/** *** Transcoding support and wrappers. *** *** See Copyright for the status of this software. *** *** Author: Patrick Monnerat <pm@datasphere.ch>, DATASPHERE S.A. **/ #define IN_LIBXML #include "libxml.h" #include <sys/types.h> #include <iconv.h> #include "libxml/xmlmemory.h" #include "libxml/dict.h" #include "transcode.h" /** *** Destroy a dictionary and mark as destroyed. **/ void xmlZapDict(xmlDictPtr * dict) { if (dict && *dict) { xmlDictFree(*dict); *dict = (xmlDictPtr) NULL; } } /** *** Support for inline conversion from/to UTF-8. *** This is targetted to function parameter encoding conversion. *** Method is: *** - Convert string from/to UTF-8. *** - Keep it in a dictionary. *** - Free original string if a release procedure is provided. *** Can also be called without dictionary to convert a string from/to UTF-8 *** into xmlMalloc'ed dynamic storage. **/ const char * xmlTranscodeResult(const xmlChar * s, const char * encoding, xmlDictPtr * dict, void (*freeproc)(const void *)) { size_t l; iconv_t cd; char * srcp; char * dstp; size_t srcc; size_t dstc; char * ts; const char * ret; int err; static const int nullstring[] = { 0 }; /* Convert from UTF-8. */ if (!s) return (const char *) NULL; ret = (const char *) NULL; ts = (char *) NULL; err = 0; l = xmlStrlen(s); if (!l && dict) ret = (const char *) nullstring; else { if (dict && !*dict) err = !(*dict = xmlDictCreate()); if (!err) err = !(ts = xmlMalloc(4 * l + 4)); dstp = ts; dstc = 4 * l; if (!err && l) { if (!encoding) encoding = "ibm-0"; /* Job's encoding. */ cd = iconv_open(encoding, "UTF-8"); if (cd == (iconv_t) -1) err = 1; else { srcp = (char *) s; srcc = l; srcc = iconv(cd, &srcp, &srcc, &dstp, &dstc); iconv_close(cd); err = srcc == (size_t) -1; } } if (!err) { dstp[0] = dstp[1] = dstp[2] = dstp[3] = '\0'; if (!dict) { if (dstc) ts = xmlRealloc(ts, (dstp - ts) + 4); ret = (const char *) ts; ts = (char *) NULL; } else ret = (char *) xmlDictLookup(*dict, (xmlChar *) ts, dstp - ts + 1); } } if (ts) xmlFree(ts); if (freeproc) (*freeproc)(s); return ret; } /** *** Support for inline conversion to UTF-8. *** Method is: *** - Convert string to UTF-8. *** - Keep it in a dictionary. *** Can also be called without dictionary to convert a string to UTF-8 into *** xmlMalloc'ed dynamic storage. **/ static const xmlChar * inTranscode(const char * s, size_t l, const char * encoding, xmlDictPtr * dict) { iconv_t cd; char * srcp; char * dstp; size_t srcc; size_t dstc; xmlChar * ts; const xmlChar * ret; static const xmlChar nullstring[] = { 0 }; if (!l && dict) return nullstring; if (dict && !*dict) if (!(*dict = xmlDictCreate())) return (const xmlChar *) NULL; ts = (xmlChar *) xmlMalloc(6 * l + 1); if (!ts) return (const xmlChar *) NULL; dstp = (char *) ts; dstc = 6 * l; if (l) { if (!encoding) encoding = "ibm-0"; /* Use job's encoding. */ cd = iconv_open("UTF-8", encoding); if (cd == (iconv_t) -1) { xmlFree((char *) ts); return (const xmlChar *) NULL; } srcp = (char *) s; srcc = l; srcc = iconv(cd, &srcp, &srcc, &dstp, &dstc); iconv_close(cd); if (srcc == (size_t) -1) { xmlFree((char *) ts); return (const xmlChar *) NULL; } } *dstp = '\0'; if (!dict) { if (dstc) ts = xmlRealloc(ts, (dstp - ts) + 1); return ts; } ret = xmlDictLookup(*dict, ts, dstp - ts + 1); xmlFree((char *) ts); return ret; } /** *** Input 8-bit character string parameter. **/ const xmlChar * xmlTranscodeString(const char * s, const char * encoding, xmlDictPtr * dict) { if (!s) return (const xmlChar *) NULL; return inTranscode(s, xmlStrlen(s), encoding, dict); } /** *** Input 16-bit character string parameter. **/ const xmlChar * xmlTranscodeWString(const char * s, const char * encoding, xmlDictPtr * dict) { size_t i; if (!s) return (const xmlChar *) NULL; for (i = 0; s[i] && s[i + 1]; i += 2) ; return inTranscode(s, i, encoding, dict); } /** *** Input 32-bit character string parameter. **/ const xmlChar * xmlTranscodeHString(const char * s, const char * encoding, xmlDictPtr * dict) { size_t i; if (!s) return (const xmlChar *) NULL; for (i = 0; s[i] && s[i + 1] && s[i + 2] && s[i + 3]; i += 4) ; return inTranscode(s, i, encoding, dict); } /** *** vasprintf() implementation with result transcoding. **/ const char * xmlVasprintf(xmlDictPtr * dict, const char * encoding, const xmlChar * fmt, va_list args) { char * s = NULL; vasprintf(&s, fmt, args); return xmlTranscodeResult((const xmlChar *) s, encoding, dict, free); }