udftools

- Main Page
- Classes
- Files

- File List
- File Members

All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
unicode.c
Go to the documentation of this file.
1 /*
2 * unicode.c
3 *
4 * Copyright (c) 2001-2002 Ben Fennema <bfennema@falcon.csc.calpoly.edu>
5 * All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 */
22
28 #include "config.h"
29
30 #include "libudffs.h"
31
32 size_t decode_utf8(dstring *in, char *out, size_t inlen)
33 {
34 size_t len = 0, i;
35 unsigned int c;
36
37 if (in[inlen-1] == 0)
38 return 0;
39 else if (in[0] != 8 && in[0] != 16)
40 return 0;
41
42 for (i=1; i<inlen;)
43 {
44 c = in[i++];
45 if (in[0] == 16)
46 c = (c << 8) | in[i++];
47
48 if (c == 0x00U)
49 break;
50 else if (c < 0x80U)
51 out[len++] = (uint8_t)c;
52 else if (c < 0x800U)
53 {
54 out[len++] = (uint8_t)(0xc0 | (c >> 6));
55 out[len++] = (uint8_t)(0x80 | (c & 0x3f));
56 }
57 else
58 {
59 out[len++] = (uint8_t)(0xe0 | (c >> 12));
60 out[len++] = (uint8_t)(0x80 | ((c >> 6) & 0x3f));
61 out[len++] = (uint8_t)(0x80 | (c & 0x3f));
62 }
63 }
64
65 return len;
66 }
67
68 size_t encode_utf8(dstring *out, char *hdr, char *in, size_t outlen)
69 {
70 size_t inlen = strlen(in);
71 size_t len = 1, i;
72 int utf_cnt;
73 uint32_t utf_char, max_val;
74 unsigned int c;
75
76 out[0] = 8;
77 max_val = 0xFF;
78
79 try_again:
80 utf_cnt = 0;
81 utf_char = 0;
82
83 if (max_val == 0xFF)
84 {
85 memcpy(&out[1], hdr, strlen(hdr));
86 len = strlen(hdr) + 1;
87 }
88 else if (max_val == 0xFFFF)
89 {
90 for (i=0; i<strlen(hdr); i++)
91 out[2+(i*2)] = hdr[i];
92 len = (strlen(hdr) * 2) + 1;
93 }
94
95 for (i=0; i<inlen; i++)
96 {
97 c = in[i];
98
99 /* Complete a multi-byte UTF-8 character */
100 if (utf_cnt)
101 {
102 utf_char = (utf_char << 6) | (c & 0x3F);
103 if (--utf_cnt)
104 continue;
105 }
106 else
107 {
108 /* Check for a multi-byte UTF-8 character */
109 if (c & 0x80)
110 {
111 /* Start a multi-byte UTF-8 character */
112 if ((c & 0xE0) == 0xC0)
113 {
114 utf_char = c & 0x1fU;
115 utf_cnt = 1;
116 }
117 else if ((c & 0xF0) == 0xE0)
118 {
119 utf_char = c & 0x0F;
120 utf_cnt = 2;
121 }
122 else if ((c & 0xF8) == 0xF0)
123 {
124 utf_char = c & 0x07;
125 utf_cnt = 3;
126 }
127 else if ((c & 0xFC) == 0xF8)
128 {
129 utf_char = c & 0x03;
130 utf_cnt = 4;
131 }
132 else if ((c & 0xFE) == 0xfc)
133 {
134 utf_char = c & 0x01;
135 utf_cnt = 5;
136 }
137 else
138 goto error_out;
139 continue;
140 }
141 else
142 {
143 /* Single byte UTF-8 character (most common) */
144 utf_char = c;
145 }
146 }
147
148 /* Choose no compression if necessary */
149 if (utf_char > max_val)
150 {
151 if ( 0xFF == max_val )
152 {
153 max_val = 0xFFFF;
154 out[0] = 0x10;
155 goto try_again;
156 }
157 goto error_out;
158 }
159
160 if (max_val == 0xFFFF)
161 {
162 if (len + 2 >= outlen)
163 goto error_out;
164 out[len++] = utf_char >> 8;
165 }
166 if (len + 1 >= outlen)
167 goto error_out;
168 out[len++] = utf_char & 0xFF;
169 }
170
171 if (utf_cnt)
172 error_out:
173 return 0;
174
175 return len;
176 }
177
178 size_t decode_string(struct udf_disc *disc, dstring *in, char *out, size_t inlen)
179 {
180 if (disc->flags & FLAG_UTF8)
181 return decode_utf8(in, out, inlen);
182 else if (disc->flags & (FLAG_UNICODE8 | FLAG_UNICODE16))
183 {
184 memcpy(out, &in[1], inlen);
185 return inlen;
186 }
187 else
188 return 0;
189 }
190
191 size_t encode_string(struct udf_disc *disc, dstring *out, char *hdr, char *in, size_t outlen)
192 {
193 size_t i;
194
195 memset(out, 0x00, outlen);
196 if (disc->flags & FLAG_UTF8)
197 return encode_utf8(out, hdr, in, outlen);
198 else if (disc->flags & FLAG_UNICODE8)
199 {
200 if (strlen(hdr) + strlen(in) >= outlen - 2)
201 return 0;
202 else
203 {
204 memcpy(&out[1], hdr, strlen(hdr));
205 memcpy(&out[1+strlen(hdr)], in, strlen(in));
206 out[0] = 0x08;
207 return strlen(hdr) + strlen(in) + 1;
208 }
209 }
210 else if (disc->flags & FLAG_UNICODE16)
211 {
212 if (strlen(hdr)*2 + strlen(in) >= outlen - 2)
213 return 0;
214 else
215 {
216 for (i=0; i<strlen(hdr); i++)
217 out[2+(i*2)] = hdr[i];
218 memcpy(&out[1+(strlen(hdr)*2)], in, strlen(in));
219 out[0] = 0x10;
220 return (strlen(hdr) * 2) + strlen(in) + 1;
221 }
222 }
223 else
224 return 0;
225 }
dstring
uint8_t dstring
Definition: ecma_167.h:63
encode_utf8
size_t encode_utf8(dstring *out, char *hdr, char *in, size_t outlen)
Definition: unicode.c:68
FLAG_UNICODE8
#define FLAG_UNICODE8
Definition: libudffs.h:45
FLAG_UTF8
#define FLAG_UTF8
Definition: libudffs.h:47
decode_string
size_t decode_string(struct udf_disc *disc, dstring *in, char *out, size_t inlen)
Definition: unicode.c:178
udf_disc::flags
uint32_t flags
Definition: libudffs.h:100
udf_disc
Definition: libudffs.h:95
encode_string
size_t encode_string(struct udf_disc *disc, dstring *out, char *hdr, char *in, size_t outlen)
Definition: unicode.c:191
libudffs.h
FLAG_UNICODE16
#define FLAG_UNICODE16
Definition: libudffs.h:46
decode_utf8
size_t decode_utf8(dstring *in, char *out, size_t inlen)
Definition: unicode.c:32