• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AddName(UStringVector & strings,UString & s)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 
ReadNamesFromListFile2(CFSTR fileName,UStringVector & strings,UINT codePage,DWORD & lastError)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