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