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
14static const char kQuoteChar = '\"';
15
16static 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
28bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage)
29{
30  NWindows::NFile::NIO::CInFile file;
31  if (!file.Open(fileName))
32    return false;
33  UInt64 fileSize;
34  if (!file.GetLength(fileSize))
35    return false;
36  if (fileSize >= ((UInt32)1 << 31) - 32)
37    return false;
38  UString u;
39  if (codePage == MY__CP_UTF16 || codePage == MY__CP_UTF16BE)
40  {
41    if ((fileSize & 1) != 0)
42      return false;
43    CByteArr buf((size_t)fileSize);
44    UInt32 processed;
45    if (!file.Read(buf, (UInt32)fileSize, processed))
46      return false;
47    if (processed != fileSize)
48      return false;
49    file.Close();
50    unsigned num = (unsigned)fileSize / 2;
51    wchar_t *p = u.GetBuf(num);
52    if (codePage == MY__CP_UTF16)
53      for (unsigned i = 0; i < num; i++)
54      {
55        wchar_t c = GetUi16(buf + i * 2);
56        if (c == 0)
57          return false;
58        p[i] = c;
59      }
60    else
61      for (unsigned i = 0; i < num; i++)
62      {
63        wchar_t c = (wchar_t)GetBe16(buf + i * 2);
64        if (c == 0)
65          return false;
66        p[i] = c;
67      }
68    p[num] = 0;
69    u.ReleaseBuf_SetLen(num);
70  }
71  else
72  {
73    AString s;
74    char *p = s.GetBuf((unsigned)fileSize);
75    UInt32 processed;
76    if (!file.Read(p, (UInt32)fileSize, processed))
77      return false;
78    if (processed != fileSize)
79      return false;
80    file.Close();
81    s.ReleaseBuf_CalcLen((unsigned)processed);
82    if (s.Len() != processed)
83      return false;
84
85    // #ifdef CP_UTF8
86    if (codePage == CP_UTF8)
87    {
88      if (!ConvertUTF8ToUnicode(s, u))
89        return false;
90    }
91    else
92    // #endif
93      MultiByteToUnicodeString2(u, s, codePage);
94  }
95
96  const wchar_t kGoodBOM = 0xFEFF;
97  const wchar_t kBadBOM  = 0xFFFE;
98
99  UString s;
100  unsigned i = 0;
101  for (; i < u.Len() && u[i] == kGoodBOM; i++);
102  for (; i < u.Len(); i++)
103  {
104    wchar_t c = u[i];
105    if (c == kGoodBOM || c == kBadBOM)
106      return false;
107    if (c == L'\n' || c == 0xD)
108    {
109      AddName(strings, s);
110      s.Empty();
111    }
112    else
113      s += c;
114  }
115  AddName(strings, s);
116  return true;
117}
118