211 #ifndef INCLUDED_SimpleIni_h
212 #define INCLUDED_SimpleIni_h
214 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
228 # pragma warning (push)
229 # pragma warning (disable: 4127 4503 4702 4786)
240 #ifdef SI_SUPPORT_IOSTREAMS
248 # define SI_ASSERT(x) assert(x)
250 # define SI_ASSERT(x)
253 using SI_Error = int;
255 constexpr
int SI_OK = 0;
256 constexpr
int SI_UPDATED = 1;
257 constexpr
int SI_INSERTED = 2;
260 constexpr
int SI_FAIL = -1;
261 constexpr
int SI_NOMEM = -2;
262 constexpr
int SI_FILE = -3;
264 #define SI_UTF8_SIGNATURE "\xEF\xBB\xBF"
267 # define SI_NEWLINE_A "\r\n"
268 # define SI_NEWLINE_W L"\r\n"
270 # define SI_NEWLINE_A "\n"
271 # define SI_NEWLINE_W L"\n"
274 #if defined(SI_CONVERT_ICU)
275 # include <unicode/ustring.h>
279 # define SI_HAS_WIDE_FILE
280 # define SI_WCHAR_T wchar_t
281 #elif defined(SI_CONVERT_ICU)
282 # define SI_HAS_WIDE_FILE
283 # define SI_WCHAR_T UChar
310 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
314 typedef SI_CHAR SI_CHAR_T;
318 const SI_CHAR * pItem;
319 const SI_CHAR * pComment;
322 Entry(
const SI_CHAR * a_pszItem = NULL,
int a_nOrder = 0)
327 Entry(
const SI_CHAR * a_pszItem,
const SI_CHAR * a_pszComment,
int a_nOrder)
329 , pComment(a_pszComment)
335 pComment = rhs.pComment;
340 #if defined(_MSC_VER) && _MSC_VER <= 1200
342 bool operator<(
const Entry & rhs)
const {
return LoadOrder()(*
this, rhs); }
343 bool operator>(
const Entry & rhs)
const {
return LoadOrder()(rhs, *
this); }
348 bool operator()(
const Entry & lhs,
const Entry & rhs)
const {
349 const static SI_STRLESS isLess = SI_STRLESS();
350 return isLess(lhs.pItem, rhs.pItem);
356 bool operator()(
const Entry & lhs,
const Entry & rhs)
const {
357 if (lhs.nOrder != rhs.nOrder) {
358 return lhs.nOrder < rhs.nOrder;
360 return KeyOrder()(lhs.pItem, rhs.pItem);
366 typedef std::multimap<Entry,const SI_CHAR *,typename Entry::KeyOrder>
TKeyVal;
369 typedef std::map<Entry,TKeyVal,typename Entry::KeyOrder>
TSection;
383 virtual void Write(
const char * a_pBuf) = 0;
393 FileWriter(FILE * a_file) : m_file(a_file) { }
394 void Write(
const char * a_pBuf) {
395 fputs(a_pBuf, m_file);
404 std::string & m_string;
406 StringWriter(std::string & a_string) : m_string(a_string) { }
407 void Write(
const char * a_pBuf) {
408 m_string.append(a_pBuf);
415 #ifdef SI_SUPPORT_IOSTREAMS
418 std::ostream & m_ostream;
420 StreamWriter(std::ostream & a_ostream) : m_ostream(a_ostream) { }
421 void Write(
const char * a_pBuf) {
425 StreamWriter(
const StreamWriter &);
426 StreamWriter & operator=(
const StreamWriter &);
435 Converter(
bool a_bStoreIsUtf8) : SI_CONVERTER(a_bStoreIsUtf8) {
436 m_scratch.resize(1024);
440 m_scratch = rhs.m_scratch;
443 bool ConvertToStore(
const SI_CHAR * a_pszString) {
444 size_t uLen = SI_CONVERTER::SizeToStore(a_pszString);
445 if (uLen == (
size_t)(-1)) {
448 while (uLen > m_scratch.size()) {
449 m_scratch.resize(m_scratch.size() * 2);
451 return SI_CONVERTER::ConvertToStore(
453 const_cast<char*
>(m_scratch.data()),
456 const char * Data() {
return m_scratch.data(); }
458 std::string m_scratch;
471 bool a_bIsUtf8 =
false,
472 bool a_bMultiKey =
false,
473 bool a_bMultiLine =
false
483 bool IsEmpty()
const {
return m_data.empty(); }
503 if (!m_pData) m_bStoreIsUtf8 = a_bIsUtf8;
528 m_bAllowMultiKey = a_bAllowMultiKey;
542 m_bAllowMultiLine = a_bAllowMultiLine;
555 m_bSpaces = a_bSpaces;
567 m_bParseQuotes = a_bParseQuotes;
582 m_bAllowKeyOnly = a_bAllowKeyOnly;
603 const char * a_pszFile
606 #ifdef SI_HAS_WIDE_FILE
614 const SI_WCHAR_T * a_pwszFile
629 #ifdef SI_SUPPORT_IOSTREAMS
637 std::istream & a_istream
648 return LoadData(a_strData.c_str(), a_strData.size());
659 const char * a_pData,
680 const char * a_pszFile,
681 bool a_bAddSignature =
true
684 #ifdef SI_HAS_WIDE_FILE
696 const SI_WCHAR_T * a_pwszFile,
697 bool a_bAddSignature =
true
715 bool a_bAddSignature =
false
750 OutputWriter & a_oOutput,
751 bool a_bAddSignature =
false
754 #ifdef SI_SUPPORT_IOSTREAMS
767 std::ostream & a_ostream,
768 bool a_bAddSignature =
false
771 StreamWriter writer(a_ostream);
772 return Save(writer, a_bAddSignature);
788 std::string & a_sBuffer,
789 bool a_bAddSignature =
false
793 return Save(writer, a_bAddSignature);
836 const SI_CHAR * a_pSection,
857 const SI_CHAR * a_pSection,
858 const SI_CHAR * a_pKey,
872 const SI_CHAR * a_pSection
889 const SI_CHAR * a_pSection
894 const SI_CHAR * a_pSection
901 const SI_CHAR * a_pSection,
902 const SI_CHAR * a_pKey
904 return GetValue(a_pSection, a_pKey) != NULL;
925 const SI_CHAR * a_pSection,
926 const SI_CHAR * a_pKey,
927 const SI_CHAR * a_pDefault = NULL,
928 bool * a_pHasMultiple = NULL
945 const SI_CHAR * a_pSection,
946 const SI_CHAR * a_pKey,
948 bool * a_pHasMultiple = NULL
965 const SI_CHAR * a_pSection,
966 const SI_CHAR * a_pKey,
967 double a_nDefault = 0,
968 bool * a_pHasMultiple = NULL
990 const SI_CHAR * a_pSection,
991 const SI_CHAR * a_pKey,
992 bool a_bDefault =
false,
993 bool * a_pHasMultiple = NULL
1026 const SI_CHAR * a_pSection,
1027 const SI_CHAR * a_pKey,
1028 const SI_CHAR * a_pValue,
1029 const SI_CHAR * a_pComment = NULL,
1030 bool a_bForceReplace =
false
1033 return AddEntry(a_pSection, a_pKey, a_pValue, a_pComment, a_bForceReplace,
true);
1060 const SI_CHAR * a_pSection,
1061 const SI_CHAR * a_pKey,
1063 const SI_CHAR * a_pComment = NULL,
1064 bool a_bUseHex =
false,
1065 bool a_bForceReplace =
false
1089 const SI_CHAR * a_pSection,
1090 const SI_CHAR * a_pKey,
1092 const SI_CHAR * a_pComment = NULL,
1093 bool a_bForceReplace =
false
1117 const SI_CHAR * a_pSection,
1118 const SI_CHAR * a_pKey,
1120 const SI_CHAR * a_pComment = NULL,
1121 bool a_bForceReplace =
false
1143 const SI_CHAR * a_pSection,
1144 const SI_CHAR * a_pKey,
1145 bool a_bRemoveEmpty =
false
1169 const SI_CHAR * a_pSection,
1170 const SI_CHAR * a_pKey,
1171 const SI_CHAR * a_pValue,
1172 bool a_bRemoveEmpty =
false
1198 SI_Error FindFileComment(
1209 const SI_CHAR *& a_pSection,
1210 const SI_CHAR *& a_pKey,
1211 const SI_CHAR *& a_pVal,
1212 const SI_CHAR *& a_pComment
1238 const SI_CHAR * a_pSection,
1239 const SI_CHAR * a_pKey,
1240 const SI_CHAR * a_pValue,
1241 const SI_CHAR * a_pComment,
1242 bool a_bForceReplace,
1247 inline bool IsSpace(SI_CHAR ch)
const {
1248 return (ch ==
' ' || ch ==
'\t' || ch ==
'\r' || ch ==
'\n');
1252 inline bool IsComment(SI_CHAR ch)
const {
1253 return (ch ==
';' || ch ==
'#');
1258 inline void SkipNewLine(SI_CHAR *& a_pData)
const {
1259 a_pData += (*a_pData ==
'\r' && *(a_pData+1) ==
'\n') ? 2 : 1;
1263 SI_Error CopyString(
const SI_CHAR *& a_pString);
1266 void DeleteString(
const SI_CHAR * a_pString);
1269 bool IsLess(
const SI_CHAR * a_pLeft,
const SI_CHAR * a_pRight)
const {
1270 const static SI_STRLESS isLess = SI_STRLESS();
1271 return isLess(a_pLeft, a_pRight);
1274 bool IsMultiLineTag(
const SI_CHAR * a_pData)
const;
1275 bool IsMultiLineData(
const SI_CHAR * a_pData)
const;
1276 bool IsSingleLineQuotedValue(
const SI_CHAR* a_pData)
const;
1277 bool LoadMultiLineText(
1279 const SI_CHAR *& a_pVal,
1280 const SI_CHAR * a_pTagName,
1281 bool a_bAllowBlankLinesInComment =
false
1283 bool IsNewLineChar(SI_CHAR a_c)
const;
1285 bool OutputMultiLineText(
1286 OutputWriter & a_oOutput,
1287 Converter & a_oConverter,
1288 const SI_CHAR * a_pText
1306 const SI_CHAR * m_pFileComment;
1309 const SI_CHAR m_cEmptyString;
1321 bool m_bStoreIsUtf8;
1324 bool m_bAllowMultiKey;
1327 bool m_bAllowMultiLine;
1333 bool m_bParseQuotes;
1336 bool m_bAllowKeyOnly;
1348 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1351 bool a_bAllowMultiKey,
1352 bool a_bAllowMultiLine
1356 , m_pFileComment(NULL)
1358 , m_bStoreIsUtf8(a_bIsUtf8)
1359 , m_bAllowMultiKey(a_bAllowMultiKey)
1360 , m_bAllowMultiLine(a_bAllowMultiLine)
1362 , m_bParseQuotes(false)
1363 , m_bAllowKeyOnly(false)
1367 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1373 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1381 m_pFileComment = NULL;
1382 if (!m_data.empty()) {
1383 m_data.erase(m_data.begin(), m_data.end());
1387 if (!m_strings.empty()) {
1388 typename TNamesDepend::iterator i = m_strings.begin();
1389 for (; i != m_strings.end(); ++i) {
1390 delete[]
const_cast<SI_CHAR*
>(i->pItem);
1392 m_strings.erase(m_strings.begin(), m_strings.end());
1396 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1399 const char * a_pszFile
1403 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
1404 fopen_s(&fp, a_pszFile,
"rb");
1406 fp = fopen(a_pszFile,
"rb");
1411 SI_Error rc = LoadFile(fp);
1416 #ifdef SI_HAS_WIDE_FILE
1417 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1420 const SI_WCHAR_T * a_pwszFile
1425 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
1426 _wfopen_s(&fp, a_pwszFile, L
"rb");
1428 fp = _wfopen(a_pwszFile, L
"rb");
1430 if (!fp)
return SI_FILE;
1431 SI_Error rc = LoadFile(fp);
1436 u_austrncpy(szFile, a_pwszFile,
sizeof(szFile));
1437 return LoadFile(szFile);
1442 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1449 int retval = fseek(a_fpFile, 0, SEEK_END);
1453 long lSize = ftell(a_fpFile);
1462 char * pData =
new(std::nothrow)
char[lSize+
static_cast<size_t>(1)];
1469 fseek(a_fpFile, 0, SEEK_SET);
1470 size_t uRead = fread(pData,
sizeof(
char), lSize, a_fpFile);
1471 if (uRead != (
size_t) lSize) {
1477 SI_Error rc = LoadData(pData, uRead);
1482 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1485 const char * a_pData,
1496 if (a_uDataLen >= 3 && memcmp(a_pData, SI_UTF8_SIGNATURE, 3) == 0) {
1499 SI_ASSERT(m_bStoreIsUtf8 || !m_pData);
1503 if (a_uDataLen == 0) {
1508 SI_CONVERTER converter(m_bStoreIsUtf8);
1509 size_t uLen = converter.SizeFromStore(a_pData, a_uDataLen);
1510 if (uLen == (
size_t)(-1)) {
1516 SI_CHAR * pData =
new(std::nothrow) SI_CHAR[uLen+1];
1520 memset(pData, 0,
sizeof(SI_CHAR)*(uLen+1));
1523 if (!converter.ConvertFromStore(a_pData, a_uDataLen, pData, uLen)) {
1529 const static SI_CHAR empty = 0;
1530 SI_CHAR * pWork = pData;
1531 const SI_CHAR * pSection = ∅
1532 const SI_CHAR * pItem = NULL;
1533 const SI_CHAR * pVal = NULL;
1534 const SI_CHAR * pComment = NULL;
1538 bool bCopyStrings = (m_pData != NULL);
1542 SI_Error rc = FindFileComment(pWork, bCopyStrings);
1543 if (rc < 0)
return rc;
1546 while (FindEntry(pWork, pSection, pItem, pVal, pComment)) {
1547 rc = AddEntry(pSection, pItem, pVal, pComment,
false, bCopyStrings);
1548 if (rc < 0)
return rc;
1557 m_uDataLen = uLen+1;
1563 #ifdef SI_SUPPORT_IOSTREAMS
1564 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1567 std::istream & a_istream
1570 std::string strData;
1573 a_istream.get(szBuf,
sizeof(szBuf),
'\0');
1574 strData.append(szBuf);
1576 while (a_istream.good());
1577 return LoadData(strData);
1581 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1589 if (m_pFileComment) {
1595 if (!LoadMultiLineText(a_pData, m_pFileComment, NULL,
false)) {
1600 if (a_bCopyStrings) {
1601 SI_Error rc = CopyString(m_pFileComment);
1602 if (rc < 0)
return rc;
1608 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1612 const SI_CHAR *& a_pSection,
1613 const SI_CHAR *& a_pKey,
1614 const SI_CHAR *& a_pVal,
1615 const SI_CHAR *& a_pComment
1620 bool bHaveValue =
false;
1621 SI_CHAR * pTrail = NULL;
1624 while (*a_pData && IsSpace(*a_pData)) {
1633 if (IsComment(*a_pData)) {
1634 LoadMultiLineText(a_pData, a_pComment, NULL,
true);
1639 if (*a_pData ==
'[') {
1642 while (*a_pData && IsSpace(*a_pData)) {
1648 a_pSection = a_pData;
1649 while (*a_pData && *a_pData !=
']' && !IsNewLineChar(*a_pData)) {
1654 if (*a_pData !=
']') {
1659 pTrail = a_pData - 1;
1660 while (pTrail >= a_pSection && IsSpace(*pTrail)) {
1668 while (*a_pData && !IsNewLineChar(*a_pData)) {
1679 while (*a_pData && *a_pData !=
'=' && !IsNewLineChar(*a_pData)) {
1685 bHaveValue = (*a_pData ==
'=');
1686 if (!bHaveValue && !m_bAllowKeyOnly) {
1691 if (bHaveValue && a_pKey == a_pData) {
1692 while (*a_pData && !IsNewLineChar(*a_pData)) {
1699 pTrail = a_pData - 1;
1700 while (pTrail >= a_pKey && IsSpace(*pTrail)) {
1711 while (*a_pData && !IsNewLineChar(*a_pData) && IsSpace(*a_pData)) {
1717 while (*a_pData && !IsNewLineChar(*a_pData)) {
1722 pTrail = a_pData - 1;
1724 SkipNewLine(a_pData);
1726 while (pTrail >= a_pVal && IsSpace(*pTrail)) {
1733 if (m_bAllowMultiLine && IsMultiLineTag(a_pVal)) {
1735 const SI_CHAR* pTagName = a_pVal + 3;
1736 return LoadMultiLineText(a_pData, a_pVal, pTagName);
1740 if (m_bParseQuotes) {
1742 if (pTrail > a_pVal && *a_pVal ==
'"' && *pTrail ==
'"') {
1751 SkipNewLine(a_pData);
1763 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1766 const SI_CHAR * a_pVal
1770 if (*a_pVal++ !=
'<')
return false;
1771 if (*a_pVal++ !=
'<')
return false;
1772 if (*a_pVal++ !=
'<')
return false;
1776 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1779 const SI_CHAR * a_pData
1793 if (IsSpace(*a_pData)) {
1799 if (IsNewLineChar(*a_pData)) {
1806 if (IsSpace(*--a_pData)) {
1813 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1816 const SI_CHAR* a_pData
1828 if (IsSpace(*a_pData)) {
1834 if (IsNewLineChar(*a_pData)) {
1841 if (IsSpace(*--a_pData)) {
1848 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1854 return (a_c ==
'\n' || a_c ==
'\r');
1857 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1861 const SI_CHAR *& a_pVal,
1862 const SI_CHAR * a_pTagName,
1863 bool a_bAllowBlankLinesInComment
1874 SI_CHAR * pDataLine = a_pData;
1875 SI_CHAR * pCurrLine;
1883 SI_CHAR cEndOfLineChar = *a_pData;
1887 if (!a_pTagName && !IsComment(*a_pData)) {
1889 if (!a_bAllowBlankLinesInComment) {
1896 SI_CHAR * pCurr = a_pData;
1898 while (IsSpace(*pCurr)) {
1899 if (IsNewLineChar(*pCurr)) {
1910 if (IsComment(*pCurr)) {
1911 for (; nNewLines > 0; --nNewLines) *pDataLine++ =
'\n';
1921 pCurrLine = a_pData;
1922 while (*a_pData && !IsNewLineChar(*a_pData)) ++a_pData;
1925 if (pDataLine < pCurrLine) {
1926 size_t nLen = (size_t) (a_pData - pCurrLine);
1927 memmove(pDataLine, pCurrLine, nLen *
sizeof(SI_CHAR));
1928 pDataLine[nLen] =
'\0';
1932 cEndOfLineChar = *a_pData;
1940 SI_CHAR* pc = a_pData - 1;
1941 while (pc > pDataLine && IsSpace(*pc)) --pc;
1945 if (!IsLess(pDataLine, a_pTagName) && !IsLess(a_pTagName, pDataLine)) {
1954 if (!cEndOfLineChar) {
1960 pDataLine += (a_pData - pCurrLine);
1961 *a_pData = cEndOfLineChar;
1962 SkipNewLine(a_pData);
1963 *pDataLine++ =
'\n';
1967 if (a_pVal == a_pData) {
1976 *--pDataLine =
'\0';
1980 if (a_pTagName && cEndOfLineChar) {
1981 SI_ASSERT(IsNewLineChar(cEndOfLineChar));
1982 *a_pData = cEndOfLineChar;
1983 SkipNewLine(a_pData);
1989 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1992 const SI_CHAR *& a_pString
1996 if (
sizeof(SI_CHAR) ==
sizeof(
char)) {
1997 uLen = strlen((
const char *)a_pString);
1999 else if (
sizeof(SI_CHAR) ==
sizeof(
wchar_t)) {
2000 uLen = wcslen((
const wchar_t *)a_pString);
2003 for ( ; a_pString[uLen]; ++uLen) ;
2006 SI_CHAR * pCopy =
new(std::nothrow) SI_CHAR[uLen];
2010 memcpy(pCopy, a_pString,
sizeof(SI_CHAR)*uLen);
2011 m_strings.push_back(pCopy);
2016 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2019 const SI_CHAR * a_pSection,
2020 const SI_CHAR * a_pKey,
2021 const SI_CHAR * a_pValue,
2022 const SI_CHAR * a_pComment,
2023 bool a_bForceReplace,
2028 bool bInserted =
false;
2030 SI_ASSERT(!a_pComment || IsComment(*a_pComment));
2034 if (a_bCopyStrings && a_pComment) {
2035 rc = CopyString(a_pComment);
2036 if (rc < 0)
return rc;
2040 typename TSection::iterator iSection = m_data.find(a_pSection);
2041 if (iSection == m_data.end()) {
2044 if (a_bCopyStrings) {
2045 rc = CopyString(a_pSection);
2046 if (rc < 0)
return rc;
2050 Entry oSection(a_pSection, ++m_nOrder);
2051 if (a_pComment && !a_pKey) {
2052 oSection.pComment = a_pComment;
2055 typename TSection::value_type oEntry(oSection, TKeyVal());
2056 typedef typename TSection::iterator SectionIterator;
2057 std::pair<SectionIterator,bool> i = m_data.insert(oEntry);
2063 return bInserted ? SI_INSERTED : SI_UPDATED;
2067 TKeyVal & keyval = iSection->second;
2068 typename TKeyVal::iterator iKey = keyval.find(a_pKey);
2069 bInserted = iKey == keyval.end();
2073 int nLoadOrder = ++m_nOrder;
2074 if (iKey != keyval.end() && m_bAllowMultiKey && a_bForceReplace) {
2075 const SI_CHAR * pComment = NULL;
2076 while (iKey != keyval.end() && !IsLess(a_pKey, iKey->first.pItem)) {
2077 if (iKey->first.nOrder < nLoadOrder) {
2078 nLoadOrder = iKey->first.nOrder;
2079 pComment = iKey->first.pComment;
2084 DeleteString(a_pComment);
2085 a_pComment = pComment;
2086 CopyString(a_pComment);
2088 Delete(a_pSection, a_pKey);
2089 iKey = keyval.end();
2094 a_pValue = &m_cEmptyString;
2098 bool bForceCreateNewKey = m_bAllowMultiKey && !a_bForceReplace;
2099 if (a_bCopyStrings) {
2100 if (bForceCreateNewKey || iKey == keyval.end()) {
2104 rc = CopyString(a_pKey);
2105 if (rc < 0)
return rc;
2109 rc = CopyString(a_pValue);
2110 if (rc < 0)
return rc;
2114 if (iKey == keyval.end() || bForceCreateNewKey) {
2115 Entry oKey(a_pKey, nLoadOrder);
2117 oKey.pComment = a_pComment;
2119 typename TKeyVal::value_type oEntry(oKey,
static_cast<const SI_CHAR *
>(NULL));
2120 iKey = keyval.insert(oEntry);
2123 iKey->second = a_pValue;
2124 return bInserted ? SI_INSERTED : SI_UPDATED;
2127 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2130 const SI_CHAR * a_pSection,
2131 const SI_CHAR * a_pKey,
2132 const SI_CHAR * a_pDefault,
2133 bool * a_pHasMultiple
2136 if (a_pHasMultiple) {
2137 *a_pHasMultiple =
false;
2139 if (!a_pSection || !a_pKey) {
2142 typename TSection::const_iterator iSection = m_data.find(a_pSection);
2143 if (iSection == m_data.end()) {
2146 typename TKeyVal::const_iterator iKeyVal = iSection->second.find(a_pKey);
2147 if (iKeyVal == iSection->second.end()) {
2152 if (m_bAllowMultiKey && a_pHasMultiple) {
2153 typename TKeyVal::const_iterator iTemp = iKeyVal;
2154 if (++iTemp != iSection->second.end()) {
2155 if (!IsLess(a_pKey, iTemp->first.pItem)) {
2156 *a_pHasMultiple =
true;
2161 return iKeyVal->second;
2164 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2167 const SI_CHAR * a_pSection,
2168 const SI_CHAR * a_pKey,
2170 bool * a_pHasMultiple
2174 const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey, NULL, a_pHasMultiple);
2175 if (!pszValue || !*pszValue)
return a_nDefault;
2178 char szValue[64] = { 0 };
2179 SI_CONVERTER c(m_bStoreIsUtf8);
2180 if (!c.ConvertToStore(pszValue, szValue,
sizeof(szValue))) {
2185 long nValue = a_nDefault;
2186 char * pszSuffix = szValue;
2187 if (szValue[0] ==
'0' && (szValue[1] ==
'x' || szValue[1] ==
'X')) {
2188 if (!szValue[2])
return a_nDefault;
2189 nValue = strtol(&szValue[2], &pszSuffix, 16);
2192 nValue = strtol(szValue, &pszSuffix, 10);
2203 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2206 const SI_CHAR * a_pSection,
2207 const SI_CHAR * a_pKey,
2209 const SI_CHAR * a_pComment,
2211 bool a_bForceReplace
2215 if (!a_pSection || !a_pKey)
return SI_FAIL;
2219 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
2220 sprintf_s(szInput, a_bUseHex ?
"0x%lx" :
"%ld", a_nValue);
2222 snprintf(szInput,
sizeof(szInput), a_bUseHex ?
"0x%lx" :
"%ld", a_nValue);
2226 SI_CHAR szOutput[64];
2227 SI_CONVERTER c(m_bStoreIsUtf8);
2228 c.ConvertFromStore(szInput, strlen(szInput) + 1,
2229 szOutput,
sizeof(szOutput) /
sizeof(SI_CHAR));
2232 return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace,
true);
2235 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2238 const SI_CHAR * a_pSection,
2239 const SI_CHAR * a_pKey,
2241 bool * a_pHasMultiple
2245 const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey, NULL, a_pHasMultiple);
2246 if (!pszValue || !*pszValue)
return a_nDefault;
2249 char szValue[64] = { 0 };
2250 SI_CONVERTER c(m_bStoreIsUtf8);
2251 if (!c.ConvertToStore(pszValue, szValue,
sizeof(szValue))) {
2255 char * pszSuffix = NULL;
2256 double nValue = strtod(szValue, &pszSuffix);
2259 if (!pszSuffix || *pszSuffix) {
2266 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2269 const SI_CHAR * a_pSection,
2270 const SI_CHAR * a_pKey,
2272 const SI_CHAR * a_pComment,
2273 bool a_bForceReplace
2277 if (!a_pSection || !a_pKey)
return SI_FAIL;
2281 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
2282 sprintf_s(szInput,
"%f", a_nValue);
2284 snprintf(szInput,
sizeof(szInput),
"%f", a_nValue);
2288 SI_CHAR szOutput[64];
2289 SI_CONVERTER c(m_bStoreIsUtf8);
2290 c.ConvertFromStore(szInput, strlen(szInput) + 1,
2291 szOutput,
sizeof(szOutput) /
sizeof(SI_CHAR));
2294 return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace,
true);
2297 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2300 const SI_CHAR * a_pSection,
2301 const SI_CHAR * a_pKey,
2303 bool * a_pHasMultiple
2307 const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey, NULL, a_pHasMultiple);
2308 if (!pszValue || !*pszValue)
return a_bDefault;
2311 switch (pszValue[0]) {
2323 if (pszValue[1] ==
'n' || pszValue[1] ==
'N')
return true;
2324 if (pszValue[1] ==
'f' || pszValue[1] ==
'F')
return false;
2332 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2335 const SI_CHAR * a_pSection,
2336 const SI_CHAR * a_pKey,
2338 const SI_CHAR * a_pComment,
2339 bool a_bForceReplace
2343 if (!a_pSection || !a_pKey)
return SI_FAIL;
2346 const char * pszInput = a_bValue ?
"true" :
"false";
2349 SI_CHAR szOutput[64];
2350 SI_CONVERTER c(m_bStoreIsUtf8);
2351 c.ConvertFromStore(pszInput, strlen(pszInput) + 1,
2352 szOutput,
sizeof(szOutput) /
sizeof(SI_CHAR));
2355 return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace,
true);
2358 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2361 const SI_CHAR * a_pSection,
2362 const SI_CHAR * a_pKey,
2368 if (!a_pSection || !a_pKey) {
2371 typename TSection::const_iterator iSection = m_data.find(a_pSection);
2372 if (iSection == m_data.end()) {
2375 typename TKeyVal::const_iterator iKeyVal = iSection->second.find(a_pKey);
2376 if (iKeyVal == iSection->second.end()) {
2381 a_values.push_back(
Entry(iKeyVal->second, iKeyVal->first.pComment, iKeyVal->first.nOrder));
2382 if (m_bAllowMultiKey) {
2384 while (iKeyVal != iSection->second.end() && !IsLess(a_pKey, iKeyVal->first.pItem)) {
2385 a_values.push_back(
Entry(iKeyVal->second, iKeyVal->first.pComment, iKeyVal->first.nOrder));
2393 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2396 const SI_CHAR * a_pSection
2403 typename TSection::const_iterator iSection = m_data.find(a_pSection);
2404 if (iSection == m_data.end()) {
2407 const TKeyVal & section = iSection->second;
2411 if (!m_bAllowMultiKey || section.empty()) {
2412 return (
int) section.size();
2417 const SI_CHAR * pLastKey = NULL;
2418 typename TKeyVal::const_iterator iKeyVal = section.begin();
2419 for (
int n = 0; iKeyVal != section.end(); ++iKeyVal, ++n) {
2420 if (!pLastKey || IsLess(pLastKey, iKeyVal->first.pItem)) {
2422 pLastKey = iKeyVal->first.pItem;
2428 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2431 const SI_CHAR * a_pSection
2435 typename TSection::const_iterator i = m_data.find(a_pSection);
2436 if (i != m_data.end()) {
2437 return &(i->second);
2443 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2450 typename TSection::const_iterator i = m_data.begin();
2451 for (
int n = 0; i != m_data.end(); ++i, ++n ) {
2452 a_names.push_back(i->first);
2456 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2459 const SI_CHAR * a_pSection,
2469 typename TSection::const_iterator iSection = m_data.find(a_pSection);
2470 if (iSection == m_data.end()) {
2474 const TKeyVal & section = iSection->second;
2475 const SI_CHAR * pLastKey = NULL;
2476 typename TKeyVal::const_iterator iKeyVal = section.begin();
2477 for (
int n = 0; iKeyVal != section.end(); ++iKeyVal, ++n ) {
2478 if (!pLastKey || IsLess(pLastKey, iKeyVal->first.pItem)) {
2479 a_names.push_back(iKeyVal->first);
2480 pLastKey = iKeyVal->first.pItem;
2487 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2490 const char * a_pszFile,
2491 bool a_bAddSignature
2495 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
2496 fopen_s(&fp, a_pszFile,
"wb");
2498 fp = fopen(a_pszFile,
"wb");
2500 if (!fp)
return SI_FILE;
2501 SI_Error rc = SaveFile(fp, a_bAddSignature);
2506 #ifdef SI_HAS_WIDE_FILE
2507 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2510 const SI_WCHAR_T * a_pwszFile,
2511 bool a_bAddSignature
2516 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
2517 _wfopen_s(&fp, a_pwszFile, L
"wb");
2519 fp = _wfopen(a_pwszFile, L
"wb");
2521 if (!fp)
return SI_FILE;
2522 SI_Error rc = SaveFile(fp, a_bAddSignature);
2527 u_austrncpy(szFile, a_pwszFile,
sizeof(szFile));
2528 return SaveFile(szFile, a_bAddSignature);
2533 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2537 bool a_bAddSignature
2541 return Save(writer, a_bAddSignature);
2544 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2548 bool a_bAddSignature
2554 if (m_bStoreIsUtf8 && a_bAddSignature) {
2555 a_oOutput.Write(SI_UTF8_SIGNATURE);
2560 GetAllSections(oSections);
2561 #if defined(_MSC_VER) && _MSC_VER <= 1200
2563 #elif defined(__BORLANDC__)
2571 typename TNamesDepend::iterator is = oSections.begin();
2572 for (; is != oSections.end(); ++is) {
2575 if (is != oSections.begin()) {
2576 oSections.splice(oSections.begin(), oSections, is, std::next(is));
2583 bool bNeedNewLine =
false;
2584 if (m_pFileComment) {
2585 if (!OutputMultiLineText(a_oOutput, convert, m_pFileComment)) {
2588 bNeedNewLine =
true;
2592 typename TNamesDepend::const_iterator iSection = oSections.begin();
2593 for ( ; iSection != oSections.end(); ++iSection ) {
2595 if (iSection->pComment) {
2597 a_oOutput.Write(SI_NEWLINE_A);
2598 a_oOutput.Write(SI_NEWLINE_A);
2600 if (!OutputMultiLineText(a_oOutput, convert, iSection->pComment)) {
2603 bNeedNewLine =
false;
2607 a_oOutput.Write(SI_NEWLINE_A);
2608 a_oOutput.Write(SI_NEWLINE_A);
2609 bNeedNewLine =
false;
2613 if (*iSection->pItem) {
2614 if (!convert.ConvertToStore(iSection->pItem)) {
2617 a_oOutput.Write(
"[");
2618 a_oOutput.Write(convert.Data());
2619 a_oOutput.Write(
"]");
2620 a_oOutput.Write(SI_NEWLINE_A);
2625 GetAllKeys(iSection->pItem, oKeys);
2626 #if defined(_MSC_VER) && _MSC_VER <= 1200
2628 #elif defined(__BORLANDC__)
2635 typename TNamesDepend::const_iterator iKey = oKeys.begin();
2636 for ( ; iKey != oKeys.end(); ++iKey) {
2639 GetAllValues(iSection->pItem, iKey->pItem, oValues);
2641 typename TNamesDepend::const_iterator iValue = oValues.begin();
2642 for ( ; iValue != oValues.end(); ++iValue) {
2644 if (iValue->pComment) {
2645 a_oOutput.Write(SI_NEWLINE_A);
2646 if (!OutputMultiLineText(a_oOutput, convert, iValue->pComment)) {
2652 if (!convert.ConvertToStore(iKey->pItem)) {
2655 a_oOutput.Write(convert.Data());
2658 if (*iValue->pItem || !m_bAllowKeyOnly) {
2659 if (!convert.ConvertToStore(iValue->pItem)) {
2662 a_oOutput.Write(m_bSpaces ?
" = " :
"=");
2663 if (m_bParseQuotes && IsSingleLineQuotedValue(iValue->pItem)) {
2666 a_oOutput.Write(
"\"");
2667 a_oOutput.Write(convert.Data());
2668 a_oOutput.Write(
"\"");
2670 else if (m_bAllowMultiLine && IsMultiLineData(iValue->pItem)) {
2673 a_oOutput.Write(
"<<<END_OF_TEXT" SI_NEWLINE_A);
2674 if (!OutputMultiLineText(a_oOutput, convert, iValue->pItem)) {
2677 a_oOutput.Write(
"END_OF_TEXT");
2680 a_oOutput.Write(convert.Data());
2683 a_oOutput.Write(SI_NEWLINE_A);
2687 bNeedNewLine =
true;
2693 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2696 OutputWriter & a_oOutput,
2697 Converter & a_oConverter,
2698 const SI_CHAR * a_pText
2701 const SI_CHAR * pEndOfLine;
2702 SI_CHAR cEndOfLineChar = *a_pText;
2703 while (cEndOfLineChar) {
2705 pEndOfLine = a_pText;
2706 for (; *pEndOfLine && *pEndOfLine !=
'\n'; ++pEndOfLine) ;
2707 cEndOfLineChar = *pEndOfLine;
2710 *
const_cast<SI_CHAR*
>(pEndOfLine) = 0;
2711 if (!a_oConverter.ConvertToStore(a_pText)) {
2714 *
const_cast<SI_CHAR*
>(pEndOfLine) = cEndOfLineChar;
2715 a_pText += (pEndOfLine - a_pText) + 1;
2716 a_oOutput.Write(a_oConverter.Data());
2717 a_oOutput.Write(SI_NEWLINE_A);
2722 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2725 const SI_CHAR * a_pSection,
2726 const SI_CHAR * a_pKey,
2730 return DeleteValue(a_pSection, a_pKey, NULL, a_bRemoveEmpty);
2733 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2736 const SI_CHAR * a_pSection,
2737 const SI_CHAR * a_pKey,
2738 const SI_CHAR * a_pValue,
2746 typename TSection::iterator iSection = m_data.find(a_pSection);
2747 if (iSection == m_data.end()) {
2753 typename TKeyVal::iterator iKeyVal = iSection->second.find(a_pKey);
2754 if (iKeyVal == iSection->second.end()) {
2758 const static SI_STRLESS isLess = SI_STRLESS();
2761 typename TKeyVal::iterator iDelete;
2762 bool bDeleted =
false;
2764 iDelete = iKeyVal++;
2766 if(a_pValue == NULL ||
2767 (isLess(a_pValue, iDelete->second) ==
false &&
2768 isLess(iDelete->second, a_pValue) ==
false)) {
2769 DeleteString(iDelete->first.pItem);
2770 DeleteString(iDelete->second);
2771 iSection->second.erase(iDelete);
2775 while (iKeyVal != iSection->second.end()
2776 && !IsLess(a_pKey, iKeyVal->first.pItem));
2785 if (!a_bRemoveEmpty || !iSection->second.empty()) {
2792 typename TKeyVal::iterator iKeyVal = iSection->second.begin();
2793 for ( ; iKeyVal != iSection->second.end(); ++iKeyVal) {
2794 DeleteString(iKeyVal->first.pItem);
2795 DeleteString(iKeyVal->second);
2800 DeleteString(iSection->first.pItem);
2801 m_data.erase(iSection);
2806 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2809 const SI_CHAR * a_pString
2815 if (a_pString < m_pData || a_pString >= m_pData + m_uDataLen) {
2816 typename TNamesDepend::iterator i = m_strings.begin();
2817 for (;i != m_strings.end(); ++i) {
2818 if (a_pString == i->pItem) {
2819 delete[]
const_cast<SI_CHAR*
>(i->pItem);
2845 #if !defined(SI_NO_CONVERSION) && !defined(SI_CONVERT_GENERIC) && !defined(SI_CONVERT_WIN32) && !defined(SI_CONVERT_ICU)
2847 # define SI_CONVERT_WIN32
2849 # define SI_NO_CONVERSION
2858 template<
class SI_CHAR>
2860 bool operator()(
const SI_CHAR * pLeft,
const SI_CHAR * pRight)
const {
2862 for ( ;*pLeft && *pRight; ++pLeft, ++pRight) {
2863 cmp = (long) *pLeft - (
long) *pRight;
2868 return *pRight != 0;
2878 template<
class SI_CHAR>
2880 inline SI_CHAR locase(SI_CHAR ch)
const {
2881 return (ch < 'A' || ch >
'Z') ? ch : (ch -
'A' +
'a');
2883 bool operator()(
const SI_CHAR * pLeft,
const SI_CHAR * pRight)
const {
2885 for ( ;*pLeft && *pRight; ++pLeft, ++pRight) {
2886 cmp = (long) locase(*pLeft) - (long) locase(*pRight);
2891 return *pRight != 0;
2898 template<
class SI_CHAR>
2900 bool m_bStoreIsUtf8;
2904 SI_ConvertA(
bool a_bStoreIsUtf8) : m_bStoreIsUtf8(a_bStoreIsUtf8) { }
2909 m_bStoreIsUtf8 = rhs.m_bStoreIsUtf8;
2927 const char * a_pInputData,
2928 size_t a_uInputDataLen)
2931 SI_ASSERT(a_uInputDataLen != (
size_t) -1);
2934 return a_uInputDataLen;
2951 const char * a_pInputData,
2952 size_t a_uInputDataLen,
2953 SI_CHAR * a_pOutputData,
2954 size_t a_uOutputDataSize)
2957 if (a_uInputDataLen > a_uOutputDataSize) {
2960 memcpy(a_pOutputData, a_pInputData, a_uInputDataLen);
2975 const SI_CHAR * a_pInputData)
2978 return strlen((
const char *)a_pInputData) + 1;
2995 const SI_CHAR * a_pInputData,
2996 char * a_pOutputData,
2997 size_t a_uOutputDataSize)
3000 size_t uInputLen = strlen((
const char *)a_pInputData) + 1;
3001 if (uInputLen > a_uOutputDataSize) {
3006 memcpy(a_pOutputData, a_pInputData, uInputLen);
3015 #ifdef SI_CONVERT_GENERIC
3017 #define SI_Case SI_GenericCase
3018 #define SI_NoCase SI_GenericNoCase
3021 #include "ConvertUTF.h"
3027 template<
class SI_CHAR>
3029 bool m_bStoreIsUtf8;
3033 SI_ConvertW(
bool a_bStoreIsUtf8) : m_bStoreIsUtf8(a_bStoreIsUtf8) { }
3036 SI_ConvertW(
const SI_ConvertW & rhs) { operator=(rhs); }
3037 SI_ConvertW & operator=(
const SI_ConvertW & rhs) {
3038 m_bStoreIsUtf8 = rhs.m_bStoreIsUtf8;
3055 size_t SizeFromStore(
3056 const char * a_pInputData,
3057 size_t a_uInputDataLen)
3059 SI_ASSERT(a_uInputDataLen != (
size_t) -1);
3061 if (m_bStoreIsUtf8) {
3065 return a_uInputDataLen;
3069 #if defined(_MSC_VER)
3071 errno_t e = mbstowcs_s(&uBufSiz, NULL, 0, a_pInputData, a_uInputDataLen);
3072 return (e == 0) ? uBufSiz : (size_t) -1;
3073 #elif !defined(SI_NO_MBSTOWCS_NULL)
3074 return mbstowcs(NULL, a_pInputData, a_uInputDataLen);
3079 return a_uInputDataLen;
3096 bool ConvertFromStore(
3097 const char * a_pInputData,
3098 size_t a_uInputDataLen,
3099 SI_CHAR * a_pOutputData,
3100 size_t a_uOutputDataSize)
3102 if (m_bStoreIsUtf8) {
3108 ConversionResult retval;
3109 const UTF8 * pUtf8 = (
const UTF8 *) a_pInputData;
3110 if (
sizeof(
wchar_t) ==
sizeof(UTF32)) {
3111 UTF32 * pUtf32 = (UTF32 *) a_pOutputData;
3112 retval = ConvertUTF8toUTF32(
3113 &pUtf8, pUtf8 + a_uInputDataLen,
3114 &pUtf32, pUtf32 + a_uOutputDataSize,
3117 else if (
sizeof(
wchar_t) ==
sizeof(UTF16)) {
3118 UTF16 * pUtf16 = (UTF16 *) a_pOutputData;
3119 retval = ConvertUTF8toUTF16(
3120 &pUtf8, pUtf8 + a_uInputDataLen,
3121 &pUtf16, pUtf16 + a_uOutputDataSize,
3124 return retval == conversionOK;
3128 #if defined(_MSC_VER)
3130 errno_t e = mbstowcs_s(&uBufSiz,
3131 a_pOutputData, a_uOutputDataSize,
3132 a_pInputData, a_uInputDataLen);
3136 size_t retval = mbstowcs(a_pOutputData,
3137 a_pInputData, a_uOutputDataSize);
3138 return retval != (size_t)(-1);
3153 const SI_CHAR * a_pInputData)
3155 if (m_bStoreIsUtf8) {
3158 while (a_pInputData[uLen]) {
3161 return (6 * uLen) + 1;
3164 size_t uLen = wcstombs(NULL, a_pInputData, 0);
3165 if (uLen == (
size_t)(-1)) {
3185 bool ConvertToStore(
3186 const SI_CHAR * a_pInputData,
3187 char * a_pOutputData,
3188 size_t a_uOutputDataSize
3191 if (m_bStoreIsUtf8) {
3193 size_t uInputLen = 0;
3194 while (a_pInputData[uInputLen]) {
3204 ConversionResult retval;
3205 UTF8 * pUtf8 = (UTF8 *) a_pOutputData;
3206 if (
sizeof(
wchar_t) ==
sizeof(UTF32)) {
3207 const UTF32 * pUtf32 = (
const UTF32 *) a_pInputData;
3208 retval = ConvertUTF32toUTF8(
3209 &pUtf32, pUtf32 + uInputLen,
3210 &pUtf8, pUtf8 + a_uOutputDataSize,
3213 else if (
sizeof(
wchar_t) ==
sizeof(UTF16)) {
3214 const UTF16 * pUtf16 = (
const UTF16 *) a_pInputData;
3215 retval = ConvertUTF16toUTF8(
3216 &pUtf16, pUtf16 + uInputLen,
3217 &pUtf8, pUtf8 + a_uOutputDataSize,
3220 return retval == conversionOK;
3223 size_t retval = wcstombs(a_pOutputData,
3224 a_pInputData, a_uOutputDataSize);
3225 return retval != (size_t) -1;
3236 #ifdef SI_CONVERT_ICU
3238 #define SI_Case SI_GenericCase
3239 #define SI_NoCase SI_GenericNoCase
3241 #include <unicode/ucnv.h>
3246 template<
class SI_CHAR>
3248 const char * m_pEncoding;
3249 UConverter * m_pConverter;
3251 SI_ConvertW() : m_pEncoding(NULL), m_pConverter(NULL) { }
3253 SI_ConvertW(
bool a_bStoreIsUtf8) : m_pConverter(NULL) {
3254 m_pEncoding = a_bStoreIsUtf8 ?
"UTF-8" : NULL;
3258 SI_ConvertW(
const SI_ConvertW & rhs) { operator=(rhs); }
3259 SI_ConvertW & operator=(
const SI_ConvertW & rhs) {
3260 m_pEncoding = rhs.m_pEncoding;
3261 m_pConverter = NULL;
3264 ~SI_ConvertW() {
if (m_pConverter) ucnv_close(m_pConverter); }
3279 size_t SizeFromStore(
3280 const char * a_pInputData,
3281 size_t a_uInputDataLen)
3283 SI_ASSERT(a_uInputDataLen != (
size_t) -1);
3287 if (!m_pConverter) {
3288 nError = U_ZERO_ERROR;
3289 m_pConverter = ucnv_open(m_pEncoding, &nError);
3290 if (U_FAILURE(nError)) {
3295 nError = U_ZERO_ERROR;
3296 int32_t nLen = ucnv_toUChars(m_pConverter, NULL, 0,
3297 a_pInputData, (int32_t) a_uInputDataLen, &nError);
3298 if (U_FAILURE(nError) && nError != U_BUFFER_OVERFLOW_ERROR) {
3302 return (
size_t) nLen;
3318 bool ConvertFromStore(
3319 const char * a_pInputData,
3320 size_t a_uInputDataLen,
3321 UChar * a_pOutputData,
3322 size_t a_uOutputDataSize)
3326 if (!m_pConverter) {
3327 nError = U_ZERO_ERROR;
3328 m_pConverter = ucnv_open(m_pEncoding, &nError);
3329 if (U_FAILURE(nError)) {
3334 nError = U_ZERO_ERROR;
3335 ucnv_toUChars(m_pConverter,
3336 a_pOutputData, (int32_t) a_uOutputDataSize,
3337 a_pInputData, (int32_t) a_uInputDataLen, &nError);
3338 if (U_FAILURE(nError)) {
3356 const UChar * a_pInputData)
3360 if (!m_pConverter) {
3361 nError = U_ZERO_ERROR;
3362 m_pConverter = ucnv_open(m_pEncoding, &nError);
3363 if (U_FAILURE(nError)) {
3368 nError = U_ZERO_ERROR;
3369 int32_t nLen = ucnv_fromUChars(m_pConverter, NULL, 0,
3370 a_pInputData, -1, &nError);
3371 if (U_FAILURE(nError) && nError != U_BUFFER_OVERFLOW_ERROR) {
3375 return (
size_t) nLen + 1;
3391 bool ConvertToStore(
3392 const UChar * a_pInputData,
3393 char * a_pOutputData,
3394 size_t a_uOutputDataSize)
3398 if (!m_pConverter) {
3399 nError = U_ZERO_ERROR;
3400 m_pConverter = ucnv_open(m_pEncoding, &nError);
3401 if (U_FAILURE(nError)) {
3406 nError = U_ZERO_ERROR;
3407 ucnv_fromUChars(m_pConverter,
3408 a_pOutputData, (int32_t) a_uOutputDataSize,
3409 a_pInputData, -1, &nError);
3410 if (U_FAILURE(nError)) {
3424 #ifdef SI_CONVERT_WIN32
3426 #define SI_Case SI_GenericCase
3435 #include <windows.h>
3437 # define SI_NoCase SI_GenericNoCase
3447 #include <mbstring.h>
3448 template<
class SI_CHAR>
3450 bool operator()(
const SI_CHAR * pLeft,
const SI_CHAR * pRight)
const {
3451 if (
sizeof(SI_CHAR) ==
sizeof(
char)) {
3452 return _mbsicmp((
const unsigned char *)pLeft,
3453 (
const unsigned char *)pRight) < 0;
3455 if (
sizeof(SI_CHAR) ==
sizeof(
wchar_t)) {
3456 return _wcsicmp((
const wchar_t *)pLeft,
3457 (
const wchar_t *)pRight) < 0;
3470 template<
class SI_CHAR>
3476 SI_ConvertW(
bool a_bStoreIsUtf8) {
3477 m_uCodePage = a_bStoreIsUtf8 ? CP_UTF8 : CP_ACP;
3481 SI_ConvertW(
const SI_ConvertW & rhs) { operator=(rhs); }
3482 SI_ConvertW & operator=(
const SI_ConvertW & rhs) {
3483 m_uCodePage = rhs.m_uCodePage;
3500 size_t SizeFromStore(
3501 const char * a_pInputData,
3502 size_t a_uInputDataLen)
3504 SI_ASSERT(a_uInputDataLen != (
size_t) -1);
3506 int retval = MultiByteToWideChar(
3508 a_pInputData, (
int) a_uInputDataLen,
3510 return (
size_t)(retval > 0 ? retval : -1);
3526 bool ConvertFromStore(
3527 const char * a_pInputData,
3528 size_t a_uInputDataLen,
3529 SI_CHAR * a_pOutputData,
3530 size_t a_uOutputDataSize)
3532 int nSize = MultiByteToWideChar(
3534 a_pInputData, (
int) a_uInputDataLen,
3535 (
wchar_t *) a_pOutputData, (
int) a_uOutputDataSize);
3550 const SI_CHAR * a_pInputData)
3552 int retval = WideCharToMultiByte(
3554 (
const wchar_t *) a_pInputData, -1,
3556 return (
size_t) (retval > 0 ? retval : -1);
3572 bool ConvertToStore(
3573 const SI_CHAR * a_pInputData,
3574 char * a_pOutputData,
3575 size_t a_uOutputDataSize)
3577 int retval = WideCharToMultiByte(
3579 (
const wchar_t *) a_pInputData, -1,
3580 a_pOutputData, (
int) a_uOutputDataSize, 0, 0);
3592 #ifdef SI_NO_CONVERSION
3594 #define SI_Case SI_GenericCase
3595 #define SI_NoCase SI_GenericNoCase
3610 #if defined(SI_NO_CONVERSION)
3613 # define CSimpleIni CSimpleIniA
3614 # define CSimpleIniCase CSimpleIniCaseA
3615 # define SI_NEWLINE SI_NEWLINE_A
3617 # if defined(SI_CONVERT_ICU)
3619 SI_NoCase<UChar>,SI_ConvertW<UChar> > CSimpleIniW;
3621 SI_Case<UChar>,SI_ConvertW<UChar> > CSimpleIniCaseW;
3624 SI_NoCase<wchar_t>,SI_ConvertW<wchar_t> > CSimpleIniW;
3626 SI_Case<wchar_t>,SI_ConvertW<wchar_t> > CSimpleIniCaseW;
3630 # define CSimpleIni CSimpleIniW
3631 # define CSimpleIniCase CSimpleIniCaseW
3632 # define SI_NEWLINE SI_NEWLINE_W
3634 # define CSimpleIni CSimpleIniA
3635 # define CSimpleIniCase CSimpleIniCaseA
3636 # define SI_NEWLINE SI_NEWLINE_A
3641 # pragma warning (pop)
Definition: SimpleIni.h:433
Definition: SimpleIni.h:390
Definition: SimpleIni.h:379
Definition: SimpleIni.h:403
Definition: SimpleIni.h:312
bool DeleteValue(const SI_CHAR *a_pSection, const SI_CHAR *a_pKey, const SI_CHAR *a_pValue, bool a_bRemoveEmpty=false)
Definition: SimpleIni.h:2735
bool GetAllKeys(const SI_CHAR *a_pSection, TNamesDepend &a_names) const
Definition: SimpleIni.h:2458
int GetSectionSize(const SI_CHAR *a_pSection) const
Definition: SimpleIni.h:2395
void SetAllowKeyOnly(bool a_bAllowKeyOnly=true)
Definition: SimpleIni.h:581
SI_Error LoadData(const std::string &a_strData)
Definition: SimpleIni.h:647
bool UsingQuotes() const
Definition: SimpleIni.h:571
std::map< Entry, TKeyVal, typename Entry::KeyOrder > TSection
Definition: SimpleIni.h:369
std::list< Entry > TNamesDepend
Definition: SimpleIni.h:374
bool IsUnicode() const
Definition: SimpleIni.h:507
SI_Error SetBoolValue(const SI_CHAR *a_pSection, const SI_CHAR *a_pKey, bool a_bValue, const SI_CHAR *a_pComment=NULL, bool a_bForceReplace=false)
Definition: SimpleIni.h:2334
bool IsMultiKey() const
Definition: SimpleIni.h:532
Converter GetConverter() const
Definition: SimpleIni.h:1184
bool IsEmpty() const
Definition: SimpleIni.h:483
const TKeyVal * GetSection(const SI_CHAR *a_pSection) const
Definition: SimpleIni.h:2430
SI_Error Save(OutputWriter &a_oOutput, bool a_bAddSignature=false) const
Definition: SimpleIni.h:2546
const SI_CHAR * GetValue(const SI_CHAR *a_pSection, const SI_CHAR *a_pKey, const SI_CHAR *a_pDefault=NULL, bool *a_pHasMultiple=NULL) const
Definition: SimpleIni.h:2129
bool GetBoolValue(const SI_CHAR *a_pSection, const SI_CHAR *a_pKey, bool a_bDefault=false, bool *a_pHasMultiple=NULL) const
Definition: SimpleIni.h:2299
long GetLongValue(const SI_CHAR *a_pSection, const SI_CHAR *a_pKey, long a_nDefault=0, bool *a_pHasMultiple=NULL) const
Definition: SimpleIni.h:2166
void GetAllSections(TNamesDepend &a_names) const
Definition: SimpleIni.h:2445
void Reset()
Definition: SimpleIni.h:1375
~CSimpleIniTempl()
Definition: SimpleIni.h:1368
bool UsingSpaces() const
Definition: SimpleIni.h:559
SI_Error Save(std::string &a_sBuffer, bool a_bAddSignature=false) const
Definition: SimpleIni.h:787
bool KeyExists(const SI_CHAR *a_pSection, const SI_CHAR *a_pKey) const
Definition: SimpleIni.h:900
SI_Error SetValue(const SI_CHAR *a_pSection, const SI_CHAR *a_pKey, const SI_CHAR *a_pValue, const SI_CHAR *a_pComment=NULL, bool a_bForceReplace=false)
Definition: SimpleIni.h:1025
bool SectionExists(const SI_CHAR *a_pSection) const
Definition: SimpleIni.h:893
bool Delete(const SI_CHAR *a_pSection, const SI_CHAR *a_pKey, bool a_bRemoveEmpty=false)
Definition: SimpleIni.h:2724
void SetMultiLine(bool a_bAllowMultiLine=true)
Definition: SimpleIni.h:541
void SetQuotes(bool a_bParseQuotes=true)
Definition: SimpleIni.h:566
void SetUnicode(bool a_bIsUtf8=true)
Definition: SimpleIni.h:502
double GetDoubleValue(const SI_CHAR *a_pSection, const SI_CHAR *a_pKey, double a_nDefault=0, bool *a_pHasMultiple=NULL) const
Definition: SimpleIni.h:2237
SI_Error SetLongValue(const SI_CHAR *a_pSection, const SI_CHAR *a_pKey, long a_nValue, const SI_CHAR *a_pComment=NULL, bool a_bUseHex=false, bool a_bForceReplace=false)
Definition: SimpleIni.h:2205
void SetMultiKey(bool a_bAllowMultiKey=true)
Definition: SimpleIni.h:527
bool GetAllValues(const SI_CHAR *a_pSection, const SI_CHAR *a_pKey, TNamesDepend &a_values) const
Definition: SimpleIni.h:2360
void SetSpaces(bool a_bSpaces=true)
Definition: SimpleIni.h:554
std::multimap< Entry, const SI_CHAR *, typename Entry::KeyOrder > TKeyVal
Definition: SimpleIni.h:366
SI_Error LoadFile(const char *a_pszFile)
Definition: SimpleIni.h:1398
bool GetAllowKeyOnly() const
Definition: SimpleIni.h:586
SI_Error SaveFile(const char *a_pszFile, bool a_bAddSignature=true) const
Definition: SimpleIni.h:2489
CSimpleIniTempl(bool a_bIsUtf8=false, bool a_bMultiKey=false, bool a_bMultiLine=false)
Definition: SimpleIni.h:1349
SI_Error SetDoubleValue(const SI_CHAR *a_pSection, const SI_CHAR *a_pKey, double a_nValue, const SI_CHAR *a_pComment=NULL, bool a_bForceReplace=false)
Definition: SimpleIni.h:2268
bool IsMultiLine() const
Definition: SimpleIni.h:546
Definition: SimpleIni.h:2899
bool ConvertToStore(const SI_CHAR *a_pInputData, char *a_pOutputData, size_t a_uOutputDataSize)
Definition: SimpleIni.h:2994
size_t SizeFromStore(const char *a_pInputData, size_t a_uInputDataLen)
Definition: SimpleIni.h:2926
size_t SizeToStore(const SI_CHAR *a_pInputData)
Definition: SimpleIni.h:2974
bool ConvertFromStore(const char *a_pInputData, size_t a_uInputDataLen, SI_CHAR *a_pOutputData, size_t a_uOutputDataSize)
Definition: SimpleIni.h:2950
Definition: SimpleIni.h:347
Definition: SimpleIni.h:355
Definition: SimpleIni.h:317
Definition: SimpleIni.h:2859
Definition: SimpleIni.h:2879