Home | History | Annotate | Download | only in Common
      1 // Common/ListFileUtils.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "../../C/CpuArch.h"
      6 
      7 #include "../Windows/FileIO.h"
      8 
      9 #include "ListFileUtils.h"
     10 #include "MyBuffer.h"
     11 #include "StringConvert.h"
     12 #include "UTFConvert.h"
     13 
     14 static const char kQuoteChar = '\"';
     15 
     16 static void AddName(UStringVector &strings, UString &s)
     17 {
     18   s.Trim();
     19   if (s.Len() >= 2 && s[0] == kQuoteChar && s.Back() == kQuoteChar)
     20   {
     21     s.DeleteBack();
     22     s.Delete(0);
     23   }
     24   if (!s.IsEmpty())
     25     strings.Add(s);
     26 }
     27 
     28 bool ReadNamesFromListFile2(CFSTR fileName, UStringVector &strings, UINT codePage, DWORD &lastError)
     29 {
     30   lastError = 0;
     31   NWindows::NFile::NIO::CInFile file;
     32   if (!file.Open(fileName))
     33   {
     34     lastError = ::GetLastError();
     35     return false;
     36   }
     37   UInt64 fileSize;
     38   if (!file.GetLength(fileSize))
     39   {
     40     lastError = ::GetLastError();
     41     return false;
     42   }
     43   if (fileSize >= ((UInt32)1 << 31) - 32)
     44     return false;
     45   UString u;
     46   if (codePage == MY__CP_UTF16 || codePage == MY__CP_UTF16BE)
     47   {
     48     if ((fileSize & 1) != 0)
     49       return false;
     50     CByteArr buf((size_t)fileSize);
     51     UInt32 processed;
     52     if (!file.Read(buf, (UInt32)fileSize, processed))
     53     {
     54       lastError = ::GetLastError();
     55       return false;
     56     }
     57     if (processed != fileSize)
     58       return false;
     59     file.Close();
     60     unsigned num = (unsigned)fileSize / 2;
     61     wchar_t *p = u.GetBuf(num);
     62     if (codePage == MY__CP_UTF16)
     63       for (unsigned i = 0; i < num; i++)
     64       {
     65         wchar_t c = GetUi16(buf + (size_t)i * 2);
     66         if (c == 0)
     67           return false;
     68         p[i] = c;
     69       }
     70     else
     71       for (unsigned i = 0; i < num; i++)
     72       {
     73         wchar_t c = (wchar_t)GetBe16(buf + (size_t)i * 2);
     74         if (c == 0)
     75           return false;
     76         p[i] = c;
     77       }
     78     p[num] = 0;
     79     u.ReleaseBuf_SetLen(num);
     80   }
     81   else
     82   {
     83     AString s;
     84     char *p = s.GetBuf((unsigned)fileSize);
     85     UInt32 processed;
     86     if (!file.Read(p, (UInt32)fileSize, processed))
     87     {
     88       lastError = ::GetLastError();
     89       return false;
     90     }
     91     if (processed != fileSize)
     92       return false;
     93     file.Close();
     94     s.ReleaseBuf_CalcLen((unsigned)processed);
     95     if (s.Len() != processed)
     96       return false;
     97 
     98     // #ifdef CP_UTF8
     99     if (codePage == CP_UTF8)
    100     {
    101       if (!ConvertUTF8ToUnicode(s, u))
    102         return false;
    103     }
    104     else
    105     // #endif
    106       MultiByteToUnicodeString2(u, s, codePage);
    107   }
    108 
    109   const wchar_t kGoodBOM = 0xFEFF;
    110   const wchar_t kBadBOM  = 0xFFFE;
    111 
    112   UString s;
    113   unsigned i = 0;
    114   for (; i < u.Len() && u[i] == kGoodBOM; i++);
    115   for (; i < u.Len(); i++)
    116   {
    117     wchar_t c = u[i];
    118     if (c == kGoodBOM || c == kBadBOM)
    119       return false;
    120     if (c == '\n' || c == 0xD)
    121     {
    122       AddName(strings, s);
    123       s.Empty();
    124     }
    125     else
    126       s += c;
    127   }
    128   AddName(strings, s);
    129   return true;
    130 }
    131