qr_reader-native 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE-mruby.txt +22 -0
- data/LICENSE-spinel.txt +19 -0
- data/LICENSE.txt +21 -0
- data/README.md +61 -0
- data/ext/qr_reader_native/SPINEL_VERSION +1 -0
- data/ext/qr_reader_native/extconf.rb +8 -0
- data/ext/qr_reader_native/mruby/error.h +13 -0
- data/ext/qr_reader_native/mruby/internal.h +145 -0
- data/ext/qr_reader_native/mruby/string.h +22 -0
- data/ext/qr_reader_native/mruby.h +93 -0
- data/ext/qr_reader_native/mruby_shim.h +118 -0
- data/ext/qr_reader_native/qr_reader_native.c +13513 -0
- data/ext/qr_reader_native/qr_reader_native.h +29 -0
- data/ext/qr_reader_native/qr_reader_native_ext.c +598 -0
- data/ext/qr_reader_native/re_cased.h +71 -0
- data/ext/qr_reader_native/re_compile.c +5784 -0
- data/ext/qr_reader_native/re_ctype.h +3540 -0
- data/ext/qr_reader_native/re_exec.c +2190 -0
- data/ext/qr_reader_native/re_internal.h +671 -0
- data/ext/qr_reader_native/re_prop.h +4629 -0
- data/ext/qr_reader_native/re_spinel.c +363 -0
- data/ext/qr_reader_native/re_spinel.h +22 -0
- data/ext/qr_reader_native/re_spinel_utf8.inc +97 -0
- data/ext/qr_reader_native/re_utf8.c +156 -0
- data/ext/qr_reader_native/sp_alloc.c +1447 -0
- data/ext/qr_reader_native/sp_alloc.h +1196 -0
- data/ext/qr_reader_native/sp_argf.h +33 -0
- data/ext/qr_reader_native/sp_array.c +1052 -0
- data/ext/qr_reader_native/sp_array.h +456 -0
- data/ext/qr_reader_native/sp_bigint.c +5826 -0
- data/ext/qr_reader_native/sp_bigint.h +117 -0
- data/ext/qr_reader_native/sp_cold.c +5259 -0
- data/ext/qr_reader_native/sp_compat.h +402 -0
- data/ext/qr_reader_native/sp_core.c +818 -0
- data/ext/qr_reader_native/sp_core.h +56 -0
- data/ext/qr_reader_native/sp_crypto.c +877 -0
- data/ext/qr_reader_native/sp_crypto.h +169 -0
- data/ext/qr_reader_native/sp_dtoa.c +1533 -0
- data/ext/qr_reader_native/sp_dtoa.h +29 -0
- data/ext/qr_reader_native/sp_encoding_names.h +172 -0
- data/ext/qr_reader_native/sp_enum.h +86 -0
- data/ext/qr_reader_native/sp_exc.c +1185 -0
- data/ext/qr_reader_native/sp_exc.h +186 -0
- data/ext/qr_reader_native/sp_exc_ctx.h +56 -0
- data/ext/qr_reader_native/sp_fiber.c +889 -0
- data/ext/qr_reader_native/sp_fiber.h +162 -0
- data/ext/qr_reader_native/sp_fiber_ctx.h +84 -0
- data/ext/qr_reader_native/sp_format.c +695 -0
- data/ext/qr_reader_native/sp_format.h +83 -0
- data/ext/qr_reader_native/sp_gc.c +1793 -0
- data/ext/qr_reader_native/sp_gc.h +762 -0
- data/ext/qr_reader_native/sp_hash.c +131 -0
- data/ext/qr_reader_native/sp_hash.h +131 -0
- data/ext/qr_reader_native/sp_inspect.c +215 -0
- data/ext/qr_reader_native/sp_inspect.h +128 -0
- data/ext/qr_reader_native/sp_io.c +1676 -0
- data/ext/qr_reader_native/sp_io.h +272 -0
- data/ext/qr_reader_native/sp_iobuffer.c +1014 -0
- data/ext/qr_reader_native/sp_iobuffer.h +167 -0
- data/ext/qr_reader_native/sp_marshal.c +487 -0
- data/ext/qr_reader_native/sp_marshal.h +60 -0
- data/ext/qr_reader_native/sp_net.c +1029 -0
- data/ext/qr_reader_native/sp_net.h +205 -0
- data/ext/qr_reader_native/sp_pack.c +1254 -0
- data/ext/qr_reader_native/sp_poly_cold.c +1220 -0
- data/ext/qr_reader_native/sp_proc.c +410 -0
- data/ext/qr_reader_native/sp_proc.h +327 -0
- data/ext/qr_reader_native/sp_process.c +547 -0
- data/ext/qr_reader_native/sp_process_status.c +211 -0
- data/ext/qr_reader_native/sp_process_status.h +66 -0
- data/ext/qr_reader_native/sp_random.c +287 -0
- data/ext/qr_reader_native/sp_random.h +52 -0
- data/ext/qr_reader_native/sp_range.h +144 -0
- data/ext/qr_reader_native/sp_re.c +1379 -0
- data/ext/qr_reader_native/sp_re.h +186 -0
- data/ext/qr_reader_native/sp_re_names.h +59 -0
- data/ext/qr_reader_native/sp_sched.c +4044 -0
- data/ext/qr_reader_native/sp_sched.h +295 -0
- data/ext/qr_reader_native/sp_slab.c +1507 -0
- data/ext/qr_reader_native/sp_str.c +1462 -0
- data/ext/qr_reader_native/sp_str.h +306 -0
- data/ext/qr_reader_native/sp_str_crypt.c +23 -0
- data/ext/qr_reader_native/sp_string.c +92 -0
- data/ext/qr_reader_native/sp_string.h +253 -0
- data/ext/qr_reader_native/sp_system.c +78 -0
- data/ext/qr_reader_native/sp_system.h +18 -0
- data/ext/qr_reader_native/sp_time.c +860 -0
- data/ext/qr_reader_native/sp_time.h +100 -0
- data/ext/qr_reader_native/sp_types.h +292 -0
- data/ext/qr_reader_native/spinel_rt.h +19017 -0
- data/ext/qr_reader_native/unicase.c +399 -0
- data/ext/qr_reader_native/unicase.h +901 -0
- data/lib/qr_reader/native.rb +6 -0
- metadata +153 -0
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
/*
|
|
2
|
+
** unicase.c - what case a Unicode character has
|
|
3
|
+
**
|
|
4
|
+
** The tables in unicase.h and the lookups over them. What a string does with
|
|
5
|
+
** the answers is string.c's business, and what a pattern does with them is
|
|
6
|
+
** mruby-regexp's; this file knows only about codepoints.
|
|
7
|
+
**
|
|
8
|
+
** See Copyright Notice in mruby.h
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
#include <string.h>
|
|
12
|
+
#include <mruby.h>
|
|
13
|
+
|
|
14
|
+
#if defined(MRB_UTF8_STRING) && !defined(MRB_USE_ASCII_CTYPE)
|
|
15
|
+
|
|
16
|
+
#include <mruby/internal.h>
|
|
17
|
+
#include "unicase.h"
|
|
18
|
+
|
|
19
|
+
mrb_static_assert(UNI_CASE_MAX_BYTES <= MRB_UNI_CASE_MAX_BYTES,
|
|
20
|
+
"a mapping outgrew the buffer its callers hand over");
|
|
21
|
+
|
|
22
|
+
static const struct case_table {
|
|
23
|
+
const uint8_t *runs;
|
|
24
|
+
size_t run_count;
|
|
25
|
+
const uint8_t *multi;
|
|
26
|
+
size_t multi_count;
|
|
27
|
+
uint32_t min, max;
|
|
28
|
+
} case_tables[] = {
|
|
29
|
+
{UNI_LOWER_RUNS, UNI_LOWER_RUN_COUNT, UNI_LOWER_MULTI, UNI_LOWER_MULTI_COUNT,
|
|
30
|
+
UNI_LOWER_MIN, UNI_LOWER_MAX},
|
|
31
|
+
{UNI_UPPER_RUNS, UNI_UPPER_RUN_COUNT, UNI_UPPER_MULTI, UNI_UPPER_MULTI_COUNT,
|
|
32
|
+
UNI_UPPER_MIN, UNI_UPPER_MAX},
|
|
33
|
+
{UNI_TITLE_RUNS, UNI_TITLE_RUN_COUNT, UNI_TITLE_MULTI, UNI_TITLE_MULTI_COUNT,
|
|
34
|
+
UNI_TITLE_MIN, UNI_TITLE_MAX},
|
|
35
|
+
{UNI_SWAP_RUNS, UNI_SWAP_RUN_COUNT, UNI_SWAP_MULTI, UNI_SWAP_MULTI_COUNT,
|
|
36
|
+
UNI_SWAP_MIN, UNI_SWAP_MAX},
|
|
37
|
+
{UNI_FOLD_RUNS, UNI_FOLD_RUN_COUNT, UNI_FOLD_MULTI, UNI_FOLD_MULTI_COUNT,
|
|
38
|
+
UNI_FOLD_MIN, UNI_FOLD_MAX},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/* The `n` bytes at `p`, least significant first, which is how unicase.h packs
|
|
42
|
+
both of its entry kinds. */
|
|
43
|
+
static uint64_t
|
|
44
|
+
case_bits(const uint8_t *p, int n)
|
|
45
|
+
{
|
|
46
|
+
uint64_t v = 0;
|
|
47
|
+
for (int i = 0; i < n; i++) v |= (uint64_t)p[i] << (8 * i);
|
|
48
|
+
return v;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
typedef struct case_run {
|
|
52
|
+
uint32_t start, count, stride;
|
|
53
|
+
int32_t delta;
|
|
54
|
+
} case_run;
|
|
55
|
+
|
|
56
|
+
static void
|
|
57
|
+
case_run_at(const uint8_t *runs, size_t i, case_run *r)
|
|
58
|
+
{
|
|
59
|
+
uint64_t v = case_bits(runs + i * UNI_CASE_RUN_BYTES, UNI_CASE_RUN_BYTES);
|
|
60
|
+
r->start = (uint32_t)(v & 0x1FFFFF);
|
|
61
|
+
r->count = (uint32_t)((v >> 21) & 0x7F);
|
|
62
|
+
r->stride = (uint32_t)((v >> 28) & 1) + 1;
|
|
63
|
+
r->delta = (int32_t)((v >> 29) & 0x1FFFF) - UNI_CASE_DELTA_BIAS;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* Locate the run holding cp. Runs are emitted in ascending source order and
|
|
67
|
+
never overlap, so a binary search on start is enough; a run with stride 2
|
|
68
|
+
covers only every other codepoint in its span, which the modulo check
|
|
69
|
+
rejects. */
|
|
70
|
+
static mrb_bool
|
|
71
|
+
case_run_for(const struct case_table *t, uint32_t cp, case_run *out)
|
|
72
|
+
{
|
|
73
|
+
size_t lo = 0, hi = t->run_count;
|
|
74
|
+
while (lo < hi) {
|
|
75
|
+
size_t mid = lo + (hi - lo) / 2;
|
|
76
|
+
case_run r;
|
|
77
|
+
case_run_at(t->runs, mid, &r);
|
|
78
|
+
uint32_t last = r.start + (r.count - 1) * r.stride;
|
|
79
|
+
if (cp < r.start) hi = mid;
|
|
80
|
+
else if (cp > last) lo = mid + 1;
|
|
81
|
+
else {
|
|
82
|
+
if ((cp - r.start) % r.stride != 0) return FALSE;
|
|
83
|
+
*out = r;
|
|
84
|
+
return TRUE;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return FALSE;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
static mrb_bool
|
|
91
|
+
case_multi_for(const struct case_table *t, uint32_t cp, uint32_t *off, uint32_t *len)
|
|
92
|
+
{
|
|
93
|
+
size_t lo = 0, hi = t->multi_count;
|
|
94
|
+
while (lo < hi) {
|
|
95
|
+
size_t mid = lo + (hi - lo) / 2;
|
|
96
|
+
uint64_t v = case_bits(t->multi + mid * UNI_CASE_MULTI_BYTES, UNI_CASE_MULTI_BYTES);
|
|
97
|
+
uint32_t mcp = (uint32_t)(v & 0x1FFFFF);
|
|
98
|
+
if (cp < mcp) hi = mid;
|
|
99
|
+
else if (cp > mcp) lo = mid + 1;
|
|
100
|
+
else {
|
|
101
|
+
*off = (uint32_t)((v >> 21) & 0xFFF);
|
|
102
|
+
*len = (uint32_t)((v >> 33) & 7);
|
|
103
|
+
return TRUE;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return FALSE;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* Ask one table about cp, writing what it says into buf. Answers the byte
|
|
110
|
+
count written, 0 for a character the table maps to itself, and -1 for one
|
|
111
|
+
the table says nothing about. The two apart is what lets title case hand a
|
|
112
|
+
character it says nothing about on to upper case while keeping the ones it
|
|
113
|
+
deliberately maps to themselves. */
|
|
114
|
+
static mrb_int
|
|
115
|
+
case_map_one(enum mrb_case_kind kind, uint32_t cp, char *buf)
|
|
116
|
+
{
|
|
117
|
+
const struct case_table *t = &case_tables[kind];
|
|
118
|
+
if (cp < t->min || t->max < cp) return -1;
|
|
119
|
+
|
|
120
|
+
uint32_t off, len;
|
|
121
|
+
if (case_multi_for(t, cp, &off, &len)) {
|
|
122
|
+
memcpy(buf, uni_case_pool + off, len);
|
|
123
|
+
return (mrb_int)len;
|
|
124
|
+
}
|
|
125
|
+
case_run r;
|
|
126
|
+
if (!case_run_for(t, cp, &r)) return -1;
|
|
127
|
+
if (r.delta == 0) return 0;
|
|
128
|
+
return mrb_utf8_to_buf(buf, (mrb_int)cp + r.delta);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
mrb_int
|
|
132
|
+
mrb_uni_case_map(enum mrb_case_kind kind, uint32_t cp, char *buf)
|
|
133
|
+
{
|
|
134
|
+
mrb_int n = case_map_one(kind, cp, buf);
|
|
135
|
+
if (n >= 0) return n;
|
|
136
|
+
|
|
137
|
+
switch (kind) {
|
|
138
|
+
case MRB_CASE_KIND_TITLE:
|
|
139
|
+
/* Title case is the difference from upper case, so a character the
|
|
140
|
+
difference says nothing about takes the upper case answer. */
|
|
141
|
+
n = case_map_one(MRB_CASE_KIND_UPPER, cp, buf);
|
|
142
|
+
break;
|
|
143
|
+
case MRB_CASE_KIND_SWAP:
|
|
144
|
+
/* Swapping is the difference from this rule: a character with a lower
|
|
145
|
+
case is an upper case one and swaps down, and one without swaps up. */
|
|
146
|
+
n = case_map_one(MRB_CASE_KIND_LOWER, cp, buf);
|
|
147
|
+
if (n < 0) n = case_map_one(MRB_CASE_KIND_UPPER, cp, buf);
|
|
148
|
+
break;
|
|
149
|
+
case MRB_CASE_KIND_FOLD:
|
|
150
|
+
/* Folding is the difference from the lowercase mapping, so a character
|
|
151
|
+
the difference says nothing about folds the way it lower cases. */
|
|
152
|
+
n = case_map_one(MRB_CASE_KIND_LOWER, cp, buf);
|
|
153
|
+
break;
|
|
154
|
+
default:
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
return n < 0 ? 0 : n;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
#ifdef HAVE_MRUBY_REGEXP_GEM
|
|
161
|
+
|
|
162
|
+
/* ------------------------------------------------------------- folding
|
|
163
|
+
|
|
164
|
+
Simple case folding is what a pattern asks for under /i, and it is the two
|
|
165
|
+
run tables read in order: the folding difference first, and the lowercase
|
|
166
|
+
mapping under it for the sources the difference passes over. A source whose
|
|
167
|
+
folding spells several characters (U+FB00 to "ff") is in a multi table and
|
|
168
|
+
in neither set of runs, which is exactly the set simple folding leaves
|
|
169
|
+
alone.
|
|
170
|
+
|
|
171
|
+
/i is the whole of what asks, so the gem that has one says it is here and
|
|
172
|
+
the rest of this file goes with it. Nothing else would drop it: the mapping
|
|
173
|
+
above is in the same object, every build calls that, and the linker takes
|
|
174
|
+
an object whole. */
|
|
175
|
+
|
|
176
|
+
/* Whether the folding difference holds a run over any of [lo, hi]. A caller
|
|
177
|
+
walking the lowercase runs asks this to know whether the difference has
|
|
178
|
+
something to say about the span it is about to report whole. Runs ascend
|
|
179
|
+
and never overlap, so their ends ascend too: the first run whose end
|
|
180
|
+
reaches lo is the only one that can start before hi, and the search below
|
|
181
|
+
keeps its start, since the last run it steps h down to is that one. */
|
|
182
|
+
static mrb_bool
|
|
183
|
+
fold_diff_touches(uint32_t lo, uint32_t hi)
|
|
184
|
+
{
|
|
185
|
+
const struct case_table *t = &case_tables[MRB_CASE_KIND_FOLD];
|
|
186
|
+
size_t l = 0, h = t->run_count;
|
|
187
|
+
uint32_t start = UINT32_MAX; /* past any hi, so no run found means FALSE */
|
|
188
|
+
while (l < h) {
|
|
189
|
+
size_t mid = l + (h - l) / 2;
|
|
190
|
+
case_run r;
|
|
191
|
+
case_run_at(t->runs, mid, &r);
|
|
192
|
+
if (r.start + (r.count - 1) * r.stride < lo) l = mid + 1;
|
|
193
|
+
else {
|
|
194
|
+
h = mid;
|
|
195
|
+
start = r.start;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return start <= hi;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
uint32_t
|
|
202
|
+
mrb_uni_case_fold(uint32_t cp)
|
|
203
|
+
{
|
|
204
|
+
/* ASCII is out of the tables, being what the tables are the rest of. */
|
|
205
|
+
if (cp < 128) return (cp >= 'A' && cp <= 'Z') ? cp + 32 : cp;
|
|
206
|
+
|
|
207
|
+
case_run r;
|
|
208
|
+
const struct case_table *f = &case_tables[MRB_CASE_KIND_FOLD];
|
|
209
|
+
if (f->min <= cp && cp <= f->max && case_run_for(f, cp, &r)) {
|
|
210
|
+
/* A run of delta 0 here is the difference saying the source folds to
|
|
211
|
+
itself where it lower cases to something, which is an answer. */
|
|
212
|
+
return (uint32_t)((int32_t)cp + r.delta);
|
|
213
|
+
}
|
|
214
|
+
const struct case_table *l = &case_tables[MRB_CASE_KIND_LOWER];
|
|
215
|
+
if (l->min <= cp && cp <= l->max && case_run_for(l, cp, &r)) {
|
|
216
|
+
return (uint32_t)((int32_t)cp + r.delta);
|
|
217
|
+
}
|
|
218
|
+
return cp;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/* Every source in `t` whose folded form is `folded`, checked back through
|
|
222
|
+
mrb_uni_case_fold() so that a source the difference overrides is not
|
|
223
|
+
reported from the mapping under it. */
|
|
224
|
+
static int
|
|
225
|
+
unfold_from(const struct case_table *t, uint32_t cp, uint32_t folded,
|
|
226
|
+
uint32_t *out, int max, int n)
|
|
227
|
+
{
|
|
228
|
+
for (size_t i = 0; i < t->run_count && n < max; i++) {
|
|
229
|
+
case_run r;
|
|
230
|
+
case_run_at(t->runs, i, &r);
|
|
231
|
+
int32_t s = (int32_t)folded - r.delta;
|
|
232
|
+
if (s < (int32_t)r.start) continue;
|
|
233
|
+
uint32_t off = (uint32_t)s - r.start;
|
|
234
|
+
if (off % r.stride) continue;
|
|
235
|
+
if (off / r.stride >= r.count) continue;
|
|
236
|
+
if ((uint32_t)s == cp) continue;
|
|
237
|
+
if (mrb_uni_case_fold((uint32_t)s) != folded) continue;
|
|
238
|
+
for (int k = 0; k < n; k++) if (out[k] == (uint32_t)s) goto next;
|
|
239
|
+
out[n++] = (uint32_t)s;
|
|
240
|
+
next:
|
|
241
|
+
;
|
|
242
|
+
}
|
|
243
|
+
return n;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
int
|
|
247
|
+
mrb_uni_case_unfold(uint32_t cp, uint32_t *out, int max)
|
|
248
|
+
{
|
|
249
|
+
int n = 0;
|
|
250
|
+
uint32_t folded = mrb_uni_case_fold(cp);
|
|
251
|
+
|
|
252
|
+
/* The folded form is itself a member of the class. */
|
|
253
|
+
if (folded != cp && n < max) out[n++] = folded;
|
|
254
|
+
|
|
255
|
+
/* ASCII sources are in no table, so the upper case letter that folds into a
|
|
256
|
+
lower case one is added here. */
|
|
257
|
+
if (folded >= 'a' && folded <= 'z' && folded - 32 != cp && n < max) {
|
|
258
|
+
out[n++] = folded - 32;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/* A non-ASCII source folding into ASCII (U+017F into 's') is the only thing
|
|
262
|
+
an ASCII source can find in a table, and the generator lists those beside
|
|
263
|
+
the tables, so the list is the whole answer for one. What that saves is
|
|
264
|
+
the two full scans below, which an ASCII source would otherwise make to
|
|
265
|
+
collect the entries the list already holds. Most patterns are ASCII and
|
|
266
|
+
nothing else, and this is what /i costs them. */
|
|
267
|
+
if (cp < 128) {
|
|
268
|
+
#define X(src, to) if (folded == (to) && n < max) out[n++] = (src);
|
|
269
|
+
UNI_FOLD_TO_ASCII
|
|
270
|
+
#undef X
|
|
271
|
+
return n;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
n = unfold_from(&case_tables[MRB_CASE_KIND_FOLD], cp, folded, out, max, n);
|
|
275
|
+
n = unfold_from(&case_tables[MRB_CASE_KIND_LOWER], cp, folded, out, max, n);
|
|
276
|
+
return n;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/* Both range walks read the tables run by run, which keeps a wide range cheap:
|
|
280
|
+
a run of stride 1 contributes one span whatever its length. A run the
|
|
281
|
+
folding difference has something to say about is reported one codepoint at a
|
|
282
|
+
time instead, since the difference may override any part of it. */
|
|
283
|
+
static void
|
|
284
|
+
fold_span(uint32_t lo, uint32_t hi, void (*add)(void *, uint32_t, uint32_t), void *user)
|
|
285
|
+
{
|
|
286
|
+
for (uint32_t cp = lo; cp <= hi; cp++) {
|
|
287
|
+
uint32_t f = mrb_uni_case_fold(cp);
|
|
288
|
+
if (f != cp) add(user, f, f);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
static void
|
|
293
|
+
fold_range_of(const struct case_table *t, mrb_bool guard, uint32_t lo, uint32_t hi,
|
|
294
|
+
void (*add)(void *, uint32_t, uint32_t), void *user)
|
|
295
|
+
{
|
|
296
|
+
for (size_t i = 0; i < t->run_count; i++) {
|
|
297
|
+
case_run r;
|
|
298
|
+
case_run_at(t->runs, i, &r);
|
|
299
|
+
uint32_t span = (r.count - 1) * r.stride;
|
|
300
|
+
|
|
301
|
+
uint32_t s_lo = r.start > lo ? r.start : lo;
|
|
302
|
+
uint32_t s_hi = r.start + span < hi ? r.start + span : hi;
|
|
303
|
+
if (s_lo > s_hi) continue;
|
|
304
|
+
/* Round s_lo up and s_hi down to codepoints the run actually holds. */
|
|
305
|
+
uint32_t off = s_lo - r.start;
|
|
306
|
+
if (off % r.stride) s_lo += r.stride - (off % r.stride);
|
|
307
|
+
s_hi -= (s_hi - r.start) % r.stride;
|
|
308
|
+
if (s_lo > s_hi) continue;
|
|
309
|
+
|
|
310
|
+
if (guard && fold_diff_touches(s_lo, s_hi)) {
|
|
311
|
+
fold_span(s_lo, s_hi, add, user);
|
|
312
|
+
}
|
|
313
|
+
else if (r.stride == 1) {
|
|
314
|
+
if (r.delta != 0) {
|
|
315
|
+
add(user, (uint32_t)((int32_t)s_lo + r.delta), (uint32_t)((int32_t)s_hi + r.delta));
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
for (uint32_t cp = s_lo; cp <= s_hi; cp += r.stride) {
|
|
320
|
+
if (r.delta == 0) continue;
|
|
321
|
+
uint32_t f = (uint32_t)((int32_t)cp + r.delta);
|
|
322
|
+
add(user, f, f);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
void
|
|
329
|
+
mrb_uni_case_fold_range(uint32_t lo, uint32_t hi,
|
|
330
|
+
void (*add)(void *, uint32_t, uint32_t), void *user)
|
|
331
|
+
{
|
|
332
|
+
fold_range_of(&case_tables[MRB_CASE_KIND_FOLD], FALSE, lo, hi, add, user);
|
|
333
|
+
fold_range_of(&case_tables[MRB_CASE_KIND_LOWER], TRUE, lo, hi, add, user);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/* The sources of the folds landing in [lo, hi]. A source found through the
|
|
337
|
+
lowercase mapping is checked back through mrb_uni_case_fold(), since the
|
|
338
|
+
difference may fold it elsewhere or leave it alone. */
|
|
339
|
+
static void
|
|
340
|
+
unfold_range_of(const struct case_table *t, mrb_bool guard, uint32_t lo, uint32_t hi,
|
|
341
|
+
void (*add)(void *, uint32_t, uint32_t), void *user)
|
|
342
|
+
{
|
|
343
|
+
for (size_t i = 0; i < t->run_count; i++) {
|
|
344
|
+
case_run r;
|
|
345
|
+
case_run_at(t->runs, i, &r);
|
|
346
|
+
uint32_t span = (r.count - 1) * r.stride;
|
|
347
|
+
|
|
348
|
+
int32_t f_start = (int32_t)r.start + r.delta;
|
|
349
|
+
if (f_start < 0) continue;
|
|
350
|
+
int32_t f_end = f_start + (int32_t)span;
|
|
351
|
+
uint32_t f_lo = (uint32_t)f_start > lo ? (uint32_t)f_start : lo;
|
|
352
|
+
uint32_t f_hi = (uint32_t)f_end < hi ? (uint32_t)f_end : hi;
|
|
353
|
+
if (f_lo > f_hi) continue;
|
|
354
|
+
uint32_t off = f_lo - (uint32_t)f_start;
|
|
355
|
+
if (off % r.stride) f_lo += r.stride - (off % r.stride);
|
|
356
|
+
f_hi -= (f_hi - (uint32_t)f_start) % r.stride;
|
|
357
|
+
if (f_lo > f_hi) continue;
|
|
358
|
+
|
|
359
|
+
uint32_t s_lo = (uint32_t)((int32_t)f_lo - r.delta);
|
|
360
|
+
uint32_t s_hi = (uint32_t)((int32_t)f_hi - r.delta);
|
|
361
|
+
if (guard && fold_diff_touches(s_lo, s_hi)) {
|
|
362
|
+
for (uint32_t cp = s_lo; cp <= s_hi; cp += r.stride) {
|
|
363
|
+
uint32_t f = mrb_uni_case_fold(cp);
|
|
364
|
+
if (f != cp && lo <= f && f <= hi) add(user, cp, cp);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
else if (r.stride == 1) {
|
|
368
|
+
if (r.delta != 0) add(user, s_lo, s_hi);
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
for (uint32_t cp = s_lo; cp <= s_hi; cp += r.stride) {
|
|
372
|
+
if (r.delta != 0) add(user, cp, cp);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
void
|
|
379
|
+
mrb_uni_case_unfold_range(uint32_t lo, uint32_t hi,
|
|
380
|
+
void (*add)(void *, uint32_t, uint32_t), void *user)
|
|
381
|
+
{
|
|
382
|
+
/* An ASCII fold has the listed sources and no others, for the reason
|
|
383
|
+
mrb_uni_case_unfold() gives, so the ASCII part of the span is answered
|
|
384
|
+
from the list and the walks below are handed what is left of it. A class
|
|
385
|
+
of nothing but ASCII, which is most classes, reaches neither walk. */
|
|
386
|
+
if (lo < 128) {
|
|
387
|
+
#define X(src, to) if (lo <= (to) && (to) <= hi) add(user, (src), (src));
|
|
388
|
+
UNI_FOLD_TO_ASCII
|
|
389
|
+
#undef X
|
|
390
|
+
if (hi < 128) return;
|
|
391
|
+
lo = 128;
|
|
392
|
+
}
|
|
393
|
+
unfold_range_of(&case_tables[MRB_CASE_KIND_FOLD], FALSE, lo, hi, add, user);
|
|
394
|
+
unfold_range_of(&case_tables[MRB_CASE_KIND_LOWER], TRUE, lo, hi, add, user);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
#endif /* HAVE_MRUBY_REGEXP_GEM */
|
|
398
|
+
|
|
399
|
+
#endif /* MRB_UTF8_STRING && !MRB_USE_ASCII_CTYPE */
|