Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * EUC_CN 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_cn_and_mic/euc_cn_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_cn_and_mic",
20 : .version = PG_VERSION
21 : );
22 :
23 6 : PG_FUNCTION_INFO_V1(euc_cn_to_mic);
24 6 : PG_FUNCTION_INFO_V1(mic_to_euc_cn);
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_cn2mic(const unsigned char *euc, unsigned char *p, int len, bool noError);
41 : static int mic2euc_cn(const unsigned char *mic, unsigned char *p, int len, bool noError);
42 :
43 : Datum
44 6 : euc_cn_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_CN, PG_MULE_INTERNAL);
53 :
54 6 : converted = euc_cn2mic(src, dest, len, noError);
55 :
56 6 : PG_RETURN_INT32(converted);
57 : }
58 :
59 : Datum
60 6 : mic_to_euc_cn(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_CN);
69 :
70 6 : converted = mic2euc_cn(src, dest, len, noError);
71 :
72 6 : PG_RETURN_INT32(converted);
73 : }
74 :
75 : /*
76 : * EUC_CN ---> MIC
77 : */
78 : static int
79 6 : euc_cn2mic(const unsigned char *euc, unsigned char *p, int len, bool noError)
80 : {
81 6 : const unsigned char *start = euc;
82 : int c1;
83 :
84 24 : while (len > 0)
85 : {
86 18 : c1 = *euc;
87 18 : if (IS_HIGHBIT_SET(c1))
88 : {
89 0 : if (len < 2 || !IS_HIGHBIT_SET(euc[1]))
90 : {
91 0 : if (noError)
92 0 : break;
93 0 : report_invalid_encoding(PG_EUC_CN, (const char *) euc, len);
94 : }
95 0 : *p++ = LC_GB2312_80;
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_CN, (const char *) euc, len);
108 : }
109 18 : *p++ = c1;
110 18 : euc++;
111 18 : len--;
112 : }
113 : }
114 6 : *p = '\0';
115 :
116 6 : return euc - start;
117 : }
118 :
119 : /*
120 : * MIC ---> EUC_CN
121 : */
122 : static int
123 6 : mic2euc_cn(const unsigned char *mic, unsigned char *p, int len, bool noError)
124 : {
125 6 : const unsigned char *start = mic;
126 : int c1;
127 :
128 24 : while (len > 0)
129 : {
130 18 : c1 = *mic;
131 18 : if (IS_HIGHBIT_SET(c1))
132 : {
133 0 : if (c1 != LC_GB2312_80)
134 : {
135 0 : if (noError)
136 0 : break;
137 0 : report_untranslatable_char(PG_MULE_INTERNAL, PG_EUC_CN,
138 : (const char *) mic, len);
139 : }
140 0 : if (len < 3 || !IS_HIGHBIT_SET(mic[1]) || !IS_HIGHBIT_SET(mic[2]))
141 : {
142 0 : if (noError)
143 0 : break;
144 0 : report_invalid_encoding(PG_MULE_INTERNAL,
145 : (const char *) mic, len);
146 : }
147 0 : mic++;
148 0 : *p++ = *mic++;
149 0 : *p++ = *mic++;
150 0 : len -= 3;
151 : }
152 : else
153 : { /* should be ASCII */
154 18 : if (c1 == 0)
155 : {
156 0 : if (noError)
157 0 : break;
158 0 : report_invalid_encoding(PG_MULE_INTERNAL,
159 : (const char *) mic, len);
160 : }
161 18 : *p++ = c1;
162 18 : mic++;
163 18 : len--;
164 : }
165 : }
166 6 : *p = '\0';
167 :
168 6 : return mic - start;
169 : }
|