Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * EUC_CN and MULE_INTERNAL
4 : *
5 : * Portions Copyright (c) 1996-2017, 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 4 : 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 : * ) returns VOID;
31 : * ----------
32 : */
33 :
34 : static void euc_cn2mic(const unsigned char *euc, unsigned char *p, int len);
35 : static void mic2euc_cn(const unsigned char *mic, unsigned char *p, int len);
36 :
37 : Datum
38 4 : euc_cn_to_mic(PG_FUNCTION_ARGS)
39 : {
40 4 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
41 4 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
42 4 : int len = PG_GETARG_INT32(4);
43 :
44 4 : CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_CN, PG_MULE_INTERNAL);
45 :
46 4 : euc_cn2mic(src, dest, len);
47 :
48 4 : PG_RETURN_VOID();
49 : }
50 :
51 : Datum
52 4 : mic_to_euc_cn(PG_FUNCTION_ARGS)
53 : {
54 4 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
55 4 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
56 4 : int len = PG_GETARG_INT32(4);
57 :
58 4 : CHECK_ENCODING_CONVERSION_ARGS(PG_MULE_INTERNAL, PG_EUC_CN);
59 :
60 4 : mic2euc_cn(src, dest, len);
61 :
62 4 : PG_RETURN_VOID();
63 : }
64 :
65 : /*
66 : * EUC_CN ---> MIC
67 : */
68 : static void
69 4 : euc_cn2mic(const unsigned char *euc, unsigned char *p, int len)
70 : {
71 : int c1;
72 :
73 14 : while (len > 0)
74 : {
75 6 : c1 = *euc;
76 6 : if (IS_HIGHBIT_SET(c1))
77 : {
78 0 : if (len < 2 || !IS_HIGHBIT_SET(euc[1]))
79 0 : report_invalid_encoding(PG_EUC_CN, (const char *) euc, len);
80 0 : *p++ = LC_GB2312_80;
81 0 : *p++ = c1;
82 0 : *p++ = euc[1];
83 0 : euc += 2;
84 0 : len -= 2;
85 : }
86 : else
87 : { /* should be ASCII */
88 6 : if (c1 == 0)
89 0 : report_invalid_encoding(PG_EUC_CN, (const char *) euc, len);
90 6 : *p++ = c1;
91 6 : euc++;
92 6 : len--;
93 : }
94 : }
95 4 : *p = '\0';
96 4 : }
97 :
98 : /*
99 : * MIC ---> EUC_CN
100 : */
101 : static void
102 4 : mic2euc_cn(const unsigned char *mic, unsigned char *p, int len)
103 : {
104 : int c1;
105 :
106 14 : while (len > 0)
107 : {
108 6 : c1 = *mic;
109 6 : if (IS_HIGHBIT_SET(c1))
110 : {
111 0 : if (c1 != LC_GB2312_80)
112 0 : report_untranslatable_char(PG_MULE_INTERNAL, PG_EUC_CN,
113 : (const char *) mic, len);
114 0 : if (len < 3 || !IS_HIGHBIT_SET(mic[1]) || !IS_HIGHBIT_SET(mic[2]))
115 0 : report_invalid_encoding(PG_MULE_INTERNAL,
116 : (const char *) mic, len);
117 0 : mic++;
118 0 : *p++ = *mic++;
119 0 : *p++ = *mic++;
120 0 : len -= 3;
121 : }
122 : else
123 : { /* should be ASCII */
124 6 : if (c1 == 0)
125 0 : report_invalid_encoding(PG_MULE_INTERNAL,
126 : (const char *) mic, len);
127 6 : *p++ = c1;
128 6 : mic++;
129 6 : len--;
130 : }
131 : }
132 4 : *p = '\0';
133 4 : }
|