blob: c85c2689cf553f70f3c49cc655c9839aab90738b [file] [log] [blame]
Patrick Monnerat17951ea2014-03-04 16:42:19 +01001/**
2*** iconv_open(), iconv(), iconv_close() wrappers for the OS/400.
3***
4*** See Copyright for the status of this software.
5***
6*** Author: Patrick Monnerat <pm@datasphere.ch>, DATASPHERE S.A.
7**/
8
9#include <errno.h>
10#include <stdio.h>
11#include <stdlib.h>
12
13#include "/QIBM/include/iconv.h" /* Force system definition. */
14
15#define USE_SYSTEM_ICONV
16#include "iconv.h" /* Use local definitions. */
17
18
19
20/**
21*** Bring-in the name-->CCSID mapping DFA tables.
22**/
23
24#include "ianatables.c"
25
26
27
28static int
29findEncoding(const unsigned char * * namep)
30
31{
32 t_staterange curstate;
33 t_ccsid ccsid;
34 t_ccsid final;
35 t_transrange l;
36 t_transrange h;
37 const unsigned char * name;
38
39 /**
40 *** Get the CCSID correspong to the name at *`namep'.
41 *** If success, update pointer at `namep' to 1st byte after matched
42 *** name and return the CCSID.
43 *** If failure, set errno and return -1.
44 **/
45
46 if (!namep || !(name = *namep)) {
47 errno = EINVAL;
48 return -1;
49 }
50
51 curstate = 0;
52 final = 0;
53
54 for (;;) {
55 if (curstate < sizeof final_array / sizeof final_array[0])
56 if (final_array[curstate]) {
57 final = final_array[curstate];
58 *namep = name;
59 }
60
61 l = trans_array[curstate] - 1;
62 h = trans_array[curstate + 1];
63
64 do {
65 if (++l >= h) {
66 if (!final) {
67 errno = EINVAL;
68 return -1;
69 }
70
71 return final - 1;
72 }
73 } while (label_array[l] != *name);
74
75 curstate = goto_array[l];
76 name++;
77 }
78
79 /* NOTREACHED. */
80}
81
82
83static void
84makeos400codename(char * buf, unsigned int ccsid)
85
86{
87 ccsid &= 0xFFFF;
88 memset(buf, 0, 32);
89 sprintf(buf, "IBMCCSID%05u0000000", ccsid);
90}
91
92
93Iconv_t
94IconvOpen(const char * tocode, const char * fromcode)
95
96{
97 int toccsid = findEncoding(&tocode);
98 int fromccsid = findEncoding(&fromcode);
99 char fromibmccsid[33];
100 char toibmccsid[33];
101 iconv_t * cd;
102
103 if (toccsid < 0 || fromccsid < 0)
104 return (Iconv_t) -1;
105
106 makeos400codename(fromibmccsid, fromccsid);
107 makeos400codename(toibmccsid, toccsid);
108 memset(toibmccsid + 13, 0, sizeof toibmccsid - 13);
109
110 cd = (iconv_t *) malloc(sizeof *cd);
111
112 if (!cd)
113 return (Iconv_t) -1;
114
115 *cd = iconv_open(toibmccsid, fromibmccsid);
116
117 if (cd->return_value) {
118 free((char *) cd);
119 return (Iconv_t) -1;
120 }
121
122 return (Iconv_t) cd;
123}
124
125
126size_t
127Iconv(Iconv_t cd, char * * inbuf, size_t * inbytesleft,
128 char * * outbuf, size_t * outbytesleft)
129
130{
131 if (!cd || cd == (Iconv_t) -1) {
132 errno = EINVAL;
133 return (size_t) -1;
134 }
135
136 return iconv(*(iconv_t *) cd, inbuf, inbytesleft, outbuf, outbytesleft);
137}
138
139
140int
141IconvClose(Iconv_t cd)
142
143{
144 if (!cd || cd == (Iconv_t) -1) {
145 errno = EINVAL;
146 return -1;
147 }
148
149 if (iconv_close(*(iconv_t *) cd))
150 return -1;
151
152 free((char *) cd);
153 return 0;
154}