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