Branch data Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * EUC_JIS_2004, SHIFT_JIS_2004
4 : : *
5 : : * Copyright (c) 2007-2026, 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 : :
17 : 2 : PG_MODULE_MAGIC_EXT(
18 : : .name = "euc2004_sjis2004",
19 : : .version = PG_VERSION
20 : : );
21 : :
22 : 1 : PG_FUNCTION_INFO_V1(euc_jis_2004_to_shift_jis_2004);
23 : 2 : 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 : 1 : euc_jis_2004_to_shift_jis_2004(PG_FUNCTION_ARGS)
44 : : {
45 : 1 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
46 : 1 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
47 : 1 : int len = PG_GETARG_INT32(4);
48 : 1 : bool noError = PG_GETARG_BOOL(5);
49 : 1 : int converted;
50 : :
51 : 1 : CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_JIS_2004, PG_SHIFT_JIS_2004);
52 : :
53 : 1 : converted = euc_jis_20042shift_jis_2004(src, dest, len, noError);
54 : :
55 : 2 : PG_RETURN_INT32(converted);
56 : 1 : }
57 : :
58 : : Datum
59 : 43 : shift_jis_2004_to_euc_jis_2004(PG_FUNCTION_ARGS)
60 : : {
61 : 43 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
62 : 43 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
63 : 43 : int len = PG_GETARG_INT32(4);
64 : 43 : bool noError = PG_GETARG_BOOL(5);
65 : 43 : int converted;
66 : :
67 : 43 : CHECK_ENCODING_CONVERSION_ARGS(PG_SHIFT_JIS_2004, PG_EUC_JIS_2004);
68 : :
69 : 43 : converted = shift_jis_20042euc_jis_2004(src, dest, len, noError);
70 : :
71 : 86 : PG_RETURN_INT32(converted);
72 : 43 : }
73 : :
74 : : /*
75 : : * EUC_JIS_2004 -> SHIFT_JIS_2004
76 : : */
77 : : static int
78 : 1 : euc_jis_20042shift_jis_2004(const unsigned char *euc, unsigned char *p, int len, bool noError)
79 : : {
80 : 1 : const unsigned char *start = euc;
81 : 1 : int c1,
82 : : ku,
83 : : ten;
84 : 1 : int l;
85 : :
86 [ + + ]: 4 : while (len > 0)
87 : : {
88 : 3 : c1 = *euc;
89 [ - + ]: 3 : if (!IS_HIGHBIT_SET(c1))
90 : : {
91 : : /* ASCII */
92 [ + - ]: 3 : if (c1 == 0)
93 : : {
94 [ # # ]: 0 : if (noError)
95 : 0 : break;
96 : 0 : report_invalid_encoding(PG_EUC_JIS_2004,
97 : 0 : (const char *) euc, len);
98 : : }
99 : 3 : *p++ = c1;
100 : 3 : euc++;
101 : 3 : len--;
102 : 3 : continue;
103 : : }
104 : :
105 : 0 : l = pg_encoding_verifymbchar(PG_EUC_JIS_2004, (const char *) euc, len);
106 : :
107 [ # # ]: 0 : if (l < 0)
108 : : {
109 [ # # ]: 0 : if (noError)
110 : 0 : break;
111 : 0 : report_invalid_encoding(PG_EUC_JIS_2004,
112 : 0 : (const char *) euc, len);
113 : : }
114 : :
115 [ # # # # ]: 0 : if (c1 == SS2 && l == 2) /* JIS X 0201 kana? */
116 : : {
117 : 0 : *p++ = euc[1];
118 : 0 : }
119 [ # # # # ]: 0 : else if (c1 == SS3 && l == 3) /* JIS X 0213 plane 2? */
120 : : {
121 : 0 : ku = euc[1] - 0xa0;
122 : 0 : ten = euc[2] - 0xa0;
123 : :
124 [ # # ]: 0 : switch (ku)
125 : : {
126 : : 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 : : default:
138 [ # # # # ]: 0 : if (ku >= 78 && ku <= 94)
139 : : {
140 : 0 : *p++ = (ku + 0x19b) >> 1;
141 : 0 : }
142 : : else
143 : : {
144 [ # # ]: 0 : if (noError)
145 : 0 : break;
146 : 0 : report_invalid_encoding(PG_EUC_JIS_2004,
147 : 0 : (const char *) euc, len);
148 : : }
149 : 0 : }
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 : : {
159 [ # # ]: 0 : if (noError)
160 : 0 : break;
161 : 0 : report_invalid_encoding(PG_EUC_JIS_2004,
162 : 0 : (const char *) euc, len);
163 : : }
164 : 0 : }
165 : : else
166 : 0 : *p++ = ten + 0x9e;
167 : 0 : }
168 : :
169 [ # # ]: 0 : else if (l == 2) /* JIS X 0213 plane 1? */
170 : : {
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 : : {
180 [ # # ]: 0 : if (noError)
181 : 0 : break;
182 : 0 : report_invalid_encoding(PG_EUC_JIS_2004,
183 : 0 : (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 : : {
194 [ # # ]: 0 : if (noError)
195 : 0 : break;
196 : 0 : report_invalid_encoding(PG_EUC_JIS_2004,
197 : 0 : (const char *) euc, len);
198 : : }
199 : 0 : }
200 : : else
201 : 0 : *p++ = ten + 0x9e;
202 : 0 : }
203 : : else
204 : : {
205 [ # # ]: 0 : if (noError)
206 : 0 : break;
207 : 0 : report_invalid_encoding(PG_EUC_JIS_2004,
208 : 0 : (const char *) euc, len);
209 : : }
210 : :
211 : 0 : euc += l;
212 : 0 : len -= l;
213 : : }
214 : 1 : *p = '\0';
215 : :
216 : 2 : return euc - start;
217 : 1 : }
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
225 : 21 : get_ten(int b, int *ku)
226 : : {
227 : 21 : int ten;
228 : :
229 [ + - + - ]: 21 : if (b >= 0x40 && b <= 0x7e)
230 : : {
231 : 0 : ten = b - 0x3f;
232 : 0 : *ku = 1;
233 : 0 : }
234 [ + - + - ]: 21 : else if (b >= 0x80 && b <= 0x9e)
235 : : {
236 : 0 : ten = b - 0x40;
237 : 0 : *ku = 1;
238 : 0 : }
239 [ + - - + ]: 21 : else if (b >= 0x9f && b <= 0xfc)
240 : : {
241 : 21 : ten = b - 0x9e;
242 : 21 : *ku = 0;
243 : 21 : }
244 : : else
245 : : {
246 : 0 : ten = -1; /* error */
247 : 0 : *ku = 0; /* keep compiler quiet */
248 : : }
249 : 42 : return ten;
250 : 21 : }
251 : :
252 : : /*
253 : : * SHIFT_JIS_2004 ---> EUC_JIS_2004
254 : : */
255 : :
256 : : static int
257 : 43 : shift_jis_20042euc_jis_2004(const unsigned char *sjis, unsigned char *p, int len, bool noError)
258 : : {
259 : 43 : const unsigned char *start = sjis;
260 : 43 : int c1;
261 : 43 : int ku,
262 : : ten,
263 : : kubun;
264 : 43 : int plane;
265 : 43 : int l;
266 : :
267 [ + + ]: 193 : while (len > 0)
268 : : {
269 : 180 : c1 = *sjis;
270 : :
271 [ + + ]: 180 : if (!IS_HIGHBIT_SET(c1))
272 : : {
273 : : /* ASCII */
274 [ + + ]: 141 : if (c1 == 0)
275 : : {
276 [ + + ]: 12 : if (noError)
277 : 6 : break;
278 : 6 : report_invalid_encoding(PG_SHIFT_JIS_2004,
279 : 6 : (const char *) sjis, len);
280 : : }
281 : 129 : *p++ = c1;
282 : 129 : sjis++;
283 : 129 : len--;
284 : 129 : continue;
285 : : }
286 : :
287 : 39 : l = pg_encoding_verifymbchar(PG_SHIFT_JIS_2004, (const char *) sjis, len);
288 : :
289 [ + + - + ]: 39 : if (l < 0 || l > len)
290 : : {
291 [ + + ]: 18 : if (noError)
292 : 9 : break;
293 : 9 : report_invalid_encoding(PG_SHIFT_JIS_2004,
294 : 9 : (const char *) sjis, len);
295 : : }
296 : :
297 [ - + # # : 21 : if (c1 >= 0xa1 && c1 <= 0xdf && l == 1)
# # ]
298 : : {
299 : : /* JIS X0201 (1 byte kana) */
300 : 0 : *p++ = SS2;
301 : 0 : *p++ = c1;
302 : 0 : }
303 [ - + ]: 21 : else if (l == 2)
304 : : {
305 : 21 : int c2 = sjis[1];
306 : :
307 : 21 : plane = 1;
308 : 21 : ku = 1;
309 : 21 : ten = 1;
310 : :
311 : : /*
312 : : * JIS X 0213
313 : : */
314 [ + - - + ]: 21 : if (c1 >= 0x81 && c1 <= 0x9f) /* plane 1 1ku-62ku */
315 : : {
316 : 21 : ku = (c1 << 1) - 0x100;
317 : 21 : ten = get_ten(c2, &kubun);
318 [ + - ]: 21 : if (ten < 0)
319 : : {
320 [ # # ]: 0 : if (noError)
321 : 0 : break;
322 : 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
323 : 0 : (const char *) sjis, len);
324 : : }
325 : 21 : ku -= kubun;
326 : 21 : }
327 [ # # # # ]: 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 : : {
333 [ # # ]: 0 : if (noError)
334 : 0 : break;
335 : 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
336 : 0 : (const char *) sjis, len);
337 : : }
338 : 0 : ku -= kubun;
339 : 0 : }
340 [ # # # # ]: 0 : else if (c1 >= 0xf0 && c1 <= 0xf3) /* plane 2
341 : : * 1,3,4,5,8,12,13,14,15 ku */
342 : : {
343 : 0 : plane = 2;
344 : 0 : ten = get_ten(c2, &kubun);
345 [ # # ]: 0 : if (ten < 0)
346 : : {
347 [ # # ]: 0 : if (noError)
348 : 0 : break;
349 : 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
350 : 0 : (const char *) sjis, len);
351 : : }
352 [ # # # # ]: 0 : switch (c1)
353 : : {
354 : : case 0xf0:
355 : 0 : ku = kubun == 0 ? 8 : 1;
356 : 0 : break;
357 : : case 0xf1:
358 : 0 : ku = kubun == 0 ? 4 : 3;
359 : 0 : break;
360 : : case 0xf2:
361 : 0 : ku = kubun == 0 ? 12 : 5;
362 : 0 : break;
363 : : default:
364 : 0 : ku = kubun == 0 ? 14 : 13;
365 : 0 : break;
366 : : }
367 : 0 : }
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 : : {
374 [ # # ]: 0 : if (noError)
375 : 0 : break;
376 : 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
377 : 0 : (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 : 0 : }
384 : : else
385 : : {
386 [ # # ]: 0 : if (noError)
387 : 0 : break;
388 : 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
389 : 0 : (const char *) sjis, len);
390 : : }
391 : :
392 [ + - ]: 21 : if (plane == 2)
393 : 0 : *p++ = SS3;
394 : :
395 : 21 : *p++ = ku + 0xa0;
396 : 21 : *p++ = ten + 0xa0;
397 [ - - + ]: 21 : }
398 : 21 : sjis += l;
399 : 21 : len -= l;
400 : : }
401 : 28 : *p = '\0';
402 : :
403 : 56 : return sjis - start;
404 : 28 : }
|