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 * Copyright (c) 1994 by Sun Microsystems, Inc. 23 */ 24 25 26 #include <stdlib.h> 27 #include <errno.h> 28 #include "ktable.h" 29 #include "utf_johap.h" 30 31 32 /**** _ I C V _ O P E N ****/ 33 34 void* _icv_open() 35 { 36 _conv_desc* cd = (_conv_desc*)malloc(sizeof(_conv_desc)); 37 38 if (cd == (_conv_desc*)NULL) 39 { 40 errno = ENOMEM; 41 return((void*)-1); 42 } 43 44 RESET_CONV_DESC(); 45 46 return((void*)cd); 47 } /* end of int _icv_open(). */ 48 49 50 /**** _ I C V _ C L O S E ****/ 51 52 void _icv_close(_conv_desc* cd) 53 { 54 if (!cd) 55 errno = EBADF; 56 else 57 free((void*)cd); 58 } /* end of void _icv_close(_conv_desc*). */ 59 60 61 /**** _ I C V _ I C O N V ****/ 62 63 size_t _icv_iconv(_conv_desc* cd, char** inbuf, size_t* inbufleft, 64 char** outbuf, size_t* outbufleft) 65 { 66 size_t ret_val = 0; 67 unsigned char* ib; 68 unsigned char* ob; 69 unsigned char* ibtail; 70 unsigned char* obtail; 71 72 if (!cd) 73 { 74 errno = EBADF; 75 return((size_t)-1); 76 } 77 78 if (!inbuf || !(*inbuf)) 79 { 80 RESET_CONV_DESC(); 81 return((size_t)0); 82 } 83 84 ib = (unsigned char*)*inbuf; 85 ob = (unsigned char*)*outbuf; 86 ibtail = ib + *inbufleft; 87 obtail = ob + *outbufleft; 88 89 while (ib < ibtail) 90 { 91 if (!(*ib & 0x80)) /* 7 bits */ 92 { 93 PROCESS_PRIOR_CVC(); 94 95 if (ob >= obtail) 96 { 97 errno = E2BIG; 98 ret_val = (size_t)-1; 99 break; 100 } 101 *ob++ = *ib++; 102 } 103 else if ((*ib & 0xF0) == 0xE0) /* 16 bits */ 104 { 105 unsigned long utf; 106 107 if ((ibtail - ib) < 3) 108 { 109 errno = EINVAL; 110 ret_val = (size_t)-1; 111 break; 112 } 113 114 utf = ((unsigned long)(*ib) << 16) | 115 ((unsigned long)(*(ib + 1)) << 8) | 116 (unsigned long)(*(ib + 2)); 117 if (utf == 0xE1859F || 118 (utf >= 0xE18480 && utf <= 0xE18492)) /* Ci */ 119 { 120 PROCESS_PRIOR_CVC(); 121 122 cd->ci = (utf == 0xE1859F) ? CVC_FILL 123 : utf - 0xE18480; 124 cd->prev_state = CI; 125 } 126 else if (utf == 0xE185A0 || 127 (utf >= 0xE185A1 && utf <= 0xE185B5)) /* V */ 128 { 129 if (cd->prev_state != E && cd->prev_state != CI) 130 PROCESS_PRIOR_CVC(); 131 132 cd->v = (utf == 0xE185A0) ? CVC_FILL 133 : utf - 0xE185A1; 134 cd->prev_state = V; 135 } 136 else if ((utf >= 0xE186A8 && utf <= 0xE186BF) || 137 (utf >= 0xE18780 && utf <= 0xE18782)) /* Cf */ 138 { 139 if (cd->prev_state != E && cd->prev_state != V) 140 PROCESS_PRIOR_CVC(); 141 142 cd->cf = utf - ((utf >= 0xE18780) ? 0xE18766 143 : 0xE186A6); 144 cd->prev_state = CF; 145 146 PROCESS_PRIOR_CVC(); 147 } 148 else 149 { 150 PROCESS_PRIOR_CVC(); 151 152 /* Let's assume the code is non-identical. */ 153 if ((obtail - ob) < 2) 154 { 155 errno = E2BIG; 156 ret_val = (size_t)-1; 157 break; 158 } 159 *ob++ = NON_IDENTICAL; 160 *ob++ = NON_IDENTICAL; 161 ret_val += 2; 162 } 163 ib += 3; 164 } 165 else /* 11, 21, 26 & 31 bits codes won't be able to convert. */ 166 { 167 short int offset; 168 169 PROCESS_PRIOR_CVC(); 170 171 if ((*ib & 0xE0) == 0xC0) /* 11 */ 172 offset = 2; 173 else if ((*ib & 0xF0) == 0xE0) /* 16 */ 174 offset = 3; 175 else if ((*ib & 0xF8) == 0xF0) /* 21 */ 176 offset = 4; 177 else if ((*ib & 0xFC) == 0xF8) /* 26 */ 178 offset = 5; 179 else if ((*ib & 0xFE) == 0xFC) /* 31 */ 180 offset = 6; 181 else /* Illegal sequence. */ 182 offset = 1; 183 184 if ((ibtail - ib) < offset) 185 { 186 errno = EINVAL; 187 ret_val = (size_t)-1; 188 break; 189 } 190 ib += offset; 191 192 /* Let's assume the code is non-identical. */ 193 offset = (offset > 2) ? 2 : 1; 194 if ((obtail - ob) < offset) 195 { 196 errno = E2BIG; 197 ret_val = (size_t)-1; 198 break; 199 } 200 *ob++ = NON_IDENTICAL; 201 if (offset > 1) 202 *ob++ = NON_IDENTICAL; 203 ret_val += offset; 204 } 205 } 206 207 *inbuf = (char*)ib; 208 *inbufleft = ibtail - ib; 209 *outbuf = (char*)ob; 210 *outbufleft = obtail - ob; 211 212 return(ret_val); 213 } /* end of size_t _icv_iconv(_conv_desc*, char**, size_t*, char**, size_t*).*/ 214