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