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