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 :
17 12 : PG_MODULE_MAGIC;
18 :
19 6 : PG_FUNCTION_INFO_V1(euc_jis_2004_to_shift_jis_2004);
20 12 : 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 6 : euc_jis_2004_to_shift_jis_2004(PG_FUNCTION_ARGS)
41 : {
42 6 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
43 6 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
44 6 : int len = PG_GETARG_INT32(4);
45 6 : bool noError = PG_GETARG_BOOL(5);
46 : int converted;
47 :
48 6 : CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_JIS_2004, PG_SHIFT_JIS_2004);
49 :
50 6 : converted = euc_jis_20042shift_jis_2004(src, dest, len, noError);
51 :
52 6 : PG_RETURN_INT32(converted);
53 : }
54 :
55 : Datum
56 258 : shift_jis_2004_to_euc_jis_2004(PG_FUNCTION_ARGS)
57 : {
58 258 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
59 258 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
60 258 : int len = PG_GETARG_INT32(4);
61 258 : bool noError = PG_GETARG_BOOL(5);
62 : int converted;
63 :
64 258 : CHECK_ENCODING_CONVERSION_ARGS(PG_SHIFT_JIS_2004, PG_EUC_JIS_2004);
65 :
66 258 : converted = shift_jis_20042euc_jis_2004(src, dest, len, noError);
67 :
68 168 : PG_RETURN_INT32(converted);
69 : }
70 :
71 : /*
72 : * EUC_JIS_2004 -> SHIFT_JIS_2004
73 : */
74 : static int
75 6 : euc_jis_20042shift_jis_2004(const unsigned char *euc, unsigned char *p, int len, bool noError)
76 : {
77 6 : const unsigned char *start = euc;
78 : int c1,
79 : ku,
80 : ten;
81 : int l;
82 :
83 24 : while (len > 0)
84 : {
85 18 : c1 = *euc;
86 18 : if (!IS_HIGHBIT_SET(c1))
87 : {
88 : /* ASCII */
89 18 : if (c1 == 0)
90 : {
91 0 : if (noError)
92 0 : break;
93 0 : report_invalid_encoding(PG_EUC_JIS_2004,
94 : (const char *) euc, len);
95 : }
96 18 : *p++ = c1;
97 18 : euc++;
98 18 : len--;
99 18 : continue;
100 : }
101 :
102 0 : l = pg_encoding_verifymbchar(PG_EUC_JIS_2004, (const char *) euc, len);
103 :
104 0 : if (l < 0)
105 : {
106 0 : if (noError)
107 0 : break;
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 : }
116 0 : else if (c1 == SS3 && l == 3) /* JIS X 0213 plane 2? */
117 : {
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 : {
141 0 : if (noError)
142 0 : break;
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 : {
156 0 : if (noError)
157 0 : break;
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 :
166 0 : else if (l == 2) /* JIS X 0213 plane 1? */
167 : {
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 : {
177 0 : if (noError)
178 0 : break;
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 : {
191 0 : if (noError)
192 0 : break;
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 : {
202 0 : if (noError)
203 0 : break;
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 : }
211 6 : *p = '\0';
212 :
213 6 : 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
222 126 : get_ten(int b, int *ku)
223 : {
224 : int ten;
225 :
226 126 : if (b >= 0x40 && b <= 0x7e)
227 : {
228 0 : ten = b - 0x3f;
229 0 : *ku = 1;
230 : }
231 126 : else if (b >= 0x80 && b <= 0x9e)
232 : {
233 0 : ten = b - 0x40;
234 0 : *ku = 1;
235 : }
236 126 : else if (b >= 0x9f && b <= 0xfc)
237 : {
238 126 : ten = b - 0x9e;
239 126 : *ku = 0;
240 : }
241 : else
242 : {
243 0 : ten = -1; /* error */
244 0 : *ku = 0; /* keep compiler quiet */
245 : }
246 126 : return ten;
247 : }
248 :
249 : /*
250 : * SHIFT_JIS_2004 ---> EUC_JIS_2004
251 : */
252 :
253 : static int
254 258 : shift_jis_20042euc_jis_2004(const unsigned char *sjis, unsigned char *p, int len, bool noError)
255 : {
256 258 : const unsigned char *start = sjis;
257 : int c1;
258 : int ku,
259 : ten,
260 : kubun;
261 : int plane;
262 : int l;
263 :
264 1158 : while (len > 0)
265 : {
266 1080 : c1 = *sjis;
267 :
268 1080 : if (!IS_HIGHBIT_SET(c1))
269 : {
270 : /* ASCII */
271 846 : if (c1 == 0)
272 : {
273 72 : if (noError)
274 36 : break;
275 36 : report_invalid_encoding(PG_SHIFT_JIS_2004,
276 : (const char *) sjis, len);
277 : }
278 774 : *p++ = c1;
279 774 : sjis++;
280 774 : len--;
281 774 : continue;
282 : }
283 :
284 234 : l = pg_encoding_verifymbchar(PG_SHIFT_JIS_2004, (const char *) sjis, len);
285 :
286 234 : if (l < 0 || l > len)
287 : {
288 108 : if (noError)
289 54 : break;
290 54 : report_invalid_encoding(PG_SHIFT_JIS_2004,
291 : (const char *) sjis, len);
292 : }
293 :
294 126 : if (c1 >= 0xa1 && c1 <= 0xdf && l == 1)
295 : {
296 : /* JIS X0201 (1 byte kana) */
297 0 : *p++ = SS2;
298 0 : *p++ = c1;
299 : }
300 126 : else if (l == 2)
301 : {
302 126 : int c2 = sjis[1];
303 :
304 126 : plane = 1;
305 126 : ku = 1;
306 126 : ten = 1;
307 :
308 : /*
309 : * JIS X 0213
310 : */
311 126 : if (c1 >= 0x81 && c1 <= 0x9f) /* plane 1 1ku-62ku */
312 : {
313 126 : ku = (c1 << 1) - 0x100;
314 126 : ten = get_ten(c2, &kubun);
315 126 : if (ten < 0)
316 : {
317 0 : if (noError)
318 0 : break;
319 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
320 : (const char *) sjis, len);
321 : }
322 126 : ku -= kubun;
323 : }
324 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 : {
330 0 : if (noError)
331 0 : break;
332 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
333 : (const char *) sjis, len);
334 : }
335 0 : ku -= kubun;
336 : }
337 0 : else if (c1 >= 0xf0 && c1 <= 0xf3) /* plane 2
338 : * 1,3,4,5,8,12,13,14,15 ku */
339 : {
340 0 : plane = 2;
341 0 : ten = get_ten(c2, &kubun);
342 0 : if (ten < 0)
343 : {
344 0 : if (noError)
345 0 : break;
346 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
347 : (const char *) sjis, len);
348 : }
349 0 : switch (c1)
350 : {
351 0 : case 0xf0:
352 0 : ku = kubun == 0 ? 8 : 1;
353 0 : break;
354 0 : case 0xf1:
355 0 : ku = kubun == 0 ? 4 : 3;
356 0 : break;
357 0 : case 0xf2:
358 0 : ku = kubun == 0 ? 12 : 5;
359 0 : break;
360 0 : default:
361 0 : ku = kubun == 0 ? 14 : 13;
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 : {
371 0 : if (noError)
372 0 : break;
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 : {
383 0 : if (noError)
384 0 : break;
385 0 : report_invalid_encoding(PG_SHIFT_JIS_2004,
386 : (const char *) sjis, len);
387 : }
388 :
389 126 : if (plane == 2)
390 0 : *p++ = SS3;
391 :
392 126 : *p++ = ku + 0xa0;
393 126 : *p++ = ten + 0xa0;
394 : }
395 126 : sjis += l;
396 126 : len -= l;
397 : }
398 168 : *p = '\0';
399 :
400 168 : return sjis - start;
401 : }
|