194 #ifndef INCLUDED_SimpleIni_h
195 #define INCLUDED_SimpleIni_h
197 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
211 # pragma warning (push)
212 # pragma warning (disable: 4127 4503 4702 4786)
222 #ifdef SI_SUPPORT_IOSTREAMS
224 #endif // SI_SUPPORT_IOSTREAMS
230 # define SI_ASSERT(x) assert(x)
232 # define SI_ASSERT(x)
246 #define SI_UTF8_SIGNATURE "\xEF\xBB\xBF"
249 # define SI_NEWLINE_A "\r\n"
250 # define SI_NEWLINE_W L"\r\n"
252 # define SI_NEWLINE_A "\n"
253 # define SI_NEWLINE_W L"\n"
256 #if defined(SI_CONVERT_ICU)
257 # include <unicode/ustring.h>
261 # define SI_HAS_WIDE_FILE
262 # define SI_WCHAR_T wchar_t
263 #elif defined(SI_CONVERT_ICU)
264 # define SI_HAS_WIDE_FILE
265 # define SI_WCHAR_T UChar
292 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
302 Entry(
const SI_CHAR * a_pszItem = NULL,
int a_nOrder = 0)
307 Entry(
const SI_CHAR * a_pszItem,
const SI_CHAR * a_pszComment,
int a_nOrder)
320 #if defined(_MSC_VER) && _MSC_VER <= 1200
322 bool operator<(
const Entry & rhs)
const {
return LoadOrder()(*
this, rhs); }
323 bool operator>(
const Entry & rhs)
const {
return LoadOrder()(rhs, *
this); }
332 const static SI_STRLESS isLess = SI_STRLESS();
333 return isLess(
lhs.pItem, rhs.
pItem);
352 typedef std::multimap<Entry,const SI_CHAR *,typename Entry::KeyOrder>
TKeyVal;
355 typedef std::map<Entry,TKeyVal,typename Entry::KeyOrder>
TSection;
369 virtual void Write(
const char * a_pBuf) = 0;
401 #ifdef SI_SUPPORT_IOSTREAMS
403 class StreamWriter :
public OutputWriter {
404 std::ostream & m_ostream;
406 StreamWriter(std::ostream & a_ostream) : m_ostream(a_ostream) { }
407 void Write(
const char * a_pBuf) {
411 StreamWriter(
const StreamWriter &);
412 StreamWriter &
operator=(
const StreamWriter &);
414 #endif // SI_SUPPORT_IOSTREAMS
421 Converter(
bool a_bStoreIsUtf8) : SI_CONVERTER(a_bStoreIsUtf8) {
430 size_t uLen = SI_CONVERTER::SizeToStore(a_pszString);
431 if (uLen == (
size_t)(-1)) {
437 return SI_CONVERTER::ConvertToStore(
457 bool a_bIsUtf8 =
false,
458 bool a_bMultiKey =
false,
459 bool a_bMultiLine =
false
560 const char * a_pszFile
563 #ifdef SI_HAS_WIDE_FILE
571 const SI_WCHAR_T * a_pwszFile
573 #endif // SI_HAS_WIDE_FILE
586 #ifdef SI_SUPPORT_IOSTREAMS
594 std::istream & a_istream
596 #endif // SI_SUPPORT_IOSTREAMS
605 return LoadData(a_strData.c_str(), a_strData.size());
616 const char * a_pData,
637 const char * a_pszFile,
638 bool a_bAddSignature =
true
641 #ifdef SI_HAS_WIDE_FILE
653 const SI_WCHAR_T * a_pwszFile,
654 bool a_bAddSignature =
true
672 bool a_bAddSignature =
false
707 OutputWriter & a_oOutput,
708 bool a_bAddSignature =
false
711 #ifdef SI_SUPPORT_IOSTREAMS
724 std::ostream & a_ostream,
725 bool a_bAddSignature =
false
728 StreamWriter writer(a_ostream);
729 return Save(writer, a_bAddSignature);
731 #endif // SI_SUPPORT_IOSTREAMS
745 std::string & a_sBuffer,
746 bool a_bAddSignature =
false
750 return Save(writer, a_bAddSignature);
793 const SI_CHAR * a_pSection,
814 const SI_CHAR * a_pSection,
815 const SI_CHAR * a_pKey,
829 const SI_CHAR * a_pSection
847 const SI_CHAR * a_pSection
868 const SI_CHAR * a_pSection,
869 const SI_CHAR * a_pKey,
870 const SI_CHAR * a_pDefault = NULL,
871 bool * a_pHasMultiple = NULL
888 const SI_CHAR * a_pSection,
889 const SI_CHAR * a_pKey,
891 bool * a_pHasMultiple = NULL
908 const SI_CHAR * a_pSection,
909 const SI_CHAR * a_pKey,
910 double a_nDefault = 0,
911 bool * a_pHasMultiple = NULL
933 const SI_CHAR * a_pSection,
934 const SI_CHAR * a_pKey,
935 bool a_bDefault =
false,
936 bool * a_pHasMultiple = NULL
969 const SI_CHAR * a_pSection,
970 const SI_CHAR * a_pKey,
971 const SI_CHAR * a_pValue,
972 const SI_CHAR * a_pComment = NULL,
973 bool a_bForceReplace =
false
976 return AddEntry(a_pSection, a_pKey, a_pValue, a_pComment, a_bForceReplace,
true);
1003 const SI_CHAR * a_pSection,
1004 const SI_CHAR * a_pKey,
1006 const SI_CHAR * a_pComment = NULL,
1007 bool a_bUseHex =
false,
1008 bool a_bForceReplace =
false
1032 const SI_CHAR * a_pSection,
1033 const SI_CHAR * a_pKey,
1035 const SI_CHAR * a_pComment = NULL,
1036 bool a_bForceReplace =
false
1060 const SI_CHAR * a_pSection,
1061 const SI_CHAR * a_pKey,
1063 const SI_CHAR * a_pComment = NULL,
1064 bool a_bForceReplace =
false
1086 const SI_CHAR * a_pSection,
1087 const SI_CHAR * a_pKey,
1088 bool a_bRemoveEmpty =
false
1125 const SI_CHAR *& a_pSection,
1126 const SI_CHAR *& a_pKey,
1127 const SI_CHAR *& a_pVal,
1128 const SI_CHAR *& a_pComment
1154 const SI_CHAR * a_pSection,
1155 const SI_CHAR * a_pKey,
1156 const SI_CHAR * a_pValue,
1157 const SI_CHAR * a_pComment,
1158 bool a_bForceReplace,
1164 return (ch ==
' ' || ch ==
'\t' || ch ==
'\r' || ch ==
'\n');
1169 return (ch ==
';' || ch ==
'#');
1175 a_pData += (*a_pData ==
'\r' && *(a_pData+1) ==
'\n') ? 2 : 1;
1185 bool IsLess(
const SI_CHAR * a_pLeft,
const SI_CHAR * a_pRight)
const {
1186 const static SI_STRLESS isLess = SI_STRLESS();
1187 return isLess(a_pLeft, a_pRight);
1194 const SI_CHAR *& a_pVal,
1195 const SI_CHAR * a_pTagName,
1196 bool a_bAllowBlankLinesInComment =
false
1201 OutputWriter & a_oOutput,
1202 Converter & a_oConverter,
1203 const SI_CHAR * a_pText
1254 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1257 bool a_bAllowMultiKey,
1258 bool a_bAllowMultiLine
1262 , m_pFileComment(
NULL)
1263 , m_bStoreIsUtf8(a_bIsUtf8)
1264 , m_bAllowMultiKey(a_bAllowMultiKey)
1265 , m_bAllowMultiLine(a_bAllowMultiLine)
1270 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1276 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1284 m_pFileComment =
NULL;
1285 if (!m_data.empty()) {
1286 m_data.erase(m_data.begin(), m_data.end());
1290 if (!m_strings.empty()) {
1291 typename TNamesDepend::iterator
i = m_strings.begin();
1292 for (;
i != m_strings.end(); ++
i) {
1293 delete[]
const_cast<SI_CHAR*
>(
i->pItem);
1295 m_strings.erase(m_strings.begin(), m_strings.end());
1299 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1302 const char * a_pszFile
1306 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
1307 fopen_s(&fp, a_pszFile,
"rb");
1308 #else // !__STDC_WANT_SECURE_LIB__
1309 fp = fopen(a_pszFile,
"rb");
1310 #endif // __STDC_WANT_SECURE_LIB__
1319 #ifdef SI_HAS_WIDE_FILE
1320 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1323 const SI_WCHAR_T * a_pwszFile
1328 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
1329 _wfopen_s(&fp, a_pwszFile, L
"rb");
1330 #else // !__STDC_WANT_SECURE_LIB__
1331 fp = _wfopen(a_pwszFile, L
"rb");
1332 #endif // __STDC_WANT_SECURE_LIB__
1337 #else // !_WIN32 (therefore SI_CONVERT_ICU)
1339 u_austrncpy(szFile, a_pwszFile,
sizeof(szFile));
1340 return LoadFile(szFile);
1343 #endif // SI_HAS_WIDE_FILE
1345 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1352 int retval = fseek(a_fpFile, 0, SEEK_END);
1356 long lSize = ftell(a_fpFile);
1363 char * pData =
new char[lSize];
1367 fseek(a_fpFile, 0, SEEK_SET);
1368 size_t uRead = fread(pData,
sizeof(
char), lSize, a_fpFile);
1369 if (uRead != (
size_t) lSize) {
1375 SI_Error rc = LoadData(pData, uRead);
1380 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1383 const char * a_pData,
1387 SI_CONVERTER converter(m_bStoreIsUtf8);
1389 if (a_uDataLen == 0) {
1394 if (m_bStoreIsUtf8 && a_uDataLen >= 3) {
1402 size_t uLen = converter.SizeFromStore(a_pData, a_uDataLen);
1403 if (uLen == (
size_t)(-1)) {
1409 SI_CHAR * pData =
new SI_CHAR[uLen+1];
1413 memset(pData, 0,
sizeof(SI_CHAR)*(uLen+1));
1416 if (!converter.ConvertFromStore(a_pData, a_uDataLen, pData, uLen)) {
1422 const static SI_CHAR
empty = 0;
1423 SI_CHAR * pWork = pData;
1424 const SI_CHAR * pSection = &
empty;
1425 const SI_CHAR * pItem =
NULL;
1426 const SI_CHAR * pVal =
NULL;
1427 const SI_CHAR * pComment =
NULL;
1431 bool bCopyStrings = (m_pData !=
NULL);
1435 SI_Error rc = FindFileComment(pWork, bCopyStrings);
1436 if (rc < 0)
return rc;
1439 while (FindEntry(pWork, pSection, pItem, pVal, pComment)) {
1440 rc = AddEntry(pSection, pItem, pVal, pComment,
false, bCopyStrings);
1441 if (rc < 0)
return rc;
1450 m_uDataLen = uLen+1;
1456 #ifdef SI_SUPPORT_IOSTREAMS
1457 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1460 std::istream & a_istream
1463 std::string strData;
1466 a_istream.get(szBuf,
sizeof(szBuf),
'\0');
1467 strData.append(szBuf);
1469 while (a_istream.good());
1470 return LoadData(strData);
1472 #endif // SI_SUPPORT_IOSTREAMS
1474 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1482 if (m_pFileComment) {
1488 if (!LoadMultiLineText(a_pData, m_pFileComment,
NULL,
false)) {
1493 if (a_bCopyStrings) {
1494 SI_Error rc = CopyString(m_pFileComment);
1495 if (rc < 0)
return rc;
1501 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1505 const SI_CHAR *& a_pSection,
1506 const SI_CHAR *& a_pKey,
1507 const SI_CHAR *& a_pVal,
1508 const SI_CHAR *& a_pComment
1513 SI_CHAR * pTrail =
NULL;
1516 while (*a_pData &&
IsSpace(*a_pData)) {
1525 if (IsComment(*a_pData)) {
1526 LoadMultiLineText(a_pData, a_pComment,
NULL,
true);
1531 if (*a_pData ==
'[') {
1534 while (*a_pData &&
IsSpace(*a_pData)) {
1540 a_pSection = a_pData;
1541 while (*a_pData && *a_pData !=
']' && !IsNewLineChar(*a_pData)) {
1546 if (*a_pData !=
']') {
1551 pTrail = a_pData - 1;
1552 while (pTrail >= a_pSection &&
IsSpace(*pTrail)) {
1560 while (*a_pData && !IsNewLineChar(*a_pData)) {
1572 while (*a_pData && *a_pData !=
'=' && !IsNewLineChar(*a_pData)) {
1577 if (*a_pData !=
'=') {
1582 if (a_pKey == a_pData) {
1583 while (*a_pData && !IsNewLineChar(*a_pData)) {
1590 pTrail = a_pData - 1;
1591 while (pTrail >= a_pKey &&
IsSpace(*pTrail)) {
1599 while (*a_pData && !IsNewLineChar(*a_pData) &&
IsSpace(*a_pData)) {
1605 while (*a_pData && !IsNewLineChar(*a_pData)) {
1610 pTrail = a_pData - 1;
1612 SkipNewLine(a_pData);
1614 while (pTrail >= a_pVal &&
IsSpace(*pTrail)) {
1621 if (m_bAllowMultiLine && IsMultiLineTag(a_pVal)) {
1623 const SI_CHAR * pTagName = a_pVal + 3;
1624 return LoadMultiLineText(a_pData, a_pVal, pTagName);
1634 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1637 const SI_CHAR * a_pVal
1641 if (*a_pVal++ !=
'<')
return false;
1642 if (*a_pVal++ !=
'<')
return false;
1643 if (*a_pVal++ !=
'<')
return false;
1647 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1650 const SI_CHAR * a_pData
1670 if (IsNewLineChar(*a_pData)) {
1684 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1690 return (a_c ==
'\n' || a_c ==
'\r');
1693 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1697 const SI_CHAR *& a_pVal,
1698 const SI_CHAR * a_pTagName,
1699 bool a_bAllowBlankLinesInComment
1710 SI_CHAR * pDataLine = a_pData;
1711 SI_CHAR * pCurrLine;
1719 SI_CHAR cEndOfLineChar = *a_pData;
1723 if (!a_pTagName && !IsComment(*a_pData)) {
1725 if (!a_bAllowBlankLinesInComment) {
1732 SI_CHAR * pCurr = a_pData;
1735 if (IsNewLineChar(*pCurr)) {
1746 if (IsComment(*pCurr)) {
1747 for (; nNewLines > 0; --nNewLines) *pDataLine++ =
'\n';
1757 pCurrLine = a_pData;
1758 while (*a_pData && !IsNewLineChar(*a_pData)) ++a_pData;
1761 if (pDataLine < pCurrLine) {
1762 size_t nLen = (
size_t) (a_pData - pCurrLine);
1763 memmove(pDataLine, pCurrLine, nLen *
sizeof(SI_CHAR));
1764 pDataLine[nLen] =
'\0';
1768 cEndOfLineChar = *a_pData;
1775 (!IsLess(pDataLine, a_pTagName) && !IsLess(a_pTagName, pDataLine)))
1782 if (!cEndOfLineChar) {
1788 pDataLine += (a_pData - pCurrLine);
1789 *a_pData = cEndOfLineChar;
1790 SkipNewLine(a_pData);
1791 *pDataLine++ =
'\n';
1795 if (a_pVal == a_pData) {
1804 *--pDataLine =
'\0';
1808 if (a_pTagName && cEndOfLineChar) {
1809 SI_ASSERT(IsNewLineChar(cEndOfLineChar));
1810 *a_pData = cEndOfLineChar;
1811 SkipNewLine(a_pData);
1817 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1820 const SI_CHAR *& a_pString
1824 if (
sizeof(SI_CHAR) ==
sizeof(
char)) {
1825 uLen = strlen((
const char *)a_pString);
1827 else if (
sizeof(SI_CHAR) ==
sizeof(
wchar_t)) {
1828 uLen = wcslen((
const wchar_t *)a_pString);
1831 for ( ; a_pString[uLen]; ++uLen) ;
1834 SI_CHAR * pCopy =
new SI_CHAR[uLen];
1838 memcpy(pCopy, a_pString,
sizeof(SI_CHAR)*uLen);
1839 m_strings.push_back(pCopy);
1844 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1847 const SI_CHAR * a_pSection,
1848 const SI_CHAR * a_pKey,
1849 const SI_CHAR * a_pValue,
1850 const SI_CHAR * a_pComment,
1851 bool a_bForceReplace,
1856 bool bInserted =
false;
1858 SI_ASSERT(!a_pComment || IsComment(*a_pComment));
1862 if (a_bCopyStrings && a_pComment) {
1863 rc = CopyString(a_pComment);
1864 if (rc < 0)
return rc;
1868 typename TSection::iterator iSection = m_data.find(a_pSection);
1869 if (iSection == m_data.end()) {
1872 if (a_bCopyStrings) {
1873 rc = CopyString(a_pSection);
1874 if (rc < 0)
return rc;
1878 Entry oSection(a_pSection, ++m_nOrder);
1879 if (a_pComment && (!a_pKey || !a_pValue)) {
1883 typename TSection::value_type oEntry(oSection,
TKeyVal());
1884 typedef typename TSection::iterator SectionIterator;
1885 std::pair<SectionIterator,bool>
i = m_data.insert(oEntry);
1889 if (!a_pKey || !a_pValue) {
1895 TKeyVal & keyval = iSection->second;
1896 typename TKeyVal::iterator iKey = keyval.find(a_pKey);
1900 int nLoadOrder = ++m_nOrder;
1901 if (iKey != keyval.end() && m_bAllowMultiKey && a_bForceReplace) {
1902 const SI_CHAR * pComment =
NULL;
1903 while (iKey != keyval.end() && !IsLess(a_pKey, iKey->first.pItem)) {
1904 if (iKey->first.nOrder < nLoadOrder) {
1905 nLoadOrder = iKey->first.nOrder;
1906 pComment = iKey->first.pComment;
1911 DeleteString(a_pComment);
1912 a_pComment = pComment;
1913 CopyString(a_pComment);
1915 Delete(a_pSection, a_pKey);
1916 iKey = keyval.end();
1920 bool bForceCreateNewKey = m_bAllowMultiKey && !a_bForceReplace;
1921 if (a_bCopyStrings) {
1922 if (bForceCreateNewKey || iKey == keyval.end()) {
1926 rc = CopyString(a_pKey);
1927 if (rc < 0)
return rc;
1931 rc = CopyString(a_pValue);
1932 if (rc < 0)
return rc;
1936 if (iKey == keyval.end() || bForceCreateNewKey) {
1937 Entry oKey(a_pKey, nLoadOrder);
1941 typename TKeyVal::value_type oEntry(oKey,
static_cast<const SI_CHAR *
>(
NULL));
1942 iKey = keyval.insert(oEntry);
1945 iKey->second = a_pValue;
1949 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1952 const SI_CHAR * a_pSection,
1953 const SI_CHAR * a_pKey,
1954 const SI_CHAR * a_pDefault,
1955 bool * a_pHasMultiple
1958 if (a_pHasMultiple) {
1959 *a_pHasMultiple =
false;
1961 if (!a_pSection || !a_pKey) {
1964 typename TSection::const_iterator iSection = m_data.find(a_pSection);
1965 if (iSection == m_data.end()) {
1968 typename TKeyVal::const_iterator iKeyVal = iSection->second.find(a_pKey);
1969 if (iKeyVal == iSection->second.end()) {
1974 if (m_bAllowMultiKey && a_pHasMultiple) {
1975 typename TKeyVal::const_iterator iTemp = iKeyVal;
1976 if (++iTemp != iSection->second.end()) {
1977 if (!IsLess(a_pKey, iTemp->first.pItem)) {
1978 *a_pHasMultiple =
true;
1983 return iKeyVal->second;
1986 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1989 const SI_CHAR * a_pSection,
1990 const SI_CHAR * a_pKey,
1992 bool * a_pHasMultiple
1996 const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey,
NULL, a_pHasMultiple);
1997 if (!pszValue || !*pszValue)
return a_nDefault;
2000 char szValue[64] = { 0 };
2001 SI_CONVERTER
c(m_bStoreIsUtf8);
2002 if (!
c.ConvertToStore(pszValue, szValue,
sizeof(szValue))) {
2007 long nValue = a_nDefault;
2008 char * pszSuffix = szValue;
2009 if (szValue[0] ==
'0' && (szValue[1] ==
'x' || szValue[1] ==
'X')) {
2010 if (!szValue[2])
return a_nDefault;
2011 nValue = strtol(&szValue[2], &pszSuffix, 16);
2014 nValue = strtol(szValue, &pszSuffix, 10);
2025 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2028 const SI_CHAR * a_pSection,
2029 const SI_CHAR * a_pKey,
2031 const SI_CHAR * a_pComment,
2033 bool a_bForceReplace
2037 if (!a_pSection || !a_pKey)
return SI_FAIL;
2041 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
2042 sprintf_s(szInput, a_bUseHex ?
"0x%lx" :
"%ld", a_nValue);
2043 #else // !__STDC_WANT_SECURE_LIB__
2044 sprintf(szInput, a_bUseHex ?
"0x%lx" :
"%ld", a_nValue);
2045 #endif // __STDC_WANT_SECURE_LIB__
2048 SI_CHAR szOutput[64];
2049 SI_CONVERTER
c(m_bStoreIsUtf8);
2050 c.ConvertFromStore(szInput, strlen(szInput) + 1,
2051 szOutput,
sizeof(szOutput) /
sizeof(SI_CHAR));
2054 return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace,
true);
2057 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2060 const SI_CHAR * a_pSection,
2061 const SI_CHAR * a_pKey,
2063 bool * a_pHasMultiple
2067 const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey,
NULL, a_pHasMultiple);
2068 if (!pszValue || !*pszValue)
return a_nDefault;
2071 char szValue[64] = { 0 };
2072 SI_CONVERTER
c(m_bStoreIsUtf8);
2073 if (!
c.ConvertToStore(pszValue, szValue,
sizeof(szValue))) {
2077 char * pszSuffix =
NULL;
2078 double nValue = strtod(szValue, &pszSuffix);
2081 if (!pszSuffix || *pszSuffix) {
2088 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2091 const SI_CHAR * a_pSection,
2092 const SI_CHAR * a_pKey,
2094 const SI_CHAR * a_pComment,
2095 bool a_bForceReplace
2099 if (!a_pSection || !a_pKey)
return SI_FAIL;
2103 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
2104 sprintf_s(szInput,
"%f", a_nValue);
2105 #else // !__STDC_WANT_SECURE_LIB__
2106 sprintf(szInput,
"%f", a_nValue);
2107 #endif // __STDC_WANT_SECURE_LIB__
2110 SI_CHAR szOutput[64];
2111 SI_CONVERTER
c(m_bStoreIsUtf8);
2112 c.ConvertFromStore(szInput, strlen(szInput) + 1,
2113 szOutput,
sizeof(szOutput) /
sizeof(SI_CHAR));
2116 return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace,
true);
2119 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2122 const SI_CHAR * a_pSection,
2123 const SI_CHAR * a_pKey,
2125 bool * a_pHasMultiple
2129 const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey,
NULL, a_pHasMultiple);
2130 if (!pszValue || !*pszValue)
return a_bDefault;
2133 switch (pszValue[0]) {
2145 if (pszValue[1] ==
'n' || pszValue[1] ==
'N')
return true;
2146 if (pszValue[1] ==
'f' || pszValue[1] ==
'F')
return false;
2154 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2157 const SI_CHAR * a_pSection,
2158 const SI_CHAR * a_pKey,
2160 const SI_CHAR * a_pComment,
2161 bool a_bForceReplace
2165 if (!a_pSection || !a_pKey)
return SI_FAIL;
2168 const char * pszInput = a_bValue ?
"true" :
"false";
2171 SI_CHAR szOutput[64];
2172 SI_CONVERTER
c(m_bStoreIsUtf8);
2173 c.ConvertFromStore(pszInput, strlen(pszInput) + 1,
2174 szOutput,
sizeof(szOutput) /
sizeof(SI_CHAR));
2177 return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace,
true);
2180 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2183 const SI_CHAR * a_pSection,
2184 const SI_CHAR * a_pKey,
2190 if (!a_pSection || !a_pKey) {
2193 typename TSection::const_iterator iSection = m_data.find(a_pSection);
2194 if (iSection == m_data.end()) {
2197 typename TKeyVal::const_iterator iKeyVal = iSection->second.find(a_pKey);
2198 if (iKeyVal == iSection->second.end()) {
2203 a_values.push_back(
Entry(iKeyVal->second, iKeyVal->first.pComment, iKeyVal->first.nOrder));
2204 if (m_bAllowMultiKey) {
2206 while (iKeyVal != iSection->second.end() && !IsLess(a_pKey, iKeyVal->first.pItem)) {
2207 a_values.push_back(
Entry(iKeyVal->second, iKeyVal->first.pComment, iKeyVal->first.nOrder));
2215 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2218 const SI_CHAR * a_pSection
2225 typename TSection::const_iterator iSection = m_data.find(a_pSection);
2226 if (iSection == m_data.end()) {
2229 const TKeyVal & section = iSection->second;
2233 if (!m_bAllowMultiKey || section.empty()) {
2234 return (
int) section.size();
2239 const SI_CHAR * pLastKey =
NULL;
2240 typename TKeyVal::const_iterator iKeyVal = section.begin();
2241 for (
int n = 0; iKeyVal != section.end(); ++iKeyVal, ++
n) {
2242 if (!pLastKey || IsLess(pLastKey, iKeyVal->first.pItem)) {
2244 pLastKey = iKeyVal->first.pItem;
2250 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2253 const SI_CHAR * a_pSection
2257 typename TSection::const_iterator
i = m_data.find(a_pSection);
2258 if (
i != m_data.end()) {
2259 return &(
i->second);
2265 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2272 typename TSection::const_iterator
i = m_data.begin();
2273 for (
int n = 0;
i != m_data.end(); ++
i, ++
n ) {
2274 a_names.push_back(
i->first);
2278 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2281 const SI_CHAR * a_pSection,
2291 typename TSection::const_iterator iSection = m_data.find(a_pSection);
2292 if (iSection == m_data.end()) {
2296 const TKeyVal & section = iSection->second;
2297 const SI_CHAR * pLastKey =
NULL;
2298 typename TKeyVal::const_iterator iKeyVal = section.begin();
2299 for (
int n = 0; iKeyVal != section.end(); ++iKeyVal, ++
n ) {
2300 if (!pLastKey || IsLess(pLastKey, iKeyVal->first.pItem)) {
2301 a_names.push_back(iKeyVal->first);
2302 pLastKey = iKeyVal->first.pItem;
2309 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2312 const char * a_pszFile,
2313 bool a_bAddSignature
2317 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
2318 fopen_s(&fp, a_pszFile,
"wb");
2319 #else // !__STDC_WANT_SECURE_LIB__
2320 fp = fopen(a_pszFile,
"wb");
2321 #endif // __STDC_WANT_SECURE_LIB__
2323 SI_Error rc = SaveFile(fp, a_bAddSignature);
2328 #ifdef SI_HAS_WIDE_FILE
2329 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2332 const SI_WCHAR_T * a_pwszFile,
2333 bool a_bAddSignature
2338 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
2339 _wfopen_s(&fp, a_pwszFile, L
"wb");
2340 #else // !__STDC_WANT_SECURE_LIB__
2341 fp = _wfopen(a_pwszFile, L
"wb");
2342 #endif // __STDC_WANT_SECURE_LIB__
2344 SI_Error rc = SaveFile(fp, a_bAddSignature);
2347 #else // !_WIN32 (therefore SI_CONVERT_ICU)
2349 u_austrncpy(szFile, a_pwszFile,
sizeof(szFile));
2350 return SaveFile(szFile, a_bAddSignature);
2353 #endif // SI_HAS_WIDE_FILE
2355 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2359 bool a_bAddSignature
2363 return Save(writer, a_bAddSignature);
2366 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2370 bool a_bAddSignature
2376 if (m_bStoreIsUtf8 && a_bAddSignature) {
2382 GetAllSections(oSections);
2383 #if defined(_MSC_VER) && _MSC_VER <= 1200
2385 #elif defined(__BORLANDC__)
2392 bool bNeedNewLine =
false;
2393 if (m_pFileComment) {
2394 if (!OutputMultiLineText(a_oOutput, convert, m_pFileComment)) {
2397 bNeedNewLine =
true;
2401 typename TNamesDepend::const_iterator iSection = oSections.begin();
2402 for ( ; iSection != oSections.end(); ++iSection ) {
2404 if (iSection->pComment) {
2409 if (!OutputMultiLineText(a_oOutput, convert, iSection->pComment)) {
2412 bNeedNewLine =
false;
2418 bNeedNewLine =
false;
2422 if (*iSection->pItem) {
2426 a_oOutput.
Write(
"[");
2428 a_oOutput.
Write(
"]");
2434 GetAllKeys(iSection->pItem, oKeys);
2435 #if defined(_MSC_VER) && _MSC_VER <= 1200
2437 #elif defined(__BORLANDC__)
2444 typename TNamesDepend::const_iterator iKey = oKeys.begin();
2445 for ( ; iKey != oKeys.end(); ++iKey) {
2448 GetAllValues(iSection->pItem, iKey->pItem, oValues);
2450 typename TNamesDepend::const_iterator iValue = oValues.begin();
2451 for ( ; iValue != oValues.end(); ++iValue) {
2453 if (iValue->pComment) {
2455 if (!OutputMultiLineText(a_oOutput, convert, iValue->pComment)) {
2470 a_oOutput.
Write(m_bSpaces ?
" = " :
"=");
2471 if (m_bAllowMultiLine && IsMultiLineData(iValue->pItem)) {
2475 if (!OutputMultiLineText(a_oOutput, convert, iValue->pItem)) {
2478 a_oOutput.
Write(
"END_OF_TEXT");
2487 bNeedNewLine =
true;
2493 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2498 const SI_CHAR * a_pText
2501 const SI_CHAR * pEndOfLine;
2502 SI_CHAR cEndOfLineChar = *a_pText;
2503 while (cEndOfLineChar) {
2505 pEndOfLine = a_pText;
2506 for (; *pEndOfLine && *pEndOfLine !=
'\n'; ++pEndOfLine) ;
2507 cEndOfLineChar = *pEndOfLine;
2510 *
const_cast<SI_CHAR*
>(pEndOfLine) = 0;
2514 *
const_cast<SI_CHAR*
>(pEndOfLine) = cEndOfLineChar;
2515 a_pText += (pEndOfLine - a_pText) + 1;
2522 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2525 const SI_CHAR * a_pSection,
2526 const SI_CHAR * a_pKey,
2534 typename TSection::iterator iSection = m_data.find(a_pSection);
2535 if (iSection == m_data.end()) {
2541 typename TKeyVal::iterator iKeyVal = iSection->second.find(a_pKey);
2542 if (iKeyVal == iSection->second.end()) {
2547 typename TKeyVal::iterator iDelete;
2549 iDelete = iKeyVal++;
2551 DeleteString(iDelete->first.pItem);
2552 DeleteString(iDelete->second);
2553 iSection->second.erase(iDelete);
2555 while (iKeyVal != iSection->second.end()
2556 && !IsLess(a_pKey, iKeyVal->first.pItem));
2561 if (!a_bRemoveEmpty || !iSection->second.empty()) {
2568 typename TKeyVal::iterator iKeyVal = iSection->second.begin();
2569 for ( ; iKeyVal != iSection->second.end(); ++iKeyVal) {
2570 DeleteString(iKeyVal->first.pItem);
2571 DeleteString(iKeyVal->second);
2576 DeleteString(iSection->first.pItem);
2577 m_data.erase(iSection);
2582 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2585 const SI_CHAR * a_pString
2591 if (a_pString < m_pData || a_pString >= m_pData + m_uDataLen) {
2592 typename TNamesDepend::iterator
i = m_strings.begin();
2593 for (;
i != m_strings.end(); ++
i) {
2594 if (a_pString ==
i->pItem) {
2595 delete[]
const_cast<SI_CHAR*
>(
i->pItem);
2617 #if !defined(SI_CONVERT_GENERIC) && !defined(SI_CONVERT_WIN32) && !defined(SI_CONVERT_ICU)
2619 # define SI_CONVERT_WIN32
2621 # define SI_CONVERT_GENERIC
2630 template<
class SI_CHAR>
2632 bool operator()(
const SI_CHAR * pLeft,
const SI_CHAR * pRight)
const {
2634 for ( ;*pLeft && *pRight; ++pLeft, ++pRight) {
2635 cmp = (long) *pLeft - (
long) *pRight;
2640 return *pRight != 0;
2650 template<
class SI_CHAR>
2653 return (ch < 'A' || ch >
'Z') ? ch : (ch -
'A' +
'a');
2655 bool operator()(
const SI_CHAR * pLeft,
const SI_CHAR * pRight)
const {
2657 for ( ;*pLeft && *pRight; ++pLeft, ++pRight) {
2663 return *pRight != 0;
2670 template<
class SI_CHAR>
2699 const char * a_pInputData,
2700 size_t a_uInputDataLen)
2703 SI_ASSERT(a_uInputDataLen != (
size_t) -1);
2706 return a_uInputDataLen;
2723 const char * a_pInputData,
2724 size_t a_uInputDataLen,
2725 SI_CHAR * a_pOutputData,
2726 size_t a_uOutputDataSize)
2729 if (a_uInputDataLen > a_uOutputDataSize) {
2732 memcpy(a_pOutputData, a_pInputData, a_uInputDataLen);
2747 const SI_CHAR * a_pInputData)
2750 return strlen((
const char *)a_pInputData) + 1;
2767 const SI_CHAR * a_pInputData,
2768 char * a_pOutputData,
2769 size_t a_uOutputDataSize)
2772 size_t uInputLen = strlen((
const char *)a_pInputData) + 1;
2773 if (uInputLen > a_uOutputDataSize) {
2778 memcpy(a_pOutputData, a_pInputData, uInputLen);
2787 #ifdef SI_CONVERT_GENERIC
2789 #define SI_Case SI_GenericCase
2790 #define SI_NoCase SI_GenericNoCase
2799 template<
class SI_CHAR>
2828 const char * a_pInputData,
2829 size_t a_uInputDataLen)
2831 SI_ASSERT(a_uInputDataLen != (
size_t) -1);
2837 return a_uInputDataLen;
2840 return mbstowcs(
NULL, a_pInputData, a_uInputDataLen);
2858 const char * a_pInputData,
2859 size_t a_uInputDataLen,
2860 SI_CHAR * a_pOutputData,
2861 size_t a_uOutputDataSize)
2870 const UTF8 * pUtf8 = (
const UTF8 *) a_pInputData;
2871 if (
sizeof(
wchar_t) ==
sizeof(
UTF32)) {
2874 &pUtf8, pUtf8 + a_uInputDataLen,
2875 &pUtf32, pUtf32 + a_uOutputDataSize,
2878 else if (
sizeof(
wchar_t) ==
sizeof(
UTF16)) {
2881 &pUtf8, pUtf8 + a_uInputDataLen,
2882 &pUtf16, pUtf16 + a_uOutputDataSize,
2888 size_t retval = mbstowcs(a_pOutputData,
2889 a_pInputData, a_uOutputDataSize);
2890 return retval != (
size_t)(-1);
2905 const SI_CHAR * a_pInputData)
2910 while (a_pInputData[uLen]) {
2913 return (6 * uLen) + 1;
2916 size_t uLen = wcstombs(
NULL, a_pInputData, 0);
2917 if (uLen == (
size_t)(-1)) {
2938 const SI_CHAR * a_pInputData,
2939 char * a_pOutputData,
2940 size_t a_uOutputDataSize
2945 size_t uInputLen = 0;
2946 while (a_pInputData[uInputLen]) {
2957 UTF8 * pUtf8 = (
UTF8 *) a_pOutputData;
2958 if (
sizeof(
wchar_t) ==
sizeof(
UTF32)) {
2959 const UTF32 * pUtf32 = (
const UTF32 *) a_pInputData;
2961 &pUtf32, pUtf32 + uInputLen,
2962 &pUtf8, pUtf8 + a_uOutputDataSize,
2965 else if (
sizeof(
wchar_t) ==
sizeof(
UTF16)) {
2966 const UTF16 * pUtf16 = (
const UTF16 *) a_pInputData;
2968 &pUtf16, pUtf16 + uInputLen,
2969 &pUtf8, pUtf8 + a_uOutputDataSize,
2975 size_t retval = wcstombs(a_pOutputData,
2976 a_pInputData, a_uOutputDataSize);
2977 return retval != (
size_t) -1;
2982 #endif // SI_CONVERT_GENERIC
2988 #ifdef SI_CONVERT_ICU
2990 #define SI_Case SI_GenericCase
2991 #define SI_NoCase SI_GenericNoCase
2993 #include <unicode/ucnv.h>
2998 template<
class SI_CHAR>
3000 const char * m_pEncoding;
3001 UConverter * m_pConverter;
3006 m_pEncoding = a_bStoreIsUtf8 ?
"UTF-8" :
NULL;
3012 m_pEncoding = rhs.m_pEncoding;
3013 m_pConverter =
NULL;
3016 ~
SI_ConvertW() {
if (m_pConverter) ucnv_close(m_pConverter); }
3032 const char * a_pInputData,
3033 size_t a_uInputDataLen)
3035 SI_ASSERT(a_uInputDataLen != (
size_t) -1);
3039 if (!m_pConverter) {
3040 nError = U_ZERO_ERROR;
3041 m_pConverter = ucnv_open(m_pEncoding, &nError);
3042 if (U_FAILURE(nError)) {
3047 nError = U_ZERO_ERROR;
3048 int32_t nLen = ucnv_toUChars(m_pConverter, NULL, 0,
3049 a_pInputData, (
int32_t) a_uInputDataLen, &nError);
3050 if (U_FAILURE(nError) && nError != U_BUFFER_OVERFLOW_ERROR) {
3054 return (
size_t) nLen;
3071 const char * a_pInputData,
3072 size_t a_uInputDataLen,
3073 UChar * a_pOutputData,
3074 size_t a_uOutputDataSize)
3078 if (!m_pConverter) {
3079 nError = U_ZERO_ERROR;
3080 m_pConverter = ucnv_open(m_pEncoding, &nError);
3081 if (U_FAILURE(nError)) {
3086 nError = U_ZERO_ERROR;
3087 ucnv_toUChars(m_pConverter,
3088 a_pOutputData, (
int32_t) a_uOutputDataSize,
3089 a_pInputData, (
int32_t) a_uInputDataLen, &nError);
3090 if (U_FAILURE(nError)) {
3108 const UChar * a_pInputData)
3112 if (!m_pConverter) {
3113 nError = U_ZERO_ERROR;
3114 m_pConverter = ucnv_open(m_pEncoding, &nError);
3115 if (U_FAILURE(nError)) {
3120 nError = U_ZERO_ERROR;
3121 int32_t nLen = ucnv_fromUChars(m_pConverter, NULL, 0,
3122 a_pInputData, -1, &nError);
3123 if (U_FAILURE(nError) && nError != U_BUFFER_OVERFLOW_ERROR) {
3127 return (
size_t) nLen + 1;
3144 const UChar * a_pInputData,
3145 char * a_pOutputData,
3146 size_t a_uOutputDataSize)
3150 if (!m_pConverter) {
3151 nError = U_ZERO_ERROR;
3152 m_pConverter = ucnv_open(m_pEncoding, &nError);
3153 if (U_FAILURE(nError)) {
3158 nError = U_ZERO_ERROR;
3159 ucnv_fromUChars(m_pConverter,
3160 a_pOutputData, (
int32_t) a_uOutputDataSize,
3161 a_pInputData, -1, &nError);
3162 if (U_FAILURE(nError)) {
3170 #endif // SI_CONVERT_ICU
3176 #ifdef SI_CONVERT_WIN32
3178 #define SI_Case SI_GenericCase
3187 #include <windows.h>
3189 # define SI_NoCase SI_GenericNoCase
3190 #else // !SI_NO_MBCS
3199 #include <mbstring.h>
3200 template<
class SI_CHAR>
3202 bool operator()(
const SI_CHAR * pLeft,
const SI_CHAR * pRight)
const {
3203 if (
sizeof(SI_CHAR) ==
sizeof(
char)) {
3204 return _mbsicmp((
const unsigned char *)pLeft,
3205 (
const unsigned char *)pRight) < 0;
3207 if (
sizeof(SI_CHAR) ==
sizeof(
wchar_t)) {
3208 return _wcsicmp((
const wchar_t *)pLeft,
3209 (
const wchar_t *)pRight) < 0;
3214 #endif // SI_NO_MBCS
3222 template<
class SI_CHAR>
3229 m_uCodePage = a_bStoreIsUtf8 ? CP_UTF8 : CP_ACP;
3235 m_uCodePage = rhs.m_uCodePage;
3253 const char * a_pInputData,
3254 size_t a_uInputDataLen)
3256 SI_ASSERT(a_uInputDataLen != (
size_t) -1);
3258 int retval = MultiByteToWideChar(
3260 a_pInputData, (
int) a_uInputDataLen,
3262 return (
size_t)(retval > 0 ? retval : -1);
3279 const char * a_pInputData,
3280 size_t a_uInputDataLen,
3281 SI_CHAR * a_pOutputData,
3282 size_t a_uOutputDataSize)
3284 int nSize = MultiByteToWideChar(
3286 a_pInputData, (
int) a_uInputDataLen,
3287 (
wchar_t *) a_pOutputData, (
int) a_uOutputDataSize);
3302 const SI_CHAR * a_pInputData)
3304 int retval = WideCharToMultiByte(
3306 (
const wchar_t *) a_pInputData, -1,
3308 return (
size_t) (retval > 0 ? retval : -1);
3325 const SI_CHAR * a_pInputData,
3326 char * a_pOutputData,
3327 size_t a_uOutputDataSize)
3329 int retval = WideCharToMultiByte(
3331 (
const wchar_t *) a_pInputData, -1,
3332 a_pOutputData, (
int) a_uOutputDataSize, 0, 0);
3337 #endif // SI_CONVERT_WIN32
3349 #if defined(SI_CONVERT_ICU)
3362 # define CSimpleIni CSimpleIniW
3363 # define CSimpleIniCase CSimpleIniCaseW
3364 # define SI_NEWLINE SI_NEWLINE_W
3366 # define CSimpleIni CSimpleIniA
3367 # define CSimpleIniCase CSimpleIniCaseA
3368 # define SI_NEWLINE SI_NEWLINE_A
3372 # pragma warning (pop)
3375 #endif // INCLUDED_SimpleIni_h