xref: /csrg-svn/lib/libc/locale/utf2.c (revision 61137)
160475Sbostic /*-
2*61137Sbostic  * Copyright (c) 1993
3*61137Sbostic  *	The Regents of the University of California.  All rights reserved.
460475Sbostic  *
560475Sbostic  * This code is derived from software contributed to Berkeley by
660475Sbostic  * Paul Borman at Krystal Technologies.
760475Sbostic  *
860475Sbostic  * %sccs.include.redist.c%
960475Sbostic  */
1060475Sbostic 
1160475Sbostic #if defined(LIBC_SCCS) && !defined(lint)
12*61137Sbostic static char sccsid[] = "@(#)utf2.c	8.1 (Berkeley) 06/04/93";
1360475Sbostic #endif /* LIBC_SCCS and not lint */
1460475Sbostic 
1560475Sbostic #include <errno.h>
1660475Sbostic #include <rune.h>
1760475Sbostic #include <stddef.h>
1860475Sbostic #include <stdio.h>
1960475Sbostic #include <stdlib.h>
2060475Sbostic 
2160475Sbostic rune_t	_UTF2_sgetrune __P((const char *, size_t, char const **));
2260475Sbostic int	_UTF2_sputrune __P((rune_t, char *, size_t, char **));
2360475Sbostic 
2460475Sbostic static _utf_count[16] = {
2560475Sbostic 	1, 1, 1, 1, 1, 1, 1, 1,
2660475Sbostic 	0, 0, 0, 0, 2, 2, 3, 0,
2760475Sbostic };
2860475Sbostic 
2960475Sbostic int
_UTF2_init(rl)3060475Sbostic _UTF2_init(rl)
3160475Sbostic 	_RuneLocale *rl;
3260475Sbostic {
3360475Sbostic 	rl->sgetrune = _UTF2_sgetrune;
3460475Sbostic 	rl->sputrune = _UTF2_sputrune;
3560475Sbostic 	_CurrentRuneLocale = rl;
3660475Sbostic 	__mb_cur_max = 3;
3760475Sbostic 	return (0);
3860475Sbostic }
3960475Sbostic 
4060475Sbostic rune_t
_UTF2_sgetrune(string,n,result)4160475Sbostic _UTF2_sgetrune(string, n, result)
4260475Sbostic 	const char *string;
4360475Sbostic 	size_t n;
4460475Sbostic 	char const **result;
4560475Sbostic {
4660475Sbostic 	int c;
4760475Sbostic 
4860475Sbostic 	if (n < 1 || (c = _utf_count[(*string >> 4) & 0xf]) > n) {
4960475Sbostic 		if (result)
5060475Sbostic 			*result = string;
5160475Sbostic 		return (_INVALID_RUNE);
5260475Sbostic 	}
5360475Sbostic 	switch (c) {
5460475Sbostic 	case 1:
5560475Sbostic 		if (result)
5660475Sbostic 			*result = string + 1;
5760475Sbostic 		return (*string & 0xff);
5860475Sbostic 	case 2:
5960475Sbostic 		if ((string[1] & 0xC0) != 0x80)
6060475Sbostic 			goto encoding_error;
6160475Sbostic 		if (result)
6260475Sbostic 			*result = string + 2;
6360475Sbostic 		return (((string[0] & 0x1F) << 6) | (string[1] & 0x3F));
6460475Sbostic 	case 3:
6560475Sbostic 		if ((string[1] & 0xC0) != 0x80 || (string[2] & 0xC0) != 0x80)
6660475Sbostic 			goto encoding_error;
6760475Sbostic 		if (result)
6860475Sbostic 			*result = string + 3;
6960475Sbostic 		return (((string[0] & 0x1F) << 12) | ((string[1] & 0x3F) << 6)
7060475Sbostic 		    | (string[2] & 0x3F));
7160475Sbostic 	default:
7260475Sbostic encoding_error:	if (result)
7360475Sbostic 			*result = string + 1;
7460475Sbostic 		return (_INVALID_RUNE);
7560475Sbostic 	}
7660475Sbostic }
7760475Sbostic 
7860475Sbostic int
_UTF2_sputrune(c,string,n,result)7960475Sbostic _UTF2_sputrune(c, string, n, result)
8060475Sbostic 	rune_t c;
8160475Sbostic 	char *string, **result;
8260475Sbostic 	size_t n;
8360475Sbostic {
8460475Sbostic 	if (c & 0xF800) {
8560475Sbostic 		if (n >= 3) {
8660475Sbostic 			if (string) {
8760475Sbostic 				string[0] = 0xE0 | ((c >> 12) & 0x0F);
8860475Sbostic 				string[1] = 0x80 | ((c >> 6) & 0x3F);
8960475Sbostic 				string[2] = 0x80 | ((c) & 0x3F);
9060475Sbostic 			}
9160475Sbostic 			if (result)
9260475Sbostic 				*result = string + 3;
9360475Sbostic 		} else
9460475Sbostic 			if (result)
9560475Sbostic 				*result = NULL;
9660475Sbostic 
9760475Sbostic 		return (3);
9860475Sbostic 	} else
9960475Sbostic 		if (c & 0x0780) {
10060475Sbostic 			if (n >= 2) {
10160475Sbostic 				if (string) {
10260475Sbostic 					string[0] = 0xC0 | ((c >> 6) & 0x1F);
10360475Sbostic 					string[1] = 0x80 | ((c) & 0x3F);
10460475Sbostic 				}
10560475Sbostic 				if (result)
10660475Sbostic 					*result = string + 2;
10760475Sbostic 			} else
10860475Sbostic 				if (result)
10960475Sbostic 					*result = NULL;
11060475Sbostic 			return (2);
11160475Sbostic 		} else {
11260475Sbostic 			if (n >= 1) {
11360475Sbostic 				if (string)
11460475Sbostic 					string[0] = c;
11560475Sbostic 				if (result)
11660475Sbostic 					*result = string + 1;
11760475Sbostic 			} else
11860475Sbostic 				if (result)
11960475Sbostic 					*result = NULL;
12060475Sbostic 			return (1);
12160475Sbostic 		}
12260475Sbostic }
123