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