00001
00194 #ifndef INCLUDED_SimpleIni_h
00195 #define INCLUDED_SimpleIni_h
00196
00197 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
00198 # pragma once
00199 #endif
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 #ifdef _MSC_VER
00211 # pragma warning (push)
00212 # pragma warning (disable: 4127 4503 4702 4786)
00213 #endif
00214
00215 #include <cstring>
00216 #include <string>
00217 #include <map>
00218 #include <list>
00219 #include <algorithm>
00220 #include <stdio.h>
00221
00222 #ifdef SI_SUPPORT_IOSTREAMS
00223 # include <iostream>
00224 #endif // SI_SUPPORT_IOSTREAMS
00225
00226 #ifdef _DEBUG
00227 # ifndef assert
00228 # include <cassert>
00229 # endif
00230 # define SI_ASSERT(x) assert(x)
00231 #else
00232 # define SI_ASSERT(x)
00233 #endif
00234
00235 enum SI_Error {
00236 SI_OK = 0,
00237 SI_UPDATED = 1,
00238 SI_INSERTED = 2,
00239
00240
00241 SI_FAIL = -1,
00242 SI_NOMEM = -2,
00243 SI_FILE = -3
00244 };
00245
00246 #define SI_UTF8_SIGNATURE "\xEF\xBB\xBF"
00247
00248 #ifdef _WIN32
00249 # define SI_NEWLINE_A "\r\n"
00250 # define SI_NEWLINE_W L"\r\n"
00251 #else // !_WIN32
00252 # define SI_NEWLINE_A "\n"
00253 # define SI_NEWLINE_W L"\n"
00254 #endif // _WIN32
00255
00256 #if defined(SI_CONVERT_ICU)
00257 # include <unicode/ustring.h>
00258 #endif
00259
00260 #if defined(_WIN32)
00261 # define SI_HAS_WIDE_FILE
00262 # define SI_WCHAR_T wchar_t
00263 #elif defined(SI_CONVERT_ICU)
00264 # define SI_HAS_WIDE_FILE
00265 # define SI_WCHAR_T UChar
00266 #endif
00267
00268
00269
00270
00271
00272
00292 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
00293 class CSimpleIniTempl
00294 {
00295 public:
00297 struct Entry {
00298 const SI_CHAR * pItem;
00299 const SI_CHAR * pComment;
00300 int nOrder;
00301
00302 Entry(const SI_CHAR * a_pszItem = NULL, int a_nOrder = 0)
00303 : pItem(a_pszItem)
00304 , pComment(NULL)
00305 , nOrder(a_nOrder)
00306 { }
00307 Entry(const SI_CHAR * a_pszItem, const SI_CHAR * a_pszComment, int a_nOrder)
00308 : pItem(a_pszItem)
00309 , pComment(a_pszComment)
00310 , nOrder(a_nOrder)
00311 { }
00312 Entry(const Entry & rhs) { operator=(rhs); }
00313 Entry & operator=(const Entry & rhs) {
00314 pItem = rhs.pItem;
00315 pComment = rhs.pComment;
00316 nOrder = rhs.nOrder;
00317 return *this;
00318 }
00319
00320 #if defined(_MSC_VER) && _MSC_VER <= 1200
00321
00322 bool operator<(const Entry & rhs) const { return LoadOrder()(*this, rhs); }
00323 bool operator>(const Entry & rhs) const { return LoadOrder()(rhs, *this); }
00324 #endif
00325
00327 struct KeyOrder : std::binary_function<Entry, Entry, bool> {
00328 bool operator()(const Entry & lhs, const Entry & rhs) const {
00329 const static SI_STRLESS isLess = SI_STRLESS();
00330 return isLess(lhs.pItem, rhs.pItem);
00331 }
00332 };
00333
00335 struct LoadOrder : std::binary_function<Entry, Entry, bool> {
00336 bool operator()(const Entry & lhs, const Entry & rhs) const {
00337 if (lhs.nOrder != rhs.nOrder) {
00338 return lhs.nOrder < rhs.nOrder;
00339 }
00340 return KeyOrder()(lhs.pItem, rhs.pItem);
00341 }
00342 };
00343 };
00344
00346 typedef std::multimap<Entry,const SI_CHAR *,typename Entry::KeyOrder> TKeyVal;
00347
00349 typedef std::map<Entry,TKeyVal,typename Entry::KeyOrder> TSection;
00350
00354 typedef std::list<Entry> TNamesDepend;
00355
00359 class OutputWriter {
00360 public:
00361 OutputWriter() { }
00362 virtual ~OutputWriter() { }
00363 virtual void Write(const char * a_pBuf) = 0;
00364 private:
00365 OutputWriter(const OutputWriter &);
00366 OutputWriter & operator=(const OutputWriter &);
00367 };
00368
00370 class FileWriter : public OutputWriter {
00371 FILE * m_file;
00372 public:
00373 FileWriter(FILE * a_file) : m_file(a_file) { }
00374 void Write(const char * a_pBuf) {
00375 fputs(a_pBuf, m_file);
00376 }
00377 private:
00378 FileWriter(const FileWriter &);
00379 FileWriter & operator=(const FileWriter &);
00380 };
00381
00383 class StringWriter : public OutputWriter {
00384 std::string & m_string;
00385 public:
00386 StringWriter(std::string & a_string) : m_string(a_string) { }
00387 void Write(const char * a_pBuf) {
00388 m_string.append(a_pBuf);
00389 }
00390 private:
00391 StringWriter(const StringWriter &);
00392 StringWriter & operator=(const StringWriter &);
00393 };
00394
00395 #ifdef SI_SUPPORT_IOSTREAMS
00396
00397 class StreamWriter : public OutputWriter {
00398 std::ostream & m_ostream;
00399 public:
00400 StreamWriter(std::ostream & a_ostream) : m_ostream(a_ostream) { }
00401 void Write(const char * a_pBuf) {
00402 m_ostream << a_pBuf;
00403 }
00404 private:
00405 StreamWriter(const StreamWriter &);
00406 StreamWriter & operator=(const StreamWriter &);
00407 };
00408 #endif // SI_SUPPORT_IOSTREAMS
00409
00413 class Converter : private SI_CONVERTER {
00414 public:
00415 Converter(bool a_bStoreIsUtf8) : SI_CONVERTER(a_bStoreIsUtf8) {
00416 m_scratch.resize(1024);
00417 }
00418 Converter(const Converter & rhs) { operator=(rhs); }
00419 Converter & operator=(const Converter & rhs) {
00420 m_scratch = rhs.m_scratch;
00421 return *this;
00422 }
00423 bool ConvertToStore(const SI_CHAR * a_pszString) {
00424 size_t uLen = SI_CONVERTER::SizeToStore(a_pszString);
00425 if (uLen == (size_t)(-1)) {
00426 return false;
00427 }
00428 while (uLen > m_scratch.size()) {
00429 m_scratch.resize(m_scratch.size() * 2);
00430 }
00431 return SI_CONVERTER::ConvertToStore(
00432 a_pszString,
00433 const_cast<char*>(m_scratch.data()),
00434 m_scratch.size());
00435 }
00436 const char * Data() { return m_scratch.data(); }
00437 private:
00438 std::string m_scratch;
00439 };
00440
00441 public:
00442
00443
00450 CSimpleIniTempl(
00451 bool a_bIsUtf8 = false,
00452 bool a_bMultiKey = false,
00453 bool a_bMultiLine = false
00454 );
00455
00457 ~CSimpleIniTempl();
00458
00460 void Reset();
00461
00463 bool IsEmpty() const { return m_data.empty(); }
00464
00465
00482 void SetUnicode(bool a_bIsUtf8 = true) {
00483 if (!m_pData) m_bStoreIsUtf8 = a_bIsUtf8;
00484 }
00485
00487 bool IsUnicode() const { return m_bStoreIsUtf8; }
00488
00507 void SetMultiKey(bool a_bAllowMultiKey = true) {
00508 m_bAllowMultiKey = a_bAllowMultiKey;
00509 }
00510
00512 bool IsMultiKey() const { return m_bAllowMultiKey; }
00513
00521 void SetMultiLine(bool a_bAllowMultiLine = true) {
00522 m_bAllowMultiLine = a_bAllowMultiLine;
00523 }
00524
00526 bool IsMultiLine() const { return m_bAllowMultiLine; }
00527
00534 void SetSpaces(bool a_bSpaces = true) {
00535 m_bSpaces = a_bSpaces;
00536 }
00537
00539 bool UsingSpaces() const { return m_bSpaces; }
00540
00541
00553 SI_Error LoadFile(
00554 const char * a_pszFile
00555 );
00556
00557 #ifdef SI_HAS_WIDE_FILE
00558
00564 SI_Error LoadFile(
00565 const SI_WCHAR_T * a_pwszFile
00566 );
00567 #endif // SI_HAS_WIDE_FILE
00568
00576 SI_Error LoadFile(
00577 FILE * a_fpFile
00578 );
00579
00580 #ifdef SI_SUPPORT_IOSTREAMS
00581
00587 SI_Error LoadData(
00588 std::istream & a_istream
00589 );
00590 #endif // SI_SUPPORT_IOSTREAMS
00591
00598 SI_Error LoadData(const std::string & a_strData) {
00599 return LoadData(a_strData.c_str(), a_strData.size());
00600 }
00601
00609 SI_Error LoadData(
00610 const char * a_pData,
00611 size_t a_uDataLen
00612 );
00613
00614
00630 SI_Error SaveFile(
00631 const char * a_pszFile,
00632 bool a_bAddSignature = true
00633 ) const;
00634
00635 #ifdef SI_HAS_WIDE_FILE
00636
00646 SI_Error SaveFile(
00647 const SI_WCHAR_T * a_pwszFile,
00648 bool a_bAddSignature = true
00649 ) const;
00650 #endif // _WIN32
00651
00664 SI_Error SaveFile(
00665 FILE * a_pFile,
00666 bool a_bAddSignature = false
00667 ) const;
00668
00700 SI_Error Save(
00701 OutputWriter & a_oOutput,
00702 bool a_bAddSignature = false
00703 ) const;
00704
00705 #ifdef SI_SUPPORT_IOSTREAMS
00706
00717 SI_Error Save(
00718 std::ostream & a_ostream,
00719 bool a_bAddSignature = false
00720 ) const
00721 {
00722 StreamWriter writer(a_ostream);
00723 return Save(writer, a_bAddSignature);
00724 }
00725 #endif // SI_SUPPORT_IOSTREAMS
00726
00738 SI_Error Save(
00739 std::string & a_sBuffer,
00740 bool a_bAddSignature = false
00741 ) const
00742 {
00743 StringWriter writer(a_sBuffer);
00744 return Save(writer, a_bAddSignature);
00745 }
00746
00747
00765 void GetAllSections(
00766 TNamesDepend & a_names
00767 ) const;
00768
00786 bool GetAllKeys(
00787 const SI_CHAR * a_pSection,
00788 TNamesDepend & a_names
00789 ) const;
00790
00807 bool GetAllValues(
00808 const SI_CHAR * a_pSection,
00809 const SI_CHAR * a_pKey,
00810 TNamesDepend & a_values
00811 ) const;
00812
00822 int GetSectionSize(
00823 const SI_CHAR * a_pSection
00824 ) const;
00825
00840 const TKeyVal * GetSection(
00841 const SI_CHAR * a_pSection
00842 ) const;
00843
00861 const SI_CHAR * GetValue(
00862 const SI_CHAR * a_pSection,
00863 const SI_CHAR * a_pKey,
00864 const SI_CHAR * a_pDefault = NULL,
00865 bool * a_pHasMultiple = NULL
00866 ) const;
00867
00881 long GetLongValue(
00882 const SI_CHAR * a_pSection,
00883 const SI_CHAR * a_pKey,
00884 long a_nDefault = 0,
00885 bool * a_pHasMultiple = NULL
00886 ) const;
00887
00901 double GetDoubleValue(
00902 const SI_CHAR * a_pSection,
00903 const SI_CHAR * a_pKey,
00904 double a_nDefault = 0,
00905 bool * a_pHasMultiple = NULL
00906 ) const;
00907
00926 bool GetBoolValue(
00927 const SI_CHAR * a_pSection,
00928 const SI_CHAR * a_pKey,
00929 bool a_bDefault = false,
00930 bool * a_pHasMultiple = NULL
00931 ) const;
00932
00962 SI_Error SetValue(
00963 const SI_CHAR * a_pSection,
00964 const SI_CHAR * a_pKey,
00965 const SI_CHAR * a_pValue,
00966 const SI_CHAR * a_pComment = NULL,
00967 bool a_bForceReplace = false
00968 )
00969 {
00970 return AddEntry(a_pSection, a_pKey, a_pValue, a_pComment, a_bForceReplace, true);
00971 }
00972
00996 SI_Error SetLongValue(
00997 const SI_CHAR * a_pSection,
00998 const SI_CHAR * a_pKey,
00999 long a_nValue,
01000 const SI_CHAR * a_pComment = NULL,
01001 bool a_bUseHex = false,
01002 bool a_bForceReplace = false
01003 );
01004
01025 SI_Error SetDoubleValue(
01026 const SI_CHAR * a_pSection,
01027 const SI_CHAR * a_pKey,
01028 double a_nValue,
01029 const SI_CHAR * a_pComment = NULL,
01030 bool a_bForceReplace = false
01031 );
01032
01053 SI_Error SetBoolValue(
01054 const SI_CHAR * a_pSection,
01055 const SI_CHAR * a_pKey,
01056 bool a_bValue,
01057 const SI_CHAR * a_pComment = NULL,
01058 bool a_bForceReplace = false
01059 );
01060
01079 bool Delete(
01080 const SI_CHAR * a_pSection,
01081 const SI_CHAR * a_pKey,
01082 bool a_bRemoveEmpty = false
01083 );
01084
01085
01094 Converter GetConverter() const {
01095 return Converter(m_bStoreIsUtf8);
01096 }
01097
01098
01101 private:
01102
01103 CSimpleIniTempl(const CSimpleIniTempl &);
01104 CSimpleIniTempl & operator=(const CSimpleIniTempl &);
01105
01108 SI_Error FindFileComment(
01109 SI_CHAR *& a_pData,
01110 bool a_bCopyStrings
01111 );
01112
01117 bool FindEntry(
01118 SI_CHAR *& a_pData,
01119 const SI_CHAR *& a_pSection,
01120 const SI_CHAR *& a_pKey,
01121 const SI_CHAR *& a_pVal,
01122 const SI_CHAR *& a_pComment
01123 ) const;
01124
01147 SI_Error AddEntry(
01148 const SI_CHAR * a_pSection,
01149 const SI_CHAR * a_pKey,
01150 const SI_CHAR * a_pValue,
01151 const SI_CHAR * a_pComment,
01152 bool a_bForceReplace,
01153 bool a_bCopyStrings
01154 );
01155
01157 inline bool IsSpace(SI_CHAR ch) const {
01158 return (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n');
01159 }
01160
01162 inline bool IsComment(SI_CHAR ch) const {
01163 return (ch == ';' || ch == '#');
01164 }
01165
01166
01168 inline void SkipNewLine(SI_CHAR *& a_pData) const {
01169 a_pData += (*a_pData == '\r' && *(a_pData+1) == '\n') ? 2 : 1;
01170 }
01171
01173 SI_Error CopyString(const SI_CHAR *& a_pString);
01174
01176 void DeleteString(const SI_CHAR * a_pString);
01177
01179 bool IsLess(const SI_CHAR * a_pLeft, const SI_CHAR * a_pRight) const {
01180 const static SI_STRLESS isLess = SI_STRLESS();
01181 return isLess(a_pLeft, a_pRight);
01182 }
01183
01184 bool IsMultiLineTag(const SI_CHAR * a_pData) const;
01185 bool IsMultiLineData(const SI_CHAR * a_pData) const;
01186 bool LoadMultiLineText(
01187 SI_CHAR *& a_pData,
01188 const SI_CHAR *& a_pVal,
01189 const SI_CHAR * a_pTagName,
01190 bool a_bAllowBlankLinesInComment = false
01191 ) const;
01192 bool IsNewLineChar(SI_CHAR a_c) const;
01193
01194 bool OutputMultiLineText(
01195 OutputWriter & a_oOutput,
01196 Converter & a_oConverter,
01197 const SI_CHAR * a_pText
01198 ) const;
01199
01200 private:
01206 SI_CHAR * m_pData;
01207
01212 size_t m_uDataLen;
01213
01215 const SI_CHAR * m_pFileComment;
01216
01218 TSection m_data;
01219
01224 TNamesDepend m_strings;
01225
01227 bool m_bStoreIsUtf8;
01228
01230 bool m_bAllowMultiKey;
01231
01233 bool m_bAllowMultiLine;
01234
01236 bool m_bSpaces;
01237
01241 int m_nOrder;
01242 };
01243
01244
01245
01246
01247
01248 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
01249 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::CSimpleIniTempl(
01250 bool a_bIsUtf8,
01251 bool a_bAllowMultiKey,
01252 bool a_bAllowMultiLine
01253 )
01254 : m_pData(0)
01255 , m_uDataLen(0)
01256 , m_pFileComment(NULL)
01257 , m_bStoreIsUtf8(a_bIsUtf8)
01258 , m_bAllowMultiKey(a_bAllowMultiKey)
01259 , m_bAllowMultiLine(a_bAllowMultiLine)
01260 , m_bSpaces(true)
01261 , m_nOrder(0)
01262 { }
01263
01264 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
01265 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::~CSimpleIniTempl()
01266 {
01267 Reset();
01268 }
01269
01270 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
01271 void
01272 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::Reset()
01273 {
01274
01275 delete[] m_pData;
01276 m_pData = NULL;
01277 m_uDataLen = 0;
01278 m_pFileComment = NULL;
01279 if (!m_data.empty()) {
01280 m_data.erase(m_data.begin(), m_data.end());
01281 }
01282
01283
01284 if (!m_strings.empty()) {
01285 typename TNamesDepend::iterator i = m_strings.begin();
01286 for (; i != m_strings.end(); ++i) {
01287 delete[] const_cast<SI_CHAR*>(i->pItem);
01288 }
01289 m_strings.erase(m_strings.begin(), m_strings.end());
01290 }
01291 }
01292
01293 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
01294 SI_Error
01295 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::LoadFile(
01296 const char * a_pszFile
01297 )
01298 {
01299 FILE * fp = NULL;
01300 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
01301 fopen_s(&fp, a_pszFile, "rb");
01302 #else // !__STDC_WANT_SECURE_LIB__
01303 fp = fopen(a_pszFile, "rb");
01304 #endif // __STDC_WANT_SECURE_LIB__
01305 if (!fp) {
01306 return SI_FILE;
01307 }
01308 SI_Error rc = LoadFile(fp);
01309 fclose(fp);
01310 return rc;
01311 }
01312
01313 #ifdef SI_HAS_WIDE_FILE
01314 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
01315 SI_Error
01316 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::LoadFile(
01317 const SI_WCHAR_T * a_pwszFile
01318 )
01319 {
01320 #ifdef _WIN32
01321 FILE * fp = NULL;
01322 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
01323 _wfopen_s(&fp, a_pwszFile, L"rb");
01324 #else // !__STDC_WANT_SECURE_LIB__
01325 fp = _wfopen(a_pwszFile, L"rb");
01326 #endif // __STDC_WANT_SECURE_LIB__
01327 if (!fp) return SI_FILE;
01328 SI_Error rc = LoadFile(fp);
01329 fclose(fp);
01330 return rc;
01331 #else // !_WIN32 (therefore SI_CONVERT_ICU)
01332 char szFile[256];
01333 u_austrncpy(szFile, a_pwszFile, sizeof(szFile));
01334 return LoadFile(szFile);
01335 #endif // _WIN32
01336 }
01337 #endif // SI_HAS_WIDE_FILE
01338
01339 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
01340 SI_Error
01341 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::LoadFile(
01342 FILE * a_fpFile
01343 )
01344 {
01345
01346 int retval = fseek(a_fpFile, 0, SEEK_END);
01347 if (retval != 0) {
01348 return SI_FILE;
01349 }
01350 long lSize = ftell(a_fpFile);
01351 if (lSize < 0) {
01352 return SI_FILE;
01353 }
01354 if (lSize == 0) {
01355 return SI_OK;
01356 }
01357 char * pData = new char[lSize];
01358 if (!pData) {
01359 return SI_NOMEM;
01360 }
01361 fseek(a_fpFile, 0, SEEK_SET);
01362 size_t uRead = fread(pData, sizeof(char), lSize, a_fpFile);
01363 if (uRead != (size_t) lSize) {
01364 delete[] pData;
01365 return SI_FILE;
01366 }
01367
01368
01369 SI_Error rc = LoadData(pData, uRead);
01370 delete[] pData;
01371 return rc;
01372 }
01373
01374 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
01375 SI_Error
01376 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::LoadData(
01377 const char * a_pData,
01378 size_t a_uDataLen
01379 )
01380 {
01381 SI_CONVERTER converter(m_bStoreIsUtf8);
01382
01383 if (a_uDataLen == 0) {
01384 return SI_OK;
01385 }
01386
01387
01388 if (m_bStoreIsUtf8 && a_uDataLen >= 3) {
01389 if (memcmp(a_pData, SI_UTF8_SIGNATURE, 3) == 0) {
01390 a_pData += 3;
01391 a_uDataLen -= 3;
01392 }
01393 }
01394
01395
01396 size_t uLen = converter.SizeFromStore(a_pData, a_uDataLen);
01397 if (uLen == (size_t)(-1)) {
01398 return SI_FAIL;
01399 }
01400
01401
01402
01403 SI_CHAR * pData = new SI_CHAR[uLen+1];
01404 if (!pData) {
01405 return SI_NOMEM;
01406 }
01407 memset(pData, 0, sizeof(SI_CHAR)*(uLen+1));
01408
01409
01410 if (!converter.ConvertFromStore(a_pData, a_uDataLen, pData, uLen)) {
01411 delete[] pData;
01412 return SI_FAIL;
01413 }
01414
01415
01416 const static SI_CHAR empty = 0;
01417 SI_CHAR * pWork = pData;
01418 const SI_CHAR * pSection = ∅
01419 const SI_CHAR * pItem = NULL;
01420 const SI_CHAR * pVal = NULL;
01421 const SI_CHAR * pComment = NULL;
01422
01423
01424
01425 bool bCopyStrings = (m_pData != NULL);
01426
01427
01428
01429 SI_Error rc = FindFileComment(pWork, bCopyStrings);
01430 if (rc < 0) return rc;
01431
01432
01433 while (FindEntry(pWork, pSection, pItem, pVal, pComment)) {
01434 rc = AddEntry(pSection, pItem, pVal, pComment, false, bCopyStrings);
01435 if (rc < 0) return rc;
01436 }
01437
01438
01439 if (bCopyStrings) {
01440 delete[] pData;
01441 }
01442 else {
01443 m_pData = pData;
01444 m_uDataLen = uLen+1;
01445 }
01446
01447 return SI_OK;
01448 }
01449
01450 #ifdef SI_SUPPORT_IOSTREAMS
01451 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
01452 SI_Error
01453 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::LoadData(
01454 std::istream & a_istream
01455 )
01456 {
01457 std::string strData;
01458 char szBuf[512];
01459 do {
01460 a_istream.get(szBuf, sizeof(szBuf), '\0');
01461 strData.append(szBuf);
01462 }
01463 while (a_istream.good());
01464 return LoadData(strData);
01465 }
01466 #endif // SI_SUPPORT_IOSTREAMS
01467
01468 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
01469 SI_Error
01470 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::FindFileComment(
01471 SI_CHAR *& a_pData,
01472 bool a_bCopyStrings
01473 )
01474 {
01475
01476 if (m_pFileComment) {
01477 return SI_OK;
01478 }
01479
01480
01481
01482 if (!LoadMultiLineText(a_pData, m_pFileComment, NULL, false)) {
01483 return SI_OK;
01484 }
01485
01486
01487 if (a_bCopyStrings) {
01488 SI_Error rc = CopyString(m_pFileComment);
01489 if (rc < 0) return rc;
01490 }
01491
01492 return SI_OK;
01493 }
01494
01495 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
01496 bool
01497 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::FindEntry(
01498 SI_CHAR *& a_pData,
01499 const SI_CHAR *& a_pSection,
01500 const SI_CHAR *& a_pKey,
01501 const SI_CHAR *& a_pVal,
01502 const SI_CHAR *& a_pComment
01503 ) const
01504 {
01505 a_pComment = NULL;
01506
01507 SI_CHAR * pTrail = NULL;
01508 while (*a_pData) {
01509
01510 while (*a_pData && IsSpace(*a_pData)) {
01511 ++a_pData;
01512 }
01513 if (!*a_pData) {
01514 break;
01515 }
01516
01517
01518
01519 if (IsComment(*a_pData)) {
01520 LoadMultiLineText(a_pData, a_pComment, NULL, true);
01521 continue;
01522 }
01523
01524
01525 if (*a_pData == '[') {
01526
01527 ++a_pData;
01528 while (*a_pData && IsSpace(*a_pData)) {
01529 ++a_pData;
01530 }
01531
01532
01533
01534 a_pSection = a_pData;
01535 while (*a_pData && *a_pData != ']' && !IsNewLineChar(*a_pData)) {
01536 ++a_pData;
01537 }
01538
01539
01540 if (*a_pData != ']') {
01541 continue;
01542 }
01543
01544
01545 pTrail = a_pData - 1;
01546 while (pTrail >= a_pSection && IsSpace(*pTrail)) {
01547 --pTrail;
01548 }
01549 ++pTrail;
01550 *pTrail = 0;
01551
01552
01553 ++a_pData;
01554 while (*a_pData && !IsNewLineChar(*a_pData)) {
01555 ++a_pData;
01556 }
01557
01558 a_pKey = NULL;
01559 a_pVal = NULL;
01560 return true;
01561 }
01562
01563
01564
01565 a_pKey = a_pData;
01566 while (*a_pData && *a_pData != '=' && !IsNewLineChar(*a_pData)) {
01567 ++a_pData;
01568 }
01569
01570
01571 if (*a_pData != '=') {
01572 continue;
01573 }
01574
01575
01576 if (a_pKey == a_pData) {
01577 while (*a_pData && !IsNewLineChar(*a_pData)) {
01578 ++a_pData;
01579 }
01580 continue;
01581 }
01582
01583
01584 pTrail = a_pData - 1;
01585 while (pTrail >= a_pKey && IsSpace(*pTrail)) {
01586 --pTrail;
01587 }
01588 ++pTrail;
01589 *pTrail = 0;
01590
01591
01592 ++a_pData;
01593 while (*a_pData && !IsNewLineChar(*a_pData) && IsSpace(*a_pData)) {
01594 ++a_pData;
01595 }
01596
01597
01598 a_pVal = a_pData;
01599 while (*a_pData && !IsNewLineChar(*a_pData)) {
01600 ++a_pData;
01601 }
01602
01603
01604 pTrail = a_pData - 1;
01605 if (*a_pData) {
01606 SkipNewLine(a_pData);
01607 }
01608 while (pTrail >= a_pVal && IsSpace(*pTrail)) {
01609 --pTrail;
01610 }
01611 ++pTrail;
01612 *pTrail = 0;
01613
01614
01615 if (m_bAllowMultiLine && IsMultiLineTag(a_pVal)) {
01616
01617 const SI_CHAR * pTagName = a_pVal + 3;
01618 return LoadMultiLineText(a_pData, a_pVal, pTagName);
01619 }
01620
01621
01622 return true;
01623 }
01624
01625 return false;
01626 }
01627
01628 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
01629 bool
01630 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::IsMultiLineTag(
01631 const SI_CHAR * a_pVal
01632 ) const
01633 {
01634
01635 if (*a_pVal++ != '<') return false;
01636 if (*a_pVal++ != '<') return false;
01637 if (*a_pVal++ != '<') return false;
01638 return true;
01639 }
01640
01641 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
01642 bool
01643 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::IsMultiLineData(
01644 const SI_CHAR * a_pData
01645 ) const
01646 {
01647
01648
01649
01650
01651
01652
01653 if (!*a_pData) {
01654 return false;
01655 }
01656
01657
01658 if (IsSpace(*a_pData)) {
01659 return true;
01660 }
01661
01662
01663 while (*a_pData) {
01664 if (IsNewLineChar(*a_pData)) {
01665 return true;
01666 }
01667 ++a_pData;
01668 }
01669
01670
01671 if (IsSpace(*--a_pData)) {
01672 return true;
01673 }
01674
01675 return false;
01676 }
01677
01678 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
01679 bool
01680 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::IsNewLineChar(
01681 SI_CHAR a_c
01682 ) const
01683 {
01684 return (a_c == '\n' || a_c == '\r');
01685 }
01686
01687 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
01688 bool
01689 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::LoadMultiLineText(
01690 SI_CHAR *& a_pData,
01691 const SI_CHAR *& a_pVal,
01692 const SI_CHAR * a_pTagName,
01693 bool a_bAllowBlankLinesInComment
01694 ) const
01695 {
01696
01697
01698
01699
01700
01701
01702
01703
01704 SI_CHAR * pDataLine = a_pData;
01705 SI_CHAR * pCurrLine;
01706
01707
01708 a_pVal = a_pData;
01709
01710
01711
01712
01713 SI_CHAR cEndOfLineChar = *a_pData;
01714 for(;;) {
01715
01716
01717 if (!a_pTagName && !IsComment(*a_pData)) {
01718
01719 if (!a_bAllowBlankLinesInComment) {
01720 break;
01721 }
01722
01723
01724
01725
01726 SI_CHAR * pCurr = a_pData;
01727 int nNewLines = 0;
01728 while (IsSpace(*pCurr)) {
01729 if (IsNewLineChar(*pCurr)) {
01730 ++nNewLines;
01731 SkipNewLine(pCurr);
01732 }
01733 else {
01734 ++pCurr;
01735 }
01736 }
01737
01738
01739
01740 if (IsComment(*pCurr)) {
01741 for (; nNewLines > 0; --nNewLines) *pDataLine++ = '\n';
01742 a_pData = pCurr;
01743 continue;
01744 }
01745
01746
01747 break;
01748 }
01749
01750
01751 pCurrLine = a_pData;
01752 while (*a_pData && !IsNewLineChar(*a_pData)) ++a_pData;
01753
01754
01755 if (pDataLine < pCurrLine) {
01756 size_t nLen = (size_t) (a_pData - pCurrLine);
01757 memmove(pDataLine, pCurrLine, nLen * sizeof(SI_CHAR));
01758 pDataLine[nLen] = '\0';
01759 }
01760
01761
01762 cEndOfLineChar = *a_pData;
01763 *a_pData = 0;
01764
01765
01766
01767
01768 if (a_pTagName &&
01769 (!IsLess(pDataLine, a_pTagName) && !IsLess(a_pTagName, pDataLine)))
01770 {
01771 break;
01772 }
01773
01774
01775
01776 if (!cEndOfLineChar) {
01777 return true;
01778 }
01779
01780
01781
01782 pDataLine += (a_pData - pCurrLine);
01783 *a_pData = cEndOfLineChar;
01784 SkipNewLine(a_pData);
01785 *pDataLine++ = '\n';
01786 }
01787
01788
01789 if (a_pVal == a_pData) {
01790 a_pVal = NULL;
01791 return false;
01792 }
01793
01794
01795
01796
01797
01798 *--pDataLine = '\0';
01799
01800
01801
01802 if (a_pTagName && cEndOfLineChar) {
01803 SI_ASSERT(IsNewLineChar(cEndOfLineChar));
01804 *a_pData = cEndOfLineChar;
01805 SkipNewLine(a_pData);
01806 }
01807
01808 return true;
01809 }
01810
01811 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
01812 SI_Error
01813 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::CopyString(
01814 const SI_CHAR *& a_pString
01815 )
01816 {
01817 size_t uLen = 0;
01818 if (sizeof(SI_CHAR) == sizeof(char)) {
01819 uLen = strlen((const char *)a_pString);
01820 }
01821 else if (sizeof(SI_CHAR) == sizeof(wchar_t)) {
01822 uLen = wcslen((const wchar_t *)a_pString);
01823 }
01824 else {
01825 for ( ; a_pString[uLen]; ++uLen) ;
01826 }
01827 ++uLen;
01828 SI_CHAR * pCopy = new SI_CHAR[uLen];
01829 if (!pCopy) {
01830 return SI_NOMEM;
01831 }
01832 memcpy(pCopy, a_pString, sizeof(SI_CHAR)*uLen);
01833 m_strings.push_back(pCopy);
01834 a_pString = pCopy;
01835 return SI_OK;
01836 }
01837
01838 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
01839 SI_Error
01840 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::AddEntry(
01841 const SI_CHAR * a_pSection,
01842 const SI_CHAR * a_pKey,
01843 const SI_CHAR * a_pValue,
01844 const SI_CHAR * a_pComment,
01845 bool a_bForceReplace,
01846 bool a_bCopyStrings
01847 )
01848 {
01849 SI_Error rc;
01850 bool bInserted = false;
01851
01852 SI_ASSERT(!a_pComment || IsComment(*a_pComment));
01853
01854
01855
01856 if (a_bCopyStrings && a_pComment) {
01857 rc = CopyString(a_pComment);
01858 if (rc < 0) return rc;
01859 }
01860
01861
01862 typename TSection::iterator iSection = m_data.find(a_pSection);
01863 if (iSection == m_data.end()) {
01864
01865
01866 if (a_bCopyStrings) {
01867 rc = CopyString(a_pSection);
01868 if (rc < 0) return rc;
01869 }
01870
01871
01872 Entry oSection(a_pSection, ++m_nOrder);
01873 if (a_pComment && (!a_pKey || !a_pValue)) {
01874 oSection.pComment = a_pComment;
01875 }
01876
01877 typename TSection::value_type oEntry(oSection, TKeyVal());
01878 typedef typename TSection::iterator SectionIterator;
01879 std::pair<SectionIterator,bool> i = m_data.insert(oEntry);
01880 iSection = i.first;
01881 bInserted = true;
01882 }
01883 if (!a_pKey || !a_pValue) {
01884
01885 return bInserted ? SI_INSERTED : SI_UPDATED;
01886 }
01887
01888
01889 TKeyVal & keyval = iSection->second;
01890 typename TKeyVal::iterator iKey = keyval.find(a_pKey);
01891
01892
01893
01894 int nLoadOrder = ++m_nOrder;
01895 if (iKey != keyval.end() && m_bAllowMultiKey && a_bForceReplace) {
01896 const SI_CHAR * pComment = NULL;
01897 while (iKey != keyval.end() && !IsLess(a_pKey, iKey->first.pItem)) {
01898 if (iKey->first.nOrder < nLoadOrder) {
01899 nLoadOrder = iKey->first.nOrder;
01900 pComment = iKey->first.pComment;
01901 }
01902 ++iKey;
01903 }
01904 if (pComment) {
01905 DeleteString(a_pComment);
01906 a_pComment = pComment;
01907 CopyString(a_pComment);
01908 }
01909 Delete(a_pSection, a_pKey);
01910 iKey = keyval.end();
01911 }
01912
01913
01914 bool bForceCreateNewKey = m_bAllowMultiKey && !a_bForceReplace;
01915 if (a_bCopyStrings) {
01916 if (bForceCreateNewKey || iKey == keyval.end()) {
01917
01918
01919
01920 rc = CopyString(a_pKey);
01921 if (rc < 0) return rc;
01922 }
01923
01924
01925 rc = CopyString(a_pValue);
01926 if (rc < 0) return rc;
01927 }
01928
01929
01930 if (iKey == keyval.end() || bForceCreateNewKey) {
01931 Entry oKey(a_pKey, nLoadOrder);
01932 if (a_pComment) {
01933 oKey.pComment = a_pComment;
01934 }
01935 typename TKeyVal::value_type oEntry(oKey, static_cast<const SI_CHAR *>(NULL));
01936 iKey = keyval.insert(oEntry);
01937 bInserted = true;
01938 }
01939 iKey->second = a_pValue;
01940 return bInserted ? SI_INSERTED : SI_UPDATED;
01941 }
01942
01943 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
01944 const SI_CHAR *
01945 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetValue(
01946 const SI_CHAR * a_pSection,
01947 const SI_CHAR * a_pKey,
01948 const SI_CHAR * a_pDefault,
01949 bool * a_pHasMultiple
01950 ) const
01951 {
01952 if (a_pHasMultiple) {
01953 *a_pHasMultiple = false;
01954 }
01955 if (!a_pSection || !a_pKey) {
01956 return a_pDefault;
01957 }
01958 typename TSection::const_iterator iSection = m_data.find(a_pSection);
01959 if (iSection == m_data.end()) {
01960 return a_pDefault;
01961 }
01962 typename TKeyVal::const_iterator iKeyVal = iSection->second.find(a_pKey);
01963 if (iKeyVal == iSection->second.end()) {
01964 return a_pDefault;
01965 }
01966
01967
01968 if (m_bAllowMultiKey && a_pHasMultiple) {
01969 typename TKeyVal::const_iterator iTemp = iKeyVal;
01970 if (++iTemp != iSection->second.end()) {
01971 if (!IsLess(a_pKey, iTemp->first.pItem)) {
01972 *a_pHasMultiple = true;
01973 }
01974 }
01975 }
01976
01977 return iKeyVal->second;
01978 }
01979
01980 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
01981 long
01982 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetLongValue(
01983 const SI_CHAR * a_pSection,
01984 const SI_CHAR * a_pKey,
01985 long a_nDefault,
01986 bool * a_pHasMultiple
01987 ) const
01988 {
01989
01990 const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey, NULL, a_pHasMultiple);
01991 if (!pszValue || !*pszValue) return a_nDefault;
01992
01993
01994 char szValue[64] = { 0 };
01995 SI_CONVERTER c(m_bStoreIsUtf8);
01996 if (!c.ConvertToStore(pszValue, szValue, sizeof(szValue))) {
01997 return a_nDefault;
01998 }
01999
02000
02001 long nValue = a_nDefault;
02002 char * pszSuffix = szValue;
02003 if (szValue[0] == '0' && (szValue[1] == 'x' || szValue[1] == 'X')) {
02004 if (!szValue[2]) return a_nDefault;
02005 nValue = strtol(&szValue[2], &pszSuffix, 16);
02006 }
02007 else {
02008 nValue = strtol(szValue, &pszSuffix, 10);
02009 }
02010
02011
02012 if (*pszSuffix) {
02013 return a_nDefault;
02014 }
02015
02016 return nValue;
02017 }
02018
02019 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
02020 SI_Error
02021 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SetLongValue(
02022 const SI_CHAR * a_pSection,
02023 const SI_CHAR * a_pKey,
02024 long a_nValue,
02025 const SI_CHAR * a_pComment,
02026 bool a_bUseHex,
02027 bool a_bForceReplace
02028 )
02029 {
02030
02031 if (!a_pSection || !a_pKey) return SI_FAIL;
02032
02033
02034 char szInput[64];
02035 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
02036 sprintf_s(szInput, a_bUseHex ? "0x%lx" : "%ld", a_nValue);
02037 #else // !__STDC_WANT_SECURE_LIB__
02038 sprintf(szInput, a_bUseHex ? "0x%lx" : "%ld", a_nValue);
02039 #endif // __STDC_WANT_SECURE_LIB__
02040
02041
02042 SI_CHAR szOutput[64];
02043 SI_CONVERTER c(m_bStoreIsUtf8);
02044 c.ConvertFromStore(szInput, strlen(szInput) + 1,
02045 szOutput, sizeof(szOutput) / sizeof(SI_CHAR));
02046
02047
02048 return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace, true);
02049 }
02050
02051 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
02052 double
02053 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetDoubleValue(
02054 const SI_CHAR * a_pSection,
02055 const SI_CHAR * a_pKey,
02056 double a_nDefault,
02057 bool * a_pHasMultiple
02058 ) const
02059 {
02060
02061 const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey, NULL, a_pHasMultiple);
02062 if (!pszValue || !*pszValue) return a_nDefault;
02063
02064
02065 char szValue[64] = { 0 };
02066 SI_CONVERTER c(m_bStoreIsUtf8);
02067 if (!c.ConvertToStore(pszValue, szValue, sizeof(szValue))) {
02068 return a_nDefault;
02069 }
02070
02071 char * pszSuffix = NULL;
02072 double nValue = strtod(szValue, &pszSuffix);
02073
02074
02075 if (!pszSuffix || *pszSuffix) {
02076 return a_nDefault;
02077 }
02078
02079 return nValue;
02080 }
02081
02082 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
02083 SI_Error
02084 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SetDoubleValue(
02085 const SI_CHAR * a_pSection,
02086 const SI_CHAR * a_pKey,
02087 double a_nValue,
02088 const SI_CHAR * a_pComment,
02089 bool a_bForceReplace
02090 )
02091 {
02092
02093 if (!a_pSection || !a_pKey) return SI_FAIL;
02094
02095
02096 char szInput[64];
02097 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
02098 sprintf_s(szInput, "%f", a_nValue);
02099 #else // !__STDC_WANT_SECURE_LIB__
02100 sprintf(szInput, "%f", a_nValue);
02101 #endif // __STDC_WANT_SECURE_LIB__
02102
02103
02104 SI_CHAR szOutput[64];
02105 SI_CONVERTER c(m_bStoreIsUtf8);
02106 c.ConvertFromStore(szInput, strlen(szInput) + 1,
02107 szOutput, sizeof(szOutput) / sizeof(SI_CHAR));
02108
02109
02110 return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace, true);
02111 }
02112
02113 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
02114 bool
02115 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetBoolValue(
02116 const SI_CHAR * a_pSection,
02117 const SI_CHAR * a_pKey,
02118 bool a_bDefault,
02119 bool * a_pHasMultiple
02120 ) const
02121 {
02122
02123 const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey, NULL, a_pHasMultiple);
02124 if (!pszValue || !*pszValue) return a_bDefault;
02125
02126
02127 switch (pszValue[0]) {
02128 case 't': case 'T':
02129 case 'y': case 'Y':
02130 case '1':
02131 return true;
02132
02133 case 'f': case 'F':
02134 case 'n': case 'N':
02135 case '0':
02136 return false;
02137
02138 case 'o': case 'O':
02139 if (pszValue[1] == 'n' || pszValue[1] == 'N') return true;
02140 if (pszValue[1] == 'f' || pszValue[1] == 'F') return false;
02141 break;
02142 }
02143
02144
02145 return a_bDefault;
02146 }
02147
02148 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
02149 SI_Error
02150 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SetBoolValue(
02151 const SI_CHAR * a_pSection,
02152 const SI_CHAR * a_pKey,
02153 bool a_bValue,
02154 const SI_CHAR * a_pComment,
02155 bool a_bForceReplace
02156 )
02157 {
02158
02159 if (!a_pSection || !a_pKey) return SI_FAIL;
02160
02161
02162 const char * pszInput = a_bValue ? "true" : "false";
02163
02164
02165 SI_CHAR szOutput[64];
02166 SI_CONVERTER c(m_bStoreIsUtf8);
02167 c.ConvertFromStore(pszInput, strlen(pszInput) + 1,
02168 szOutput, sizeof(szOutput) / sizeof(SI_CHAR));
02169
02170
02171 return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace, true);
02172 }
02173
02174 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
02175 bool
02176 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetAllValues(
02177 const SI_CHAR * a_pSection,
02178 const SI_CHAR * a_pKey,
02179 TNamesDepend & a_values
02180 ) const
02181 {
02182 a_values.clear();
02183
02184 if (!a_pSection || !a_pKey) {
02185 return false;
02186 }
02187 typename TSection::const_iterator iSection = m_data.find(a_pSection);
02188 if (iSection == m_data.end()) {
02189 return false;
02190 }
02191 typename TKeyVal::const_iterator iKeyVal = iSection->second.find(a_pKey);
02192 if (iKeyVal == iSection->second.end()) {
02193 return false;
02194 }
02195
02196
02197 a_values.push_back(Entry(iKeyVal->second, iKeyVal->first.pComment, iKeyVal->first.nOrder));
02198 if (m_bAllowMultiKey) {
02199 ++iKeyVal;
02200 while (iKeyVal != iSection->second.end() && !IsLess(a_pKey, iKeyVal->first.pItem)) {
02201 a_values.push_back(Entry(iKeyVal->second, iKeyVal->first.pComment, iKeyVal->first.nOrder));
02202 ++iKeyVal;
02203 }
02204 }
02205
02206 return true;
02207 }
02208
02209 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
02210 int
02211 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetSectionSize(
02212 const SI_CHAR * a_pSection
02213 ) const
02214 {
02215 if (!a_pSection) {
02216 return -1;
02217 }
02218
02219 typename TSection::const_iterator iSection = m_data.find(a_pSection);
02220 if (iSection == m_data.end()) {
02221 return -1;
02222 }
02223 const TKeyVal & section = iSection->second;
02224
02225
02226
02227 if (!m_bAllowMultiKey || section.empty()) {
02228 return (int) section.size();
02229 }
02230
02231
02232 int nCount = 0;
02233 const SI_CHAR * pLastKey = NULL;
02234 typename TKeyVal::const_iterator iKeyVal = section.begin();
02235 for (int n = 0; iKeyVal != section.end(); ++iKeyVal, ++n) {
02236 if (!pLastKey || IsLess(pLastKey, iKeyVal->first.pItem)) {
02237 ++nCount;
02238 pLastKey = iKeyVal->first.pItem;
02239 }
02240 }
02241 return nCount;
02242 }
02243
02244 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
02245 const typename CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::TKeyVal *
02246 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetSection(
02247 const SI_CHAR * a_pSection
02248 ) const
02249 {
02250 if (a_pSection) {
02251 typename TSection::const_iterator i = m_data.find(a_pSection);
02252 if (i != m_data.end()) {
02253 return &(i->second);
02254 }
02255 }
02256 return 0;
02257 }
02258
02259 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
02260 void
02261 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetAllSections(
02262 TNamesDepend & a_names
02263 ) const
02264 {
02265 a_names.clear();
02266 typename TSection::const_iterator i = m_data.begin();
02267 for (int n = 0; i != m_data.end(); ++i, ++n ) {
02268 a_names.push_back(i->first);
02269 }
02270 }
02271
02272 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
02273 bool
02274 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetAllKeys(
02275 const SI_CHAR * a_pSection,
02276 TNamesDepend & a_names
02277 ) const
02278 {
02279 a_names.clear();
02280
02281 if (!a_pSection) {
02282 return false;
02283 }
02284
02285 typename TSection::const_iterator iSection = m_data.find(a_pSection);
02286 if (iSection == m_data.end()) {
02287 return false;
02288 }
02289
02290 const TKeyVal & section = iSection->second;
02291 const SI_CHAR * pLastKey = NULL;
02292 typename TKeyVal::const_iterator iKeyVal = section.begin();
02293 for (int n = 0; iKeyVal != section.end(); ++iKeyVal, ++n ) {
02294 if (!pLastKey || IsLess(pLastKey, iKeyVal->first.pItem)) {
02295 a_names.push_back(iKeyVal->first);
02296 pLastKey = iKeyVal->first.pItem;
02297 }
02298 }
02299
02300 return true;
02301 }
02302
02303 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
02304 SI_Error
02305 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SaveFile(
02306 const char * a_pszFile,
02307 bool a_bAddSignature
02308 ) const
02309 {
02310 FILE * fp = NULL;
02311 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
02312 fopen_s(&fp, a_pszFile, "wb");
02313 #else // !__STDC_WANT_SECURE_LIB__
02314 fp = fopen(a_pszFile, "wb");
02315 #endif // __STDC_WANT_SECURE_LIB__
02316 if (!fp) return SI_FILE;
02317 SI_Error rc = SaveFile(fp, a_bAddSignature);
02318 fclose(fp);
02319 return rc;
02320 }
02321
02322 #ifdef SI_HAS_WIDE_FILE
02323 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
02324 SI_Error
02325 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SaveFile(
02326 const SI_WCHAR_T * a_pwszFile,
02327 bool a_bAddSignature
02328 ) const
02329 {
02330 #ifdef _WIN32
02331 FILE * fp = NULL;
02332 #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
02333 _wfopen_s(&fp, a_pwszFile, L"wb");
02334 #else // !__STDC_WANT_SECURE_LIB__
02335 fp = _wfopen(a_pwszFile, L"wb");
02336 #endif // __STDC_WANT_SECURE_LIB__
02337 if (!fp) return SI_FILE;
02338 SI_Error rc = SaveFile(fp, a_bAddSignature);
02339 fclose(fp);
02340 return rc;
02341 #else // !_WIN32 (therefore SI_CONVERT_ICU)
02342 char szFile[256];
02343 u_austrncpy(szFile, a_pwszFile, sizeof(szFile));
02344 return SaveFile(szFile, a_bAddSignature);
02345 #endif // _WIN32
02346 }
02347 #endif // SI_HAS_WIDE_FILE
02348
02349 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
02350 SI_Error
02351 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SaveFile(
02352 FILE * a_pFile,
02353 bool a_bAddSignature
02354 ) const
02355 {
02356 FileWriter writer(a_pFile);
02357 return Save(writer, a_bAddSignature);
02358 }
02359
02360 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
02361 SI_Error
02362 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::Save(
02363 OutputWriter & a_oOutput,
02364 bool a_bAddSignature
02365 ) const
02366 {
02367 Converter convert(m_bStoreIsUtf8);
02368
02369
02370 if (m_bStoreIsUtf8 && a_bAddSignature) {
02371 a_oOutput.Write(SI_UTF8_SIGNATURE);
02372 }
02373
02374
02375 TNamesDepend oSections;
02376 GetAllSections(oSections);
02377 #if defined(_MSC_VER) && _MSC_VER <= 1200
02378 oSections.sort();
02379 #elif defined(__BORLANDC__)
02380 oSections.sort(Entry::LoadOrder());
02381 #else
02382 oSections.sort(typename Entry::LoadOrder());
02383 #endif
02384
02385
02386 bool bNeedNewLine = false;
02387 if (m_pFileComment) {
02388 if (!OutputMultiLineText(a_oOutput, convert, m_pFileComment)) {
02389 return SI_FAIL;
02390 }
02391 bNeedNewLine = true;
02392 }
02393
02394
02395 typename TNamesDepend::const_iterator iSection = oSections.begin();
02396 for ( ; iSection != oSections.end(); ++iSection ) {
02397
02398 if (iSection->pComment) {
02399 if (bNeedNewLine) {
02400 a_oOutput.Write(SI_NEWLINE_A);
02401 a_oOutput.Write(SI_NEWLINE_A);
02402 }
02403 if (!OutputMultiLineText(a_oOutput, convert, iSection->pComment)) {
02404 return SI_FAIL;
02405 }
02406 bNeedNewLine = false;
02407 }
02408
02409 if (bNeedNewLine) {
02410 a_oOutput.Write(SI_NEWLINE_A);
02411 a_oOutput.Write(SI_NEWLINE_A);
02412 bNeedNewLine = false;
02413 }
02414
02415
02416 if (*iSection->pItem) {
02417 if (!convert.ConvertToStore(iSection->pItem)) {
02418 return SI_FAIL;
02419 }
02420 a_oOutput.Write("[");
02421 a_oOutput.Write(convert.Data());
02422 a_oOutput.Write("]");
02423 a_oOutput.Write(SI_NEWLINE_A);
02424 }
02425
02426
02427 TNamesDepend oKeys;
02428 GetAllKeys(iSection->pItem, oKeys);
02429 #if defined(_MSC_VER) && _MSC_VER <= 1200
02430 oKeys.sort();
02431 #elif defined(__BORLANDC__)
02432 oKeys.sort(Entry::LoadOrder());
02433 #else
02434 oKeys.sort(typename Entry::LoadOrder());
02435 #endif
02436
02437
02438 typename TNamesDepend::const_iterator iKey = oKeys.begin();
02439 for ( ; iKey != oKeys.end(); ++iKey) {
02440
02441 TNamesDepend oValues;
02442 GetAllValues(iSection->pItem, iKey->pItem, oValues);
02443
02444 typename TNamesDepend::const_iterator iValue = oValues.begin();
02445 for ( ; iValue != oValues.end(); ++iValue) {
02446
02447 if (iValue->pComment) {
02448 a_oOutput.Write(SI_NEWLINE_A);
02449 if (!OutputMultiLineText(a_oOutput, convert, iValue->pComment)) {
02450 return SI_FAIL;
02451 }
02452 }
02453
02454
02455 if (!convert.ConvertToStore(iKey->pItem)) {
02456 return SI_FAIL;
02457 }
02458 a_oOutput.Write(convert.Data());
02459
02460
02461 if (!convert.ConvertToStore(iValue->pItem)) {
02462 return SI_FAIL;
02463 }
02464 a_oOutput.Write(m_bSpaces ? " = " : "=");
02465 if (m_bAllowMultiLine && IsMultiLineData(iValue->pItem)) {
02466
02467
02468 a_oOutput.Write("<<<END_OF_TEXT" SI_NEWLINE_A);
02469 if (!OutputMultiLineText(a_oOutput, convert, iValue->pItem)) {
02470 return SI_FAIL;
02471 }
02472 a_oOutput.Write("END_OF_TEXT");
02473 }
02474 else {
02475 a_oOutput.Write(convert.Data());
02476 }
02477 a_oOutput.Write(SI_NEWLINE_A);
02478 }
02479 }
02480
02481 bNeedNewLine = true;
02482 }
02483
02484 return SI_OK;
02485 }
02486
02487 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
02488 bool
02489 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::OutputMultiLineText(
02490 OutputWriter & a_oOutput,
02491 Converter & a_oConverter,
02492 const SI_CHAR * a_pText
02493 ) const
02494 {
02495 const SI_CHAR * pEndOfLine;
02496 SI_CHAR cEndOfLineChar = *a_pText;
02497 while (cEndOfLineChar) {
02498
02499 pEndOfLine = a_pText;
02500 for (; *pEndOfLine && *pEndOfLine != '\n'; ++pEndOfLine) ;
02501 cEndOfLineChar = *pEndOfLine;
02502
02503
02504 *const_cast<SI_CHAR*>(pEndOfLine) = 0;
02505 if (!a_oConverter.ConvertToStore(a_pText)) {
02506 return false;
02507 }
02508 *const_cast<SI_CHAR*>(pEndOfLine) = cEndOfLineChar;
02509 a_pText += (pEndOfLine - a_pText) + 1;
02510 a_oOutput.Write(a_oConverter.Data());
02511 a_oOutput.Write(SI_NEWLINE_A);
02512 }
02513 return true;
02514 }
02515
02516 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
02517 bool
02518 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::Delete(
02519 const SI_CHAR * a_pSection,
02520 const SI_CHAR * a_pKey,
02521 bool a_bRemoveEmpty
02522 )
02523 {
02524 if (!a_pSection) {
02525 return false;
02526 }
02527
02528 typename TSection::iterator iSection = m_data.find(a_pSection);
02529 if (iSection == m_data.end()) {
02530 return false;
02531 }
02532
02533
02534 if (a_pKey) {
02535 typename TKeyVal::iterator iKeyVal = iSection->second.find(a_pKey);
02536 if (iKeyVal == iSection->second.end()) {
02537 return false;
02538 }
02539
02540
02541 typename TKeyVal::iterator iDelete;
02542 do {
02543 iDelete = iKeyVal++;
02544
02545 DeleteString(iDelete->first.pItem);
02546 DeleteString(iDelete->second);
02547 iSection->second.erase(iDelete);
02548 }
02549 while (iKeyVal != iSection->second.end()
02550 && !IsLess(a_pKey, iKeyVal->first.pItem));
02551
02552
02553
02554
02555 if (!a_bRemoveEmpty || !iSection->second.empty()) {
02556 return true;
02557 }
02558 }
02559 else {
02560
02561
02562 typename TKeyVal::iterator iKeyVal = iSection->second.begin();
02563 for ( ; iKeyVal != iSection->second.end(); ++iKeyVal) {
02564 DeleteString(iKeyVal->first.pItem);
02565 DeleteString(iKeyVal->second);
02566 }
02567 }
02568
02569
02570 DeleteString(iSection->first.pItem);
02571 m_data.erase(iSection);
02572
02573 return true;
02574 }
02575
02576 template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
02577 void
02578 CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::DeleteString(
02579 const SI_CHAR * a_pString
02580 )
02581 {
02582
02583
02584
02585 if (a_pString < m_pData || a_pString >= m_pData + m_uDataLen) {
02586 typename TNamesDepend::iterator i = m_strings.begin();
02587 for (;i != m_strings.end(); ++i) {
02588 if (a_pString == i->pItem) {
02589 delete[] const_cast<SI_CHAR*>(i->pItem);
02590 m_strings.erase(i);
02591 break;
02592 }
02593 }
02594 }
02595 }
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611 #if !defined(SI_CONVERT_GENERIC) && !defined(SI_CONVERT_WIN32) && !defined(SI_CONVERT_ICU)
02612 # ifdef _WIN32
02613 # define SI_CONVERT_WIN32
02614 # else
02615 # define SI_CONVERT_GENERIC
02616 # endif
02617 #endif
02618
02624 template<class SI_CHAR>
02625 struct SI_GenericCase {
02626 bool operator()(const SI_CHAR * pLeft, const SI_CHAR * pRight) const {
02627 long cmp;
02628 for ( ;*pLeft && *pRight; ++pLeft, ++pRight) {
02629 cmp = (long) *pLeft - (long) *pRight;
02630 if (cmp != 0) {
02631 return cmp < 0;
02632 }
02633 }
02634 return *pRight != 0;
02635 }
02636 };
02637
02644 template<class SI_CHAR>
02645 struct SI_GenericNoCase {
02646 inline SI_CHAR locase(SI_CHAR ch) const {
02647 return (ch < 'A' || ch > 'Z') ? ch : (ch - 'A' + 'a');
02648 }
02649 bool operator()(const SI_CHAR * pLeft, const SI_CHAR * pRight) const {
02650 long cmp;
02651 for ( ;*pLeft && *pRight; ++pLeft, ++pRight) {
02652 cmp = (long) locase(*pLeft) - (long) locase(*pRight);
02653 if (cmp != 0) {
02654 return cmp < 0;
02655 }
02656 }
02657 return *pRight != 0;
02658 }
02659 };
02660
02664 template<class SI_CHAR>
02665 class SI_ConvertA {
02666 bool m_bStoreIsUtf8;
02667 protected:
02668 SI_ConvertA() { }
02669 public:
02670 SI_ConvertA(bool a_bStoreIsUtf8) : m_bStoreIsUtf8(a_bStoreIsUtf8) { }
02671
02672
02673 SI_ConvertA(const SI_ConvertA & rhs) { operator=(rhs); }
02674 SI_ConvertA & operator=(const SI_ConvertA & rhs) {
02675 m_bStoreIsUtf8 = rhs.m_bStoreIsUtf8;
02676 return *this;
02677 }
02678
02692 size_t SizeFromStore(
02693 const char * a_pInputData,
02694 size_t a_uInputDataLen)
02695 {
02696 (void)a_pInputData;
02697 SI_ASSERT(a_uInputDataLen != (size_t) -1);
02698
02699
02700 return a_uInputDataLen;
02701 }
02702
02716 bool ConvertFromStore(
02717 const char * a_pInputData,
02718 size_t a_uInputDataLen,
02719 SI_CHAR * a_pOutputData,
02720 size_t a_uOutputDataSize)
02721 {
02722
02723 if (a_uInputDataLen > a_uOutputDataSize) {
02724 return false;
02725 }
02726 memcpy(a_pOutputData, a_pInputData, a_uInputDataLen);
02727 return true;
02728 }
02729
02740 size_t SizeToStore(
02741 const SI_CHAR * a_pInputData)
02742 {
02743
02744 return strlen((const char *)a_pInputData) + 1;
02745 }
02746
02760 bool ConvertToStore(
02761 const SI_CHAR * a_pInputData,
02762 char * a_pOutputData,
02763 size_t a_uOutputDataSize)
02764 {
02765
02766 size_t uInputLen = strlen((const char *)a_pInputData) + 1;
02767 if (uInputLen > a_uOutputDataSize) {
02768 return false;
02769 }
02770
02771
02772 memcpy(a_pOutputData, a_pInputData, uInputLen);
02773 return true;
02774 }
02775 };
02776
02777
02778
02779
02780
02781 #ifdef SI_CONVERT_GENERIC
02782
02783 #define SI_Case SI_GenericCase
02784 #define SI_NoCase SI_GenericNoCase
02785
02786 #include <wchar.h>
02787 #include "ConvertUTF.h"
02788
02793 template<class SI_CHAR>
02794 class SI_ConvertW {
02795 bool m_bStoreIsUtf8;
02796 protected:
02797 SI_ConvertW() { }
02798 public:
02799 SI_ConvertW(bool a_bStoreIsUtf8) : m_bStoreIsUtf8(a_bStoreIsUtf8) { }
02800
02801
02802 SI_ConvertW(const SI_ConvertW & rhs) { operator=(rhs); }
02803 SI_ConvertW & operator=(const SI_ConvertW & rhs) {
02804 m_bStoreIsUtf8 = rhs.m_bStoreIsUtf8;
02805 return *this;
02806 }
02807
02821 size_t SizeFromStore(
02822 const char * a_pInputData,
02823 size_t a_uInputDataLen)
02824 {
02825 SI_ASSERT(a_uInputDataLen != (size_t) -1);
02826
02827 if (m_bStoreIsUtf8) {
02828
02829
02830
02831 return a_uInputDataLen;
02832 }
02833 else {
02834 return mbstowcs(NULL, a_pInputData, a_uInputDataLen);
02835 }
02836 }
02837
02851 bool ConvertFromStore(
02852 const char * a_pInputData,
02853 size_t a_uInputDataLen,
02854 SI_CHAR * a_pOutputData,
02855 size_t a_uOutputDataSize)
02856 {
02857 if (m_bStoreIsUtf8) {
02858
02859
02860
02861
02862
02863 ConversionResult retval;
02864 const UTF8 * pUtf8 = (const UTF8 *) a_pInputData;
02865 if (sizeof(wchar_t) == sizeof(UTF32)) {
02866 UTF32 * pUtf32 = (UTF32 *) a_pOutputData;
02867 retval = ConvertUTF8toUTF32(
02868 &pUtf8, pUtf8 + a_uInputDataLen,
02869 &pUtf32, pUtf32 + a_uOutputDataSize,
02870 lenientConversion);
02871 }
02872 else if (sizeof(wchar_t) == sizeof(UTF16)) {
02873 UTF16 * pUtf16 = (UTF16 *) a_pOutputData;
02874 retval = ConvertUTF8toUTF16(
02875 &pUtf8, pUtf8 + a_uInputDataLen,
02876 &pUtf16, pUtf16 + a_uOutputDataSize,
02877 lenientConversion);
02878 }
02879 return retval == conversionOK;
02880 }
02881 else {
02882 size_t retval = mbstowcs(a_pOutputData,
02883 a_pInputData, a_uOutputDataSize);
02884 return retval != (size_t)(-1);
02885 }
02886 }
02887
02898 size_t SizeToStore(
02899 const SI_CHAR * a_pInputData)
02900 {
02901 if (m_bStoreIsUtf8) {
02902
02903 size_t uLen = 0;
02904 while (a_pInputData[uLen]) {
02905 ++uLen;
02906 }
02907 return (6 * uLen) + 1;
02908 }
02909 else {
02910 size_t uLen = wcstombs(NULL, a_pInputData, 0);
02911 if (uLen == (size_t)(-1)) {
02912 return uLen;
02913 }
02914 return uLen + 1;
02915 }
02916 }
02917
02931 bool ConvertToStore(
02932 const SI_CHAR * a_pInputData,
02933 char * a_pOutputData,
02934 size_t a_uOutputDataSize
02935 )
02936 {
02937 if (m_bStoreIsUtf8) {
02938
02939 size_t uInputLen = 0;
02940 while (a_pInputData[uInputLen]) {
02941 ++uInputLen;
02942 }
02943 ++uInputLen;
02944
02945
02946
02947
02948
02949
02950 ConversionResult retval;
02951 UTF8 * pUtf8 = (UTF8 *) a_pOutputData;
02952 if (sizeof(wchar_t) == sizeof(UTF32)) {
02953 const UTF32 * pUtf32 = (const UTF32 *) a_pInputData;
02954 retval = ConvertUTF32toUTF8(
02955 &pUtf32, pUtf32 + uInputLen,
02956 &pUtf8, pUtf8 + a_uOutputDataSize,
02957 lenientConversion);
02958 }
02959 else if (sizeof(wchar_t) == sizeof(UTF16)) {
02960 const UTF16 * pUtf16 = (const UTF16 *) a_pInputData;
02961 retval = ConvertUTF16toUTF8(
02962 &pUtf16, pUtf16 + uInputLen,
02963 &pUtf8, pUtf8 + a_uOutputDataSize,
02964 lenientConversion);
02965 }
02966 return retval == conversionOK;
02967 }
02968 else {
02969 size_t retval = wcstombs(a_pOutputData,
02970 a_pInputData, a_uOutputDataSize);
02971 return retval != (size_t) -1;
02972 }
02973 }
02974 };
02975
02976 #endif // SI_CONVERT_GENERIC
02977
02978
02979
02980
02981
02982 #ifdef SI_CONVERT_ICU
02983
02984 #define SI_Case SI_GenericCase
02985 #define SI_NoCase SI_GenericNoCase
02986
02987 #include <unicode/ucnv.h>
02988
02992 template<class SI_CHAR>
02993 class SI_ConvertW {
02994 const char * m_pEncoding;
02995 UConverter * m_pConverter;
02996 protected:
02997 SI_ConvertW() : m_pEncoding(NULL), m_pConverter(NULL) { }
02998 public:
02999 SI_ConvertW(bool a_bStoreIsUtf8) : m_pConverter(NULL) {
03000 m_pEncoding = a_bStoreIsUtf8 ? "UTF-8" : NULL;
03001 }
03002
03003
03004 SI_ConvertW(const SI_ConvertW & rhs) { operator=(rhs); }
03005 SI_ConvertW & operator=(const SI_ConvertW & rhs) {
03006 m_pEncoding = rhs.m_pEncoding;
03007 m_pConverter = NULL;
03008 return *this;
03009 }
03010 ~SI_ConvertW() { if (m_pConverter) ucnv_close(m_pConverter); }
03011
03025 size_t SizeFromStore(
03026 const char * a_pInputData,
03027 size_t a_uInputDataLen)
03028 {
03029 SI_ASSERT(a_uInputDataLen != (size_t) -1);
03030
03031 UErrorCode nError;
03032
03033 if (!m_pConverter) {
03034 nError = U_ZERO_ERROR;
03035 m_pConverter = ucnv_open(m_pEncoding, &nError);
03036 if (U_FAILURE(nError)) {
03037 return (size_t) -1;
03038 }
03039 }
03040
03041 nError = U_ZERO_ERROR;
03042 int32_t nLen = ucnv_toUChars(m_pConverter, NULL, 0,
03043 a_pInputData, (int32_t) a_uInputDataLen, &nError);
03044 if (U_FAILURE(nError) && nError != U_BUFFER_OVERFLOW_ERROR) {
03045 return (size_t) -1;
03046 }
03047
03048 return (size_t) nLen;
03049 }
03050
03064 bool ConvertFromStore(
03065 const char * a_pInputData,
03066 size_t a_uInputDataLen,
03067 UChar * a_pOutputData,
03068 size_t a_uOutputDataSize)
03069 {
03070 UErrorCode nError;
03071
03072 if (!m_pConverter) {
03073 nError = U_ZERO_ERROR;
03074 m_pConverter = ucnv_open(m_pEncoding, &nError);
03075 if (U_FAILURE(nError)) {
03076 return false;
03077 }
03078 }
03079
03080 nError = U_ZERO_ERROR;
03081 ucnv_toUChars(m_pConverter,
03082 a_pOutputData, (int32_t) a_uOutputDataSize,
03083 a_pInputData, (int32_t) a_uInputDataLen, &nError);
03084 if (U_FAILURE(nError)) {
03085 return false;
03086 }
03087
03088 return true;
03089 }
03090
03101 size_t SizeToStore(
03102 const UChar * a_pInputData)
03103 {
03104 UErrorCode nError;
03105
03106 if (!m_pConverter) {
03107 nError = U_ZERO_ERROR;
03108 m_pConverter = ucnv_open(m_pEncoding, &nError);
03109 if (U_FAILURE(nError)) {
03110 return (size_t) -1;
03111 }
03112 }
03113
03114 nError = U_ZERO_ERROR;
03115 int32_t nLen = ucnv_fromUChars(m_pConverter, NULL, 0,
03116 a_pInputData, -1, &nError);
03117 if (U_FAILURE(nError) && nError != U_BUFFER_OVERFLOW_ERROR) {
03118 return (size_t) -1;
03119 }
03120
03121 return (size_t) nLen + 1;
03122 }
03123
03137 bool ConvertToStore(
03138 const UChar * a_pInputData,
03139 char * a_pOutputData,
03140 size_t a_uOutputDataSize)
03141 {
03142 UErrorCode nError;
03143
03144 if (!m_pConverter) {
03145 nError = U_ZERO_ERROR;
03146 m_pConverter = ucnv_open(m_pEncoding, &nError);
03147 if (U_FAILURE(nError)) {
03148 return false;
03149 }
03150 }
03151
03152 nError = U_ZERO_ERROR;
03153 ucnv_fromUChars(m_pConverter,
03154 a_pOutputData, (int32_t) a_uOutputDataSize,
03155 a_pInputData, -1, &nError);
03156 if (U_FAILURE(nError)) {
03157 return false;
03158 }
03159
03160 return true;
03161 }
03162 };
03163
03164 #endif // SI_CONVERT_ICU
03165
03166
03167
03168
03169
03170 #ifdef SI_CONVERT_WIN32
03171
03172 #define SI_Case SI_GenericCase
03173
03174
03175 #ifdef _WIN32_WCE
03176 # ifndef SI_NO_MBCS
03177 # define SI_NO_MBCS
03178 # endif
03179 #endif
03180
03181 #include <windows.h>
03182 #ifdef SI_NO_MBCS
03183 # define SI_NoCase SI_GenericNoCase
03184 #else // !SI_NO_MBCS
03185
03193 #include <mbstring.h>
03194 template<class SI_CHAR>
03195 struct SI_NoCase {
03196 bool operator()(const SI_CHAR * pLeft, const SI_CHAR * pRight) const {
03197 if (sizeof(SI_CHAR) == sizeof(char)) {
03198 return _mbsicmp((const unsigned char *)pLeft,
03199 (const unsigned char *)pRight) < 0;
03200 }
03201 if (sizeof(SI_CHAR) == sizeof(wchar_t)) {
03202 return _wcsicmp((const wchar_t *)pLeft,
03203 (const wchar_t *)pRight) < 0;
03204 }
03205 return SI_GenericNoCase<SI_CHAR>()(pLeft, pRight);
03206 }
03207 };
03208 #endif // SI_NO_MBCS
03209
03216 template<class SI_CHAR>
03217 class SI_ConvertW {
03218 UINT m_uCodePage;
03219 protected:
03220 SI_ConvertW() { }
03221 public:
03222 SI_ConvertW(bool a_bStoreIsUtf8) {
03223 m_uCodePage = a_bStoreIsUtf8 ? CP_UTF8 : CP_ACP;
03224 }
03225
03226
03227 SI_ConvertW(const SI_ConvertW & rhs) { operator=(rhs); }
03228 SI_ConvertW & operator=(const SI_ConvertW & rhs) {
03229 m_uCodePage = rhs.m_uCodePage;
03230 return *this;
03231 }
03232
03246 size_t SizeFromStore(
03247 const char * a_pInputData,
03248 size_t a_uInputDataLen)
03249 {
03250 SI_ASSERT(a_uInputDataLen != (size_t) -1);
03251
03252 int retval = MultiByteToWideChar(
03253 m_uCodePage, 0,
03254 a_pInputData, (int) a_uInputDataLen,
03255 0, 0);
03256 return (size_t)(retval > 0 ? retval : -1);
03257 }
03258
03272 bool ConvertFromStore(
03273 const char * a_pInputData,
03274 size_t a_uInputDataLen,
03275 SI_CHAR * a_pOutputData,
03276 size_t a_uOutputDataSize)
03277 {
03278 int nSize = MultiByteToWideChar(
03279 m_uCodePage, 0,
03280 a_pInputData, (int) a_uInputDataLen,
03281 (wchar_t *) a_pOutputData, (int) a_uOutputDataSize);
03282 return (nSize > 0);
03283 }
03284
03295 size_t SizeToStore(
03296 const SI_CHAR * a_pInputData)
03297 {
03298 int retval = WideCharToMultiByte(
03299 m_uCodePage, 0,
03300 (const wchar_t *) a_pInputData, -1,
03301 0, 0, 0, 0);
03302 return (size_t) (retval > 0 ? retval : -1);
03303 }
03304
03318 bool ConvertToStore(
03319 const SI_CHAR * a_pInputData,
03320 char * a_pOutputData,
03321 size_t a_uOutputDataSize)
03322 {
03323 int retval = WideCharToMultiByte(
03324 m_uCodePage, 0,
03325 (const wchar_t *) a_pInputData, -1,
03326 a_pOutputData, (int) a_uOutputDataSize, 0, 0);
03327 return retval > 0;
03328 }
03329 };
03330
03331 #endif // SI_CONVERT_WIN32
03332
03333
03334
03335
03336
03337
03338 typedef CSimpleIniTempl<char,
03339 SI_NoCase<char>,SI_ConvertA<char> > CSimpleIniA;
03340 typedef CSimpleIniTempl<char,
03341 SI_Case<char>,SI_ConvertA<char> > CSimpleIniCaseA;
03342
03343 #if defined(SI_CONVERT_ICU)
03344 typedef CSimpleIniTempl<UChar,
03345 SI_NoCase<UChar>,SI_ConvertW<UChar> > CSimpleIniW;
03346 typedef CSimpleIniTempl<UChar,
03347 SI_Case<UChar>,SI_ConvertW<UChar> > CSimpleIniCaseW;
03348 #else
03349 typedef CSimpleIniTempl<wchar_t,
03350 SI_NoCase<wchar_t>,SI_ConvertW<wchar_t> > CSimpleIniW;
03351 typedef CSimpleIniTempl<wchar_t,
03352 SI_Case<wchar_t>,SI_ConvertW<wchar_t> > CSimpleIniCaseW;
03353 #endif
03354
03355 #ifdef _UNICODE
03356 # define CSimpleIni CSimpleIniW
03357 # define CSimpleIniCase CSimpleIniCaseW
03358 # define SI_NEWLINE SI_NEWLINE_W
03359 #else // !_UNICODE
03360 # define CSimpleIni CSimpleIniA
03361 # define CSimpleIniCase CSimpleIniCaseA
03362 # define SI_NEWLINE SI_NEWLINE_A
03363 #endif // _UNICODE
03364
03365 #ifdef _MSC_VER
03366 # pragma warning (pop)
03367 #endif
03368
03369 #endif // INCLUDED_SimpleIni_h
03370