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