1 // Common/Lang.cpp 2 3 #include "StdAfx.h" 4 5 #include "Lang.h" 6 #include "StringToInt.h" 7 #include "UTFConvert.h" 8 9 #include "../Windows/FileIO.h" 10 Clear()11void CLang::Clear() throw() 12 { 13 _ids.Clear(); 14 _offsets.Clear(); 15 delete []_text; 16 _text = 0; 17 } 18 19 static const char * const kLangSignature = ";!@Lang2@!UTF-8!"; 20 OpenFromString(const AString & s2)21bool CLang::OpenFromString(const AString &s2) 22 { 23 UString s; 24 if (!ConvertUTF8ToUnicode(s2, s)) 25 return false; 26 unsigned i = 0; 27 if (s.IsEmpty()) 28 return false; 29 if (s[0] == 0xFEFF) 30 i++; 31 32 for (const char *p = kLangSignature;; i++) 33 { 34 Byte c = (Byte)(*p++); 35 if (c == 0) 36 break; 37 if (s[i] != c) 38 return false; 39 } 40 41 _text = new wchar_t[s.Len() - i + 1]; 42 wchar_t *text = _text; 43 44 Int32 id = -100; 45 UInt32 pos = 0; 46 47 while (i < s.Len()) 48 { 49 unsigned start = pos; 50 do 51 { 52 wchar_t c = s[i++]; 53 if (c == '\n') 54 break; 55 if (c == '\\') 56 { 57 if (i == s.Len()) 58 return false; 59 c = s[i++]; 60 switch (c) 61 { 62 case '\n': return false; 63 case 'n': c = '\n'; break; 64 case 't': c = '\t'; break; 65 case '\\': c = '\\'; break; 66 default: text[pos++] = L'\\'; break; 67 } 68 } 69 text[pos++] = c; 70 } 71 while (i < s.Len()); 72 73 { 74 unsigned j = start; 75 for (; j < pos; j++) 76 if (text[j] != ' ') 77 break; 78 if (j == pos) 79 { 80 id++; 81 continue; 82 } 83 } 84 if (text[start] == ';') 85 { 86 pos = start; 87 id++; 88 continue; 89 } 90 91 text[pos++] = 0; 92 const wchar_t *end; 93 UInt32 id32 = ConvertStringToUInt32(text + start, &end); 94 if (*end == 0) 95 { 96 if (id32 > ((UInt32)1 << 30) || (Int32)id32 < id) 97 return false; 98 id = (Int32)id32; 99 pos = start; 100 continue; 101 } 102 103 if (id < 0) 104 return false; 105 _ids.Add((UInt32)id++); 106 _offsets.Add(start); 107 } 108 109 return true; 110 } 111 Open(CFSTR fileName,const char * id)112bool CLang::Open(CFSTR fileName, const char *id) 113 { 114 Clear(); 115 NWindows::NFile::NIO::CInFile file; 116 if (!file.Open(fileName)) 117 return false; 118 UInt64 length; 119 if (!file.GetLength(length)) 120 return false; 121 if (length > (1 << 20)) 122 return false; 123 124 AString s; 125 const unsigned len = (unsigned)length; 126 char *p = s.GetBuf(len); 127 size_t processed; 128 if (!file.ReadFull(p, len, processed)) 129 return false; 130 file.Close(); 131 if (len != processed) 132 return false; 133 134 char *p2 = p; 135 for (unsigned i = 0; i < len; i++) 136 { 137 char c = p[i]; 138 if (c == 0) 139 break; 140 if (c != 0x0D) 141 *p2++ = c; 142 } 143 *p2 = 0; 144 s.ReleaseBuf_SetLen((unsigned)(p2 - p)); 145 146 if (OpenFromString(s)) 147 { 148 const wchar_t *name = Get(0); 149 if (name && StringsAreEqual_Ascii(name, id)) 150 return true; 151 } 152 153 Clear(); 154 return false; 155 } 156 Get(UInt32 id) const157const wchar_t *CLang::Get(UInt32 id) const throw() 158 { 159 int index = _ids.FindInSorted(id); 160 if (index < 0) 161 return NULL; 162 return _text + (size_t)_offsets[(unsigned)index]; 163 } 164