📄 ini.cpp
字号:
&& DeleteKey(lpSrcSection, lpSrcKey);
}
/////////////////////////////////////////////////////////////////////////////////
// Helper Functions
/////////////////////////////////////////////////////////////////////////////////
// Get a profile string value, return a heap pointer so we do not have to worry
// about the buffer size, however, this function requires the caller to manually
// free the memory.
// This function is the back-bone of all "Getxxx" functions of this class.
LPTSTR CIni::__GetStringDynamic(LPCTSTR lpSection, LPCTSTR lpKey, LPCTSTR lpDefault) const
{
TCHAR* psz = NULL;
if (lpSection == NULL || lpKey == NULL)
{
// Invalid section or key name, just return the default string
if (lpDefault == NULL)
{
// Empty string
psz = new TCHAR[1];
*psz = _T('\0');
}
else
{
psz = new TCHAR[_tcslen(lpDefault) + 1];
_tcscpy(psz, lpDefault);
}
return psz;
}
// Keep enlarging the buffer size until being certain on that the string we
// retrieved was original(not truncated).
DWORD dwLen = DEF_PROFILE_THRESHOLD;
psz = new TCHAR[dwLen + 1];
DWORD dwCopied = ::GetPrivateProfileString(lpSection, lpKey, lpDefault == NULL ? _T("") : lpDefault, psz, dwLen, m_pszPathName);
while (dwCopied + 1 >= dwLen)
{
dwLen += DEF_PROFILE_THRESHOLD;
delete [] psz;
psz = new TCHAR[dwLen + 1];
dwCopied = ::GetPrivateProfileString(lpSection, lpKey, lpDefault == NULL ? _T("") : lpDefault, psz, dwLen, m_pszPathName);
}
return psz; // !!! Requires the caller to free this memory !!!
}
// Split a string usinf a particular delimiter, split result are copied into lpBuffer
// in the "double null terminated string" format as the following figure shows:
// xxx\0xxxx\0xx\0xxx\0\0
//
// For example, if the delimiter is ",", then string "ab,cd,e" will be
// splitted into "ab\0cd\0e\0\0", this string format can be parsed into an array
// of sub strings easily using user defined functions or CIni::ParseStringArray.
DWORD CIni::__StringSplit(LPCTSTR lpString, LPTSTR lpBuffer, DWORD dwBufSize, LPCTSTR lpDelimiter, BOOL bTrimString)
{
if (lpString == NULL || lpBuffer == NULL || dwBufSize == 0)
return 0;
DWORD dwCopied = 0;
*lpBuffer = _T('\0');
if (*lpString == _T('\0'))
return 0;
// If lpDelimiter is NULL, use the default delimiter ",", if delimiter length
// is 0, then return whole string
if (lpDelimiter != NULL && *lpDelimiter == _T('\0'))
{
_tcsncpy(lpBuffer, lpString, dwBufSize - 1);
return _tcslen(lpBuffer);
}
LPTSTR pszDel = (lpDelimiter == NULL) ? _tcsdup(DEF_PROFILE_DELIMITER) : _tcsdup(lpDelimiter);
const DWORD DEL_LEN = _tcslen(pszDel);
LPTSTR lpTarget = lpBuffer;
// Search through lpString for delimiter matches, and extract sub strings out
LPCTSTR lpPos = lpString;
LPCTSTR lpEnd = _tcsstr(lpPos, pszDel);
while (lpEnd != NULL)
{
LPTSTR pszSeg = __StrDupEx(lpPos, lpEnd);
if (bTrimString)
__TrimString(pszSeg);
const DWORD SEG_LEN = _tcslen(pszSeg);
const DWORD COPY_LEN = min(SEG_LEN, dwBufSize - dwCopied);
// Need to avoid buffer overflow
if (COPY_LEN > 0)
{
dwCopied += COPY_LEN + 1;
_tcsncpy(lpTarget, pszSeg, COPY_LEN);
lpTarget[COPY_LEN] = _T('\0');
lpTarget = &lpTarget[SEG_LEN + 1];
}
delete [] pszSeg;
lpPos = &lpEnd[DEL_LEN]; // Advance the pointer for next search
lpEnd = _tcsstr(lpPos, pszDel);
}
// The last part of string, there may not be the trailing delimiter, so we
// need to take care of this part, too
LPTSTR pszSeg = _tcsdup(lpPos);
if (bTrimString)
__TrimString(pszSeg);
const DWORD SEG_LEN = _tcslen(pszSeg);
const DWORD COPY_LEN = min(SEG_LEN, dwBufSize - dwCopied);
if (COPY_LEN > 0)
{
dwCopied += COPY_LEN + 1;
_tcsncpy(lpTarget, pszSeg, COPY_LEN);
lpTarget[COPY_LEN] = _T('\0');
}
delete [] pszSeg;
lpBuffer[dwCopied] = _T('\0');
delete [] pszDel;
return dwCopied;
}
// Parse a "double null terminated string", pass each sub string to a user-defined
// callback function
BOOL CIni::ParseDNTString(LPCTSTR lpString, SUBSTRPROC lpFnStrProc, LPVOID lpParam)
{
if (lpString == NULL || lpFnStrProc == NULL)
return FALSE;
LPCTSTR p = lpString;
DWORD dwLen = _tcslen(p);
while (dwLen > 0)
{
if (!lpFnStrProc(p, lpParam))
return FALSE;
p = &p[dwLen + 1];
dwLen = _tcslen(p);
}
return TRUE;
}
// Callback function used to compare elements inside of a
// "double null terminated string" with a given string. Useful for
// searching in the section names list.
BOOL CALLBACK CIni::__SubStrCompare(LPCTSTR lpString1, LPVOID lpParam)
{
assert(lpString1 != NULL);
LPCTSTR lpString2 = (LPCTSTR)lpParam;
assert(lpString2 != NULL);
// if two string matches, return zero to stop the parsing
return _tcsicmp(lpString1, lpString2) != 0;
}
// Callback function used to process a key-pair, it extracts the
// key name from the key-pair string
BOOL CALLBACK CIni:: __KeyPairProc(LPCTSTR lpString, LPVOID lpParam)
{
STR_LIMIT* psl = (STR_LIMIT*)lpParam;
if (lpString == NULL || psl== NULL)
return FALSE;
LPCTSTR p = _tcschr(lpString, _T('='));
if (p == NULL || p == lpString)
return TRUE;
// extract the sub-string on left side of the '='
LPTSTR psz = new TCHAR[_tcslen(lpString) + 1];
for (int i = 0; &lpString[i] < p; i++)
psz[i] = lpString[i];
psz[i] = _T('\0');
// trim
__TrimString(psz);
DWORD dwNameLen = _tcslen(psz);
DWORD dwCopyLen = 0;
//copy to the buffer
if (psl->lpTarget != NULL)
{
dwCopyLen = (psl->dwRemain > 1) ? min(dwNameLen, psl->dwRemain - 1) : 0;
_tcsncpy(psl->lpTarget, psz, dwCopyLen);
psl->lpTarget[dwCopyLen] = _T('\0');
psl->lpTarget = &(psl->lpTarget[dwCopyLen + 1]);
psl->dwRemain -= dwCopyLen + 1;
}
else
{
dwCopyLen = dwNameLen;
}
delete [] psz;
psl->dwTotalCopied += dwCopyLen + 1;
return TRUE;
}
#ifdef __AFXWIN_H__
// Callback function used to add elements that are extracted from a
// "double null terminated string" to an MFC CStringArray.
BOOL CALLBACK CIni::__SubStrAdd(LPCTSTR lpString, LPVOID lpParam)
{
CStringArray* pArray = (CStringArray*)lpParam;
if (pArray == NULL || lpString == NULL)
return FALSE;
pArray->Add(lpString);
return TRUE;
}
#endif
// Convert an integer into binary string format
void CIni::__ToBinaryString(UINT nNumber, LPTSTR lpBuffer, DWORD dwBufSize)
{
if (dwBufSize == 0)
return;
DWORD dwIndex = 0;
do
{
lpBuffer[dwIndex++] = (nNumber % 2) ? _T('1') : _T('0');
nNumber /= 2;
} while (nNumber > 0 && dwIndex < dwBufSize);
lpBuffer[dwIndex] = _T('\0');
_tcsrev(lpBuffer);
}
// Make sure the base will be expected value
int CIni::__ValidateBase(int nBase)
{
switch (nBase)
{
case BASE_BINARY:
case BASE_OCTAL:
case BASE_HEXADECIMAL:
break;
default:
nBase = BASE_DECIMAL;
}
return nBase;
}
// Convert a signed integer into string representation, based on its base
void CIni::__IntToString(int nNumber, LPTSTR lpBuffer, int nBase)
{
switch (nBase)
{
case BASE_BINARY:
case BASE_OCTAL:
case BASE_HEXADECIMAL:
__UIntToString((UINT)nNumber, lpBuffer, nBase);
break;
default:
_stprintf(lpBuffer, _T("%d"), nNumber);
break;
}
}
// Convert an unsigned integer into string representation, based on its base
void CIni::__UIntToString(UINT nNumber, LPTSTR lpBuffer, int nBase)
{
switch (nBase)
{
case BASE_BINARY:
__ToBinaryString(nNumber, lpBuffer, DEF_PROFILE_NUM_LEN);
break;
case BASE_OCTAL:
_stprintf(lpBuffer, _T("%o"), nNumber);
break;
case BASE_HEXADECIMAL:
_stprintf(lpBuffer, _T("%X"), nNumber);
break;
default:
_stprintf(lpBuffer, _T("%u"), nNumber);
break;
}
}
BOOL CIni::StringToBool(LPCTSTR lpString, BOOL bDefault)
{
// Default: empty string
// TRUE: "true", "yes", non-zero decimal numner
// FALSE: all other cases
if (lpString == NULL || *lpString == _T('\0'))
return bDefault;
return (_tcsicmp(lpString, _T("true")) == 0
|| _tcsicmp(lpString, _T("yes")) == 0
|| _tcstol(lpString, NULL, BASE_DECIMAL) != 0);
}
BOOL CIni::__TrimString(LPTSTR lpString)
{
if (lpString == NULL)
return FALSE;
BOOL bTrimmed = FALSE;
int nLen = _tcslen(lpString);
// '\n' and '\r' are actually not possible in this case, but anyway...
// Trim right side
while (nLen >= 0
&& (lpString[nLen - 1] == _T(' ')
|| lpString[nLen - 1] == _T('\t')
|| lpString[nLen - 1] == _T('\r')
|| lpString[nLen - 1] == _T('\n')))
{
lpString[--nLen] = _T('\0');
bTrimmed = TRUE;
}
// Trim left side
LPCTSTR p = lpString;
while (*p == _T(' ')
|| *p == _T('\t')
|| *p == _T('\r')
|| *p == _T('\n'))
{
p = &p[1];
bTrimmed = TRUE;
}
if (p != lpString)
{
LPTSTR psz = _tcsdup(p);
_tcscpy(lpString, psz);
delete [] psz;
}
return bTrimmed;
}
LPTSTR CIni::__StrDupEx(LPCTSTR lpStart, LPCTSTR lpEnd)
{
const DWORD LEN = ((DWORD)lpEnd - (DWORD)lpStart) / sizeof(TCHAR);
LPTSTR psz = new TCHAR[LEN + 1];
_tcsncpy(psz, lpStart, LEN);
psz[LEN] = _T('\0');
return psz; // !!! Requires the caller to free this memory !!!
}
/////////////////////////////////////////////////////////////////////////////////
// End of Cini Class Implementation
/////////////////////////////////////////////////////////////////////////////////
// If you are getting this error:
// ----------------------------------------------------------------------------
// "fatal error C1010: unexpected end of file while looking for precompiled
// header directive"
//-----------------------------------------------------------------------------
// Please scroll all the way up and uncomment '#include "stdafx.h"'
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -