00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "precomp.h"
00028 #include "FileIni.h"
00029
00030 #include <vector>
00031 #include <tchar.h>
00032 #include <io.h>
00033 #include <fcntl.h>
00034
00036 typedef std::vector<int> INTARRAY;
00037 typedef std::vector<std::tstring::size_type> SIZETARRAY;
00038
00046 void TrimLen(const WCHAR* pStr, std::tstring::size_type& nLen, bool bSpace, bool bUnicode)
00047 {
00048
00049 if (bUnicode)
00050 {
00051 while ((nLen > 0) && (wcschr(bSpace ? L" \t\n\r" : L"\n\r", pStr[nLen-1]) != NULL))
00052 nLen--;
00053 }
00054 else
00055 {
00056 while ((nLen > 0) && (strchr(bSpace ? " \t\n\r" : "\n\r", ((const char*)pStr)[nLen-1]) != NULL))
00057 nLen--;
00058 }
00059 }
00060
00066 std::tstring Trim(const WCHAR* pStr, std::tstring::size_type nLen, bool bUnicode)
00067 {
00068 std::tstring sRet;
00069 if (bUnicode)
00070 sRet = MakeTString(std::wstring(pStr, nLen));
00071 else
00072 sRet = MakeTString(std::string((const char*)pStr, nLen));
00073
00074
00075 if (sRet.empty())
00076 return sRet;
00077
00078
00079 std::tstring::size_type pos = sRet.find_last_not_of(_T(" \t\n\r"));
00080 if (pos != std::tstring::npos)
00081 {
00082 pos++;
00083 if (pos < sRet.size())
00084 sRet.erase(pos);
00085 }
00086
00087 pos = sRet.find_first_not_of(_T(" \t\n\r"));
00088 if (pos != std::tstring::npos)
00089 sRet.erase(0, pos);
00090
00091 return sRet;
00092 }
00093
00099 std::wstring Trim(const WCHAR* pStr, std::tstring::size_type nLen)
00100 {
00101
00102 if (nLen == 0)
00103 return L"";
00104
00105 while ((nLen > 0) && (wcschr(L" \t\n\r", *pStr) != NULL))
00106 {
00107 pStr++;
00108 nLen--;
00109 }
00110
00111
00112 while ((nLen > 0) && (wcschr(L" \t\n\r", pStr[nLen-1]) != NULL))
00113 nLen--;
00114
00115
00116 if (nLen == 0)
00117 return L"";
00118 else
00119 return std::wstring(pStr, nLen);
00120 }
00121
00126 std::tstring Trim(const std::string& s)
00127 {
00128 return Trim((const WCHAR*)s.c_str(), s.size(), false);
00129 }
00130
00135 std::tstring Trim(const std::wstring& s)
00136 {
00137 return Trim(s.c_str(), s.size(), true);
00138 }
00139
00147 bool IsComment(const WCHAR* pStr, std::tstring::size_type nLen, bool bUnicode)
00148 {
00149
00150 if (nLen < 2)
00151 return false;
00152
00153 return bUnicode ? ((pStr[0] == '/') && (pStr[1] == '/')) : ((((char*)pStr)[0] == (char)'/') && (((char*)pStr)[1] == (char)'/'));
00154 }
00155
00161 void FindNextLine(const WCHAR*& pLine, std::tstring::size_type nLen, bool bUnicode)
00162 {
00163
00164 if (bUnicode)
00165 {
00166
00167 pLine += nLen;
00168 while ((*pLine != '\0') && (wcschr(L"\r\n", *pLine) != NULL))
00169 pLine++;
00170 return;
00171 }
00172
00173
00174 const char* pNext = (const char*)pLine;
00175 pNext += nLen;
00176 while ((*pNext != '\0') && (strchr("\r\n", *pNext) != NULL))
00177 pNext++;
00178
00179 pLine = (const WCHAR*)pNext;
00180 }
00181
00182
00183
00189 FileINI::FileINI(char* pData, DWORD dwSize, bool bOwn ) : m_bUnicode(false), m_nOffset(0)
00190 {
00191
00192 if (pData == NULL)
00193 {
00194
00195 m_pData = NULL;
00196 m_bOwn = false;
00197 return;
00198 }
00199
00200
00201 if (pData[dwSize-1] == '\0')
00202 {
00203
00204 m_pData = pData;
00205 m_bOwn = bOwn;
00206 }
00207 else
00208 {
00209
00210 m_pData = new char[dwSize + 1];
00211 memcpy(m_pData, pData, dwSize);
00212 m_pData[dwSize] = (char)'\0';
00213 m_bOwn = true;
00214 if (bOwn)
00215
00216 delete [] pData;
00217 }
00218
00219 m_bUnicode = TestUnicode();
00220 if (m_bUnicode)
00221 m_nOffset = 2;
00222 }
00223
00230 FileINI::FileINI(bool bUnicode, char* pData, DWORD dwSize, bool bOwn ) : m_bUnicode(bUnicode), m_nOffset(0)
00231 {
00232 if (pData == NULL)
00233 {
00234 m_pData = NULL;
00235 m_bOwn = false;
00236 return;
00237 }
00238
00239
00240 if ((pData[dwSize-1] == (char)'\0') && (!bUnicode || (pData[dwSize-2] == (char)'\0')))
00241 {
00242
00243 m_pData = pData;
00244 m_bOwn = bOwn;
00245 }
00246 else
00247 {
00248
00249 m_pData = new char[dwSize + 2];
00250 memcpy(m_pData, pData, dwSize);
00251
00252 m_pData[dwSize] = (char)'\0';
00253 m_pData[dwSize + 1] = (char)'\0';
00254 m_bOwn = true;
00255 if (bOwn)
00256
00257 delete [] pData;
00258 }
00259 }
00260
00264 FileINI::FileINI(LPCTSTR lpFilename) : m_pData(NULL), m_bOwn(false), m_bUnicode(false), m_nOffset(0)
00265 {
00266
00267 LoadINIFile(lpFilename);
00268 }
00269
00274 bool FileINI::LoadINIFile(LPCTSTR lpFilename)
00275 {
00276
00277 FILE* pFile;
00278 if (NULL != _tfopen_s(&pFile, lpFilename, _T("rt")))
00279 return false;
00280
00281
00282 if ((m_pData != NULL) && m_bOwn)
00283 {
00284 delete [] m_pData;
00285 m_pData = NULL;
00286 }
00287
00288
00289 fseek(pFile, 0, SEEK_END);
00290 long lSize = ftell(pFile);
00291 std::tstring::size_type lReadSize;
00292 fseek(pFile, 0, SEEK_SET);
00293
00294
00295 m_pData = new char[(lSize + 1) * 2];
00296 m_bOwn = true;
00297
00298
00299 lReadSize = fread(m_pData, 1, lSize, pFile);
00300 fclose(pFile);
00301
00302
00303 m_pData[lReadSize] = (char)'\0';
00304 m_pData[lReadSize+1] = (char)'\0';
00305
00306
00307 m_bUnicode = TestUnicode();
00308 if (m_bUnicode)
00309 m_nOffset = 2;
00310
00311 return true;
00312 }
00313
00318 bool FileINI::TestUnicode(FILE* pFile)
00319 {
00320
00321 char c[2];
00322 long lSize = (long)fread(c, sizeof(char), 2, pFile);
00323
00324 if (lSize < 2)
00325 {
00326 if (lSize > 0)
00327 fseek(pFile, -lSize, SEEK_CUR);
00328
00329 return false;
00330 }
00331
00332
00333 if ((c[0] == (char)0xFF) && (c[1] == (char)0xFE))
00334 {
00335
00336 _setmode(_fileno(pFile), _O_BINARY);
00337 return true;
00338 }
00339
00340 fseek(pFile, -2, SEEK_CUR);
00341 return false;
00342 }
00343
00347 bool FileINI::TestUnicode()
00348 {
00349 if (m_pData == NULL)
00350 return false;
00351 return ((m_pData[0] == (char)0xFF) && (m_pData[1] == (char)0xFE));
00352 }
00353
00363 bool FileINI::GetLines(LPCTSTR pFilename, LPCTSTR pSection, TCHARSTRLIST& listLines, UINT uFlags)
00364 {
00365
00366 FILE* pFile;
00367 if (NULL != _tfopen_s(&pFile, pFilename, _T("rt")))
00368 return false;
00369
00370
00371 bool bUnicode = TestUnicode(pFile);
00372
00373
00374 bool bFoundSection = false, bFoundSectionNow;
00375 WCHAR c[MAX_PATH + 1];
00376 std::tstring::size_type nLen, nSectionLen = _tcslen(pSection);
00377
00378
00379 while (!feof(pFile))
00380 {
00381
00382 if (bUnicode)
00383 {
00384
00385 if (fgetws(c, MAX_PATH, pFile) == NULL)
00386 break;
00387
00388
00389 nLen = wcslen(c);
00390 }
00391 else
00392 {
00393
00394 if (fgets((char*)c, MAX_PATH, pFile) == NULL)
00395 break;
00396
00397
00398 nLen = strlen((char*)c);
00399 }
00400
00401
00402 TrimLen(c, nLen, (uFlags & FILEINI_TRIM) != 0, bUnicode);
00403
00404 if (nLen < 1)
00405 continue;
00406
00407
00408 bFoundSectionNow = CheckLineForSection(c, nLen, pSection, nSectionLen, bUnicode, bFoundSection);
00409 if (bFoundSection && !bFoundSectionNow)
00410 {
00411
00412 if ((uFlags & FILEINI_IGNORE_COMMENTS) && IsComment(c, nLen, bUnicode))
00413 continue;
00414 if (uFlags & FILEINI_TRIM)
00415 {
00416
00417 std::tstring s = Trim(c, nLen, bUnicode);
00418 if (!s.empty())
00419
00420 listLines.push_back(s);
00421 }
00422 else
00423 {
00424
00425 if (bUnicode)
00426 listLines.push_back(MakeTString(std::wstring(c, nLen)));
00427 else
00428 listLines.push_back(MakeTString(std::string((const char*)c, nLen)));
00429 }
00430 }
00431 }
00432
00433
00434 fclose(pFile);
00435 return true;
00436 }
00437
00447 bool FileINI::GetKeys(LPCTSTR pFilename, LPCTSTR pSection, INILINELIST& listLines, UINT uFlags)
00448 {
00449
00450 FILE* pFile;
00451 if (NULL != _tfopen_s(&pFile, pFilename, _T("rt")))
00452 return false;
00453
00454
00455 bool bUnicode = TestUnicode(pFile);
00456
00457
00458 bool bFoundSection = false, bFoundSectionNow;
00459 WCHAR c[MAX_PATH+1];
00460 std::tstring::size_type nLen, nSectionLen = _tcslen(pSection);
00461
00462
00463 while (!feof(pFile))
00464 {
00465
00466 if (bUnicode)
00467 {
00468
00469 if (fgetws(c, MAX_PATH, pFile) == NULL)
00470 break;
00471
00472
00473 nLen = wcslen(c);
00474 }
00475 else
00476 {
00477
00478 if (fgets((char*)c, MAX_PATH, pFile) == NULL)
00479 break;
00480
00481
00482 nLen = strlen((char*)c);
00483 }
00484
00485
00486 TrimLen(c, nLen, (uFlags & FILEINI_TRIM) != 0, bUnicode);
00487
00488 if (nLen < 1)
00489 continue;
00490
00491
00492 bFoundSectionNow = CheckLineForSection(c, nLen, pSection, nSectionLen, bUnicode, bFoundSection);
00493 if (bFoundSection && !bFoundSectionNow)
00494
00495 DoInitLine(c, nLen, listLines, uFlags, bUnicode);
00496 }
00497
00498
00499 fclose(pFile);
00500 return true;
00501 }
00502
00512 bool FileINI::CheckLineForSection(const WCHAR* pLine, std::tstring::size_type nLineLen, LPCTSTR pSection, std::tstring::size_type nSectionLen, bool bUnicode, bool& bFoundSection)
00513 {
00514
00515 std::tstring sLine;
00516 if (bUnicode)
00517 sLine = MakeTString(std::wstring(pLine, nLineLen));
00518 else
00519 sLine = MakeTString(std::string((const char*)pLine, nLineLen));
00520
00521
00522 if ((sLine[0] != '[') || (sLine[nLineLen-1] != ']'))
00523
00524 return false;
00525
00526 if (nLineLen != nSectionLen + 2)
00527 bFoundSection = false;
00528 else
00529 bFoundSection = _tcsnicmp(pSection, sLine.c_str() + 1, nSectionLen) == 0;
00530
00531
00532 return bFoundSection;
00533 }
00534
00542 void FileINI::DoInitLine(const WCHAR* pLine, std::tstring::size_type nLineLen, INILINELIST& listLines, UINT uFlags, bool bUnicode)
00543 {
00544
00545 if ((uFlags & FILEINI_IGNORE_COMMENTS) && IsComment(pLine, nLineLen, bUnicode))
00546 return;
00547
00548
00549 std::tstring sLine;
00550 if (bUnicode)
00551 sLine = MakeTString(std::wstring(pLine, nLineLen));
00552 else
00553 sLine = MakeTString(std::string((const char*)pLine, nLineLen));
00554
00555
00556 std::tstring::size_type nPos = sLine.find('=');
00557 std::tstring sBefore, sAfter;
00558 if (nPos == std::tstring::npos)
00559 {
00560
00561 sBefore = sLine;
00562 sAfter = _T("");
00563 }
00564 else
00565 {
00566
00567 sBefore = sLine.substr(0, nPos);
00568 sAfter = sLine.substr(nPos + 1);
00569 }
00570
00571
00572 if (uFlags & FILEINI_TRIM)
00573 {
00574 sBefore = Trim(sBefore);
00575 sAfter = Trim(sAfter);
00576 }
00577
00578 listLines.push_back(INILine(sBefore, sAfter));
00579 }
00580
00588 bool FileINI::GetKeys(LPCTSTR pFilename, LPCTSTR pSection, TCHARSTR2STR& mapKeys, UINT uFlags)
00589 {
00590
00591 INILINELIST listLines;
00592 if (!GetKeys(pFilename, pSection, listLines, uFlags))
00593 return false;
00594
00595
00596 for (INILINELIST::iterator i = listLines.begin(); i != listLines.end(); i++)
00597 mapKeys[(*i).sKey] = (*i).sValue;
00598
00599 return true;
00600 }
00601
00612 bool FileINI::GetVarValues(LPCTSTR pVarValue, TCHARSTRLIST& lValues)
00613 {
00614
00615 lValues.clear();
00616 std::tstring sValue, sVarValue = Trim(std::tstring(pVarValue, _tcslen(pVarValue)));
00617
00618 bool bQuote;
00619 std::tstring::size_type nLen;
00620
00621
00622 while (!sVarValue.empty())
00623 {
00624
00625 if (sVarValue[0] == (TCHAR)'"')
00626 {
00627
00628 bQuote = true;
00629
00630
00631 sVarValue.erase(sVarValue.begin());
00632
00633
00634 if (sVarValue.empty())
00635 return false;
00636 }
00637 else
00638
00639 bQuote = false;
00640
00641
00642 nLen = 0;
00643 while (nLen < sVarValue.size())
00644 {
00645 if (bQuote && (sVarValue[nLen] == (TCHAR)'"'))
00646
00647 break;
00648 if (!bQuote && (sVarValue[nLen] == (TCHAR)','))
00649
00650 break;
00651 nLen++;
00652 }
00653
00654
00655 if (nLen == sVarValue.size())
00656 {
00657 if (bQuote)
00658
00659 return false;
00660
00661
00662 sValue = sVarValue;
00663 sVarValue = _T("");
00664 }
00665 else
00666 {
00667
00668 sValue = sVarValue.substr(0, nLen-1);
00669
00670 sVarValue.erase(0, nLen);
00671 if (!sVarValue.empty() && (sVarValue[0] != ','))
00672
00673 return false;
00674 }
00675
00676
00677 if (!sValue.empty())
00678 lValues.push_back(sValue);
00679 }
00680 return true;
00681 }
00682
00690 bool ReplaceVariables(LPCTSTR pValue, const TCHARSTR2STRLIST& lVariables, TCHARSTR2STRLIST::const_iterator& iPos, TCHARSTRLIST& lResults)
00691 {
00692
00693 TCHAR* pLoc;
00694 while ((iPos != lVariables.end()) && ((pLoc = (TCHAR*)_tcsstr(pValue, (*iPos).first.c_str())) == NULL))
00695 iPos++;
00696
00697 if (iPos == lVariables.end())
00698 {
00699
00700 lResults.push_back(pValue);
00701 return true;
00702 }
00703
00704 SIZETARRAY ar;
00705 std::tstring sRet = pValue;
00706
00707
00708 std::tstring::size_type nPos = (pLoc - pValue), nLen = (*iPos).first.size();
00709 ar.push_back(nPos);
00710 while ((nPos = sRet.find((*iPos).first.c_str(), nPos + nLen)) != std::string::npos)
00711 ar.push_back(nPos);
00712
00713
00714 TCHARSTR2STRLIST::const_iterator iWork = iPos;
00715 iPos++;
00716
00717
00718 for (TCHARSTRLIST::const_iterator i = (*iWork).second.begin(); i != (*iWork).second.end(); i++)
00719 {
00720
00721 sRet = pValue;
00722 for (SIZETARRAY::iterator j = ar.begin(); j != ar.end(); j++)
00723 sRet.replace((*j), nLen, (*i).c_str());
00724
00725
00726 if (!ReplaceVariables(sRet.c_str(), lVariables, iPos, lResults))
00727 return false;
00728 }
00729 return true;
00730 }
00731
00738 bool FileINI::ReplaceVariables(LPCTSTR pValue, const TCHARSTR2STRLIST& lVariables, TCHARSTRLIST& lResults)
00739 {
00740 return ::ReplaceVariables(pValue, lVariables, lVariables.begin(), lResults);
00741 }
00742
00748 bool FileINI::GetAllSections(LPCTSTR pFilename, TCHARSTRLIST& lSections)
00749 {
00750
00751 FILE* pFile;
00752 if (NULL != _tfopen_s (&pFile, pFilename, _T("rt")))
00753 return false;
00754
00755
00756 bool bUnicode = TestUnicode(pFile);
00757
00758
00759 WCHAR c[MAX_PATH+1];
00760 std::tstring::size_type nLen;
00761
00762
00763 while (!feof(pFile))
00764 {
00765
00766 if (bUnicode)
00767 {
00768
00769 if (fgetws(c, MAX_PATH, pFile) == NULL)
00770 break;
00771
00772
00773 nLen = wcslen(c);
00774 }
00775 else
00776 {
00777
00778 if (fgets((char*)c, MAX_PATH, pFile) == NULL)
00779 break;
00780
00781
00782 nLen = strlen((char*)c);
00783 }
00784
00785
00786 TrimLen(c, nLen, true, bUnicode);
00787
00788
00789 if (nLen < 1)
00790 continue;
00791
00792 if (bUnicode)
00793 {
00794
00795 if ((c[0] == '[') && (c[nLen-1] == ']'))
00796
00797 lSections.push_back(MakeTString(std::wstring(c+1, nLen-2)));
00798 }
00799 else
00800 {
00801
00802 if ((((char*)c)[0] == (char)'[') && (((char*)c)[nLen-1] == (char)']'))
00803
00804 lSections.push_back(MakeTString(std::string(((char*)c)+1, nLen-2)));
00805 }
00806 }
00807
00808
00809 fclose(pFile);
00810 return true;
00811 }
00812
00817 bool FileINI::GetAllSections(TCHARSTRLIST& lSections)
00818 {
00819
00820 bool bFoundSection = false;
00821 std::tstring::size_type nLen, nLineLen;
00822 const WCHAR* pLine = (const WCHAR*)(m_pData + m_nOffset);
00823 std::tstring s;
00824
00825
00826 do
00827 {
00828
00829 if (m_bUnicode)
00830 nLen = wcscspn(pLine, L"\r\n");
00831 else
00832 nLen = strcspn((const char*)pLine, "\r\n");
00833
00834
00835 if (nLen > 0)
00836 {
00837
00838 nLineLen = nLen;
00839 TrimLen(pLine, nLineLen, true, m_bUnicode);
00840
00841 if (nLineLen > 1)
00842 {
00843
00844 if (m_bUnicode)
00845 {
00846 if ((pLine[0] == '[') && (pLine[nLen-1] == ']'))
00847 lSections.push_back(MakeTString(std::wstring(pLine+1, nLen-2)));
00848 }
00849 else
00850 {
00851 if ((((char*)pLine)[0] == (char)'[') && (((char*)pLine)[nLen-1] == (char)']'))
00852 lSections.push_back(MakeTString(std::string(((char*)pLine)+1, nLen-2)));
00853 }
00854 }
00855 }
00856
00857 FindNextLine(pLine, nLen, m_bUnicode);
00858 } while (m_bUnicode ? ((*pLine) != '\0') : ((*((const char*)pLine)) != (char)'\0'));
00859
00860 return true;
00861 }
00862
00869 bool FileINI::GetKeys(LPCTSTR pSection, TCHARSTR2STR& mapKeys, UINT uFlags)
00870 {
00871
00872 INILINELIST listLines;
00873 if (!GetKeys(pSection, listLines, uFlags))
00874 return false;
00875
00876
00877 for (INILINELIST::iterator i = listLines.begin(); i != listLines.end(); i++)
00878 mapKeys[(*i).sKey] = (*i).sValue;
00879
00880 return true;
00881 }
00882
00889 bool FileINI::GetKeys(LPCTSTR pSection, INILINELIST& listLines, UINT uFlags )
00890 {
00891
00892 if (m_pData == NULL)
00893 return false;
00894
00895
00896 bool bFoundSection = false, bFoundSectionNow;
00897 std::tstring::size_type nLen, nLineLen, nSectionLen = _tcslen(pSection);
00898 const WCHAR* pLine = (const WCHAR*)(m_pData + m_nOffset);
00899
00900 do
00901 {
00902
00903 if (m_bUnicode)
00904 nLen = wcscspn(pLine, L"\r\n");
00905 else
00906 nLen = strcspn((const char*)pLine, "\r\n");
00907
00908
00909 if (nLen > 0)
00910 {
00911
00912 nLineLen = nLen;
00913 TrimLen(pLine, nLineLen, (uFlags & FILEINI_TRIM) != 0, m_bUnicode);
00914
00915
00916 if (nLineLen > 1)
00917 {
00918
00919 bFoundSectionNow = CheckLineForSection(pLine, nLineLen, pSection, nSectionLen, m_bUnicode, bFoundSection);
00920 if (bFoundSection && !bFoundSectionNow)
00921
00922 DoInitLine(pLine, nLineLen, listLines, uFlags, m_bUnicode);
00923 }
00924 }
00925
00926
00927 FindNextLine(pLine, nLen, m_bUnicode);
00928 } while (m_bUnicode ? ((*pLine) != '\0') : ((*((const char*)pLine)) != (char)'\0'));
00929
00930 return true;
00931 }
00932
00941 bool FileINI::GetLines(LPCTSTR pSection, TCHARSTRLIST& listLines, UINT uFlags )
00942 {
00943
00944 if (m_pData == NULL)
00945 return false;
00946
00947
00948 bool bFoundSection = false, bFoundSectionNow;
00949 std::tstring::size_type nLen, nLineLen, nSectionLen = _tcslen(pSection);
00950 const WCHAR* pLine = (const WCHAR*)(m_pData + m_nOffset);
00951 std::tstring s;
00952
00953
00954 do
00955 {
00956
00957 if (m_bUnicode)
00958 nLen = wcscspn(pLine, L"\r\n");
00959 else
00960 nLen = strcspn((const char*)pLine, "\r\n");
00961
00962
00963 if (nLen > 0)
00964 {
00965
00966 nLineLen = nLen;
00967 TrimLen(pLine, nLineLen, (uFlags & FILEINI_TRIM) != 0, m_bUnicode);
00968
00969
00970 if (nLineLen > 1)
00971 {
00972
00973 bFoundSectionNow = CheckLineForSection(pLine, nLineLen, pSection, nSectionLen, m_bUnicode, bFoundSection);
00974 if (bFoundSection && !bFoundSectionNow)
00975 {
00976
00977 if ((uFlags & FILEINI_IGNORE_COMMENTS) && IsComment(pLine, nLineLen, m_bUnicode))
00978 continue;
00979
00980
00981 if (m_bUnicode)
00982 s = MakeTString(std::wstring(pLine, nLineLen));
00983 else
00984 s = MakeTString(std::string((const char*)pLine, nLineLen));
00985
00986
00987 if (uFlags & FILEINI_TRIM)
00988 s = Trim(s);
00989
00990
00991 if (!s.empty())
00992 listLines.push_back(s);
00993 }
00994 }
00995 }
00996
00997
00998 FindNextLine(pLine, nLen, m_bUnicode);
00999 } while (m_bUnicode ? ((*pLine) != '\0') : ((*((const char*)pLine)) != (char)'\0'));
01000
01001 return true;
01002 }