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