blob: bae61872122edea94317b9b34be484db9add03e5 [file] [log] [blame]
Patrick Monnerat5621c812014-03-04 17:09:26 +01001/**
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
23void
24xmlZapDict(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
45const char *
46xmlTranscodeResult(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
135static const xmlChar *
136inTranscode(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
204const xmlChar *
205xmlTranscodeString(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
219const xmlChar *
220xmlTranscodeWString(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
239const xmlChar *
240xmlTranscodeHString(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
259const char *
260xmlVasprintf(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}