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