Blame


1 5e11c00c 2021-03-02 op /* Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
2 5e11c00c 2021-03-02 op *
3 5e11c00c 2021-03-02 op * Permission is hereby granted, free of charge, to any person
4 5e11c00c 2021-03-02 op * obtaining a copy of this software and associated documentation
5 5e11c00c 2021-03-02 op * files (the "Software"), to deal in the Software without
6 5e11c00c 2021-03-02 op * restriction, including without limitation the rights to use, copy,
7 5e11c00c 2021-03-02 op * modify, merge, publish, distribute, sublicense, and/or sell copies
8 5e11c00c 2021-03-02 op * of the Software, and to permit persons to whom the Software is
9 5e11c00c 2021-03-02 op * furnished to do so, subject to the following conditions:
10 5e11c00c 2021-03-02 op *
11 5e11c00c 2021-03-02 op * The above copyright notice and this permission notice shall be
12 5e11c00c 2021-03-02 op * included in all copies or substantial portions of the Software.
13 5e11c00c 2021-03-02 op *
14 5e11c00c 2021-03-02 op * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 5e11c00c 2021-03-02 op * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 5e11c00c 2021-03-02 op * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 5e11c00c 2021-03-02 op * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
18 5e11c00c 2021-03-02 op * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 5e11c00c 2021-03-02 op * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 5e11c00c 2021-03-02 op * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 5e11c00c 2021-03-02 op * SOFTWARE.
22 5e11c00c 2021-03-02 op */
23 5e11c00c 2021-03-02 op
24 5e11c00c 2021-03-02 op #include "gmid.h"
25 5e11c00c 2021-03-02 op
26 5e11c00c 2021-03-02 op #include <stddef.h>
27 5e11c00c 2021-03-02 op #include <stdint.h>
28 5e11c00c 2021-03-02 op
29 5e11c00c 2021-03-02 op #define UTF8_ACCEPT 0
30 5e11c00c 2021-03-02 op #define UTF8_REJECT 1
31 5e11c00c 2021-03-02 op
32 5e11c00c 2021-03-02 op static const uint8_t utf8d[] = {
33 5e11c00c 2021-03-02 op 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f
34 5e11c00c 2021-03-02 op 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f
35 5e11c00c 2021-03-02 op 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f
36 5e11c00c 2021-03-02 op 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f
37 5e11c00c 2021-03-02 op 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f
38 5e11c00c 2021-03-02 op 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf
39 5e11c00c 2021-03-02 op 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df
40 5e11c00c 2021-03-02 op 0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef
41 5e11c00c 2021-03-02 op 0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff
42 5e11c00c 2021-03-02 op 0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0
43 5e11c00c 2021-03-02 op 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2
44 5e11c00c 2021-03-02 op 1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4
45 5e11c00c 2021-03-02 op 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6
46 5e11c00c 2021-03-02 op 1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8
47 5e11c00c 2021-03-02 op };
48 5e11c00c 2021-03-02 op
49 5e11c00c 2021-03-02 op static inline uint32_t
50 5e11c00c 2021-03-02 op utf8_decode(uint32_t* state, uint32_t* codep, uint8_t byte) {
51 5e11c00c 2021-03-02 op uint32_t type = utf8d[byte];
52 5e11c00c 2021-03-02 op
53 5e11c00c 2021-03-02 op *codep = (*state != UTF8_ACCEPT) ?
54 5e11c00c 2021-03-02 op (byte & 0x3fu) | (*codep << 6) :
55 5e11c00c 2021-03-02 op (0xff >> type) & (byte);
56 5e11c00c 2021-03-02 op
57 5e11c00c 2021-03-02 op *state = utf8d[256 + *state*16 + type];
58 5e11c00c 2021-03-02 op return *state;
59 5e11c00c 2021-03-02 op }
60 5e11c00c 2021-03-02 op
61 5e11c00c 2021-03-02 op /* for the iri parser. Modelled after printCodePoints */
62 5e11c00c 2021-03-02 op int
63 5e11c00c 2021-03-02 op valid_multibyte_utf8(struct parser *p)
64 5e11c00c 2021-03-02 op {
65 5e11c00c 2021-03-02 op uint32_t cp = 0, state = 0;
66 5e11c00c 2021-03-02 op
67 5e11c00c 2021-03-02 op for (; *p->iri; p->iri++)
68 5e11c00c 2021-03-02 op if (!utf8_decode(&state, &cp, *p->iri))
69 5e11c00c 2021-03-02 op break;
70 5e11c00c 2021-03-02 op
71 5e11c00c 2021-03-02 op /* reject the ASCII range */
72 5e11c00c 2021-03-02 op if (state || cp <= 0x7F) {
73 5e11c00c 2021-03-02 op /* XXX: do some error recovery? */
74 5e11c00c 2021-03-02 op if (state)
75 5e11c00c 2021-03-02 op p->err = "invalid UTF-8 character";
76 5e11c00c 2021-03-02 op return 0;
77 5e11c00c 2021-03-02 op }
78 5e11c00c 2021-03-02 op return 1;
79 5e11c00c 2021-03-02 op }
80 5e11c00c 2021-03-02 op
81 5e11c00c 2021-03-02 op char *
82 5e11c00c 2021-03-02 op utf8_nth(char *s, size_t n)
83 5e11c00c 2021-03-02 op {
84 5e11c00c 2021-03-02 op size_t i;
85 5e11c00c 2021-03-02 op uint32_t cp = 0, state = 0;
86 5e11c00c 2021-03-02 op
87 5e11c00c 2021-03-02 op for (i = 0; *s && i < n; ++s)
88 5e11c00c 2021-03-02 op if (!utf8_decode(&state, &cp, *s))
89 5e11c00c 2021-03-02 op ++i;
90 5e11c00c 2021-03-02 op
91 5e11c00c 2021-03-02 op if (state != UTF8_ACCEPT)
92 5e11c00c 2021-03-02 op return NULL;
93 5e11c00c 2021-03-02 op if (i == n)
94 5e11c00c 2021-03-02 op return s;
95 5e11c00c 2021-03-02 op return NULL;
96 5e11c00c 2021-03-02 op }