]> mj.ucw.cz Git - libucw.git/blob - lib/ff-unicode.c
UCW: Implemented bput_utf16_*.
[libucw.git] / lib / ff-unicode.c
1 /*
2  *      UCW Library: Reading and writing of UTF-8 on Fastbuf Streams
3  *
4  *      (c) 2001--2004 Martin Mares <mj@ucw.cz>
5  *      (c) 2004 Robert Spalek <robert@ucw.cz>
6  *
7  *      This software may be freely distributed and used according to the terms
8  *      of the GNU Lesser General Public License.
9  */
10
11 #include "lib/lib.h"
12 #include "lib/fastbuf.h"
13 #include "lib/unicode.h"
14 #include "lib/ff-unicode.h"
15 #include "lib/ff-binary.h"
16
17 /*** UTF-8 ***/
18
19 int
20 bget_utf8_slow(struct fastbuf *b, uns repl)
21 {
22   int c = bgetc(b);
23   int code;
24
25   if (c < 0x80)                         /* Includes EOF */
26     return c;
27   if (c < 0xc0)                         /* Incorrect combination */
28     return repl;
29   if (c >= 0xf0)                        /* Too large, skip it */
30     {
31       while ((c = bgetc(b)) >= 0x80 && c < 0xc0)
32         ;
33       goto wrong;
34     }
35   if (c >= 0xe0)                        /* 3 bytes */
36     {
37       code = c & 0x0f;
38       if ((c = bgetc(b)) < 0x80 || c >= 0xc0)
39         goto wrong;
40       code = (code << 6) | (c & 0x3f);
41       if ((c = bgetc(b)) < 0x80 || c >= 0xc0)
42         goto wrong;
43       code = (code << 6) | (c & 0x3f);
44     }
45   else                                  /* 2 bytes */
46     {
47       code = c & 0x1f;
48       if ((c = bgetc(b)) < 0x80 || c >= 0xc0)
49         goto wrong;
50       code = (code << 6) | (c & 0x3f);
51     }
52   return code;
53
54  wrong:
55   if (c >= 0)
56     bungetc(b);
57   return repl;
58 }
59
60 int
61 bget_utf8_32_slow(struct fastbuf *b, uns repl)
62 {
63   int c = bgetc(b);
64   int code;
65   int nr;
66
67   if (c < 0x80)                         /* Includes EOF */
68     return c;
69   if (c < 0xc0)                         /* Incorrect combination */
70     return repl;
71   if (c < 0xe0)
72     {
73       code = c & 0x1f;
74       nr = 1;
75     }
76   else if (c < 0xf0)
77     {
78       code = c & 0x0f;
79       nr = 2;
80     }
81   else if (c < 0xf8)
82     {
83       code = c & 0x07;
84       nr = 3;
85     }
86   else if (c < 0xfc)
87     {
88       code = c & 0x03;
89       nr = 4;
90     }
91   else if (c < 0xfe)
92     {
93       code = c & 0x01;
94       nr = 5;
95     }
96   else                                  /* Too large, skip it */
97     {
98       while ((c = bgetc(b)) >= 0x80 && c < 0xc0)
99         ;
100       goto wrong;
101     }
102   while (nr-- > 0)
103     {
104       if ((c = bgetc(b)) < 0x80 || c >= 0xc0)
105         goto wrong;
106       code = (code << 6) | (c & 0x3f);
107     }
108   return code;
109
110  wrong:
111   if (c >= 0)
112     bungetc(b);
113   return repl;
114 }
115
116 void
117 bput_utf8_slow(struct fastbuf *b, uns u)
118 {
119   ASSERT(u < 65536);
120   if (u < 0x80)
121     bputc(b, u);
122   else
123     {
124       if (u < 0x800)
125         bputc(b, 0xc0 | (u >> 6));
126       else
127         {
128           bputc(b, 0xe0 | (u >> 12));
129           bputc(b, 0x80 | ((u >> 6) & 0x3f));
130         }
131       bputc(b, 0x80 | (u & 0x3f));
132     }
133 }
134
135 void
136 bput_utf8_32_slow(struct fastbuf *b, uns u)
137 {
138   ASSERT(u < (1U<<31));
139   if (u < 0x80)
140     bputc(b, u);
141   else
142     {
143       if (u < 0x800)
144         bputc(b, 0xc0 | (u >> 6));
145       else
146         {
147           if (u < (1<<16))
148             bputc(b, 0xe0 | (u >> 12));
149           else
150             {
151               if (u < (1<<21))
152                 bputc(b, 0xf0 | (u >> 18));
153               else
154                 {
155                   if (u < (1<<26))
156                     bputc(b, 0xf8 | (u >> 24));
157                   else
158                     {
159                       bputc(b, 0xfc | (u >> 30));
160                       bputc(b, 0x80 | ((u >> 24) & 0x3f));
161                     }
162                   bputc(b, 0x80 | ((u >> 18) & 0x3f));
163                 }
164               bputc(b, 0x80 | ((u >> 12) & 0x3f));
165             }
166           bputc(b, 0x80 | ((u >> 6) & 0x3f));
167         }
168       bputc(b, 0x80 | (u & 0x3f));
169     }
170 }
171
172 /*** UTF-16 ***/
173
174 int
175 bget_utf16_be_slow(struct fastbuf *b, uns repl)
176 {
177   if (bpeekc(b) < 0)
178     return -1;
179   uns u = bgetw_be(b), x, y;
180   if ((int)u < 0)
181     return repl;
182   if ((x = u - 0xd800) >= 0x800)
183     return u;
184   if (x >= 0x400 || bpeekc(b) < 0 || (y = bgetw_be(b) - 0xdc00) >= 0x400)
185     return repl;
186   return 0x10000 + (x << 10) + y;
187 }
188
189 int
190 bget_utf16_le_slow(struct fastbuf *b, uns repl)
191 {
192   if (bpeekc(b) < 0)
193     return -1;
194   uns u = bgetw_le(b), x, y;
195   if ((int)u < 0)
196     return repl;
197   if ((x = u - 0xd800) >= 0x800)
198     return u;
199   if (x >= 0x400 || bpeekc(b) < 0 || (y = bgetw_le(b) - 0xdc00) >= 0x400)
200     return repl;
201   return 0x10000 + (x << 10) + y;
202 }
203
204 void
205 bput_utf16_be_slow(struct fastbuf *b, uns u)
206 {
207   if (u < 0xd800 || (u < 0x10000 && u >= 0xe000))
208     {
209       bputc(b, u >> 8);
210       bputc(b, u & 0xff);
211     }
212   else if ((u -= 0x10000) < 0x100000)
213     {
214       bputc(b, 0xd8 | (u >> 18));
215       bputc(b, (u >> 10) & 0xff);
216       bputc(b, 0xdc | ((u >> 8) & 0x3));
217       bputc(b, u & 0xff);
218     }
219   else
220     ASSERT(0);
221 }
222
223 void
224 bput_utf16_le_slow(struct fastbuf *b, uns u)
225 {
226   if (u < 0xd800 || (u < 0x10000 && u >= 0xe000))
227     {
228       bputc(b, u & 0xff);
229       bputc(b, u >> 8);
230     }
231   else if ((u -= 0x10000) < 0x100000)
232     {
233       bputc(b, (u >> 10) & 0xff);
234       bputc(b, 0xd8 | (u >> 18));
235       bputc(b, u & 0xff);
236       bputc(b, 0xdc | ((u >> 8) & 0x3));
237     }
238   else
239     ASSERT(0);
240 }