summaryrefslogtreecommitdiffstats
path: root/libxml2/os400/iconv/iconv.c
diff options
context:
space:
mode:
Diffstat (limited to 'libxml2/os400/iconv/iconv.c')
-rw-r--r--libxml2/os400/iconv/iconv.c154
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;
+}