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