@mikrojs/quickjs 0.18.1 → 0.18.2
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.
- package/deps/quickjs/api-test.c +234 -0
- package/deps/quickjs/libregexp.c +18 -1
- package/deps/quickjs/libunicode-table.h +71 -84
- package/deps/quickjs/quickjs-libc.c +2 -2
- package/deps/quickjs/quickjs.c +103 -76
- package/deps/quickjs/quickjs.h +1 -1
- package/deps/quickjs/run-test262.c +22 -4
- package/deps/quickjs/unicode_gen.c +498 -2
- package/deps/quickjs/unicode_gen_def.h +16 -0
- package/package.json +1 -1
|
@@ -151,6 +151,120 @@ char *get_line(char *buf, int buf_size, FILE *f)
|
|
|
151
151
|
return buf;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
/* hashed set of code point sequences, used to collect the RGI emoji ZWJ
|
|
155
|
+
sequences */
|
|
156
|
+
typedef struct REString {
|
|
157
|
+
struct REString *next;
|
|
158
|
+
uint32_t hash;
|
|
159
|
+
uint32_t len;
|
|
160
|
+
uint32_t flags;
|
|
161
|
+
uint32_t buf[];
|
|
162
|
+
} REString;
|
|
163
|
+
|
|
164
|
+
typedef struct {
|
|
165
|
+
uint32_t n_strings;
|
|
166
|
+
uint32_t hash_size;
|
|
167
|
+
int hash_bits;
|
|
168
|
+
REString **hash_table;
|
|
169
|
+
} REStringList;
|
|
170
|
+
|
|
171
|
+
static uint32_t re_string_hash(int len, const uint32_t *buf)
|
|
172
|
+
{
|
|
173
|
+
int i;
|
|
174
|
+
uint32_t h;
|
|
175
|
+
h = 1;
|
|
176
|
+
for(i = 0; i < len; i++)
|
|
177
|
+
h = h * 263 + buf[i];
|
|
178
|
+
return h * 0x61C88647;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
static void re_string_list_init(REStringList *s)
|
|
182
|
+
{
|
|
183
|
+
s->n_strings = 0;
|
|
184
|
+
s->hash_size = 0;
|
|
185
|
+
s->hash_bits = 0;
|
|
186
|
+
s->hash_table = NULL;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
static void re_string_list_free(REStringList *s)
|
|
190
|
+
{
|
|
191
|
+
REString *p, *p_next;
|
|
192
|
+
uint32_t i;
|
|
193
|
+
for(i = 0; i < s->hash_size; i++) {
|
|
194
|
+
for(p = s->hash_table[i]; p != NULL; p = p_next) {
|
|
195
|
+
p_next = p->next;
|
|
196
|
+
free(p);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
free(s->hash_table);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
static REString *re_string_find2(REStringList *s, int len, const uint32_t *buf,
|
|
203
|
+
uint32_t h0, bool add_flag)
|
|
204
|
+
{
|
|
205
|
+
uint32_t h = 0; /* avoid warning */
|
|
206
|
+
REString *p;
|
|
207
|
+
if (s->n_strings != 0) {
|
|
208
|
+
h = h0 >> (32 - s->hash_bits);
|
|
209
|
+
for(p = s->hash_table[h]; p != NULL; p = p->next) {
|
|
210
|
+
if (p->hash == h0 && p->len == (uint32_t)len &&
|
|
211
|
+
!memcmp(p->buf, buf, len * sizeof(buf[0]))) {
|
|
212
|
+
return p;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/* not found */
|
|
217
|
+
if (!add_flag)
|
|
218
|
+
return NULL;
|
|
219
|
+
/* increase the size of the hash table if needed */
|
|
220
|
+
if ((s->n_strings + 1) > s->hash_size) {
|
|
221
|
+
REString **new_hash_table, *p_next;
|
|
222
|
+
int new_hash_bits;
|
|
223
|
+
uint32_t new_hash_size, i;
|
|
224
|
+
new_hash_bits = max_int(s->hash_bits + 1, 4);
|
|
225
|
+
new_hash_size = 1 << new_hash_bits;
|
|
226
|
+
new_hash_table = mallocz(sizeof(new_hash_table[0]) * new_hash_size);
|
|
227
|
+
for(i = 0; i < s->hash_size; i++) {
|
|
228
|
+
for(p = s->hash_table[i]; p != NULL; p = p_next) {
|
|
229
|
+
p_next = p->next;
|
|
230
|
+
h = p->hash >> (32 - new_hash_bits);
|
|
231
|
+
p->next = new_hash_table[h];
|
|
232
|
+
new_hash_table[h] = p;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
free(s->hash_table);
|
|
236
|
+
s->hash_bits = new_hash_bits;
|
|
237
|
+
s->hash_size = new_hash_size;
|
|
238
|
+
s->hash_table = new_hash_table;
|
|
239
|
+
h = h0 >> (32 - s->hash_bits);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
p = malloc(sizeof(REString) + len * sizeof(buf[0]));
|
|
243
|
+
if (!p) {
|
|
244
|
+
fprintf(stderr, "memory allocation error\n");
|
|
245
|
+
exit(1);
|
|
246
|
+
}
|
|
247
|
+
p->next = s->hash_table[h];
|
|
248
|
+
s->hash_table[h] = p;
|
|
249
|
+
s->n_strings++;
|
|
250
|
+
p->hash = h0;
|
|
251
|
+
p->len = len;
|
|
252
|
+
p->flags = 0;
|
|
253
|
+
memcpy(p->buf, buf, sizeof(buf[0]) * len);
|
|
254
|
+
return p;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
static REString *re_string_find(REStringList *s, int len, const uint32_t *buf,
|
|
258
|
+
bool add_flag)
|
|
259
|
+
{
|
|
260
|
+
return re_string_find2(s, len, buf, re_string_hash(len, buf), add_flag);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
static void re_string_add(REStringList *s, int len, const uint32_t *buf)
|
|
264
|
+
{
|
|
265
|
+
re_string_find(s, len, buf, true);
|
|
266
|
+
}
|
|
267
|
+
|
|
154
268
|
#define UNICODE_GENERAL_CATEGORY
|
|
155
269
|
|
|
156
270
|
typedef enum {
|
|
@@ -220,6 +334,23 @@ static const char *unicode_prop_short_name[] = {
|
|
|
220
334
|
|
|
221
335
|
#undef UNICODE_PROP_LIST
|
|
222
336
|
|
|
337
|
+
#define UNICODE_SEQUENCE_PROP_LIST
|
|
338
|
+
|
|
339
|
+
typedef enum {
|
|
340
|
+
#define DEF(id) SEQUENCE_PROP_ ## id,
|
|
341
|
+
#include "unicode_gen_def.h"
|
|
342
|
+
#undef DEF
|
|
343
|
+
SEQUENCE_PROP_COUNT,
|
|
344
|
+
} UnicodeSequencePropEnum1;
|
|
345
|
+
|
|
346
|
+
static const char *unicode_sequence_prop_name[] = {
|
|
347
|
+
#define DEF(id) #id,
|
|
348
|
+
#include "unicode_gen_def.h"
|
|
349
|
+
#undef DEF
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
#undef UNICODE_SEQUENCE_PROP_LIST
|
|
353
|
+
|
|
223
354
|
typedef struct {
|
|
224
355
|
/* case conv */
|
|
225
356
|
uint8_t u_len;
|
|
@@ -243,6 +374,8 @@ typedef struct {
|
|
|
243
374
|
} CCInfo;
|
|
244
375
|
|
|
245
376
|
CCInfo *unicode_db;
|
|
377
|
+
REStringList rgi_emoji_zwj_sequence;
|
|
378
|
+
DynBuf rgi_emoji_tag_sequence;
|
|
246
379
|
|
|
247
380
|
int find_name(const char **tab, int tab_len, const char *name)
|
|
248
381
|
{
|
|
@@ -733,6 +866,152 @@ void parse_prop_list(const char *filename)
|
|
|
733
866
|
fclose(f);
|
|
734
867
|
}
|
|
735
868
|
|
|
869
|
+
#define SEQ_MAX_LEN 16
|
|
870
|
+
|
|
871
|
+
static bool is_emoji_modifier(uint32_t c)
|
|
872
|
+
{
|
|
873
|
+
return (c >= 0x1f3fb && c <= 0x1f3ff);
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
/* the sequence properties are stored either as a code point property
|
|
877
|
+
(when the sequence can be derived from its first code point) or in a
|
|
878
|
+
dedicated table */
|
|
879
|
+
static void add_sequence_prop(int idx, int seq_len, int *seq)
|
|
880
|
+
{
|
|
881
|
+
int i;
|
|
882
|
+
|
|
883
|
+
assert(idx < SEQUENCE_PROP_COUNT);
|
|
884
|
+
switch(idx) {
|
|
885
|
+
case SEQUENCE_PROP_Basic_Emoji:
|
|
886
|
+
/* convert to 2 properties lists */
|
|
887
|
+
if (seq_len == 1) {
|
|
888
|
+
set_prop(seq[0], PROP_Basic_Emoji1, 1);
|
|
889
|
+
} else if (seq_len == 2 && seq[1] == 0xfe0f) {
|
|
890
|
+
set_prop(seq[0], PROP_Basic_Emoji2, 1);
|
|
891
|
+
} else {
|
|
892
|
+
abort();
|
|
893
|
+
}
|
|
894
|
+
break;
|
|
895
|
+
case SEQUENCE_PROP_RGI_Emoji_Modifier_Sequence:
|
|
896
|
+
/* no table needed: the sequences are Emoji_Modifier_Base followed
|
|
897
|
+
by one of the 5 emoji modifiers */
|
|
898
|
+
assert(seq_len == 2);
|
|
899
|
+
assert(is_emoji_modifier(seq[1]));
|
|
900
|
+
assert(get_prop(seq[0], PROP_Emoji_Modifier_Base));
|
|
901
|
+
break;
|
|
902
|
+
case SEQUENCE_PROP_RGI_Emoji_Flag_Sequence:
|
|
903
|
+
{
|
|
904
|
+
int code;
|
|
905
|
+
assert(seq_len == 2);
|
|
906
|
+
assert(seq[0] >= 0x1F1E6 && seq[0] <= 0x1F1FF);
|
|
907
|
+
assert(seq[1] >= 0x1F1E6 && seq[1] <= 0x1F1FF);
|
|
908
|
+
code = (seq[0] - 0x1F1E6) * 26 + (seq[1] - 0x1F1E6);
|
|
909
|
+
/* XXX: would be more compact with a simple bitmap -> 676 bits */
|
|
910
|
+
set_prop(code, PROP_RGI_Emoji_Flag_Sequence, 1);
|
|
911
|
+
}
|
|
912
|
+
break;
|
|
913
|
+
case SEQUENCE_PROP_RGI_Emoji_ZWJ_Sequence:
|
|
914
|
+
re_string_add(&rgi_emoji_zwj_sequence, seq_len, (uint32_t *)seq);
|
|
915
|
+
break;
|
|
916
|
+
case SEQUENCE_PROP_RGI_Emoji_Tag_Sequence:
|
|
917
|
+
{
|
|
918
|
+
assert(seq_len >= 3);
|
|
919
|
+
assert(seq[0] == 0x1F3F4);
|
|
920
|
+
assert(seq[seq_len - 1] == 0xE007F);
|
|
921
|
+
for(i = 1; i < seq_len - 1; i++) {
|
|
922
|
+
assert(seq[i] >= 0xe0001 && seq[i] <= 0xe007e);
|
|
923
|
+
dbuf_putc(&rgi_emoji_tag_sequence, seq[i] - 0xe0000);
|
|
924
|
+
}
|
|
925
|
+
dbuf_putc(&rgi_emoji_tag_sequence, 0);
|
|
926
|
+
}
|
|
927
|
+
break;
|
|
928
|
+
case SEQUENCE_PROP_Emoji_Keycap_Sequence:
|
|
929
|
+
assert(seq_len == 3);
|
|
930
|
+
assert(seq[1] == 0xfe0f);
|
|
931
|
+
assert(seq[2] == 0x20e3);
|
|
932
|
+
set_prop(seq[0], PROP_Emoji_Keycap_Sequence, 1);
|
|
933
|
+
break;
|
|
934
|
+
default:
|
|
935
|
+
assert(0);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
/* parse emoji-sequences.txt and emoji-zwj-sequences.txt */
|
|
940
|
+
void parse_sequence_prop_list(const char *filename)
|
|
941
|
+
{
|
|
942
|
+
FILE *f;
|
|
943
|
+
char line[4096], *p, buf[256], *q, *p_start;
|
|
944
|
+
uint32_t c0, c1, c;
|
|
945
|
+
int idx, seq_len;
|
|
946
|
+
int seq[SEQ_MAX_LEN];
|
|
947
|
+
|
|
948
|
+
f = fopen(filename, "rb");
|
|
949
|
+
if (!f) {
|
|
950
|
+
perror(filename);
|
|
951
|
+
exit(1);
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
for(;;) {
|
|
955
|
+
if (!get_line(line, sizeof(line), f))
|
|
956
|
+
break;
|
|
957
|
+
p = line;
|
|
958
|
+
while (isspace(*p))
|
|
959
|
+
p++;
|
|
960
|
+
if (*p == '#' || *p == '@' || *p == '\0')
|
|
961
|
+
continue;
|
|
962
|
+
p_start = p;
|
|
963
|
+
|
|
964
|
+
/* find the sequence property name */
|
|
965
|
+
p = strchr(p, ';');
|
|
966
|
+
if (!p)
|
|
967
|
+
continue;
|
|
968
|
+
p++;
|
|
969
|
+
p += strspn(p, " \t");
|
|
970
|
+
q = buf;
|
|
971
|
+
while (*p != '\0' && *p != ' ' && *p != '#' && *p != '\t' && *p != ';') {
|
|
972
|
+
if ((size_t)(q - buf) < sizeof(buf) - 1)
|
|
973
|
+
*q++ = *p;
|
|
974
|
+
p++;
|
|
975
|
+
}
|
|
976
|
+
*q = '\0';
|
|
977
|
+
idx = find_name(unicode_sequence_prop_name,
|
|
978
|
+
countof(unicode_sequence_prop_name), buf);
|
|
979
|
+
if (idx < 0) {
|
|
980
|
+
fprintf(stderr, "Property not found: %s\n", buf);
|
|
981
|
+
exit(1);
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
p = p_start;
|
|
985
|
+
c0 = strtoul(p, (char **)&p, 16);
|
|
986
|
+
assert(c0 <= CHARCODE_MAX);
|
|
987
|
+
|
|
988
|
+
if (*p == '.' && p[1] == '.') {
|
|
989
|
+
p += 2;
|
|
990
|
+
c1 = strtoul(p, (char **)&p, 16);
|
|
991
|
+
assert(c1 <= CHARCODE_MAX);
|
|
992
|
+
for(c = c0; c <= c1; c++) {
|
|
993
|
+
seq[0] = c;
|
|
994
|
+
add_sequence_prop(idx, 1, seq);
|
|
995
|
+
}
|
|
996
|
+
} else {
|
|
997
|
+
seq_len = 0;
|
|
998
|
+
seq[seq_len++] = c0;
|
|
999
|
+
for(;;) {
|
|
1000
|
+
while (isspace(*p))
|
|
1001
|
+
p++;
|
|
1002
|
+
if (*p == ';' || *p == '\0')
|
|
1003
|
+
break;
|
|
1004
|
+
c0 = strtoul(p, (char **)&p, 16);
|
|
1005
|
+
assert(c0 <= CHARCODE_MAX);
|
|
1006
|
+
assert(seq_len < countof(seq));
|
|
1007
|
+
seq[seq_len++] = c0;
|
|
1008
|
+
}
|
|
1009
|
+
add_sequence_prop(idx, seq_len, seq);
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
fclose(f);
|
|
1013
|
+
}
|
|
1014
|
+
|
|
736
1015
|
void parse_scripts(const char *filename)
|
|
737
1016
|
{
|
|
738
1017
|
FILE *f;
|
|
@@ -1585,7 +1864,7 @@ void dump_name_table(FILE *f, const char *cname, const char **tab_name, int len,
|
|
|
1585
1864
|
maxw = 0;
|
|
1586
1865
|
for(i = 0; i < len; i++) {
|
|
1587
1866
|
w = strlen(tab_name[i]);
|
|
1588
|
-
if (tab_short_name[i][0] != '\0') {
|
|
1867
|
+
if (tab_short_name && tab_short_name[i][0] != '\0') {
|
|
1589
1868
|
w += 1 + strlen(tab_short_name[i]);
|
|
1590
1869
|
}
|
|
1591
1870
|
if (maxw < w)
|
|
@@ -1597,7 +1876,7 @@ void dump_name_table(FILE *f, const char *cname, const char **tab_name, int len,
|
|
|
1597
1876
|
for(i = 0; i < len; i++) {
|
|
1598
1877
|
fprintf(f, " \"");
|
|
1599
1878
|
w = fprintf(f, "%s", tab_name[i]);
|
|
1600
|
-
if (tab_short_name[i][0] != '\0') {
|
|
1879
|
+
if (tab_short_name && tab_short_name[i][0] != '\0') {
|
|
1601
1880
|
w += fprintf(f, ",%s", tab_short_name[i]);
|
|
1602
1881
|
}
|
|
1603
1882
|
fprintf(f, "\"%*s\"\\0\"\n", 1 + maxw - w, "");
|
|
@@ -1846,6 +2125,209 @@ void build_prop_list_table(FILE *f)
|
|
|
1846
2125
|
fprintf(f, "};\n\n");
|
|
1847
2126
|
}
|
|
1848
2127
|
|
|
2128
|
+
static bool is_emoji_hair_color(uint32_t c)
|
|
2129
|
+
{
|
|
2130
|
+
return (c >= 0x1F9B0 && c <= 0x1F9B3);
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
#define EMOJI_MOD_NONE 0
|
|
2134
|
+
#define EMOJI_MOD_TYPE1 1
|
|
2135
|
+
#define EMOJI_MOD_TYPE2 2
|
|
2136
|
+
#define EMOJI_MOD_TYPE2D 3
|
|
2137
|
+
|
|
2138
|
+
/* Test whether all the variants of 'buf' obtained by substituting the emoji
|
|
2139
|
+
modifiers at 'mod_pos' and the hair color at 'hc_pos' are present in 'sl'.
|
|
2140
|
+
If 'mark_flag' is true, they are marked as already handled. 'buf' is
|
|
2141
|
+
modified. */
|
|
2142
|
+
static bool mark_zwj_string(REStringList *sl, uint32_t *buf, int len,
|
|
2143
|
+
int mod_type, int *mod_pos, int hc_pos,
|
|
2144
|
+
bool mark_flag)
|
|
2145
|
+
{
|
|
2146
|
+
REString *p;
|
|
2147
|
+
int i, n_mod, i0, i1, hc_count, j;
|
|
2148
|
+
|
|
2149
|
+
switch(mod_type) {
|
|
2150
|
+
case EMOJI_MOD_NONE:
|
|
2151
|
+
n_mod = 1;
|
|
2152
|
+
break;
|
|
2153
|
+
case EMOJI_MOD_TYPE1:
|
|
2154
|
+
n_mod = 5;
|
|
2155
|
+
break;
|
|
2156
|
+
case EMOJI_MOD_TYPE2:
|
|
2157
|
+
n_mod = 25;
|
|
2158
|
+
break;
|
|
2159
|
+
case EMOJI_MOD_TYPE2D:
|
|
2160
|
+
n_mod = 20;
|
|
2161
|
+
break;
|
|
2162
|
+
default:
|
|
2163
|
+
abort();
|
|
2164
|
+
}
|
|
2165
|
+
if (hc_pos >= 0)
|
|
2166
|
+
hc_count = 4;
|
|
2167
|
+
else
|
|
2168
|
+
hc_count = 1;
|
|
2169
|
+
/* check that all the related strings are present */
|
|
2170
|
+
for(j = 0; j < hc_count; j++) {
|
|
2171
|
+
for(i = 0; i < n_mod; i++) {
|
|
2172
|
+
switch(mod_type) {
|
|
2173
|
+
case EMOJI_MOD_NONE:
|
|
2174
|
+
break;
|
|
2175
|
+
case EMOJI_MOD_TYPE1:
|
|
2176
|
+
buf[mod_pos[0]] = 0x1f3fb + i;
|
|
2177
|
+
break;
|
|
2178
|
+
case EMOJI_MOD_TYPE2:
|
|
2179
|
+
case EMOJI_MOD_TYPE2D:
|
|
2180
|
+
i0 = i / 5;
|
|
2181
|
+
i1 = i % 5;
|
|
2182
|
+
/* avoid identical values */
|
|
2183
|
+
if (mod_type == EMOJI_MOD_TYPE2D && i0 >= i1)
|
|
2184
|
+
i0++;
|
|
2185
|
+
buf[mod_pos[0]] = 0x1f3fb + i0;
|
|
2186
|
+
buf[mod_pos[1]] = 0x1f3fb + i1;
|
|
2187
|
+
break;
|
|
2188
|
+
default:
|
|
2189
|
+
abort();
|
|
2190
|
+
}
|
|
2191
|
+
|
|
2192
|
+
if (hc_pos >= 0)
|
|
2193
|
+
buf[hc_pos] = 0x1F9B0 + j;
|
|
2194
|
+
|
|
2195
|
+
p = re_string_find(sl, len, buf, false);
|
|
2196
|
+
if (!p)
|
|
2197
|
+
return false;
|
|
2198
|
+
if (mark_flag)
|
|
2199
|
+
p->flags |= 1;
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
return true;
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
/* encode a ZWJ sequence as a length followed by 16 bit code points. The
|
|
2206
|
+
ZWJ separators, the presentation selectors and the emoji modifiers are
|
|
2207
|
+
encoded in the code points, see unicode_sequence_prop1() in
|
|
2208
|
+
libunicode.c */
|
|
2209
|
+
static void zwj_encode_string(DynBuf *dbuf, const uint32_t *buf, int len,
|
|
2210
|
+
int mod_type)
|
|
2211
|
+
{
|
|
2212
|
+
int i, j;
|
|
2213
|
+
int c, code;
|
|
2214
|
+
uint32_t buf1[SEQ_MAX_LEN];
|
|
2215
|
+
|
|
2216
|
+
j = 0;
|
|
2217
|
+
for(i = 0; i < len;) {
|
|
2218
|
+
c = buf[i++];
|
|
2219
|
+
if (c >= 0x2000 && c <= 0x2fff) {
|
|
2220
|
+
code = c - 0x2000;
|
|
2221
|
+
} else if (c >= 0x1f000 && c <= 0x1ffff) {
|
|
2222
|
+
code = c - 0x1f000 + 0x1000;
|
|
2223
|
+
} else {
|
|
2224
|
+
abort();
|
|
2225
|
+
}
|
|
2226
|
+
if (i < len && is_emoji_modifier(buf[i])) {
|
|
2227
|
+
/* modifier */
|
|
2228
|
+
code |= (mod_type << 13);
|
|
2229
|
+
i++;
|
|
2230
|
+
}
|
|
2231
|
+
if (i < len && buf[i] == 0xfe0f) {
|
|
2232
|
+
/* presentation selector present */
|
|
2233
|
+
code |= 0x8000;
|
|
2234
|
+
i++;
|
|
2235
|
+
}
|
|
2236
|
+
if (i < len) {
|
|
2237
|
+
/* zero width joiner */
|
|
2238
|
+
assert(buf[i] == 0x200d);
|
|
2239
|
+
i++;
|
|
2240
|
+
}
|
|
2241
|
+
buf1[j++] = code;
|
|
2242
|
+
}
|
|
2243
|
+
dbuf_putc(dbuf, j);
|
|
2244
|
+
for(i = 0; i < j; i++) {
|
|
2245
|
+
dbuf_putc(dbuf, buf1[i]);
|
|
2246
|
+
dbuf_putc(dbuf, buf1[i] >> 8);
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
static void build_rgi_emoji_zwj_sequence(FILE *f, REStringList *sl)
|
|
2251
|
+
{
|
|
2252
|
+
int mod_pos[2], mod_count, hair_color_pos;
|
|
2253
|
+
uint32_t buf[SEQ_MAX_LEN], h, j;
|
|
2254
|
+
REString *p;
|
|
2255
|
+
DynBuf dbuf;
|
|
2256
|
+
|
|
2257
|
+
dbuf_init(&dbuf);
|
|
2258
|
+
|
|
2259
|
+
/* avoid duplicating strings with emoji modifiers or hair colors */
|
|
2260
|
+
for(h = 0; h < sl->hash_size; h++) {
|
|
2261
|
+
for(p = sl->hash_table[h]; p != NULL; p = p->next) {
|
|
2262
|
+
if (p->flags) /* already examined */
|
|
2263
|
+
continue;
|
|
2264
|
+
mod_count = 0;
|
|
2265
|
+
hair_color_pos = -1;
|
|
2266
|
+
for(j = 0; j < p->len; j++) {
|
|
2267
|
+
if (is_emoji_modifier(p->buf[j])) {
|
|
2268
|
+
assert(mod_count < 2);
|
|
2269
|
+
mod_pos[mod_count++] = j;
|
|
2270
|
+
} else if (is_emoji_hair_color(p->buf[j])) {
|
|
2271
|
+
hair_color_pos = j;
|
|
2272
|
+
}
|
|
2273
|
+
buf[j] = p->buf[j];
|
|
2274
|
+
}
|
|
2275
|
+
|
|
2276
|
+
if (mod_count != 0 || hair_color_pos >= 0) {
|
|
2277
|
+
int mod_type;
|
|
2278
|
+
if (mod_count == 0)
|
|
2279
|
+
mod_type = EMOJI_MOD_NONE;
|
|
2280
|
+
else if (mod_count == 1)
|
|
2281
|
+
mod_type = EMOJI_MOD_TYPE1;
|
|
2282
|
+
else
|
|
2283
|
+
mod_type = EMOJI_MOD_TYPE2;
|
|
2284
|
+
|
|
2285
|
+
if (mark_zwj_string(sl, buf, p->len, mod_type, mod_pos, hair_color_pos, false)) {
|
|
2286
|
+
mark_zwj_string(sl, buf, p->len, mod_type, mod_pos, hair_color_pos, true);
|
|
2287
|
+
} else if (mod_type == EMOJI_MOD_TYPE2) {
|
|
2288
|
+
mod_type = EMOJI_MOD_TYPE2D;
|
|
2289
|
+
if (mark_zwj_string(sl, buf, p->len, mod_type, mod_pos, hair_color_pos, false)) {
|
|
2290
|
+
mark_zwj_string(sl, buf, p->len, mod_type, mod_pos, hair_color_pos, true);
|
|
2291
|
+
} else {
|
|
2292
|
+
dump_str("not_found", (int *)p->buf, p->len);
|
|
2293
|
+
goto keep;
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
if (hair_color_pos >= 0)
|
|
2297
|
+
buf[hair_color_pos] = 0x1f9b0;
|
|
2298
|
+
/* encode the string */
|
|
2299
|
+
zwj_encode_string(&dbuf, buf, p->len, mod_type);
|
|
2300
|
+
} else {
|
|
2301
|
+
keep:
|
|
2302
|
+
zwj_encode_string(&dbuf, buf, p->len, EMOJI_MOD_NONE);
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
dump_byte_table(f, "unicode_rgi_emoji_zwj_sequence", dbuf.buf, dbuf.size);
|
|
2308
|
+
|
|
2309
|
+
dbuf_free(&dbuf);
|
|
2310
|
+
}
|
|
2311
|
+
|
|
2312
|
+
void build_sequence_prop_list_table(FILE *f)
|
|
2313
|
+
{
|
|
2314
|
+
int i;
|
|
2315
|
+
|
|
2316
|
+
fprintf(f, "typedef enum {\n");
|
|
2317
|
+
for(i = 0; i < SEQUENCE_PROP_COUNT; i++)
|
|
2318
|
+
fprintf(f, " UNICODE_SEQUENCE_PROP_%s,\n", unicode_sequence_prop_name[i]);
|
|
2319
|
+
fprintf(f, " UNICODE_SEQUENCE_PROP_COUNT,\n");
|
|
2320
|
+
fprintf(f, "} UnicodeSequencePropertyEnum;\n\n");
|
|
2321
|
+
|
|
2322
|
+
dump_name_table(f, "unicode_sequence_prop_name_table",
|
|
2323
|
+
unicode_sequence_prop_name, SEQUENCE_PROP_COUNT, NULL);
|
|
2324
|
+
|
|
2325
|
+
dump_byte_table(f, "unicode_rgi_emoji_tag_sequence",
|
|
2326
|
+
rgi_emoji_tag_sequence.buf, rgi_emoji_tag_sequence.size);
|
|
2327
|
+
|
|
2328
|
+
build_rgi_emoji_zwj_sequence(f, &rgi_emoji_zwj_sequence);
|
|
2329
|
+
}
|
|
2330
|
+
|
|
1849
2331
|
#ifdef USE_TEST
|
|
1850
2332
|
int check_conv(uint32_t *res, uint32_t c, int conv_type)
|
|
1851
2333
|
{
|
|
@@ -3025,6 +3507,8 @@ int main(int argc, char **argv)
|
|
|
3025
3507
|
outfilename = argv[2];
|
|
3026
3508
|
|
|
3027
3509
|
unicode_db = mallocz(sizeof(unicode_db[0]) * (CHARCODE_MAX + 1));
|
|
3510
|
+
re_string_list_init(&rgi_emoji_zwj_sequence);
|
|
3511
|
+
dbuf_init(&rgi_emoji_tag_sequence);
|
|
3028
3512
|
|
|
3029
3513
|
snprintf(filename, sizeof(filename), "%s/UnicodeData.txt", unicode_db_path);
|
|
3030
3514
|
|
|
@@ -3059,6 +3543,14 @@ int main(int argc, char **argv)
|
|
|
3059
3543
|
unicode_db_path);
|
|
3060
3544
|
parse_prop_list(filename);
|
|
3061
3545
|
|
|
3546
|
+
snprintf(filename, sizeof(filename), "%s/emoji-sequences.txt",
|
|
3547
|
+
unicode_db_path);
|
|
3548
|
+
parse_sequence_prop_list(filename);
|
|
3549
|
+
|
|
3550
|
+
snprintf(filename, sizeof(filename), "%s/emoji-zwj-sequences.txt",
|
|
3551
|
+
unicode_db_path);
|
|
3552
|
+
parse_sequence_prop_list(filename);
|
|
3553
|
+
|
|
3062
3554
|
// dump_unicode_data(unicode_db);
|
|
3063
3555
|
build_conv_table(unicode_db);
|
|
3064
3556
|
|
|
@@ -3115,7 +3607,11 @@ int main(int argc, char **argv)
|
|
|
3115
3607
|
build_script_table(fo);
|
|
3116
3608
|
build_script_ext_table(fo);
|
|
3117
3609
|
build_prop_list_table(fo);
|
|
3610
|
+
build_sequence_prop_list_table(fo);
|
|
3118
3611
|
fclose(fo);
|
|
3119
3612
|
}
|
|
3613
|
+
|
|
3614
|
+
re_string_list_free(&rgi_emoji_zwj_sequence);
|
|
3615
|
+
dbuf_free(&rgi_emoji_tag_sequence);
|
|
3120
3616
|
return 0;
|
|
3121
3617
|
}
|
|
@@ -239,6 +239,11 @@ DEF(XID_Continue1, "")
|
|
|
239
239
|
DEF(Changes_When_Titlecased1, "")
|
|
240
240
|
DEF(Changes_When_Casefolded1, "")
|
|
241
241
|
DEF(Changes_When_NFKC_Casefolded1, "")
|
|
242
|
+
/* RGI emoji sequence support (see UNICODE_SEQUENCE_PROP_LIST below) */
|
|
243
|
+
DEF(Basic_Emoji1, "")
|
|
244
|
+
DEF(Basic_Emoji2, "")
|
|
245
|
+
DEF(RGI_Emoji_Flag_Sequence, "")
|
|
246
|
+
DEF(Emoji_Keycap_Sequence, "")
|
|
242
247
|
|
|
243
248
|
/* Prop list exported to JS */
|
|
244
249
|
DEF(ASCII_Hex_Digit, "AHex")
|
|
@@ -308,3 +313,14 @@ DEF(Cased1, "")
|
|
|
308
313
|
DEF(InCB, "")
|
|
309
314
|
|
|
310
315
|
#endif
|
|
316
|
+
|
|
317
|
+
/* Unicode "properties of strings" (used by the regexp v flag) */
|
|
318
|
+
#ifdef UNICODE_SEQUENCE_PROP_LIST
|
|
319
|
+
DEF(Basic_Emoji)
|
|
320
|
+
DEF(Emoji_Keycap_Sequence)
|
|
321
|
+
DEF(RGI_Emoji_Modifier_Sequence)
|
|
322
|
+
DEF(RGI_Emoji_Flag_Sequence)
|
|
323
|
+
DEF(RGI_Emoji_Tag_Sequence)
|
|
324
|
+
DEF(RGI_Emoji_ZWJ_Sequence)
|
|
325
|
+
DEF(RGI_Emoji)
|
|
326
|
+
#endif
|