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 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} 269