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 21static 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 34static 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 51bool 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