| |
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 "nsGBKConvUtil.h" |
| |
7 #include "gbku.h" |
| |
8 #include "nsDebug.h" |
| |
9 #define MAX_GBK_LENGTH 24066 /* (0xfe-0x80)*(0xfe-0x3f) */ |
| |
10 //-------------------------------------------------------------------- |
| |
11 // nsGBKConvUtil |
| |
12 //-------------------------------------------------------------------- |
| |
13 |
| |
14 static const char16_t gGBKToUnicodeTable[MAX_GBK_LENGTH] = { |
| |
15 #include "cp936map.h" |
| |
16 }; |
| |
17 static const uint16_t gUnicodeToGBKTable[0xA000-0x4e00] = { |
| |
18 #include "cp936invmap.h" |
| |
19 }; |
| |
20 |
| |
21 bool nsGBKConvUtil::UnicodeToGBKChar( |
| |
22 char16_t aChar, bool aToGL, char* |
| |
23 aOutByte1, char* aOutByte2) |
| |
24 { |
| |
25 bool found=false; |
| |
26 *aOutByte1 = *aOutByte2 = 0; |
| |
27 if(UNICHAR_IN_RANGE(0xd800, aChar, 0xdfff)) |
| |
28 { |
| |
29 // surrogate is not in here |
| |
30 return false; |
| |
31 } |
| |
32 if(UNICHAR_IN_RANGE(0x4e00, aChar, 0x9FFF)) |
| |
33 { |
| |
34 uint16_t item = gUnicodeToGBKTable[aChar - 0x4e00]; |
| |
35 if(item != 0) |
| |
36 { |
| |
37 *aOutByte1 = item >> 8; |
| |
38 *aOutByte2 = item & 0x00FF; |
| |
39 found = true; |
| |
40 } else { |
| |
41 return false; |
| |
42 } |
| |
43 } else { |
| |
44 // ugly linear search |
| |
45 for( int32_t i = 0; i < MAX_GBK_LENGTH; i++ ) |
| |
46 { |
| |
47 if( aChar == gGBKToUnicodeTable[i]) |
| |
48 { |
| |
49 *aOutByte1 = (i / 0x00BF + 0x0081) ; |
| |
50 *aOutByte2 = (i % 0x00BF + 0x0040) ; |
| |
51 found = true; |
| |
52 break; |
| |
53 } |
| |
54 } |
| |
55 } |
| |
56 if(! found) |
| |
57 return false; |
| |
58 |
| |
59 if(aToGL) { |
| |
60 // to GL, we only return if it is in the range |
| |
61 if(UINT8_IN_RANGE(0xA1, *aOutByte1, 0xFE) && |
| |
62 UINT8_IN_RANGE(0xA1, *aOutByte2, 0xFE)) |
| |
63 { |
| |
64 // mask them to GL |
| |
65 *aOutByte1 &= 0x7F; |
| |
66 *aOutByte2 &= 0x7F; |
| |
67 } else { |
| |
68 // if it does not fit into 0xa1-0xfe 0xa1-0xfe range that mean |
| |
69 // it is not a GB2312 character, we cannot map to GL |
| |
70 *aOutByte1 = 0x00; |
| |
71 *aOutByte2 = 0x00; |
| |
72 return false; |
| |
73 } |
| |
74 } |
| |
75 return true; |
| |
76 } |
| |
77 char16_t nsGBKConvUtil::GBKCharToUnicode(char aByte1, char aByte2) |
| |
78 { |
| |
79 NS_ASSERTION(UINT8_IN_RANGE(0x81,aByte1, 0xFE), "first byte out of range"); |
| |
80 NS_ASSERTION(UINT8_IN_RANGE(0x40,aByte2, 0xFE), "second byte out of range"); |
| |
81 |
| |
82 uint8_t i1 = (uint8_t)aByte1; |
| |
83 uint8_t i2 = (uint8_t)aByte2; |
| |
84 uint16_t idx = (i1 - 0x0081) * 0x00bf + i2 - 0x0040 ; |
| |
85 |
| |
86 NS_ASSERTION(idx < MAX_GBK_LENGTH, "ARB"); |
| |
87 // play it safe- add if statement here ot protect ARB |
| |
88 // probably not necessary |
| |
89 if(idx < MAX_GBK_LENGTH) |
| |
90 return gGBKToUnicodeTable[ idx ]; |
| |
91 else |
| |
92 return UCS2_NO_MAPPING; |
| |
93 } |