efichar.c revision 1.1 1 1.1 nonaka /* $NetBSD: efichar.c,v 1.1 2018/03/27 14:15:05 nonaka Exp $ */
2 1.1 nonaka
3 1.1 nonaka /*-
4 1.1 nonaka * Copyright (c) 2010 Marcel Moolenaar
5 1.1 nonaka * All rights reserved.
6 1.1 nonaka *
7 1.1 nonaka * Redistribution and use in source and binary forms, with or without
8 1.1 nonaka * modification, are permitted provided that the following conditions
9 1.1 nonaka * are met:
10 1.1 nonaka * 1. Redistributions of source code must retain the above copyright
11 1.1 nonaka * notice, this list of conditions and the following disclaimer.
12 1.1 nonaka * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 nonaka * notice, this list of conditions and the following disclaimer in the
14 1.1 nonaka * documentation and/or other materials provided with the distribution.
15 1.1 nonaka *
16 1.1 nonaka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 1.1 nonaka * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 1.1 nonaka * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 1.1 nonaka * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 1.1 nonaka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 1.1 nonaka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 1.1 nonaka * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 1.1 nonaka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 1.1 nonaka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 1.1 nonaka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 1.1 nonaka * SUCH DAMAGE.
27 1.1 nonaka */
28 1.1 nonaka
29 1.1 nonaka #include <sys/cdefs.h>
30 1.1 nonaka #if 0
31 1.1 nonaka __FBSDID("$FreeBSD: head/stand/efi/libefi/efichar.c 328061 2018-01-16 20:35:54Z tsoome $");
32 1.1 nonaka #endif
33 1.1 nonaka
34 1.1 nonaka #include "efiboot.h"
35 1.1 nonaka
36 1.1 nonaka size_t
37 1.1 nonaka ucs2len(const CHAR16 *str)
38 1.1 nonaka {
39 1.1 nonaka size_t i;
40 1.1 nonaka
41 1.1 nonaka i = 0;
42 1.1 nonaka while (*str++)
43 1.1 nonaka i++;
44 1.1 nonaka return i;
45 1.1 nonaka }
46 1.1 nonaka
47 1.1 nonaka /*
48 1.1 nonaka * If nm were converted to utf8, what what would strlen
49 1.1 nonaka * return on the resulting string?
50 1.1 nonaka */
51 1.1 nonaka static size_t
52 1.1 nonaka utf8_len_of_ucs2(const CHAR16 *nm)
53 1.1 nonaka {
54 1.1 nonaka size_t len;
55 1.1 nonaka CHAR16 c;
56 1.1 nonaka
57 1.1 nonaka len = 0;
58 1.1 nonaka while (*nm) {
59 1.1 nonaka c = *nm++;
60 1.1 nonaka if (c > 0x7ff)
61 1.1 nonaka len += 3;
62 1.1 nonaka else if (c > 0x7f)
63 1.1 nonaka len += 2;
64 1.1 nonaka else
65 1.1 nonaka len++;
66 1.1 nonaka }
67 1.1 nonaka
68 1.1 nonaka return len;
69 1.1 nonaka }
70 1.1 nonaka
71 1.1 nonaka int
72 1.1 nonaka ucs2_to_utf8(const CHAR16 *nm, char **name)
73 1.1 nonaka {
74 1.1 nonaka size_t len, sz;
75 1.1 nonaka CHAR16 c;
76 1.1 nonaka char *cp;
77 1.1 nonaka int freeit = *name == NULL;
78 1.1 nonaka
79 1.1 nonaka sz = utf8_len_of_ucs2(nm) + 1;
80 1.1 nonaka len = 0;
81 1.1 nonaka if (*name != NULL)
82 1.1 nonaka cp = *name;
83 1.1 nonaka else
84 1.1 nonaka cp = *name = AllocatePool(sz);
85 1.1 nonaka if (*name == NULL)
86 1.1 nonaka return ENOMEM;
87 1.1 nonaka
88 1.1 nonaka while (*nm) {
89 1.1 nonaka c = *nm++;
90 1.1 nonaka if (c > 0x7ff) {
91 1.1 nonaka if (len++ < sz)
92 1.1 nonaka *cp++ = (char)(0xE0 | (c >> 12));
93 1.1 nonaka if (len++ < sz)
94 1.1 nonaka *cp++ = (char)(0x80 | ((c >> 6) & 0x3f));
95 1.1 nonaka if (len++ < sz)
96 1.1 nonaka *cp++ = (char)(0x80 | (c & 0x3f));
97 1.1 nonaka } else if (c > 0x7f) {
98 1.1 nonaka if (len++ < sz)
99 1.1 nonaka *cp++ = (char)(0xC0 | ((c >> 6) & 0x1f));
100 1.1 nonaka if (len++ < sz)
101 1.1 nonaka *cp++ = (char)(0x80 | (c & 0x3f));
102 1.1 nonaka } else {
103 1.1 nonaka if (len++ < sz)
104 1.1 nonaka *cp++ = (char)(c & 0x7f);
105 1.1 nonaka }
106 1.1 nonaka }
107 1.1 nonaka
108 1.1 nonaka if (len >= sz) {
109 1.1 nonaka /* Absent bugs, we'll never return EOVERFLOW */
110 1.1 nonaka if (freeit) {
111 1.1 nonaka FreePool(*name);
112 1.1 nonaka *name = NULL;
113 1.1 nonaka }
114 1.1 nonaka return EOVERFLOW;
115 1.1 nonaka }
116 1.1 nonaka *cp++ = '\0';
117 1.1 nonaka
118 1.1 nonaka return 0;
119 1.1 nonaka }
120 1.1 nonaka
121 1.1 nonaka int
122 1.1 nonaka utf8_to_ucs2(const char *name, CHAR16 **nmp, size_t *len)
123 1.1 nonaka {
124 1.1 nonaka CHAR16 *nm;
125 1.1 nonaka size_t sz;
126 1.1 nonaka uint32_t ucs4;
127 1.1 nonaka int c, bytes;
128 1.1 nonaka int freeit = *nmp == NULL;
129 1.1 nonaka
130 1.1 nonaka sz = strlen(name) * 2 + 2;
131 1.1 nonaka if (*nmp == NULL)
132 1.1 nonaka *nmp = AllocatePool(sz);
133 1.1 nonaka if (*nmp == NULL)
134 1.1 nonaka return ENOMEM;
135 1.1 nonaka nm = *nmp;
136 1.1 nonaka *len = sz;
137 1.1 nonaka
138 1.1 nonaka ucs4 = 0;
139 1.1 nonaka bytes = 0;
140 1.1 nonaka while (sz > 1 && *name != '\0') {
141 1.1 nonaka c = *name++;
142 1.1 nonaka /*
143 1.1 nonaka * Conditionalize on the two major character types:
144 1.1 nonaka * initial and followup characters.
145 1.1 nonaka */
146 1.1 nonaka if ((c & 0xc0) != 0x80) {
147 1.1 nonaka /* Initial characters. */
148 1.1 nonaka if (bytes != 0)
149 1.1 nonaka goto ilseq;
150 1.1 nonaka if ((c & 0xf8) == 0xf0) {
151 1.1 nonaka ucs4 = c & 0x07;
152 1.1 nonaka bytes = 3;
153 1.1 nonaka } else if ((c & 0xf0) == 0xe0) {
154 1.1 nonaka ucs4 = c & 0x0f;
155 1.1 nonaka bytes = 2;
156 1.1 nonaka } else if ((c & 0xe0) == 0xc0) {
157 1.1 nonaka ucs4 = c & 0x1f;
158 1.1 nonaka bytes = 1;
159 1.1 nonaka } else {
160 1.1 nonaka ucs4 = c & 0x7f;
161 1.1 nonaka bytes = 0;
162 1.1 nonaka }
163 1.1 nonaka } else {
164 1.1 nonaka /* Followup characters. */
165 1.1 nonaka if (bytes > 0) {
166 1.1 nonaka ucs4 = (ucs4 << 6) + (c & 0x3f);
167 1.1 nonaka bytes--;
168 1.1 nonaka } else if (bytes == 0)
169 1.1 nonaka goto ilseq;
170 1.1 nonaka }
171 1.1 nonaka if (bytes == 0) {
172 1.1 nonaka if (ucs4 > 0xffff)
173 1.1 nonaka goto ilseq;
174 1.1 nonaka *nm++ = (CHAR16)ucs4;
175 1.1 nonaka sz -= 2;
176 1.1 nonaka }
177 1.1 nonaka }
178 1.1 nonaka if (sz < 2) {
179 1.1 nonaka if (freeit) {
180 1.1 nonaka FreePool(nm);
181 1.1 nonaka *nmp = NULL;
182 1.1 nonaka }
183 1.1 nonaka return EINVAL;
184 1.1 nonaka }
185 1.1 nonaka sz -= 2;
186 1.1 nonaka *nm = 0;
187 1.1 nonaka *len -= sz;
188 1.1 nonaka return 0;
189 1.1 nonaka ilseq:
190 1.1 nonaka if (freeit) {
191 1.1 nonaka FreePool(nm);
192 1.1 nonaka *nmp = NULL;
193 1.1 nonaka }
194 1.1 nonaka return EILSEQ;
195 1.1 nonaka }
196