Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * EUC_JIS_2004, SHIFT_JIS_2004
4 : *
5 : * Copyright (c) 2007-2023, PostgreSQL Global Development Group
6 : *
7 : * IDENTIFICATION
8 : * src/backend/utils/mb/conversion_procs/euc2004_sjis2004/euc2004_sjis2004.c
9 : *
10 : *-------------------------------------------------------------------------
11 : */
12 :
13 : #include "postgres.h"
14 : #include "fmgr.h"
15 : #include "mb/pg_wchar.h"
16 :
5859 ishii 17 CBC 6 : PG_MODULE_MAGIC;
18 :
19 3 : PG_FUNCTION_INFO_V1(euc_jis_2004_to_shift_jis_2004);
20 6 : PG_FUNCTION_INFO_V1(shift_jis_2004_to_euc_jis_2004);
21 :
22 : static int euc_jis_20042shift_jis_2004(const unsigned char *euc, unsigned char *p, int len, bool noError);
23 : static int shift_jis_20042euc_jis_2004(const unsigned char *sjis, unsigned char *p, int len, bool noError);
24 :
25 : /* ----------
26 : * conv_proc(
27 : * INTEGER, -- source encoding id
28 : * INTEGER, -- destination encoding id
29 : * CSTRING, -- source string (null terminated C string)
30 : * CSTRING, -- destination string (null terminated C string)
31 : * INTEGER, -- source string length
32 : * BOOL -- if true, don't throw an error if conversion fails
33 : * ) returns INTEGER;
34 : *
35 : * Returns the number of bytes successfully converted.
36 : * ----------
37 : */
38 :
39 : Datum
40 3 : euc_jis_2004_to_shift_jis_2004(PG_FUNCTION_ARGS)
41 : {
42 3 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
43 3 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
44 3 : int len = PG_GETARG_INT32(4);
738 heikki.linnakangas 45 3 : bool noError = PG_GETARG_BOOL(5);
46 : int converted;
47 :
5183 tgl 48 3 : CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_JIS_2004, PG_SHIFT_JIS_2004);
49 :
738 heikki.linnakangas 50 3 : converted = euc_jis_20042shift_jis_2004(src, dest, len, noError);
51 :
52 3 : PG_RETURN_INT32(converted);
53 : }
54 :
55 : Datum
5859 ishii 56 129 : shift_jis_2004_to_euc_jis_2004(PG_FUNCTION_ARGS)
57 : {
58 129 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
59 129 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
60 129 : int len = PG_GETARG_INT32(4);
738 heikki.linnakangas 61 129 : bool noError = PG_GETARG_BOOL(5);
62 : int converted;
63 :
5183 tgl 64 129 : CHECK_ENCODING_CONVERSION_ARGS(PG_SHIFT_JIS_2004, PG_EUC_JIS_2004);
65 :
738 heikki.linnakangas 66 129 : converted = shift_jis_20042euc_jis_2004(src, dest, len, noError);
67 :
68 84 : PG_RETURN_INT32(converted);
69 : }
70 :
71 : /*
72 : * EUC_JIS_2004 -> SHIFT_JIS_2004
73 : */
74 : static int
75 3 : euc_jis_20042shift_jis_2004(const unsigned char *euc, unsigned char *p, int len, bool noError)
76 : {
77 3 : const unsigned char *start = euc;
78 : int c1,
79 : ku,
80 : ten;
81 : int l;
82 :
5859 ishii 83 12 : while (len > 0)
84 : {
85 9 : c1 = *euc;
86 9 : if (!IS_HIGHBIT_SET(c1))
87 : {
88 : /* ASCII */
89 9 : if (c1 == 0)
90 : {
738 heikki.linnakangas 91 UBC 0 : if (noError)
92 0 : break;
5859 ishii 93 0 : report_invalid_encoding(PG_EUC_JIS_2004,
94 : (const char *) euc, len);
95 : }
5859 ishii 96 CBC 9 : *p++ = c1;
97 9 : euc++;
98 9 : len--;
99 9 : continue;
100 : }
101 :
801 heikki.linnakangas 102 UBC 0 : l = pg_encoding_verifymbchar(PG_EUC_JIS_2004, (const char *) euc, len);
103 :
5859 ishii 104 0 : if (l < 0)
105 : {
738 heikki.linnakangas 106 0 : if (noError)
107 0 : break;
5859 ishii 108 0 : report_invalid_encoding(PG_EUC_JIS_2004,
109 : (const char *) euc, len);
110 : }
111 :
112 0 : if (c1 == SS2 && l == 2) /* JIS X 0201 kana? */
113 : {
114 0 : *p++ = euc[1];
115 : }
5624 bruce 116 0 : else if (c1 == SS3 && l == 3) /* JIS X 0213 plane 2? */
117 : {
5859 ishii 118 0 : ku = euc[1] - 0xa0;
119 0 : ten = euc[2] - 0xa0;
120 :
121 0 : switch (ku)
122 : {
123 0 : case 1:
124 : case 3:
125 : case 4:
126 : case 5:
127 : case 8:
128 : case 12:
129 : case 13:
130 : case 14:
131 : case 15:
132 0 : *p++ = ((ku + 0x1df) >> 1) - (ku >> 3) * 3;
133 0 : break;
134 0 : default:
135 0 : if (ku >= 78 && ku <= 94)
136 : {
137 0 : *p++ = (ku + 0x19b) >> 1;
138 : }
139 : else
140 : {
738 heikki.linnakangas 141 0 : if (noError)
142 0 : break;
5859 ishii 143 0 : report_invalid_encoding(PG_EUC_JIS_2004,
144 : (const char *) euc, len);
145 : }
146 : }
147 :
148 0 : if (ku % 2)
149 : {
150 0 : if (ten >= 1 && ten <= 63)
151 0 : *p++ = ten + 0x3f;
152 0 : else if (ten >= 64 && ten <= 94)
153 0 : *p++ = ten + 0x40;
154 : else
155 : {
738 heikki.linnakangas 156 0 : if (noError)
157 0 : break;
5859 ishii 158 0 : report_invalid_encoding(PG_EUC_JIS_2004,
159 : (const char *) euc, len);
160 : }
161 : }
162 : else
163 0 : *p++ = ten + 0x9e;
164 : }
165 :
5624 bruce 166 0 : else if (l == 2) /* JIS X 0213 plane 1? */
167 : {
5859 ishii 168 0 : ku = c1 - 0xa0;
169 0 : ten = euc[1] - 0xa0;
170 :
171 0 : if (ku >= 1 && ku <= 62)
172 0 : *p++ = (ku + 0x101) >> 1;
173 0 : else if (ku >= 63 && ku <= 94)
174 0 : *p++ = (ku + 0x181) >> 1;
175 : else
176 : {
738 heikki.linnakangas 177 0 : if (noError)
178 0 : break;
5859 ishii 179 0 : report_invalid_encoding(PG_EUC_JIS_2004,
180 : (const char *) euc, len);
181 : }
182 :
183 0 : if (ku % 2)
184 : {
185 0 : if (ten >= 1 && ten <= 63)
186 0 : *p++ = ten + 0x3f;
187 0 : else if (ten >= 64 && ten <= 94)
188 0 : *p++ = ten + 0x40;
189 : else
190 : {
738 heikki.linnakangas 191 0 : if (noError)
192 0 : break;
5859 ishii 193 0 : report_invalid_encoding(PG_EUC_JIS_2004,
194 : (const char *) euc, len);
195 : }
196 : }
197 : else
198 0 : *p++ = ten + 0x9e;
199 : }
200 : else
201 : {
738 heikki.linnakangas 202 0 : if (noError)
203 0 : break;
5859 ishii 204 0 : report_invalid_encoding(PG_EUC_JIS_2004,
205 : (const char *) euc, len);
206 : }
207 :
208 0 : euc += l;
209 0 : len -= l;
210 : }
5859 ishii 211 CBC 3 : *p = '\0';
212 :
738 heikki.linnakangas 213 3 : return euc - start;
214 : }
215 :
216 : /*
217 : * returns SHIFT_JIS_2004 "ku" code indicated by second byte
218 : * *ku = 0: "ku" = even
219 : * *ku = 1: "ku" = odd
220 : */
221 : static int
5624 bruce 222 63 : get_ten(int b, int *ku)
223 : {
224 : int ten;
225 :
5859 ishii 226 63 : if (b >= 0x40 && b <= 0x7e)
227 : {
5859 ishii 228 UBC 0 : ten = b - 0x3f;
229 0 : *ku = 1;
230 : }
5624 bruce 231 CBC 63 : else if (b >= 0x80 && b <= 0x9e)
232 : {
5859 ishii 233 UBC 0 : ten = b - 0x40;
234 0 : *ku = 1;
235 : }
5624 bruce 236 CBC 63 : else if (b >= 0x9f && b <= 0xfc)
237 : {
5859 ishii 238 63 : ten = b - 0x9e;
239 63 : *ku = 0;
240 : }
241 : else
242 : {
5624 bruce 243 UBC 0 : ten = -1; /* error */
5336 tgl 244 0 : *ku = 0; /* keep compiler quiet */
245 : }
5859 ishii 246 CBC 63 : return ten;
247 : }
248 :
249 : /*
250 : * SHIFT_JIS_2004 ---> EUC_JIS_2004
251 : */
252 :
253 : static int
738 heikki.linnakangas 254 129 : shift_jis_20042euc_jis_2004(const unsigned char *sjis, unsigned char *p, int len, bool noError)
255 : {
256 129 : const unsigned char *start = sjis;
257 : int c1;
258 : int ku,
259 : ten,
260 : kubun;
261 : int plane;
262 : int l;
263 :
5859 ishii 264 579 : while (len > 0)
265 : {
266 540 : c1 = *sjis;
267 :
268 540 : if (!IS_HIGHBIT_SET(c1))
269 : {
270 : /* ASCII */
271 423 : if (c1 == 0)
272 : {
738 heikki.linnakangas 273 36 : if (noError)
274 18 : break;
5859 ishii 275 18 : report_invalid_encoding(PG_SHIFT_JIS_2004,
276 : (const char *) sjis, len);
277 : }
278 387 : *p++ = c1;
279 387 : sjis++;
280 387 : len--;
281 387 : continue;
282 : }
283 :
801 heikki.linnakangas 284 117 : l = pg_encoding_verifymbchar(PG_SHIFT_JIS_2004, (const char *) sjis, len);
285 :
4233 tgl 286 117 : if (l < 0 || l > len)
287 : {
738 heikki.linnakangas 288 54 : if (noError)
289 27 : break;
5859 ishii 290 27 : report_invalid_encoding(PG_SHIFT_JIS_2004,
291 : (const char *) sjis, len);
292 : }
293 :
294 63 : if (c1 >= 0xa1 && c1 <= 0xdf && l == 1)
295 : {
296 : /* JIS X0201 (1 byte kana) */
5859 ishii 297 UBC 0 : *p++ = SS2;
298 0 : *p++ = c1;
299 : }
5859 ishii 300 CBC 63 : else if (l == 2)
301 : {
4233 tgl 302 63 : int c2 = sjis[1];
303 :
5859 ishii 304 63 : plane = 1;
305 63 : ku = 1;
306 63 : ten = 1;
307 :
308 : /*
309 : * JIS X 0213
310 : */
2118 tgl 311 63 : if (c1 >= 0x81 && c1 <= 0x9f) /* plane 1 1ku-62ku */
312 : {
5859 ishii 313 63 : ku = (c1 << 1) - 0x100;
314 63 : ten = get_ten(c2, &kubun);
315 63 : if (ten < 0)
316 : {
738 heikki.linnakangas 317 UBC 0 : if (noError)
318 0 : break;
5859 ishii 319 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
320 : (const char *) sjis, len);
321 : }
5859 ishii 322 CBC 63 : ku -= kubun;
323 : }
5859 ishii 324 UBC 0 : else if (c1 >= 0xe0 && c1 <= 0xef) /* plane 1 62ku-94ku */
325 : {
326 0 : ku = (c1 << 1) - 0x180;
327 0 : ten = get_ten(c2, &kubun);
328 0 : if (ten < 0)
329 : {
738 heikki.linnakangas 330 0 : if (noError)
331 0 : break;
5859 ishii 332 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
333 : (const char *) sjis, len);
334 : }
335 0 : ku -= kubun;
336 : }
5624 bruce 337 0 : else if (c1 >= 0xf0 && c1 <= 0xf3) /* plane 2
338 : * 1,3,4,5,8,12,13,14,15 ku */
339 : {
5859 ishii 340 0 : plane = 2;
341 0 : ten = get_ten(c2, &kubun);
342 0 : if (ten < 0)
343 : {
738 heikki.linnakangas 344 0 : if (noError)
345 0 : break;
5859 ishii 346 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
347 : (const char *) sjis, len);
348 : }
349 0 : switch (c1)
350 : {
351 0 : case 0xf0:
5624 bruce 352 0 : ku = kubun == 0 ? 8 : 1;
5859 ishii 353 0 : break;
354 0 : case 0xf1:
5624 bruce 355 0 : ku = kubun == 0 ? 4 : 3;
5859 ishii 356 0 : break;
357 0 : case 0xf2:
5624 bruce 358 0 : ku = kubun == 0 ? 12 : 5;
5859 ishii 359 0 : break;
360 0 : default:
5624 bruce 361 0 : ku = kubun == 0 ? 14 : 13;
5859 ishii 362 0 : break;
363 : }
364 : }
365 0 : else if (c1 >= 0xf4 && c1 <= 0xfc) /* plane 2 78-94ku */
366 : {
367 0 : plane = 2;
368 0 : ten = get_ten(c2, &kubun);
369 0 : if (ten < 0)
370 : {
738 heikki.linnakangas 371 0 : if (noError)
372 0 : break;
5859 ishii 373 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
374 : (const char *) sjis, len);
375 : }
376 0 : if (c1 == 0xf4 && kubun == 1)
377 0 : ku = 15;
378 : else
379 0 : ku = (c1 << 1) - 0x19a - kubun;
380 : }
381 : else
382 : {
738 heikki.linnakangas 383 0 : if (noError)
384 0 : break;
5859 ishii 385 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
386 : (const char *) sjis, len);
387 : }
388 :
5859 ishii 389 CBC 63 : if (plane == 2)
5859 ishii 390 UBC 0 : *p++ = SS3;
391 :
5859 ishii 392 CBC 63 : *p++ = ku + 0xa0;
393 63 : *p++ = ten + 0xa0;
394 : }
395 63 : sjis += l;
396 63 : len -= l;
397 : }
398 84 : *p = '\0';
399 :
738 heikki.linnakangas 400 84 : return sjis - start;
401 : }
|