1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1997, by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <sys/types.h>
31
32 #include "tab_lookup.h" /* table lookup data types */
33
34 int bisearch(unsigned long val, _icv_state *st, int n);
35
36 /*
37 * Actual conversion; called from iconv().
38 * Peforms conversion as per the parameters specified in
39 * structure st.
40 */
41 size_t
_icv_iconv_lu(_icv_state * st,unsigned char ** ibuf,size_t * inbytesleft,unsigned char ** obuf,size_t * outbytesleft)42 _icv_iconv_lu(_icv_state *st, unsigned char **ibuf, size_t *inbytesleft,
43 unsigned char **obuf, size_t *outbytesleft)
44 {
45 int idx, data_size;
46 unsigned long search_val = 0, match_val;
47 unsigned char **inbuf, **outbuf;
48
49 inbuf = (unsigned char **)ibuf;
50 outbuf = (unsigned char **)obuf;
51
52 if (st == NULL) {
53 errno = EBADF;
54 return ((size_t)-1);
55 }
56
57 if (inbuf == NULL || *inbuf == NULL) { /* Reset request */
58
59 return 0;
60 }
61
62 errno = 0;
63
64
65 while (*inbytesleft > 0 && *outbytesleft > 0) {
66 fprintf(stderr, "INBL: %d , OUBL: %d \n",
67 *inbytesleft, *outbytesleft);
68 search_val = 0;
69
70 /*
71 * form a search member
72 * lookup character by character
73 */
74
75 if ( st->left_to_right ) {
76 /*
77 * create search val from the left code
78 */
79
80 data_size = st->left_code_size;
81 while ( data_size > 0 ) {
82 search_val = ( search_val << 8 ) | ( **inbuf );
83 data_size--;
84 (*inbuf)++;
85 (*inbytesleft)--;
86 }
87
88 idx = bisearch(search_val, st, st->table_size);
89 #ifdef TEST
90 fprintf(stderr, "Match idx: %d \n", idx);
91 #endif
92
93 if ( idx >= 0 ) {
94 /*
95 * create matched code from the right column
96 */
97 match_val = st->table[idx].right_code;
98
99 } else {
100 match_val = NON_ID_CHAR;
101
102 }
103
104 /*
105 * Check sufficient space in the outbuf
106 */
107 if ( *outbytesleft >= st->right_code_size ) {
108
109 data_size = st->right_code_size;
110 while ( data_size > 0 ) {
111 *(*outbuf + data_size-- - 1 ) =
112 (unsigned char) (match_val & 0xff);
113 #ifdef TEST
114 fprintf(stderr, "outbyte: %x \n",
115 (unsigned char) (match_val & 0xff));
116 #endif
117 match_val >>= 8;
118 }
119 (*outbuf) += st->right_code_size;
120 (*outbytesleft) -= st->right_code_size;
121
122 } else {
123 /* no space for outbytes */
124 errno = E2BIG;
125 return ((size_t)-1);
126 }
127 } else {
128 /* search from right to left */
129 /*
130 * create search val from the left code
131 */
132
133 data_size = st->right_code_size;
134 while ( data_size > 0 ) {
135 search_val = ( search_val << 8 ) | ( **inbuf );
136 data_size--;
137 (*inbuf)++;
138 (*inbytesleft)--;
139 }
140
141 idx = bisearch(search_val, st, st->table_size);
142
143 #ifdef TEST
144 fprintf(stderr, "Match idx: %d \n", idx);
145 #endif
146
147 if ( idx >= 0 ) {
148 /*
149 * create matched code from the right column
150 */
151 match_val = st->table[idx].left_code;
152
153 } else {
154 match_val = UCS2_NON_ID_CHAR;
155
156 }
157
158 /*
159 * Check sufficient space in the outbuf
160 */
161 if ( *outbytesleft >= st->left_code_size ) {
162
163 data_size = st->left_code_size;
164 while ( data_size > 0 ) {
165 *(*outbuf + data_size-- - 1 ) =
166 (unsigned char) (match_val & 0xff);
167 #ifdef TEST
168 fprintf(stderr, "outbyte: %x \n",
169 (unsigned char) (match_val & 0xff));
170 #endif
171 match_val >>= 8;
172 }
173 (*outbuf) += st->left_code_size;
174 (*outbytesleft) -= st->left_code_size;
175
176 } else {
177 /* no space for outbytes */
178 errno = E2BIG;
179 return ((size_t)-1);
180 }
181
182 }
183 #ifdef TEST
184 fprintf(stderr, "Search: %x match: %x \n", search_val, match_val);
185 #endif
186
187 }/* (*inbytesleft) && (*outbytesleft) */
188
189 if ( *inbytesleft && (!(*outbytesleft)) ) {
190 errno = E2BIG;
191 return ((size_t)-1);
192 }
193
194 return (*inbytesleft);
195 }
196
197
198 /*
199 * Performs the binary search in the lookup table of structure
200 * st. Memebers (left_to_right, right_to_left) control
201 * the lookup direction.
202 */
bisearch(unsigned long val,_icv_state * st,int n)203 int bisearch(unsigned long val, _icv_state *st, int n)
204 {
205 int low, high, mid;
206
207 #ifdef TEST
208 fprintf(stderr, "Search: %x limit: %d \n", val, n);
209 #endif
210
211 low = 0;
212 high = n - 1;
213 while ( low <= high ) {
214 mid = (low + high) / 2;
215 if ( st->left_to_right ) {
216 if ( val < st->table[mid].left_code )
217 high = mid - 1;
218 else if ( val > st->table[mid].left_code )
219 low = mid + 1;
220 else /* found match */
221 return mid;
222 } else {
223 if ( val < st->table[mid].right_code )
224 high = mid - 1;
225 else if ( val > st->table[mid].right_code )
226 low = mid + 1;
227 else /* found match */
228 return mid;
229 }
230
231 }
232
233 return (-1);
234 }
235