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) 1995 by Sun Microsystems, Inc. 23 * All Rights Reserved. 24 */ 25 26 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <ctype.h> 30 #include <string.h> 31 #include "kctype.h" 32 #include "kdefs.h" 33 #include <errno.h> 34 #include "ktable.h" 35 #include "hangulcode.h" 36 37 38 KCHAR c2p(); 39 40 struct _cv_state { 41 char **my_outbuf; 42 size_t *my_outbytesleft; 43 int invalid; 44 int flush_obuf; 45 char temp_obuf[5]; 46 int start_cnt; 47 int end_cnt; 48 char temp_ibuf[1]; 49 int ibuf_left; 50 }; 51 52 void AddChar (char Char, struct _cv_state* st); 53 54 KCHAR comptopack(KCHAR comp); 55 56 static unsigned short _wansung_to_johap(unsigned short code); 57 58 /**** _ I C V _ O P E N ****/ 59 60 void* _icv_open() 61 { 62 return((void*)MAGIC_NUMBER); 63 } /* end of int _icv_open(). */ 64 65 66 /**** _ I C V _ C L O S E ****/ 67 68 void _icv_close(int* cd) 69 { 70 if (!cd || cd != (int*)MAGIC_NUMBER) 71 errno = EBADF; 72 } /* end of void _icv_close(int*). */ 73 74 75 /**** _ I C V _ I C O N V ****/ 76 77 size_t _icv_iconv(int* cd, char** inbuf, size_t* inbufleft, 78 char** outbuf, size_t* outbufleft) 79 { 80 size_t ret_val = 0; 81 unsigned char* ib; 82 unsigned char* ob; 83 unsigned char* ibtail; 84 unsigned char* obtail; 85 86 if (!cd || cd != (int*)MAGIC_NUMBER) 87 { 88 errno = EBADF; 89 return((size_t)-1); 90 } 91 92 if (!inbuf || !(*inbuf)) 93 { 94 return((size_t)0); 95 } 96 97 ib = (unsigned char*)*inbuf; 98 ob = (unsigned char*)*outbuf; 99 ibtail = ib + *inbufleft; 100 obtail = ob + *outbufleft; 101 102 while (ib < ibtail) 103 { 104 if (!(*ib & 0x80)) /* 7 bits */ 105 { 106 if (ob >= obtail) 107 { 108 errno = E2BIG; 109 ret_val = (size_t)-1; 110 break; 111 } 112 *ob++ = *ib++; 113 } 114 else 115 { 116 unsigned short code; 117 118 if ((ibtail - ib) < 2) 119 { 120 errno = EINVAL; 121 ret_val = (size_t)-1; 122 break; 123 } 124 125 if ((obtail - ob) < 2) 126 { 127 errno = E2BIG; 128 ret_val = (size_t)-1; 129 break; 130 } 131 132 code = _wansung_to_johap((unsigned short)(*ib)<<8 | 133 (unsigned short)(*(ib + 1))); 134 if (code != FAILED && code != ILLEGAL_SEQ) 135 { 136 *ob++ = (unsigned char)(code >> 8); 137 *ob++ = (unsigned char)(code & 0xFF); 138 } 139 else 140 { 141 *ob++ = NON_IDENTICAL; 142 *ob++ = NON_IDENTICAL; 143 } 144 ib += 2; 145 } 146 } 147 148 *inbuf = (char*)ib; 149 *inbufleft = ibtail - ib; 150 *outbuf = (char*)ob; 151 *outbufleft = obtail - ob; 152 153 return(ret_val); 154 } /* end of size_t _icv_iconv(int*, char**, size_t*, char**, size_t*).*/ 155 156 157 /**** _ W A N S U N G _ T O _ J O H A P ****/ 158 159 static unsigned short _wansung_to_johap(unsigned short code) 160 { 161 register short h, i, l; 162 short ci, v, cf; 163 short disp; 164 long cfbit; 165 166 if ((unsigned short)(code & 0xFF) < 0xA1) 167 return(ILLEGAL_SEQ); 168 169 if (code >= 0xB0A1 && code <= 0xC8FE) /* Hangul */ 170 { 171 for (h = CI_CNT, l = 0; ; ) 172 { 173 ci = (l + h) / 2; 174 if (l >= h) 175 break; 176 if (code < cmp_srchtbl[ci][0]) 177 h = ci - 1; 178 else if (code < cmp_srchtbl[ci + 1][0]) 179 break; 180 else 181 l = ci + 1; 182 } 183 184 for (v = 1; ; ) 185 { 186 if (code < cmp_srchtbl[ci][v]) 187 { 188 while (!cmp_srchtbl[ci][--v]) 189 ; 190 break; 191 } 192 else if (v == V_CNT) 193 break; 194 v++; 195 } 196 197 disp = code - cmp_srchtbl[ci][v]; 198 if (((short)(cmp_srchtbl[ci][v] & BYTE_MASK) + disp) > 0xfe) 199 disp -= SKIP; 200 201 for (cfbit = cmp_bitmap[ci][v], i = -1, cf = -1; i < disp; cf++) 202 { 203 if (cfbit & BIT_MASK) 204 i++; 205 cfbit >>= 1; 206 } 207 208 if (cf == -1) 209 return(FAILED); 210 211 code = ci + 0xa; 212 code = (code << 5) | (v + (v + 1) / 3 + 2); 213 return((code << 5) | cf | 0x8000); 214 } 215 else if (code >= 0xA4A1 && code <= 0xA4BE) /* Chosung-only */ 216 { 217 if (X32_19[code -= 0xA4A0] == -1) 218 return(ILLEGAL_SEQ); 219 return(((unsigned char)(X32_19[code] << 2) << 8) | 0x8021); 220 } 221 else if (code >= 0xA4BF && code <= 0xA4D3) /* Joongsung-only */ 222 { 223 code -= 0xA4BE; 224 return(((code + code / 3 + 1) << 5) | 0xA401); 225 } 226 227 return(FAILED); 228 } /* end of static unsigned short _wansung_to_johap(unsigned short). */ 229 230 231 struct _cv_state * 232 _cv_open() 233 { 234 struct _cv_state *st; 235 236 if ((st = (struct _cv_state *)malloc(sizeof(struct _cv_state))) == NULL) 237 return ((void *)-1); 238 239 st->invalid = 0; 240 st->flush_obuf = 0; 241 st->ibuf_left = 0; 242 st->start_cnt = 0; 243 st->end_cnt = 0; 244 245 return (st); 246 } 247 248 void 249 _cv_close(st) 250 struct _cv_state *st; 251 { 252 free(st); 253 } 254 255 256 size_t 257 _cv_enconv(st, inbuf, inbytesleft, outbuf, outbytesleft) 258 struct _cv_state *st; 259 char **inbuf; 260 size_t*inbytesleft; 261 char **outbuf; 262 size_t*outbytesleft; 263 { 264 int c, d; 265 KCHAR code; 266 267 if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ 268 st->invalid = 0; 269 st->flush_obuf = 0; 270 st->ibuf_left = 0; 271 st->start_cnt = 0; 272 st->end_cnt = 0; 273 return (0); 274 } 275 276 if (st->flush_obuf) { 277 while ((*outbytesleft > 0) && (st->start_cnt < st->end_cnt)) { 278 **outbuf = st->temp_obuf[st->start_cnt]; 279 (*outbuf)++; 280 (*outbytesleft)--; 281 (st->start_cnt)++; 282 } 283 284 if (st->start_cnt < st->end_cnt) { 285 return(*inbytesleft); 286 } else { 287 st->flush_obuf = 0; 288 st->start_cnt = 0; 289 st->end_cnt = 0; 290 } 291 } 292 293 st->my_outbuf = outbuf; 294 st->my_outbytesleft = outbytesleft; 295 296 while (*inbytesleft > 0 && *(st->my_outbytesleft) > 0) { 297 298 if (st->ibuf_left) { 299 c = st->temp_ibuf[0]; 300 st->ibuf_left = 0; 301 } else { 302 c = (**inbuf)&BYTE_MASK; 303 (*inbuf)++, (*inbytesleft)--; 304 } 305 306 if (iskorea1(c)) { 307 if ( *inbytesleft <= 0) { 308 st->ibuf_left = 1; 309 st->temp_ibuf[0] = c; 310 return(*inbytesleft); 311 } 312 313 d = (**inbuf)&BYTE_MASK; 314 (*inbuf)++, (*inbytesleft)--; 315 code = c<<8|d; 316 317 if ((code = comptopack(code)) == K_ILLEGAL) { 318 AddChar ('?', st); 319 AddChar ('?', st); 320 } else { 321 AddChar (code>>8, st); 322 AddChar (code&BYTE_MASK, st); 323 } 324 if (st->invalid) { 325 st->invalid = 0; 326 return(*inbytesleft); 327 } 328 329 } else { /* output normal Ascii code */ 330 AddChar (c, st); 331 if (st->invalid) { 332 st->invalid = 0; 333 return(*inbytesleft); 334 } 335 } 336 } 337 return (*inbytesleft); 338 } 339 340 void 341 AddChar (Char, st) 342 char Char; 343 struct _cv_state *st; 344 { 345 /* no more outbuf space */ 346 if (*(st->my_outbytesleft) <= 0) { 347 st->invalid = 1; 348 st->temp_obuf[st->end_cnt] = Char; 349 st->end_cnt++; 350 st->flush_obuf = 1; 351 } else { 352 **(st->my_outbuf) = Char; 353 (*(st->my_outbuf))++, (*(st->my_outbytesleft))--; 354 } 355 } 356 357 #ifdef TEST 358 359 /* test case 1 */ 360 char ibuf1[] = {0xb0, 0xa1, 0xb0, 0xa2, 0x41, 0xb0 , 0xa3}; 361 char obuf1[20]; 362 363 /* test case 2 */ 364 char ibuf2[] = {0xb0, 0xa1, 0xb0, 0xa2, 0xb0}; 365 char ibuf21[] = {0xa3 , 0x41}; 366 char obuf2[20]; 367 368 /* test case 3 */ 369 char ibuf3[] = {0xb0, 0xa1, 0xb0, 0xa2, 0xb0, 0xa3 , 0x41}; 370 char obuf3[5]; 371 372 main() 373 { 374 int i; 375 struct _cv_state *st; 376 size_t oleft, ileft; 377 char *ip1 = &ibuf1[0], *op1 = &obuf1[0], 378 *ip2 = &ibuf2[0], *ip21 = &ibuf21[0], *op2 = &obuf2[0], 379 *ip3 = &ibuf3[0], *op3 = &obuf3[0]; 380 381 /****************************** test case 1 *************************/ 382 ileft = sizeof(ibuf1); 383 oleft = sizeof(obuf1); 384 385 st = _cv_open(); 386 387 printf("TEST 1\n INPUT BUFFER: "); 388 for (i = 0; i < ileft ; i++) { 389 printf("%x ", 0xff&ibuf1[i]); 390 } 391 printf("\n"); 392 printf("OUTPUT: return value %d ", 393 _cv_enconv(st, &ip1, &ileft, &op1, &oleft)); 394 printf("ileft %d oleft %d\n", ileft, oleft); 395 printf(" flush_obuf %d ibuf_left %d\n", st->flush_obuf, 396 st->ibuf_left); 397 printf("OUTPUT BUFFER: "); 398 for (i = 0; i < (sizeof(obuf1) - oleft) ; i++) { 399 printf("%x ", obuf1[i]); 400 } 401 printf("\n\n\n"); 402 _cv_close(st); 403 404 /************************ test case 2 ******************************/ 405 ileft = sizeof(ibuf2); 406 oleft = sizeof(obuf2); 407 408 st = _cv_open(); 409 410 printf("TEST 2\nINPUT BUFFER: "); 411 for (i = 0; i < ileft ; i++) { 412 printf("%x ", 0xff&ibuf2[i]); 413 } 414 printf("\n"); 415 printf("OUTPUT: return value %d ", 416 _cv_enconv(st, &ip2, &ileft, &op2, &oleft)); 417 printf("ileft %d oleft %d\n", ileft, oleft); 418 printf(" flush_obuf %d ibuf_left %d\n", st->flush_obuf, 419 st->ibuf_left); 420 printf("OUTPUT BUFFER: "); 421 for (i = 0; i < (sizeof(obuf2) - oleft) ; i++) { 422 printf("%x ", obuf2[i]); 423 } 424 printf("\n\n"); 425 426 ileft = sizeof(ibuf21); 427 oleft = sizeof(obuf2); 428 op2 = &obuf2[0]; 429 printf("INPUT BUFFER: "); 430 for (i = 0; i < ileft ; i++) { 431 printf("%x ", 0xff&ibuf21[i]); 432 } 433 printf("\n"); 434 printf("OUTPUT: return value %d ", 435 _cv_enconv(st, &ip21, &ileft, &op2, &oleft)); 436 printf("ileft %d oleft %d\n", ileft, oleft); 437 printf(" flush_obuf %d ibuf_left %d\n", st->flush_obuf, 438 st->ibuf_left); 439 printf("OUTPUT BUFFER: "); 440 for (i = 0; i < (sizeof(obuf2) - oleft) ; i++) { 441 printf("%x ", obuf2[i]); 442 } 443 printf("\n\n\n"); 444 _cv_close(st); 445 446 /************************ test case 3 ******************************/ 447 ileft = sizeof(ibuf3); 448 oleft = sizeof(obuf3); 449 450 st = _cv_open(); 451 452 printf("TEST 3\nINPUT BUFFER: "); 453 for (i = 0; i < ileft ; i++) { 454 printf("%x ", 0xff&ibuf3[i]); 455 } 456 printf("\n"); 457 printf("OUTPUT: return value %d ", 458 _cv_enconv(st, &ip3, &ileft, &op3, &oleft)); 459 printf("ileft %d oleft %d\n", ileft, oleft); 460 printf(" flush_obuf %d ibuf_left %d\n", st->flush_obuf, 461 st->ibuf_left); 462 printf(" strat_cnt %d end_cnt %d\n", st->start_cnt, 463 st->end_cnt); 464 printf("OUTPUT BUFFER: "); 465 for (i = 0; i < (sizeof(obuf3) - oleft) ; i++) { 466 printf("%x ", obuf3[i]); 467 } 468 printf("\n\n"); 469 470 op3 = &obuf3[0]; 471 oleft = sizeof(obuf3); 472 printf("OUTPUT: return value %d ", 473 _cv_enconv(st, &ip3, &ileft, &op3, &oleft)); 474 printf("ileft %d oleft %d\n", ileft, oleft); 475 printf(" flush_obuf %d ibuf_left %d\n", st->flush_obuf, 476 st->ibuf_left); 477 printf(" strat_cnt %d end_cnt %d\n", st->start_cnt, 478 st->end_cnt); 479 printf("OUTPUT BUFFER: "); 480 for (i = 0; i < (sizeof(obuf3) - oleft) ; i++) { 481 printf("%x ", obuf3[i]); 482 } 483 printf("\n\n"); 484 485 op3 = &obuf3[0]; 486 oleft = sizeof(obuf3); 487 printf("OUTPUT: return value %d ", 488 _cv_enconv(st, &ip3, &ileft, &op3, &oleft)); 489 printf("ileft %d oleft %d\n", ileft, oleft); 490 printf(" flush_obuf %d ibuf_left %d\n", st->flush_obuf, 491 st->ibuf_left); 492 printf(" strat_cnt %d end_cnt %d\n", st->start_cnt, 493 st->end_cnt); 494 printf("OUTPUT BUFFER: "); 495 for (i = 0; i < (sizeof(obuf3) - oleft) ; i++) { 496 printf("%x ", obuf3[i]); 497 } 498 printf("\n\n\n"); 499 _cv_close(st); 500 } 501 502 /* expected output 503 504 TEST 1 505 INPUT BUFFER: b0 a1 b0 a2 41 b0 a3 506 OUTPUT: return value 0 ileft 0 oleft 13 507 flush_obuf 0 ibuf_left 0 508 OUTPUT BUFFER: ffffffa8 41 ffffffa8 42 41 ffffffa8 45 509 510 511 TEST 2 512 INPUT BUFFER: b0 a1 b0 a2 b0 513 OUTPUT: return value 0 ileft 0 oleft 16 514 flush_obuf 0 ibuf_left 1 515 OUTPUT BUFFER: ffffffa8 41 ffffffa8 42 516 517 INPUT BUFFER: a3 41 518 OUTPUT: return value 0 ileft 0 oleft 17 519 flush_obuf 0 ibuf_left 0 520 OUTPUT BUFFER: ffffffa8 45 41 521 522 523 TEST 3 524 INPUT BUFFER: b0 a1 b0 a2 b0 a3 41 525 OUTPUT: return value 1 ileft 1 oleft 0 526 flush_obuf 1 ibuf_left 0 527 strat_cnt 0 end_cnt 1 528 OUTPUT BUFFER: ffffffa8 41 ffffffa8 42 ffffffa8 529 530 OUTPUT: return value 0 ileft 0 oleft 3 531 flush_obuf 0 ibuf_left 0 532 strat_cnt 0 end_cnt 0 533 OUTPUT BUFFER: 45 41 534 535 OUTPUT: return value 0 ileft 0 oleft 5 536 flush_obuf 0 ibuf_left 0 537 strat_cnt 0 end_cnt 0 538 OUTPUT BUFFER: 539 */ 540 541 #endif /* TEST */ 542