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 :
17 12 : PG_MODULE_MAGIC_EXT(
18 : .name = "euc2004_sjis2004",
19 : .version = PG_VERSION
20 : );
21 :
22 6 : PG_FUNCTION_INFO_V1(euc_jis_2004_to_shift_jis_2004);
23 12 : 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 6 : euc_jis_2004_to_shift_jis_2004(PG_FUNCTION_ARGS)
44 : {
45 6 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
46 6 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
47 6 : int len = PG_GETARG_INT32(4);
48 6 : bool noError = PG_GETARG_BOOL(5);
49 : int converted;
50 :
51 6 : CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_JIS_2004, PG_SHIFT_JIS_2004);
52 :
53 6 : converted = euc_jis_20042shift_jis_2004(src, dest, len, noError);
54 :
55 6 : PG_RETURN_INT32(converted);
56 : }
57 :
58 : Datum
59 258 : shift_jis_2004_to_euc_jis_2004(PG_FUNCTION_ARGS)
60 : {
61 258 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
62 258 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
63 258 : int len = PG_GETARG_INT32(4);
64 258 : bool noError = PG_GETARG_BOOL(5);
65 : int converted;
66 :
67 258 : CHECK_ENCODING_CONVERSION_ARGS(PG_SHIFT_JIS_2004, PG_EUC_JIS_2004);
68 :
69 258 : converted = shift_jis_20042euc_jis_2004(src, dest, len, noError);
70 :
71 168 : PG_RETURN_INT32(converted);
72 : }
73 :
74 : /*
75 : * EUC_JIS_2004 -> SHIFT_JIS_2004
76 : */
77 : static int
78 6 : euc_jis_20042shift_jis_2004(const unsigned char *euc, unsigned char *p, int len, bool noError)
79 : {
80 6 : const unsigned char *start = euc;
81 : int c1,
82 : ku,
83 : ten;
84 : int l;
85 :
86 24 : while (len > 0)
87 : {
88 18 : c1 = *euc;
89 18 : if (!IS_HIGHBIT_SET(c1))
90 : {
91 : /* ASCII */
92 18 : if (c1 == 0)
93 : {
94 0 : if (noError)
95 0 : break;
96 0 : report_invalid_encoding(PG_EUC_JIS_2004,
97 : (const char *) euc, len);
98 : }
99 18 : *p++ = c1;
100 18 : euc++;
101 18 : len--;
102 18 : 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 : (const char *) euc, len);
113 : }
114 :
115 0 : if (c1 == SS2 && l == 2) /* JIS X 0201 kana? */
116 : {
117 0 : *p++ = euc[1];
118 : }
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 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 : {
144 0 : if (noError)
145 0 : break;
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 : {
159 0 : if (noError)
160 0 : break;
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 :
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 : (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 : (const char *) euc, len);
198 : }
199 : }
200 : else
201 0 : *p++ = ten + 0x9e;
202 : }
203 : else
204 : {
205 0 : if (noError)
206 0 : break;
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 : }
214 6 : *p = '\0';
215 :
216 6 : 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
225 126 : get_ten(int b, int *ku)
226 : {
227 : int ten;
228 :
229 126 : if (b >= 0x40 && b <= 0x7e)
230 : {
231 0 : ten = b - 0x3f;
232 0 : *ku = 1;
233 : }
234 126 : else if (b >= 0x80 && b <= 0x9e)
235 : {
236 0 : ten = b - 0x40;
237 0 : *ku = 1;
238 : }
239 126 : else if (b >= 0x9f && b <= 0xfc)
240 : {
241 126 : ten = b - 0x9e;
242 126 : *ku = 0;
243 : }
244 : else
245 : {
246 0 : ten = -1; /* error */
247 0 : *ku = 0; /* keep compiler quiet */
248 : }
249 126 : return ten;
250 : }
251 :
252 : /*
253 : * SHIFT_JIS_2004 ---> EUC_JIS_2004
254 : */
255 :
256 : static int
257 258 : shift_jis_20042euc_jis_2004(const unsigned char *sjis, unsigned char *p, int len, bool noError)
258 : {
259 258 : const unsigned char *start = sjis;
260 : int c1;
261 : int ku,
262 : ten,
263 : kubun;
264 : int plane;
265 : int l;
266 :
267 1158 : while (len > 0)
268 : {
269 1080 : c1 = *sjis;
270 :
271 1080 : if (!IS_HIGHBIT_SET(c1))
272 : {
273 : /* ASCII */
274 846 : if (c1 == 0)
275 : {
276 72 : if (noError)
277 36 : break;
278 36 : report_invalid_encoding(PG_SHIFT_JIS_2004,
279 : (const char *) sjis, len);
280 : }
281 774 : *p++ = c1;
282 774 : sjis++;
283 774 : len--;
284 774 : continue;
285 : }
286 :
287 234 : l = pg_encoding_verifymbchar(PG_SHIFT_JIS_2004, (const char *) sjis, len);
288 :
289 234 : if (l < 0 || l > len)
290 : {
291 108 : if (noError)
292 54 : break;
293 54 : report_invalid_encoding(PG_SHIFT_JIS_2004,
294 : (const char *) sjis, len);
295 : }
296 :
297 126 : if (c1 >= 0xa1 && c1 <= 0xdf && l == 1)
298 : {
299 : /* JIS X0201 (1 byte kana) */
300 0 : *p++ = SS2;
301 0 : *p++ = c1;
302 : }
303 126 : else if (l == 2)
304 : {
305 126 : int c2 = sjis[1];
306 :
307 126 : plane = 1;
308 126 : ku = 1;
309 126 : ten = 1;
310 :
311 : /*
312 : * JIS X 0213
313 : */
314 126 : if (c1 >= 0x81 && c1 <= 0x9f) /* plane 1 1ku-62ku */
315 : {
316 126 : ku = (c1 << 1) - 0x100;
317 126 : ten = get_ten(c2, &kubun);
318 126 : if (ten < 0)
319 : {
320 0 : if (noError)
321 0 : break;
322 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
323 : (const char *) sjis, len);
324 : }
325 126 : ku -= kubun;
326 : }
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 : (const char *) sjis, len);
337 : }
338 0 : ku -= kubun;
339 : }
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 : (const char *) sjis, len);
351 : }
352 0 : switch (c1)
353 : {
354 0 : case 0xf0:
355 0 : ku = kubun == 0 ? 8 : 1;
356 0 : break;
357 0 : case 0xf1:
358 0 : ku = kubun == 0 ? 4 : 3;
359 0 : break;
360 0 : case 0xf2:
361 0 : ku = kubun == 0 ? 12 : 5;
362 0 : break;
363 0 : default:
364 0 : ku = kubun == 0 ? 14 : 13;
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 : {
374 0 : if (noError)
375 0 : break;
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 : {
386 0 : if (noError)
387 0 : break;
388 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
389 : (const char *) sjis, len);
390 : }
391 :
392 126 : if (plane == 2)
393 0 : *p++ = SS3;
394 :
395 126 : *p++ = ku + 0xa0;
396 126 : *p++ = ten + 0xa0;
397 : }
398 126 : sjis += l;
399 126 : len -= l;
400 : }
401 168 : *p = '\0';
402 :
403 168 : return sjis - start;
404 : }
|