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