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 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 */ 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