OSDN Git Service

pgindent run.
[pg-rex/syncrep.git] / src / backend / utils / mb / conversion_procs / euc_tw_and_big5 / euc_tw_and_big5.c
1 /*-------------------------------------------------------------------------
2  *
3  *        EUC_TW, BIG5 and MULE_INTERNAL
4  *
5  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
6  * Portions Copyright (c) 1994, Regents of the University of California
7  *
8  * IDENTIFICATION
9  *        $Header: /cvsroot/pgsql/src/backend/utils/mb/conversion_procs/euc_tw_and_big5/euc_tw_and_big5.c,v 1.3 2002/09/04 20:31:31 momjian Exp $
10  *
11  *-------------------------------------------------------------------------
12  */
13
14 #include "postgres.h"
15 #include "fmgr.h"
16 #include "mb/pg_wchar.h"
17
18 #define ENCODING_GROWTH_RATE 4
19
20 PG_FUNCTION_INFO_V1(euc_tw_to_big5)
21 PG_FUNCTION_INFO_V1(big5_to_euc_tw)
22 PG_FUNCTION_INFO_V1(euc_tw_to_mic)
23 PG_FUNCTION_INFO_V1(mic_to_euc_tw)
24 PG_FUNCTION_INFO_V1(big5_to_mic)
25 PG_FUNCTION_INFO_V1(mic_to_big5)
26
27 extern Datum euc_tw_to_big5(PG_FUNCTION_ARGS);
28 extern Datum big5_to_euc_tw(PG_FUNCTION_ARGS);
29 extern Datum euc_tw_to_mic(PG_FUNCTION_ARGS);
30 extern Datum mic_to_euc_tw(PG_FUNCTION_ARGS);
31 extern Datum big5_to_mic(PG_FUNCTION_ARGS);
32 extern Datum mic_to_big5(PG_FUNCTION_ARGS);
33
34 /* ----------
35  * conv_proc(
36  *              INTEGER,        -- source encoding id
37  *              INTEGER,        -- destination encoding id
38  *              CSTRING,        -- source string (null terminated C string)
39  *              CSTRING,        -- destination string (null terminated C string)
40  *              INTEGER         -- source string length
41  * ) returns VOID;
42  * ----------
43  */
44
45 static void big52mic(unsigned char *big5, unsigned char *p, int len);
46 static void mic2big5(unsigned char *mic, unsigned char *p, int len);
47 static void euc_tw2mic(unsigned char *euc, unsigned char *p, int len);
48 static void mic2euc_tw(unsigned char *mic, unsigned char *p, int len);
49
50 Datum
51 euc_tw_to_big5(PG_FUNCTION_ARGS)
52 {
53         unsigned char *src = PG_GETARG_CSTRING(2);
54         unsigned char *dest = PG_GETARG_CSTRING(3);
55         int                     len = PG_GETARG_INT32(4);
56         unsigned char *buf;
57
58         Assert(PG_GETARG_INT32(0) == PG_EUC_TW);
59         Assert(PG_GETARG_INT32(1) == PG_BIG5);
60         Assert(len > 0);
61
62         buf = palloc(len * ENCODING_GROWTH_RATE);
63         euc_tw2mic(src, buf, len);
64         mic2big5(buf, dest, strlen(buf));
65         pfree(buf);
66
67         PG_RETURN_INT32(0);
68 }
69
70 Datum
71 big5_to_euc_tw(PG_FUNCTION_ARGS)
72 {
73         unsigned char *src = PG_GETARG_CSTRING(2);
74         unsigned char *dest = PG_GETARG_CSTRING(3);
75         int                     len = PG_GETARG_INT32(4);
76         unsigned char *buf;
77
78         Assert(PG_GETARG_INT32(0) == PG_BIG5);
79         Assert(PG_GETARG_INT32(1) == PG_EUC_TW);
80         Assert(len > 0);
81
82         buf = palloc(len * ENCODING_GROWTH_RATE);
83         big52mic(src, buf, len);
84         mic2euc_tw(buf, dest, strlen(buf));
85         pfree(buf);
86
87         PG_RETURN_INT32(0);
88 }
89
90 Datum
91 euc_tw_to_mic(PG_FUNCTION_ARGS)
92 {
93         unsigned char *src = PG_GETARG_CSTRING(2);
94         unsigned char *dest = PG_GETARG_CSTRING(3);
95         int                     len = PG_GETARG_INT32(4);
96
97         Assert(PG_GETARG_INT32(0) == PG_EUC_TW);
98         Assert(PG_GETARG_INT32(1) == PG_MULE_INTERNAL);
99         Assert(len > 0);
100
101         euc_tw2mic(src, dest, len);
102
103         PG_RETURN_INT32(0);
104 }
105
106 Datum
107 mic_to_euc_tw(PG_FUNCTION_ARGS)
108 {
109         unsigned char *src = PG_GETARG_CSTRING(2);
110         unsigned char *dest = PG_GETARG_CSTRING(3);
111         int                     len = PG_GETARG_INT32(4);
112
113         Assert(PG_GETARG_INT32(0) == PG_MULE_INTERNAL);
114         Assert(PG_GETARG_INT32(1) == PG_EUC_TW);
115         Assert(len > 0);
116
117         mic2big5(src, dest, len);
118
119         PG_RETURN_INT32(0);
120 }
121
122 Datum
123 big5_to_mic(PG_FUNCTION_ARGS)
124 {
125         unsigned char *src = PG_GETARG_CSTRING(2);
126         unsigned char *dest = PG_GETARG_CSTRING(3);
127         int                     len = PG_GETARG_INT32(4);
128
129         Assert(PG_GETARG_INT32(0) == PG_BIG5);
130         Assert(PG_GETARG_INT32(1) == PG_MULE_INTERNAL);
131         Assert(len > 0);
132
133         big52mic(src, dest, len);
134
135         PG_RETURN_INT32(0);
136 }
137
138 Datum
139 mic_to_big5(PG_FUNCTION_ARGS)
140 {
141         unsigned char *src = PG_GETARG_CSTRING(2);
142         unsigned char *dest = PG_GETARG_CSTRING(3);
143         int                     len = PG_GETARG_INT32(4);
144
145         Assert(PG_GETARG_INT32(0) == PG_MULE_INTERNAL);
146         Assert(PG_GETARG_INT32(1) == PG_BIG5);
147         Assert(len > 0);
148
149         mic2big5(src, dest, len);
150
151         PG_RETURN_INT32(0);
152 }
153
154 /*
155  * EUC_TW ---> MIC
156  */
157 static void
158 euc_tw2mic(unsigned char *euc, unsigned char *p, int len)
159 {
160         int                     c1;
161
162         while (len > 0 && (c1 = *euc++))
163         {
164                 if (c1 == SS2)
165                 {
166                         len -= 4;
167                         c1 = *euc++;            /* plane No. */
168                         if (c1 == 0xa1)
169                                 *p++ = LC_CNS11643_1;
170                         else if (c1 == 0xa2)
171                                 *p++ = LC_CNS11643_2;
172                         else
173                         {
174                                 *p++ = 0x9d;    /* LCPRV2 */
175                                 *p++ = 0xa3 - c1 + LC_CNS11643_3;
176                         }
177                         *p++ = *euc++;
178                         *p++ = *euc++;
179                 }
180                 else if (c1 & 0x80)
181                 {                                               /* CNS11643-1 */
182                         len -= 2;
183                         *p++ = LC_CNS11643_1;
184                         *p++ = c1;
185                         *p++ = *euc++;
186                 }
187                 else
188                 {                                               /* should be ASCII */
189                         len--;
190                         *p++ = c1;
191                 }
192         }
193         *p = '\0';
194 }
195
196 /*
197  * MIC ---> EUC_TW
198  */
199 static void
200 mic2euc_tw(unsigned char *mic, unsigned char *p, int len)
201 {
202         int                     c1;
203
204         while (len > 0 && (c1 = *mic))
205         {
206                 len -= pg_mic_mblen(mic++);
207
208                 if (c1 == LC_CNS11643_1)
209                 {
210                         *p++ = *mic++;
211                         *p++ = *mic++;
212                 }
213                 else if (c1 == LC_CNS11643_2)
214                 {
215                         *p++ = SS2;
216                         *p++ = 0xa2;
217                         *p++ = *mic++;
218                         *p++ = *mic++;
219                 }
220                 else if (c1 == 0x9d)
221                 {                                               /* LCPRV2? */
222                         *p++ = SS2;
223                         *p++ = *mic++ - LC_CNS11643_3 + 0xa3;
224                         *p++ = *mic++;
225                         *p++ = *mic++;
226                 }
227                 else if (c1 > 0x7f)
228                 {                                               /* cannot convert to EUC_TW! */
229                         mic--;
230                         pg_print_bogus_char(&mic, &p);
231                 }
232                 else
233                 {                                               /* should be ASCII */
234                         *p++ = c1;
235                 }
236         }
237         *p = '\0';
238 }
239
240 /*
241  * Big5 ---> MIC
242  */
243 static void
244 big52mic(unsigned char *big5, unsigned char *p, int len)
245 {
246         unsigned short c1;
247         unsigned short big5buf,
248                                 cnsBuf;
249         unsigned char lc;
250         char            bogusBuf[3];
251         int                     i;
252
253         while (len > 0 && (c1 = *big5++))
254         {
255                 if (c1 <= 0x7fU)
256                 {                                               /* ASCII */
257                         len--;
258                         *p++ = c1;
259                 }
260                 else
261                 {
262                         len -= 2;
263                         big5buf = c1 << 8;
264                         c1 = *big5++;
265                         big5buf |= c1;
266                         cnsBuf = BIG5toCNS(big5buf, &lc);
267                         if (lc != 0)
268                         {
269                                 if (lc == LC_CNS11643_3 || lc == LC_CNS11643_4)
270                                 {
271                                         *p++ = 0x9d;    /* LCPRV2 */
272                                 }
273                                 *p++ = lc;              /* Plane No. */
274                                 *p++ = (cnsBuf >> 8) & 0x00ff;
275                                 *p++ = cnsBuf & 0x00ff;
276                         }
277                         else
278                         {                                       /* cannot convert */
279                                 big5 -= 2;
280                                 *p++ = '(';
281                                 for (i = 0; i < 2; i++)
282                                 {
283                                         sprintf(bogusBuf, "%02x", *big5++);
284                                         *p++ = bogusBuf[0];
285                                         *p++ = bogusBuf[1];
286                                 }
287                                 *p++ = ')';
288                         }
289                 }
290         }
291         *p = '\0';
292 }
293
294 /*
295  * MIC ---> Big5
296  */
297 static void
298 mic2big5(unsigned char *mic, unsigned char *p, int len)
299 {
300         int                     l;
301         unsigned short c1;
302         unsigned short big5buf,
303                                 cnsBuf;
304
305         while (len > 0 && (c1 = *mic))
306         {
307                 l = pg_mic_mblen(mic++);
308                 len -= l;
309
310                 /* 0x9d means LCPRV2 */
311                 if (c1 == LC_CNS11643_1 || c1 == LC_CNS11643_2 || c1 == 0x9d)
312                 {
313                         if (c1 == 0x9d)
314                         {
315                                 c1 = *mic++;    /* get plane no. */
316                         }
317                         cnsBuf = (*mic++) << 8;
318                         cnsBuf |= (*mic++) & 0x00ff;
319                         big5buf = CNStoBIG5(cnsBuf, c1);
320                         if (big5buf == 0)
321                         {                                       /* cannot convert to Big5! */
322                                 mic -= l;
323                                 pg_print_bogus_char(&mic, &p);
324                         }
325                         else
326                         {
327                                 *p++ = (big5buf >> 8) & 0x00ff;
328                                 *p++ = big5buf & 0x00ff;
329                         }
330                 }
331                 else if (c1 <= 0x7f)    /* ASCII */
332                         *p++ = c1;
333                 else
334                 {                                               /* cannot convert to Big5! */
335                         mic--;
336                         pg_print_bogus_char(&mic, &p);
337                 }
338         }
339         *p = '\0';
340 }