diff options
Diffstat (limited to 'libxml2/os400/iconv/iconv.c')
-rw-r--r-- | libxml2/os400/iconv/iconv.c | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/libxml2/os400/iconv/iconv.c b/libxml2/os400/iconv/iconv.c new file mode 100644 index 0000000..c85c268 --- /dev/null +++ b/libxml2/os400/iconv/iconv.c @@ -0,0 +1,154 @@ +/** +*** iconv_open(), iconv(), iconv_close() wrappers for the OS/400. +*** +*** See Copyright for the status of this software. +*** +*** Author: Patrick Monnerat <pm@datasphere.ch>, DATASPHERE S.A. +**/ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +#include "/QIBM/include/iconv.h" /* Force system definition. */ + +#define USE_SYSTEM_ICONV +#include "iconv.h" /* Use local definitions. */ + + + +/** +*** Bring-in the name-->CCSID mapping DFA tables. +**/ + +#include "ianatables.c" + + + +static int +findEncoding(const unsigned char * * namep) + +{ + t_staterange curstate; + t_ccsid ccsid; + t_ccsid final; + t_transrange l; + t_transrange h; + const unsigned char * name; + + /** + *** Get the CCSID correspong to the name at *`namep'. + *** If success, update pointer at `namep' to 1st byte after matched + *** name and return the CCSID. + *** If failure, set errno and return -1. + **/ + + if (!namep || !(name = *namep)) { + errno = EINVAL; + return -1; + } + + curstate = 0; + final = 0; + + for (;;) { + if (curstate < sizeof final_array / sizeof final_array[0]) + if (final_array[curstate]) { + final = final_array[curstate]; + *namep = name; + } + + l = trans_array[curstate] - 1; + h = trans_array[curstate + 1]; + + do { + if (++l >= h) { + if (!final) { + errno = EINVAL; + return -1; + } + + return final - 1; + } + } while (label_array[l] != *name); + + curstate = goto_array[l]; + name++; + } + + /* NOTREACHED. */ +} + + +static void +makeos400codename(char * buf, unsigned int ccsid) + +{ + ccsid &= 0xFFFF; + memset(buf, 0, 32); + sprintf(buf, "IBMCCSID%05u0000000", ccsid); +} + + +Iconv_t +IconvOpen(const char * tocode, const char * fromcode) + +{ + int toccsid = findEncoding(&tocode); + int fromccsid = findEncoding(&fromcode); + char fromibmccsid[33]; + char toibmccsid[33]; + iconv_t * cd; + + if (toccsid < 0 || fromccsid < 0) + return (Iconv_t) -1; + + makeos400codename(fromibmccsid, fromccsid); + makeos400codename(toibmccsid, toccsid); + memset(toibmccsid + 13, 0, sizeof toibmccsid - 13); + + cd = (iconv_t *) malloc(sizeof *cd); + + if (!cd) + return (Iconv_t) -1; + + *cd = iconv_open(toibmccsid, fromibmccsid); + + if (cd->return_value) { + free((char *) cd); + return (Iconv_t) -1; + } + + return (Iconv_t) cd; +} + + +size_t +Iconv(Iconv_t cd, char * * inbuf, size_t * inbytesleft, + char * * outbuf, size_t * outbytesleft) + +{ + if (!cd || cd == (Iconv_t) -1) { + errno = EINVAL; + return (size_t) -1; + } + + return iconv(*(iconv_t *) cd, inbuf, inbytesleft, outbuf, outbytesleft); +} + + +int +IconvClose(Iconv_t cd) + +{ + if (!cd || cd == (Iconv_t) -1) { + errno = EINVAL; + return -1; + } + + if (iconv_close(*(iconv_t *) cd)) + return -1; + + free((char *) cd); + return 0; +} |