Branch data Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * EUC_TW and BIG5
4 : : *
5 : : * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
6 : : * Portions Copyright (c) 1994, Regents of the University of California
7 : : *
8 : : * IDENTIFICATION
9 : : * src/backend/utils/mb/conversion_procs/euc_tw_and_big5/euc_tw_and_big5.c
10 : : *
11 : : *-------------------------------------------------------------------------
12 : : */
13 : :
14 : : #include "postgres.h"
15 : : #include "fmgr.h"
16 : : #include "mb/pg_wchar.h"
17 : :
18 : 4 : PG_MODULE_MAGIC_EXT(
19 : : .name = "euc_tw_and_big5",
20 : : .version = PG_VERSION
21 : : );
22 : :
23 : 4 : PG_FUNCTION_INFO_V1(euc_tw_to_big5);
24 : 4 : PG_FUNCTION_INFO_V1(big5_to_euc_tw);
25 : :
26 : : /* ----------
27 : : * conv_proc(
28 : : * INTEGER, -- source encoding id
29 : : * INTEGER, -- destination encoding id
30 : : * CSTRING, -- source string (null terminated C string)
31 : : * CSTRING, -- destination string (null terminated C string)
32 : : * INTEGER, -- source string length
33 : : * BOOL -- if true, don't throw an error if conversion fails
34 : : * ) returns INTEGER;
35 : : *
36 : : * Returns the number of bytes successfully converted.
37 : : * ----------
38 : : */
39 : :
40 : : static int euc_tw2big5(const unsigned char *euc, unsigned char *p, int len, bool noError);
41 : : static int big52euc_tw(const unsigned char *big5, unsigned char *p, int len, bool noError);
42 : :
43 : : Datum
44 : 4 : euc_tw_to_big5(PG_FUNCTION_ARGS)
45 : : {
46 : 4 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
47 : 4 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
48 : 4 : int len = PG_GETARG_INT32(4);
49 : 4 : bool noError = PG_GETARG_BOOL(5);
50 : : int converted;
51 : :
52 : 4 : CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_TW, PG_BIG5);
53 : :
54 : 4 : converted = euc_tw2big5(src, dest, len, noError);
55 : :
56 : 4 : PG_RETURN_INT32(converted);
57 : : }
58 : :
59 : : Datum
60 : 4 : big5_to_euc_tw(PG_FUNCTION_ARGS)
61 : : {
62 : 4 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
63 : 4 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
64 : 4 : int len = PG_GETARG_INT32(4);
65 : 4 : bool noError = PG_GETARG_BOOL(5);
66 : : int converted;
67 : :
68 : 4 : CHECK_ENCODING_CONVERSION_ARGS(PG_BIG5, PG_EUC_TW);
69 : :
70 : 4 : converted = big52euc_tw(src, dest, len, noError);
71 : :
72 : 4 : PG_RETURN_INT32(converted);
73 : : }
74 : :
75 : : static int
76 : 4 : euc_tw2big5(const unsigned char *euc, unsigned char *p, int len, bool noError)
77 : : {
78 : 4 : const unsigned char *start = euc;
79 : : unsigned char c1;
80 : : unsigned short big5buf,
81 : : cnsBuf;
82 : : unsigned char lc;
83 : : int l;
84 : :
85 [ + + ]: 16 : while (len > 0)
86 : : {
87 : 12 : c1 = *euc;
88 [ - + ]: 12 : if (IS_HIGHBIT_SET(c1))
89 : : {
90 : : /* Verify and decode the next EUC_TW input character */
91 : 0 : l = pg_encoding_verifymbchar(PG_EUC_TW, (const char *) euc, len);
92 [ # # ]: 0 : if (l < 0)
93 : : {
94 [ # # ]: 0 : if (noError)
95 : 0 : break;
96 : 0 : report_invalid_encoding(PG_EUC_TW,
97 : : (const char *) euc, len);
98 : : }
99 [ # # ]: 0 : if (c1 == SS2)
100 : : {
101 : 0 : c1 = euc[1]; /* plane No. */
102 [ # # ]: 0 : if (c1 == 0xa1)
103 : 0 : lc = LC_CNS11643_1;
104 [ # # ]: 0 : else if (c1 == 0xa2)
105 : 0 : lc = LC_CNS11643_2;
106 : : else
107 : 0 : lc = c1 - 0xa3 + LC_CNS11643_3;
108 : 0 : cnsBuf = (euc[2] << 8) | euc[3];
109 : : }
110 : : else
111 : : { /* CNS11643-1 */
112 : 0 : lc = LC_CNS11643_1;
113 : 0 : cnsBuf = (c1 << 8) | euc[1];
114 : : }
115 : :
116 : : /* Write it out in Big5 */
117 : 0 : big5buf = CNStoBIG5(cnsBuf, lc);
118 [ # # ]: 0 : if (big5buf == 0)
119 : : {
120 [ # # ]: 0 : if (noError)
121 : 0 : break;
122 : 0 : report_untranslatable_char(PG_EUC_TW, PG_BIG5,
123 : : (const char *) euc, len);
124 : : }
125 : 0 : *p++ = (big5buf >> 8) & 0x00ff;
126 : 0 : *p++ = big5buf & 0x00ff;
127 : :
128 : 0 : euc += l;
129 : 0 : len -= l;
130 : : }
131 : : else
132 : : { /* should be ASCII */
133 [ - + ]: 12 : if (c1 == 0)
134 : : {
135 [ # # ]: 0 : if (noError)
136 : 0 : break;
137 : 0 : report_invalid_encoding(PG_EUC_TW,
138 : : (const char *) euc, len);
139 : : }
140 : 12 : *p++ = c1;
141 : 12 : euc++;
142 : 12 : len--;
143 : : }
144 : : }
145 : 4 : *p = '\0';
146 : :
147 : 4 : return euc - start;
148 : : }
149 : :
150 : : /*
151 : : * Big5 ---> EUC_TW
152 : : */
153 : : static int
154 : 4 : big52euc_tw(const unsigned char *big5, unsigned char *p, int len, bool noError)
155 : : {
156 : 4 : const unsigned char *start = big5;
157 : : unsigned short c1;
158 : : unsigned short big5buf,
159 : : cnsBuf;
160 : : unsigned char lc;
161 : : int l;
162 : :
163 [ + + ]: 16 : while (len > 0)
164 : : {
165 : : /* Verify and decode the next Big5 input character */
166 : 12 : c1 = *big5;
167 [ - + ]: 12 : if (IS_HIGHBIT_SET(c1))
168 : : {
169 : 0 : l = pg_encoding_verifymbchar(PG_BIG5, (const char *) big5, len);
170 [ # # ]: 0 : if (l < 0)
171 : : {
172 [ # # ]: 0 : if (noError)
173 : 0 : break;
174 : 0 : report_invalid_encoding(PG_BIG5,
175 : : (const char *) big5, len);
176 : : }
177 : 0 : big5buf = (c1 << 8) | big5[1];
178 : 0 : cnsBuf = BIG5toCNS(big5buf, &lc);
179 : :
180 [ # # ]: 0 : if (lc == LC_CNS11643_1)
181 : : {
182 : 0 : *p++ = (cnsBuf >> 8) & 0x00ff;
183 : 0 : *p++ = cnsBuf & 0x00ff;
184 : : }
185 [ # # ]: 0 : else if (lc == LC_CNS11643_2)
186 : : {
187 : 0 : *p++ = SS2;
188 : 0 : *p++ = 0xa2;
189 : 0 : *p++ = (cnsBuf >> 8) & 0x00ff;
190 : 0 : *p++ = cnsBuf & 0x00ff;
191 : : }
192 [ # # # # ]: 0 : else if (lc >= LC_CNS11643_3 && lc <= LC_CNS11643_7)
193 : : {
194 : 0 : *p++ = SS2;
195 : 0 : *p++ = lc - LC_CNS11643_3 + 0xa3;
196 : 0 : *p++ = (cnsBuf >> 8) & 0x00ff;
197 : 0 : *p++ = cnsBuf & 0x00ff;
198 : : }
199 : : else
200 : : {
201 [ # # ]: 0 : if (noError)
202 : 0 : break;
203 : 0 : report_untranslatable_char(PG_BIG5, PG_EUC_TW,
204 : : (const char *) big5, len);
205 : : }
206 : :
207 : 0 : big5 += l;
208 : 0 : len -= l;
209 : : }
210 : : else
211 : : {
212 : : /* ASCII */
213 [ - + ]: 12 : if (c1 == 0)
214 : : {
215 [ # # ]: 0 : if (noError)
216 : 0 : break;
217 : 0 : report_invalid_encoding(PG_BIG5,
218 : : (const char *) big5, len);
219 : : }
220 : 12 : *p++ = c1;
221 : 12 : big5++;
222 : 12 : len--;
223 : 12 : continue;
224 : : }
225 : : }
226 : 4 : *p = '\0';
227 : :
228 : 4 : return big5 - start;
229 : : }
|