Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * EUC_JIS_2004, SHIFT_JIS_2004
4 : : *
5 : : * Copyright (c) 2007-2024, 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 : :
6230 ishii@postgresql.org 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);
1109 heikki.linnakangas@i 45 : 3 : bool noError = PG_GETARG_BOOL(5);
46 : : int converted;
47 : :
5554 tgl@sss.pgh.pa.us 48 : 3 : CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_JIS_2004, PG_SHIFT_JIS_2004);
49 : :
1109 heikki.linnakangas@i 50 : 3 : converted = euc_jis_20042shift_jis_2004(src, dest, len, noError);
51 : :
52 : 3 : PG_RETURN_INT32(converted);
53 : : }
54 : :
55 : : Datum
6230 ishii@postgresql.org 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);
1109 heikki.linnakangas@i 61 : 129 : bool noError = PG_GETARG_BOOL(5);
62 : : int converted;
63 : :
5554 tgl@sss.pgh.pa.us 64 : 129 : CHECK_ENCODING_CONVERSION_ARGS(PG_SHIFT_JIS_2004, PG_EUC_JIS_2004);
65 : :
1109 heikki.linnakangas@i 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 : :
6230 ishii@postgresql.org 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 : : {
1109 heikki.linnakangas@i 91 [ # # ]:UBC 0 : if (noError)
92 : 0 : break;
6230 ishii@postgresql.org 93 : 0 : report_invalid_encoding(PG_EUC_JIS_2004,
94 : : (const char *) euc, len);
95 : : }
6230 ishii@postgresql.org 96 :CBC 9 : *p++ = c1;
97 : 9 : euc++;
98 : 9 : len--;
99 : 9 : continue;
100 : : }
101 : :
1172 heikki.linnakangas@i 102 :UBC 0 : l = pg_encoding_verifymbchar(PG_EUC_JIS_2004, (const char *) euc, len);
103 : :
6230 ishii@postgresql.org 104 [ # # ]: 0 : if (l < 0)
105 : : {
1109 heikki.linnakangas@i 106 [ # # ]: 0 : if (noError)
107 : 0 : break;
6230 ishii@postgresql.org 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 : : }
5995 bruce@momjian.us 116 [ # # # # ]: 0 : else if (c1 == SS3 && l == 3) /* JIS X 0213 plane 2? */
117 : : {
6230 ishii@postgresql.org 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 : : {
1109 heikki.linnakangas@i 141 [ # # ]: 0 : if (noError)
142 : 0 : break;
6230 ishii@postgresql.org 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 : : {
1109 heikki.linnakangas@i 156 [ # # ]: 0 : if (noError)
157 : 0 : break;
6230 ishii@postgresql.org 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 : :
5995 bruce@momjian.us 166 [ # # ]: 0 : else if (l == 2) /* JIS X 0213 plane 1? */
167 : : {
6230 ishii@postgresql.org 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 : : {
1109 heikki.linnakangas@i 177 [ # # ]: 0 : if (noError)
178 : 0 : break;
6230 ishii@postgresql.org 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 : : {
1109 heikki.linnakangas@i 191 [ # # ]: 0 : if (noError)
192 : 0 : break;
6230 ishii@postgresql.org 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 : : {
1109 heikki.linnakangas@i 202 [ # # ]: 0 : if (noError)
203 : 0 : break;
6230 ishii@postgresql.org 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 : : }
6230 ishii@postgresql.org 211 :CBC 3 : *p = '\0';
212 : :
1109 heikki.linnakangas@i 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
5995 bruce@momjian.us 222 : 63 : get_ten(int b, int *ku)
223 : : {
224 : : int ten;
225 : :
6230 ishii@postgresql.org 226 [ + - - + ]: 63 : if (b >= 0x40 && b <= 0x7e)
227 : : {
6230 ishii@postgresql.org 228 :UBC 0 : ten = b - 0x3f;
229 : 0 : *ku = 1;
230 : : }
5995 bruce@momjian.us 231 [ + - - + ]:CBC 63 : else if (b >= 0x80 && b <= 0x9e)
232 : : {
6230 ishii@postgresql.org 233 :UBC 0 : ten = b - 0x40;
234 : 0 : *ku = 1;
235 : : }
5995 bruce@momjian.us 236 [ + - + - ]:CBC 63 : else if (b >= 0x9f && b <= 0xfc)
237 : : {
6230 ishii@postgresql.org 238 : 63 : ten = b - 0x9e;
239 : 63 : *ku = 0;
240 : : }
241 : : else
242 : : {
5995 bruce@momjian.us 243 :UBC 0 : ten = -1; /* error */
5707 tgl@sss.pgh.pa.us 244 : 0 : *ku = 0; /* keep compiler quiet */
245 : : }
6230 ishii@postgresql.org 246 :CBC 63 : return ten;
247 : : }
248 : :
249 : : /*
250 : : * SHIFT_JIS_2004 ---> EUC_JIS_2004
251 : : */
252 : :
253 : : static int
1109 heikki.linnakangas@i 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 : :
6230 ishii@postgresql.org 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 : : {
1109 heikki.linnakangas@i 273 [ + + ]: 36 : if (noError)
274 : 18 : break;
6230 ishii@postgresql.org 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 : :
1172 heikki.linnakangas@i 284 : 117 : l = pg_encoding_verifymbchar(PG_SHIFT_JIS_2004, (const char *) sjis, len);
285 : :
4604 tgl@sss.pgh.pa.us 286 [ + + - + ]: 117 : if (l < 0 || l > len)
287 : : {
1109 heikki.linnakangas@i 288 [ + + ]: 54 : if (noError)
289 : 27 : break;
6230 ishii@postgresql.org 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) */
6230 ishii@postgresql.org 297 :UBC 0 : *p++ = SS2;
298 : 0 : *p++ = c1;
299 : : }
6230 ishii@postgresql.org 300 [ + - ]:CBC 63 : else if (l == 2)
301 : : {
4604 tgl@sss.pgh.pa.us 302 : 63 : int c2 = sjis[1];
303 : :
6230 ishii@postgresql.org 304 : 63 : plane = 1;
305 : 63 : ku = 1;
306 : 63 : ten = 1;
307 : :
308 : : /*
309 : : * JIS X 0213
310 : : */
2489 tgl@sss.pgh.pa.us 311 [ + - + - ]: 63 : if (c1 >= 0x81 && c1 <= 0x9f) /* plane 1 1ku-62ku */
312 : : {
6230 ishii@postgresql.org 313 : 63 : ku = (c1 << 1) - 0x100;
314 : 63 : ten = get_ten(c2, &kubun);
315 [ - + ]: 63 : if (ten < 0)
316 : : {
1109 heikki.linnakangas@i 317 [ # # ]:UBC 0 : if (noError)
318 : 0 : break;
6230 ishii@postgresql.org 319 : 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
320 : : (const char *) sjis, len);
321 : : }
6230 ishii@postgresql.org 322 :CBC 63 : ku -= kubun;
323 : : }
6230 ishii@postgresql.org 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 : : {
1109 heikki.linnakangas@i 330 [ # # ]: 0 : if (noError)
331 : 0 : break;
6230 ishii@postgresql.org 332 : 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
333 : : (const char *) sjis, len);
334 : : }
335 : 0 : ku -= kubun;
336 : : }
5995 bruce@momjian.us 337 [ # # # # ]: 0 : else if (c1 >= 0xf0 && c1 <= 0xf3) /* plane 2
338 : : * 1,3,4,5,8,12,13,14,15 ku */
339 : : {
6230 ishii@postgresql.org 340 : 0 : plane = 2;
341 : 0 : ten = get_ten(c2, &kubun);
342 [ # # ]: 0 : if (ten < 0)
343 : : {
1109 heikki.linnakangas@i 344 [ # # ]: 0 : if (noError)
345 : 0 : break;
6230 ishii@postgresql.org 346 : 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
347 : : (const char *) sjis, len);
348 : : }
349 [ # # # # ]: 0 : switch (c1)
350 : : {
351 : 0 : case 0xf0:
5995 bruce@momjian.us 352 [ # # ]: 0 : ku = kubun == 0 ? 8 : 1;
6230 ishii@postgresql.org 353 : 0 : break;
354 : 0 : case 0xf1:
5995 bruce@momjian.us 355 [ # # ]: 0 : ku = kubun == 0 ? 4 : 3;
6230 ishii@postgresql.org 356 : 0 : break;
357 : 0 : case 0xf2:
5995 bruce@momjian.us 358 [ # # ]: 0 : ku = kubun == 0 ? 12 : 5;
6230 ishii@postgresql.org 359 : 0 : break;
360 : 0 : default:
5995 bruce@momjian.us 361 [ # # ]: 0 : ku = kubun == 0 ? 14 : 13;
6230 ishii@postgresql.org 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 : : {
1109 heikki.linnakangas@i 371 [ # # ]: 0 : if (noError)
372 : 0 : break;
6230 ishii@postgresql.org 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 : : {
1109 heikki.linnakangas@i 383 [ # # ]: 0 : if (noError)
384 : 0 : break;
6230 ishii@postgresql.org 385 : 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
386 : : (const char *) sjis, len);
387 : : }
388 : :
6230 ishii@postgresql.org 389 [ - + ]:CBC 63 : if (plane == 2)
6230 ishii@postgresql.org 390 :UBC 0 : *p++ = SS3;
391 : :
6230 ishii@postgresql.org 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 : :
1109 heikki.linnakangas@i 400 : 84 : return sjis - start;
401 : : }
|