]> mj.ucw.cz Git - libucw.git/blob - lib/ff-unicode.c
047fff84cf16bb57d05748d38b2f9d8c6e6dfe6a
[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 int
18 bget_utf8_slow(struct fastbuf *b, uns repl)
19 {
20   int c = bgetc(b);
21   int code;
22
23   if (c < 0x80)                         /* Includes EOF */
24     return c;
25   if (c < 0xc0)                         /* Incorrect combination */
26     return repl;
27   if (c >= 0xf0)                        /* Too large, skip it */
28     {
29       while ((c = bgetc(b)) >= 0x80 && c < 0xc0)
30         ;
31       goto wrong;
32     }
33   if (c >= 0xe0)                        /* 3 bytes */
34     {
35       code = c & 0x0f;
36       if ((c = bgetc(b)) < 0x80 || c >= 0xc0)
37         goto wrong;
38       code = (code << 6) | (c & 0x3f);
39       if ((c = bgetc(b)) < 0x80 || c >= 0xc0)
40         goto wrong;
41       code = (code << 6) | (c & 0x3f);
42     }
43   else                                  /* 2 bytes */
44     {
45       code = c & 0x1f;
46       if ((c = bgetc(b)) < 0x80 || c >= 0xc0)
47         goto wrong;
48       code = (code << 6) | (c & 0x3f);
49     }
50   return code;
51
52  wrong:
53   if (c >= 0)
54     bungetc(b);
55   return repl;
56 }
57
58 int
59 bget_utf8_32_slow(struct fastbuf *b, uns repl)
60 {
61   int c = bgetc(b);
62   int code;
63   int nr;
64
65   if (c < 0x80)                         /* Includes EOF */
66     return c;
67   if (c < 0xc0)                         /* Incorrect combination */
68     return repl;
69   if (c < 0xe0)
70     {
71       code = c & 0x1f;
72       nr = 1;
73     }
74   else if (c < 0xf0)
75     {
76       code = c & 0x0f;
77       nr = 2;
78     }
79   else if (c < 0xf8)
80     {
81       code = c & 0x07;
82       nr = 3;
83     }
84   else if (c < 0xfc)
85     {
86       code = c & 0x03;
87       nr = 4;
88     }
89   else if (c < 0xfe)
90     {
91       code = c & 0x01;
92       nr = 5;
93     }
94   else                                  /* Too large, skip it */
95     {
96       while ((c = bgetc(b)) >= 0x80 && c < 0xc0)
97         ;
98       goto wrong;
99     }
100   while (nr-- > 0)
101     {
102       if ((c = bgetc(b)) < 0x80 || c >= 0xc0)
103         goto wrong;
104       code = (code << 6) | (c & 0x3f);
105     }
106   return code;
107
108  wrong:
109   if (c >= 0)
110     bungetc(b);
111   return repl;
112 }
113
114 void
115 bput_utf8_slow(struct fastbuf *b, uns u)
116 {
117   ASSERT(u < 65536);
118   if (u < 0x80)
119     bputc(b, u);
120   else
121     {
122       if (u < 0x800)
123         bputc(b, 0xc0 | (u >> 6));
124       else
125         {
126           bputc(b, 0xe0 | (u >> 12));
127           bputc(b, 0x80 | ((u >> 6) & 0x3f));
128         }
129       bputc(b, 0x80 | (u & 0x3f));
130     }
131 }
132
133 void
134 bput_utf8_32_slow(struct fastbuf *b, uns u)
135 {
136   ASSERT(u < (1U<<31));
137   if (u < 0x80)
138     bputc(b, u);
139   else
140     {
141       if (u < 0x800)
142         bputc(b, 0xc0 | (u >> 6));
143       else
144         {
145           if (u < (1<<16))
146             bputc(b, 0xe0 | (u >> 12));
147           else
148             {
149               if (u < (1<<21))
150                 bputc(b, 0xf0 | (u >> 18));
151               else
152                 {
153                   if (u < (1<<26))
154                     bputc(b, 0xf8 | (u >> 24));
155                   else
156                     {
157                       bputc(b, 0xfc | (u >> 30));
158                       bputc(b, 0x80 | ((u >> 24) & 0x3f));
159                     }
160                   bputc(b, 0x80 | ((u >> 18) & 0x3f));
161                 }
162               bputc(b, 0x80 | ((u >> 12) & 0x3f));
163             }
164           bputc(b, 0x80 | ((u >> 6) & 0x3f));
165         }
166       bputc(b, 0x80 | (u & 0x3f));
167     }
168 }
169
170 int
171 bget_utf16_be_slow(struct fastbuf *b, uns repl)
172 {
173   if (bpeekc(b) < 0)
174     return -1;
175   uns u = bgetw_be(b), x, y;
176   if ((int)u < 0)
177     return repl;
178   if ((x = u - 0xd800) >= 0x800)
179     return u;
180   if (x >= 0x400 || bpeekc(b) < 0 || (y = bgetw_be(b) - 0xdc00) >= 0x400)
181     return repl;
182   return 0x10000 + (x << 10) + y;
183 }
184
185 int
186 bget_utf16_le_slow(struct fastbuf *b, uns repl)
187 {
188   if (bpeekc(b) < 0)
189     return -1;
190   uns u = bgetw_le(b), x, y;
191   if ((int)u < 0)
192     return repl;
193   if ((x = u - 0xd800) >= 0x800)
194     return u;
195   if (x >= 0x400 || bpeekc(b) < 0 || (y = bgetw_le(b) - 0xdc00) >= 0x400)
196     return repl;
197   return 0x10000 + (x << 10) + y;
198 }