Tag
Hash :
17951ea2
Author :
Date :
2014-03-04T16:42:19
OS400: iconv functions compatibility wrappers and table builder.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 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;
}