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