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