diff options
-rw-r--r-- | os400/transcode.c | 268 | ||||
-rw-r--r-- | os400/transcode.h | 43 |
2 files changed, 311 insertions, 0 deletions
diff --git a/os400/transcode.c b/os400/transcode.c new file mode 100644 index 00000000..bae61872 --- /dev/null +++ b/os400/transcode.c @@ -0,0 +1,268 @@ +/** +*** 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); +} diff --git a/os400/transcode.h b/os400/transcode.h new file mode 100644 index 00000000..6ca5773b --- /dev/null +++ b/os400/transcode.h @@ -0,0 +1,43 @@ +/** +*** Transcoding support declarations. +*** +*** See Copyright for the status of this software. +*** +*** Author: Patrick Monnerat <pm@datasphere.ch>, DATASPHERE S.A. +**/ + +#ifndef _TRANSCODE_H_ +#define _TRANSCODE_H_ + +#include <stdarg.h> +#include <libxml/dict.h> + + +XMLPUBFUN void xmlZapDict(xmlDictPtr * dict); +XMLPUBFUN const char * xmlTranscodeResult(const xmlChar * s, + const char * encoding, xmlDictPtr * dict, + void (*freeproc)(const void *)); +XMLPUBFUN const xmlChar * xmlTranscodeString(const char * s, + const char * encoding, xmlDictPtr * dict); +XMLPUBFUN const xmlChar * xmlTranscodeWString(const char * s, + const char * encoding, xmlDictPtr * dict); +XMLPUBFUN const xmlChar * xmlTranscodeHString(const char * s, + const char * encoding, xmlDictPtr * dict); + +#ifndef XML_NO_SHORT_NAMES +/** +*** Since the above functions are generally called "inline" (i.e.: several +*** times nested in a single expression), define shorthand names +*** to minimize calling statement length. +**/ + +#define xmlTR xmlTranscodeResult +#define xmlTS xmlTranscodeString +#define xmlTW xmlTranscodeWString +#define xmlTH xmlTranscodeHstring +#endif + +XMLPUBFUN const char * xmlVasprintf(xmlDictPtr * dict, const char * encoding, + const xmlChar * fmt, va_list args); + +#endif |