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