|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "unicpriv.h" |
|
7 #include "nsUnicodeDecodeHelper.h" |
|
8 #include "nsAutoPtr.h" |
|
9 |
|
10 //---------------------------------------------------------------------- |
|
11 // Class nsUnicodeDecodeHelper [implementation] |
|
12 nsresult nsUnicodeDecodeHelper::ConvertByTable( |
|
13 const char * aSrc, |
|
14 int32_t * aSrcLength, |
|
15 char16_t * aDest, |
|
16 int32_t * aDestLength, |
|
17 uScanClassID aScanClass, |
|
18 uShiftInTable * aShiftInTable, |
|
19 uMappingTable * aMappingTable, |
|
20 bool aErrorSignal) |
|
21 { |
|
22 const char * src = aSrc; |
|
23 int32_t srcLen = *aSrcLength; |
|
24 char16_t * dest = aDest; |
|
25 char16_t * destEnd = aDest + *aDestLength; |
|
26 |
|
27 char16_t med; |
|
28 int32_t bcr; // byte count for read |
|
29 nsresult res = NS_OK; |
|
30 |
|
31 while ((srcLen > 0) && (dest < destEnd)) { |
|
32 bool charFound; |
|
33 if (aScanClass == uMultibytesCharset) { |
|
34 NS_ASSERTION(aShiftInTable, "shift table missing"); |
|
35 charFound = uScanShift(aShiftInTable, nullptr, (uint8_t *)src, |
|
36 reinterpret_cast<uint16_t*>(&med), srcLen, |
|
37 (uint32_t *)&bcr); |
|
38 } else { |
|
39 charFound = uScan(aScanClass, nullptr, (uint8_t *)src, |
|
40 reinterpret_cast<uint16_t*>(&med), |
|
41 srcLen, (uint32_t *)&bcr); |
|
42 } |
|
43 if (!charFound) { |
|
44 res = NS_OK_UDEC_MOREINPUT; |
|
45 break; |
|
46 } |
|
47 |
|
48 if (!uMapCode((uTable*) aMappingTable, static_cast<uint16_t>(med), reinterpret_cast<uint16_t*>(dest))) { |
|
49 if (med < 0x20) { |
|
50 // somehow some table miss the 0x00 - 0x20 part |
|
51 *dest = med; |
|
52 } else { |
|
53 if (aErrorSignal) { |
|
54 res = NS_ERROR_ILLEGAL_INPUT; |
|
55 break; |
|
56 } |
|
57 // Unicode replacement value for unmappable chars |
|
58 *dest = 0xfffd; |
|
59 } |
|
60 } |
|
61 |
|
62 src += bcr; |
|
63 srcLen -= bcr; |
|
64 dest++; |
|
65 } |
|
66 |
|
67 if ((srcLen > 0) && (res == NS_OK)) res = NS_OK_UDEC_MOREOUTPUT; |
|
68 |
|
69 *aSrcLength = src - aSrc; |
|
70 *aDestLength = dest - aDest; |
|
71 return res; |
|
72 } |
|
73 |
|
74 nsresult nsUnicodeDecodeHelper::ConvertByMultiTable( |
|
75 const char * aSrc, |
|
76 int32_t * aSrcLength, |
|
77 char16_t * aDest, |
|
78 int32_t * aDestLength, |
|
79 int32_t aTableCount, |
|
80 const uRange * aRangeArray, |
|
81 uScanClassID * aScanClassArray, |
|
82 uMappingTable ** aMappingTable, |
|
83 bool aErrorSignal) |
|
84 { |
|
85 uint8_t * src = (uint8_t *)aSrc; |
|
86 int32_t srcLen = *aSrcLength; |
|
87 char16_t * dest = aDest; |
|
88 char16_t * destEnd = aDest + *aDestLength; |
|
89 |
|
90 char16_t med; |
|
91 int32_t bcr; // byte count for read |
|
92 nsresult res = NS_OK; |
|
93 int32_t i; |
|
94 |
|
95 while ((srcLen > 0) && (dest < destEnd)) |
|
96 { |
|
97 bool done= false; |
|
98 bool passRangeCheck = false; |
|
99 bool passScan = false; |
|
100 for (i=0; (!done) && (i<aTableCount); i++) |
|
101 { |
|
102 if ((aRangeArray[i].min <= *src) && (*src <= aRangeArray[i].max)) |
|
103 { |
|
104 passRangeCheck = true; |
|
105 if (uScan(aScanClassArray[i], nullptr, src, |
|
106 reinterpret_cast<uint16_t*>(&med), srcLen, |
|
107 (uint32_t *)&bcr)) |
|
108 { |
|
109 passScan = true; |
|
110 done = uMapCode((uTable*) aMappingTable[i], |
|
111 static_cast<uint16_t>(med), |
|
112 reinterpret_cast<uint16_t*>(dest)); |
|
113 } // if (uScan ... ) |
|
114 } // if Range |
|
115 } // for loop |
|
116 |
|
117 if(passRangeCheck && (! passScan)) |
|
118 { |
|
119 if (res != NS_ERROR_ILLEGAL_INPUT) |
|
120 res = NS_OK_UDEC_MOREINPUT; |
|
121 break; |
|
122 } |
|
123 if(! done) |
|
124 { |
|
125 bcr = 1; |
|
126 if ((uint8_t)*src < 0x20) { |
|
127 // somehow some table miss the 0x00 - 0x20 part |
|
128 *dest = *src; |
|
129 } else if(*src == (uint8_t) 0xa0) { |
|
130 // handle nbsp |
|
131 *dest = 0x00a0; |
|
132 } else { |
|
133 // we need to decide how many byte we skip. We can use uScan to do this |
|
134 for (i=0; i<aTableCount; i++) |
|
135 { |
|
136 if ((aRangeArray[i].min <= *src) && (*src <= aRangeArray[i].max)) |
|
137 { |
|
138 if (uScan(aScanClassArray[i], nullptr, src, |
|
139 reinterpret_cast<uint16_t*>(&med), srcLen, |
|
140 (uint32_t*)&bcr)) |
|
141 { |
|
142 // match the patten |
|
143 |
|
144 int32_t k; |
|
145 for(k = 1; k < bcr; k++) |
|
146 { |
|
147 if(0 == (src[k] & 0x80)) |
|
148 { // only skip if all bytes > 0x80 |
|
149 // if we hit bytes <= 0x80, skip only one byte |
|
150 bcr = 1; |
|
151 break; |
|
152 } |
|
153 } |
|
154 break; |
|
155 } |
|
156 } |
|
157 } |
|
158 // treat it as NSBR if bcr == 1 and it is 0xa0 |
|
159 if ((1==bcr)&&(*src == (uint8_t)0xa0 )) { |
|
160 *dest = 0x00a0; |
|
161 } else { |
|
162 if (aErrorSignal) { |
|
163 res = NS_ERROR_ILLEGAL_INPUT; |
|
164 break; |
|
165 } |
|
166 *dest = 0xfffd; |
|
167 } |
|
168 } |
|
169 } |
|
170 |
|
171 src += bcr; |
|
172 srcLen -= bcr; |
|
173 dest++; |
|
174 } // while |
|
175 |
|
176 if ((srcLen > 0) && (res == NS_OK)) res = NS_OK_UDEC_MOREOUTPUT; |
|
177 |
|
178 *aSrcLength = src - (uint8_t *)aSrc; |
|
179 *aDestLength = dest - aDest; |
|
180 return res; |
|
181 } |
|
182 |
|
183 nsresult nsUnicodeDecodeHelper::ConvertByFastTable( |
|
184 const char * aSrc, |
|
185 int32_t * aSrcLength, |
|
186 char16_t * aDest, |
|
187 int32_t * aDestLength, |
|
188 const char16_t * aFastTable, |
|
189 int32_t aTableSize, |
|
190 bool aErrorSignal) |
|
191 { |
|
192 uint8_t * src = (uint8_t *)aSrc; |
|
193 uint8_t * srcEnd = src; |
|
194 char16_t * dest = aDest; |
|
195 |
|
196 nsresult res; |
|
197 if (*aSrcLength > *aDestLength) { |
|
198 srcEnd += (*aDestLength); |
|
199 res = NS_PARTIAL_MORE_OUTPUT; |
|
200 } else { |
|
201 srcEnd += (*aSrcLength); |
|
202 res = NS_OK; |
|
203 } |
|
204 |
|
205 for (; src<srcEnd;) { |
|
206 *dest = aFastTable[*src]; |
|
207 if (*dest == 0xfffd && aErrorSignal) { |
|
208 res = NS_ERROR_ILLEGAL_INPUT; |
|
209 break; |
|
210 } |
|
211 src++; |
|
212 dest++; |
|
213 } |
|
214 |
|
215 *aSrcLength = src - (uint8_t *)aSrc; |
|
216 *aDestLength = dest - aDest; |
|
217 return res; |
|
218 } |
|
219 |
|
220 nsresult nsUnicodeDecodeHelper::CreateFastTable( |
|
221 uMappingTable * aMappingTable, |
|
222 char16_t * aFastTable, |
|
223 int32_t aTableSize) |
|
224 { |
|
225 int32_t tableSize = aTableSize; |
|
226 int32_t buffSize = aTableSize; |
|
227 nsAutoArrayPtr<char> buff(new char [buffSize]); |
|
228 |
|
229 char * p = buff; |
|
230 for (int32_t i=0; i<aTableSize; i++) *(p++) = i; |
|
231 return ConvertByTable(buff, &buffSize, aFastTable, &tableSize, |
|
232 u1ByteCharset, nullptr, aMappingTable); |
|
233 } |
|
234 |