/ libxml2 / os400 / transcode.c
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  }