1 #ifndef CONF_MANAGER_HPP
2 #define CONF_MANAGER_HPP
18 #pragma comment(lib, "urlmon.lib")
48 #ifndef INCLUDED_SimpleIni_h
49 #define INCLUDED_SimpleIni_h
51 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
65 #pragma warning (push)
66 #pragma warning (disable: 4127 4503 4702 4786)
77 #ifdef SI_SUPPORT_IOSTREAMS
85 #define SI_ASSERT(x) assert(x)
104 #define SI_UTF8_SIGNATURE "\xEF\xBB\xBF"
107 #define SI_NEWLINE_A "\r\n"
108 #define SI_NEWLINE_W L"\r\n"
110 #define SI_NEWLINE_A "\n"
111 #define SI_NEWLINE_W L"\n"
114 #if defined(SI_CONVERT_ICU)
115 #include <unicode/ustring.h>
119 #define SI_HAS_WIDE_FILE
120 #define SI_WCHAR_T wchar_t
121 #elif defined(SI_CONVERT_ICU)
122 #define SI_HAS_WIDE_FILE
123 #define SI_WCHAR_T UChar
126 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
137 Entry(
const SI_CHAR * a_pszItem = NULL,
int a_nOrder = 0)
143 Entry(
const SI_CHAR * a_pszItem,
const SI_CHAR * a_pszComment,
int a_nOrder)
160 #if defined(_MSC_VER) && _MSC_VER <= 1200
173 struct KeyOrder : std::binary_function<Entry, Entry, bool> {
176 const static SI_STRLESS isLess = SI_STRLESS();
182 struct LoadOrder : std::binary_function<Entry, Entry, bool> {
194 typedef std::multimap<Entry, const SI_CHAR *, typename Entry::KeyOrder>
TKeyVal;
197 typedef std::map<Entry, TKeyVal, typename Entry::KeyOrder>
TSection;
215 virtual void Write(
const char * a_pBuf) = 0;
230 fputs(a_pBuf, m_file);
239 std::string & m_string;
246 m_string.append(a_pBuf);
253 #ifdef SI_SUPPORT_IOSTREAMS
257 std::ostream & m_ostream;
278 Converter(
bool a_bStoreIsUtf8) : SI_CONVERTER(a_bStoreIsUtf8) {
279 m_scratch.resize(1024);
287 m_scratch = rhs.m_scratch;
292 size_t uLen = SI_CONVERTER::SizeToStore(a_pszString);
293 if (uLen == (
size_t) (-1)) {
296 while (uLen > m_scratch.size()) {
297 m_scratch.resize(m_scratch.size() * 2);
299 return SI_CONVERTER::ConvertToStore(
301 const_cast<char*
> (m_scratch.data()),
306 return m_scratch.data();
309 std::string m_scratch;
322 bool a_bIsUtf8 =
false,
323 bool a_bMultiKey =
false,
324 bool a_bMultiLine =
false
335 return m_data.empty();
356 if (!m_pData) m_bStoreIsUtf8 = a_bIsUtf8;
361 return m_bStoreIsUtf8;
383 m_bAllowMultiKey = a_bAllowMultiKey;
388 return m_bAllowMultiKey;
399 m_bAllowMultiLine = a_bAllowMultiLine;
404 return m_bAllowMultiLine;
414 m_bSpaces = a_bSpaces;
435 const char * a_pszFile
438 #ifdef SI_HAS_WIDE_FILE
446 const SI_WCHAR_T * a_pwszFile
461 #ifdef SI_SUPPORT_IOSTREAMS
469 std::istream & a_istream
480 return LoadData(a_strData.c_str(), a_strData.size());
491 const char * a_pData,
509 const char * a_pszFile,
510 bool a_bAddSignature =
true
513 #ifdef SI_HAS_WIDE_FILE
525 const SI_WCHAR_T * a_pwszFile,
526 bool a_bAddSignature =
true
544 bool a_bAddSignature =
false
579 OutputWriter & a_oOutput,
580 bool a_bAddSignature =
false
583 #ifdef SI_SUPPORT_IOSTREAMS
597 std::ostream & a_ostream,
598 bool a_bAddSignature =
false
601 return Save(writer, a_bAddSignature);
617 std::string & a_sBuffer,
618 bool a_bAddSignature =
false
621 return Save(writer, a_bAddSignature);
661 const SI_CHAR * a_pSection,
682 const SI_CHAR * a_pSection,
683 const SI_CHAR * a_pKey,
697 const SI_CHAR * a_pSection
715 const SI_CHAR * a_pSection
736 const SI_CHAR * a_pSection,
737 const SI_CHAR * a_pKey,
738 const SI_CHAR * a_pDefault = NULL,
739 bool * a_pHasMultiple = NULL
756 const SI_CHAR * a_pSection,
757 const SI_CHAR * a_pKey,
759 bool * a_pHasMultiple = NULL
776 const SI_CHAR * a_pSection,
777 const SI_CHAR * a_pKey,
778 double a_nDefault = 0,
779 bool * a_pHasMultiple = NULL
801 const SI_CHAR * a_pSection,
802 const SI_CHAR * a_pKey,
803 bool a_bDefault =
false,
804 bool * a_pHasMultiple = NULL
837 const SI_CHAR * a_pSection,
838 const SI_CHAR * a_pKey,
839 const SI_CHAR * a_pValue,
840 const SI_CHAR * a_pComment = NULL,
841 bool a_bForceReplace =
false
843 return AddEntry(a_pSection, a_pKey, a_pValue, a_pComment, a_bForceReplace,
true);
870 const SI_CHAR * a_pSection,
871 const SI_CHAR * a_pKey,
873 const SI_CHAR * a_pComment = NULL,
874 bool a_bUseHex =
false,
875 bool a_bForceReplace =
false
899 const SI_CHAR * a_pSection,
900 const SI_CHAR * a_pKey,
902 const SI_CHAR * a_pComment = NULL,
903 bool a_bForceReplace =
false
927 const SI_CHAR * a_pSection,
928 const SI_CHAR * a_pKey,
930 const SI_CHAR * a_pComment = NULL,
931 bool a_bForceReplace =
false
953 const SI_CHAR * a_pSection,
954 const SI_CHAR * a_pKey,
955 bool a_bRemoveEmpty =
false
979 const SI_CHAR * a_pSection,
980 const SI_CHAR * a_pKey,
981 const SI_CHAR * a_pValue,
982 bool a_bRemoveEmpty =
false
1015 const SI_CHAR *& a_pSection,
1016 const SI_CHAR *& a_pKey,
1017 const SI_CHAR *& a_pVal,
1018 const SI_CHAR *& a_pComment
1044 const SI_CHAR * a_pSection,
1045 const SI_CHAR * a_pKey,
1046 const SI_CHAR * a_pValue,
1047 const SI_CHAR * a_pComment,
1048 bool a_bForceReplace,
1053 inline bool IsSpace(SI_CHAR ch)
const {
1054 return (ch ==
' ' || ch ==
'\t' || ch ==
'\r' || ch ==
'\n');
1058 inline bool IsComment(SI_CHAR ch)
const {
1059 return (ch ==
';' || ch ==
'#');
1063 inline void SkipNewLine(SI_CHAR *& a_pData)
const {
1064 a_pData += (*a_pData ==
'\r' && *(a_pData + 1) ==
'\n') ? 2 : 1;
1068 SI_Error CopyString(
const SI_CHAR *& a_pString);
1071 void DeleteString(
const SI_CHAR * a_pString);
1074 bool IsLess(
const SI_CHAR * a_pLeft,
const SI_CHAR * a_pRight)
const {
1075 const static SI_STRLESS isLess = SI_STRLESS();
1076 return isLess(a_pLeft, a_pRight);
1079 bool IsMultiLineTag(
const SI_CHAR * a_pData)
const;
1080 bool IsMultiLineData(
const SI_CHAR * a_pData)
const;
1081 bool LoadMultiLineText(
1083 const SI_CHAR *& a_pVal,
1084 const SI_CHAR * a_pTagName,
1085 bool a_bAllowBlankLinesInComment =
false
1087 bool IsNewLineChar(SI_CHAR a_c)
const;
1089 bool OutputMultiLineText(
1090 OutputWriter & a_oOutput,
1091 Converter & a_oConverter,
1092 const SI_CHAR * a_pText
1110 const SI_CHAR * m_pFileComment;
1122 bool m_bStoreIsUtf8;
1125 bool m_bAllowMultiKey;
1128 bool m_bAllowMultiLine;
1143 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1146 bool a_bAllowMultiKey,
1147 bool a_bAllowMultiLine
1151 , m_pFileComment(NULL)
1152 , m_bStoreIsUtf8(a_bIsUtf8)
1153 , m_bAllowMultiKey(a_bAllowMultiKey)
1154 , m_bAllowMultiLine(a_bAllowMultiLine)
1159 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1164 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1171 m_pFileComment = NULL;
1172 if (!m_data.empty()) {
1173 m_data.erase(m_data.begin(), m_data.end());
1177 if (!m_strings.empty()) {
1178 typename TNamesDepend::iterator i = m_strings.begin();
1179 for (; i != m_strings.end(); ++i) {
1180 delete[]
const_cast<SI_CHAR*
> (i->pItem);
1182 m_strings.erase(m_strings.begin(), m_strings.end());
1186 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1189 const char * a_pszFile
1192 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
1193 fopen_s(&fp, a_pszFile,
"rb");
1195 fp = fopen(a_pszFile,
"rb");
1205 #ifdef SI_HAS_WIDE_FILE
1207 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1210 const SI_WCHAR_T * a_pwszFile
1214 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
1215 _wfopen_s(&fp, a_pwszFile, L
"rb");
1217 fp = _wfopen(a_pwszFile, L
"rb");
1225 u_austrncpy(szFile, a_pwszFile,
sizeof (szFile));
1226 return LoadFile(szFile);
1231 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1237 int retval = fseek(a_fpFile, 0, SEEK_END);
1241 long lSize = ftell(a_fpFile);
1250 char * pData =
new(std::nothrow)
char[lSize + 1];
1257 fseek(a_fpFile, 0, SEEK_SET);
1258 size_t uRead = fread(pData,
sizeof (
char), lSize, a_fpFile);
1259 if (uRead != (
size_t) lSize) {
1265 SI_Error rc = LoadData(pData, uRead);
1270 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1273 const char * a_pData,
1276 SI_CONVERTER converter(m_bStoreIsUtf8);
1278 if (a_uDataLen == 0) {
1283 if (m_bStoreIsUtf8 && a_uDataLen >= 3) {
1284 if (memcmp(a_pData, SI_UTF8_SIGNATURE, 3) == 0) {
1291 size_t uLen = converter.SizeFromStore(a_pData, a_uDataLen);
1292 if (uLen == (
size_t) (-1)) {
1298 SI_CHAR * pData =
new(std::nothrow) SI_CHAR[uLen + 1];
1302 memset(pData, 0,
sizeof (SI_CHAR)*(uLen + 1));
1305 if (!converter.ConvertFromStore(a_pData, a_uDataLen, pData, uLen)) {
1311 const static SI_CHAR empty = 0;
1312 SI_CHAR * pWork = pData;
1313 const SI_CHAR * pSection = ∅
1314 const SI_CHAR * pItem = NULL;
1315 const SI_CHAR * pVal = NULL;
1316 const SI_CHAR * pComment = NULL;
1320 bool bCopyStrings = (m_pData != NULL);
1324 SI_Error rc = FindFileComment(pWork, bCopyStrings);
1325 if (rc < 0)
return rc;
1328 while (FindEntry(pWork, pSection, pItem, pVal, pComment)) {
1329 rc = AddEntry(pSection, pItem, pVal, pComment,
false, bCopyStrings);
1330 if (rc < 0)
return rc;
1338 m_uDataLen = uLen + 1;
1344 #ifdef SI_SUPPORT_IOSTREAMS
1346 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1349 std::istream & a_istream
1351 std::string strData;
1354 a_istream.get(szBuf,
sizeof (szBuf),
'\0');
1355 strData.append(szBuf);
1356 }
while (a_istream.good());
1357 return LoadData(strData);
1361 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1368 if (m_pFileComment) {
1374 if (!LoadMultiLineText(a_pData, m_pFileComment, NULL,
false)) {
1379 if (a_bCopyStrings) {
1380 SI_Error rc = CopyString(m_pFileComment);
1381 if (rc < 0)
return rc;
1387 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1389 CSimpleIniTempl<SI_CHAR, SI_STRLESS, SI_CONVERTER>::FindEntry(
1391 const SI_CHAR *& a_pSection,
1392 const SI_CHAR *& a_pKey,
1393 const SI_CHAR *& a_pVal,
1394 const SI_CHAR *& a_pComment
1398 SI_CHAR * pTrail = NULL;
1401 while (*a_pData && IsSpace(*a_pData)) {
1410 if (IsComment(*a_pData)) {
1411 LoadMultiLineText(a_pData, a_pComment, NULL,
true);
1416 if (*a_pData ==
'[') {
1419 while (*a_pData && IsSpace(*a_pData)) {
1425 a_pSection = a_pData;
1426 while (*a_pData && *a_pData !=
']' && !IsNewLineChar(*a_pData)) {
1431 if (*a_pData !=
']') {
1436 pTrail = a_pData - 1;
1437 while (pTrail >= a_pSection && IsSpace(*pTrail)) {
1445 while (*a_pData && !IsNewLineChar(*a_pData)) {
1457 while (*a_pData && *a_pData !=
'=' && !IsNewLineChar(*a_pData)) {
1462 if (*a_pData !=
'=') {
1467 if (a_pKey == a_pData) {
1468 while (*a_pData && !IsNewLineChar(*a_pData)) {
1475 pTrail = a_pData - 1;
1476 while (pTrail >= a_pKey && IsSpace(*pTrail)) {
1484 while (*a_pData && !IsNewLineChar(*a_pData) && IsSpace(*a_pData)) {
1490 while (*a_pData && !IsNewLineChar(*a_pData)) {
1495 pTrail = a_pData - 1;
1497 SkipNewLine(a_pData);
1499 while (pTrail >= a_pVal && IsSpace(*pTrail)) {
1506 if (m_bAllowMultiLine && IsMultiLineTag(a_pVal)) {
1508 const SI_CHAR * pTagName = a_pVal + 3;
1509 return LoadMultiLineText(a_pData, a_pVal, pTagName);
1519 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1521 CSimpleIniTempl<SI_CHAR, SI_STRLESS, SI_CONVERTER>::IsMultiLineTag(
1522 const SI_CHAR * a_pVal
1525 if (*a_pVal++ !=
'<')
return false;
1526 if (*a_pVal++ !=
'<')
return false;
1527 if (*a_pVal++ !=
'<')
return false;
1531 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1533 CSimpleIniTempl<SI_CHAR, SI_STRLESS, SI_CONVERTER>::IsMultiLineData(
1534 const SI_CHAR * a_pData
1547 if (IsSpace(*a_pData)) {
1553 if (IsNewLineChar(*a_pData)) {
1560 if (IsSpace(*--a_pData)) {
1567 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1569 CSimpleIniTempl<SI_CHAR, SI_STRLESS, SI_CONVERTER>::IsNewLineChar(
1572 return (a_c ==
'\n' || a_c ==
'\r');
1575 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1577 CSimpleIniTempl<SI_CHAR, SI_STRLESS, SI_CONVERTER>::LoadMultiLineText(
1579 const SI_CHAR *& a_pVal,
1580 const SI_CHAR * a_pTagName,
1581 bool a_bAllowBlankLinesInComment
1591 SI_CHAR * pDataLine = a_pData;
1592 SI_CHAR * pCurrLine;
1600 SI_CHAR cEndOfLineChar = *a_pData;
1604 if (!a_pTagName && !IsComment(*a_pData)) {
1606 if (!a_bAllowBlankLinesInComment) {
1613 SI_CHAR * pCurr = a_pData;
1615 while (IsSpace(*pCurr)) {
1616 if (IsNewLineChar(*pCurr)) {
1626 if (IsComment(*pCurr)) {
1627 for (; nNewLines > 0; --nNewLines) *pDataLine++ =
'\n';
1637 pCurrLine = a_pData;
1638 while (*a_pData && !IsNewLineChar(*a_pData)) ++a_pData;
1641 if (pDataLine < pCurrLine) {
1642 size_t nLen = (size_t) (a_pData - pCurrLine);
1643 memmove(pDataLine, pCurrLine, nLen *
sizeof (SI_CHAR));
1644 pDataLine[nLen] =
'\0';
1648 cEndOfLineChar = *a_pData;
1655 (!IsLess(pDataLine, a_pTagName) && !IsLess(a_pTagName, pDataLine))) {
1661 if (!cEndOfLineChar) {
1667 pDataLine += (a_pData - pCurrLine);
1668 *a_pData = cEndOfLineChar;
1669 SkipNewLine(a_pData);
1670 *pDataLine++ =
'\n';
1674 if (a_pVal == a_pData) {
1683 *--pDataLine =
'\0';
1687 if (a_pTagName && cEndOfLineChar) {
1688 SI_ASSERT(IsNewLineChar(cEndOfLineChar));
1689 *a_pData = cEndOfLineChar;
1690 SkipNewLine(a_pData);
1696 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1698 CSimpleIniTempl<SI_CHAR, SI_STRLESS, SI_CONVERTER>::CopyString(
1699 const SI_CHAR *& a_pString
1702 if (
sizeof (SI_CHAR) ==
sizeof (
char)) {
1703 uLen = strlen((
const char *) a_pString);
1704 }
else if (
sizeof (SI_CHAR) ==
sizeof (
wchar_t)) {
1705 uLen = wcslen((
const wchar_t *)a_pString);
1707 for (; a_pString[uLen]; ++uLen) ;
1710 SI_CHAR * pCopy =
new(std::nothrow) SI_CHAR[uLen];
1714 memcpy(pCopy, a_pString,
sizeof (SI_CHAR) * uLen);
1715 m_strings.push_back(pCopy);
1720 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1722 CSimpleIniTempl<SI_CHAR, SI_STRLESS, SI_CONVERTER>::AddEntry(
1723 const SI_CHAR * a_pSection,
1724 const SI_CHAR * a_pKey,
1725 const SI_CHAR * a_pValue,
1726 const SI_CHAR * a_pComment,
1727 bool a_bForceReplace,
1731 bool bInserted =
false;
1733 SI_ASSERT(!a_pComment || IsComment(*a_pComment));
1737 if (a_bCopyStrings && a_pComment) {
1738 rc = CopyString(a_pComment);
1739 if (rc < 0)
return rc;
1743 typename TSection::iterator iSection = m_data.find(a_pSection);
1744 if (iSection == m_data.end()) {
1747 if (a_bCopyStrings) {
1748 rc = CopyString(a_pSection);
1749 if (rc < 0)
return rc;
1753 Entry oSection(a_pSection, ++m_nOrder);
1754 if (a_pComment && (!a_pKey || !a_pValue)) {
1755 oSection.pComment = a_pComment;
1758 typename TSection::value_type oEntry(oSection, TKeyVal());
1759 typedef typename TSection::iterator SectionIterator;
1760 std::pair<SectionIterator, bool> i = m_data.insert(oEntry);
1764 if (!a_pKey || !a_pValue) {
1770 TKeyVal & keyval = iSection->second;
1771 typename TKeyVal::iterator iKey = keyval.find(a_pKey);
1775 int nLoadOrder = ++m_nOrder;
1776 if (iKey != keyval.end() && m_bAllowMultiKey && a_bForceReplace) {
1777 const SI_CHAR * pComment = NULL;
1778 while (iKey != keyval.end() && !IsLess(a_pKey, iKey->first.pItem)) {
1779 if (iKey->first.nOrder < nLoadOrder) {
1780 nLoadOrder = iKey->first.nOrder;
1781 pComment = iKey->first.pComment;
1786 DeleteString(a_pComment);
1787 a_pComment = pComment;
1788 CopyString(a_pComment);
1790 Delete(a_pSection, a_pKey);
1791 iKey = keyval.end();
1795 bool bForceCreateNewKey = m_bAllowMultiKey && !a_bForceReplace;
1796 if (a_bCopyStrings) {
1797 if (bForceCreateNewKey || iKey == keyval.end()) {
1801 rc = CopyString(a_pKey);
1802 if (rc < 0)
return rc;
1806 rc = CopyString(a_pValue);
1807 if (rc < 0)
return rc;
1811 if (iKey == keyval.end() || bForceCreateNewKey) {
1812 Entry oKey(a_pKey, nLoadOrder);
1814 oKey.pComment = a_pComment;
1816 typename TKeyVal::value_type oEntry(oKey,
static_cast<const SI_CHAR *
> (NULL));
1817 iKey = keyval.insert(oEntry);
1820 iKey->second = a_pValue;
1824 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1827 const SI_CHAR * a_pSection,
1828 const SI_CHAR * a_pKey,
1829 const SI_CHAR * a_pDefault,
1830 bool * a_pHasMultiple
1832 if (a_pHasMultiple) {
1833 *a_pHasMultiple =
false;
1835 if (!a_pSection || !a_pKey) {
1838 typename TSection::const_iterator iSection = m_data.find(a_pSection);
1839 if (iSection == m_data.end()) {
1842 typename TKeyVal::const_iterator iKeyVal = iSection->second.find(a_pKey);
1843 if (iKeyVal == iSection->second.end()) {
1848 if (m_bAllowMultiKey && a_pHasMultiple) {
1849 typename TKeyVal::const_iterator iTemp = iKeyVal;
1850 if (++iTemp != iSection->second.end()) {
1851 if (!IsLess(a_pKey, iTemp->first.pItem)) {
1852 *a_pHasMultiple =
true;
1857 return iKeyVal->second;
1860 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1863 const SI_CHAR * a_pSection,
1864 const SI_CHAR * a_pKey,
1866 bool * a_pHasMultiple
1869 const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey, NULL, a_pHasMultiple);
1870 if (!pszValue || !*pszValue)
return a_nDefault;
1873 char szValue[64] = {0};
1874 SI_CONVERTER c(m_bStoreIsUtf8);
1875 if (!c.ConvertToStore(pszValue, szValue, sizeof (szValue))) {
1880 long nValue = a_nDefault;
1881 char * pszSuffix = szValue;
1882 if (szValue[0] ==
'0' && (szValue[1] ==
'x' || szValue[1] ==
'X')) {
1883 if (!szValue[2])
return a_nDefault;
1884 nValue = strtol(&szValue[2], &pszSuffix, 16);
1886 nValue = strtol(szValue, &pszSuffix, 10);
1897 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1900 const SI_CHAR * a_pSection,
1901 const SI_CHAR * a_pKey,
1903 const SI_CHAR * a_pComment,
1905 bool a_bForceReplace
1908 if (!a_pSection || !a_pKey)
return SI_FAIL;
1912 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
1913 sprintf_s(szInput, a_bUseHex ?
"0x%lx" :
"%ld", a_nValue);
1915 sprintf(szInput, a_bUseHex ?
"0x%lx" :
"%ld", a_nValue);
1919 SI_CHAR szOutput[64];
1920 SI_CONVERTER c(m_bStoreIsUtf8);
1921 c.ConvertFromStore(szInput, strlen(szInput) + 1,
1922 szOutput,
sizeof (szOutput) /
sizeof (SI_CHAR));
1925 return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace,
true);
1928 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1931 const SI_CHAR * a_pSection,
1932 const SI_CHAR * a_pKey,
1934 bool * a_pHasMultiple
1937 const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey, NULL, a_pHasMultiple);
1938 if (!pszValue || !*pszValue)
return a_nDefault;
1941 char szValue[64] = {0};
1942 SI_CONVERTER c(m_bStoreIsUtf8);
1943 if (!c.ConvertToStore(pszValue, szValue, sizeof (szValue))) {
1947 char * pszSuffix = NULL;
1948 double nValue = strtod(szValue, &pszSuffix);
1951 if (!pszSuffix || *pszSuffix) {
1958 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1961 const SI_CHAR * a_pSection,
1962 const SI_CHAR * a_pKey,
1964 const SI_CHAR * a_pComment,
1965 bool a_bForceReplace
1968 if (!a_pSection || !a_pKey)
return SI_FAIL;
1972 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
1973 sprintf_s(szInput,
"%f", a_nValue);
1975 sprintf(szInput,
"%f", a_nValue);
1979 SI_CHAR szOutput[64];
1980 SI_CONVERTER c(m_bStoreIsUtf8);
1981 c.ConvertFromStore(szInput, strlen(szInput) + 1,
1982 szOutput,
sizeof (szOutput) /
sizeof (SI_CHAR));
1985 return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace,
true);
1988 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
1991 const SI_CHAR * a_pSection,
1992 const SI_CHAR * a_pKey,
1994 bool * a_pHasMultiple
1997 const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey, NULL, a_pHasMultiple);
1998 if (!pszValue || !*pszValue)
return a_bDefault;
2001 switch (pszValue[0]) {
2013 if (pszValue[1] ==
'n' || pszValue[1] ==
'N')
return true;
2014 if (pszValue[1] ==
'f' || pszValue[1] ==
'F')
return false;
2022 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2025 const SI_CHAR * a_pSection,
2026 const SI_CHAR * a_pKey,
2028 const SI_CHAR * a_pComment,
2029 bool a_bForceReplace
2032 if (!a_pSection || !a_pKey)
return SI_FAIL;
2035 const char * pszInput = a_bValue ?
"true" :
"false";
2038 SI_CHAR szOutput[64];
2039 SI_CONVERTER c(m_bStoreIsUtf8);
2040 c.ConvertFromStore(pszInput, strlen(pszInput) + 1,
2041 szOutput,
sizeof (szOutput) /
sizeof (SI_CHAR));
2044 return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace,
true);
2047 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2050 const SI_CHAR * a_pSection,
2051 const SI_CHAR * a_pKey,
2056 if (!a_pSection || !a_pKey) {
2059 typename TSection::const_iterator iSection = m_data.find(a_pSection);
2060 if (iSection == m_data.end()) {
2063 typename TKeyVal::const_iterator iKeyVal = iSection->second.find(a_pKey);
2064 if (iKeyVal == iSection->second.end()) {
2069 a_values.push_back(
Entry(iKeyVal->second, iKeyVal->first.pComment, iKeyVal->first.nOrder));
2070 if (m_bAllowMultiKey) {
2072 while (iKeyVal != iSection->second.end() && !IsLess(a_pKey, iKeyVal->first.pItem)) {
2073 a_values.push_back(
Entry(iKeyVal->second, iKeyVal->first.pComment, iKeyVal->first.nOrder));
2081 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2084 const SI_CHAR * a_pSection
2090 typename TSection::const_iterator iSection = m_data.find(a_pSection);
2091 if (iSection == m_data.end()) {
2094 const TKeyVal & section = iSection->second;
2098 if (!m_bAllowMultiKey || section.empty()) {
2099 return (
int) section.size();
2104 const SI_CHAR * pLastKey = NULL;
2105 typename TKeyVal::const_iterator iKeyVal = section.begin();
2106 for (
int n = 0; iKeyVal != section.end(); ++iKeyVal, ++n) {
2107 if (!pLastKey || IsLess(pLastKey, iKeyVal->first.pItem)) {
2109 pLastKey = iKeyVal->first.pItem;
2115 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2118 const SI_CHAR * a_pSection
2121 typename TSection::const_iterator i = m_data.find(a_pSection);
2122 if (i != m_data.end()) {
2123 return &(i->second);
2129 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2135 typename TSection::const_iterator i = m_data.begin();
2136 for (
int n = 0; i != m_data.end(); ++i, ++n) {
2137 a_names.push_back(i->first);
2141 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2144 const SI_CHAR * a_pSection,
2153 typename TSection::const_iterator iSection = m_data.find(a_pSection);
2154 if (iSection == m_data.end()) {
2158 const TKeyVal & section = iSection->second;
2159 const SI_CHAR * pLastKey = NULL;
2160 typename TKeyVal::const_iterator iKeyVal = section.begin();
2161 for (
int n = 0; iKeyVal != section.end(); ++iKeyVal, ++n) {
2162 if (!pLastKey || IsLess(pLastKey, iKeyVal->first.pItem)) {
2163 a_names.push_back(iKeyVal->first);
2164 pLastKey = iKeyVal->first.pItem;
2172 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2175 const char * a_pszFile,
2176 bool a_bAddSignature
2179 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
2180 fopen_s(&fp, a_pszFile,
"wb");
2182 fp = fopen(a_pszFile,
"wb");
2185 SI_Error rc = SaveFile(fp, a_bAddSignature);
2190 #ifdef SI_HAS_WIDE_FILE
2192 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2195 const SI_WCHAR_T * a_pwszFile,
2196 bool a_bAddSignature
2200 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
2201 _wfopen_s(&fp, a_pwszFile, L
"wb");
2203 fp = _wfopen(a_pwszFile, L
"wb");
2206 SI_Error rc = SaveFile(fp, a_bAddSignature);
2211 u_austrncpy(szFile, a_pwszFile,
sizeof (szFile));
2212 return SaveFile(szFile, a_bAddSignature);
2217 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2221 bool a_bAddSignature
2224 return Save(writer, a_bAddSignature);
2227 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2231 bool a_bAddSignature
2236 if (m_bStoreIsUtf8 && a_bAddSignature) {
2237 a_oOutput.
Write(SI_UTF8_SIGNATURE);
2242 GetAllSections(oSections);
2243 #if defined(_MSC_VER) && _MSC_VER <= 1200
2245 #elif defined(__BORLANDC__)
2252 bool bNeedNewLine =
false;
2253 if (m_pFileComment) {
2254 if (!OutputMultiLineText(a_oOutput, convert, m_pFileComment)) {
2257 bNeedNewLine =
true;
2261 typename TNamesDepend::const_iterator iSection = oSections.begin();
2262 for (; iSection != oSections.end(); ++iSection) {
2264 if (iSection->pComment) {
2266 a_oOutput.
Write(SI_NEWLINE_A);
2267 a_oOutput.
Write(SI_NEWLINE_A);
2269 if (!OutputMultiLineText(a_oOutput, convert, iSection->pComment)) {
2272 bNeedNewLine =
false;
2276 a_oOutput.
Write(SI_NEWLINE_A);
2277 a_oOutput.
Write(SI_NEWLINE_A);
2278 bNeedNewLine =
false;
2282 if (*iSection->pItem) {
2286 a_oOutput.
Write(
"[");
2288 a_oOutput.
Write(
"]");
2289 a_oOutput.
Write(SI_NEWLINE_A);
2294 GetAllKeys(iSection->pItem, oKeys);
2295 #if defined(_MSC_VER) && _MSC_VER <= 1200
2297 #elif defined(__BORLANDC__)
2304 typename TNamesDepend::const_iterator iKey = oKeys.begin();
2305 for (; iKey != oKeys.end(); ++iKey) {
2308 GetAllValues(iSection->pItem, iKey->pItem, oValues);
2310 typename TNamesDepend::const_iterator iValue = oValues.begin();
2311 for (; iValue != oValues.end(); ++iValue) {
2313 if (iValue->pComment) {
2314 a_oOutput.
Write(SI_NEWLINE_A);
2315 if (!OutputMultiLineText(a_oOutput, convert, iValue->pComment)) {
2330 a_oOutput.
Write(m_bSpaces ?
" = " :
"=");
2331 if (m_bAllowMultiLine && IsMultiLineData(iValue->pItem)) {
2334 a_oOutput.
Write(
"<<<END_OF_TEXT" SI_NEWLINE_A);
2335 if (!OutputMultiLineText(a_oOutput, convert, iValue->pItem)) {
2338 a_oOutput.
Write(
"END_OF_TEXT");
2342 a_oOutput.
Write(SI_NEWLINE_A);
2346 bNeedNewLine =
true;
2354 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2357 OutputWriter & a_oOutput,
2358 Converter & a_oConverter,
2359 const SI_CHAR * a_pText
2361 const SI_CHAR * pEndOfLine;
2362 SI_CHAR cEndOfLineChar = *a_pText;
2363 while (cEndOfLineChar) {
2365 pEndOfLine = a_pText;
2366 for (; *pEndOfLine && *pEndOfLine !=
'\n'; ++pEndOfLine) ;
2367 cEndOfLineChar = *pEndOfLine;
2370 *
const_cast<SI_CHAR*
> (pEndOfLine) = 0;
2371 if (!a_oConverter.ConvertToStore(a_pText)) {
2374 *
const_cast<SI_CHAR*
> (pEndOfLine) = cEndOfLineChar;
2375 a_pText += (pEndOfLine - a_pText) + 1;
2376 a_oOutput.Write(a_oConverter.Data());
2377 a_oOutput.Write(SI_NEWLINE_A);
2382 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2385 const SI_CHAR * a_pSection,
2386 const SI_CHAR * a_pKey,
2389 return DeleteValue(a_pSection, a_pKey, NULL, a_bRemoveEmpty);
2392 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2395 const SI_CHAR * a_pSection,
2396 const SI_CHAR * a_pKey,
2397 const SI_CHAR * a_pValue,
2404 typename TSection::iterator iSection = m_data.find(a_pSection);
2405 if (iSection == m_data.end()) {
2411 typename TKeyVal::iterator iKeyVal = iSection->second.find(a_pKey);
2412 if (iKeyVal == iSection->second.end()) {
2416 const static SI_STRLESS isLess = SI_STRLESS();
2419 typename TKeyVal::iterator iDelete;
2420 bool bDeleted =
false;
2422 iDelete = iKeyVal++;
2424 if (a_pValue == NULL ||
2425 (isLess(a_pValue, iDelete->second) ==
false &&
2426 isLess(iDelete->second, a_pValue) ==
false)) {
2427 DeleteString(iDelete->first.pItem);
2428 DeleteString(iDelete->second);
2429 iSection->second.erase(iDelete);
2432 }
while (iKeyVal != iSection->second.end()
2433 && !IsLess(a_pKey, iKeyVal->first.pItem));
2442 if (!a_bRemoveEmpty || !iSection->second.empty()) {
2448 typename TKeyVal::iterator iKeyVal = iSection->second.begin();
2449 for (; iKeyVal != iSection->second.end(); ++iKeyVal) {
2450 DeleteString(iKeyVal->first.pItem);
2451 DeleteString(iKeyVal->second);
2456 DeleteString(iSection->first.pItem);
2457 m_data.erase(iSection);
2462 template<
class SI_CHAR,
class SI_STRLESS,
class SI_CONVERTER>
2465 const SI_CHAR * a_pString
2470 if (a_pString < m_pData || a_pString >= m_pData + m_uDataLen) {
2471 typename TNamesDepend::iterator i = m_strings.begin();
2472 for (; i != m_strings.end(); ++i) {
2473 if (a_pString == i->pItem) {
2474 delete[]
const_cast<SI_CHAR*
> (i->pItem);
2496 #if !defined(SI_CONVERT_GENERIC) && !defined(SI_CONVERT_WIN32) && !defined(SI_CONVERT_ICU)
2498 #define SI_CONVERT_WIN32
2500 #define SI_CONVERT_GENERIC
2509 template<
class SI_CHAR>
2512 bool operator()(
const SI_CHAR * pLeft,
const SI_CHAR * pRight)
const {
2514 for (; *pLeft && *pRight; ++pLeft, ++pRight) {
2515 cmp = (long) *pLeft - (
long) *pRight;
2520 return *pRight != 0;
2530 template<
class SI_CHAR>
2534 return (ch < 'A' || ch >
'Z') ? ch : (ch -
'A' +
'a');
2537 bool operator()(
const SI_CHAR * pLeft,
const SI_CHAR * pRight)
const {
2539 for (; *pLeft && *pRight; ++pLeft, ++pRight) {
2545 return *pRight != 0;
2552 template<
class SI_CHAR>
2554 bool m_bStoreIsUtf8;
2570 m_bStoreIsUtf8 = rhs.m_bStoreIsUtf8;
2588 const char * a_pInputData,
2589 size_t a_uInputDataLen) {
2590 (void) a_pInputData;
2591 SI_ASSERT(a_uInputDataLen != (
size_t) - 1);
2594 return a_uInputDataLen;
2611 const char * a_pInputData,
2612 size_t a_uInputDataLen,
2613 SI_CHAR * a_pOutputData,
2614 size_t a_uOutputDataSize) {
2616 if (a_uInputDataLen > a_uOutputDataSize) {
2619 memcpy(a_pOutputData, a_pInputData, a_uInputDataLen);
2634 const SI_CHAR * a_pInputData) {
2636 return strlen((
const char *) a_pInputData) + 1;
2653 const SI_CHAR * a_pInputData,
2654 char * a_pOutputData,
2655 size_t a_uOutputDataSize) {
2657 size_t uInputLen = strlen((
const char *) a_pInputData) + 1;
2658 if (uInputLen > a_uOutputDataSize) {
2663 memcpy(a_pOutputData, a_pInputData, uInputLen);
2672 #ifdef SI_CONVERT_GENERIC
2674 #define SI_Case SI_GenericCase
2675 #define SI_NoCase SI_GenericNoCase
2773 #define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
2774 #define UNI_MAX_BMP (UTF32)0x0000FFFF
2775 #define UNI_MAX_UTF16 (UTF32)0x0010FFFF
2776 #define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
2777 #define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
2797 const UTF8** sourceStart,
const UTF8* sourceEnd,
2801 const UTF16** sourceStart,
const UTF16* sourceEnd,
2805 const UTF8** sourceStart,
const UTF8* sourceEnd,
2809 const UTF32** sourceStart,
const UTF32* sourceEnd,
2813 const UTF16** sourceStart,
const UTF16* sourceEnd,
2817 const UTF32** sourceStart,
const UTF32* sourceEnd,
2828 static const int halfShift = 10;
2830 static const UTF32 halfBase = 0x0010000UL;
2831 static const UTF32 halfMask = 0x3FFUL;
2833 #define UNI_SUR_HIGH_START (UTF32)0xD800
2834 #define UNI_SUR_HIGH_END (UTF32)0xDBFF
2835 #define UNI_SUR_LOW_START (UTF32)0xDC00
2836 #define UNI_SUR_LOW_END (UTF32)0xDFFF
2843 const UTF32** sourceStart,
const UTF32* sourceEnd,
2846 const UTF32* source = *sourceStart;
2847 UTF16* target = *targetStart;
2848 while (source < sourceEnd) {
2850 if (target >= targetEnd) {
2855 if (ch <= UNI_MAX_BMP) {
2857 if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
2863 *target++ = UNI_REPLACEMENT_CHAR;
2866 *target++ = (
UTF16) ch;
2868 }
else if (ch > UNI_MAX_LEGAL_UTF32) {
2872 *target++ = UNI_REPLACEMENT_CHAR;
2876 if (target + 1 >= targetEnd) {
2882 *target++ = (
UTF16) ((ch >> halfShift) + UNI_SUR_HIGH_START);
2883 *target++ = (
UTF16) ((ch & halfMask) + UNI_SUR_LOW_START);
2886 *sourceStart = source;
2887 *targetStart = target;
2894 const UTF16** sourceStart,
const UTF16* sourceEnd,
2897 const UTF16* source = *sourceStart;
2898 UTF32* target = *targetStart;
2900 while (source < sourceEnd) {
2901 const UTF16* oldSource = source;
2904 if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
2906 if (source < sourceEnd) {
2909 if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
2910 ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
2911 + (ch2 - UNI_SUR_LOW_START) + halfBase;
2925 if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
2931 if (target >= targetEnd) {
2938 *sourceStart = source;
2939 *targetStart = target;
2942 fprintf(stderr,
"ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);
2958 static const char trailingBytesForUTF8[256] = {
2959 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2960 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2961 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2962 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2963 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2964 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2965 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2966 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
2974 static const UTF32 offsetsFromUTF8[6] = {0x00000000UL, 0x00003080UL, 0x000E2080UL,
2975 0x03C82080UL, 0xFA082080UL, 0x82082080UL};
2984 static const UTF8 firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
2999 const UTF16** sourceStart,
const UTF16* sourceEnd,
3002 const UTF16* source = *sourceStart;
3003 UTF8* target = *targetStart;
3004 while (source < sourceEnd) {
3006 unsigned short bytesToWrite = 0;
3007 const UTF32 byteMask = 0xBF;
3008 const UTF32 byteMark = 0x80;
3009 const UTF16* oldSource = source;
3012 if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
3014 if (source < sourceEnd) {
3015 UTF32 ch2 = *source;
3017 if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
3018 ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
3019 + (ch2 - UNI_SUR_LOW_START) + halfBase;
3033 if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
3040 if (ch < (
UTF32) 0x80) {
3042 }
else if (ch < (
UTF32) 0x800) {
3044 }
else if (ch < (
UTF32) 0x10000) {
3046 }
else if (ch < (
UTF32) 0x110000) {
3050 ch = UNI_REPLACEMENT_CHAR;
3053 target += bytesToWrite;
3054 if (target > targetEnd) {
3056 target -= bytesToWrite;
3060 switch (bytesToWrite) {
3061 case 4: *--target = (
UTF8) ((ch | byteMark) & byteMask);
3063 case 3: *--target = (
UTF8) ((ch | byteMark) & byteMask);
3065 case 2: *--target = (
UTF8) ((ch | byteMark) & byteMask);
3067 case 1: *--target = (
UTF8) (ch | firstByteMark[bytesToWrite]);
3069 target += bytesToWrite;
3071 *sourceStart = source;
3072 *targetStart = target;
3089 static bool isLegalUTF8(
const UTF8 *source,
int length) {
3091 const UTF8 *srcptr = source + length;
3093 default:
return false;
3095 case 4:
if ((a = (*--srcptr)) < 0x80 || a > 0xBF)
return false;
3096 case 3:
if ((a = (*--srcptr)) < 0x80 || a > 0xBF)
return false;
3097 case 2:
if ((a = (*--srcptr)) > 0xBF)
return false;
3101 case 0xE0:
if (a < 0xA0)
return false;
3103 case 0xED:
if (a > 0x9F)
return false;
3105 case 0xF0:
if (a < 0x90)
return false;
3107 case 0xF4:
if (a > 0x8F)
return false;
3109 default:
if (a < 0x80)
return false;
3112 case 1:
if (*source >= 0x80 && *source < 0xC2)
return false;
3114 if (*source > 0xF4)
return false;
3125 int length = trailingBytesForUTF8[*source] + 1;
3126 if (source + length > sourceEnd) {
3129 return isLegalUTF8(source, length);
3135 const UTF8** sourceStart,
const UTF8* sourceEnd,
3138 const UTF8* source = *sourceStart;
3139 UTF16* target = *targetStart;
3140 while (source < sourceEnd) {
3142 unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
3143 if (source + extraBytesToRead >= sourceEnd) {
3148 if (!isLegalUTF8(source, extraBytesToRead + 1)) {
3155 switch (extraBytesToRead) {
3156 case 5: ch += *source++;
3158 case 4: ch += *source++;
3160 case 3: ch += *source++;
3162 case 2: ch += *source++;
3164 case 1: ch += *source++;
3166 case 0: ch += *source++;
3168 ch -= offsetsFromUTF8[extraBytesToRead];
3170 if (target >= targetEnd) {
3171 source -= (extraBytesToRead + 1);
3175 if (ch <= UNI_MAX_BMP) {
3177 if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
3179 source -= (extraBytesToRead + 1);
3183 *target++ = UNI_REPLACEMENT_CHAR;
3186 *target++ = (
UTF16) ch;
3188 }
else if (ch > UNI_MAX_UTF16) {
3191 source -= (extraBytesToRead + 1);
3194 *target++ = UNI_REPLACEMENT_CHAR;
3198 if (target + 1 >= targetEnd) {
3199 source -= (extraBytesToRead + 1);
3204 *target++ = (
UTF16) ((ch >> halfShift) + UNI_SUR_HIGH_START);
3205 *target++ = (
UTF16) ((ch & halfMask) + UNI_SUR_LOW_START);
3208 *sourceStart = source;
3209 *targetStart = target;
3216 const UTF32** sourceStart,
const UTF32* sourceEnd,
3219 const UTF32* source = *sourceStart;
3220 UTF8* target = *targetStart;
3221 while (source < sourceEnd) {
3223 unsigned short bytesToWrite = 0;
3224 const UTF32 byteMask = 0xBF;
3225 const UTF32 byteMark = 0x80;
3229 if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
3239 if (ch < (
UTF32) 0x80) {
3241 }
else if (ch < (
UTF32) 0x800) {
3243 }
else if (ch < (
UTF32) 0x10000) {
3245 }
else if (ch <= UNI_MAX_LEGAL_UTF32) {
3249 ch = UNI_REPLACEMENT_CHAR;
3253 target += bytesToWrite;
3254 if (target > targetEnd) {
3256 target -= bytesToWrite;
3260 switch (bytesToWrite) {
3261 case 4: *--target = (
UTF8) ((ch | byteMark) & byteMask);
3263 case 3: *--target = (
UTF8) ((ch | byteMark) & byteMask);
3265 case 2: *--target = (
UTF8) ((ch | byteMark) & byteMask);
3267 case 1: *--target = (
UTF8) (ch | firstByteMark[bytesToWrite]);
3269 target += bytesToWrite;
3271 *sourceStart = source;
3272 *targetStart = target;
3279 const UTF8** sourceStart,
const UTF8* sourceEnd,
3282 const UTF8* source = *sourceStart;
3283 UTF32* target = *targetStart;
3284 while (source < sourceEnd) {
3286 unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
3287 if (source + extraBytesToRead >= sourceEnd) {
3292 if (!isLegalUTF8(source, extraBytesToRead + 1)) {
3299 switch (extraBytesToRead) {
3300 case 5: ch += *source++;
3302 case 4: ch += *source++;
3304 case 3: ch += *source++;
3306 case 2: ch += *source++;
3308 case 1: ch += *source++;
3310 case 0: ch += *source++;
3312 ch -= offsetsFromUTF8[extraBytesToRead];
3314 if (target >= targetEnd) {
3315 source -= (extraBytesToRead + 1);
3319 if (ch <= UNI_MAX_LEGAL_UTF32) {
3324 if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
3326 source -= (extraBytesToRead + 1);
3330 *target++ = UNI_REPLACEMENT_CHAR;
3337 *target++ = UNI_REPLACEMENT_CHAR;
3340 *sourceStart = source;
3341 *targetStart = target;
3374 template<
class SI_CHAR>
3376 bool m_bStoreIsUtf8;
3392 m_bStoreIsUtf8 = rhs.m_bStoreIsUtf8;
3410 const char * a_pInputData,
3411 size_t a_uInputDataLen) {
3412 SI_ASSERT(a_uInputDataLen != (
size_t) - 1);
3414 if (m_bStoreIsUtf8) {
3418 return a_uInputDataLen;
3421 #if defined(SI_NO_MBSTOWCS_NULL) || (!defined(_MSC_VER) && !defined(_linux))
3424 (void) a_pInputData;
3425 return a_uInputDataLen;
3428 return mbstowcs(NULL, a_pInputData, a_uInputDataLen);
3446 const char * a_pInputData,
3447 size_t a_uInputDataLen,
3448 SI_CHAR * a_pOutputData,
3449 size_t a_uOutputDataSize) {
3450 if (m_bStoreIsUtf8) {
3457 const UTF8 * pUtf8 = (
const UTF8 *) a_pInputData;
3458 if (
sizeof (
wchar_t) ==
sizeof (
UTF32)) {
3461 &pUtf8, pUtf8 + a_uInputDataLen,
3462 &pUtf32, pUtf32 + a_uOutputDataSize,
3464 }
else if (
sizeof (
wchar_t) ==
sizeof (
UTF16)) {
3467 &pUtf8, pUtf8 + a_uInputDataLen,
3468 &pUtf16, pUtf16 + a_uOutputDataSize,
3475 size_t retval = mbstowcs(a_pOutputData,
3476 a_pInputData, a_uOutputDataSize);
3477 return retval != (size_t) (-1);
3491 const SI_CHAR * a_pInputData) {
3492 if (m_bStoreIsUtf8) {
3495 while (a_pInputData[uLen]) {
3498 return (6 * uLen) + 1;
3500 size_t uLen = wcstombs(NULL, a_pInputData, 0);
3501 if (uLen == (
size_t) (-1)) {
3522 const SI_CHAR * a_pInputData,
3523 char * a_pOutputData,
3524 size_t a_uOutputDataSize
3526 if (m_bStoreIsUtf8) {
3528 size_t uInputLen = 0;
3529 while (a_pInputData[uInputLen]) {
3540 UTF8 * pUtf8 = (
UTF8 *) a_pOutputData;
3541 if (
sizeof (
wchar_t) ==
sizeof (
UTF32)) {
3542 const UTF32 * pUtf32 = (
const UTF32 *) a_pInputData;
3544 &pUtf32, pUtf32 + uInputLen,
3545 &pUtf8, pUtf8 + a_uOutputDataSize,
3547 }
else if (
sizeof (
wchar_t) ==
sizeof (
UTF16)) {
3548 const UTF16 * pUtf16 = (
const UTF16 *) a_pInputData;
3550 &pUtf16, pUtf16 + uInputLen,
3551 &pUtf8, pUtf8 + a_uOutputDataSize,
3556 size_t retval = wcstombs(a_pOutputData,
3557 a_pInputData, a_uOutputDataSize);
3558 return retval != (size_t) - 1;
3569 #ifdef SI_CONVERT_ICU
3571 #define SI_Case SI_GenericCase
3572 #define SI_NoCase SI_GenericNoCase
3574 #include <unicode/ucnv.h>
3579 template<
class SI_CHAR>
3581 const char * m_pEncoding;
3582 UConverter * m_pConverter;
3590 m_pEncoding = a_bStoreIsUtf8 ?
"UTF-8" : NULL;
3599 m_pEncoding = rhs.m_pEncoding;
3600 m_pConverter = NULL;
3605 if (m_pConverter) ucnv_close(m_pConverter);
3622 const char * a_pInputData,
3623 size_t a_uInputDataLen) {
3624 SI_ASSERT(a_uInputDataLen != (
size_t) - 1);
3628 if (!m_pConverter) {
3629 nError = U_ZERO_ERROR;
3630 m_pConverter = ucnv_open(m_pEncoding, &nError);
3631 if (U_FAILURE(nError)) {
3632 return (
size_t) - 1;
3636 nError = U_ZERO_ERROR;
3637 int32_t nLen = ucnv_toUChars(m_pConverter, NULL, 0,
3638 a_pInputData, (int32_t) a_uInputDataLen, &nError);
3639 if (U_FAILURE(nError) && nError != U_BUFFER_OVERFLOW_ERROR) {
3640 return (
size_t) - 1;
3643 return (
size_t) nLen;
3660 const char * a_pInputData,
3661 size_t a_uInputDataLen,
3662 UChar * a_pOutputData,
3663 size_t a_uOutputDataSize) {
3666 if (!m_pConverter) {
3667 nError = U_ZERO_ERROR;
3668 m_pConverter = ucnv_open(m_pEncoding, &nError);
3669 if (U_FAILURE(nError)) {
3674 nError = U_ZERO_ERROR;
3675 ucnv_toUChars(m_pConverter,
3676 a_pOutputData, (int32_t) a_uOutputDataSize,
3677 a_pInputData, (int32_t) a_uInputDataLen, &nError);
3678 if (U_FAILURE(nError)) {
3696 const UChar * a_pInputData) {
3699 if (!m_pConverter) {
3700 nError = U_ZERO_ERROR;
3701 m_pConverter = ucnv_open(m_pEncoding, &nError);
3702 if (U_FAILURE(nError)) {
3703 return (
size_t) - 1;
3707 nError = U_ZERO_ERROR;
3708 int32_t nLen = ucnv_fromUChars(m_pConverter, NULL, 0,
3709 a_pInputData, -1, &nError);
3710 if (U_FAILURE(nError) && nError != U_BUFFER_OVERFLOW_ERROR) {
3711 return (
size_t) - 1;
3714 return (
size_t) nLen + 1;
3731 const UChar * a_pInputData,
3732 char * a_pOutputData,
3733 size_t a_uOutputDataSize) {
3736 if (!m_pConverter) {
3737 nError = U_ZERO_ERROR;
3738 m_pConverter = ucnv_open(m_pEncoding, &nError);
3739 if (U_FAILURE(nError)) {
3744 nError = U_ZERO_ERROR;
3745 ucnv_fromUChars(m_pConverter,
3746 a_pOutputData, (int32_t) a_uOutputDataSize,
3747 a_pInputData, -1, &nError);
3748 if (U_FAILURE(nError)) {
3762 #ifdef SI_CONVERT_WIN32
3764 #define SI_Case SI_GenericCase
3773 #include <windows.h>
3775 #define SI_NoCase SI_GenericNoCase
3785 #include <mbstring.h>
3787 template<
class SI_CHAR>
3790 bool operator()(
const SI_CHAR * pLeft,
const SI_CHAR * pRight)
const {
3791 if (
sizeof (SI_CHAR) ==
sizeof (
char)) {
3792 return _mbsicmp((
const unsigned char *) pLeft,
3793 (
const unsigned char *) pRight) < 0;
3795 if (
sizeof (SI_CHAR) ==
sizeof (
wchar_t)) {
3796 return _wcsicmp((
const wchar_t *)pLeft,
3797 (
const wchar_t *)pRight) < 0;
3810 template<
class SI_CHAR>
3820 m_uCodePage = a_bStoreIsUtf8 ? CP_UTF8 : CP_ACP;
3829 m_uCodePage = rhs.m_uCodePage;
3847 const char * a_pInputData,
3848 size_t a_uInputDataLen) {
3849 SI_ASSERT(a_uInputDataLen != (
size_t) - 1);
3851 int retval = MultiByteToWideChar(
3853 a_pInputData, (
int) a_uInputDataLen,
3855 return (
size_t) (retval > 0 ? retval : -1);
3872 const char * a_pInputData,
3873 size_t a_uInputDataLen,
3874 SI_CHAR * a_pOutputData,
3875 size_t a_uOutputDataSize) {
3876 int nSize = MultiByteToWideChar(
3878 a_pInputData, (
int) a_uInputDataLen,
3879 (
wchar_t *) a_pOutputData, (
int) a_uOutputDataSize);
3894 const SI_CHAR * a_pInputData) {
3895 int retval = WideCharToMultiByte(
3897 (
const wchar_t *) a_pInputData, -1,
3899 return (
size_t) (retval > 0 ? retval : -1);
3916 const SI_CHAR * a_pInputData,
3917 char * a_pOutputData,
3918 size_t a_uOutputDataSize) {
3919 int retval = WideCharToMultiByte(
3921 (
const wchar_t *) a_pInputData, -1,
3922 a_pOutputData, (
int) a_uOutputDataSize, 0, 0);
3934 typedef CSimpleIniTempl<char,
3939 #if defined(SI_CONVERT_ICU)
3952 #define CSimpleIni CSimpleIniW
3953 #define CSimpleIniCase CSimpleIniCaseW
3954 #define SI_NEWLINE SI_NEWLINE_W
3956 #define CSimpleIni CSimpleIniA
3957 #define CSimpleIniCase CSimpleIniCaseA
3958 #define SI_NEWLINE SI_NEWLINE_A
3962 #pragma warning (pop)
3988 inline std::vector<std::string> &
split(
const std::string &s,
char delim, std::vector<std::string> &elems) {
3989 std::stringstream ss(s);
3991 while (getline(ss, item, delim)) {
3992 elems.push_back(item);
3997 inline std::vector<std::string>
split(
const std::string &s,
char delim) {
3998 std::vector<std::string> elems;
3999 split(s, delim, elems);
4007 filename_ = filename;
4010 is_opened_ = !(rc < 0);
4017 float getValue(std::string key,
float default_value = -1) {
4019 std::vector<std::string> elems;
4020 split(key,
':', elems);
4022 return atof(ini_.
GetValue(elems.front().c_str(), elems.back().c_str(), std::to_string(default_value).c_str()));
4029 std::vector<std::string> elems;
4030 split(key,
':', elems);
4032 ini_.
SetValue(elems.front().c_str(), elems.back().c_str(), std::to_string(value).c_str());
4041 std::string filename_;
4049 std::ifstream f(path.c_str());
4053 static inline std::string getRootHiddenDir() {
4057 wchar_t szPath[MAX_PATH];
4059 TCHAR szPath[MAX_PATH];
4062 if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath)))
4065 char snfile_path[MAX_PATH];
4069 size_t newsize = strlen(szPath) + 1;
4070 wchar_t * wcstring =
new wchar_t[newsize];
4072 size_t convertedChars = 0;
4073 mbstowcs_s(&convertedChars, wcstring, newsize, szPath, _TRUNCATE);
4074 wcstombs(snfile_path, wcstring, MAX_PATH);
4076 wcstombs(snfile_path, szPath, MAX_PATH);
4079 std::string filename(snfile_path);
4080 filename +=
"\\Stereolabs\\";
4083 std::string homepath = getenv(
"HOME");
4084 std::string filename = homepath +
"/zed/";
4091 static inline std::string getHiddenDir() {
4092 std::string filename = getRootHiddenDir();
4094 filename +=
"settings\\";
4096 filename +=
"settings/";
4103 std::string path = getHiddenDir();
4104 char specific_name[128];
4105 sprintf(specific_name,
"SN%d.conf", serial_number);
4106 calibration_file = path + specific_name;
4112 cmd =
"mkdir -p " + path;
4113 res = system(cmd.c_str());
4116 std::string url(
"'https://calib.stereolabs.com/?SN=");
4118 cmd =
"wget " + url + std::to_string(serial_number) +
"' -O " + calibration_file;
4119 std::cout << cmd << std::endl;
4120 res = system(cmd.c_str());
4122 if( res == EXIT_FAILURE )
4124 std::cerr <<
"Error downloading the calibration file" << std::endl;
4129 std::cerr <<
"Invalid calibration file" << std::endl;
4134 std::string path = getHiddenDir();
4135 char specific_name[128];
4136 sprintf(specific_name,
"SN%d.conf", serial_number);
4137 calibration_file = path + specific_name;
4139 TCHAR *settingFolder =
new TCHAR[path.size() + 1];
4140 settingFolder[path.size()] = 0;
4141 std::copy(path.begin(), path.end(), settingFolder);
4142 SHCreateDirectoryEx(NULL, settingFolder, NULL);
4144 std::string url(
"https://calib.stereolabs.com/?SN=");
4145 url += std::to_string(serial_number);
4146 TCHAR *address =
new TCHAR[url.size() + 1];
4147 address[url.size()] = 0;
4148 std::copy(url.begin(), url.end(), address);
4149 TCHAR *calibPath =
new TCHAR[calibration_file.size() + 1];
4150 calibPath[calibration_file.size()] = 0;
4151 std::copy(calibration_file.begin(), calibration_file.end(), calibPath);
4153 HRESULT hr = URLDownloadToFile(NULL, address, calibPath, 0, NULL);
4155 std::cout <<
"Fail to download calibration file" << std::endl;
4160 std::cout <<
"Invalid calibration file" << std::endl;
4170 #include <opencv2/opencv.hpp>
4172 bool initCalibration(std::string calibration_file, cv::Size2i image_size, cv::Mat &map_left_x, cv::Mat &map_left_y,
4173 cv::Mat &map_right_x, cv::Mat &map_right_y, cv::Mat &cameraMatrix_left, cv::Mat &cameraMatrix_right,
double *baseline=
nullptr) {
4176 std::cout <<
"Calibration file missing." << std::endl;
4181 ConfManager camerareader(calibration_file.c_str());
4185 std::string resolution_str;
4186 switch ((
int) image_size.width) {
4188 resolution_str =
"2k";
4191 resolution_str =
"fhd";
4194 resolution_str =
"hd";
4197 resolution_str =
"vga";
4200 resolution_str =
"hd";
4206 T_[0] = camerareader.
getValue(
"stereo:baseline", 0.0f);
4207 T_[1] = camerareader.
getValue(
"stereo:ty_" + resolution_str, 0.f);
4208 T_[2] = camerareader.
getValue(
"stereo:tz_" + resolution_str, 0.f);
4210 if(baseline) *baseline=T_[0];
4213 float left_cam_cx = camerareader.
getValue(
"left_cam_" + resolution_str +
":cx", 0.0f);
4214 float left_cam_cy = camerareader.
getValue(
"left_cam_" + resolution_str +
":cy", 0.0f);
4215 float left_cam_fx = camerareader.
getValue(
"left_cam_" + resolution_str +
":fx", 0.0f);
4216 float left_cam_fy = camerareader.
getValue(
"left_cam_" + resolution_str +
":fy", 0.0f);
4217 float left_cam_k1 = camerareader.
getValue(
"left_cam_" + resolution_str +
":k1", 0.0f);
4218 float left_cam_k2 = camerareader.
getValue(
"left_cam_" + resolution_str +
":k2", 0.0f);
4219 float left_cam_p1 = camerareader.
getValue(
"left_cam_" + resolution_str +
":p1", 0.0f);
4220 float left_cam_p2 = camerareader.
getValue(
"left_cam_" + resolution_str +
":p2", 0.0f);
4221 float left_cam_k3 = camerareader.
getValue(
"left_cam_" + resolution_str +
":k3", 0.0f);
4224 float right_cam_cx = camerareader.
getValue(
"right_cam_" + resolution_str +
":cx", 0.0f);
4225 float right_cam_cy = camerareader.
getValue(
"right_cam_" + resolution_str +
":cy", 0.0f);
4226 float right_cam_fx = camerareader.
getValue(
"right_cam_" + resolution_str +
":fx", 0.0f);
4227 float right_cam_fy = camerareader.
getValue(
"right_cam_" + resolution_str +
":fy", 0.0f);
4228 float right_cam_k1 = camerareader.
getValue(
"right_cam_" + resolution_str +
":k1", 0.0f);
4229 float right_cam_k2 = camerareader.
getValue(
"right_cam_" + resolution_str +
":k2", 0.0f);
4230 float right_cam_p1 = camerareader.
getValue(
"right_cam_" + resolution_str +
":p1", 0.0f);
4231 float right_cam_p2 = camerareader.
getValue(
"right_cam_" + resolution_str +
":p2", 0.0f);
4232 float right_cam_k3 = camerareader.
getValue(
"right_cam_" + resolution_str +
":k3", 0.0f);
4236 if (right_cam_k1 == 0 && left_cam_k1 == 0 && left_cam_k2 == 0 && right_cam_k2 == 0) {
4237 std::cout <<
"ZED File invalid" << std::endl;
4239 std::string cmd =
"rm " + calibration_file;
4240 int res = system(cmd.c_str());
4241 if( res == EXIT_FAILURE )
4251 cv::Mat R_zed = (cv::Mat_<double>(1, 3) << camerareader.
getValue(
"stereo:rx_" + resolution_str, 0.f), camerareader.
getValue(
"stereo:cv_" + resolution_str, 0.f), camerareader.
getValue(
"stereo:rz_" + resolution_str, 0.f));
4254 cv::Rodrigues(R_zed , R );
4256 cv::Mat distCoeffs_left, distCoeffs_right;
4259 cameraMatrix_left = (cv::Mat_<double>(3, 3) << left_cam_fx, 0, left_cam_cx, 0, left_cam_fy, left_cam_cy, 0, 0, 1);
4260 distCoeffs_left = (cv::Mat_<double>(5, 1) << left_cam_k1, left_cam_k2, left_cam_p1, left_cam_p2, left_cam_k3);
4263 cameraMatrix_right = (cv::Mat_<double>(3, 3) << right_cam_fx, 0, right_cam_cx, 0, right_cam_fy, right_cam_cy, 0, 0, 1);
4264 distCoeffs_right = (cv::Mat_<double>(5, 1) << right_cam_k1, right_cam_k2, right_cam_p1, right_cam_p2, right_cam_k3);
4267 cv::Mat T = (cv::Mat_<double>(3, 1) << T_[0], T_[1], T_[2]);
4268 std::cout <<
" Camera Matrix L: \n" << cameraMatrix_left << std::endl << std::endl;
4269 std::cout <<
" Camera Matrix R: \n" << cameraMatrix_right << std::endl << std::endl;
4271 cv::Mat R1, R2, P1, P2, Q;
4272 cv::stereoRectify(cameraMatrix_left, distCoeffs_left, cameraMatrix_right, distCoeffs_right, image_size, R, T,
4273 R1, R2, P1, P2, Q, cv::CALIB_ZERO_DISPARITY, 0, image_size);
4276 initUndistortRectifyMap(cameraMatrix_left, distCoeffs_left, R1, P1, image_size, CV_32FC1, map_left_x, map_left_y);
4277 initUndistortRectifyMap(cameraMatrix_right, distCoeffs_right, R2, P2, image_size, CV_32FC1, map_right_x, map_right_y);
4279 cameraMatrix_left = P1;
4280 cameraMatrix_right = P2;
bool operator()(const Entry &lhs, const Entry &rhs) const
bool operator()(const Entry &lhs, const Entry &rhs) const
Entry(const SI_CHAR *a_pszItem, const SI_CHAR *a_pszComment, int a_nOrder)
bool operator>(const Entry &rhs) const
Entry(const SI_CHAR *a_pszItem=NULL, int a_nOrder=0)
bool operator<(const Entry &rhs) const
Entry & operator=(const Entry &rhs)