Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * EUC_KR and MULE_INTERNAL
4 : *
5 : * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
6 : * Portions Copyright (c) 1994, Regents of the University of California
7 : *
8 : * IDENTIFICATION
9 : * src/backend/utils/mb/conversion_procs/euc_kr_and_mic/euc_kr_and_mic.c
10 : *
11 : *-------------------------------------------------------------------------
12 : */
13 :
14 : #include "postgres.h"
15 : #include "fmgr.h"
16 : #include "mb/pg_wchar.h"
17 :
18 6 : PG_MODULE_MAGIC;
19 :
20 6 : PG_FUNCTION_INFO_V1(euc_kr_to_mic);
21 6 : PG_FUNCTION_INFO_V1(mic_to_euc_kr);
22 :
23 : /* ----------
24 : * conv_proc(
25 : * INTEGER, -- source encoding id
26 : * INTEGER, -- destination encoding id
27 : * CSTRING, -- source string (null terminated C string)
28 : * CSTRING, -- destination string (null terminated C string)
29 : * INTEGER, -- source string length
30 : * BOOL -- if true, don't throw an error if conversion fails
31 : * ) returns INTEGER;
32 : *
33 : * Returns the number of bytes successfully converted.
34 : * ----------
35 : */
36 :
37 : static int euc_kr2mic(const unsigned char *euc, unsigned char *p, int len, bool noError);
38 : static int mic2euc_kr(const unsigned char *mic, unsigned char *p, int len, bool noError);
39 :
40 : Datum
41 6 : euc_kr_to_mic(PG_FUNCTION_ARGS)
42 : {
43 6 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
44 6 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
45 6 : int len = PG_GETARG_INT32(4);
46 6 : bool noError = PG_GETARG_BOOL(5);
47 : int converted;
48 :
49 6 : CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_KR, PG_MULE_INTERNAL);
50 :
51 6 : converted = euc_kr2mic(src, dest, len, noError);
52 :
53 6 : PG_RETURN_INT32(converted);
54 : }
55 :
56 : Datum
57 6 : mic_to_euc_kr(PG_FUNCTION_ARGS)
58 : {
59 6 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
60 6 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
61 6 : int len = PG_GETARG_INT32(4);
62 6 : bool noError = PG_GETARG_BOOL(5);
63 : int converted;
64 :
65 6 : CHECK_ENCODING_CONVERSION_ARGS(PG_MULE_INTERNAL, PG_EUC_KR);
66 :
67 6 : converted = mic2euc_kr(src, dest, len, noError);
68 :
69 6 : PG_RETURN_INT32(converted);
70 : }
71 :
72 : /*
73 : * EUC_KR ---> MIC
74 : */
75 : static int
76 6 : euc_kr2mic(const unsigned char *euc, unsigned char *p, int len, bool noError)
77 : {
78 6 : const unsigned char *start = euc;
79 : int c1;
80 : int l;
81 :
82 24 : while (len > 0)
83 : {
84 18 : c1 = *euc;
85 18 : if (IS_HIGHBIT_SET(c1))
86 : {
87 0 : l = pg_encoding_verifymbchar(PG_EUC_KR, (const char *) euc, len);
88 0 : if (l != 2)
89 : {
90 0 : if (noError)
91 0 : break;
92 0 : report_invalid_encoding(PG_EUC_KR,
93 : (const char *) euc, len);
94 : }
95 0 : *p++ = LC_KS5601;
96 0 : *p++ = c1;
97 0 : *p++ = euc[1];
98 0 : euc += 2;
99 0 : len -= 2;
100 : }
101 : else
102 : { /* should be ASCII */
103 18 : if (c1 == 0)
104 : {
105 0 : if (noError)
106 0 : break;
107 0 : report_invalid_encoding(PG_EUC_KR,
108 : (const char *) euc, len);
109 : }
110 18 : *p++ = c1;
111 18 : euc++;
112 18 : len--;
113 : }
114 : }
115 6 : *p = '\0';
116 :
117 6 : return euc - start;
118 : }
119 :
120 : /*
121 : * MIC ---> EUC_KR
122 : */
123 : static int
124 6 : mic2euc_kr(const unsigned char *mic, unsigned char *p, int len, bool noError)
125 : {
126 6 : const unsigned char *start = mic;
127 : int c1;
128 : int l;
129 :
130 24 : while (len > 0)
131 : {
132 18 : c1 = *mic;
133 18 : if (!IS_HIGHBIT_SET(c1))
134 : {
135 : /* ASCII */
136 18 : if (c1 == 0)
137 : {
138 0 : if (noError)
139 0 : break;
140 0 : report_invalid_encoding(PG_MULE_INTERNAL,
141 : (const char *) mic, len);
142 : }
143 18 : *p++ = c1;
144 18 : mic++;
145 18 : len--;
146 18 : continue;
147 : }
148 0 : l = pg_encoding_verifymbchar(PG_MULE_INTERNAL, (const char *) mic, len);
149 0 : if (l < 0)
150 : {
151 0 : if (noError)
152 0 : break;
153 0 : report_invalid_encoding(PG_MULE_INTERNAL,
154 : (const char *) mic, len);
155 : }
156 0 : if (c1 == LC_KS5601)
157 : {
158 0 : *p++ = mic[1];
159 0 : *p++ = mic[2];
160 : }
161 : else
162 : {
163 0 : if (noError)
164 0 : break;
165 0 : report_untranslatable_char(PG_MULE_INTERNAL, PG_EUC_KR,
166 : (const char *) mic, len);
167 : }
168 0 : mic += l;
169 0 : len -= l;
170 : }
171 6 : *p = '\0';
172 :
173 6 : return mic - start;
174 : }
|