xref: /aosp_15_r20/external/libxml2/os400/transcode.c (revision 7c5688314b92172186c154356a6374bf7684c3ca)
1*7c568831SAndroid Build Coastguard Worker /**
2*7c568831SAndroid Build Coastguard Worker ***     Transcoding support and wrappers.
3*7c568831SAndroid Build Coastguard Worker ***
4*7c568831SAndroid Build Coastguard Worker ***     See Copyright for the status of this software.
5*7c568831SAndroid Build Coastguard Worker ***
6*7c568831SAndroid Build Coastguard Worker ***     Author: Patrick Monnerat <[email protected]>, DATASPHERE S.A.
7*7c568831SAndroid Build Coastguard Worker **/
8*7c568831SAndroid Build Coastguard Worker 
9*7c568831SAndroid Build Coastguard Worker #define IN_LIBXML
10*7c568831SAndroid Build Coastguard Worker #include "libxml.h"
11*7c568831SAndroid Build Coastguard Worker 
12*7c568831SAndroid Build Coastguard Worker #include <sys/types.h>
13*7c568831SAndroid Build Coastguard Worker #include <iconv.h>
14*7c568831SAndroid Build Coastguard Worker #include "libxml/xmlmemory.h"
15*7c568831SAndroid Build Coastguard Worker #include "libxml/dict.h"
16*7c568831SAndroid Build Coastguard Worker #include "transcode.h"
17*7c568831SAndroid Build Coastguard Worker 
18*7c568831SAndroid Build Coastguard Worker 
19*7c568831SAndroid Build Coastguard Worker /**
20*7c568831SAndroid Build Coastguard Worker ***     Destroy a dictionary and mark as destroyed.
21*7c568831SAndroid Build Coastguard Worker **/
22*7c568831SAndroid Build Coastguard Worker 
23*7c568831SAndroid Build Coastguard Worker void
xmlZapDict(xmlDictPtr * dict)24*7c568831SAndroid Build Coastguard Worker xmlZapDict(xmlDictPtr * dict)
25*7c568831SAndroid Build Coastguard Worker 
26*7c568831SAndroid Build Coastguard Worker {
27*7c568831SAndroid Build Coastguard Worker         if (dict && *dict) {
28*7c568831SAndroid Build Coastguard Worker                 xmlDictFree(*dict);
29*7c568831SAndroid Build Coastguard Worker                 *dict = (xmlDictPtr) NULL;
30*7c568831SAndroid Build Coastguard Worker                 }
31*7c568831SAndroid Build Coastguard Worker }
32*7c568831SAndroid Build Coastguard Worker 
33*7c568831SAndroid Build Coastguard Worker 
34*7c568831SAndroid Build Coastguard Worker /**
35*7c568831SAndroid Build Coastguard Worker ***     Support for inline conversion from/to UTF-8.
36*7c568831SAndroid Build Coastguard Worker ***     This is targeted to function parameter encoding conversion.
37*7c568831SAndroid Build Coastguard Worker ***     Method is:
38*7c568831SAndroid Build Coastguard Worker ***     -       Convert string from/to UTF-8.
39*7c568831SAndroid Build Coastguard Worker ***     -       Keep it in a dictionary.
40*7c568831SAndroid Build Coastguard Worker ***     -       Free original string if a release procedure is provided.
41*7c568831SAndroid Build Coastguard Worker ***     Can also be called without dictionary to convert a string from/to UTF-8
42*7c568831SAndroid Build Coastguard Worker ***             into xmlMalloc'ed dynamic storage.
43*7c568831SAndroid Build Coastguard Worker **/
44*7c568831SAndroid Build Coastguard Worker 
45*7c568831SAndroid Build Coastguard Worker const char *
xmlTranscodeResult(const xmlChar * s,const char * encoding,xmlDictPtr * dict,void (* freeproc)(const void *))46*7c568831SAndroid Build Coastguard Worker xmlTranscodeResult(const xmlChar * s, const char * encoding,
47*7c568831SAndroid Build Coastguard Worker                         xmlDictPtr * dict, void (*freeproc)(const void *))
48*7c568831SAndroid Build Coastguard Worker 
49*7c568831SAndroid Build Coastguard Worker {
50*7c568831SAndroid Build Coastguard Worker         size_t l;
51*7c568831SAndroid Build Coastguard Worker         iconv_t cd;
52*7c568831SAndroid Build Coastguard Worker         char * srcp;
53*7c568831SAndroid Build Coastguard Worker         char * dstp;
54*7c568831SAndroid Build Coastguard Worker         size_t srcc;
55*7c568831SAndroid Build Coastguard Worker         size_t dstc;
56*7c568831SAndroid Build Coastguard Worker         char * ts;
57*7c568831SAndroid Build Coastguard Worker         const char * ret;
58*7c568831SAndroid Build Coastguard Worker         int err;
59*7c568831SAndroid Build Coastguard Worker         static const int nullstring[] = { 0 };
60*7c568831SAndroid Build Coastguard Worker 
61*7c568831SAndroid Build Coastguard Worker         /* Convert from UTF-8. */
62*7c568831SAndroid Build Coastguard Worker 
63*7c568831SAndroid Build Coastguard Worker         if (!s)
64*7c568831SAndroid Build Coastguard Worker                 return (const char *) NULL;
65*7c568831SAndroid Build Coastguard Worker 
66*7c568831SAndroid Build Coastguard Worker         ret = (const char *) NULL;
67*7c568831SAndroid Build Coastguard Worker         ts = (char *) NULL;
68*7c568831SAndroid Build Coastguard Worker         err = 0;
69*7c568831SAndroid Build Coastguard Worker         l = xmlStrlen(s);
70*7c568831SAndroid Build Coastguard Worker 
71*7c568831SAndroid Build Coastguard Worker         if (!l && dict)
72*7c568831SAndroid Build Coastguard Worker                 ret = (const char *) nullstring;
73*7c568831SAndroid Build Coastguard Worker         else {
74*7c568831SAndroid Build Coastguard Worker                 if (dict && !*dict)
75*7c568831SAndroid Build Coastguard Worker                         err = !(*dict = xmlDictCreate());
76*7c568831SAndroid Build Coastguard Worker 
77*7c568831SAndroid Build Coastguard Worker                 if (!err)
78*7c568831SAndroid Build Coastguard Worker                         err = !(ts = xmlMalloc(4 * l + 4));
79*7c568831SAndroid Build Coastguard Worker 
80*7c568831SAndroid Build Coastguard Worker                 dstp = ts;
81*7c568831SAndroid Build Coastguard Worker                 dstc = 4 * l;
82*7c568831SAndroid Build Coastguard Worker 
83*7c568831SAndroid Build Coastguard Worker                 if (!err && l) {
84*7c568831SAndroid Build Coastguard Worker                         if (!encoding)
85*7c568831SAndroid Build Coastguard Worker                                 encoding = "ibm-0";     /* Job's encoding. */
86*7c568831SAndroid Build Coastguard Worker 
87*7c568831SAndroid Build Coastguard Worker                         cd = iconv_open(encoding, "UTF-8");
88*7c568831SAndroid Build Coastguard Worker 
89*7c568831SAndroid Build Coastguard Worker                         if (cd == (iconv_t) -1)
90*7c568831SAndroid Build Coastguard Worker                                 err = 1;
91*7c568831SAndroid Build Coastguard Worker                         else {
92*7c568831SAndroid Build Coastguard Worker                                 srcp = (char *) s;
93*7c568831SAndroid Build Coastguard Worker                                 srcc = l;
94*7c568831SAndroid Build Coastguard Worker                                 srcc = iconv(cd, &srcp, &srcc, &dstp, &dstc);
95*7c568831SAndroid Build Coastguard Worker                                 iconv_close(cd);
96*7c568831SAndroid Build Coastguard Worker                                 err = srcc == (size_t) -1;
97*7c568831SAndroid Build Coastguard Worker                                 }
98*7c568831SAndroid Build Coastguard Worker                         }
99*7c568831SAndroid Build Coastguard Worker 
100*7c568831SAndroid Build Coastguard Worker                 if (!err) {
101*7c568831SAndroid Build Coastguard Worker                         dstp[0] = dstp[1] = dstp[2] = dstp[3] = '\0';
102*7c568831SAndroid Build Coastguard Worker 
103*7c568831SAndroid Build Coastguard Worker                         if (!dict) {
104*7c568831SAndroid Build Coastguard Worker                                 if (dstc)
105*7c568831SAndroid Build Coastguard Worker                                         ts = xmlRealloc(ts, (dstp - ts) + 4);
106*7c568831SAndroid Build Coastguard Worker 
107*7c568831SAndroid Build Coastguard Worker                                 ret = (const char *) ts;
108*7c568831SAndroid Build Coastguard Worker                                 ts = (char *) NULL;
109*7c568831SAndroid Build Coastguard Worker                                 }
110*7c568831SAndroid Build Coastguard Worker                         else
111*7c568831SAndroid Build Coastguard Worker                                 ret = (char *) xmlDictLookup(*dict,
112*7c568831SAndroid Build Coastguard Worker                                     (xmlChar *) ts, dstp - ts + 1);
113*7c568831SAndroid Build Coastguard Worker                         }
114*7c568831SAndroid Build Coastguard Worker                 }
115*7c568831SAndroid Build Coastguard Worker 
116*7c568831SAndroid Build Coastguard Worker         if (ts)
117*7c568831SAndroid Build Coastguard Worker                 xmlFree(ts);
118*7c568831SAndroid Build Coastguard Worker 
119*7c568831SAndroid Build Coastguard Worker         if (freeproc)
120*7c568831SAndroid Build Coastguard Worker                 (*freeproc)(s);
121*7c568831SAndroid Build Coastguard Worker 
122*7c568831SAndroid Build Coastguard Worker         return ret;
123*7c568831SAndroid Build Coastguard Worker }
124*7c568831SAndroid Build Coastguard Worker 
125*7c568831SAndroid Build Coastguard Worker 
126*7c568831SAndroid Build Coastguard Worker /**
127*7c568831SAndroid Build Coastguard Worker ***     Support for inline conversion to UTF-8.
128*7c568831SAndroid Build Coastguard Worker ***     Method is:
129*7c568831SAndroid Build Coastguard Worker ***     -       Convert string to UTF-8.
130*7c568831SAndroid Build Coastguard Worker ***     -       Keep it in a dictionary.
131*7c568831SAndroid Build Coastguard Worker ***     Can also be called without dictionary to convert a string to UTF-8 into
132*7c568831SAndroid Build Coastguard Worker ***             xmlMalloc'ed dynamic storage.
133*7c568831SAndroid Build Coastguard Worker **/
134*7c568831SAndroid Build Coastguard Worker 
135*7c568831SAndroid Build Coastguard Worker static const xmlChar *
inTranscode(const char * s,size_t l,const char * encoding,xmlDictPtr * dict)136*7c568831SAndroid Build Coastguard Worker inTranscode(const char * s, size_t l, const char * encoding, xmlDictPtr * dict)
137*7c568831SAndroid Build Coastguard Worker 
138*7c568831SAndroid Build Coastguard Worker {
139*7c568831SAndroid Build Coastguard Worker         iconv_t cd;
140*7c568831SAndroid Build Coastguard Worker         char * srcp;
141*7c568831SAndroid Build Coastguard Worker         char * dstp;
142*7c568831SAndroid Build Coastguard Worker         size_t srcc;
143*7c568831SAndroid Build Coastguard Worker         size_t dstc;
144*7c568831SAndroid Build Coastguard Worker         xmlChar * ts;
145*7c568831SAndroid Build Coastguard Worker         const xmlChar * ret;
146*7c568831SAndroid Build Coastguard Worker         static const xmlChar nullstring[] = { 0 };
147*7c568831SAndroid Build Coastguard Worker 
148*7c568831SAndroid Build Coastguard Worker         if (!l && dict)
149*7c568831SAndroid Build Coastguard Worker                 return nullstring;
150*7c568831SAndroid Build Coastguard Worker 
151*7c568831SAndroid Build Coastguard Worker         if (dict && !*dict)
152*7c568831SAndroid Build Coastguard Worker                 if (!(*dict = xmlDictCreate()))
153*7c568831SAndroid Build Coastguard Worker                         return (const xmlChar *) NULL;
154*7c568831SAndroid Build Coastguard Worker 
155*7c568831SAndroid Build Coastguard Worker         ts = (xmlChar *) xmlMalloc(6 * l + 1);
156*7c568831SAndroid Build Coastguard Worker 
157*7c568831SAndroid Build Coastguard Worker         if (!ts)
158*7c568831SAndroid Build Coastguard Worker                 return (const xmlChar *) NULL;
159*7c568831SAndroid Build Coastguard Worker 
160*7c568831SAndroid Build Coastguard Worker         dstp = (char *) ts;
161*7c568831SAndroid Build Coastguard Worker         dstc = 6 * l;
162*7c568831SAndroid Build Coastguard Worker 
163*7c568831SAndroid Build Coastguard Worker         if (l) {
164*7c568831SAndroid Build Coastguard Worker                 if (!encoding)
165*7c568831SAndroid Build Coastguard Worker                         encoding = "ibm-0";     /* Use job's encoding. */
166*7c568831SAndroid Build Coastguard Worker 
167*7c568831SAndroid Build Coastguard Worker                 cd = iconv_open("UTF-8", encoding);
168*7c568831SAndroid Build Coastguard Worker 
169*7c568831SAndroid Build Coastguard Worker                 if (cd == (iconv_t) -1) {
170*7c568831SAndroid Build Coastguard Worker                         xmlFree((char *) ts);
171*7c568831SAndroid Build Coastguard Worker                         return (const xmlChar *) NULL;
172*7c568831SAndroid Build Coastguard Worker                         }
173*7c568831SAndroid Build Coastguard Worker 
174*7c568831SAndroid Build Coastguard Worker                 srcp = (char *) s;
175*7c568831SAndroid Build Coastguard Worker                 srcc = l;
176*7c568831SAndroid Build Coastguard Worker                 srcc = iconv(cd, &srcp, &srcc, &dstp, &dstc);
177*7c568831SAndroid Build Coastguard Worker                 iconv_close(cd);
178*7c568831SAndroid Build Coastguard Worker 
179*7c568831SAndroid Build Coastguard Worker                 if (srcc == (size_t) -1) {
180*7c568831SAndroid Build Coastguard Worker                         xmlFree((char *) ts);
181*7c568831SAndroid Build Coastguard Worker                         return (const xmlChar *) NULL;
182*7c568831SAndroid Build Coastguard Worker                         }
183*7c568831SAndroid Build Coastguard Worker                 }
184*7c568831SAndroid Build Coastguard Worker 
185*7c568831SAndroid Build Coastguard Worker         *dstp = '\0';
186*7c568831SAndroid Build Coastguard Worker 
187*7c568831SAndroid Build Coastguard Worker         if (!dict) {
188*7c568831SAndroid Build Coastguard Worker                 if (dstc)
189*7c568831SAndroid Build Coastguard Worker                         ts = xmlRealloc(ts, (dstp - ts) + 1);
190*7c568831SAndroid Build Coastguard Worker 
191*7c568831SAndroid Build Coastguard Worker                 return ts;
192*7c568831SAndroid Build Coastguard Worker                 }
193*7c568831SAndroid Build Coastguard Worker 
194*7c568831SAndroid Build Coastguard Worker         ret = xmlDictLookup(*dict, ts, dstp - ts + 1);
195*7c568831SAndroid Build Coastguard Worker         xmlFree((char *) ts);
196*7c568831SAndroid Build Coastguard Worker         return ret;
197*7c568831SAndroid Build Coastguard Worker }
198*7c568831SAndroid Build Coastguard Worker 
199*7c568831SAndroid Build Coastguard Worker 
200*7c568831SAndroid Build Coastguard Worker /**
201*7c568831SAndroid Build Coastguard Worker ***     Input 8-bit character string parameter.
202*7c568831SAndroid Build Coastguard Worker **/
203*7c568831SAndroid Build Coastguard Worker 
204*7c568831SAndroid Build Coastguard Worker const xmlChar *
xmlTranscodeString(const char * s,const char * encoding,xmlDictPtr * dict)205*7c568831SAndroid Build Coastguard Worker xmlTranscodeString(const char * s, const char * encoding, xmlDictPtr * dict)
206*7c568831SAndroid Build Coastguard Worker 
207*7c568831SAndroid Build Coastguard Worker {
208*7c568831SAndroid Build Coastguard Worker         if (!s)
209*7c568831SAndroid Build Coastguard Worker                 return (const xmlChar *) NULL;
210*7c568831SAndroid Build Coastguard Worker 
211*7c568831SAndroid Build Coastguard Worker         return inTranscode(s, xmlStrlen(s), encoding, dict);
212*7c568831SAndroid Build Coastguard Worker }
213*7c568831SAndroid Build Coastguard Worker 
214*7c568831SAndroid Build Coastguard Worker 
215*7c568831SAndroid Build Coastguard Worker /**
216*7c568831SAndroid Build Coastguard Worker ***     Input 16-bit character string parameter.
217*7c568831SAndroid Build Coastguard Worker **/
218*7c568831SAndroid Build Coastguard Worker 
219*7c568831SAndroid Build Coastguard Worker const xmlChar *
xmlTranscodeWString(const char * s,const char * encoding,xmlDictPtr * dict)220*7c568831SAndroid Build Coastguard Worker xmlTranscodeWString(const char * s, const char * encoding, xmlDictPtr * dict)
221*7c568831SAndroid Build Coastguard Worker 
222*7c568831SAndroid Build Coastguard Worker {
223*7c568831SAndroid Build Coastguard Worker         size_t i;
224*7c568831SAndroid Build Coastguard Worker 
225*7c568831SAndroid Build Coastguard Worker         if (!s)
226*7c568831SAndroid Build Coastguard Worker                 return (const xmlChar *) NULL;
227*7c568831SAndroid Build Coastguard Worker 
228*7c568831SAndroid Build Coastguard Worker         for (i = 0; s[i] && s[i + 1]; i += 2)
229*7c568831SAndroid Build Coastguard Worker                 ;
230*7c568831SAndroid Build Coastguard Worker 
231*7c568831SAndroid Build Coastguard Worker         return inTranscode(s, i, encoding, dict);
232*7c568831SAndroid Build Coastguard Worker }
233*7c568831SAndroid Build Coastguard Worker 
234*7c568831SAndroid Build Coastguard Worker 
235*7c568831SAndroid Build Coastguard Worker /**
236*7c568831SAndroid Build Coastguard Worker ***     Input 32-bit character string parameter.
237*7c568831SAndroid Build Coastguard Worker **/
238*7c568831SAndroid Build Coastguard Worker 
239*7c568831SAndroid Build Coastguard Worker const xmlChar *
xmlTranscodeHString(const char * s,const char * encoding,xmlDictPtr * dict)240*7c568831SAndroid Build Coastguard Worker xmlTranscodeHString(const char * s, const char * encoding, xmlDictPtr * dict)
241*7c568831SAndroid Build Coastguard Worker 
242*7c568831SAndroid Build Coastguard Worker {
243*7c568831SAndroid Build Coastguard Worker         size_t i;
244*7c568831SAndroid Build Coastguard Worker 
245*7c568831SAndroid Build Coastguard Worker         if (!s)
246*7c568831SAndroid Build Coastguard Worker                 return (const xmlChar *) NULL;
247*7c568831SAndroid Build Coastguard Worker 
248*7c568831SAndroid Build Coastguard Worker         for (i = 0; s[i] && s[i + 1] && s[i + 2] && s[i + 3]; i += 4)
249*7c568831SAndroid Build Coastguard Worker                 ;
250*7c568831SAndroid Build Coastguard Worker 
251*7c568831SAndroid Build Coastguard Worker         return inTranscode(s, i, encoding, dict);
252*7c568831SAndroid Build Coastguard Worker }
253*7c568831SAndroid Build Coastguard Worker 
254*7c568831SAndroid Build Coastguard Worker 
255*7c568831SAndroid Build Coastguard Worker /**
256*7c568831SAndroid Build Coastguard Worker ***     vasprintf() implementation with result transcoding.
257*7c568831SAndroid Build Coastguard Worker **/
258*7c568831SAndroid Build Coastguard Worker 
259*7c568831SAndroid Build Coastguard Worker const char *
xmlVasprintf(xmlDictPtr * dict,const char * encoding,const xmlChar * fmt,va_list args)260*7c568831SAndroid Build Coastguard Worker xmlVasprintf(xmlDictPtr * dict, const char * encoding,
261*7c568831SAndroid Build Coastguard Worker                                         const xmlChar * fmt, va_list args)
262*7c568831SAndroid Build Coastguard Worker 
263*7c568831SAndroid Build Coastguard Worker {
264*7c568831SAndroid Build Coastguard Worker         char * s = NULL;
265*7c568831SAndroid Build Coastguard Worker 
266*7c568831SAndroid Build Coastguard Worker         vasprintf(&s, fmt, args);
267*7c568831SAndroid Build Coastguard Worker         return xmlTranscodeResult((const xmlChar *) s, encoding, dict, free);
268*7c568831SAndroid Build Coastguard Worker }
269