xref: /original-bsd/lib/libc/locale/utf2.c (revision c3e32dec)
1 /*-
2  * Copyright (c) 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Paul Borman at Krystal Technologies.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #if defined(LIBC_SCCS) && !defined(lint)
12 static char sccsid[] = "@(#)utf2.c	8.1 (Berkeley) 06/04/93";
13 #endif /* LIBC_SCCS and not lint */
14 
15 #include <errno.h>
16 #include <rune.h>
17 #include <stddef.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 
21 rune_t	_UTF2_sgetrune __P((const char *, size_t, char const **));
22 int	_UTF2_sputrune __P((rune_t, char *, size_t, char **));
23 
24 static _utf_count[16] = {
25 	1, 1, 1, 1, 1, 1, 1, 1,
26 	0, 0, 0, 0, 2, 2, 3, 0,
27 };
28 
29 int
30 _UTF2_init(rl)
31 	_RuneLocale *rl;
32 {
33 	rl->sgetrune = _UTF2_sgetrune;
34 	rl->sputrune = _UTF2_sputrune;
35 	_CurrentRuneLocale = rl;
36 	__mb_cur_max = 3;
37 	return (0);
38 }
39 
40 rune_t
41 _UTF2_sgetrune(string, n, result)
42 	const char *string;
43 	size_t n;
44 	char const **result;
45 {
46 	int c;
47 
48 	if (n < 1 || (c = _utf_count[(*string >> 4) & 0xf]) > n) {
49 		if (result)
50 			*result = string;
51 		return (_INVALID_RUNE);
52 	}
53 	switch (c) {
54 	case 1:
55 		if (result)
56 			*result = string + 1;
57 		return (*string & 0xff);
58 	case 2:
59 		if ((string[1] & 0xC0) != 0x80)
60 			goto encoding_error;
61 		if (result)
62 			*result = string + 2;
63 		return (((string[0] & 0x1F) << 6) | (string[1] & 0x3F));
64 	case 3:
65 		if ((string[1] & 0xC0) != 0x80 || (string[2] & 0xC0) != 0x80)
66 			goto encoding_error;
67 		if (result)
68 			*result = string + 3;
69 		return (((string[0] & 0x1F) << 12) | ((string[1] & 0x3F) << 6)
70 		    | (string[2] & 0x3F));
71 	default:
72 encoding_error:	if (result)
73 			*result = string + 1;
74 		return (_INVALID_RUNE);
75 	}
76 }
77 
78 int
79 _UTF2_sputrune(c, string, n, result)
80 	rune_t c;
81 	char *string, **result;
82 	size_t n;
83 {
84 	if (c & 0xF800) {
85 		if (n >= 3) {
86 			if (string) {
87 				string[0] = 0xE0 | ((c >> 12) & 0x0F);
88 				string[1] = 0x80 | ((c >> 6) & 0x3F);
89 				string[2] = 0x80 | ((c) & 0x3F);
90 			}
91 			if (result)
92 				*result = string + 3;
93 		} else
94 			if (result)
95 				*result = NULL;
96 
97 		return (3);
98 	} else
99 		if (c & 0x0780) {
100 			if (n >= 2) {
101 				if (string) {
102 					string[0] = 0xC0 | ((c >> 6) & 0x1F);
103 					string[1] = 0x80 | ((c) & 0x3F);
104 				}
105 				if (result)
106 					*result = string + 2;
107 			} else
108 				if (result)
109 					*result = NULL;
110 			return (2);
111 		} else {
112 			if (n >= 1) {
113 				if (string)
114 					string[0] = c;
115 				if (result)
116 					*result = string + 1;
117 			} else
118 				if (result)
119 					*result = NULL;
120 			return (1);
121 		}
122 }
123