YAZ 5.38.1
utf8.c
Go to the documentation of this file.
1/* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
4 */
9
10#if HAVE_CONFIG_H
11#include <config.h>
12#endif
13
14#include <assert.h>
15#include <errno.h>
16#include <string.h>
17
18#include "iconv-p.h"
19
21 unsigned char *inp,
22 size_t inbytesleft, size_t *no_read)
23{
24 if (!inp || inp[0] != 0xef)
25 {
26 *no_read = 0;
27 return 0;
28 }
29 if (inbytesleft < 3)
30 {
32 return (size_t) -1;
33 }
34 if (inp[1] != 0xbb && inp[2] == 0xbf)
35 *no_read = 3;
36 else
37 *no_read = 0;
38 return 0;
39}
40
41unsigned long yaz_read_UTF8_char(const unsigned char *inp,
42 size_t inbytesleft, size_t *no_read,
43 int *error)
44{
45 unsigned long x = 0;
46
47 *no_read = 0; /* by default */
48 if (!inbytesleft)
49 {
50 *error = YAZ_ICONV_EINVAL;
51 }
52 else if (inp[0] <= 0x7f)
53 {
54 x = inp[0];
55 *no_read = 1;
56 }
57 else if (inp[0] < 0xc2 || inp[0] > 0xf4)
58 {
59 *error = YAZ_ICONV_EILSEQ;
60 }
61 else if (inp[0] <= 0xdf && inbytesleft >= 2)
62 {
63 if ((inp[1] & 0xc0) == 0x80)
64 {
65 x = ((inp[0] & 0x1f) << 6) | (inp[1] & 0x3f);
66 *no_read = 2;
67 }
68 else
69 *error = YAZ_ICONV_EILSEQ;
70 }
71 else if (inp[0] <= 0xef && inbytesleft >= 3)
72 {
73 if ((inp[1] & 0xc0) == 0x80 && (inp[2] & 0xc0) == 0x80)
74 {
75 x = ((inp[0] & 0x0f) << 12) | ((inp[1] & 0x3f) << 6) |
76 (inp[2] & 0x3f);
77 if (x >= 0x800 && (x < 0xd800 || x > 0xdfff))
78 *no_read = 3;
79 else
80 *error = YAZ_ICONV_EILSEQ;
81 }
82 else
83 *error = YAZ_ICONV_EILSEQ;
84 }
85 else if (inp[0] <= 0xf4 && inbytesleft >= 4)
86 {
87 if ((inp[1] & 0xc0) == 0x80 && (inp[2] & 0xc0) == 0x80
88 && (inp[3] & 0xc0) == 0x80)
89 {
90 x = ((inp[0] & 0x07) << 18) | ((inp[1] & 0x3f) << 12) |
91 ((inp[2] & 0x3f) << 6) | (inp[3] & 0x3f);
92 if (x >= 0x10000 && x <= 0x10ffff)
93 *no_read = 4;
94 else
95 *error = YAZ_ICONV_EILSEQ;
96 }
97 else
98 *error = YAZ_ICONV_EILSEQ;
99 }
100 else
101 *error = YAZ_ICONV_EINVAL; /* incomplete sentence */
102
103 return x;
104}
105
106static unsigned long read_utf8(yaz_iconv_t cd, yaz_iconv_decoder_t d,
107 unsigned char *inp,
108 size_t inbytesleft, size_t *no_read)
109{
110 int err = 0;
111 int r = yaz_read_UTF8_char(inp, inbytesleft, no_read, &err);
112 yaz_iconv_set_errno(cd, err);
113 return r;
114}
115
116
118 unsigned long x,
119 char **outbuf, size_t *outbytesleft)
120{
121 int err = 0;
122 int r = yaz_write_UTF8_char(x, outbuf, outbytesleft, &err);
123 yaz_iconv_set_errno(cd, err);
124 return r;
125}
126
127size_t yaz_write_UTF8_char(unsigned long x,
128 char **outbuf, size_t *outbytesleft,
129 int *error)
130{
131 unsigned char *outp = (unsigned char *) *outbuf;
132
133 if ((x >= 0xd800 && x <= 0xdfff) || x > 0x10ffff)
134 {
135 *error = YAZ_ICONV_EILSEQ;
136 return (size_t)(-1);
137 }
138 if (x <= 0x7f && *outbytesleft >= 1)
139 {
140 *outp++ = (unsigned char) x;
141 (*outbytesleft)--;
142 }
143 else if (x <= 0x7ff && *outbytesleft >= 2)
144 {
145 *outp++ = (unsigned char) ((x >> 6) | 0xc0);
146 *outp++ = (unsigned char) ((x & 0x3f) | 0x80);
147 (*outbytesleft) -= 2;
148 }
149 else if (x <= 0xffff && *outbytesleft >= 3)
150 {
151 *outp++ = (unsigned char) ((x >> 12) | 0xe0);
152 *outp++ = (unsigned char) (((x >> 6) & 0x3f) | 0x80);
153 *outp++ = (unsigned char) ((x & 0x3f) | 0x80);
154 (*outbytesleft) -= 3;
155 }
156 else if (x <= 0x10ffff && *outbytesleft >= 4)
157 {
158 *outp++ = (unsigned char) ((x >> 18) | 0xf0);
159 *outp++ = (unsigned char) (((x >> 12) & 0x3f) | 0x80);
160 *outp++ = (unsigned char) (((x >> 6) & 0x3f) | 0x80);
161 *outp++ = (unsigned char) ((x & 0x3f) | 0x80);
162 (*outbytesleft) -= 4;
163 }
164 else
165 {
166 *error = YAZ_ICONV_E2BIG; /* not room for output */
167 return (size_t)(-1);
168 }
169 *outbuf = (char *) outp;
170 return 0;
171}
172
175
176{
177 if (!yaz_matchstr(tocode, "UTF8"))
178 {
180 return e;
181 }
182 return 0;
183}
184
187{
188 if (!yaz_matchstr(fromcode, "UTF8"))
189 {
192 return d;
193 }
194 return 0;
195}
196
197int yaz_utf8_check(const char *str)
198{
199 /* cast OK: yaz_read_UTF8_char is read-only */
200 unsigned char *inp = (unsigned char *) str;
201 size_t inbytesleft = strlen(str);
202
203 while (inbytesleft)
204 {
205 int error = 0;
206 size_t no_read;
207 yaz_read_UTF8_char(inp, inbytesleft, &no_read, &error);
208 if (error)
209 return 0;
210 inp += no_read;
211 inbytesleft -= no_read;
212 }
213 return 1;
214}
215
216/*
217 * Local variables:
218 * c-basic-offset: 4
219 * c-file-style: "Stroustrup"
220 * indent-tabs-mode: nil
221 * End:
222 * vim: shiftwidth=4 tabstop=8 expandtab
223 */
Header for errno utilities.
Internal header for iconv.
struct yaz_iconv_decoder_s * yaz_iconv_decoder_t
Definition iconv-p.h:80
struct yaz_iconv_encoder_s * yaz_iconv_encoder_t
Definition iconv-p.h:42
yaz_iconv_encoder_t yaz_utf8_encoder(const char *name, yaz_iconv_encoder_t e)
Definition utf8.c:173
yaz_iconv_decoder_t yaz_utf8_decoder(const char *fromcode, yaz_iconv_decoder_t d)
Definition utf8.c:185
void yaz_iconv_set_errno(yaz_iconv_t cd, int no)
Definition siconv.c:298
int yaz_matchstr(const char *s1, const char *s2)
match strings - independent of case and '-'
Definition matchstr.c:42
unsigned long(*) read_handle(yaz_iconv_t cd, yaz_iconv_decoder_t d, unsigned char *inbuf, size_t inbytesleft, size_t *no_read)
Definition iconv-p.h:86
size_t(*) init_handle(yaz_iconv_t cd, yaz_iconv_decoder_t d, unsigned char *inbuf, size_t inbytesleft, size_t *no_read)
Definition iconv-p.h:83
size_t(*) write_handle(yaz_iconv_t cd, yaz_iconv_encoder_t e, unsigned long x, char **outbuf, size_t *outbytesleft)
Definition iconv-p.h:45
static size_t write_UTF8(yaz_iconv_t cd, yaz_iconv_encoder_t en, unsigned long x, char **outbuf, size_t *outbytesleft)
Definition utf8.c:117
static unsigned long read_utf8(yaz_iconv_t cd, yaz_iconv_decoder_t d, unsigned char *inp, size_t inbytesleft, size_t *no_read)
Definition utf8.c:106
size_t yaz_write_UTF8_char(unsigned long x, char **outbuf, size_t *outbytesleft, int *error)
encodes UTF-8 sequence
Definition utf8.c:127
int yaz_utf8_check(const char *str)
check whether string apppers to be UTF-8 encoded
Definition utf8.c:197
static size_t init_utf8(yaz_iconv_t cd, yaz_iconv_decoder_t d, unsigned char *inp, size_t inbytesleft, size_t *no_read)
Definition utf8.c:20
unsigned long yaz_read_UTF8_char(const unsigned char *inp, size_t inbytesleft, size_t *no_read, int *error)
Definition utf8.c:41
#define YAZ_ICONV_EILSEQ
error code: Invalid sequence
Definition yaz-iconv.h:49
#define YAZ_ICONV_E2BIG
error code: Not sufficient room for output buffer
Definition yaz-iconv.h:47
#define YAZ_ICONV_EINVAL
error code: An incomplete multibyte sequence is in input buffer
Definition yaz-iconv.h:51
struct yaz_iconv_struct * yaz_iconv_t
yaz_iconv handle (similar to iconv_t)
Definition yaz-iconv.h:42