Coverage Report

Created: 2026-01-10 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ada-url/build/singleheader/ada.cpp
Line
Count
Source
1
/* auto-generated on 2026-01-08 10:25:21 -0500. Do not edit! */
2
/* begin file src/ada.cpp */
3
#include "ada.h"
4
/* begin file src/checkers.cpp */
5
6
#include <algorithm>
7
#include <array>
8
#include <string_view>
9
10
namespace ada::checkers {
11
12
4.37k
ada_really_inline constexpr bool is_ipv4(std::string_view view) noexcept {
13
  // The string is not empty and does not contain upper case ASCII characters.
14
  //
15
  // Optimization. To be considered as a possible ipv4, the string must end
16
  // with 'x' or a lowercase hex character.
17
  // Most of the time, this will be false so this simple check will save a lot
18
  // of effort.
19
  // If the address ends with a dot, we need to prune it (special case).
20
4.37k
  if (view.ends_with('.')) {
21
209
    view.remove_suffix(1);
22
209
    if (view.empty()) {
23
50
      return false;
24
50
    }
25
209
  }
26
4.32k
  char last_char = view.back();
27
4.32k
  bool possible_ipv4 = (last_char >= '0' && last_char <= '9') ||
28
2.89k
                       (last_char >= 'a' && last_char <= 'f') ||
29
1.41k
                       last_char == 'x';
30
4.32k
  if (!possible_ipv4) {
31
1.22k
    return false;
32
1.22k
  }
33
  // From the last character, find the last dot.
34
3.10k
  size_t last_dot = view.rfind('.');
35
3.10k
  if (last_dot != std::string_view::npos) {
36
    // We have at least one dot.
37
860
    view = view.substr(last_dot + 1);
38
860
  }
39
  /** Optimization opportunity: we have basically identified the last number of
40
     the ipv4 if we return true here. We might as well parse it and have at
41
     least one number parsed when we get to parse_ipv4. */
42
3.10k
  if (std::ranges::all_of(view, ada::checkers::is_digit)) {
43
1.05k
    return true;
44
1.05k
  }
45
  // It could be hex (0x), but not if there is a single character.
46
2.05k
  if (view.size() == 1) {
47
193
    return false;
48
193
  }
49
  // It must start with 0x.
50
1.85k
  if (!view.starts_with("0x")) {
51
1.25k
    return false;
52
1.25k
  }
53
  // We must allow "0x".
54
605
  if (view.size() == 2) {
55
38
    return true;
56
38
  }
57
  // We have 0x followed by some characters, we need to check that they are
58
  // hexadecimals.
59
567
  view.remove_prefix(2);
60
567
  return std::ranges::all_of(view, ada::unicode::is_lowercase_hex);
61
605
}
62
63
// for use with path_signature, we include all characters that need percent
64
// encoding.
65
static constexpr std::array<uint8_t, 256> path_signature_table =
66
    []() consteval {
67
      std::array<uint8_t, 256> result{};
68
      for (size_t i = 0; i < 256; i++) {
69
        if (i <= 0x20 || i == 0x22 || i == 0x23 || i == 0x3c || i == 0x3e ||
70
            i == 0x3f || i == 0x5e || i == 0x60 || i == 0x7b || i == 0x7d ||
71
            i > 0x7e) {
72
          result[i] = 1;
73
        } else if (i == 0x25) {
74
          result[i] = 8;
75
        } else if (i == 0x2e) {
76
          result[i] = 4;
77
        } else if (i == 0x5c) {
78
          result[i] = 2;
79
        } else {
80
          result[i] = 0;
81
        }
82
      }
83
      return result;
84
    }();
85
86
ada_really_inline constexpr uint8_t path_signature(
87
0
    std::string_view input) noexcept {
88
  // The path percent-encode set is the query percent-encode set and U+003F (?),
89
  // U+0060 (`), U+007B ({), and U+007D (}). The query percent-encode set is the
90
  // C0 control percent-encode set and U+0020 SPACE, U+0022 ("), U+0023 (#),
91
  // U+003C (<), and U+003E (>). The C0 control percent-encode set are the C0
92
  // controls and all code points greater than U+007E (~).
93
0
  size_t i = 0;
94
0
  uint8_t accumulator{};
95
0
  for (; i + 7 < input.size(); i += 8) {
96
0
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])] |
97
0
                           path_signature_table[uint8_t(input[i + 1])] |
98
0
                           path_signature_table[uint8_t(input[i + 2])] |
99
0
                           path_signature_table[uint8_t(input[i + 3])] |
100
0
                           path_signature_table[uint8_t(input[i + 4])] |
101
0
                           path_signature_table[uint8_t(input[i + 5])] |
102
0
                           path_signature_table[uint8_t(input[i + 6])] |
103
0
                           path_signature_table[uint8_t(input[i + 7])]);
104
0
  }
105
0
  for (; i < input.size(); i++) {
106
0
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])]);
107
0
  }
108
0
  return accumulator;
109
0
}
110
111
ada_really_inline constexpr bool verify_dns_length(
112
0
    std::string_view input) noexcept {
113
0
  if (input.back() == '.') {
114
0
    if (input.size() > 254) return false;
115
0
  } else if (input.size() > 253)
116
0
    return false;
117
118
0
  size_t start = 0;
119
0
  while (start < input.size()) {
120
0
    auto dot_location = input.find('.', start);
121
    // If not found, it's likely the end of the domain
122
0
    if (dot_location == std::string_view::npos) dot_location = input.size();
123
124
0
    auto label_size = dot_location - start;
125
0
    if (label_size > 63 || label_size == 0) return false;
126
127
0
    start = dot_location + 1;
128
0
  }
129
130
0
  return true;
131
0
}
132
}  // namespace ada::checkers
133
/* end file src/checkers.cpp */
134
/* begin file src/unicode.cpp */
135
136
137
ADA_PUSH_DISABLE_ALL_WARNINGS
138
/* begin file src/ada_idna.cpp */
139
/* auto-generated on 2025-06-26 23:04:30 -0300. Do not edit! */
140
/* begin file src/idna.cpp */
141
/* begin file src/unicode_transcoding.cpp */
142
143
#include <algorithm>
144
#include <cstdint>
145
#include <cstring>
146
147
namespace ada::idna {
148
149
3.10k
size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) {
150
3.10k
  const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
151
3.10k
  size_t pos = 0;
152
3.10k
  const char32_t* start{utf32_output};
153
47.1k
  while (pos < len) {
154
    // try to convert the next block of 16 ASCII bytes
155
44.4k
    if (pos + 16 <= len) {  // if it is safe to read 16 more
156
                            // bytes, check that they are ascii
157
29.4k
      uint64_t v1;
158
29.4k
      std::memcpy(&v1, data + pos, sizeof(uint64_t));
159
29.4k
      uint64_t v2;
160
29.4k
      std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
161
29.4k
      uint64_t v{v1 | v2};
162
29.4k
      if ((v & 0x8080808080808080) == 0) {
163
1.01k
        size_t final_pos = pos + 16;
164
17.3k
        while (pos < final_pos) {
165
16.3k
          *utf32_output++ = char32_t(buf[pos]);
166
16.3k
          pos++;
167
16.3k
        }
168
1.01k
        continue;
169
1.01k
      }
170
29.4k
    }
171
43.4k
    uint8_t leading_byte = data[pos];  // leading byte
172
43.4k
    if (leading_byte < 0b10000000) {
173
      // converting one ASCII byte !!!
174
21.9k
      *utf32_output++ = char32_t(leading_byte);
175
21.9k
      pos++;
176
21.9k
    } else if ((leading_byte & 0b11100000) == 0b11000000) {
177
      // We have a two-byte UTF-8
178
5.01k
      if (pos + 1 >= len) {
179
43
        return 0;
180
43
      }  // minimal bound checking
181
4.97k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
182
48
        return 0;
183
48
      }
184
      // range check
185
4.92k
      uint32_t code_point =
186
4.92k
          (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
187
4.92k
      if (code_point < 0x80 || 0x7ff < code_point) {
188
4
        return 0;
189
4
      }
190
4.92k
      *utf32_output++ = char32_t(code_point);
191
4.92k
      pos += 2;
192
16.4k
    } else if ((leading_byte & 0b11110000) == 0b11100000) {
193
      // We have a three-byte UTF-8
194
15.7k
      if (pos + 2 >= len) {
195
15
        return 0;
196
15
      }  // minimal bound checking
197
198
15.7k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
199
12
        return 0;
200
12
      }
201
15.7k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
202
5
        return 0;
203
5
      }
204
      // range check
205
15.7k
      uint32_t code_point = (leading_byte & 0b00001111) << 12 |
206
15.7k
                            (data[pos + 1] & 0b00111111) << 6 |
207
15.7k
                            (data[pos + 2] & 0b00111111);
208
15.7k
      if (code_point < 0x800 || 0xffff < code_point ||
209
15.7k
          (0xd7ff < code_point && code_point < 0xe000)) {
210
12
        return 0;
211
12
      }
212
15.7k
      *utf32_output++ = char32_t(code_point);
213
15.7k
      pos += 3;
214
15.7k
    } else if ((leading_byte & 0b11111000) == 0b11110000) {  // 0b11110000
215
      // we have a 4-byte UTF-8 word.
216
454
      if (pos + 3 >= len) {
217
13
        return 0;
218
13
      }  // minimal bound checking
219
441
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
220
11
        return 0;
221
11
      }
222
430
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
223
3
        return 0;
224
3
      }
225
427
      if ((data[pos + 3] & 0b11000000) != 0b10000000) {
226
6
        return 0;
227
6
      }
228
229
      // range check
230
421
      uint32_t code_point = (leading_byte & 0b00000111) << 18 |
231
421
                            (data[pos + 1] & 0b00111111) << 12 |
232
421
                            (data[pos + 2] & 0b00111111) << 6 |
233
421
                            (data[pos + 3] & 0b00111111);
234
421
      if (code_point <= 0xffff || 0x10ffff < code_point) {
235
14
        return 0;
236
14
      }
237
407
      *utf32_output++ = char32_t(code_point);
238
407
      pos += 4;
239
407
    } else {
240
191
      return 0;
241
191
    }
242
43.4k
  }
243
2.72k
  return utf32_output - start;
244
3.10k
}
245
246
0
size_t utf8_length_from_utf32(const char32_t* buf, size_t len) {
247
  // We are not BOM aware.
248
0
  const uint32_t* p = reinterpret_cast<const uint32_t*>(buf);
249
0
  size_t counter{0};
250
0
  for (size_t i = 0; i != len; ++i) {
251
0
    ++counter;                                      // ASCII
252
0
    counter += static_cast<size_t>(p[i] > 0x7F);    // two-byte
253
0
    counter += static_cast<size_t>(p[i] > 0x7FF);   // three-byte
254
0
    counter += static_cast<size_t>(p[i] > 0xFFFF);  // four-bytes
255
0
  }
256
0
  return counter;
257
0
}
258
259
3.10k
size_t utf32_length_from_utf8(const char* buf, size_t len) {
260
3.10k
  const int8_t* p = reinterpret_cast<const int8_t*>(buf);
261
104k
  return std::count_if(p, std::next(p, len), [](int8_t c) {
262
    // -65 is 0b10111111, anything larger in two-complement's
263
    // should start a new code point.
264
104k
    return c > -65;
265
104k
  });
266
3.10k
}
267
268
0
size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) {
269
0
  const uint32_t* data = reinterpret_cast<const uint32_t*>(buf);
270
0
  size_t pos = 0;
271
0
  const char* start{utf8_output};
272
0
  while (pos < len) {
273
    // try to convert the next block of 2 ASCII characters
274
0
    if (pos + 2 <= len) {  // if it is safe to read 8 more
275
                           // bytes, check that they are ascii
276
0
      uint64_t v;
277
0
      std::memcpy(&v, data + pos, sizeof(uint64_t));
278
0
      if ((v & 0xFFFFFF80FFFFFF80) == 0) {
279
0
        *utf8_output++ = char(buf[pos]);
280
0
        *utf8_output++ = char(buf[pos + 1]);
281
0
        pos += 2;
282
0
        continue;
283
0
      }
284
0
    }
285
0
    uint32_t word = data[pos];
286
0
    if ((word & 0xFFFFFF80) == 0) {
287
      // will generate one UTF-8 bytes
288
0
      *utf8_output++ = char(word);
289
0
      pos++;
290
0
    } else if ((word & 0xFFFFF800) == 0) {
291
      // will generate two UTF-8 bytes
292
      // we have 0b110XXXXX 0b10XXXXXX
293
0
      *utf8_output++ = char((word >> 6) | 0b11000000);
294
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
295
0
      pos++;
296
0
    } else if ((word & 0xFFFF0000) == 0) {
297
      // will generate three UTF-8 bytes
298
      // we have 0b1110XXXX 0b10XXXXXX 0b10XXXXXX
299
0
      if (word >= 0xD800 && word <= 0xDFFF) {
300
0
        return 0;
301
0
      }
302
0
      *utf8_output++ = char((word >> 12) | 0b11100000);
303
0
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
304
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
305
0
      pos++;
306
0
    } else {
307
      // will generate four UTF-8 bytes
308
      // we have 0b11110XXX 0b10XXXXXX 0b10XXXXXX
309
      // 0b10XXXXXX
310
0
      if (word > 0x10FFFF) {
311
0
        return 0;
312
0
      }
313
0
      *utf8_output++ = char((word >> 18) | 0b11110000);
314
0
      *utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
315
0
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
316
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
317
0
      pos++;
318
0
    }
319
0
  }
320
0
  return utf8_output - start;
321
0
}
322
}  // namespace ada::idna
323
/* end file src/unicode_transcoding.cpp */
324
/* begin file src/mapping.cpp */
325
326
#include <algorithm>
327
#include <array>
328
#include <string>
329
330
/* begin file src/mapping_tables.cpp */
331
// IDNA  16.0.0
332
333
// clang-format off
334
#ifndef ADA_IDNA_TABLES_H
335
#define ADA_IDNA_TABLES_H
336
#include <cstdint>
337
338
namespace ada::idna {
339
340
const uint32_t mappings[5236] =
341
{
342
  97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
343
  114, 115, 116, 117, 118, 119, 120, 121, 122, 32, 32, 776, 32, 772, 50, 51, 32, 769,
344
  956, 32, 807, 49, 49, 8260, 52, 49, 8260, 50, 51, 8260, 52, 224, 225, 226, 227,
345
  228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
346
  244, 245, 246, 248, 249, 250, 251, 252, 253, 254, 257, 259, 261, 263, 265, 267,
347
  269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299,
348
  301, 303, 105, 775, 309, 311, 314, 316, 318, 108, 183, 322, 324, 326, 328, 700,
349
  110, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359,
350
  361, 363, 365, 367, 369, 371, 373, 375, 255, 378, 380, 382, 595, 387, 389, 596,
351
  392, 598, 599, 396, 477, 601, 603, 402, 608, 611, 617, 616, 409, 623, 626, 629,
352
  417, 419, 421, 640, 424, 643, 429, 648, 432, 650, 651, 436, 438, 658, 441, 445,
353
  100, 382, 108, 106, 110, 106, 462, 464, 466, 468, 470, 472, 474, 476, 479, 481,
354
  483, 485, 487, 489, 491, 493, 495, 100, 122, 501, 405, 447, 505, 507, 509, 511,
355
  513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535, 537, 539, 541, 543,
356
  414, 547, 549, 551, 553, 555, 557, 559, 561, 563, 11365, 572, 410, 11366, 578, 384,
357
  649, 652, 583, 585, 587, 589, 591, 614, 633, 635, 641, 32, 774, 32, 775, 32, 778,
358
  32, 808, 32, 771, 32, 779, 661, 768, 787, 776, 769, 953, 881, 883, 697, 887, 32,
359
  953, 59, 1011, 32, 776, 769, 940, 941, 942, 943, 972, 973, 974, 945, 946, 947, 948,
360
  949, 950, 951, 952, 954, 955, 957, 958, 959, 960, 961, 963, 964, 965, 966, 967,
361
  968, 969, 970, 971, 983, 985, 987, 989, 991, 993, 995, 997, 999, 1001, 1003, 1005,
362
  1007, 1016, 1019, 891, 892, 893, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111,
363
  1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1072, 1073, 1074, 1075, 1076, 1077,
364
  1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091,
365
  1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1121, 1123,
366
  1125, 1127, 1129, 1131, 1133, 1135, 1137, 1139, 1141, 1143, 1145, 1147, 1149, 1151,
367
  1153, 1163, 1165, 1167, 1169, 1171, 1173, 1175, 1177, 1179, 1181, 1183, 1185, 1187,
368
  1189, 1191, 1193, 1195, 1197, 1199, 1201, 1203, 1205, 1207, 1209, 1211, 1213, 1215,
369
  1231, 1218, 1220, 1222, 1224, 1226, 1228, 1230, 1233, 1235, 1237, 1239, 1241, 1243,
370
  1245, 1247, 1249, 1251, 1253, 1255, 1257, 1259, 1261, 1263, 1265, 1267, 1269, 1271,
371
  1273, 1275, 1277, 1279, 1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, 1297, 1299,
372
  1301, 1303, 1305, 1307, 1309, 1311, 1313, 1315, 1317, 1319, 1321, 1323, 1325, 1327,
373
  1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390,
374
  1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404,
375
  1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1381, 1410, 1575, 1652,
376
  1608, 1652, 1735, 1652, 1610, 1652, 2325, 2364, 2326, 2364, 2327, 2364, 2332, 2364,
377
  2337, 2364, 2338, 2364, 2347, 2364, 2351, 2364, 2465, 2492, 2466, 2492, 2479, 2492,
378
  2610, 2620, 2616, 2620, 2582, 2620, 2583, 2620, 2588, 2620, 2603, 2620, 2849, 2876,
379
  2850, 2876, 3661, 3634, 3789, 3762, 3755, 3737, 3755, 3745, 3851, 3906, 4023, 3916,
380
  4023, 3921, 4023, 3926, 4023, 3931, 4023, 3904, 4021, 3953, 3954, 3953, 3956, 4018,
381
  3968, 4018, 3953, 3968, 4019, 3968, 4019, 3953, 3968, 3986, 4023, 3996, 4023, 4001,
382
  4023, 4006, 4023, 4011, 4023, 3984, 4021, 11520, 11521, 11522, 11523, 11524, 11525,
383
  11526, 11527, 11528, 11529, 11530, 11531, 11532, 11533, 11534, 11535, 11536, 11537,
384
  11538, 11539, 11540, 11541, 11542, 11543, 11544, 11545, 11546, 11547, 11548, 11549,
385
  11550, 11551, 11552, 11553, 11554, 11555, 11556, 11557, 11559, 11565, 4316, 5104,
386
  5105, 5106, 5107, 5108, 5109, 42571, 7306, 4304, 4305, 4306, 4307, 4308, 4309, 4310,
387
  4311, 4312, 4313, 4314, 4315, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325,
388
  4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339,
389
  4340, 4341, 4342, 4343, 4344, 4345, 4346, 4349, 4350, 4351, 592, 593, 7426, 604,
390
  7446, 7447, 7453, 7461, 594, 597, 607, 609, 613, 618, 7547, 669, 621, 7557, 671,
391
  625, 624, 627, 628, 632, 642, 427, 7452, 656, 657, 7681, 7683, 7685, 7687, 7689,
392
  7691, 7693, 7695, 7697, 7699, 7701, 7703, 7705, 7707, 7709, 7711, 7713, 7715, 7717,
393
  7719, 7721, 7723, 7725, 7727, 7729, 7731, 7733, 7735, 7737, 7739, 7741, 7743, 7745,
394
  7747, 7749, 7751, 7753, 7755, 7757, 7759, 7761, 7763, 7765, 7767, 7769, 7771, 7773,
395
  7775, 7777, 7779, 7781, 7783, 7785, 7787, 7789, 7791, 7793, 7795, 7797, 7799, 7801,
396
  7803, 7805, 7807, 7809, 7811, 7813, 7815, 7817, 7819, 7821, 7823, 7825, 7827, 7829,
397
  97, 702, 223, 7841, 7843, 7845, 7847, 7849, 7851, 7853, 7855, 7857, 7859, 7861,
398
  7863, 7865, 7867, 7869, 7871, 7873, 7875, 7877, 7879, 7881, 7883, 7885, 7887, 7889,
399
  7891, 7893, 7895, 7897, 7899, 7901, 7903, 7905, 7907, 7909, 7911, 7913, 7915, 7917,
400
  7919, 7921, 7923, 7925, 7927, 7929, 7931, 7933, 7935, 7936, 7937, 7938, 7939, 7940,
401
  7941, 7942, 7943, 7952, 7953, 7954, 7955, 7956, 7957, 7968, 7969, 7970, 7971, 7972,
402
  7973, 7974, 7975, 7984, 7985, 7986, 7987, 7988, 7989, 7990, 7991, 8000, 8001, 8002,
403
  8003, 8004, 8005, 8017, 8019, 8021, 8023, 8032, 8033, 8034, 8035, 8036, 8037, 8038,
404
  8039, 7936, 953, 7937, 953, 7938, 953, 7939, 953, 7940, 953, 7941, 953, 7942, 953,
405
  7943, 953, 7968, 953, 7969, 953, 7970, 953, 7971, 953, 7972, 953, 7973, 953, 7974,
406
  953, 7975, 953, 8032, 953, 8033, 953, 8034, 953, 8035, 953, 8036, 953, 8037, 953,
407
  8038, 953, 8039, 953, 8048, 953, 945, 953, 940, 953, 8118, 953, 8112, 8113, 32,
408
  787, 32, 834, 32, 776, 834, 8052, 953, 951, 953, 942, 953, 8134, 953, 8050, 32,
409
  787, 768, 32, 787, 769, 32, 787, 834, 912, 8144, 8145, 8054, 32, 788, 768, 32, 788,
410
  769, 32, 788, 834, 944, 8160, 8161, 8058, 8165, 32, 776, 768, 96, 8060, 953, 969,
411
  953, 974, 953, 8182, 953, 8056, 8208, 32, 819, 8242, 8242, 8242, 8242, 8242, 8245,
412
  8245, 8245, 8245, 8245, 33, 33, 32, 773, 63, 63, 63, 33, 33, 63, 48, 53, 54, 55,
413
  56, 57, 43, 8722, 61, 40, 41, 97, 47, 99, 97, 47, 115, 176, 99, 99, 47, 111, 99,
414
  47, 117, 176, 102, 115, 109, 116, 101, 108, 116, 109, 8526, 1488, 1489, 1490, 1491,
415
  102, 97, 120, 8721, 49, 8260, 55, 49, 8260, 57, 49, 8260, 49, 48, 49, 8260, 51,
416
  50, 8260, 51, 49, 8260, 53, 50, 8260, 53, 51, 8260, 53, 52, 8260, 53, 49, 8260,
417
  54, 53, 8260, 54, 49, 8260, 56, 51, 8260, 56, 53, 8260, 56, 55, 8260, 56, 105, 105,
418
  105, 105, 105, 105, 118, 118, 105, 118, 105, 105, 118, 105, 105, 105, 105, 120,
419
  120, 105, 120, 105, 105, 8580, 48, 8260, 51, 8747, 8747, 8747, 8747, 8747, 8750,
420
  8750, 8750, 8750, 8750, 12296, 12297, 49, 50, 49, 51, 49, 52, 49, 53, 49, 54, 49,
421
  55, 49, 56, 49, 57, 50, 48, 40, 49, 41, 40, 50, 41, 40, 51, 41, 40, 52, 41, 40,
422
  53, 41, 40, 54, 41, 40, 55, 41, 40, 56, 41, 40, 57, 41, 40, 49, 48, 41, 40, 49,
423
  49, 41, 40, 49, 50, 41, 40, 49, 51, 41, 40, 49, 52, 41, 40, 49, 53, 41, 40, 49,
424
  54, 41, 40, 49, 55, 41, 40, 49, 56, 41, 40, 49, 57, 41, 40, 50, 48, 41, 40, 97,
425
  41, 40, 98, 41, 40, 99, 41, 40, 100, 41, 40, 101, 41, 40, 102, 41, 40, 103, 41,
426
  40, 104, 41, 40, 105, 41, 40, 106, 41, 40, 107, 41, 40, 108, 41, 40, 109, 41, 40,
427
  110, 41, 40, 111, 41, 40, 112, 41, 40, 113, 41, 40, 114, 41, 40, 115, 41, 40, 116,
428
  41, 40, 117, 41, 40, 118, 41, 40, 119, 41, 40, 120, 41, 40, 121, 41, 40, 122, 41,
429
  58, 58, 61, 61, 61, 10973, 824, 11312, 11313, 11314, 11315, 11316, 11317, 11318,
430
  11319, 11320, 11321, 11322, 11323, 11324, 11325, 11326, 11327, 11328, 11329, 11330,
431
  11331, 11332, 11333, 11334, 11335, 11336, 11337, 11338, 11339, 11340, 11341, 11342,
432
  11343, 11344, 11345, 11346, 11347, 11348, 11349, 11350, 11351, 11352, 11353, 11354,
433
  11355, 11356, 11357, 11358, 11359, 11361, 619, 7549, 637, 11368, 11370, 11372, 11379,
434
  11382, 575, 576, 11393, 11395, 11397, 11399, 11401, 11403, 11405, 11407, 11409,
435
  11411, 11413, 11415, 11417, 11419, 11421, 11423, 11425, 11427, 11429, 11431, 11433,
436
  11435, 11437, 11439, 11441, 11443, 11445, 11447, 11449, 11451, 11453, 11455, 11457,
437
  11459, 11461, 11463, 11465, 11467, 11469, 11471, 11473, 11475, 11477, 11479, 11481,
438
  11483, 11485, 11487, 11489, 11491, 11500, 11502, 11507, 11617, 27597, 40863, 19968,
439
  20008, 20022, 20031, 20057, 20101, 20108, 20128, 20154, 20799, 20837, 20843, 20866,
440
  20886, 20907, 20960, 20981, 20992, 21147, 21241, 21269, 21274, 21304, 21313, 21340,
441
  21353, 21378, 21430, 21448, 21475, 22231, 22303, 22763, 22786, 22794, 22805, 22823,
442
  22899, 23376, 23424, 23544, 23567, 23586, 23608, 23662, 23665, 24027, 24037, 24049,
443
  24062, 24178, 24186, 24191, 24308, 24318, 24331, 24339, 24400, 24417, 24435, 24515,
444
  25096, 25142, 25163, 25903, 25908, 25991, 26007, 26020, 26041, 26080, 26085, 26352,
445
  26376, 26408, 27424, 27490, 27513, 27571, 27595, 27604, 27611, 27663, 27668, 27700,
446
  28779, 29226, 29238, 29243, 29247, 29255, 29273, 29275, 29356, 29572, 29577, 29916,
447
  29926, 29976, 29983, 29992, 30000, 30091, 30098, 30326, 30333, 30382, 30399, 30446,
448
  30683, 30690, 30707, 31034, 31160, 31166, 31348, 31435, 31481, 31859, 31992, 32566,
449
  32593, 32650, 32701, 32769, 32780, 32786, 32819, 32895, 32905, 33251, 33258, 33267,
450
  33276, 33292, 33307, 33311, 33390, 33394, 33400, 34381, 34411, 34880, 34892, 34915,
451
  35198, 35211, 35282, 35328, 35895, 35910, 35925, 35960, 35997, 36196, 36208, 36275,
452
  36523, 36554, 36763, 36784, 36789, 37009, 37193, 37318, 37324, 37329, 38263, 38272,
453
  38428, 38582, 38585, 38632, 38737, 38750, 38754, 38761, 38859, 38893, 38899, 38913,
454
  39080, 39131, 39135, 39318, 39321, 39340, 39592, 39640, 39647, 39717, 39727, 39730,
455
  39740, 39770, 40165, 40565, 40575, 40613, 40635, 40643, 40653, 40657, 40697, 40701,
456
  40718, 40723, 40736, 40763, 40778, 40786, 40845, 40860, 40864, 46, 12306, 21316,
457
  21317, 32, 12441, 32, 12442, 12424, 12426, 12467, 12488, 4352, 4353, 4522, 4354,
458
  4524, 4525, 4355, 4356, 4357, 4528, 4529, 4530, 4531, 4532, 4533, 4378, 4358, 4359,
459
  4360, 4385, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4449, 4450,
460
  4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464,
461
  4465, 4466, 4467, 4468, 4469, 4372, 4373, 4551, 4552, 4556, 4558, 4563, 4567, 4569,
462
  4380, 4573, 4575, 4381, 4382, 4384, 4386, 4387, 4391, 4393, 4395, 4396, 4397, 4398,
463
  4399, 4402, 4406, 4416, 4423, 4428, 4593, 4594, 4439, 4440, 4441, 4484, 4485, 4488,
464
  4497, 4498, 4500, 4510, 4513, 19977, 22235, 19978, 20013, 19979, 30002, 19993, 19969,
465
  22825, 22320, 40, 4352, 41, 40, 4354, 41, 40, 4355, 41, 40, 4357, 41, 40, 4358,
466
  41, 40, 4359, 41, 40, 4361, 41, 40, 4363, 41, 40, 4364, 41, 40, 4366, 41, 40, 4367,
467
  41, 40, 4368, 41, 40, 4369, 41, 40, 4370, 41, 40, 44032, 41, 40, 45208, 41, 40,
468
  45796, 41, 40, 46972, 41, 40, 47560, 41, 40, 48148, 41, 40, 49324, 41, 40, 50500,
469
  41, 40, 51088, 41, 40, 52264, 41, 40, 52852, 41, 40, 53440, 41, 40, 54028, 41, 40,
470
  54616, 41, 40, 51452, 41, 40, 50724, 51204, 41, 40, 50724, 54980, 41, 40, 19968,
471
  41, 40, 20108, 41, 40, 19977, 41, 40, 22235, 41, 40, 20116, 41, 40, 20845, 41, 40,
472
  19971, 41, 40, 20843, 41, 40, 20061, 41, 40, 21313, 41, 40, 26376, 41, 40, 28779,
473
  41, 40, 27700, 41, 40, 26408, 41, 40, 37329, 41, 40, 22303, 41, 40, 26085, 41, 40,
474
  26666, 41, 40, 26377, 41, 40, 31038, 41, 40, 21517, 41, 40, 29305, 41, 40, 36001,
475
  41, 40, 31069, 41, 40, 21172, 41, 40, 20195, 41, 40, 21628, 41, 40, 23398, 41, 40,
476
  30435, 41, 40, 20225, 41, 40, 36039, 41, 40, 21332, 41, 40, 31085, 41, 40, 20241,
477
  41, 40, 33258, 41, 40, 33267, 41, 21839, 24188, 31631, 112, 116, 101, 50, 50, 50,
478
  52, 50, 53, 50, 54, 50, 55, 50, 56, 50, 57, 51, 48, 51, 51, 51, 52, 51, 53, 52280,
479
  44256, 51452, 51032, 50864, 31192, 30007, 36969, 20778, 21360, 27880, 38917, 20889,
480
  27491, 24038, 21491, 21307, 23447, 22812, 51, 54, 51, 55, 51, 56, 51, 57, 52, 48,
481
  52, 52, 52, 53, 52, 54, 52, 55, 52, 56, 52, 57, 53, 48, 49, 26376, 50, 26376, 51,
482
  26376, 52, 26376, 53, 26376, 54, 26376, 55, 26376, 56, 26376, 57, 26376, 49, 48,
483
  26376, 49, 49, 26376, 49, 50, 26376, 104, 103, 101, 114, 103, 101, 118, 108, 116,
484
  100, 12450, 12452, 12454, 12456, 12458, 12459, 12461, 12463, 12465, 12469, 12471,
485
  12473, 12475, 12477, 12479, 12481, 12484, 12486, 12490, 12491, 12492, 12493, 12494,
486
  12495, 12498, 12501, 12504, 12507, 12510, 12511, 12512, 12513, 12514, 12516, 12518,
487
  12520, 12521, 12522, 12523, 12524, 12525, 12527, 12528, 12529, 12530, 20196, 21644,
488
  12450, 12497, 12540, 12488, 12450, 12523, 12501, 12449, 12450, 12531, 12506, 12450,
489
  12450, 12540, 12523, 12452, 12491, 12531, 12464, 12452, 12531, 12481, 12454, 12457,
490
  12531, 12456, 12473, 12463, 12540, 12489, 12456, 12540, 12459, 12540, 12458, 12531,
491
  12473, 12458, 12540, 12512, 12459, 12452, 12522, 12459, 12521, 12483, 12488, 12459,
492
  12525, 12522, 12540, 12460, 12525, 12531, 12460, 12531, 12510, 12462, 12460, 12462,
493
  12491, 12540, 12461, 12517, 12522, 12540, 12462, 12523, 12480, 12540, 12461, 12525,
494
  12461, 12525, 12464, 12521, 12512, 12461, 12525, 12513, 12540, 12488, 12523, 12461,
495
  12525, 12527, 12483, 12488, 12464, 12521, 12512, 12488, 12531, 12463, 12523, 12476,
496
  12452, 12525, 12463, 12525, 12540, 12493, 12465, 12540, 12473, 12467, 12523, 12490,
497
  12467, 12540, 12509, 12469, 12452, 12463, 12523, 12469, 12531, 12481, 12540, 12512,
498
  12471, 12522, 12531, 12464, 12475, 12531, 12481, 12475, 12531, 12488, 12480, 12540,
499
  12473, 12487, 12471, 12489, 12523, 12490, 12494, 12494, 12483, 12488, 12495, 12452,
500
  12484, 12497, 12540, 12475, 12531, 12488, 12497, 12540, 12484, 12496, 12540, 12524,
501
  12523, 12500, 12450, 12473, 12488, 12523, 12500, 12463, 12523, 12500, 12467, 12499,
502
  12523, 12501, 12449, 12521, 12483, 12489, 12501, 12451, 12540, 12488, 12502, 12483,
503
  12471, 12455, 12523, 12501, 12521, 12531, 12504, 12463, 12479, 12540, 12523, 12506,
504
  12477, 12506, 12491, 12498, 12504, 12523, 12484, 12506, 12531, 12473, 12506, 12540,
505
  12472, 12505, 12540, 12479, 12509, 12452, 12531, 12488, 12508, 12523, 12488, 12507,
506
  12531, 12509, 12531, 12489, 12507, 12540, 12523, 12507, 12540, 12531, 12510, 12452,
507
  12463, 12525, 12510, 12452, 12523, 12510, 12483, 12495, 12510, 12523, 12463, 12510,
508
  12531, 12471, 12519, 12531, 12511, 12463, 12525, 12531, 12511, 12522, 12511, 12522,
509
  12496, 12540, 12523, 12513, 12460, 12513, 12460, 12488, 12531, 12516, 12540, 12489,
510
  12516, 12540, 12523, 12518, 12450, 12531, 12522, 12483, 12488, 12523, 12522, 12521,
511
  12523, 12500, 12540, 12523, 12540, 12502, 12523, 12524, 12512, 12524, 12531, 12488,
512
  12466, 12531, 48, 28857, 49, 28857, 50, 28857, 51, 28857, 52, 28857, 53, 28857,
513
  54, 28857, 55, 28857, 56, 28857, 57, 28857, 49, 48, 28857, 49, 49, 28857, 49, 50,
514
  28857, 49, 51, 28857, 49, 52, 28857, 49, 53, 28857, 49, 54, 28857, 49, 55, 28857,
515
  49, 56, 28857, 49, 57, 28857, 50, 48, 28857, 50, 49, 28857, 50, 50, 28857, 50, 51,
516
  28857, 50, 52, 28857, 104, 112, 97, 100, 97, 97, 117, 98, 97, 114, 111, 118, 112,
517
  99, 100, 109, 100, 109, 50, 100, 109, 51, 105, 117, 24179, 25104, 26157, 21644,
518
  22823, 27491, 26126, 27835, 26666, 24335, 20250, 31038, 110, 97, 956, 97, 109, 97,
519
  107, 97, 107, 98, 109, 98, 103, 98, 99, 97, 108, 107, 99, 97, 108, 112, 102, 110,
520
  102, 956, 102, 956, 103, 109, 103, 107, 103, 104, 122, 107, 104, 122, 109, 104,
521
  122, 116, 104, 122, 956, 108, 109, 108, 100, 108, 102, 109, 110, 109, 956, 109,
522
  109, 109, 99, 109, 107, 109, 109, 109, 50, 99, 109, 50, 107, 109, 50, 109, 109,
523
  51, 99, 109, 51, 107, 109, 51, 109, 8725, 115, 109, 8725, 115, 50, 107, 112, 97,
524
  109, 112, 97, 103, 112, 97, 114, 97, 100, 114, 97, 100, 8725, 115, 114, 97, 100,
525
  8725, 115, 50, 112, 115, 110, 115, 956, 115, 109, 115, 112, 118, 110, 118, 956,
526
  118, 109, 118, 107, 118, 112, 119, 110, 119, 956, 119, 109, 119, 107, 119, 107,
527
  969, 109, 969, 98, 113, 99, 8725, 107, 103, 100, 98, 103, 121, 104, 97, 105, 110,
528
  107, 107, 107, 116, 108, 110, 108, 111, 103, 108, 120, 109, 105, 108, 109, 111,
529
  108, 112, 104, 112, 112, 109, 112, 114, 115, 118, 119, 98, 118, 8725, 109, 97, 8725,
530
  109, 49, 26085, 50, 26085, 51, 26085, 52, 26085, 53, 26085, 54, 26085, 55, 26085,
531
  56, 26085, 57, 26085, 49, 48, 26085, 49, 49, 26085, 49, 50, 26085, 49, 51, 26085,
532
  49, 52, 26085, 49, 53, 26085, 49, 54, 26085, 49, 55, 26085, 49, 56, 26085, 49, 57,
533
  26085, 50, 48, 26085, 50, 49, 26085, 50, 50, 26085, 50, 51, 26085, 50, 52, 26085,
534
  50, 53, 26085, 50, 54, 26085, 50, 55, 26085, 50, 56, 26085, 50, 57, 26085, 51, 48,
535
  26085, 51, 49, 26085, 103, 97, 108, 42561, 42563, 42565, 42567, 42569, 42573, 42575,
536
  42577, 42579, 42581, 42583, 42585, 42587, 42589, 42591, 42593, 42595, 42597, 42599,
537
  42601, 42603, 42605, 42625, 42627, 42629, 42631, 42633, 42635, 42637, 42639, 42641,
538
  42643, 42645, 42647, 42649, 42651, 42787, 42789, 42791, 42793, 42795, 42797, 42799,
539
  42803, 42805, 42807, 42809, 42811, 42813, 42815, 42817, 42819, 42821, 42823, 42825,
540
  42827, 42829, 42831, 42833, 42835, 42837, 42839, 42841, 42843, 42845, 42847, 42849,
541
  42851, 42853, 42855, 42857, 42859, 42861, 42863, 42874, 42876, 7545, 42879, 42881,
542
  42883, 42885, 42887, 42892, 42897, 42899, 42903, 42905, 42907, 42909, 42911, 42913,
543
  42915, 42917, 42919, 42921, 620, 670, 647, 43859, 42933, 42935, 42937, 42939, 42941,
544
  42943, 42945, 42947, 42900, 7566, 42952, 42954, 612, 42957, 42961, 42967, 42969,
545
  42971, 411, 42998, 43831, 43858, 653, 5024, 5025, 5026, 5027, 5028, 5029, 5030,
546
  5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044,
547
  5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058,
548
  5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072,
549
  5073, 5074, 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086,
550
  5087, 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100,
551
  5101, 5102, 5103, 35912, 26356, 36040, 28369, 20018, 21477, 22865, 21895, 22856,
552
  25078, 30313, 32645, 34367, 34746, 35064, 37007, 27138, 27931, 28889, 29662, 33853,
553
  37226, 39409, 20098, 21365, 27396, 29211, 34349, 40478, 23888, 28651, 34253, 35172,
554
  25289, 33240, 34847, 24266, 26391, 28010, 29436, 37070, 20358, 20919, 21214, 25796,
555
  27347, 29200, 30439, 34310, 34396, 36335, 38706, 39791, 40442, 30860, 31103, 32160,
556
  33737, 37636, 35542, 22751, 24324, 31840, 32894, 29282, 30922, 36034, 38647, 22744,
557
  23650, 27155, 28122, 28431, 32047, 32311, 38475, 21202, 32907, 20956, 20940, 31260,
558
  32190, 33777, 38517, 35712, 25295, 35582, 20025, 23527, 24594, 29575, 30064, 21271,
559
  30971, 20415, 24489, 19981, 27852, 25976, 32034, 21443, 22622, 30465, 33865, 35498,
560
  27578, 27784, 25342, 33509, 25504, 30053, 20142, 20841, 20937, 26753, 31975, 33391,
561
  35538, 37327, 21237, 21570, 24300, 26053, 28670, 31018, 38317, 39530, 40599, 40654,
562
  26310, 27511, 36706, 24180, 24976, 25088, 25754, 28451, 29001, 29833, 31178, 32244,
563
  32879, 36646, 34030, 36899, 37706, 21015, 21155, 21693, 28872, 35010, 24265, 24565,
564
  25467, 27566, 31806, 29557, 22265, 23994, 24604, 29618, 29801, 32666, 32838, 37428,
565
  38646, 38728, 38936, 20363, 31150, 37300, 38584, 24801, 20102, 20698, 23534, 23615,
566
  26009, 29134, 30274, 34044, 36988, 26248, 38446, 21129, 26491, 26611, 27969, 28316,
567
  29705, 30041, 30827, 32016, 39006, 25134, 38520, 20523, 23833, 28138, 36650, 24459,
568
  24900, 26647, 38534, 21033, 21519, 23653, 26131, 26446, 26792, 27877, 29702, 30178,
569
  32633, 35023, 35041, 38626, 21311, 28346, 21533, 29136, 29848, 34298, 38563, 40023,
570
  40607, 26519, 28107, 33256, 31520, 31890, 29376, 28825, 35672, 20160, 33590, 21050,
571
  20999, 24230, 25299, 31958, 23429, 27934, 26292, 36667, 38477, 24275, 20800, 21952,
572
  22618, 26228, 20958, 29482, 30410, 31036, 31070, 31077, 31119, 38742, 31934, 34322,
573
  35576, 36920, 37117, 39151, 39164, 39208, 40372, 37086, 38583, 20398, 20711, 20813,
574
  21193, 21220, 21329, 21917, 22022, 22120, 22592, 22696, 23652, 24724, 24936, 24974,
575
  25074, 25935, 26082, 26257, 26757, 28023, 28186, 28450, 29038, 29227, 29730, 30865,
576
  31049, 31048, 31056, 31062, 31117, 31118, 31296, 31361, 31680, 32265, 32321, 32626,
577
  32773, 33261, 33401, 33879, 35088, 35222, 35585, 35641, 36051, 36104, 36790, 38627,
578
  38911, 38971, 24693, 148206, 33304, 20006, 20917, 20840, 20352, 20805, 20864, 21191,
579
  21242, 21845, 21913, 21986, 22707, 22852, 22868, 23138, 23336, 24274, 24281, 24425,
580
  24493, 24792, 24910, 24840, 24928, 25140, 25540, 25628, 25682, 25942, 26395, 26454,
581
  28379, 28363, 28702, 30631, 29237, 29359, 29809, 29958, 30011, 30237, 30239, 30427,
582
  30452, 30538, 30528, 30924, 31409, 31867, 32091, 32574, 33618, 33775, 34681, 35137,
583
  35206, 35519, 35531, 35565, 35722, 36664, 36978, 37273, 37494, 38524, 38875, 38923,
584
  39698, 141386, 141380, 144341, 15261, 16408, 16441, 152137, 154832, 163539, 40771,
585
  40846, 102, 102, 102, 105, 102, 108, 102, 102, 108, 1396, 1398, 1396, 1381, 1396,
586
  1387, 1406, 1398, 1396, 1389, 1497, 1460, 1522, 1463, 1506, 1492, 1499, 1500, 1501,
587
  1512, 1514, 1513, 1473, 1513, 1474, 1513, 1468, 1473, 1513, 1468, 1474, 1488, 1463,
588
  1488, 1464, 1488, 1468, 1489, 1468, 1490, 1468, 1491, 1468, 1492, 1468, 1493, 1468,
589
  1494, 1468, 1496, 1468, 1497, 1468, 1498, 1468, 1499, 1468, 1500, 1468, 1502, 1468,
590
  1504, 1468, 1505, 1468, 1507, 1468, 1508, 1468, 1510, 1468, 1511, 1468, 1512, 1468,
591
  1514, 1468, 1493, 1465, 1489, 1471, 1499, 1471, 1508, 1471, 1488, 1500, 1649, 1659,
592
  1662, 1664, 1658, 1663, 1657, 1700, 1702, 1668, 1667, 1670, 1671, 1677, 1676, 1678,
593
  1672, 1688, 1681, 1705, 1711, 1715, 1713, 1722, 1723, 1728, 1729, 1726, 1746, 1747,
594
  1709, 1734, 1736, 1739, 1733, 1737, 1744, 1609, 1574, 1575, 1574, 1749, 1574, 1608,
595
  1574, 1735, 1574, 1734, 1574, 1736, 1574, 1744, 1574, 1609, 1740, 1574, 1580, 1574,
596
  1581, 1574, 1605, 1574, 1610, 1576, 1580, 1576, 1581, 1576, 1582, 1576, 1605, 1576,
597
  1609, 1576, 1610, 1578, 1580, 1578, 1581, 1578, 1582, 1578, 1605, 1578, 1609, 1578,
598
  1610, 1579, 1580, 1579, 1605, 1579, 1609, 1579, 1610, 1580, 1581, 1580, 1605, 1581,
599
  1605, 1582, 1580, 1582, 1581, 1582, 1605, 1587, 1580, 1587, 1581, 1587, 1582, 1587,
600
  1605, 1589, 1581, 1589, 1605, 1590, 1580, 1590, 1581, 1590, 1582, 1590, 1605, 1591,
601
  1581, 1591, 1605, 1592, 1605, 1593, 1580, 1593, 1605, 1594, 1580, 1594, 1605, 1601,
602
  1580, 1601, 1581, 1601, 1582, 1601, 1605, 1601, 1609, 1601, 1610, 1602, 1581, 1602,
603
  1605, 1602, 1609, 1602, 1610, 1603, 1575, 1603, 1580, 1603, 1581, 1603, 1582, 1603,
604
  1604, 1603, 1605, 1603, 1609, 1603, 1610, 1604, 1580, 1604, 1581, 1604, 1582, 1604,
605
  1605, 1604, 1609, 1604, 1610, 1605, 1580, 1605, 1605, 1605, 1609, 1605, 1610, 1606,
606
  1580, 1606, 1581, 1606, 1582, 1606, 1605, 1606, 1609, 1606, 1610, 1607, 1580, 1607,
607
  1605, 1607, 1609, 1607, 1610, 1610, 1581, 1610, 1582, 1610, 1609, 1584, 1648, 1585,
608
  1648, 1609, 1648, 32, 1612, 1617, 32, 1613, 1617, 32, 1614, 1617, 32, 1615, 1617,
609
  32, 1616, 1617, 32, 1617, 1648, 1574, 1585, 1574, 1586, 1574, 1606, 1576, 1585,
610
  1576, 1586, 1576, 1606, 1578, 1585, 1578, 1586, 1578, 1606, 1579, 1585, 1579, 1586,
611
  1579, 1606, 1605, 1575, 1606, 1585, 1606, 1586, 1606, 1606, 1610, 1585, 1610, 1586,
612
  1574, 1582, 1574, 1607, 1576, 1607, 1578, 1607, 1589, 1582, 1604, 1607, 1606, 1607,
613
  1607, 1648, 1579, 1607, 1587, 1607, 1588, 1605, 1588, 1607, 1600, 1614, 1617, 1600,
614
  1615, 1617, 1600, 1616, 1617, 1591, 1609, 1591, 1610, 1593, 1609, 1593, 1610, 1594,
615
  1609, 1594, 1610, 1587, 1609, 1587, 1610, 1588, 1609, 1588, 1610, 1581, 1609, 1580,
616
  1609, 1580, 1610, 1582, 1609, 1589, 1609, 1589, 1610, 1590, 1609, 1590, 1610, 1588,
617
  1580, 1588, 1581, 1588, 1582, 1588, 1585, 1587, 1585, 1589, 1585, 1590, 1585, 1575,
618
  1611, 1578, 1580, 1605, 1578, 1581, 1580, 1578, 1581, 1605, 1578, 1582, 1605, 1578,
619
  1605, 1580, 1578, 1605, 1581, 1578, 1605, 1582, 1581, 1605, 1610, 1581, 1605, 1609,
620
  1587, 1581, 1580, 1587, 1580, 1581, 1587, 1580, 1609, 1587, 1605, 1581, 1587, 1605,
621
  1580, 1587, 1605, 1605, 1589, 1581, 1581, 1589, 1605, 1605, 1588, 1581, 1605, 1588,
622
  1580, 1610, 1588, 1605, 1582, 1588, 1605, 1605, 1590, 1581, 1609, 1590, 1582, 1605,
623
  1591, 1605, 1581, 1591, 1605, 1605, 1591, 1605, 1610, 1593, 1580, 1605, 1593, 1605,
624
  1605, 1593, 1605, 1609, 1594, 1605, 1605, 1594, 1605, 1610, 1594, 1605, 1609, 1601,
625
  1582, 1605, 1602, 1605, 1581, 1602, 1605, 1605, 1604, 1581, 1605, 1604, 1581, 1610,
626
  1604, 1581, 1609, 1604, 1580, 1580, 1604, 1582, 1605, 1604, 1605, 1581, 1605, 1581,
627
  1580, 1605, 1581, 1610, 1605, 1580, 1581, 1605, 1582, 1605, 1605, 1580, 1582, 1607,
628
  1605, 1580, 1607, 1605, 1605, 1606, 1581, 1605, 1606, 1581, 1609, 1606, 1580, 1605,
629
  1606, 1580, 1609, 1606, 1605, 1610, 1606, 1605, 1609, 1610, 1605, 1605, 1576, 1582,
630
  1610, 1578, 1580, 1610, 1578, 1580, 1609, 1578, 1582, 1610, 1578, 1582, 1609, 1578,
631
  1605, 1610, 1578, 1605, 1609, 1580, 1605, 1610, 1580, 1581, 1609, 1580, 1605, 1609,
632
  1587, 1582, 1609, 1589, 1581, 1610, 1588, 1581, 1610, 1590, 1581, 1610, 1604, 1580,
633
  1610, 1604, 1605, 1610, 1610, 1580, 1610, 1610, 1605, 1610, 1605, 1605, 1610, 1602,
634
  1605, 1610, 1606, 1581, 1610, 1593, 1605, 1610, 1603, 1605, 1610, 1606, 1580, 1581,
635
  1605, 1582, 1610, 1604, 1580, 1605, 1603, 1605, 1605, 1580, 1581, 1610, 1581, 1580,
636
  1610, 1605, 1580, 1610, 1601, 1605, 1610, 1576, 1581, 1610, 1587, 1582, 1610, 1606,
637
  1580, 1610, 1589, 1604, 1746, 1602, 1604, 1746, 1575, 1604, 1604, 1607, 1575, 1603,
638
  1576, 1585, 1605, 1581, 1605, 1583, 1589, 1604, 1593, 1605, 1585, 1587, 1608, 1604,
639
  1593, 1604, 1610, 1607, 1608, 1587, 1604, 1605, 1589, 1604, 1609, 1589, 1604, 1609,
640
  32, 1575, 1604, 1604, 1607, 32, 1593, 1604, 1610, 1607, 32, 1608, 1587, 1604, 1605,
641
  1580, 1604, 32, 1580, 1604, 1575, 1604, 1607, 1585, 1740, 1575, 1604, 44, 12289,
642
  12310, 12311, 8212, 8211, 95, 123, 125, 12308, 12309, 12304, 12305, 12298, 12299,
643
  12300, 12301, 12302, 12303, 91, 93, 35, 38, 42, 45, 60, 62, 92, 36, 37, 64, 32,
644
  1611, 1600, 1611, 1600, 1617, 32, 1618, 1600, 1618, 1569, 1570, 1571, 1572, 1573,
645
  1577, 1604, 1570, 1604, 1571, 1604, 1573, 34, 39, 94, 124, 126, 10629, 10630, 12539,
646
  12453, 12515, 162, 163, 172, 166, 165, 8361, 9474, 8592, 8593, 8594, 8595, 9632,
647
  9675, 66600, 66601, 66602, 66603, 66604, 66605, 66606, 66607, 66608, 66609, 66610,
648
  66611, 66612, 66613, 66614, 66615, 66616, 66617, 66618, 66619, 66620, 66621, 66622,
649
  66623, 66624, 66625, 66626, 66627, 66628, 66629, 66630, 66631, 66632, 66633, 66634,
650
  66635, 66636, 66637, 66638, 66639, 66776, 66777, 66778, 66779, 66780, 66781, 66782,
651
  66783, 66784, 66785, 66786, 66787, 66788, 66789, 66790, 66791, 66792, 66793, 66794,
652
  66795, 66796, 66797, 66798, 66799, 66800, 66801, 66802, 66803, 66804, 66805, 66806,
653
  66807, 66808, 66809, 66810, 66811, 66967, 66968, 66969, 66970, 66971, 66972, 66973,
654
  66974, 66975, 66976, 66977, 66979, 66980, 66981, 66982, 66983, 66984, 66985, 66986,
655
  66987, 66988, 66989, 66990, 66991, 66992, 66993, 66995, 66996, 66997, 66998, 66999,
656
  67000, 67001, 67003, 67004, 720, 721, 665, 675, 43878, 677, 676, 7569, 600, 606,
657
  681, 610, 667, 668, 615, 644, 682, 683, 122628, 42894, 622, 122629, 654, 122630,
658
  630, 631, 634, 122632, 638, 680, 678, 43879, 679, 11377, 655, 673, 674, 664, 448,
659
  449, 450, 122634, 122654, 68800, 68801, 68802, 68803, 68804, 68805, 68806, 68807,
660
  68808, 68809, 68810, 68811, 68812, 68813, 68814, 68815, 68816, 68817, 68818, 68819,
661
  68820, 68821, 68822, 68823, 68824, 68825, 68826, 68827, 68828, 68829, 68830, 68831,
662
  68832, 68833, 68834, 68835, 68836, 68837, 68838, 68839, 68840, 68841, 68842, 68843,
663
  68844, 68845, 68846, 68847, 68848, 68849, 68850, 68976, 68977, 68978, 68979, 68980,
664
  68981, 68982, 68983, 68984, 68985, 68986, 68987, 68988, 68989, 68990, 68991, 68992,
665
  68993, 68994, 68995, 68996, 68997, 71872, 71873, 71874, 71875, 71876, 71877, 71878,
666
  71879, 71880, 71881, 71882, 71883, 71884, 71885, 71886, 71887, 71888, 71889, 71890,
667
  71891, 71892, 71893, 71894, 71895, 71896, 71897, 71898, 71899, 71900, 71901, 71902,
668
  71903, 93792, 93793, 93794, 93795, 93796, 93797, 93798, 93799, 93800, 93801, 93802,
669
  93803, 93804, 93805, 93806, 93807, 93808, 93809, 93810, 93811, 93812, 93813, 93814,
670
  93815, 93816, 93817, 93818, 93819, 93820, 93821, 93822, 93823, 119127, 119141, 119128,
671
  119141, 119128, 119141, 119150, 119128, 119141, 119151, 119128, 119141, 119152,
672
  119128, 119141, 119153, 119128, 119141, 119154, 119225, 119141, 119226, 119141,
673
  119225, 119141, 119150, 119226, 119141, 119150, 119225, 119141, 119151, 119226,
674
  119141, 119151, 305, 567, 8711, 8706, 125218, 125219, 125220, 125221, 125222, 125223,
675
  125224, 125225, 125226, 125227, 125228, 125229, 125230, 125231, 125232, 125233,
676
  125234, 125235, 125236, 125237, 125238, 125239, 125240, 125241, 125242, 125243,
677
  125244, 125245, 125246, 125247, 125248, 125249, 125250, 125251, 1646, 1697, 1647,
678
  48, 44, 49, 44, 50, 44, 51, 44, 52, 44, 53, 44, 54, 44, 55, 44, 56, 44, 57, 44,
679
  12308, 115, 12309, 119, 122, 104, 118, 115, 100, 115, 115, 112, 112, 118, 119, 99,
680
  109, 114, 100, 106, 12411, 12363, 12467, 12467, 23383, 21452, 22810, 35299, 20132,
681
  26144, 28961, 21069, 24460, 20877, 26032, 21021, 32066, 36009, 22768, 21561, 28436,
682
  25237, 25429, 36938, 25351, 25171, 31105, 31354, 21512, 28288, 30003, 21106, 21942,
683
  37197, 12308, 26412, 12309, 12308, 19977, 12309, 12308, 20108, 12309, 12308, 23433,
684
  12309, 12308, 28857, 12309, 12308, 25171, 12309, 12308, 30423, 12309, 12308, 21213,
685
  12309, 12308, 25943, 12309, 24471, 21487, 20029, 20024, 20033, 131362, 20320, 20411,
686
  20482, 20602, 20633, 20687, 13470, 132666, 20820, 20836, 20855, 132380, 13497, 20839,
687
  132427, 20887, 20900, 20172, 20908, 168415, 20995, 13535, 21051, 21062, 21111, 13589,
688
  21253, 21254, 21321, 21338, 21363, 21373, 21375, 133676, 28784, 21450, 21471, 133987,
689
  21483, 21489, 21510, 21662, 21560, 21576, 21608, 21666, 21750, 21776, 21843, 21859,
690
  21892, 21931, 21939, 21954, 22294, 22295, 22097, 22132, 22766, 22478, 22516, 22541,
691
  22411, 22578, 22577, 22700, 136420, 22770, 22775, 22790, 22818, 22882, 136872, 136938,
692
  23020, 23067, 23079, 23000, 23142, 14062, 14076, 23304, 23358, 137672, 23491, 23512,
693
  23539, 138008, 23551, 23558, 24403, 14209, 23648, 23744, 23693, 138724, 23875, 138726,
694
  23918, 23915, 23932, 24033, 24034, 14383, 24061, 24104, 24125, 24169, 14434, 139651,
695
  14460, 24240, 24243, 24246, 172946, 140081, 33281, 24354, 14535, 144056, 156122,
696
  24418, 24427, 14563, 24474, 24525, 24535, 24569, 24705, 14650, 14620, 141012, 24775,
697
  24904, 24908, 24954, 25010, 24996, 25007, 25054, 25115, 25181, 25265, 25300, 25424,
698
  142092, 25405, 25340, 25448, 25475, 25572, 142321, 25634, 25541, 25513, 14894, 25705,
699
  25726, 25757, 25719, 14956, 25964, 143370, 26083, 26360, 26185, 15129, 15112, 15076,
700
  20882, 20885, 26368, 26268, 32941, 17369, 26401, 26462, 26451, 144323, 15177, 26618,
701
  26501, 26706, 144493, 26766, 26655, 26900, 26946, 27043, 27114, 27304, 145059, 27355,
702
  15384, 27425, 145575, 27476, 15438, 27506, 27551, 27579, 146061, 138507, 146170,
703
  27726, 146620, 27839, 27853, 27751, 27926, 27966, 28009, 28024, 28037, 146718, 27956,
704
  28207, 28270, 15667, 28359, 147153, 28153, 28526, 147294, 147342, 28614, 28729,
705
  28699, 15766, 28746, 28797, 28791, 28845, 132389, 28997, 148067, 29084, 148395,
706
  29224, 29264, 149000, 29312, 29333, 149301, 149524, 29562, 29579, 16044, 29605,
707
  16056, 29767, 29788, 29829, 29898, 16155, 29988, 150582, 30014, 150674, 139679,
708
  30224, 151457, 151480, 151620, 16380, 16392, 151795, 151794, 151833, 151859, 30494,
709
  30495, 30603, 16454, 16534, 152605, 30798, 16611, 153126, 153242, 153285, 31211,
710
  16687, 31306, 31311, 153980, 154279, 31470, 16898, 154539, 31686, 31689, 16935,
711
  154752, 31954, 17056, 31976, 31971, 32000, 155526, 32099, 17153, 32199, 32258, 32325,
712
  17204, 156200, 156231, 17241, 156377, 32634, 156478, 32661, 32762, 156890, 156963,
713
  32864, 157096, 32880, 144223, 17365, 32946, 33027, 17419, 33086, 23221, 157607,
714
  157621, 144275, 144284, 33284, 36766, 17515, 33425, 33419, 33437, 21171, 33457,
715
  33459, 33469, 33510, 158524, 33565, 33635, 33709, 33571, 33725, 33767, 33619, 33738,
716
  33740, 33756, 158774, 159083, 158933, 17707, 34033, 34035, 34070, 160714, 34148,
717
  159532, 17757, 17761, 159665, 159954, 17771, 34384, 34407, 34409, 34473, 34440,
718
  34574, 34530, 34600, 34667, 34694, 17879, 34785, 34817, 17913, 34912, 161383, 35031,
719
  35038, 17973, 35066, 13499, 161966, 162150, 18110, 18119, 35488, 162984, 36011,
720
  36033, 36123, 36215, 163631, 133124, 36299, 36284, 36336, 133342, 36564, 165330,
721
  165357, 37012, 37105, 37137, 165678, 37147, 37432, 37591, 37592, 37500, 37881, 37909,
722
  166906, 38283, 18837, 38327, 167287, 18918, 38595, 23986, 38691, 168261, 168474,
723
  19054, 19062, 38880, 168970, 19122, 169110, 38953, 169398, 39138, 19251, 39209,
724
  39335, 39362, 39422, 19406, 170800, 40000, 40189, 19662, 19693, 40295, 172238, 19704,
725
  172293, 172558, 172689, 19798, 40702, 40709, 40719, 40726, 173568,
726
727
};
728
const uint32_t table[8150][2] =
729
{
730
  {0, 1}, {65, 16777219}, {66, 16777475}, {67, 16777731},
731
  {68, 16777987}, {69, 16778243}, {70, 16778499}, {71, 16778755},
732
  {72, 16779011}, {73, 16779267}, {74, 16779523}, {75, 16779779},
733
  {76, 16780035}, {77, 16780291}, {78, 16780547}, {79, 16780803},
734
  {80, 16781059}, {81, 16781315}, {82, 16781571}, {83, 16781827},
735
  {84, 16782083}, {85, 16782339}, {86, 16782595}, {87, 16782851},
736
  {88, 16783107}, {89, 16783363}, {90, 16783619}, {91, 1},
737
  {128, 2}, {160, 16783875}, {161, 1}, {168, 33561347},
738
  {169, 1}, {170, 16777219}, {171, 1}, {173, 0},
739
  {174, 1}, {175, 33561859}, {176, 1}, {178, 16785155},
740
  {179, 16785411}, {180, 33562883}, {181, 16786179}, {182, 1},
741
  {184, 33563651}, {185, 16786947}, {186, 16780803}, {187, 1},
742
  {188, 50341635}, {189, 50342403}, {190, 50343171}, {191, 1},
743
  {192, 16789507}, {193, 16789763}, {194, 16790019}, {195, 16790275},
744
  {196, 16790531}, {197, 16790787}, {198, 16791043}, {199, 16791299},
745
  {200, 16791555}, {201, 16791811}, {202, 16792067}, {203, 16792323},
746
  {204, 16792579}, {205, 16792835}, {206, 16793091}, {207, 16793347},
747
  {208, 16793603}, {209, 16793859}, {210, 16794115}, {211, 16794371},
748
  {212, 16794627}, {213, 16794883}, {214, 16795139}, {215, 1},
749
  {216, 16795395}, {217, 16795651}, {218, 16795907}, {219, 16796163},
750
  {220, 16796419}, {221, 16796675}, {222, 16796931}, {223, 1},
751
  {256, 16797187}, {257, 1}, {258, 16797443}, {259, 1},
752
  {260, 16797699}, {261, 1}, {262, 16797955}, {263, 1},
753
  {264, 16798211}, {265, 1}, {266, 16798467}, {267, 1},
754
  {268, 16798723}, {269, 1}, {270, 16798979}, {271, 1},
755
  {272, 16799235}, {273, 1}, {274, 16799491}, {275, 1},
756
  {276, 16799747}, {277, 1}, {278, 16800003}, {279, 1},
757
  {280, 16800259}, {281, 1}, {282, 16800515}, {283, 1},
758
  {284, 16800771}, {285, 1}, {286, 16801027}, {287, 1},
759
  {288, 16801283}, {289, 1}, {290, 16801539}, {291, 1},
760
  {292, 16801795}, {293, 1}, {294, 16802051}, {295, 1},
761
  {296, 16802307}, {297, 1}, {298, 16802563}, {299, 1},
762
  {300, 16802819}, {301, 1}, {302, 16803075}, {303, 1},
763
  {304, 33580547}, {305, 1}, {306, 33556483}, {308, 16803843},
764
  {309, 1}, {310, 16804099}, {311, 1}, {313, 16804355},
765
  {314, 1}, {315, 16804611}, {316, 1}, {317, 16804867},
766
  {318, 1}, {319, 33582339}, {321, 16805635}, {322, 1},
767
  {323, 16805891}, {324, 1}, {325, 16806147}, {326, 1},
768
  {327, 16806403}, {328, 1}, {329, 33583875}, {330, 16807171},
769
  {331, 1}, {332, 16807427}, {333, 1}, {334, 16807683},
770
  {335, 1}, {336, 16807939}, {337, 1}, {338, 16808195},
771
  {339, 1}, {340, 16808451}, {341, 1}, {342, 16808707},
772
  {343, 1}, {344, 16808963}, {345, 1}, {346, 16809219},
773
  {347, 1}, {348, 16809475}, {349, 1}, {350, 16809731},
774
  {351, 1}, {352, 16809987}, {353, 1}, {354, 16810243},
775
  {355, 1}, {356, 16810499}, {357, 1}, {358, 16810755},
776
  {359, 1}, {360, 16811011}, {361, 1}, {362, 16811267},
777
  {363, 1}, {364, 16811523}, {365, 1}, {366, 16811779},
778
  {367, 1}, {368, 16812035}, {369, 1}, {370, 16812291},
779
  {371, 1}, {372, 16812547}, {373, 1}, {374, 16812803},
780
  {375, 1}, {376, 16813059}, {377, 16813315}, {378, 1},
781
  {379, 16813571}, {380, 1}, {381, 16813827}, {382, 1},
782
  {383, 16781827}, {384, 1}, {385, 16814083}, {386, 16814339},
783
  {387, 1}, {388, 16814595}, {389, 1}, {390, 16814851},
784
  {391, 16815107}, {392, 1}, {393, 16815363}, {394, 16815619},
785
  {395, 16815875}, {396, 1}, {398, 16816131}, {399, 16816387},
786
  {400, 16816643}, {401, 16816899}, {402, 1}, {403, 16817155},
787
  {404, 16817411}, {405, 1}, {406, 16817667}, {407, 16817923},
788
  {408, 16818179}, {409, 1}, {412, 16818435}, {413, 16818691},
789
  {414, 1}, {415, 16818947}, {416, 16819203}, {417, 1},
790
  {418, 16819459}, {419, 1}, {420, 16819715}, {421, 1},
791
  {422, 16819971}, {423, 16820227}, {424, 1}, {425, 16820483},
792
  {426, 1}, {428, 16820739}, {429, 1}, {430, 16820995},
793
  {431, 16821251}, {432, 1}, {433, 16821507}, {434, 16821763},
794
  {435, 16822019}, {436, 1}, {437, 16822275}, {438, 1},
795
  {439, 16822531}, {440, 16822787}, {441, 1}, {444, 16823043},
796
  {445, 1}, {452, 33600515}, {455, 33601027}, {458, 33601539},
797
  {461, 16824835}, {462, 1}, {463, 16825091}, {464, 1},
798
  {465, 16825347}, {466, 1}, {467, 16825603}, {468, 1},
799
  {469, 16825859}, {470, 1}, {471, 16826115}, {472, 1},
800
  {473, 16826371}, {474, 1}, {475, 16826627}, {476, 1},
801
  {478, 16826883}, {479, 1}, {480, 16827139}, {481, 1},
802
  {482, 16827395}, {483, 1}, {484, 16827651}, {485, 1},
803
  {486, 16827907}, {487, 1}, {488, 16828163}, {489, 1},
804
  {490, 16828419}, {491, 1}, {492, 16828675}, {493, 1},
805
  {494, 16828931}, {495, 1}, {497, 33606403}, {500, 16829699},
806
  {501, 1}, {502, 16829955}, {503, 16830211}, {504, 16830467},
807
  {505, 1}, {506, 16830723}, {507, 1}, {508, 16830979},
808
  {509, 1}, {510, 16831235}, {511, 1}, {512, 16831491},
809
  {513, 1}, {514, 16831747}, {515, 1}, {516, 16832003},
810
  {517, 1}, {518, 16832259}, {519, 1}, {520, 16832515},
811
  {521, 1}, {522, 16832771}, {523, 1}, {524, 16833027},
812
  {525, 1}, {526, 16833283}, {527, 1}, {528, 16833539},
813
  {529, 1}, {530, 16833795}, {531, 1}, {532, 16834051},
814
  {533, 1}, {534, 16834307}, {535, 1}, {536, 16834563},
815
  {537, 1}, {538, 16834819}, {539, 1}, {540, 16835075},
816
  {541, 1}, {542, 16835331}, {543, 1}, {544, 16835587},
817
  {545, 1}, {546, 16835843}, {547, 1}, {548, 16836099},
818
  {549, 1}, {550, 16836355}, {551, 1}, {552, 16836611},
819
  {553, 1}, {554, 16836867}, {555, 1}, {556, 16837123},
820
  {557, 1}, {558, 16837379}, {559, 1}, {560, 16837635},
821
  {561, 1}, {562, 16837891}, {563, 1}, {570, 16838147},
822
  {571, 16838403}, {572, 1}, {573, 16838659}, {574, 16838915},
823
  {575, 1}, {577, 16839171}, {578, 1}, {579, 16839427},
824
  {580, 16839683}, {581, 16839939}, {582, 16840195}, {583, 1},
825
  {584, 16840451}, {585, 1}, {586, 16840707}, {587, 1},
826
  {588, 16840963}, {589, 1}, {590, 16841219}, {591, 1},
827
  {688, 16779011}, {689, 16841475}, {690, 16779523}, {691, 16781571},
828
  {692, 16841731}, {693, 16841987}, {694, 16842243}, {695, 16782851},
829
  {696, 16783363}, {697, 1}, {728, 33619715}, {729, 33620227},
830
  {730, 33620739}, {731, 33621251}, {732, 33621763}, {733, 33622275},
831
  {734, 1}, {736, 16817411}, {737, 16780035}, {738, 16781827},
832
  {739, 16783107}, {740, 16845571}, {741, 1}, {832, 16845827},
833
  {833, 16785923}, {834, 1}, {835, 16846083}, {836, 33623555},
834
  {837, 16846851}, {838, 1}, {847, 0}, {848, 1},
835
  {880, 16847107}, {881, 1}, {882, 16847363}, {883, 1},
836
  {884, 16847619}, {885, 1}, {886, 16847875}, {887, 1},
837
  {888, 2}, {890, 33625347}, {891, 1}, {894, 16848643},
838
  {895, 16848899}, {896, 2}, {900, 33562883}, {901, 50403587},
839
  {902, 16849923}, {903, 16805379}, {904, 16850179}, {905, 16850435},
840
  {906, 16850691}, {907, 2}, {908, 16850947}, {909, 2},
841
  {910, 16851203}, {911, 16851459}, {912, 1}, {913, 16851715},
842
  {914, 16851971}, {915, 16852227}, {916, 16852483}, {917, 16852739},
843
  {918, 16852995}, {919, 16853251}, {920, 16853507}, {921, 16846851},
844
  {922, 16853763}, {923, 16854019}, {924, 16786179}, {925, 16854275},
845
  {926, 16854531}, {927, 16854787}, {928, 16855043}, {929, 16855299},
846
  {930, 2}, {931, 16855555}, {932, 16855811}, {933, 16856067},
847
  {934, 16856323}, {935, 16856579}, {936, 16856835}, {937, 16857091},
848
  {938, 16857347}, {939, 16857603}, {940, 1}, {975, 16857859},
849
  {976, 16851971}, {977, 16853507}, {978, 16856067}, {979, 16851203},
850
  {980, 16857603}, {981, 16856323}, {982, 16855043}, {983, 1},
851
  {984, 16858115}, {985, 1}, {986, 16858371}, {987, 1},
852
  {988, 16858627}, {989, 1}, {990, 16858883}, {991, 1},
853
  {992, 16859139}, {993, 1}, {994, 16859395}, {995, 1},
854
  {996, 16859651}, {997, 1}, {998, 16859907}, {999, 1},
855
  {1000, 16860163}, {1001, 1}, {1002, 16860419}, {1003, 1},
856
  {1004, 16860675}, {1005, 1}, {1006, 16860931}, {1007, 1},
857
  {1008, 16853763}, {1009, 16855299}, {1010, 16855555}, {1011, 1},
858
  {1012, 16853507}, {1013, 16852739}, {1014, 1}, {1015, 16861187},
859
  {1016, 1}, {1017, 16855555}, {1018, 16861443}, {1019, 1},
860
  {1021, 16861699}, {1022, 16861955}, {1023, 16862211}, {1024, 16862467},
861
  {1025, 16862723}, {1026, 16862979}, {1027, 16863235}, {1028, 16863491},
862
  {1029, 16863747}, {1030, 16864003}, {1031, 16864259}, {1032, 16864515},
863
  {1033, 16864771}, {1034, 16865027}, {1035, 16865283}, {1036, 16865539},
864
  {1037, 16865795}, {1038, 16866051}, {1039, 16866307}, {1040, 16866563},
865
  {1041, 16866819}, {1042, 16867075}, {1043, 16867331}, {1044, 16867587},
866
  {1045, 16867843}, {1046, 16868099}, {1047, 16868355}, {1048, 16868611},
867
  {1049, 16868867}, {1050, 16869123}, {1051, 16869379}, {1052, 16869635},
868
  {1053, 16869891}, {1054, 16870147}, {1055, 16870403}, {1056, 16870659},
869
  {1057, 16870915}, {1058, 16871171}, {1059, 16871427}, {1060, 16871683},
870
  {1061, 16871939}, {1062, 16872195}, {1063, 16872451}, {1064, 16872707},
871
  {1065, 16872963}, {1066, 16873219}, {1067, 16873475}, {1068, 16873731},
872
  {1069, 16873987}, {1070, 16874243}, {1071, 16874499}, {1072, 1},
873
  {1120, 16874755}, {1121, 1}, {1122, 16875011}, {1123, 1},
874
  {1124, 16875267}, {1125, 1}, {1126, 16875523}, {1127, 1},
875
  {1128, 16875779}, {1129, 1}, {1130, 16876035}, {1131, 1},
876
  {1132, 16876291}, {1133, 1}, {1134, 16876547}, {1135, 1},
877
  {1136, 16876803}, {1137, 1}, {1138, 16877059}, {1139, 1},
878
  {1140, 16877315}, {1141, 1}, {1142, 16877571}, {1143, 1},
879
  {1144, 16877827}, {1145, 1}, {1146, 16878083}, {1147, 1},
880
  {1148, 16878339}, {1149, 1}, {1150, 16878595}, {1151, 1},
881
  {1152, 16878851}, {1153, 1}, {1162, 16879107}, {1163, 1},
882
  {1164, 16879363}, {1165, 1}, {1166, 16879619}, {1167, 1},
883
  {1168, 16879875}, {1169, 1}, {1170, 16880131}, {1171, 1},
884
  {1172, 16880387}, {1173, 1}, {1174, 16880643}, {1175, 1},
885
  {1176, 16880899}, {1177, 1}, {1178, 16881155}, {1179, 1},
886
  {1180, 16881411}, {1181, 1}, {1182, 16881667}, {1183, 1},
887
  {1184, 16881923}, {1185, 1}, {1186, 16882179}, {1187, 1},
888
  {1188, 16882435}, {1189, 1}, {1190, 16882691}, {1191, 1},
889
  {1192, 16882947}, {1193, 1}, {1194, 16883203}, {1195, 1},
890
  {1196, 16883459}, {1197, 1}, {1198, 16883715}, {1199, 1},
891
  {1200, 16883971}, {1201, 1}, {1202, 16884227}, {1203, 1},
892
  {1204, 16884483}, {1205, 1}, {1206, 16884739}, {1207, 1},
893
  {1208, 16884995}, {1209, 1}, {1210, 16885251}, {1211, 1},
894
  {1212, 16885507}, {1213, 1}, {1214, 16885763}, {1215, 1},
895
  {1216, 16886019}, {1217, 16886275}, {1218, 1}, {1219, 16886531},
896
  {1220, 1}, {1221, 16886787}, {1222, 1}, {1223, 16887043},
897
  {1224, 1}, {1225, 16887299}, {1226, 1}, {1227, 16887555},
898
  {1228, 1}, {1229, 16887811}, {1230, 1}, {1232, 16888067},
899
  {1233, 1}, {1234, 16888323}, {1235, 1}, {1236, 16888579},
900
  {1237, 1}, {1238, 16888835}, {1239, 1}, {1240, 16889091},
901
  {1241, 1}, {1242, 16889347}, {1243, 1}, {1244, 16889603},
902
  {1245, 1}, {1246, 16889859}, {1247, 1}, {1248, 16890115},
903
  {1249, 1}, {1250, 16890371}, {1251, 1}, {1252, 16890627},
904
  {1253, 1}, {1254, 16890883}, {1255, 1}, {1256, 16891139},
905
  {1257, 1}, {1258, 16891395}, {1259, 1}, {1260, 16891651},
906
  {1261, 1}, {1262, 16891907}, {1263, 1}, {1264, 16892163},
907
  {1265, 1}, {1266, 16892419}, {1267, 1}, {1268, 16892675},
908
  {1269, 1}, {1270, 16892931}, {1271, 1}, {1272, 16893187},
909
  {1273, 1}, {1274, 16893443}, {1275, 1}, {1276, 16893699},
910
  {1277, 1}, {1278, 16893955}, {1279, 1}, {1280, 16894211},
911
  {1281, 1}, {1282, 16894467}, {1283, 1}, {1284, 16894723},
912
  {1285, 1}, {1286, 16894979}, {1287, 1}, {1288, 16895235},
913
  {1289, 1}, {1290, 16895491}, {1291, 1}, {1292, 16895747},
914
  {1293, 1}, {1294, 16896003}, {1295, 1}, {1296, 16896259},
915
  {1297, 1}, {1298, 16896515}, {1299, 1}, {1300, 16896771},
916
  {1301, 1}, {1302, 16897027}, {1303, 1}, {1304, 16897283},
917
  {1305, 1}, {1306, 16897539}, {1307, 1}, {1308, 16897795},
918
  {1309, 1}, {1310, 16898051}, {1311, 1}, {1312, 16898307},
919
  {1313, 1}, {1314, 16898563}, {1315, 1}, {1316, 16898819},
920
  {1317, 1}, {1318, 16899075}, {1319, 1}, {1320, 16899331},
921
  {1321, 1}, {1322, 16899587}, {1323, 1}, {1324, 16899843},
922
  {1325, 1}, {1326, 16900099}, {1327, 1}, {1328, 2},
923
  {1329, 16900355}, {1330, 16900611}, {1331, 16900867}, {1332, 16901123},
924
  {1333, 16901379}, {1334, 16901635}, {1335, 16901891}, {1336, 16902147},
925
  {1337, 16902403}, {1338, 16902659}, {1339, 16902915}, {1340, 16903171},
926
  {1341, 16903427}, {1342, 16903683}, {1343, 16903939}, {1344, 16904195},
927
  {1345, 16904451}, {1346, 16904707}, {1347, 16904963}, {1348, 16905219},
928
  {1349, 16905475}, {1350, 16905731}, {1351, 16905987}, {1352, 16906243},
929
  {1353, 16906499}, {1354, 16906755}, {1355, 16907011}, {1356, 16907267},
930
  {1357, 16907523}, {1358, 16907779}, {1359, 16908035}, {1360, 16908291},
931
  {1361, 16908547}, {1362, 16908803}, {1363, 16909059}, {1364, 16909315},
932
  {1365, 16909571}, {1366, 16909827}, {1367, 2}, {1369, 1},
933
  {1415, 33687299}, {1416, 1}, {1419, 2}, {1421, 1},
934
  {1424, 2}, {1425, 1}, {1480, 2}, {1488, 1},
935
  {1515, 2}, {1519, 1}, {1525, 2}, {1542, 1},
936
  {1564, 2}, {1565, 1}, {1653, 33687811}, {1654, 33688323},
937
  {1655, 33688835}, {1656, 33689347}, {1657, 1}, {1757, 2},
938
  {1758, 1}, {1806, 2}, {1808, 1}, {1867, 2},
939
  {1869, 1}, {1970, 2}, {1984, 1}, {2043, 2},
940
  {2045, 1}, {2094, 2}, {2096, 1}, {2111, 2},
941
  {2112, 1}, {2140, 2}, {2142, 1}, {2143, 2},
942
  {2144, 1}, {2155, 2}, {2160, 1}, {2191, 2},
943
  {2199, 1}, {2274, 2}, {2275, 1}, {2392, 33689859},
944
  {2393, 33690371}, {2394, 33690883}, {2395, 33691395}, {2396, 33691907},
945
  {2397, 33692419}, {2398, 33692931}, {2399, 33693443}, {2400, 1},
946
  {2436, 2}, {2437, 1}, {2445, 2}, {2447, 1},
947
  {2449, 2}, {2451, 1}, {2473, 2}, {2474, 1},
948
  {2481, 2}, {2482, 1}, {2483, 2}, {2486, 1},
949
  {2490, 2}, {2492, 1}, {2501, 2}, {2503, 1},
950
  {2505, 2}, {2507, 1}, {2511, 2}, {2519, 1},
951
  {2520, 2}, {2524, 33693955}, {2525, 33694467}, {2526, 2},
952
  {2527, 33694979}, {2528, 1}, {2532, 2}, {2534, 1},
953
  {2559, 2}, {2561, 1}, {2564, 2}, {2565, 1},
954
  {2571, 2}, {2575, 1}, {2577, 2}, {2579, 1},
955
  {2601, 2}, {2602, 1}, {2609, 2}, {2610, 1},
956
  {2611, 33695491}, {2612, 2}, {2613, 1}, {2614, 33696003},
957
  {2615, 2}, {2616, 1}, {2618, 2}, {2620, 1},
958
  {2621, 2}, {2622, 1}, {2627, 2}, {2631, 1},
959
  {2633, 2}, {2635, 1}, {2638, 2}, {2641, 1},
960
  {2642, 2}, {2649, 33696515}, {2650, 33697027}, {2651, 33697539},
961
  {2652, 1}, {2653, 2}, {2654, 33698051}, {2655, 2},
962
  {2662, 1}, {2679, 2}, {2689, 1}, {2692, 2},
963
  {2693, 1}, {2702, 2}, {2703, 1}, {2706, 2},
964
  {2707, 1}, {2729, 2}, {2730, 1}, {2737, 2},
965
  {2738, 1}, {2740, 2}, {2741, 1}, {2746, 2},
966
  {2748, 1}, {2758, 2}, {2759, 1}, {2762, 2},
967
  {2763, 1}, {2766, 2}, {2768, 1}, {2769, 2},
968
  {2784, 1}, {2788, 2}, {2790, 1}, {2802, 2},
969
  {2809, 1}, {2816, 2}, {2817, 1}, {2820, 2},
970
  {2821, 1}, {2829, 2}, {2831, 1}, {2833, 2},
971
  {2835, 1}, {2857, 2}, {2858, 1}, {2865, 2},
972
  {2866, 1}, {2868, 2}, {2869, 1}, {2874, 2},
973
  {2876, 1}, {2885, 2}, {2887, 1}, {2889, 2},
974
  {2891, 1}, {2894, 2}, {2901, 1}, {2904, 2},
975
  {2908, 33698563}, {2909, 33699075}, {2910, 2}, {2911, 1},
976
  {2916, 2}, {2918, 1}, {2936, 2}, {2946, 1},
977
  {2948, 2}, {2949, 1}, {2955, 2}, {2958, 1},
978
  {2961, 2}, {2962, 1}, {2966, 2}, {2969, 1},
979
  {2971, 2}, {2972, 1}, {2973, 2}, {2974, 1},
980
  {2976, 2}, {2979, 1}, {2981, 2}, {2984, 1},
981
  {2987, 2}, {2990, 1}, {3002, 2}, {3006, 1},
982
  {3011, 2}, {3014, 1}, {3017, 2}, {3018, 1},
983
  {3022, 2}, {3024, 1}, {3025, 2}, {3031, 1},
984
  {3032, 2}, {3046, 1}, {3067, 2}, {3072, 1},
985
  {3085, 2}, {3086, 1}, {3089, 2}, {3090, 1},
986
  {3113, 2}, {3114, 1}, {3130, 2}, {3132, 1},
987
  {3141, 2}, {3142, 1}, {3145, 2}, {3146, 1},
988
  {3150, 2}, {3157, 1}, {3159, 2}, {3160, 1},
989
  {3163, 2}, {3165, 1}, {3166, 2}, {3168, 1},
990
  {3172, 2}, {3174, 1}, {3184, 2}, {3191, 1},
991
  {3213, 2}, {3214, 1}, {3217, 2}, {3218, 1},
992
  {3241, 2}, {3242, 1}, {3252, 2}, {3253, 1},
993
  {3258, 2}, {3260, 1}, {3269, 2}, {3270, 1},
994
  {3273, 2}, {3274, 1}, {3278, 2}, {3285, 1},
995
  {3287, 2}, {3293, 1}, {3295, 2}, {3296, 1},
996
  {3300, 2}, {3302, 1}, {3312, 2}, {3313, 1},
997
  {3316, 2}, {3328, 1}, {3341, 2}, {3342, 1},
998
  {3345, 2}, {3346, 1}, {3397, 2}, {3398, 1},
999
  {3401, 2}, {3402, 1}, {3408, 2}, {3412, 1},
1000
  {3428, 2}, {3430, 1}, {3456, 2}, {3457, 1},
1001
  {3460, 2}, {3461, 1}, {3479, 2}, {3482, 1},
1002
  {3506, 2}, {3507, 1}, {3516, 2}, {3517, 1},
1003
  {3518, 2}, {3520, 1}, {3527, 2}, {3530, 1},
1004
  {3531, 2}, {3535, 1}, {3541, 2}, {3542, 1},
1005
  {3543, 2}, {3544, 1}, {3552, 2}, {3558, 1},
1006
  {3568, 2}, {3570, 1}, {3573, 2}, {3585, 1},
1007
  {3635, 33699587}, {3636, 1}, {3643, 2}, {3647, 1},
1008
  {3676, 2}, {3713, 1}, {3715, 2}, {3716, 1},
1009
  {3717, 2}, {3718, 1}, {3723, 2}, {3724, 1},
1010
  {3748, 2}, {3749, 1}, {3750, 2}, {3751, 1},
1011
  {3763, 33700099}, {3764, 1}, {3774, 2}, {3776, 1},
1012
  {3781, 2}, {3782, 1}, {3783, 2}, {3784, 1},
1013
  {3791, 2}, {3792, 1}, {3802, 2}, {3804, 33700611},
1014
  {3805, 33701123}, {3806, 1}, {3808, 2}, {3840, 1},
1015
  {3852, 16924419}, {3853, 1}, {3907, 33701891}, {3908, 1},
1016
  {3912, 2}, {3913, 1}, {3917, 33702403}, {3918, 1},
1017
  {3922, 33702915}, {3923, 1}, {3927, 33703427}, {3928, 1},
1018
  {3932, 33703939}, {3933, 1}, {3945, 33704451}, {3946, 1},
1019
  {3949, 2}, {3953, 1}, {3955, 33704963}, {3956, 1},
1020
  {3957, 33705475}, {3958, 33705987}, {3959, 50483715}, {3960, 33707267},
1021
  {3961, 50484995}, {3962, 1}, {3969, 33706755}, {3970, 1},
1022
  {3987, 33708547}, {3988, 1}, {3992, 2}, {3993, 1},
1023
  {3997, 33709059}, {3998, 1}, {4002, 33709571}, {4003, 1},
1024
  {4007, 33710083}, {4008, 1}, {4012, 33710595}, {4013, 1},
1025
  {4025, 33711107}, {4026, 1}, {4029, 2}, {4030, 1},
1026
  {4045, 2}, {4046, 1}, {4059, 2}, {4096, 1},
1027
  {4256, 16934403}, {4257, 16934659}, {4258, 16934915}, {4259, 16935171},
1028
  {4260, 16935427}, {4261, 16935683}, {4262, 16935939}, {4263, 16936195},
1029
  {4264, 16936451}, {4265, 16936707}, {4266, 16936963}, {4267, 16937219},
1030
  {4268, 16937475}, {4269, 16937731}, {4270, 16937987}, {4271, 16938243},
1031
  {4272, 16938499}, {4273, 16938755}, {4274, 16939011}, {4275, 16939267},
1032
  {4276, 16939523}, {4277, 16939779}, {4278, 16940035}, {4279, 16940291},
1033
  {4280, 16940547}, {4281, 16940803}, {4282, 16941059}, {4283, 16941315},
1034
  {4284, 16941571}, {4285, 16941827}, {4286, 16942083}, {4287, 16942339},
1035
  {4288, 16942595}, {4289, 16942851}, {4290, 16943107}, {4291, 16943363},
1036
  {4292, 16943619}, {4293, 16943875}, {4294, 2}, {4295, 16944131},
1037
  {4296, 2}, {4301, 16944387}, {4302, 2}, {4304, 1},
1038
  {4348, 16944643}, {4349, 1}, {4447, 0}, {4449, 1},
1039
  {4681, 2}, {4682, 1}, {4686, 2}, {4688, 1},
1040
  {4695, 2}, {4696, 1}, {4697, 2}, {4698, 1},
1041
  {4702, 2}, {4704, 1}, {4745, 2}, {4746, 1},
1042
  {4750, 2}, {4752, 1}, {4785, 2}, {4786, 1},
1043
  {4790, 2}, {4792, 1}, {4799, 2}, {4800, 1},
1044
  {4801, 2}, {4802, 1}, {4806, 2}, {4808, 1},
1045
  {4823, 2}, {4824, 1}, {4881, 2}, {4882, 1},
1046
  {4886, 2}, {4888, 1}, {4955, 2}, {4957, 1},
1047
  {4989, 2}, {4992, 1}, {5018, 2}, {5024, 1},
1048
  {5110, 2}, {5112, 16944899}, {5113, 16945155}, {5114, 16945411},
1049
  {5115, 16945667}, {5116, 16945923}, {5117, 16946179}, {5118, 2},
1050
  {5120, 1}, {5760, 2}, {5761, 1}, {5789, 2},
1051
  {5792, 1}, {5881, 2}, {5888, 1}, {5910, 2},
1052
  {5919, 1}, {5943, 2}, {5952, 1}, {5972, 2},
1053
  {5984, 1}, {5997, 2}, {5998, 1}, {6001, 2},
1054
  {6002, 1}, {6004, 2}, {6016, 1}, {6068, 0},
1055
  {6070, 1}, {6110, 2}, {6112, 1}, {6122, 2},
1056
  {6128, 1}, {6138, 2}, {6144, 1}, {6155, 0},
1057
  {6160, 1}, {6170, 2}, {6176, 1}, {6265, 2},
1058
  {6272, 1}, {6315, 2}, {6320, 1}, {6390, 2},
1059
  {6400, 1}, {6431, 2}, {6432, 1}, {6444, 2},
1060
  {6448, 1}, {6460, 2}, {6464, 1}, {6465, 2},
1061
  {6468, 1}, {6510, 2}, {6512, 1}, {6517, 2},
1062
  {6528, 1}, {6572, 2}, {6576, 1}, {6602, 2},
1063
  {6608, 1}, {6619, 2}, {6622, 1}, {6684, 2},
1064
  {6686, 1}, {6751, 2}, {6752, 1}, {6781, 2},
1065
  {6783, 1}, {6794, 2}, {6800, 1}, {6810, 2},
1066
  {6816, 1}, {6830, 2}, {6832, 1}, {6863, 2},
1067
  {6912, 1}, {6989, 2}, {6990, 1}, {7156, 2},
1068
  {7164, 1}, {7224, 2}, {7227, 1}, {7242, 2},
1069
  {7245, 1}, {7296, 16867075}, {7297, 16867587}, {7298, 16870147},
1070
  {7299, 16870915}, {7300, 16871171}, {7302, 16873219}, {7303, 16875011},
1071
  {7304, 16946435}, {7305, 16946691}, {7306, 1}, {7307, 2},
1072
  {7312, 16946947}, {7313, 16947203}, {7314, 16947459}, {7315, 16947715},
1073
  {7316, 16947971}, {7317, 16948227}, {7318, 16948483}, {7319, 16948739},
1074
  {7320, 16948995}, {7321, 16949251}, {7322, 16949507}, {7323, 16949763},
1075
  {7324, 16944643}, {7325, 16950019}, {7326, 16950275}, {7327, 16950531},
1076
  {7328, 16950787}, {7329, 16951043}, {7330, 16951299}, {7331, 16951555},
1077
  {7332, 16951811}, {7333, 16952067}, {7334, 16952323}, {7335, 16952579},
1078
  {7336, 16952835}, {7337, 16953091}, {7338, 16953347}, {7339, 16953603},
1079
  {7340, 16953859}, {7341, 16954115}, {7342, 16954371}, {7343, 16954627},
1080
  {7344, 16954883}, {7345, 16955139}, {7346, 16955395}, {7347, 16955651},
1081
  {7348, 16955907}, {7349, 16956163}, {7350, 16956419}, {7351, 16956675},
1082
  {7352, 16956931}, {7353, 16957187}, {7354, 16957443}, {7355, 2},
1083
  {7357, 16957699}, {7358, 16957955}, {7359, 16958211}, {7360, 1},
1084
  {7368, 2}, {7376, 1}, {7419, 2}, {7424, 1},
1085
  {7468, 16777219}, {7469, 16791043}, {7470, 16777475}, {7471, 1},
1086
  {7472, 16777987}, {7473, 16778243}, {7474, 16816131}, {7475, 16778755},
1087
  {7476, 16779011}, {7477, 16779267}, {7478, 16779523}, {7479, 16779779},
1088
  {7480, 16780035}, {7481, 16780291}, {7482, 16780547}, {7483, 1},
1089
  {7484, 16780803}, {7485, 16835843}, {7486, 16781059}, {7487, 16781571},
1090
  {7488, 16782083}, {7489, 16782339}, {7490, 16782851}, {7491, 16777219},
1091
  {7492, 16958467}, {7493, 16958723}, {7494, 16958979}, {7495, 16777475},
1092
  {7496, 16777987}, {7497, 16778243}, {7498, 16816387}, {7499, 16816643},
1093
  {7500, 16959235}, {7501, 16778755}, {7502, 1}, {7503, 16779779},
1094
  {7504, 16780291}, {7505, 16807171}, {7506, 16780803}, {7507, 16814851},
1095
  {7508, 16959491}, {7509, 16959747}, {7510, 16781059}, {7511, 16782083},
1096
  {7512, 16782339}, {7513, 16960003}, {7514, 16818435}, {7515, 16782595},
1097
  {7516, 16960259}, {7517, 16851971}, {7518, 16852227}, {7519, 16852483},
1098
  {7520, 16856323}, {7521, 16856579}, {7522, 16779267}, {7523, 16781571},
1099
  {7524, 16782339}, {7525, 16782595}, {7526, 16851971}, {7527, 16852227},
1100
  {7528, 16855299}, {7529, 16856323}, {7530, 16856579}, {7531, 1},
1101
  {7544, 16869891}, {7545, 1}, {7579, 16960515}, {7580, 16777731},
1102
  {7581, 16960771}, {7582, 16793603}, {7583, 16959235}, {7584, 16778499},
1103
  {7585, 16961027}, {7586, 16961283}, {7587, 16961539}, {7588, 16817923},
1104
  {7589, 16817667}, {7590, 16961795}, {7591, 16962051}, {7592, 16962307},
1105
  {7593, 16962563}, {7594, 16962819}, {7595, 16963075}, {7596, 16963331},
1106
  {7597, 16963587}, {7598, 16818691}, {7599, 16963843}, {7600, 16964099},
1107
  {7601, 16818947}, {7602, 16964355}, {7603, 16964611}, {7604, 16820483},
1108
  {7605, 16964867}, {7606, 16839683}, {7607, 16821507}, {7608, 16965123},
1109
  {7609, 16821763}, {7610, 16839939}, {7611, 16783619}, {7612, 16965379},
1110
  {7613, 16965635}, {7614, 16822531}, {7615, 16853507}, {7616, 1},
1111
  {7680, 16965891}, {7681, 1}, {7682, 16966147}, {7683, 1},
1112
  {7684, 16966403}, {7685, 1}, {7686, 16966659}, {7687, 1},
1113
  {7688, 16966915}, {7689, 1}, {7690, 16967171}, {7691, 1},
1114
  {7692, 16967427}, {7693, 1}, {7694, 16967683}, {7695, 1},
1115
  {7696, 16967939}, {7697, 1}, {7698, 16968195}, {7699, 1},
1116
  {7700, 16968451}, {7701, 1}, {7702, 16968707}, {7703, 1},
1117
  {7704, 16968963}, {7705, 1}, {7706, 16969219}, {7707, 1},
1118
  {7708, 16969475}, {7709, 1}, {7710, 16969731}, {7711, 1},
1119
  {7712, 16969987}, {7713, 1}, {7714, 16970243}, {7715, 1},
1120
  {7716, 16970499}, {7717, 1}, {7718, 16970755}, {7719, 1},
1121
  {7720, 16971011}, {7721, 1}, {7722, 16971267}, {7723, 1},
1122
  {7724, 16971523}, {7725, 1}, {7726, 16971779}, {7727, 1},
1123
  {7728, 16972035}, {7729, 1}, {7730, 16972291}, {7731, 1},
1124
  {7732, 16972547}, {7733, 1}, {7734, 16972803}, {7735, 1},
1125
  {7736, 16973059}, {7737, 1}, {7738, 16973315}, {7739, 1},
1126
  {7740, 16973571}, {7741, 1}, {7742, 16973827}, {7743, 1},
1127
  {7744, 16974083}, {7745, 1}, {7746, 16974339}, {7747, 1},
1128
  {7748, 16974595}, {7749, 1}, {7750, 16974851}, {7751, 1},
1129
  {7752, 16975107}, {7753, 1}, {7754, 16975363}, {7755, 1},
1130
  {7756, 16975619}, {7757, 1}, {7758, 16975875}, {7759, 1},
1131
  {7760, 16976131}, {7761, 1}, {7762, 16976387}, {7763, 1},
1132
  {7764, 16976643}, {7765, 1}, {7766, 16976899}, {7767, 1},
1133
  {7768, 16977155}, {7769, 1}, {7770, 16977411}, {7771, 1},
1134
  {7772, 16977667}, {7773, 1}, {7774, 16977923}, {7775, 1},
1135
  {7776, 16978179}, {7777, 1}, {7778, 16978435}, {7779, 1},
1136
  {7780, 16978691}, {7781, 1}, {7782, 16978947}, {7783, 1},
1137
  {7784, 16979203}, {7785, 1}, {7786, 16979459}, {7787, 1},
1138
  {7788, 16979715}, {7789, 1}, {7790, 16979971}, {7791, 1},
1139
  {7792, 16980227}, {7793, 1}, {7794, 16980483}, {7795, 1},
1140
  {7796, 16980739}, {7797, 1}, {7798, 16980995}, {7799, 1},
1141
  {7800, 16981251}, {7801, 1}, {7802, 16981507}, {7803, 1},
1142
  {7804, 16981763}, {7805, 1}, {7806, 16982019}, {7807, 1},
1143
  {7808, 16982275}, {7809, 1}, {7810, 16982531}, {7811, 1},
1144
  {7812, 16982787}, {7813, 1}, {7814, 16983043}, {7815, 1},
1145
  {7816, 16983299}, {7817, 1}, {7818, 16983555}, {7819, 1},
1146
  {7820, 16983811}, {7821, 1}, {7822, 16984067}, {7823, 1},
1147
  {7824, 16984323}, {7825, 1}, {7826, 16984579}, {7827, 1},
1148
  {7828, 16984835}, {7829, 1}, {7834, 33762307}, {7835, 16978179},
1149
  {7836, 1}, {7838, 16985603}, {7839, 1}, {7840, 16985859},
1150
  {7841, 1}, {7842, 16986115}, {7843, 1}, {7844, 16986371},
1151
  {7845, 1}, {7846, 16986627}, {7847, 1}, {7848, 16986883},
1152
  {7849, 1}, {7850, 16987139}, {7851, 1}, {7852, 16987395},
1153
  {7853, 1}, {7854, 16987651}, {7855, 1}, {7856, 16987907},
1154
  {7857, 1}, {7858, 16988163}, {7859, 1}, {7860, 16988419},
1155
  {7861, 1}, {7862, 16988675}, {7863, 1}, {7864, 16988931},
1156
  {7865, 1}, {7866, 16989187}, {7867, 1}, {7868, 16989443},
1157
  {7869, 1}, {7870, 16989699}, {7871, 1}, {7872, 16989955},
1158
  {7873, 1}, {7874, 16990211}, {7875, 1}, {7876, 16990467},
1159
  {7877, 1}, {7878, 16990723}, {7879, 1}, {7880, 16990979},
1160
  {7881, 1}, {7882, 16991235}, {7883, 1}, {7884, 16991491},
1161
  {7885, 1}, {7886, 16991747}, {7887, 1}, {7888, 16992003},
1162
  {7889, 1}, {7890, 16992259}, {7891, 1}, {7892, 16992515},
1163
  {7893, 1}, {7894, 16992771}, {7895, 1}, {7896, 16993027},
1164
  {7897, 1}, {7898, 16993283}, {7899, 1}, {7900, 16993539},
1165
  {7901, 1}, {7902, 16993795}, {7903, 1}, {7904, 16994051},
1166
  {7905, 1}, {7906, 16994307}, {7907, 1}, {7908, 16994563},
1167
  {7909, 1}, {7910, 16994819}, {7911, 1}, {7912, 16995075},
1168
  {7913, 1}, {7914, 16995331}, {7915, 1}, {7916, 16995587},
1169
  {7917, 1}, {7918, 16995843}, {7919, 1}, {7920, 16996099},
1170
  {7921, 1}, {7922, 16996355}, {7923, 1}, {7924, 16996611},
1171
  {7925, 1}, {7926, 16996867}, {7927, 1}, {7928, 16997123},
1172
  {7929, 1}, {7930, 16997379}, {7931, 1}, {7932, 16997635},
1173
  {7933, 1}, {7934, 16997891}, {7935, 1}, {7944, 16998147},
1174
  {7945, 16998403}, {7946, 16998659}, {7947, 16998915}, {7948, 16999171},
1175
  {7949, 16999427}, {7950, 16999683}, {7951, 16999939}, {7952, 1},
1176
  {7958, 2}, {7960, 17000195}, {7961, 17000451}, {7962, 17000707},
1177
  {7963, 17000963}, {7964, 17001219}, {7965, 17001475}, {7966, 2},
1178
  {7968, 1}, {7976, 17001731}, {7977, 17001987}, {7978, 17002243},
1179
  {7979, 17002499}, {7980, 17002755}, {7981, 17003011}, {7982, 17003267},
1180
  {7983, 17003523}, {7984, 1}, {7992, 17003779}, {7993, 17004035},
1181
  {7994, 17004291}, {7995, 17004547}, {7996, 17004803}, {7997, 17005059},
1182
  {7998, 17005315}, {7999, 17005571}, {8000, 1}, {8006, 2},
1183
  {8008, 17005827}, {8009, 17006083}, {8010, 17006339}, {8011, 17006595},
1184
  {8012, 17006851}, {8013, 17007107}, {8014, 2}, {8016, 1},
1185
  {8024, 2}, {8025, 17007363}, {8026, 2}, {8027, 17007619},
1186
  {8028, 2}, {8029, 17007875}, {8030, 2}, {8031, 17008131},
1187
  {8032, 1}, {8040, 17008387}, {8041, 17008643}, {8042, 17008899},
1188
  {8043, 17009155}, {8044, 17009411}, {8045, 17009667}, {8046, 17009923},
1189
  {8047, 17010179}, {8048, 1}, {8049, 16849923}, {8050, 1},
1190
  {8051, 16850179}, {8052, 1}, {8053, 16850435}, {8054, 1},
1191
  {8055, 16850691}, {8056, 1}, {8057, 16850947}, {8058, 1},
1192
  {8059, 16851203}, {8060, 1}, {8061, 16851459}, {8062, 2},
1193
  {8064, 33787651}, {8065, 33788163}, {8066, 33788675}, {8067, 33789187},
1194
  {8068, 33789699}, {8069, 33790211}, {8070, 33790723}, {8071, 33791235},
1195
  {8072, 33787651}, {8073, 33788163}, {8074, 33788675}, {8075, 33789187},
1196
  {8076, 33789699}, {8077, 33790211}, {8078, 33790723}, {8079, 33791235},
1197
  {8080, 33791747}, {8081, 33792259}, {8082, 33792771}, {8083, 33793283},
1198
  {8084, 33793795}, {8085, 33794307}, {8086, 33794819}, {8087, 33795331},
1199
  {8088, 33791747}, {8089, 33792259}, {8090, 33792771}, {8091, 33793283},
1200
  {8092, 33793795}, {8093, 33794307}, {8094, 33794819}, {8095, 33795331},
1201
  {8096, 33795843}, {8097, 33796355}, {8098, 33796867}, {8099, 33797379},
1202
  {8100, 33797891}, {8101, 33798403}, {8102, 33798915}, {8103, 33799427},
1203
  {8104, 33795843}, {8105, 33796355}, {8106, 33796867}, {8107, 33797379},
1204
  {8108, 33797891}, {8109, 33798403}, {8110, 33798915}, {8111, 33799427},
1205
  {8112, 1}, {8114, 33799939}, {8115, 33800451}, {8116, 33800963},
1206
  {8117, 2}, {8118, 1}, {8119, 33801475}, {8120, 17024771},
1207
  {8121, 17025027}, {8122, 17022723}, {8123, 16849923}, {8124, 33800451},
1208
  {8125, 33802499}, {8126, 16846851}, {8127, 33802499}, {8128, 33803011},
1209
  {8129, 50580739}, {8130, 33804291}, {8131, 33804803}, {8132, 33805315},
1210
  {8133, 2}, {8134, 1}, {8135, 33805827}, {8136, 17029123},
1211
  {8137, 16850179}, {8138, 17027075}, {8139, 16850435}, {8140, 33804803},
1212
  {8141, 50583811}, {8142, 50584579}, {8143, 50585347}, {8144, 1},
1213
  {8147, 17031683}, {8148, 2}, {8150, 1}, {8152, 17031939},
1214
  {8153, 17032195}, {8154, 17032451}, {8155, 16850691}, {8156, 2},
1215
  {8157, 50587139}, {8158, 50587907}, {8159, 50588675}, {8160, 1},
1216
  {8163, 17035011}, {8164, 1}, {8168, 17035267}, {8169, 17035523},
1217
  {8170, 17035779}, {8171, 16851203}, {8172, 17036035}, {8173, 50590723},
1218
  {8174, 50403587}, {8175, 17037059}, {8176, 2}, {8178, 33814531},
1219
  {8179, 33815043}, {8180, 33815555}, {8181, 2}, {8182, 1},
1220
  {8183, 33816067}, {8184, 17039363}, {8185, 16850947}, {8186, 17037315},
1221
  {8187, 16851459}, {8188, 33815043}, {8189, 33562883}, {8190, 33809923},
1222
  {8191, 2}, {8192, 16783875}, {8203, 0}, {8204, 1},
1223
  {8206, 2}, {8208, 1}, {8209, 17039619}, {8210, 1},
1224
  {8215, 33817091}, {8216, 1}, {8228, 2}, {8231, 1},
1225
  {8232, 2}, {8239, 16783875}, {8240, 1}, {8243, 33817603},
1226
  {8244, 50595331}, {8245, 1}, {8246, 33818883}, {8247, 50596611},
1227
  {8248, 1}, {8252, 33820163}, {8253, 1}, {8254, 33820675},
1228
  {8255, 1}, {8263, 33821187}, {8264, 33821699}, {8265, 33822211},
1229
  {8266, 1}, {8279, 67372035}, {8280, 1}, {8287, 16783875},
1230
  {8288, 0}, {8293, 2}, {8298, 0}, {8304, 17045507},
1231
  {8305, 16779267}, {8306, 2}, {8308, 16787715}, {8309, 17045763},
1232
  {8310, 17046019}, {8311, 17046275}, {8312, 17046531}, {8313, 17046787},
1233
  {8314, 17047043}, {8315, 17047299}, {8316, 17047555}, {8317, 17047811},
1234
  {8318, 17048067}, {8319, 16780547}, {8320, 17045507}, {8321, 16786947},
1235
  {8322, 16785155}, {8323, 16785411}, {8324, 16787715}, {8325, 17045763},
1236
  {8326, 17046019}, {8327, 17046275}, {8328, 17046531}, {8329, 17046787},
1237
  {8330, 17047043}, {8331, 17047299}, {8332, 17047555}, {8333, 17047811},
1238
  {8334, 17048067}, {8335, 2}, {8336, 16777219}, {8337, 16778243},
1239
  {8338, 16780803}, {8339, 16783107}, {8340, 16816387}, {8341, 16779011},
1240
  {8342, 16779779}, {8343, 16780035}, {8344, 16780291}, {8345, 16780547},
1241
  {8346, 16781059}, {8347, 16781827}, {8348, 16782083}, {8349, 2},
1242
  {8352, 1}, {8360, 33558787}, {8361, 1}, {8385, 2},
1243
  {8400, 1}, {8433, 2}, {8448, 50602755}, {8449, 50603523},
1244
  {8450, 16777731}, {8451, 33827075}, {8452, 1}, {8453, 50604803},
1245
  {8454, 50605571}, {8455, 16816643}, {8456, 1}, {8457, 33829123},
1246
  {8458, 16778755}, {8459, 16779011}, {8463, 16802051}, {8464, 16779267},
1247
  {8466, 16780035}, {8468, 1}, {8469, 16780547}, {8470, 33557763},
1248
  {8471, 1}, {8473, 16781059}, {8474, 16781315}, {8475, 16781571},
1249
  {8478, 1}, {8480, 33829635}, {8481, 50607363}, {8482, 33830915},
1250
  {8483, 1}, {8484, 16783619}, {8485, 1}, {8486, 16857091},
1251
  {8487, 1}, {8488, 16783619}, {8489, 1}, {8490, 16779779},
1252
  {8491, 16790787}, {8492, 16777475}, {8493, 16777731}, {8494, 1},
1253
  {8495, 16778243}, {8497, 16778499}, {8498, 17054211}, {8499, 16780291},
1254
  {8500, 16780803}, {8501, 17054467}, {8502, 17054723}, {8503, 17054979},
1255
  {8504, 17055235}, {8505, 16779267}, {8506, 1}, {8507, 50609923},
1256
  {8508, 16855043}, {8509, 16852227}, {8511, 16855043}, {8512, 17056259},
1257
  {8513, 1}, {8517, 16777987}, {8519, 16778243}, {8520, 16779267},
1258
  {8521, 16779523}, {8522, 1}, {8528, 50610947}, {8529, 50611715},
1259
  {8530, 67389699}, {8531, 50613507}, {8532, 50614275}, {8533, 50615043},
1260
  {8534, 50615811}, {8535, 50616579}, {8536, 50617347}, {8537, 50618115},
1261
  {8538, 50618883}, {8539, 50619651}, {8540, 50620419}, {8541, 50621187},
1262
  {8542, 50621955}, {8543, 33564419}, {8544, 16779267}, {8545, 33845507},
1263
  {8546, 50623235}, {8547, 33846787}, {8548, 16782595}, {8549, 33847299},
1264
  {8550, 50625027}, {8551, 67403011}, {8552, 33849603}, {8553, 16783107},
1265
  {8554, 33850115}, {8555, 50627843}, {8556, 16780035}, {8557, 16777731},
1266
  {8558, 16777987}, {8559, 16780291}, {8560, 16779267}, {8561, 33845507},
1267
  {8562, 50622723}, {8563, 33846787}, {8564, 16782595}, {8565, 33847299},
1268
  {8566, 50625027}, {8567, 67403011}, {8568, 33849603}, {8569, 16783107},
1269
  {8570, 33850115}, {8571, 50627843}, {8572, 16780035}, {8573, 16777731},
1270
  {8574, 16777987}, {8575, 16780291}, {8576, 1}, {8579, 17074179},
1271
  {8580, 1}, {8585, 50628867}, {8586, 1}, {8588, 2},
1272
  {8592, 1}, {8748, 33852419}, {8749, 50630147}, {8750, 1},
1273
  {8751, 33853699}, {8752, 50631427}, {8753, 1}, {9001, 17077763},
1274
  {9002, 17078019}, {9003, 1}, {9258, 2}, {9280, 1},
1275
  {9291, 2}, {9312, 16786947}, {9313, 16785155}, {9314, 16785411},
1276
  {9315, 16787715}, {9316, 17045763}, {9317, 17046019}, {9318, 17046275},
1277
  {9319, 17046531}, {9320, 17046787}, {9321, 33835779}, {9322, 33564163},
1278
  {9323, 33855491}, {9324, 33856003}, {9325, 33856515}, {9326, 33857027},
1279
  {9327, 33857539}, {9328, 33858051}, {9329, 33858563}, {9330, 33859075},
1280
  {9331, 33859587}, {9332, 50637315}, {9333, 50638083}, {9334, 50638851},
1281
  {9335, 50639619}, {9336, 50640387}, {9337, 50641155}, {9338, 50641923},
1282
  {9339, 50642691}, {9340, 50643459}, {9341, 67421443}, {9342, 67422467},
1283
  {9343, 67423491}, {9344, 67424515}, {9345, 67425539}, {9346, 67426563},
1284
  {9347, 67427587}, {9348, 67428611}, {9349, 67429635}, {9350, 67430659},
1285
  {9351, 67431683}, {9352, 2}, {9372, 50655491}, {9373, 50656259},
1286
  {9374, 50657027}, {9375, 50657795}, {9376, 50658563}, {9377, 50659331},
1287
  {9378, 50660099}, {9379, 50660867}, {9380, 50661635}, {9381, 50662403},
1288
  {9382, 50663171}, {9383, 50663939}, {9384, 50664707}, {9385, 50665475},
1289
  {9386, 50666243}, {9387, 50667011}, {9388, 50667779}, {9389, 50668547},
1290
  {9390, 50669315}, {9391, 50670083}, {9392, 50670851}, {9393, 50671619},
1291
  {9394, 50672387}, {9395, 50673155}, {9396, 50673923}, {9397, 50674691},
1292
  {9398, 16777219}, {9399, 16777475}, {9400, 16777731}, {9401, 16777987},
1293
  {9402, 16778243}, {9403, 16778499}, {9404, 16778755}, {9405, 16779011},
1294
  {9406, 16779267}, {9407, 16779523}, {9408, 16779779}, {9409, 16780035},
1295
  {9410, 16780291}, {9411, 16780547}, {9412, 16780803}, {9413, 16781059},
1296
  {9414, 16781315}, {9415, 16781571}, {9416, 16781827}, {9417, 16782083},
1297
  {9418, 16782339}, {9419, 16782595}, {9420, 16782851}, {9421, 16783107},
1298
  {9422, 16783363}, {9423, 16783619}, {9424, 16777219}, {9425, 16777475},
1299
  {9426, 16777731}, {9427, 16777987}, {9428, 16778243}, {9429, 16778499},
1300
  {9430, 16778755}, {9431, 16779011}, {9432, 16779267}, {9433, 16779523},
1301
  {9434, 16779779}, {9435, 16780035}, {9436, 16780291}, {9437, 16780547},
1302
  {9438, 16780803}, {9439, 16781059}, {9440, 16781315}, {9441, 16781571},
1303
  {9442, 16781827}, {9443, 16782083}, {9444, 16782339}, {9445, 16782595},
1304
  {9446, 16782851}, {9447, 16783107}, {9448, 16783363}, {9449, 16783619},
1305
  {9450, 17045507}, {9451, 1}, {10764, 67406851}, {10765, 1},
1306
  {10868, 50675459}, {10869, 33899011}, {10870, 50675971}, {10871, 1},
1307
  {10972, 33899523}, {10973, 1}, {11124, 2}, {11126, 1},
1308
  {11158, 2}, {11159, 1}, {11264, 17122819}, {11265, 17123075},
1309
  {11266, 17123331}, {11267, 17123587}, {11268, 17123843}, {11269, 17124099},
1310
  {11270, 17124355}, {11271, 17124611}, {11272, 17124867}, {11273, 17125123},
1311
  {11274, 17125379}, {11275, 17125635}, {11276, 17125891}, {11277, 17126147},
1312
  {11278, 17126403}, {11279, 17126659}, {11280, 17126915}, {11281, 17127171},
1313
  {11282, 17127427}, {11283, 17127683}, {11284, 17127939}, {11285, 17128195},
1314
  {11286, 17128451}, {11287, 17128707}, {11288, 17128963}, {11289, 17129219},
1315
  {11290, 17129475}, {11291, 17129731}, {11292, 17129987}, {11293, 17130243},
1316
  {11294, 17130499}, {11295, 17130755}, {11296, 17131011}, {11297, 17131267},
1317
  {11298, 17131523}, {11299, 17131779}, {11300, 17132035}, {11301, 17132291},
1318
  {11302, 17132547}, {11303, 17132803}, {11304, 17133059}, {11305, 17133315},
1319
  {11306, 17133571}, {11307, 17133827}, {11308, 17134083}, {11309, 17134339},
1320
  {11310, 17134595}, {11311, 17134851}, {11312, 1}, {11360, 17135107},
1321
  {11361, 1}, {11362, 17135363}, {11363, 17135619}, {11364, 17135875},
1322
  {11365, 1}, {11367, 17136131}, {11368, 1}, {11369, 17136387},
1323
  {11370, 1}, {11371, 17136643}, {11372, 1}, {11373, 16958723},
1324
  {11374, 16963331}, {11375, 16958467}, {11376, 16960515}, {11377, 1},
1325
  {11378, 17136899}, {11379, 1}, {11381, 17137155}, {11382, 1},
1326
  {11388, 16779523}, {11389, 16782595}, {11390, 17137411}, {11391, 17137667},
1327
  {11392, 17137923}, {11393, 1}, {11394, 17138179}, {11395, 1},
1328
  {11396, 17138435}, {11397, 1}, {11398, 17138691}, {11399, 1},
1329
  {11400, 17138947}, {11401, 1}, {11402, 17139203}, {11403, 1},
1330
  {11404, 17139459}, {11405, 1}, {11406, 17139715}, {11407, 1},
1331
  {11408, 17139971}, {11409, 1}, {11410, 17140227}, {11411, 1},
1332
  {11412, 17140483}, {11413, 1}, {11414, 17140739}, {11415, 1},
1333
  {11416, 17140995}, {11417, 1}, {11418, 17141251}, {11419, 1},
1334
  {11420, 17141507}, {11421, 1}, {11422, 17141763}, {11423, 1},
1335
  {11424, 17142019}, {11425, 1}, {11426, 17142275}, {11427, 1},
1336
  {11428, 17142531}, {11429, 1}, {11430, 17142787}, {11431, 1},
1337
  {11432, 17143043}, {11433, 1}, {11434, 17143299}, {11435, 1},
1338
  {11436, 17143555}, {11437, 1}, {11438, 17143811}, {11439, 1},
1339
  {11440, 17144067}, {11441, 1}, {11442, 17144323}, {11443, 1},
1340
  {11444, 17144579}, {11445, 1}, {11446, 17144835}, {11447, 1},
1341
  {11448, 17145091}, {11449, 1}, {11450, 17145347}, {11451, 1},
1342
  {11452, 17145603}, {11453, 1}, {11454, 17145859}, {11455, 1},
1343
  {11456, 17146115}, {11457, 1}, {11458, 17146371}, {11459, 1},
1344
  {11460, 17146627}, {11461, 1}, {11462, 17146883}, {11463, 1},
1345
  {11464, 17147139}, {11465, 1}, {11466, 17147395}, {11467, 1},
1346
  {11468, 17147651}, {11469, 1}, {11470, 17147907}, {11471, 1},
1347
  {11472, 17148163}, {11473, 1}, {11474, 17148419}, {11475, 1},
1348
  {11476, 17148675}, {11477, 1}, {11478, 17148931}, {11479, 1},
1349
  {11480, 17149187}, {11481, 1}, {11482, 17149443}, {11483, 1},
1350
  {11484, 17149699}, {11485, 1}, {11486, 17149955}, {11487, 1},
1351
  {11488, 17150211}, {11489, 1}, {11490, 17150467}, {11491, 1},
1352
  {11499, 17150723}, {11500, 1}, {11501, 17150979}, {11502, 1},
1353
  {11506, 17151235}, {11507, 1}, {11508, 2}, {11513, 1},
1354
  {11558, 2}, {11559, 1}, {11560, 2}, {11565, 1},
1355
  {11566, 2}, {11568, 1}, {11624, 2}, {11631, 17151491},
1356
  {11632, 1}, {11633, 2}, {11647, 1}, {11671, 2},
1357
  {11680, 1}, {11687, 2}, {11688, 1}, {11695, 2},
1358
  {11696, 1}, {11703, 2}, {11704, 1}, {11711, 2},
1359
  {11712, 1}, {11719, 2}, {11720, 1}, {11727, 2},
1360
  {11728, 1}, {11735, 2}, {11736, 1}, {11743, 2},
1361
  {11744, 1}, {11870, 2}, {11904, 1}, {11930, 2},
1362
  {11931, 1}, {11935, 17151747}, {11936, 1}, {12019, 17152003},
1363
  {12020, 2}, {12032, 17152259}, {12033, 17152515}, {12034, 17152771},
1364
  {12035, 17153027}, {12036, 17153283}, {12037, 17153539}, {12038, 17153795},
1365
  {12039, 17154051}, {12040, 17154307}, {12041, 17154563}, {12042, 17154819},
1366
  {12043, 17155075}, {12044, 17155331}, {12045, 17155587}, {12046, 17155843},
1367
  {12047, 17156099}, {12048, 17156355}, {12049, 17156611}, {12050, 17156867},
1368
  {12051, 17157123}, {12052, 17157379}, {12053, 17157635}, {12054, 17157891},
1369
  {12055, 17158147}, {12056, 17158403}, {12057, 17158659}, {12058, 17158915},
1370
  {12059, 17159171}, {12060, 17159427}, {12061, 17159683}, {12062, 17159939},
1371
  {12063, 17160195}, {12064, 17160451}, {12065, 17160707}, {12066, 17160963},
1372
  {12067, 17161219}, {12068, 17161475}, {12069, 17161731}, {12070, 17161987},
1373
  {12071, 17162243}, {12072, 17162499}, {12073, 17162755}, {12074, 17163011},
1374
  {12075, 17163267}, {12076, 17163523}, {12077, 17163779}, {12078, 17164035},
1375
  {12079, 17164291}, {12080, 17164547}, {12081, 17164803}, {12082, 17165059},
1376
  {12083, 17165315}, {12084, 17165571}, {12085, 17165827}, {12086, 17166083},
1377
  {12087, 17166339}, {12088, 17166595}, {12089, 17166851}, {12090, 17167107},
1378
  {12091, 17167363}, {12092, 17167619}, {12093, 17167875}, {12094, 17168131},
1379
  {12095, 17168387}, {12096, 17168643}, {12097, 17168899}, {12098, 17169155},
1380
  {12099, 17169411}, {12100, 17169667}, {12101, 17169923}, {12102, 17170179},
1381
  {12103, 17170435}, {12104, 17170691}, {12105, 17170947}, {12106, 17171203},
1382
  {12107, 17171459}, {12108, 17171715}, {12109, 17171971}, {12110, 17172227},
1383
  {12111, 17172483}, {12112, 17172739}, {12113, 17172995}, {12114, 17173251},
1384
  {12115, 17173507}, {12116, 17173763}, {12117, 17174019}, {12118, 17174275},
1385
  {12119, 17174531}, {12120, 17174787}, {12121, 17175043}, {12122, 17175299},
1386
  {12123, 17175555}, {12124, 17175811}, {12125, 17176067}, {12126, 17176323},
1387
  {12127, 17176579}, {12128, 17176835}, {12129, 17177091}, {12130, 17177347},
1388
  {12131, 17177603}, {12132, 17177859}, {12133, 17178115}, {12134, 17178371},
1389
  {12135, 17178627}, {12136, 17178883}, {12137, 17179139}, {12138, 17179395},
1390
  {12139, 17179651}, {12140, 17179907}, {12141, 17180163}, {12142, 17180419},
1391
  {12143, 17180675}, {12144, 17180931}, {12145, 17181187}, {12146, 17181443},
1392
  {12147, 17181699}, {12148, 17181955}, {12149, 17182211}, {12150, 17182467},
1393
  {12151, 17182723}, {12152, 17182979}, {12153, 17183235}, {12154, 17183491},
1394
  {12155, 17183747}, {12156, 17184003}, {12157, 17184259}, {12158, 17184515},
1395
  {12159, 17184771}, {12160, 17185027}, {12161, 17185283}, {12162, 17185539},
1396
  {12163, 17185795}, {12164, 17186051}, {12165, 17186307}, {12166, 17186563},
1397
  {12167, 17186819}, {12168, 17187075}, {12169, 17187331}, {12170, 17187587},
1398
  {12171, 17187843}, {12172, 17188099}, {12173, 17188355}, {12174, 17188611},
1399
  {12175, 17188867}, {12176, 17189123}, {12177, 17189379}, {12178, 17189635},
1400
  {12179, 17189891}, {12180, 17190147}, {12181, 17190403}, {12182, 17190659},
1401
  {12183, 17190915}, {12184, 17191171}, {12185, 17191427}, {12186, 17191683},
1402
  {12187, 17191939}, {12188, 17192195}, {12189, 17192451}, {12190, 17192707},
1403
  {12191, 17192963}, {12192, 17193219}, {12193, 17193475}, {12194, 17193731},
1404
  {12195, 17193987}, {12196, 17194243}, {12197, 17194499}, {12198, 17194755},
1405
  {12199, 17195011}, {12200, 17195267}, {12201, 17195523}, {12202, 17195779},
1406
  {12203, 17196035}, {12204, 17196291}, {12205, 17196547}, {12206, 17196803},
1407
  {12207, 17197059}, {12208, 17197315}, {12209, 17197571}, {12210, 17197827},
1408
  {12211, 17198083}, {12212, 17198339}, {12213, 17198595}, {12214, 17198851},
1409
  {12215, 17199107}, {12216, 17199363}, {12217, 17199619}, {12218, 17199875},
1410
  {12219, 17200131}, {12220, 17200387}, {12221, 17200643}, {12222, 17200899},
1411
  {12223, 17201155}, {12224, 17201411}, {12225, 17201667}, {12226, 17201923},
1412
  {12227, 17202179}, {12228, 17202435}, {12229, 17202691}, {12230, 17202947},
1413
  {12231, 17203203}, {12232, 17203459}, {12233, 17203715}, {12234, 17203971},
1414
  {12235, 17204227}, {12236, 17204483}, {12237, 17204739}, {12238, 17204995},
1415
  {12239, 17205251}, {12240, 17205507}, {12241, 17205763}, {12242, 17206019},
1416
  {12243, 17206275}, {12244, 17206531}, {12245, 17206787}, {12246, 2},
1417
  {12288, 16783875}, {12289, 1}, {12290, 17207043}, {12291, 1},
1418
  {12342, 17207299}, {12343, 1}, {12344, 17158147}, {12345, 17207555},
1419
  {12346, 17207811}, {12347, 1}, {12352, 2}, {12353, 1},
1420
  {12439, 2}, {12441, 1}, {12443, 33985283}, {12444, 33985795},
1421
  {12445, 1}, {12447, 33986307}, {12448, 1}, {12543, 33986819},
1422
  {12544, 2}, {12549, 1}, {12592, 2}, {12593, 17210115},
1423
  {12594, 17210371}, {12595, 17210627}, {12596, 17210883}, {12597, 17211139},
1424
  {12598, 17211395}, {12599, 17211651}, {12600, 17211907}, {12601, 17212163},
1425
  {12602, 17212419}, {12603, 17212675}, {12604, 17212931}, {12605, 17213187},
1426
  {12606, 17213443}, {12607, 17213699}, {12608, 17213955}, {12609, 17214211},
1427
  {12610, 17214467}, {12611, 17214723}, {12612, 17214979}, {12613, 17215235},
1428
  {12614, 17215491}, {12615, 17215747}, {12616, 17216003}, {12617, 17216259},
1429
  {12618, 17216515}, {12619, 17216771}, {12620, 17217027}, {12621, 17217283},
1430
  {12622, 17217539}, {12623, 17217795}, {12624, 17218051}, {12625, 17218307},
1431
  {12626, 17218563}, {12627, 17218819}, {12628, 17219075}, {12629, 17219331},
1432
  {12630, 17219587}, {12631, 17219843}, {12632, 17220099}, {12633, 17220355},
1433
  {12634, 17220611}, {12635, 17220867}, {12636, 17221123}, {12637, 17221379},
1434
  {12638, 17221635}, {12639, 17221891}, {12640, 17222147}, {12641, 17222403},
1435
  {12642, 17222659}, {12643, 17222915}, {12644, 0}, {12645, 17223171},
1436
  {12646, 17223427}, {12647, 17223683}, {12648, 17223939}, {12649, 17224195},
1437
  {12650, 17224451}, {12651, 17224707}, {12652, 17224963}, {12653, 17225219},
1438
  {12654, 17225475}, {12655, 17225731}, {12656, 17225987}, {12657, 17226243},
1439
  {12658, 17226499}, {12659, 17226755}, {12660, 17227011}, {12661, 17227267},
1440
  {12662, 17227523}, {12663, 17227779}, {12664, 17228035}, {12665, 17228291},
1441
  {12666, 17228547}, {12667, 17228803}, {12668, 17229059}, {12669, 17229315},
1442
  {12670, 17229571}, {12671, 17229827}, {12672, 17230083}, {12673, 17230339},
1443
  {12674, 17230595}, {12675, 17230851}, {12676, 17231107}, {12677, 17231363},
1444
  {12678, 17231619}, {12679, 17231875}, {12680, 17232131}, {12681, 17232387},
1445
  {12682, 17232643}, {12683, 17232899}, {12684, 17233155}, {12685, 17233411},
1446
  {12686, 17233667}, {12687, 2}, {12688, 1}, {12690, 17152259},
1447
  {12691, 17153795}, {12692, 17233923}, {12693, 17234179}, {12694, 17234435},
1448
  {12695, 17234691}, {12696, 17234947}, {12697, 17235203}, {12698, 17153283},
1449
  {12699, 17235459}, {12700, 17235715}, {12701, 17235971}, {12702, 17236227},
1450
  {12703, 17154307}, {12704, 1}, {12774, 2}, {12784, 1},
1451
  {12800, 50790915}, {12801, 50791683}, {12802, 50792451}, {12803, 50793219},
1452
  {12804, 50793987}, {12805, 50794755}, {12806, 50795523}, {12807, 50796291},
1453
  {12808, 50797059}, {12809, 50797827}, {12810, 50798595}, {12811, 50799363},
1454
  {12812, 50800131}, {12813, 50800899}, {12814, 50801667}, {12815, 50802435},
1455
  {12816, 50803203}, {12817, 50803971}, {12818, 50804739}, {12819, 50805507},
1456
  {12820, 50806275}, {12821, 50807043}, {12822, 50807811}, {12823, 50808579},
1457
  {12824, 50809347}, {12825, 50810115}, {12826, 50810883}, {12827, 50811651},
1458
  {12828, 50812419}, {12829, 67590403}, {12830, 67591427}, {12831, 2},
1459
  {12832, 50815235}, {12833, 50816003}, {12834, 50816771}, {12835, 50817539},
1460
  {12836, 50818307}, {12837, 50819075}, {12838, 50819843}, {12839, 50820611},
1461
  {12840, 50821379}, {12841, 50822147}, {12842, 50822915}, {12843, 50823683},
1462
  {12844, 50824451}, {12845, 50825219}, {12846, 50825987}, {12847, 50826755},
1463
  {12848, 50827523}, {12849, 50828291}, {12850, 50829059}, {12851, 50829827},
1464
  {12852, 50830595}, {12853, 50831363}, {12854, 50832131}, {12855, 50832899},
1465
  {12856, 50833667}, {12857, 50834435}, {12858, 50835203}, {12859, 50835971},
1466
  {12860, 50836739}, {12861, 50837507}, {12862, 50838275}, {12863, 50839043},
1467
  {12864, 50839811}, {12865, 50840579}, {12866, 50841347}, {12867, 50842115},
1468
  {12868, 17288451}, {12869, 17288707}, {12870, 17169155}, {12871, 17288963},
1469
  {12872, 1}, {12880, 50843651}, {12881, 33855747}, {12882, 34067203},
1470
  {12883, 33562371}, {12884, 34067715}, {12885, 34068227}, {12886, 34068739},
1471
  {12887, 34069251}, {12888, 34069763}, {12889, 34070275}, {12890, 34070787},
1472
  {12891, 33837571}, {12892, 33836803}, {12893, 34071299}, {12894, 34071811},
1473
  {12895, 34072323}, {12896, 17210115}, {12897, 17210883}, {12898, 17211651},
1474
  {12899, 17212163}, {12900, 17214211}, {12901, 17214467}, {12902, 17215235},
1475
  {12903, 17215747}, {12904, 17216003}, {12905, 17216515}, {12906, 17216771},
1476
  {12907, 17217027}, {12908, 17217283}, {12909, 17217539}, {12910, 17247491},
1477
  {12911, 17248259}, {12912, 17249027}, {12913, 17249795}, {12914, 17250563},
1478
  {12915, 17251331}, {12916, 17252099}, {12917, 17252867}, {12918, 17253635},
1479
  {12919, 17254403}, {12920, 17255171}, {12921, 17255939}, {12922, 17256707},
1480
  {12923, 17257475}, {12924, 34072835}, {12925, 34073347}, {12926, 17296643},
1481
  {12927, 1}, {12928, 17152259}, {12929, 17153795}, {12930, 17233923},
1482
  {12931, 17234179}, {12932, 17264131}, {12933, 17264899}, {12934, 17265667},
1483
  {12935, 17155075}, {12936, 17267203}, {12937, 17158147}, {12938, 17170947},
1484
  {12939, 17174019}, {12940, 17173763}, {12941, 17171203}, {12942, 17194755},
1485
  {12943, 17160195}, {12944, 17170435}, {12945, 17274115}, {12946, 17274883},
1486
  {12947, 17275651}, {12948, 17276419}, {12949, 17277187}, {12950, 17277955},
1487
  {12951, 17278723}, {12952, 17279491}, {12953, 17296899}, {12954, 17297155},
1488
  {12955, 17161731}, {12956, 17297411}, {12957, 17297667}, {12958, 17297923},
1489
  {12959, 17298179}, {12960, 17298435}, {12961, 17286403}, {12962, 17298691},
1490
  {12963, 17298947}, {12964, 17234435}, {12965, 17234691}, {12966, 17234947},
1491
  {12967, 17299203}, {12968, 17299459}, {12969, 17299715}, {12970, 17299971},
1492
  {12971, 17281795}, {12972, 17282563}, {12973, 17283331}, {12974, 17284099},
1493
  {12975, 17284867}, {12976, 17300227}, {12977, 34077699}, {12978, 34078211},
1494
  {12979, 34078723}, {12980, 34079235}, {12981, 34079747}, {12982, 33564931},
1495
  {12983, 34067971}, {12984, 34072067}, {12985, 34080259}, {12986, 34080771},
1496
  {12987, 34081283}, {12988, 34081795}, {12989, 34082307}, {12990, 34082819},
1497
  {12991, 34083331}, {12992, 34083843}, {12993, 34084355}, {12994, 34084867},
1498
  {12995, 34085379}, {12996, 34085891}, {12997, 34086403}, {12998, 34086915},
1499
  {12999, 34087427}, {13000, 34087939}, {13001, 50865667}, {13002, 50866435},
1500
  {13003, 50867203}, {13004, 34090755}, {13005, 50868483}, {13006, 34092035},
1501
  {13007, 50869763}, {13008, 17316099}, {13009, 17316355}, {13010, 17316611},
1502
  {13011, 17316867}, {13012, 17317123}, {13013, 17317379}, {13014, 17317635},
1503
  {13015, 17317891}, {13016, 17318147}, {13017, 17209603}, {13018, 17318403},
1504
  {13019, 17318659}, {13020, 17318915}, {13021, 17319171}, {13022, 17319427},
1505
  {13023, 17319683}, {13024, 17319939}, {13025, 17320195}, {13026, 17320451},
1506
  {13027, 17209859}, {13028, 17320707}, {13029, 17320963}, {13030, 17321219},
1507
  {13031, 17321475}, {13032, 17321731}, {13033, 17321987}, {13034, 17322243},
1508
  {13035, 17322499}, {13036, 17322755}, {13037, 17323011}, {13038, 17323267},
1509
  {13039, 17323523}, {13040, 17323779}, {13041, 17324035}, {13042, 17324291},
1510
  {13043, 17324547}, {13044, 17324803}, {13045, 17325059}, {13046, 17325315},
1511
  {13047, 17325571}, {13048, 17325827}, {13049, 17326083}, {13050, 17326339},
1512
  {13051, 17326595}, {13052, 17326851}, {13053, 17327107}, {13054, 17327363},
1513
  {13055, 34104835}, {13056, 67659779}, {13057, 67660803}, {13058, 67661827},
1514
  {13059, 50885635}, {13060, 67663619}, {13061, 50887427}, {13062, 50888195},
1515
  {13063, 84443395}, {13064, 67667459}, {13065, 50891267}, {13066, 50892035},
1516
  {13067, 50892803}, {13068, 67670787}, {13069, 67671811}, {13070, 50895619},
1517
  {13071, 50896387}, {13072, 34119939}, {13073, 50897667}, {13074, 67675651},
1518
  {13075, 67676675}, {13076, 34123267}, {13077, 84455427}, {13078, 101233923},
1519
  {13079, 84458243}, {13080, 50901507}, {13081, 84459523}, {13082, 84460803},
1520
  {13083, 67684867}, {13084, 50908675}, {13085, 50909443}, {13086, 50910211},
1521
  {13087, 67688195}, {13088, 84466435}, {13089, 67690499}, {13090, 50914307},
1522
  {13091, 50915075}, {13092, 50915843}, {13093, 34139395}, {13094, 34139907},
1523
  {13095, 34128643}, {13096, 34140419}, {13097, 50918147}, {13098, 50918915},
1524
  {13099, 84474115}, {13100, 50920963}, {13101, 67698947}, {13102, 84477187},
1525
  {13103, 50924035}, {13104, 34147587}, {13105, 34148099}, {13106, 84480259},
1526
  {13107, 67704323}, {13108, 84482563}, {13109, 50929411}, {13110, 84484611},
1527
  {13111, 34154243}, {13112, 50931971}, {13113, 50932739}, {13114, 50933507},
1528
  {13115, 50934275}, {13116, 50935043}, {13117, 67713027}, {13118, 50936835},
1529
  {13119, 34160387}, {13120, 50938115}, {13121, 50938883}, {13122, 50939651},
1530
  {13123, 67717635}, {13124, 50941443}, {13125, 50942211}, {13126, 50942979},
1531
  {13127, 84498179}, {13128, 67722243}, {13129, 34168835}, {13130, 84500995},
1532
  {13131, 34170627}, {13132, 67725571}, {13133, 67680003}, {13134, 50949379},
1533
  {13135, 50950147}, {13136, 50950915}, {13137, 67728899}, {13138, 34175491},
1534
  {13139, 50953219}, {13140, 67731203}, {13141, 34177795}, {13142, 84509955},
1535
  {13143, 50904323}, {13144, 34179587}, {13145, 34180099}, {13146, 34180611},
1536
  {13147, 34181123}, {13148, 34181635}, {13149, 34182147}, {13150, 34182659},
1537
  {13151, 34183171}, {13152, 34183683}, {13153, 34184195}, {13154, 50961923},
1538
  {13155, 50962691}, {13156, 50963459}, {13157, 50964227}, {13158, 50964995},
1539
  {13159, 50965763}, {13160, 50966531}, {13161, 50967299}, {13162, 50968067},
1540
  {13163, 50968835}, {13164, 50969603}, {13165, 50970371}, {13166, 50971139},
1541
  {13167, 50971907}, {13168, 50972675}, {13169, 50973443}, {13170, 34196995},
1542
  {13171, 34197507}, {13172, 50975235}, {13173, 34198787}, {13174, 34199299},
1543
  {13175, 34199811}, {13176, 50977539}, {13177, 50978307}, {13178, 34201859},
1544
  {13179, 34202371}, {13180, 34202883}, {13181, 34203395}, {13182, 34203907},
1545
  {13183, 67758851}, {13184, 34196483}, {13185, 34205443}, {13186, 34205955},
1546
  {13187, 34206467}, {13188, 34206979}, {13189, 34207491}, {13190, 34208003},
1547
  {13191, 34208515}, {13192, 50986243}, {13193, 67764227}, {13194, 34210819},
1548
  {13195, 34211331}, {13196, 34211843}, {13197, 34212355}, {13198, 34212867},
1549
  {13199, 34213379}, {13200, 34213891}, {13201, 50991619}, {13202, 50992387},
1550
  {13203, 50990851}, {13204, 50993155}, {13205, 34216707}, {13206, 34217219},
1551
  {13207, 34217731}, {13208, 33556995}, {13209, 34218243}, {13210, 34218755},
1552
  {13211, 34219267}, {13212, 34219779}, {13213, 34220291}, {13214, 34220803},
1553
  {13215, 50998531}, {13216, 50999299}, {13217, 34200579}, {13218, 51000067},
1554
  {13219, 51000835}, {13220, 51001603}, {13221, 34201347}, {13222, 51002371},
1555
  {13223, 51003139}, {13224, 67781123}, {13225, 34196483}, {13226, 51004931},
1556
  {13227, 51005699}, {13228, 51006467}, {13229, 51007235}, {13230, 84562435},
1557
  {13231, 101340931}, {13232, 34233603}, {13233, 34234115}, {13234, 34234627},
1558
  {13235, 34235139}, {13236, 34235651}, {13237, 34236163}, {13238, 34236675},
1559
  {13239, 34237187}, {13240, 34237699}, {13241, 34237187}, {13242, 34238211},
1560
  {13243, 34238723}, {13244, 34239235}, {13245, 34239747}, {13246, 34240259},
1561
  {13247, 34239747}, {13248, 34240771}, {13249, 34241283}, {13250, 2},
1562
  {13251, 34241795}, {13252, 33827331}, {13253, 33554947}, {13254, 67796739},
1563
  {13255, 2}, {13256, 34243331}, {13257, 34243843}, {13258, 34244355},
1564
  {13259, 34196227}, {13260, 34244867}, {13261, 34245379}, {13262, 34220803},
1565
  {13263, 34245891}, {13264, 33557251}, {13265, 34246403}, {13266, 51024131},
1566
  {13267, 34247683}, {13268, 34208003}, {13269, 51025411}, {13270, 51026179},
1567
  {13271, 34249731}, {13272, 2}, {13273, 51027459}, {13274, 34251011},
1568
  {13275, 34231811}, {13276, 34251523}, {13277, 34252035}, {13278, 51029763},
1569
  {13279, 51030531}, {13280, 34254083}, {13281, 34254595}, {13282, 34255107},
1570
  {13283, 34255619}, {13284, 34256131}, {13285, 34256643}, {13286, 34257155},
1571
  {13287, 34257667}, {13288, 34258179}, {13289, 51035907}, {13290, 51036675},
1572
  {13291, 51037443}, {13292, 51038211}, {13293, 51038979}, {13294, 51039747},
1573
  {13295, 51040515}, {13296, 51041283}, {13297, 51042051}, {13298, 51042819},
1574
  {13299, 51043587}, {13300, 51044355}, {13301, 51045123}, {13302, 51045891},
1575
  {13303, 51046659}, {13304, 51047427}, {13305, 51048195}, {13306, 51048963},
1576
  {13307, 51049731}, {13308, 51050499}, {13309, 51051267}, {13310, 51052035},
1577
  {13311, 51052803}, {13312, 1}, {42125, 2}, {42128, 1},
1578
  {42183, 2}, {42192, 1}, {42540, 2}, {42560, 17499139},
1579
  {42561, 1}, {42562, 17499395}, {42563, 1}, {42564, 17499651},
1580
  {42565, 1}, {42566, 17499907}, {42567, 1}, {42568, 17500163},
1581
  {42569, 1}, {42570, 16946435}, {42571, 1}, {42572, 17500419},
1582
  {42573, 1}, {42574, 17500675}, {42575, 1}, {42576, 17500931},
1583
  {42577, 1}, {42578, 17501187}, {42579, 1}, {42580, 17501443},
1584
  {42581, 1}, {42582, 17501699}, {42583, 1}, {42584, 17501955},
1585
  {42585, 1}, {42586, 17502211}, {42587, 1}, {42588, 17502467},
1586
  {42589, 1}, {42590, 17502723}, {42591, 1}, {42592, 17502979},
1587
  {42593, 1}, {42594, 17503235}, {42595, 1}, {42596, 17503491},
1588
  {42597, 1}, {42598, 17503747}, {42599, 1}, {42600, 17504003},
1589
  {42601, 1}, {42602, 17504259}, {42603, 1}, {42604, 17504515},
1590
  {42605, 1}, {42624, 17504771}, {42625, 1}, {42626, 17505027},
1591
  {42627, 1}, {42628, 17505283}, {42629, 1}, {42630, 17505539},
1592
  {42631, 1}, {42632, 17505795}, {42633, 1}, {42634, 17506051},
1593
  {42635, 1}, {42636, 17506307}, {42637, 1}, {42638, 17506563},
1594
  {42639, 1}, {42640, 17506819}, {42641, 1}, {42642, 17507075},
1595
  {42643, 1}, {42644, 17507331}, {42645, 1}, {42646, 17507587},
1596
  {42647, 1}, {42648, 17507843}, {42649, 1}, {42650, 17508099},
1597
  {42651, 1}, {42652, 16873219}, {42653, 16873731}, {42654, 1},
1598
  {42744, 2}, {42752, 1}, {42786, 17508355}, {42787, 1},
1599
  {42788, 17508611}, {42789, 1}, {42790, 17508867}, {42791, 1},
1600
  {42792, 17509123}, {42793, 1}, {42794, 17509379}, {42795, 1},
1601
  {42796, 17509635}, {42797, 1}, {42798, 17509891}, {42799, 1},
1602
  {42802, 17510147}, {42803, 1}, {42804, 17510403}, {42805, 1},
1603
  {42806, 17510659}, {42807, 1}, {42808, 17510915}, {42809, 1},
1604
  {42810, 17511171}, {42811, 1}, {42812, 17511427}, {42813, 1},
1605
  {42814, 17511683}, {42815, 1}, {42816, 17511939}, {42817, 1},
1606
  {42818, 17512195}, {42819, 1}, {42820, 17512451}, {42821, 1},
1607
  {42822, 17512707}, {42823, 1}, {42824, 17512963}, {42825, 1},
1608
  {42826, 17513219}, {42827, 1}, {42828, 17513475}, {42829, 1},
1609
  {42830, 17513731}, {42831, 1}, {42832, 17513987}, {42833, 1},
1610
  {42834, 17514243}, {42835, 1}, {42836, 17514499}, {42837, 1},
1611
  {42838, 17514755}, {42839, 1}, {42840, 17515011}, {42841, 1},
1612
  {42842, 17515267}, {42843, 1}, {42844, 17515523}, {42845, 1},
1613
  {42846, 17515779}, {42847, 1}, {42848, 17516035}, {42849, 1},
1614
  {42850, 17516291}, {42851, 1}, {42852, 17516547}, {42853, 1},
1615
  {42854, 17516803}, {42855, 1}, {42856, 17517059}, {42857, 1},
1616
  {42858, 17517315}, {42859, 1}, {42860, 17517571}, {42861, 1},
1617
  {42862, 17517827}, {42863, 1}, {42864, 17517827}, {42865, 1},
1618
  {42873, 17518083}, {42874, 1}, {42875, 17518339}, {42876, 1},
1619
  {42877, 17518595}, {42878, 17518851}, {42879, 1}, {42880, 17519107},
1620
  {42881, 1}, {42882, 17519363}, {42883, 1}, {42884, 17519619},
1621
  {42885, 1}, {42886, 17519875}, {42887, 1}, {42891, 17520131},
1622
  {42892, 1}, {42893, 16961539}, {42894, 1}, {42896, 17520387},
1623
  {42897, 1}, {42898, 17520643}, {42899, 1}, {42902, 17520899},
1624
  {42903, 1}, {42904, 17521155}, {42905, 1}, {42906, 17521411},
1625
  {42907, 1}, {42908, 17521667}, {42909, 1}, {42910, 17521923},
1626
  {42911, 1}, {42912, 17522179}, {42913, 1}, {42914, 17522435},
1627
  {42915, 1}, {42916, 17522691}, {42917, 1}, {42918, 17522947},
1628
  {42919, 1}, {42920, 17523203}, {42921, 1}, {42922, 16841475},
1629
  {42923, 16959235}, {42924, 16961283}, {42925, 17523459}, {42926, 16961795},
1630
  {42927, 1}, {42928, 17523715}, {42929, 17523971}, {42930, 16962307},
1631
  {42931, 17524227}, {42932, 17524483}, {42933, 1}, {42934, 17524739},
1632
  {42935, 1}, {42936, 17524995}, {42937, 1}, {42938, 17525251},
1633
  {42939, 1}, {42940, 17525507}, {42941, 1}, {42942, 17525763},
1634
  {42943, 1}, {42944, 17526019}, {42945, 1}, {42946, 17526275},
1635
  {42947, 1}, {42948, 17526531}, {42949, 16964611}, {42950, 17526787},
1636
  {42951, 17527043}, {42952, 1}, {42953, 17527299}, {42954, 1},
1637
  {42955, 17527555}, {42956, 17527811}, {42957, 1}, {42958, 2},
1638
  {42960, 17528067}, {42961, 1}, {42962, 2}, {42963, 1},
1639
  {42964, 2}, {42965, 1}, {42966, 17528323}, {42967, 1},
1640
  {42968, 17528579}, {42969, 1}, {42970, 17528835}, {42971, 1},
1641
  {42972, 17529091}, {42973, 2}, {42994, 16777731}, {42995, 16778499},
1642
  {42996, 16781315}, {42997, 17529347}, {42998, 1}, {43000, 16802051},
1643
  {43001, 16808195}, {43002, 1}, {43053, 2}, {43056, 1},
1644
  {43066, 2}, {43072, 1}, {43128, 2}, {43136, 1},
1645
  {43206, 2}, {43214, 1}, {43226, 2}, {43232, 1},
1646
  {43348, 2}, {43359, 1}, {43389, 2}, {43392, 1},
1647
  {43470, 2}, {43471, 1}, {43482, 2}, {43486, 1},
1648
  {43519, 2}, {43520, 1}, {43575, 2}, {43584, 1},
1649
  {43598, 2}, {43600, 1}, {43610, 2}, {43612, 1},
1650
  {43715, 2}, {43739, 1}, {43767, 2}, {43777, 1},
1651
  {43783, 2}, {43785, 1}, {43791, 2}, {43793, 1},
1652
  {43799, 2}, {43808, 1}, {43815, 2}, {43816, 1},
1653
  {43823, 2}, {43824, 1}, {43868, 17508867}, {43869, 17529603},
1654
  {43870, 17135363}, {43871, 17529859}, {43872, 1}, {43881, 17530115},
1655
  {43882, 1}, {43884, 2}, {43888, 17530371}, {43889, 17530627},
1656
  {43890, 17530883}, {43891, 17531139}, {43892, 17531395}, {43893, 17531651},
1657
  {43894, 17531907}, {43895, 17532163}, {43896, 17532419}, {43897, 17532675},
1658
  {43898, 17532931}, {43899, 17533187}, {43900, 17533443}, {43901, 17533699},
1659
  {43902, 17533955}, {43903, 17534211}, {43904, 17534467}, {43905, 17534723},
1660
  {43906, 17534979}, {43907, 17535235}, {43908, 17535491}, {43909, 17535747},
1661
  {43910, 17536003}, {43911, 17536259}, {43912, 17536515}, {43913, 17536771},
1662
  {43914, 17537027}, {43915, 17537283}, {43916, 17537539}, {43917, 17537795},
1663
  {43918, 17538051}, {43919, 17538307}, {43920, 17538563}, {43921, 17538819},
1664
  {43922, 17539075}, {43923, 17539331}, {43924, 17539587}, {43925, 17539843},
1665
  {43926, 17540099}, {43927, 17540355}, {43928, 17540611}, {43929, 17540867},
1666
  {43930, 17541123}, {43931, 17541379}, {43932, 17541635}, {43933, 17541891},
1667
  {43934, 17542147}, {43935, 17542403}, {43936, 17542659}, {43937, 17542915},
1668
  {43938, 17543171}, {43939, 17543427}, {43940, 17543683}, {43941, 17543939},
1669
  {43942, 17544195}, {43943, 17544451}, {43944, 17544707}, {43945, 17544963},
1670
  {43946, 17545219}, {43947, 17545475}, {43948, 17545731}, {43949, 17545987},
1671
  {43950, 17546243}, {43951, 17546499}, {43952, 17546755}, {43953, 17547011},
1672
  {43954, 17547267}, {43955, 17547523}, {43956, 17547779}, {43957, 17548035},
1673
  {43958, 17548291}, {43959, 17548547}, {43960, 17548803}, {43961, 17549059},
1674
  {43962, 17549315}, {43963, 17549571}, {43964, 17549827}, {43965, 17550083},
1675
  {43966, 17550339}, {43967, 17550595}, {43968, 1}, {44014, 2},
1676
  {44016, 1}, {44026, 2}, {44032, 1}, {55204, 2},
1677
  {55216, 1}, {55239, 2}, {55243, 1}, {55292, 2},
1678
  {63744, 17550851}, {63745, 17551107}, {63746, 17192707}, {63747, 17551363},
1679
  {63748, 17551619}, {63749, 17551875}, {63750, 17552131}, {63751, 17206531},
1680
  {63753, 17552387}, {63754, 17194755}, {63755, 17552643}, {63756, 17552899},
1681
  {63757, 17553155}, {63758, 17553411}, {63759, 17553667}, {63760, 17553923},
1682
  {63761, 17554179}, {63762, 17554435}, {63763, 17554691}, {63764, 17554947},
1683
  {63765, 17555203}, {63766, 17555459}, {63767, 17555715}, {63768, 17555971},
1684
  {63769, 17556227}, {63770, 17556483}, {63771, 17556739}, {63772, 17556995},
1685
  {63773, 17557251}, {63774, 17557507}, {63775, 17557763}, {63776, 17558019},
1686
  {63777, 17558275}, {63778, 17558531}, {63779, 17558787}, {63780, 17559043},
1687
  {63781, 17559299}, {63782, 17559555}, {63783, 17559811}, {63784, 17560067},
1688
  {63785, 17560323}, {63786, 17560579}, {63787, 17560835}, {63788, 17561091},
1689
  {63789, 17561347}, {63790, 17561603}, {63791, 17561859}, {63792, 17562115},
1690
  {63793, 17562371}, {63794, 17562627}, {63795, 17562883}, {63796, 17184003},
1691
  {63797, 17563139}, {63798, 17563395}, {63799, 17563651}, {63800, 17563907},
1692
  {63801, 17564163}, {63802, 17564419}, {63803, 17564675}, {63804, 17564931},
1693
  {63805, 17565187}, {63806, 17565443}, {63807, 17565699}, {63808, 17202691},
1694
  {63809, 17565955}, {63810, 17566211}, {63811, 17566467}, {63812, 17566723},
1695
  {63813, 17566979}, {63814, 17567235}, {63815, 17567491}, {63816, 17567747},
1696
  {63817, 17568003}, {63818, 17568259}, {63819, 17568515}, {63820, 17568771},
1697
  {63821, 17569027}, {63822, 17569283}, {63823, 17569539}, {63824, 17569795},
1698
  {63825, 17570051}, {63826, 17570307}, {63827, 17570563}, {63828, 17570819},
1699
  {63829, 17571075}, {63830, 17571331}, {63831, 17571587}, {63832, 17571843},
1700
  {63833, 17572099}, {63834, 17572355}, {63835, 17572611}, {63836, 17554947},
1701
  {63837, 17572867}, {63838, 17573123}, {63839, 17573379}, {63840, 17573635},
1702
  {63841, 17573891}, {63842, 17574147}, {63843, 17574403}, {63844, 17574659},
1703
  {63845, 17574915}, {63846, 17575171}, {63847, 17575427}, {63848, 17575683},
1704
  {63849, 17575939}, {63850, 17576195}, {63851, 17576451}, {63852, 17576707},
1705
  {63853, 17576963}, {63854, 17577219}, {63855, 17577475}, {63856, 17577731},
1706
  {63857, 17193219}, {63858, 17577987}, {63859, 17578243}, {63860, 17578499},
1707
  {63861, 17578755}, {63862, 17579011}, {63863, 17579267}, {63864, 17579523},
1708
  {63865, 17579779}, {63866, 17580035}, {63867, 17580291}, {63868, 17580547},
1709
  {63869, 17580803}, {63870, 17581059}, {63871, 17581315}, {63872, 17581571},
1710
  {63873, 17161731}, {63874, 17581827}, {63875, 17582083}, {63876, 17582339},
1711
  {63877, 17582595}, {63878, 17582851}, {63879, 17583107}, {63880, 17583363},
1712
  {63881, 17583619}, {63882, 17156867}, {63883, 17583875}, {63884, 17584131},
1713
  {63885, 17584387}, {63886, 17584643}, {63887, 17584899}, {63888, 17585155},
1714
  {63889, 17585411}, {63890, 17585667}, {63891, 17585923}, {63892, 17586179},
1715
  {63893, 17586435}, {63894, 17586691}, {63895, 17586947}, {63896, 17587203},
1716
  {63897, 17587459}, {63898, 17587715}, {63899, 17587971}, {63900, 17588227},
1717
  {63901, 17588483}, {63902, 17588739}, {63903, 17588995}, {63904, 17589251},
1718
  {63905, 17577475}, {63906, 17589507}, {63907, 17589763}, {63908, 17590019},
1719
  {63909, 17590275}, {63910, 17590531}, {63911, 17590787}, {63912, 17327619},
1720
  {63913, 17591043}, {63914, 17573379}, {63915, 17591299}, {63916, 17591555},
1721
  {63917, 17591811}, {63918, 17592067}, {63919, 17592323}, {63920, 17592579},
1722
  {63921, 17592835}, {63922, 17593091}, {63923, 17593347}, {63924, 17593603},
1723
  {63925, 17593859}, {63926, 17594115}, {63927, 17594371}, {63928, 17594627},
1724
  {63929, 17594883}, {63930, 17595139}, {63931, 17595395}, {63932, 17595651},
1725
  {63933, 17595907}, {63934, 17596163}, {63935, 17554947}, {63936, 17596419},
1726
  {63937, 17596675}, {63938, 17596931}, {63939, 17597187}, {63940, 17206275},
1727
  {63941, 17597443}, {63942, 17597699}, {63943, 17597955}, {63944, 17598211},
1728
  {63945, 17598467}, {63946, 17598723}, {63947, 17598979}, {63948, 17599235},
1729
  {63949, 17599491}, {63950, 17599747}, {63951, 17600003}, {63952, 17600259},
1730
  {63953, 17264899}, {63954, 17600515}, {63955, 17600771}, {63956, 17601027},
1731
  {63957, 17601283}, {63958, 17601539}, {63959, 17601795}, {63960, 17602051},
1732
  {63961, 17602307}, {63962, 17602563}, {63963, 17573891}, {63964, 17602819},
1733
  {63965, 17603075}, {63966, 17603331}, {63967, 17603587}, {63968, 17603843},
1734
  {63969, 17604099}, {63970, 17604355}, {63971, 17604611}, {63972, 17604867},
1735
  {63973, 17605123}, {63974, 17605379}, {63975, 17605635}, {63976, 17605891},
1736
  {63977, 17194499}, {63978, 17606147}, {63979, 17606403}, {63980, 17606659},
1737
  {63981, 17606915}, {63982, 17607171}, {63983, 17607427}, {63984, 17607683},
1738
  {63985, 17607939}, {63986, 17608195}, {63987, 17608451}, {63988, 17608707},
1739
  {63989, 17608963}, {63990, 17609219}, {63991, 17181955}, {63992, 17609475},
1740
  {63993, 17609731}, {63994, 17609987}, {63995, 17610243}, {63996, 17610499},
1741
  {63997, 17610755}, {63998, 17611011}, {63999, 17611267}, {64000, 17611523},
1742
  {64001, 17611779}, {64002, 17612035}, {64003, 17612291}, {64004, 17612547},
1743
  {64005, 17612803}, {64006, 17613059}, {64007, 17613315}, {64008, 17188867},
1744
  {64009, 17613571}, {64010, 17189635}, {64011, 17613827}, {64012, 17614083},
1745
  {64013, 17614339}, {64014, 1}, {64016, 17614595}, {64017, 1},
1746
  {64018, 17614851}, {64019, 1}, {64021, 17615107}, {64022, 17615363},
1747
  {64023, 17615619}, {64024, 17615875}, {64025, 17616131}, {64026, 17616387},
1748
  {64027, 17616643}, {64028, 17616899}, {64029, 17617155}, {64030, 17183747},
1749
  {64031, 1}, {64032, 17617411}, {64033, 1}, {64034, 17617667},
1750
  {64035, 1}, {64037, 17617923}, {64038, 17618179}, {64039, 1},
1751
  {64042, 17618435}, {64043, 17618691}, {64044, 17618947}, {64045, 17619203},
1752
  {64046, 17619459}, {64047, 17619715}, {64048, 17619971}, {64049, 17620227},
1753
  {64050, 17620483}, {64051, 17620739}, {64052, 17620995}, {64053, 17621251},
1754
  {64054, 17621507}, {64055, 17621763}, {64056, 17622019}, {64057, 17622275},
1755
  {64058, 17622531}, {64059, 17622787}, {64060, 17163523}, {64061, 17623043},
1756
  {64062, 17623299}, {64063, 17623555}, {64064, 17623811}, {64065, 17624067},
1757
  {64066, 17624323}, {64067, 17624579}, {64068, 17624835}, {64069, 17625091},
1758
  {64070, 17625347}, {64071, 17625603}, {64072, 17625859}, {64073, 17626115},
1759
  {64074, 17626371}, {64075, 17626627}, {64076, 17275651}, {64077, 17626883},
1760
  {64078, 17627139}, {64079, 17627395}, {64080, 17627651}, {64081, 17278723},
1761
  {64082, 17627907}, {64083, 17628163}, {64084, 17628419}, {64085, 17628675},
1762
  {64086, 17628931}, {64087, 17586691}, {64088, 17629187}, {64089, 17629443},
1763
  {64090, 17629699}, {64091, 17629955}, {64092, 17630211}, {64093, 17630467},
1764
  {64095, 17630723}, {64096, 17630979}, {64097, 17631235}, {64098, 17631491},
1765
  {64099, 17631747}, {64100, 17632003}, {64101, 17632259}, {64102, 17632515},
1766
  {64103, 17617923}, {64104, 17632771}, {64105, 17633027}, {64106, 17633283},
1767
  {64107, 17633539}, {64108, 17633795}, {64109, 17634051}, {64110, 2},
1768
  {64112, 17634307}, {64113, 17634563}, {64114, 17634819}, {64115, 17635075},
1769
  {64116, 17635331}, {64117, 17635587}, {64118, 17635843}, {64119, 17636099},
1770
  {64120, 17621507}, {64121, 17636355}, {64122, 17636611}, {64123, 17636867},
1771
  {64124, 17614595}, {64125, 17637123}, {64126, 17637379}, {64127, 17637635},
1772
  {64128, 17637891}, {64129, 17638147}, {64130, 17638403}, {64131, 17638659},
1773
  {64132, 17638915}, {64133, 17639171}, {64134, 17639427}, {64135, 17639683},
1774
  {64136, 17639939}, {64137, 17623555}, {64138, 17640195}, {64139, 17623811},
1775
  {64140, 17640451}, {64141, 17640707}, {64142, 17640963}, {64143, 17641219},
1776
  {64144, 17641475}, {64145, 17614851}, {64146, 17560323}, {64147, 17641731},
1777
  {64148, 17641987}, {64149, 17171971}, {64150, 17577731}, {64151, 17598723},
1778
  {64152, 17642243}, {64153, 17642499}, {64154, 17625603}, {64155, 17642755},
1779
  {64156, 17625859}, {64157, 17643011}, {64158, 17643267}, {64159, 17643523},
1780
  {64160, 17615363}, {64161, 17643779}, {64162, 17644035}, {64163, 17644291},
1781
  {64164, 17644547}, {64165, 17644803}, {64166, 17615619}, {64167, 17645059},
1782
  {64168, 17645315}, {64169, 17645571}, {64170, 17645827}, {64171, 17646083},
1783
  {64172, 17646339}, {64173, 17628931}, {64174, 17646595}, {64175, 17646851},
1784
  {64176, 17586691}, {64177, 17647107}, {64178, 17629955}, {64179, 17647363},
1785
  {64180, 17647619}, {64181, 17647875}, {64182, 17648131}, {64183, 17648387},
1786
  {64184, 17631235}, {64185, 17648643}, {64186, 17617667}, {64187, 17648899},
1787
  {64188, 17631491}, {64189, 17572867}, {64190, 17649155}, {64191, 17631747},
1788
  {64192, 17649411}, {64193, 17632259}, {64194, 17649667}, {64195, 17649923},
1789
  {64196, 17650179}, {64197, 17650435}, {64198, 17650691}, {64199, 17632771},
1790
  {64200, 17616899}, {64201, 17650947}, {64202, 17633027}, {64203, 17651203},
1791
  {64204, 17633283}, {64205, 17651459}, {64206, 17206531}, {64207, 17651715},
1792
  {64208, 17651971}, {64209, 17652227}, {64210, 17652483}, {64211, 17652739},
1793
  {64212, 17652995}, {64213, 17653251}, {64214, 17653507}, {64215, 17653763},
1794
  {64216, 17654019}, {64217, 17654275}, {64218, 2}, {64256, 34431747},
1795
  {64257, 34432259}, {64258, 34432771}, {64259, 51209219}, {64260, 51210499},
1796
  {64261, 33559043}, {64263, 2}, {64275, 34434051}, {64276, 34434563},
1797
  {64277, 34435075}, {64278, 34435587}, {64279, 34436099}, {64280, 2},
1798
  {64285, 34436611}, {64286, 1}, {64287, 34437123}, {64288, 17660419},
1799
  {64289, 17054467}, {64290, 17055235}, {64291, 17660675}, {64292, 17660931},
1800
  {64293, 17661187}, {64294, 17661443}, {64295, 17661699}, {64296, 17661955},
1801
  {64297, 17047043}, {64298, 34439427}, {64299, 34439939}, {64300, 51217667},
1802
  {64301, 51218435}, {64302, 34441987}, {64303, 34442499}, {64304, 34443011},
1803
  {64305, 34443523}, {64306, 34444035}, {64307, 34444547}, {64308, 34445059},
1804
  {64309, 34445571}, {64310, 34446083}, {64311, 2}, {64312, 34446595},
1805
  {64313, 34447107}, {64314, 34447619}, {64315, 34448131}, {64316, 34448643},
1806
  {64317, 2}, {64318, 34449155}, {64319, 2}, {64320, 34449667},
1807
  {64321, 34450179}, {64322, 2}, {64323, 34450691}, {64324, 34451203},
1808
  {64325, 2}, {64326, 34451715}, {64327, 34452227}, {64328, 34452739},
1809
  {64329, 34440451}, {64330, 34453251}, {64331, 34453763}, {64332, 34454275},
1810
  {64333, 34454787}, {64334, 34455299}, {64335, 34455811}, {64336, 17679107},
1811
  {64338, 17679363}, {64342, 17679619}, {64346, 17679875}, {64350, 17680131},
1812
  {64354, 17680387}, {64358, 17680643}, {64362, 17680899}, {64366, 17681155},
1813
  {64370, 17681411}, {64374, 17681667}, {64378, 17681923}, {64382, 17682179},
1814
  {64386, 17682435}, {64388, 17682691}, {64390, 17682947}, {64392, 17683203},
1815
  {64394, 17683459}, {64396, 17683715}, {64398, 17683971}, {64402, 17684227},
1816
  {64406, 17684483}, {64410, 17684739}, {64414, 17684995}, {64416, 17685251},
1817
  {64420, 17685507}, {64422, 17685763}, {64426, 17686019}, {64430, 17686275},
1818
  {64432, 17686531}, {64434, 1}, {64451, 2}, {64467, 17686787},
1819
  {64471, 16911619}, {64473, 17687043}, {64475, 17687299}, {64477, 33688835},
1820
  {64478, 17687555}, {64480, 17687811}, {64482, 17688067}, {64484, 17688323},
1821
  {64488, 17688579}, {64490, 34466051}, {64492, 34466563}, {64494, 34467075},
1822
  {64496, 34467587}, {64498, 34468099}, {64500, 34468611}, {64502, 34469123},
1823
  {64505, 34469635}, {64508, 17692931}, {64512, 34470403}, {64513, 34470915},
1824
  {64514, 34471427}, {64515, 34469635}, {64516, 34471939}, {64517, 34472451},
1825
  {64518, 34472963}, {64519, 34473475}, {64520, 34473987}, {64521, 34474499},
1826
  {64522, 34475011}, {64523, 34475523}, {64524, 34476035}, {64525, 34476547},
1827
  {64526, 34477059}, {64527, 34477571}, {64528, 34478083}, {64529, 34478595},
1828
  {64530, 34479107}, {64531, 34479619}, {64532, 34480131}, {64533, 34480643},
1829
  {64534, 34481155}, {64535, 34480899}, {64536, 34481667}, {64537, 34482179},
1830
  {64538, 34482691}, {64539, 34483203}, {64540, 34483715}, {64541, 34484227},
1831
  {64542, 34484739}, {64543, 34485251}, {64544, 34485763}, {64545, 34486275},
1832
  {64546, 34486787}, {64547, 34487299}, {64548, 34487811}, {64549, 34488323},
1833
  {64550, 34488835}, {64551, 34489347}, {64552, 34489859}, {64553, 34490371},
1834
  {64554, 34490883}, {64555, 34491395}, {64556, 34491907}, {64557, 34492419},
1835
  {64558, 34492931}, {64559, 34493443}, {64560, 34493955}, {64561, 34494467},
1836
  {64562, 34494979}, {64563, 34495491}, {64564, 34496003}, {64565, 34496515},
1837
  {64566, 34497027}, {64567, 34497539}, {64568, 34498051}, {64569, 34498563},
1838
  {64570, 34499075}, {64571, 34499587}, {64572, 34500099}, {64573, 34500611},
1839
  {64574, 34501123}, {64575, 34501635}, {64576, 34502147}, {64577, 34502659},
1840
  {64578, 34503171}, {64579, 34503683}, {64580, 34504195}, {64581, 34504707},
1841
  {64582, 34481411}, {64583, 34481923}, {64584, 34505219}, {64585, 34505731},
1842
  {64586, 34506243}, {64587, 34506755}, {64588, 34507267}, {64589, 34507779},
1843
  {64590, 34508291}, {64591, 34508803}, {64592, 34509315}, {64593, 34509827},
1844
  {64594, 34510339}, {64595, 34510851}, {64596, 34511363}, {64597, 34480387},
1845
  {64598, 34511875}, {64599, 34512387}, {64600, 34504451}, {64601, 34512899},
1846
  {64602, 34511619}, {64603, 34513411}, {64604, 34513923}, {64605, 34514435},
1847
  {64606, 51292163}, {64607, 51292931}, {64608, 51293699}, {64609, 51294467},
1848
  {64610, 51295235}, {64611, 51296003}, {64612, 34519555}, {64613, 34520067},
1849
  {64614, 34471427}, {64615, 34520579}, {64616, 34469635}, {64617, 34471939},
1850
  {64618, 34521091}, {64619, 34521603}, {64620, 34473987}, {64621, 34522115},
1851
  {64622, 34474499}, {64623, 34475011}, {64624, 34522627}, {64625, 34523139},
1852
  {64626, 34477059}, {64627, 34523651}, {64628, 34477571}, {64629, 34478083},
1853
  {64630, 34524163}, {64631, 34524675}, {64632, 34479107}, {64633, 34525187},
1854
  {64634, 34479619}, {64635, 34480131}, {64636, 34494467}, {64637, 34494979},
1855
  {64638, 34496515}, {64639, 34497027}, {64640, 34497539}, {64641, 34499587},
1856
  {64642, 34500099}, {64643, 34500611}, {64644, 34501123}, {64645, 34503171},
1857
  {64646, 34503683}, {64647, 34504195}, {64648, 34525699}, {64649, 34505219},
1858
  {64650, 34526211}, {64651, 34526723}, {64652, 34508291}, {64653, 34527235},
1859
  {64654, 34508803}, {64655, 34509315}, {64656, 34514435}, {64657, 34527747},
1860
  {64658, 34528259}, {64659, 34504451}, {64660, 34506499}, {64661, 34512899},
1861
  {64662, 34511619}, {64663, 34470403}, {64664, 34470915}, {64665, 34528771},
1862
  {64666, 34471427}, {64667, 34529283}, {64668, 34472451}, {64669, 34472963},
1863
  {64670, 34473475}, {64671, 34473987}, {64672, 34529795}, {64673, 34475523},
1864
  {64674, 34476035}, {64675, 34476547}, {64676, 34477059}, {64677, 34530307},
1865
  {64678, 34479107}, {64679, 34480643}, {64680, 34481155}, {64681, 34480899},
1866
  {64682, 34481667}, {64683, 34482179}, {64684, 34483203}, {64685, 34483715},
1867
  {64686, 34484227}, {64687, 34484739}, {64688, 34485251}, {64689, 34485763},
1868
  {64690, 34530819}, {64691, 34486275}, {64692, 34486787}, {64693, 34487299},
1869
  {64694, 34487811}, {64695, 34488323}, {64696, 34488835}, {64697, 34489859},
1870
  {64698, 34490371}, {64699, 34490883}, {64700, 34491395}, {64701, 34491907},
1871
  {64702, 34492419}, {64703, 34492931}, {64704, 34493443}, {64705, 34493955},
1872
  {64706, 34495491}, {64707, 34496003}, {64708, 34498051}, {64709, 34498563},
1873
  {64710, 34499075}, {64711, 34499587}, {64712, 34500099}, {64713, 34501635},
1874
  {64714, 34502147}, {64715, 34502659}, {64716, 34503171}, {64717, 34531331},
1875
  {64718, 34504707}, {64719, 34481411}, {64720, 34481923}, {64721, 34505219},
1876
  {64722, 34506755}, {64723, 34507267}, {64724, 34507779}, {64725, 34508291},
1877
  {64726, 34531843}, {64727, 34509827}, {64728, 34510339}, {64729, 34532355},
1878
  {64730, 34480387}, {64731, 34511875}, {64732, 34512387}, {64733, 34504451},
1879
  {64734, 34509571}, {64735, 34471427}, {64736, 34529283}, {64737, 34473987},
1880
  {64738, 34529795}, {64739, 34477059}, {64740, 34530307}, {64741, 34479107},
1881
  {64742, 34532867}, {64743, 34485251}, {64744, 34533379}, {64745, 34533891},
1882
  {64746, 34534403}, {64747, 34499587}, {64748, 34500099}, {64749, 34503171},
1883
  {64750, 34508291}, {64751, 34531843}, {64752, 34504451}, {64753, 34509571},
1884
  {64754, 51312131}, {64755, 51312899}, {64756, 51313667}, {64757, 34537219},
1885
  {64758, 34537731}, {64759, 34538243}, {64760, 34538755}, {64761, 34539267},
1886
  {64762, 34539779}, {64763, 34540291}, {64764, 34540803}, {64765, 34541315},
1887
  {64766, 34541827}, {64767, 34542339}, {64768, 34512131}, {64769, 34542851},
1888
  {64770, 34543363}, {64771, 34543875}, {64772, 34512643}, {64773, 34544387},
1889
  {64774, 34544899}, {64775, 34545411}, {64776, 34545923}, {64777, 34546435},
1890
  {64778, 34546947}, {64779, 34547459}, {64780, 34533891}, {64781, 34547971},
1891
  {64782, 34548483}, {64783, 34548995}, {64784, 34549507}, {64785, 34537219},
1892
  {64786, 34537731}, {64787, 34538243}, {64788, 34538755}, {64789, 34539267},
1893
  {64790, 34539779}, {64791, 34540291}, {64792, 34540803}, {64793, 34541315},
1894
  {64794, 34541827}, {64795, 34542339}, {64796, 34512131}, {64797, 34542851},
1895
  {64798, 34543363}, {64799, 34543875}, {64800, 34512643}, {64801, 34544387},
1896
  {64802, 34544899}, {64803, 34545411}, {64804, 34545923}, {64805, 34546435},
1897
  {64806, 34546947}, {64807, 34547459}, {64808, 34533891}, {64809, 34547971},
1898
  {64810, 34548483}, {64811, 34548995}, {64812, 34549507}, {64813, 34546435},
1899
  {64814, 34546947}, {64815, 34547459}, {64816, 34533891}, {64817, 34533379},
1900
  {64818, 34534403}, {64819, 34489347}, {64820, 34483715}, {64821, 34484227},
1901
  {64822, 34484739}, {64823, 34546435}, {64824, 34546947}, {64825, 34547459},
1902
  {64826, 34489347}, {64827, 34489859}, {64828, 34550019}, {64830, 1},
1903
  {64848, 51327747}, {64849, 51328515}, {64851, 51329283}, {64852, 51330051},
1904
  {64853, 51330819}, {64854, 51331587}, {64855, 51332355}, {64856, 51258371},
1905
  {64858, 51333123}, {64859, 51333891}, {64860, 51334659}, {64861, 51335427},
1906
  {64862, 51336195}, {64863, 51336963}, {64865, 51337731}, {64866, 51338499},
1907
  {64868, 51339267}, {64870, 51340035}, {64871, 51340803}, {64873, 51341571},
1908
  {64874, 51342339}, {64876, 51343107}, {64878, 51343875}, {64879, 51344643},
1909
  {64881, 51345411}, {64883, 51346179}, {64884, 51346947}, {64885, 51347715},
1910
  {64886, 51348483}, {64888, 51349251}, {64889, 51350019}, {64890, 51350787},
1911
  {64891, 51351555}, {64892, 51352323}, {64894, 51353091}, {64895, 51353859},
1912
  {64896, 51354627}, {64897, 51355395}, {64898, 51356163}, {64899, 51356931},
1913
  {64901, 51357699}, {64903, 51358467}, {64905, 51359235}, {64906, 51258627},
1914
  {64907, 51360003}, {64908, 51360771}, {64909, 51281923}, {64910, 51259139},
1915
  {64911, 51361539}, {64912, 2}, {64914, 51362307}, {64915, 51363075},
1916
  {64916, 51363843}, {64917, 51364611}, {64918, 51365379}, {64919, 51366147},
1917
  {64921, 51366915}, {64922, 51367683}, {64923, 51368451}, {64924, 51369219},
1918
  {64926, 51369987}, {64927, 51370755}, {64928, 51371523}, {64929, 51372291},
1919
  {64930, 51373059}, {64931, 51373827}, {64932, 51374595}, {64933, 51375363},
1920
  {64934, 51376131}, {64935, 51376899}, {64936, 51377667}, {64937, 51378435},
1921
  {64938, 51379203}, {64939, 51379971}, {64940, 51380739}, {64941, 51381507},
1922
  {64942, 51289091}, {64943, 51382275}, {64944, 51383043}, {64945, 51383811},
1923
  {64946, 51384579}, {64947, 51385347}, {64948, 51353091}, {64949, 51354627},
1924
  {64950, 51386115}, {64951, 51386883}, {64952, 51387651}, {64953, 51388419},
1925
  {64954, 51389187}, {64955, 51389955}, {64956, 51389187}, {64957, 51387651},
1926
  {64958, 51390723}, {64959, 51391491}, {64960, 51392259}, {64961, 51393027},
1927
  {64962, 51393795}, {64963, 51389955}, {64964, 51347715}, {64965, 51340035},
1928
  {64966, 51394563}, {64967, 51395331}, {64968, 2}, {64975, 1},
1929
  {64976, 2}, {65008, 51396099}, {65009, 51396867}, {65010, 68174851},
1930
  {65011, 68175875}, {65012, 68176899}, {65013, 68177923}, {65014, 68178947},
1931
  {65015, 68179971}, {65016, 68180995}, {65017, 51404803}, {65018, 303063811},
1932
  {65019, 135296259}, {65020, 68189443}, {65021, 1}, {65024, 0},
1933
  {65040, 17858819}, {65041, 17859075}, {65042, 2}, {65043, 17121027},
1934
  {65044, 16848643}, {65045, 17042947}, {65046, 17043971}, {65047, 17859331},
1935
  {65048, 17859587}, {65049, 2}, {65056, 1}, {65072, 2},
1936
  {65073, 17859843}, {65074, 17860099}, {65075, 17860355}, {65077, 17047811},
1937
  {65078, 17048067}, {65079, 17860611}, {65080, 17860867}, {65081, 17861123},
1938
  {65082, 17861379}, {65083, 17861635}, {65084, 17861891}, {65085, 17862147},
1939
  {65086, 17862403}, {65087, 17077763}, {65088, 17078019}, {65089, 17862659},
1940
  {65090, 17862915}, {65091, 17863171}, {65092, 17863427}, {65093, 1},
1941
  {65095, 17863683}, {65096, 17863939}, {65097, 33820675}, {65101, 17860355},
1942
  {65104, 17858819}, {65105, 17859075}, {65106, 2}, {65108, 16848643},
1943
  {65109, 17121027}, {65110, 17043971}, {65111, 17042947}, {65112, 17859843},
1944
  {65113, 17047811}, {65114, 17048067}, {65115, 17860611}, {65116, 17860867},
1945
  {65117, 17861123}, {65118, 17861379}, {65119, 17864195}, {65120, 17864451},
1946
  {65121, 17864707}, {65122, 17047043}, {65123, 17864963}, {65124, 17865219},
1947
  {65125, 17865475}, {65126, 17047555}, {65127, 2}, {65128, 17865731},
1948
  {65129, 17865987}, {65130, 17866243}, {65131, 17866499}, {65132, 2},
1949
  {65136, 34643971}, {65137, 34644483}, {65138, 34514947}, {65139, 1},
1950
  {65140, 34515715}, {65141, 2}, {65142, 34516483}, {65143, 34534915},
1951
  {65144, 34517251}, {65145, 34535683}, {65146, 34518019}, {65147, 34536451},
1952
  {65148, 34518787}, {65149, 34644995}, {65150, 34645507}, {65151, 34646019},
1953
  {65152, 17869315}, {65153, 17869571}, {65155, 17869827}, {65157, 17870083},
1954
  {65159, 17870339}, {65161, 17688835}, {65165, 16910595}, {65167, 17695235},
1955
  {65171, 17870595}, {65173, 17698307}, {65177, 17701379}, {65181, 17693443},
1956
  {65185, 17693955}, {65189, 17696515}, {65193, 17846019}, {65195, 17736195},
1957
  {65197, 17736707}, {65199, 17743107}, {65201, 17706499}, {65205, 17756675},
1958
  {65209, 17708547}, {65213, 17709571}, {65217, 17711619}, {65221, 17712643},
1959
  {65225, 17713155}, {65229, 17714179}, {65233, 17715203}, {65237, 17718275},
1960
  {65241, 17720323}, {65245, 17722627}, {65249, 17694467}, {65253, 17729539},
1961
  {65257, 17732611}, {65261, 16911107}, {65263, 17688579}, {65265, 16912131},
1962
  {65269, 34648067}, {65271, 34648579}, {65273, 34649091}, {65275, 34633987},
1963
  {65277, 2}, {65279, 0}, {65280, 2}, {65281, 17042947},
1964
  {65282, 17872387}, {65283, 17864195}, {65284, 17865987}, {65285, 17866243},
1965
  {65286, 17864451}, {65287, 17872643}, {65288, 17047811}, {65289, 17048067},
1966
  {65290, 17864707}, {65291, 17047043}, {65292, 17858819}, {65293, 17864963},
1967
  {65294, 17207043}, {65295, 17048579}, {65296, 17045507}, {65297, 16786947},
1968
  {65298, 16785155}, {65299, 16785411}, {65300, 16787715}, {65301, 17045763},
1969
  {65302, 17046019}, {65303, 17046275}, {65304, 17046531}, {65305, 17046787},
1970
  {65306, 17121027}, {65307, 16848643}, {65308, 17865219}, {65309, 17047555},
1971
  {65310, 17865475}, {65311, 17043971}, {65312, 17866499}, {65313, 16777219},
1972
  {65314, 16777475}, {65315, 16777731}, {65316, 16777987}, {65317, 16778243},
1973
  {65318, 16778499}, {65319, 16778755}, {65320, 16779011}, {65321, 16779267},
1974
  {65322, 16779523}, {65323, 16779779}, {65324, 16780035}, {65325, 16780291},
1975
  {65326, 16780547}, {65327, 16780803}, {65328, 16781059}, {65329, 16781315},
1976
  {65330, 16781571}, {65331, 16781827}, {65332, 16782083}, {65333, 16782339},
1977
  {65334, 16782595}, {65335, 16782851}, {65336, 16783107}, {65337, 16783363},
1978
  {65338, 16783619}, {65339, 17863683}, {65340, 17865731}, {65341, 17863939},
1979
  {65342, 17872899}, {65343, 17860355}, {65344, 17037059}, {65345, 16777219},
1980
  {65346, 16777475}, {65347, 16777731}, {65348, 16777987}, {65349, 16778243},
1981
  {65350, 16778499}, {65351, 16778755}, {65352, 16779011}, {65353, 16779267},
1982
  {65354, 16779523}, {65355, 16779779}, {65356, 16780035}, {65357, 16780291},
1983
  {65358, 16780547}, {65359, 16780803}, {65360, 16781059}, {65361, 16781315},
1984
  {65362, 16781571}, {65363, 16781827}, {65364, 16782083}, {65365, 16782339},
1985
  {65366, 16782595}, {65367, 16782851}, {65368, 16783107}, {65369, 16783363},
1986
  {65370, 16783619}, {65371, 17860611}, {65372, 17873155}, {65373, 17860867},
1987
  {65374, 17873411}, {65375, 17873667}, {65376, 17873923}, {65377, 17207043},
1988
  {65378, 17862659}, {65379, 17862915}, {65380, 17859075}, {65381, 17874179},
1989
  {65382, 17327363}, {65383, 17329923}, {65384, 17372931}, {65385, 17874435},
1990
  {65386, 17374467}, {65387, 17334019}, {65388, 17874691}, {65389, 17344259},
1991
  {65390, 17390083}, {65391, 17339651}, {65392, 17328643}, {65393, 17316099},
1992
  {65394, 17316355}, {65395, 17316611}, {65396, 17316867}, {65397, 17317123},
1993
  {65398, 17317379}, {65399, 17317635}, {65400, 17317891}, {65401, 17318147},
1994
  {65402, 17209603}, {65403, 17318403}, {65404, 17318659}, {65405, 17318915},
1995
  {65406, 17319171}, {65407, 17319427}, {65408, 17319683}, {65409, 17319939},
1996
  {65410, 17320195}, {65411, 17320451}, {65412, 17209859}, {65413, 17320707},
1997
  {65414, 17320963}, {65415, 17321219}, {65416, 17321475}, {65417, 17321731},
1998
  {65418, 17321987}, {65419, 17322243}, {65420, 17322499}, {65421, 17322755},
1999
  {65422, 17323011}, {65423, 17323267}, {65424, 17323523}, {65425, 17323779},
2000
  {65426, 17324035}, {65427, 17324291}, {65428, 17324547}, {65429, 17324803},
2001
  {65430, 17325059}, {65431, 17325315}, {65432, 17325571}, {65433, 17325827},
2002
  {65434, 17326083}, {65435, 17326339}, {65436, 17326595}, {65437, 17330435},
2003
  {65438, 17208323}, {65439, 17208835}, {65440, 0}, {65441, 17210115},
2004
  {65442, 17210371}, {65443, 17210627}, {65444, 17210883}, {65445, 17211139},
2005
  {65446, 17211395}, {65447, 17211651}, {65448, 17211907}, {65449, 17212163},
2006
  {65450, 17212419}, {65451, 17212675}, {65452, 17212931}, {65453, 17213187},
2007
  {65454, 17213443}, {65455, 17213699}, {65456, 17213955}, {65457, 17214211},
2008
  {65458, 17214467}, {65459, 17214723}, {65460, 17214979}, {65461, 17215235},
2009
  {65462, 17215491}, {65463, 17215747}, {65464, 17216003}, {65465, 17216259},
2010
  {65466, 17216515}, {65467, 17216771}, {65468, 17217027}, {65469, 17217283},
2011
  {65470, 17217539}, {65471, 2}, {65474, 17217795}, {65475, 17218051},
2012
  {65476, 17218307}, {65477, 17218563}, {65478, 17218819}, {65479, 17219075},
2013
  {65480, 2}, {65482, 17219331}, {65483, 17219587}, {65484, 17219843},
2014
  {65485, 17220099}, {65486, 17220355}, {65487, 17220611}, {65488, 2},
2015
  {65490, 17220867}, {65491, 17221123}, {65492, 17221379}, {65493, 17221635},
2016
  {65494, 17221891}, {65495, 17222147}, {65496, 2}, {65498, 17222403},
2017
  {65499, 17222659}, {65500, 17222915}, {65501, 2}, {65504, 17874947},
2018
  {65505, 17875203}, {65506, 17875459}, {65507, 33561859}, {65508, 17875715},
2019
  {65509, 17875971}, {65510, 17876227}, {65511, 2}, {65512, 17876483},
2020
  {65513, 17876739}, {65514, 17876995}, {65515, 17877251}, {65516, 17877507},
2021
  {65517, 17877763}, {65518, 17878019}, {65519, 2}, {65536, 1},
2022
  {65548, 2}, {65549, 1}, {65575, 2}, {65576, 1},
2023
  {65595, 2}, {65596, 1}, {65598, 2}, {65599, 1},
2024
  {65614, 2}, {65616, 1}, {65630, 2}, {65664, 1},
2025
  {65787, 2}, {65792, 1}, {65795, 2}, {65799, 1},
2026
  {65844, 2}, {65847, 1}, {65935, 2}, {65936, 1},
2027
  {65949, 2}, {65952, 1}, {65953, 2}, {66000, 1},
2028
  {66046, 2}, {66176, 1}, {66205, 2}, {66208, 1},
2029
  {66257, 2}, {66272, 1}, {66300, 2}, {66304, 1},
2030
  {66340, 2}, {66349, 1}, {66379, 2}, {66384, 1},
2031
  {66427, 2}, {66432, 1}, {66462, 2}, {66463, 1},
2032
  {66500, 2}, {66504, 1}, {66518, 2}, {66560, 17878275},
2033
  {66561, 17878531}, {66562, 17878787}, {66563, 17879043}, {66564, 17879299},
2034
  {66565, 17879555}, {66566, 17879811}, {66567, 17880067}, {66568, 17880323},
2035
  {66569, 17880579}, {66570, 17880835}, {66571, 17881091}, {66572, 17881347},
2036
  {66573, 17881603}, {66574, 17881859}, {66575, 17882115}, {66576, 17882371},
2037
  {66577, 17882627}, {66578, 17882883}, {66579, 17883139}, {66580, 17883395},
2038
  {66581, 17883651}, {66582, 17883907}, {66583, 17884163}, {66584, 17884419},
2039
  {66585, 17884675}, {66586, 17884931}, {66587, 17885187}, {66588, 17885443},
2040
  {66589, 17885699}, {66590, 17885955}, {66591, 17886211}, {66592, 17886467},
2041
  {66593, 17886723}, {66594, 17886979}, {66595, 17887235}, {66596, 17887491},
2042
  {66597, 17887747}, {66598, 17888003}, {66599, 17888259}, {66600, 1},
2043
  {66718, 2}, {66720, 1}, {66730, 2}, {66736, 17888515},
2044
  {66737, 17888771}, {66738, 17889027}, {66739, 17889283}, {66740, 17889539},
2045
  {66741, 17889795}, {66742, 17890051}, {66743, 17890307}, {66744, 17890563},
2046
  {66745, 17890819}, {66746, 17891075}, {66747, 17891331}, {66748, 17891587},
2047
  {66749, 17891843}, {66750, 17892099}, {66751, 17892355}, {66752, 17892611},
2048
  {66753, 17892867}, {66754, 17893123}, {66755, 17893379}, {66756, 17893635},
2049
  {66757, 17893891}, {66758, 17894147}, {66759, 17894403}, {66760, 17894659},
2050
  {66761, 17894915}, {66762, 17895171}, {66763, 17895427}, {66764, 17895683},
2051
  {66765, 17895939}, {66766, 17896195}, {66767, 17896451}, {66768, 17896707},
2052
  {66769, 17896963}, {66770, 17897219}, {66771, 17897475}, {66772, 2},
2053
  {66776, 1}, {66812, 2}, {66816, 1}, {66856, 2},
2054
  {66864, 1}, {66916, 2}, {66927, 1}, {66928, 17897731},
2055
  {66929, 17897987}, {66930, 17898243}, {66931, 17898499}, {66932, 17898755},
2056
  {66933, 17899011}, {66934, 17899267}, {66935, 17899523}, {66936, 17899779},
2057
  {66937, 17900035}, {66938, 17900291}, {66939, 2}, {66940, 17900547},
2058
  {66941, 17900803}, {66942, 17901059}, {66943, 17901315}, {66944, 17901571},
2059
  {66945, 17901827}, {66946, 17902083}, {66947, 17902339}, {66948, 17902595},
2060
  {66949, 17902851}, {66950, 17903107}, {66951, 17903363}, {66952, 17903619},
2061
  {66953, 17903875}, {66954, 17904131}, {66955, 2}, {66956, 17904387},
2062
  {66957, 17904643}, {66958, 17904899}, {66959, 17905155}, {66960, 17905411},
2063
  {66961, 17905667}, {66962, 17905923}, {66963, 2}, {66964, 17906179},
2064
  {66965, 17906435}, {66966, 2}, {66967, 1}, {66978, 2},
2065
  {66979, 1}, {66994, 2}, {66995, 1}, {67002, 2},
2066
  {67003, 1}, {67005, 2}, {67008, 1}, {67060, 2},
2067
  {67072, 1}, {67383, 2}, {67392, 1}, {67414, 2},
2068
  {67424, 1}, {67432, 2}, {67456, 1}, {67457, 17906691},
2069
  {67458, 17906947}, {67459, 16791043}, {67460, 17907203}, {67461, 16814083},
2070
  {67462, 2}, {67463, 17907459}, {67464, 17907715}, {67465, 17907971},
2071
  {67466, 17908227}, {67467, 16815363}, {67468, 16815619}, {67469, 17908483},
2072
  {67470, 17908739}, {67471, 17908995}, {67472, 17909251}, {67473, 17527555},
2073
  {67474, 17909507}, {67475, 16817155}, {67476, 17909763}, {67477, 16802051},
2074
  {67478, 17910019}, {67479, 17910275}, {67480, 17910531}, {67481, 17910787},
2075
  {67482, 17911043}, {67483, 17523459}, {67484, 17911299}, {67485, 17911555},
2076
  {67486, 17911811}, {67487, 17912067}, {67488, 17912323}, {67489, 17912579},
2077
  {67490, 16795395}, {67491, 17912835}, {67492, 17913091}, {67493, 16781315},
2078
  {67494, 17913347}, {67495, 17913603}, {67496, 17135875}, {67497, 17913859},
2079
  {67498, 16819971}, {67499, 17914115}, {67500, 17914371}, {67501, 17914627},
2080
  {67502, 17914883}, {67503, 16820995}, {67504, 17915139}, {67505, 2},
2081
  {67506, 17915395}, {67507, 17915651}, {67508, 17915907}, {67509, 17916163},
2082
  {67510, 17916419}, {67511, 17916675}, {67512, 17916931}, {67513, 17917187},
2083
  {67514, 17917443}, {67515, 2}, {67584, 1}, {67590, 2},
2084
  {67592, 1}, {67593, 2}, {67594, 1}, {67638, 2},
2085
  {67639, 1}, {67641, 2}, {67644, 1}, {67645, 2},
2086
  {67647, 1}, {67670, 2}, {67671, 1}, {67743, 2},
2087
  {67751, 1}, {67760, 2}, {67808, 1}, {67827, 2},
2088
  {67828, 1}, {67830, 2}, {67835, 1}, {67868, 2},
2089
  {67871, 1}, {67898, 2}, {67903, 1}, {67904, 2},
2090
  {67968, 1}, {68024, 2}, {68028, 1}, {68048, 2},
2091
  {68050, 1}, {68100, 2}, {68101, 1}, {68103, 2},
2092
  {68108, 1}, {68116, 2}, {68117, 1}, {68120, 2},
2093
  {68121, 1}, {68150, 2}, {68152, 1}, {68155, 2},
2094
  {68159, 1}, {68169, 2}, {68176, 1}, {68185, 2},
2095
  {68192, 1}, {68256, 2}, {68288, 1}, {68327, 2},
2096
  {68331, 1}, {68343, 2}, {68352, 1}, {68406, 2},
2097
  {68409, 1}, {68438, 2}, {68440, 1}, {68467, 2},
2098
  {68472, 1}, {68498, 2}, {68505, 1}, {68509, 2},
2099
  {68521, 1}, {68528, 2}, {68608, 1}, {68681, 2},
2100
  {68736, 17917699}, {68737, 17917955}, {68738, 17918211}, {68739, 17918467},
2101
  {68740, 17918723}, {68741, 17918979}, {68742, 17919235}, {68743, 17919491},
2102
  {68744, 17919747}, {68745, 17920003}, {68746, 17920259}, {68747, 17920515},
2103
  {68748, 17920771}, {68749, 17921027}, {68750, 17921283}, {68751, 17921539},
2104
  {68752, 17921795}, {68753, 17922051}, {68754, 17922307}, {68755, 17922563},
2105
  {68756, 17922819}, {68757, 17923075}, {68758, 17923331}, {68759, 17923587},
2106
  {68760, 17923843}, {68761, 17924099}, {68762, 17924355}, {68763, 17924611},
2107
  {68764, 17924867}, {68765, 17925123}, {68766, 17925379}, {68767, 17925635},
2108
  {68768, 17925891}, {68769, 17926147}, {68770, 17926403}, {68771, 17926659},
2109
  {68772, 17926915}, {68773, 17927171}, {68774, 17927427}, {68775, 17927683},
2110
  {68776, 17927939}, {68777, 17928195}, {68778, 17928451}, {68779, 17928707},
2111
  {68780, 17928963}, {68781, 17929219}, {68782, 17929475}, {68783, 17929731},
2112
  {68784, 17929987}, {68785, 17930243}, {68786, 17930499}, {68787, 2},
2113
  {68800, 1}, {68851, 2}, {68858, 1}, {68904, 2},
2114
  {68912, 1}, {68922, 2}, {68928, 1}, {68944, 17930755},
2115
  {68945, 17931011}, {68946, 17931267}, {68947, 17931523}, {68948, 17931779},
2116
  {68949, 17932035}, {68950, 17932291}, {68951, 17932547}, {68952, 17932803},
2117
  {68953, 17933059}, {68954, 17933315}, {68955, 17933571}, {68956, 17933827},
2118
  {68957, 17934083}, {68958, 17934339}, {68959, 17934595}, {68960, 17934851},
2119
  {68961, 17935107}, {68962, 17935363}, {68963, 17935619}, {68964, 17935875},
2120
  {68965, 17936131}, {68966, 2}, {68969, 1}, {68998, 2},
2121
  {69006, 1}, {69008, 2}, {69216, 1}, {69247, 2},
2122
  {69248, 1}, {69290, 2}, {69291, 1}, {69294, 2},
2123
  {69296, 1}, {69298, 2}, {69314, 1}, {69317, 2},
2124
  {69372, 1}, {69416, 2}, {69424, 1}, {69466, 2},
2125
  {69488, 1}, {69514, 2}, {69552, 1}, {69580, 2},
2126
  {69600, 1}, {69623, 2}, {69632, 1}, {69710, 2},
2127
  {69714, 1}, {69750, 2}, {69759, 1}, {69821, 2},
2128
  {69822, 1}, {69827, 2}, {69840, 1}, {69865, 2},
2129
  {69872, 1}, {69882, 2}, {69888, 1}, {69941, 2},
2130
  {69942, 1}, {69960, 2}, {69968, 1}, {70007, 2},
2131
  {70016, 1}, {70112, 2}, {70113, 1}, {70133, 2},
2132
  {70144, 1}, {70162, 2}, {70163, 1}, {70210, 2},
2133
  {70272, 1}, {70279, 2}, {70280, 1}, {70281, 2},
2134
  {70282, 1}, {70286, 2}, {70287, 1}, {70302, 2},
2135
  {70303, 1}, {70314, 2}, {70320, 1}, {70379, 2},
2136
  {70384, 1}, {70394, 2}, {70400, 1}, {70404, 2},
2137
  {70405, 1}, {70413, 2}, {70415, 1}, {70417, 2},
2138
  {70419, 1}, {70441, 2}, {70442, 1}, {70449, 2},
2139
  {70450, 1}, {70452, 2}, {70453, 1}, {70458, 2},
2140
  {70459, 1}, {70469, 2}, {70471, 1}, {70473, 2},
2141
  {70475, 1}, {70478, 2}, {70480, 1}, {70481, 2},
2142
  {70487, 1}, {70488, 2}, {70493, 1}, {70500, 2},
2143
  {70502, 1}, {70509, 2}, {70512, 1}, {70517, 2},
2144
  {70528, 1}, {70538, 2}, {70539, 1}, {70540, 2},
2145
  {70542, 1}, {70543, 2}, {70544, 1}, {70582, 2},
2146
  {70583, 1}, {70593, 2}, {70594, 1}, {70595, 2},
2147
  {70597, 1}, {70598, 2}, {70599, 1}, {70603, 2},
2148
  {70604, 1}, {70614, 2}, {70615, 1}, {70617, 2},
2149
  {70625, 1}, {70627, 2}, {70656, 1}, {70748, 2},
2150
  {70749, 1}, {70754, 2}, {70784, 1}, {70856, 2},
2151
  {70864, 1}, {70874, 2}, {71040, 1}, {71094, 2},
2152
  {71096, 1}, {71134, 2}, {71168, 1}, {71237, 2},
2153
  {71248, 1}, {71258, 2}, {71264, 1}, {71277, 2},
2154
  {71296, 1}, {71354, 2}, {71360, 1}, {71370, 2},
2155
  {71376, 1}, {71396, 2}, {71424, 1}, {71451, 2},
2156
  {71453, 1}, {71468, 2}, {71472, 1}, {71495, 2},
2157
  {71680, 1}, {71740, 2}, {71840, 17936387}, {71841, 17936643},
2158
  {71842, 17936899}, {71843, 17937155}, {71844, 17937411}, {71845, 17937667},
2159
  {71846, 17937923}, {71847, 17938179}, {71848, 17938435}, {71849, 17938691},
2160
  {71850, 17938947}, {71851, 17939203}, {71852, 17939459}, {71853, 17939715},
2161
  {71854, 17939971}, {71855, 17940227}, {71856, 17940483}, {71857, 17940739},
2162
  {71858, 17940995}, {71859, 17941251}, {71860, 17941507}, {71861, 17941763},
2163
  {71862, 17942019}, {71863, 17942275}, {71864, 17942531}, {71865, 17942787},
2164
  {71866, 17943043}, {71867, 17943299}, {71868, 17943555}, {71869, 17943811},
2165
  {71870, 17944067}, {71871, 17944323}, {71872, 1}, {71923, 2},
2166
  {71935, 1}, {71943, 2}, {71945, 1}, {71946, 2},
2167
  {71948, 1}, {71956, 2}, {71957, 1}, {71959, 2},
2168
  {71960, 1}, {71990, 2}, {71991, 1}, {71993, 2},
2169
  {71995, 1}, {72007, 2}, {72016, 1}, {72026, 2},
2170
  {72096, 1}, {72104, 2}, {72106, 1}, {72152, 2},
2171
  {72154, 1}, {72165, 2}, {72192, 1}, {72264, 2},
2172
  {72272, 1}, {72355, 2}, {72368, 1}, {72441, 2},
2173
  {72448, 1}, {72458, 2}, {72640, 1}, {72674, 2},
2174
  {72688, 1}, {72698, 2}, {72704, 1}, {72713, 2},
2175
  {72714, 1}, {72759, 2}, {72760, 1}, {72774, 2},
2176
  {72784, 1}, {72813, 2}, {72816, 1}, {72848, 2},
2177
  {72850, 1}, {72872, 2}, {72873, 1}, {72887, 2},
2178
  {72960, 1}, {72967, 2}, {72968, 1}, {72970, 2},
2179
  {72971, 1}, {73015, 2}, {73018, 1}, {73019, 2},
2180
  {73020, 1}, {73022, 2}, {73023, 1}, {73032, 2},
2181
  {73040, 1}, {73050, 2}, {73056, 1}, {73062, 2},
2182
  {73063, 1}, {73065, 2}, {73066, 1}, {73103, 2},
2183
  {73104, 1}, {73106, 2}, {73107, 1}, {73113, 2},
2184
  {73120, 1}, {73130, 2}, {73440, 1}, {73465, 2},
2185
  {73472, 1}, {73489, 2}, {73490, 1}, {73531, 2},
2186
  {73534, 1}, {73563, 2}, {73648, 1}, {73649, 2},
2187
  {73664, 1}, {73714, 2}, {73727, 1}, {74650, 2},
2188
  {74752, 1}, {74863, 2}, {74864, 1}, {74869, 2},
2189
  {74880, 1}, {75076, 2}, {77712, 1}, {77811, 2},
2190
  {77824, 1}, {78896, 2}, {78912, 1}, {78934, 2},
2191
  {78944, 1}, {82939, 2}, {82944, 1}, {83527, 2},
2192
  {90368, 1}, {90426, 2}, {92160, 1}, {92729, 2},
2193
  {92736, 1}, {92767, 2}, {92768, 1}, {92778, 2},
2194
  {92782, 1}, {92863, 2}, {92864, 1}, {92874, 2},
2195
  {92880, 1}, {92910, 2}, {92912, 1}, {92918, 2},
2196
  {92928, 1}, {92998, 2}, {93008, 1}, {93018, 2},
2197
  {93019, 1}, {93026, 2}, {93027, 1}, {93048, 2},
2198
  {93053, 1}, {93072, 2}, {93504, 1}, {93562, 2},
2199
  {93760, 17944579}, {93761, 17944835}, {93762, 17945091}, {93763, 17945347},
2200
  {93764, 17945603}, {93765, 17945859}, {93766, 17946115}, {93767, 17946371},
2201
  {93768, 17946627}, {93769, 17946883}, {93770, 17947139}, {93771, 17947395},
2202
  {93772, 17947651}, {93773, 17947907}, {93774, 17948163}, {93775, 17948419},
2203
  {93776, 17948675}, {93777, 17948931}, {93778, 17949187}, {93779, 17949443},
2204
  {93780, 17949699}, {93781, 17949955}, {93782, 17950211}, {93783, 17950467},
2205
  {93784, 17950723}, {93785, 17950979}, {93786, 17951235}, {93787, 17951491},
2206
  {93788, 17951747}, {93789, 17952003}, {93790, 17952259}, {93791, 17952515},
2207
  {93792, 1}, {93851, 2}, {93952, 1}, {94027, 2},
2208
  {94031, 1}, {94088, 2}, {94095, 1}, {94112, 2},
2209
  {94176, 1}, {94181, 2}, {94192, 1}, {94194, 2},
2210
  {94208, 1}, {100344, 2}, {100352, 1}, {101590, 2},
2211
  {101631, 1}, {101641, 2}, {110576, 1}, {110580, 2},
2212
  {110581, 1}, {110588, 2}, {110589, 1}, {110591, 2},
2213
  {110592, 1}, {110883, 2}, {110898, 1}, {110899, 2},
2214
  {110928, 1}, {110931, 2}, {110933, 1}, {110934, 2},
2215
  {110948, 1}, {110952, 2}, {110960, 1}, {111356, 2},
2216
  {113664, 1}, {113771, 2}, {113776, 1}, {113789, 2},
2217
  {113792, 1}, {113801, 2}, {113808, 1}, {113818, 2},
2218
  {113820, 1}, {113824, 0}, {113828, 2}, {117760, 1},
2219
  {117974, 16777219}, {117975, 16777475}, {117976, 16777731}, {117977, 16777987},
2220
  {117978, 16778243}, {117979, 16778499}, {117980, 16778755}, {117981, 16779011},
2221
  {117982, 16779267}, {117983, 16779523}, {117984, 16779779}, {117985, 16780035},
2222
  {117986, 16780291}, {117987, 16780547}, {117988, 16780803}, {117989, 16781059},
2223
  {117990, 16781315}, {117991, 16781571}, {117992, 16781827}, {117993, 16782083},
2224
  {117994, 16782339}, {117995, 16782595}, {117996, 16782851}, {117997, 16783107},
2225
  {117998, 16783363}, {117999, 16783619}, {118000, 17045507}, {118001, 16786947},
2226
  {118002, 16785155}, {118003, 16785411}, {118004, 16787715}, {118005, 17045763},
2227
  {118006, 17046019}, {118007, 17046275}, {118008, 17046531}, {118009, 17046787},
2228
  {118010, 2}, {118016, 1}, {118452, 2}, {118528, 1},
2229
  {118574, 2}, {118576, 1}, {118599, 2}, {118608, 1},
2230
  {118724, 2}, {118784, 1}, {119030, 2}, {119040, 1},
2231
  {119079, 2}, {119081, 1}, {119134, 34729987}, {119135, 34730499},
2232
  {119136, 51508227}, {119137, 51508995}, {119138, 51509763}, {119139, 51510531},
2233
  {119140, 51511299}, {119141, 1}, {119155, 0}, {119163, 1},
2234
  {119227, 34734851}, {119228, 34735363}, {119229, 51513091}, {119230, 51513859},
2235
  {119231, 51514627}, {119232, 51515395}, {119233, 1}, {119275, 2},
2236
  {119296, 1}, {119366, 2}, {119488, 1}, {119508, 2},
2237
  {119520, 1}, {119540, 2}, {119552, 1}, {119639, 2},
2238
  {119648, 1}, {119673, 2}, {119808, 16777219}, {119809, 16777475},
2239
  {119810, 16777731}, {119811, 16777987}, {119812, 16778243}, {119813, 16778499},
2240
  {119814, 16778755}, {119815, 16779011}, {119816, 16779267}, {119817, 16779523},
2241
  {119818, 16779779}, {119819, 16780035}, {119820, 16780291}, {119821, 16780547},
2242
  {119822, 16780803}, {119823, 16781059}, {119824, 16781315}, {119825, 16781571},
2243
  {119826, 16781827}, {119827, 16782083}, {119828, 16782339}, {119829, 16782595},
2244
  {119830, 16782851}, {119831, 16783107}, {119832, 16783363}, {119833, 16783619},
2245
  {119834, 16777219}, {119835, 16777475}, {119836, 16777731}, {119837, 16777987},
2246
  {119838, 16778243}, {119839, 16778499}, {119840, 16778755}, {119841, 16779011},
2247
  {119842, 16779267}, {119843, 16779523}, {119844, 16779779}, {119845, 16780035},
2248
  {119846, 16780291}, {119847, 16780547}, {119848, 16780803}, {119849, 16781059},
2249
  {119850, 16781315}, {119851, 16781571}, {119852, 16781827}, {119853, 16782083},
2250
  {119854, 16782339}, {119855, 16782595}, {119856, 16782851}, {119857, 16783107},
2251
  {119858, 16783363}, {119859, 16783619}, {119860, 16777219}, {119861, 16777475},
2252
  {119862, 16777731}, {119863, 16777987}, {119864, 16778243}, {119865, 16778499},
2253
  {119866, 16778755}, {119867, 16779011}, {119868, 16779267}, {119869, 16779523},
2254
  {119870, 16779779}, {119871, 16780035}, {119872, 16780291}, {119873, 16780547},
2255
  {119874, 16780803}, {119875, 16781059}, {119876, 16781315}, {119877, 16781571},
2256
  {119878, 16781827}, {119879, 16782083}, {119880, 16782339}, {119881, 16782595},
2257
  {119882, 16782851}, {119883, 16783107}, {119884, 16783363}, {119885, 16783619},
2258
  {119886, 16777219}, {119887, 16777475}, {119888, 16777731}, {119889, 16777987},
2259
  {119890, 16778243}, {119891, 16778499}, {119892, 16778755}, {119893, 2},
2260
  {119894, 16779267}, {119895, 16779523}, {119896, 16779779}, {119897, 16780035},
2261
  {119898, 16780291}, {119899, 16780547}, {119900, 16780803}, {119901, 16781059},
2262
  {119902, 16781315}, {119903, 16781571}, {119904, 16781827}, {119905, 16782083},
2263
  {119906, 16782339}, {119907, 16782595}, {119908, 16782851}, {119909, 16783107},
2264
  {119910, 16783363}, {119911, 16783619}, {119912, 16777219}, {119913, 16777475},
2265
  {119914, 16777731}, {119915, 16777987}, {119916, 16778243}, {119917, 16778499},
2266
  {119918, 16778755}, {119919, 16779011}, {119920, 16779267}, {119921, 16779523},
2267
  {119922, 16779779}, {119923, 16780035}, {119924, 16780291}, {119925, 16780547},
2268
  {119926, 16780803}, {119927, 16781059}, {119928, 16781315}, {119929, 16781571},
2269
  {119930, 16781827}, {119931, 16782083}, {119932, 16782339}, {119933, 16782595},
2270
  {119934, 16782851}, {119935, 16783107}, {119936, 16783363}, {119937, 16783619},
2271
  {119938, 16777219}, {119939, 16777475}, {119940, 16777731}, {119941, 16777987},
2272
  {119942, 16778243}, {119943, 16778499}, {119944, 16778755}, {119945, 16779011},
2273
  {119946, 16779267}, {119947, 16779523}, {119948, 16779779}, {119949, 16780035},
2274
  {119950, 16780291}, {119951, 16780547}, {119952, 16780803}, {119953, 16781059},
2275
  {119954, 16781315}, {119955, 16781571}, {119956, 16781827}, {119957, 16782083},
2276
  {119958, 16782339}, {119959, 16782595}, {119960, 16782851}, {119961, 16783107},
2277
  {119962, 16783363}, {119963, 16783619}, {119964, 16777219}, {119965, 2},
2278
  {119966, 16777731}, {119967, 16777987}, {119968, 2}, {119970, 16778755},
2279
  {119971, 2}, {119973, 16779523}, {119974, 16779779}, {119975, 2},
2280
  {119977, 16780547}, {119978, 16780803}, {119979, 16781059}, {119980, 16781315},
2281
  {119981, 2}, {119982, 16781827}, {119983, 16782083}, {119984, 16782339},
2282
  {119985, 16782595}, {119986, 16782851}, {119987, 16783107}, {119988, 16783363},
2283
  {119989, 16783619}, {119990, 16777219}, {119991, 16777475}, {119992, 16777731},
2284
  {119993, 16777987}, {119994, 2}, {119995, 16778499}, {119996, 2},
2285
  {119997, 16779011}, {119998, 16779267}, {119999, 16779523}, {120000, 16779779},
2286
  {120001, 16780035}, {120002, 16780291}, {120003, 16780547}, {120004, 2},
2287
  {120005, 16781059}, {120006, 16781315}, {120007, 16781571}, {120008, 16781827},
2288
  {120009, 16782083}, {120010, 16782339}, {120011, 16782595}, {120012, 16782851},
2289
  {120013, 16783107}, {120014, 16783363}, {120015, 16783619}, {120016, 16777219},
2290
  {120017, 16777475}, {120018, 16777731}, {120019, 16777987}, {120020, 16778243},
2291
  {120021, 16778499}, {120022, 16778755}, {120023, 16779011}, {120024, 16779267},
2292
  {120025, 16779523}, {120026, 16779779}, {120027, 16780035}, {120028, 16780291},
2293
  {120029, 16780547}, {120030, 16780803}, {120031, 16781059}, {120032, 16781315},
2294
  {120033, 16781571}, {120034, 16781827}, {120035, 16782083}, {120036, 16782339},
2295
  {120037, 16782595}, {120038, 16782851}, {120039, 16783107}, {120040, 16783363},
2296
  {120041, 16783619}, {120042, 16777219}, {120043, 16777475}, {120044, 16777731},
2297
  {120045, 16777987}, {120046, 16778243}, {120047, 16778499}, {120048, 16778755},
2298
  {120049, 16779011}, {120050, 16779267}, {120051, 16779523}, {120052, 16779779},
2299
  {120053, 16780035}, {120054, 16780291}, {120055, 16780547}, {120056, 16780803},
2300
  {120057, 16781059}, {120058, 16781315}, {120059, 16781571}, {120060, 16781827},
2301
  {120061, 16782083}, {120062, 16782339}, {120063, 16782595}, {120064, 16782851},
2302
  {120065, 16783107}, {120066, 16783363}, {120067, 16783619}, {120068, 16777219},
2303
  {120069, 16777475}, {120070, 2}, {120071, 16777987}, {120072, 16778243},
2304
  {120073, 16778499}, {120074, 16778755}, {120075, 2}, {120077, 16779523},
2305
  {120078, 16779779}, {120079, 16780035}, {120080, 16780291}, {120081, 16780547},
2306
  {120082, 16780803}, {120083, 16781059}, {120084, 16781315}, {120085, 2},
2307
  {120086, 16781827}, {120087, 16782083}, {120088, 16782339}, {120089, 16782595},
2308
  {120090, 16782851}, {120091, 16783107}, {120092, 16783363}, {120093, 2},
2309
  {120094, 16777219}, {120095, 16777475}, {120096, 16777731}, {120097, 16777987},
2310
  {120098, 16778243}, {120099, 16778499}, {120100, 16778755}, {120101, 16779011},
2311
  {120102, 16779267}, {120103, 16779523}, {120104, 16779779}, {120105, 16780035},
2312
  {120106, 16780291}, {120107, 16780547}, {120108, 16780803}, {120109, 16781059},
2313
  {120110, 16781315}, {120111, 16781571}, {120112, 16781827}, {120113, 16782083},
2314
  {120114, 16782339}, {120115, 16782595}, {120116, 16782851}, {120117, 16783107},
2315
  {120118, 16783363}, {120119, 16783619}, {120120, 16777219}, {120121, 16777475},
2316
  {120122, 2}, {120123, 16777987}, {120124, 16778243}, {120125, 16778499},
2317
  {120126, 16778755}, {120127, 2}, {120128, 16779267}, {120129, 16779523},
2318
  {120130, 16779779}, {120131, 16780035}, {120132, 16780291}, {120133, 2},
2319
  {120134, 16780803}, {120135, 2}, {120138, 16781827}, {120139, 16782083},
2320
  {120140, 16782339}, {120141, 16782595}, {120142, 16782851}, {120143, 16783107},
2321
  {120144, 16783363}, {120145, 2}, {120146, 16777219}, {120147, 16777475},
2322
  {120148, 16777731}, {120149, 16777987}, {120150, 16778243}, {120151, 16778499},
2323
  {120152, 16778755}, {120153, 16779011}, {120154, 16779267}, {120155, 16779523},
2324
  {120156, 16779779}, {120157, 16780035}, {120158, 16780291}, {120159, 16780547},
2325
  {120160, 16780803}, {120161, 16781059}, {120162, 16781315}, {120163, 16781571},
2326
  {120164, 16781827}, {120165, 16782083}, {120166, 16782339}, {120167, 16782595},
2327
  {120168, 16782851}, {120169, 16783107}, {120170, 16783363}, {120171, 16783619},
2328
  {120172, 16777219}, {120173, 16777475}, {120174, 16777731}, {120175, 16777987},
2329
  {120176, 16778243}, {120177, 16778499}, {120178, 16778755}, {120179, 16779011},
2330
  {120180, 16779267}, {120181, 16779523}, {120182, 16779779}, {120183, 16780035},
2331
  {120184, 16780291}, {120185, 16780547}, {120186, 16780803}, {120187, 16781059},
2332
  {120188, 16781315}, {120189, 16781571}, {120190, 16781827}, {120191, 16782083},
2333
  {120192, 16782339}, {120193, 16782595}, {120194, 16782851}, {120195, 16783107},
2334
  {120196, 16783363}, {120197, 16783619}, {120198, 16777219}, {120199, 16777475},
2335
  {120200, 16777731}, {120201, 16777987}, {120202, 16778243}, {120203, 16778499},
2336
  {120204, 16778755}, {120205, 16779011}, {120206, 16779267}, {120207, 16779523},
2337
  {120208, 16779779}, {120209, 16780035}, {120210, 16780291}, {120211, 16780547},
2338
  {120212, 16780803}, {120213, 16781059}, {120214, 16781315}, {120215, 16781571},
2339
  {120216, 16781827}, {120217, 16782083}, {120218, 16782339}, {120219, 16782595},
2340
  {120220, 16782851}, {120221, 16783107}, {120222, 16783363}, {120223, 16783619},
2341
  {120224, 16777219}, {120225, 16777475}, {120226, 16777731}, {120227, 16777987},
2342
  {120228, 16778243}, {120229, 16778499}, {120230, 16778755}, {120231, 16779011},
2343
  {120232, 16779267}, {120233, 16779523}, {120234, 16779779}, {120235, 16780035},
2344
  {120236, 16780291}, {120237, 16780547}, {120238, 16780803}, {120239, 16781059},
2345
  {120240, 16781315}, {120241, 16781571}, {120242, 16781827}, {120243, 16782083},
2346
  {120244, 16782339}, {120245, 16782595}, {120246, 16782851}, {120247, 16783107},
2347
  {120248, 16783363}, {120249, 16783619}, {120250, 16777219}, {120251, 16777475},
2348
  {120252, 16777731}, {120253, 16777987}, {120254, 16778243}, {120255, 16778499},
2349
  {120256, 16778755}, {120257, 16779011}, {120258, 16779267}, {120259, 16779523},
2350
  {120260, 16779779}, {120261, 16780035}, {120262, 16780291}, {120263, 16780547},
2351
  {120264, 16780803}, {120265, 16781059}, {120266, 16781315}, {120267, 16781571},
2352
  {120268, 16781827}, {120269, 16782083}, {120270, 16782339}, {120271, 16782595},
2353
  {120272, 16782851}, {120273, 16783107}, {120274, 16783363}, {120275, 16783619},
2354
  {120276, 16777219}, {120277, 16777475}, {120278, 16777731}, {120279, 16777987},
2355
  {120280, 16778243}, {120281, 16778499}, {120282, 16778755}, {120283, 16779011},
2356
  {120284, 16779267}, {120285, 16779523}, {120286, 16779779}, {120287, 16780035},
2357
  {120288, 16780291}, {120289, 16780547}, {120290, 16780803}, {120291, 16781059},
2358
  {120292, 16781315}, {120293, 16781571}, {120294, 16781827}, {120295, 16782083},
2359
  {120296, 16782339}, {120297, 16782595}, {120298, 16782851}, {120299, 16783107},
2360
  {120300, 16783363}, {120301, 16783619}, {120302, 16777219}, {120303, 16777475},
2361
  {120304, 16777731}, {120305, 16777987}, {120306, 16778243}, {120307, 16778499},
2362
  {120308, 16778755}, {120309, 16779011}, {120310, 16779267}, {120311, 16779523},
2363
  {120312, 16779779}, {120313, 16780035}, {120314, 16780291}, {120315, 16780547},
2364
  {120316, 16780803}, {120317, 16781059}, {120318, 16781315}, {120319, 16781571},
2365
  {120320, 16781827}, {120321, 16782083}, {120322, 16782339}, {120323, 16782595},
2366
  {120324, 16782851}, {120325, 16783107}, {120326, 16783363}, {120327, 16783619},
2367
  {120328, 16777219}, {120329, 16777475}, {120330, 16777731}, {120331, 16777987},
2368
  {120332, 16778243}, {120333, 16778499}, {120334, 16778755}, {120335, 16779011},
2369
  {120336, 16779267}, {120337, 16779523}, {120338, 16779779}, {120339, 16780035},
2370
  {120340, 16780291}, {120341, 16780547}, {120342, 16780803}, {120343, 16781059},
2371
  {120344, 16781315}, {120345, 16781571}, {120346, 16781827}, {120347, 16782083},
2372
  {120348, 16782339}, {120349, 16782595}, {120350, 16782851}, {120351, 16783107},
2373
  {120352, 16783363}, {120353, 16783619}, {120354, 16777219}, {120355, 16777475},
2374
  {120356, 16777731}, {120357, 16777987}, {120358, 16778243}, {120359, 16778499},
2375
  {120360, 16778755}, {120361, 16779011}, {120362, 16779267}, {120363, 16779523},
2376
  {120364, 16779779}, {120365, 16780035}, {120366, 16780291}, {120367, 16780547},
2377
  {120368, 16780803}, {120369, 16781059}, {120370, 16781315}, {120371, 16781571},
2378
  {120372, 16781827}, {120373, 16782083}, {120374, 16782339}, {120375, 16782595},
2379
  {120376, 16782851}, {120377, 16783107}, {120378, 16783363}, {120379, 16783619},
2380
  {120380, 16777219}, {120381, 16777475}, {120382, 16777731}, {120383, 16777987},
2381
  {120384, 16778243}, {120385, 16778499}, {120386, 16778755}, {120387, 16779011},
2382
  {120388, 16779267}, {120389, 16779523}, {120390, 16779779}, {120391, 16780035},
2383
  {120392, 16780291}, {120393, 16780547}, {120394, 16780803}, {120395, 16781059},
2384
  {120396, 16781315}, {120397, 16781571}, {120398, 16781827}, {120399, 16782083},
2385
  {120400, 16782339}, {120401, 16782595}, {120402, 16782851}, {120403, 16783107},
2386
  {120404, 16783363}, {120405, 16783619}, {120406, 16777219}, {120407, 16777475},
2387
  {120408, 16777731}, {120409, 16777987}, {120410, 16778243}, {120411, 16778499},
2388
  {120412, 16778755}, {120413, 16779011}, {120414, 16779267}, {120415, 16779523},
2389
  {120416, 16779779}, {120417, 16780035}, {120418, 16780291}, {120419, 16780547},
2390
  {120420, 16780803}, {120421, 16781059}, {120422, 16781315}, {120423, 16781571},
2391
  {120424, 16781827}, {120425, 16782083}, {120426, 16782339}, {120427, 16782595},
2392
  {120428, 16782851}, {120429, 16783107}, {120430, 16783363}, {120431, 16783619},
2393
  {120432, 16777219}, {120433, 16777475}, {120434, 16777731}, {120435, 16777987},
2394
  {120436, 16778243}, {120437, 16778499}, {120438, 16778755}, {120439, 16779011},
2395
  {120440, 16779267}, {120441, 16779523}, {120442, 16779779}, {120443, 16780035},
2396
  {120444, 16780291}, {120445, 16780547}, {120446, 16780803}, {120447, 16781059},
2397
  {120448, 16781315}, {120449, 16781571}, {120450, 16781827}, {120451, 16782083},
2398
  {120452, 16782339}, {120453, 16782595}, {120454, 16782851}, {120455, 16783107},
2399
  {120456, 16783363}, {120457, 16783619}, {120458, 16777219}, {120459, 16777475},
2400
  {120460, 16777731}, {120461, 16777987}, {120462, 16778243}, {120463, 16778499},
2401
  {120464, 16778755}, {120465, 16779011}, {120466, 16779267}, {120467, 16779523},
2402
  {120468, 16779779}, {120469, 16780035}, {120470, 16780291}, {120471, 16780547},
2403
  {120472, 16780803}, {120473, 16781059}, {120474, 16781315}, {120475, 16781571},
2404
  {120476, 16781827}, {120477, 16782083}, {120478, 16782339}, {120479, 16782595},
2405
  {120480, 16782851}, {120481, 16783107}, {120482, 16783363}, {120483, 16783619},
2406
  {120484, 17961731}, {120485, 17961987}, {120486, 2}, {120488, 16851715},
2407
  {120489, 16851971}, {120490, 16852227}, {120491, 16852483}, {120492, 16852739},
2408
  {120493, 16852995}, {120494, 16853251}, {120495, 16853507}, {120496, 16846851},
2409
  {120497, 16853763}, {120498, 16854019}, {120499, 16786179}, {120500, 16854275},
2410
  {120501, 16854531}, {120502, 16854787}, {120503, 16855043}, {120504, 16855299},
2411
  {120505, 16853507}, {120506, 16855555}, {120507, 16855811}, {120508, 16856067},
2412
  {120509, 16856323}, {120510, 16856579}, {120511, 16856835}, {120512, 16857091},
2413
  {120513, 17962243}, {120514, 16851715}, {120515, 16851971}, {120516, 16852227},
2414
  {120517, 16852483}, {120518, 16852739}, {120519, 16852995}, {120520, 16853251},
2415
  {120521, 16853507}, {120522, 16846851}, {120523, 16853763}, {120524, 16854019},
2416
  {120525, 16786179}, {120526, 16854275}, {120527, 16854531}, {120528, 16854787},
2417
  {120529, 16855043}, {120530, 16855299}, {120531, 16855555}, {120533, 16855811},
2418
  {120534, 16856067}, {120535, 16856323}, {120536, 16856579}, {120537, 16856835},
2419
  {120538, 16857091}, {120539, 17962499}, {120540, 16852739}, {120541, 16853507},
2420
  {120542, 16853763}, {120543, 16856323}, {120544, 16855299}, {120545, 16855043},
2421
  {120546, 16851715}, {120547, 16851971}, {120548, 16852227}, {120549, 16852483},
2422
  {120550, 16852739}, {120551, 16852995}, {120552, 16853251}, {120553, 16853507},
2423
  {120554, 16846851}, {120555, 16853763}, {120556, 16854019}, {120557, 16786179},
2424
  {120558, 16854275}, {120559, 16854531}, {120560, 16854787}, {120561, 16855043},
2425
  {120562, 16855299}, {120563, 16853507}, {120564, 16855555}, {120565, 16855811},
2426
  {120566, 16856067}, {120567, 16856323}, {120568, 16856579}, {120569, 16856835},
2427
  {120570, 16857091}, {120571, 17962243}, {120572, 16851715}, {120573, 16851971},
2428
  {120574, 16852227}, {120575, 16852483}, {120576, 16852739}, {120577, 16852995},
2429
  {120578, 16853251}, {120579, 16853507}, {120580, 16846851}, {120581, 16853763},
2430
  {120582, 16854019}, {120583, 16786179}, {120584, 16854275}, {120585, 16854531},
2431
  {120586, 16854787}, {120587, 16855043}, {120588, 16855299}, {120589, 16855555},
2432
  {120591, 16855811}, {120592, 16856067}, {120593, 16856323}, {120594, 16856579},
2433
  {120595, 16856835}, {120596, 16857091}, {120597, 17962499}, {120598, 16852739},
2434
  {120599, 16853507}, {120600, 16853763}, {120601, 16856323}, {120602, 16855299},
2435
  {120603, 16855043}, {120604, 16851715}, {120605, 16851971}, {120606, 16852227},
2436
  {120607, 16852483}, {120608, 16852739}, {120609, 16852995}, {120610, 16853251},
2437
  {120611, 16853507}, {120612, 16846851}, {120613, 16853763}, {120614, 16854019},
2438
  {120615, 16786179}, {120616, 16854275}, {120617, 16854531}, {120618, 16854787},
2439
  {120619, 16855043}, {120620, 16855299}, {120621, 16853507}, {120622, 16855555},
2440
  {120623, 16855811}, {120624, 16856067}, {120625, 16856323}, {120626, 16856579},
2441
  {120627, 16856835}, {120628, 16857091}, {120629, 17962243}, {120630, 16851715},
2442
  {120631, 16851971}, {120632, 16852227}, {120633, 16852483}, {120634, 16852739},
2443
  {120635, 16852995}, {120636, 16853251}, {120637, 16853507}, {120638, 16846851},
2444
  {120639, 16853763}, {120640, 16854019}, {120641, 16786179}, {120642, 16854275},
2445
  {120643, 16854531}, {120644, 16854787}, {120645, 16855043}, {120646, 16855299},
2446
  {120647, 16855555}, {120649, 16855811}, {120650, 16856067}, {120651, 16856323},
2447
  {120652, 16856579}, {120653, 16856835}, {120654, 16857091}, {120655, 17962499},
2448
  {120656, 16852739}, {120657, 16853507}, {120658, 16853763}, {120659, 16856323},
2449
  {120660, 16855299}, {120661, 16855043}, {120662, 16851715}, {120663, 16851971},
2450
  {120664, 16852227}, {120665, 16852483}, {120666, 16852739}, {120667, 16852995},
2451
  {120668, 16853251}, {120669, 16853507}, {120670, 16846851}, {120671, 16853763},
2452
  {120672, 16854019}, {120673, 16786179}, {120674, 16854275}, {120675, 16854531},
2453
  {120676, 16854787}, {120677, 16855043}, {120678, 16855299}, {120679, 16853507},
2454
  {120680, 16855555}, {120681, 16855811}, {120682, 16856067}, {120683, 16856323},
2455
  {120684, 16856579}, {120685, 16856835}, {120686, 16857091}, {120687, 17962243},
2456
  {120688, 16851715}, {120689, 16851971}, {120690, 16852227}, {120691, 16852483},
2457
  {120692, 16852739}, {120693, 16852995}, {120694, 16853251}, {120695, 16853507},
2458
  {120696, 16846851}, {120697, 16853763}, {120698, 16854019}, {120699, 16786179},
2459
  {120700, 16854275}, {120701, 16854531}, {120702, 16854787}, {120703, 16855043},
2460
  {120704, 16855299}, {120705, 16855555}, {120707, 16855811}, {120708, 16856067},
2461
  {120709, 16856323}, {120710, 16856579}, {120711, 16856835}, {120712, 16857091},
2462
  {120713, 17962499}, {120714, 16852739}, {120715, 16853507}, {120716, 16853763},
2463
  {120717, 16856323}, {120718, 16855299}, {120719, 16855043}, {120720, 16851715},
2464
  {120721, 16851971}, {120722, 16852227}, {120723, 16852483}, {120724, 16852739},
2465
  {120725, 16852995}, {120726, 16853251}, {120727, 16853507}, {120728, 16846851},
2466
  {120729, 16853763}, {120730, 16854019}, {120731, 16786179}, {120732, 16854275},
2467
  {120733, 16854531}, {120734, 16854787}, {120735, 16855043}, {120736, 16855299},
2468
  {120737, 16853507}, {120738, 16855555}, {120739, 16855811}, {120740, 16856067},
2469
  {120741, 16856323}, {120742, 16856579}, {120743, 16856835}, {120744, 16857091},
2470
  {120745, 17962243}, {120746, 16851715}, {120747, 16851971}, {120748, 16852227},
2471
  {120749, 16852483}, {120750, 16852739}, {120751, 16852995}, {120752, 16853251},
2472
  {120753, 16853507}, {120754, 16846851}, {120755, 16853763}, {120756, 16854019},
2473
  {120757, 16786179}, {120758, 16854275}, {120759, 16854531}, {120760, 16854787},
2474
  {120761, 16855043}, {120762, 16855299}, {120763, 16855555}, {120765, 16855811},
2475
  {120766, 16856067}, {120767, 16856323}, {120768, 16856579}, {120769, 16856835},
2476
  {120770, 16857091}, {120771, 17962499}, {120772, 16852739}, {120773, 16853507},
2477
  {120774, 16853763}, {120775, 16856323}, {120776, 16855299}, {120777, 16855043},
2478
  {120778, 16858627}, {120780, 2}, {120782, 17045507}, {120783, 16786947},
2479
  {120784, 16785155}, {120785, 16785411}, {120786, 16787715}, {120787, 17045763},
2480
  {120788, 17046019}, {120789, 17046275}, {120790, 17046531}, {120791, 17046787},
2481
  {120792, 17045507}, {120793, 16786947}, {120794, 16785155}, {120795, 16785411},
2482
  {120796, 16787715}, {120797, 17045763}, {120798, 17046019}, {120799, 17046275},
2483
  {120800, 17046531}, {120801, 17046787}, {120802, 17045507}, {120803, 16786947},
2484
  {120804, 16785155}, {120805, 16785411}, {120806, 16787715}, {120807, 17045763},
2485
  {120808, 17046019}, {120809, 17046275}, {120810, 17046531}, {120811, 17046787},
2486
  {120812, 17045507}, {120813, 16786947}, {120814, 16785155}, {120815, 16785411},
2487
  {120816, 16787715}, {120817, 17045763}, {120818, 17046019}, {120819, 17046275},
2488
  {120820, 17046531}, {120821, 17046787}, {120822, 17045507}, {120823, 16786947},
2489
  {120824, 16785155}, {120825, 16785411}, {120826, 16787715}, {120827, 17045763},
2490
  {120828, 17046019}, {120829, 17046275}, {120830, 17046531}, {120831, 17046787},
2491
  {120832, 1}, {121484, 2}, {121499, 1}, {121504, 2},
2492
  {121505, 1}, {121520, 2}, {122624, 1}, {122655, 2},
2493
  {122661, 1}, {122667, 2}, {122880, 1}, {122887, 2},
2494
  {122888, 1}, {122905, 2}, {122907, 1}, {122914, 2},
2495
  {122915, 1}, {122917, 2}, {122918, 1}, {122923, 2},
2496
  {122928, 16866563}, {122929, 16866819}, {122930, 16867075}, {122931, 16867331},
2497
  {122932, 16867587}, {122933, 16867843}, {122934, 16868099}, {122935, 16868355},
2498
  {122936, 16868611}, {122937, 16869123}, {122938, 16869379}, {122939, 16869635},
2499
  {122940, 16870147}, {122941, 16870403}, {122942, 16870659}, {122943, 16870915},
2500
  {122944, 16871171}, {122945, 16871427}, {122946, 16871683}, {122947, 16871939},
2501
  {122948, 16872195}, {122949, 16872451}, {122950, 16872707}, {122951, 16873475},
2502
  {122952, 16873987}, {122953, 16874243}, {122954, 17505795}, {122955, 16889091},
2503
  {122956, 16864003}, {122957, 16864515}, {122958, 16891139}, {122959, 16883715},
2504
  {122960, 16886019}, {122961, 16866563}, {122962, 16866819}, {122963, 16867075},
2505
  {122964, 16867331}, {122965, 16867587}, {122966, 16867843}, {122967, 16868099},
2506
  {122968, 16868355}, {122969, 16868611}, {122970, 16869123}, {122971, 16869379},
2507
  {122972, 16870147}, {122973, 16870403}, {122974, 16870915}, {122975, 16871427},
2508
  {122976, 16871683}, {122977, 16871939}, {122978, 16872195}, {122979, 16872451},
2509
  {122980, 16872707}, {122981, 16873219}, {122982, 16873475}, {122983, 16879875},
2510
  {122984, 16864003}, {122985, 16863747}, {122986, 16866307}, {122987, 16883203},
2511
  {122988, 17500931}, {122989, 16883971}, {122990, 2}, {123023, 1},
2512
  {123024, 2}, {123136, 1}, {123181, 2}, {123184, 1},
2513
  {123198, 2}, {123200, 1}, {123210, 2}, {123214, 1},
2514
  {123216, 2}, {123536, 1}, {123567, 2}, {123584, 1},
2515
  {123642, 2}, {123647, 1}, {123648, 2}, {124112, 1},
2516
  {124154, 2}, {124368, 1}, {124411, 2}, {124415, 1},
2517
  {124416, 2}, {124896, 1}, {124903, 2}, {124904, 1},
2518
  {124908, 2}, {124909, 1}, {124911, 2}, {124912, 1},
2519
  {124927, 2}, {124928, 1}, {125125, 2}, {125127, 1},
2520
  {125143, 2}, {125184, 17962755}, {125185, 17963011}, {125186, 17963267},
2521
  {125187, 17963523}, {125188, 17963779}, {125189, 17964035}, {125190, 17964291},
2522
  {125191, 17964547}, {125192, 17964803}, {125193, 17965059}, {125194, 17965315},
2523
  {125195, 17965571}, {125196, 17965827}, {125197, 17966083}, {125198, 17966339},
2524
  {125199, 17966595}, {125200, 17966851}, {125201, 17967107}, {125202, 17967363},
2525
  {125203, 17967619}, {125204, 17967875}, {125205, 17968131}, {125206, 17968387},
2526
  {125207, 17968643}, {125208, 17968899}, {125209, 17969155}, {125210, 17969411},
2527
  {125211, 17969667}, {125212, 17969923}, {125213, 17970179}, {125214, 17970435},
2528
  {125215, 17970691}, {125216, 17970947}, {125217, 17971203}, {125218, 1},
2529
  {125260, 2}, {125264, 1}, {125274, 2}, {125278, 1},
2530
  {125280, 2}, {126065, 1}, {126133, 2}, {126209, 1},
2531
  {126270, 2}, {126464, 16910595}, {126465, 17695235}, {126466, 17693443},
2532
  {126467, 17846019}, {126468, 2}, {126469, 16911107}, {126470, 17743107},
2533
  {126471, 17693955}, {126472, 17711619}, {126473, 16912131}, {126474, 17720323},
2534
  {126475, 17722627}, {126476, 17694467}, {126477, 17729539}, {126478, 17706499},
2535
  {126479, 17713155}, {126480, 17715203}, {126481, 17708547}, {126482, 17718275},
2536
  {126483, 17736707}, {126484, 17756675}, {126485, 17698307}, {126486, 17701379},
2537
  {126487, 17696515}, {126488, 17736195}, {126489, 17709571}, {126490, 17712643},
2538
  {126491, 17714179}, {126492, 17971459}, {126493, 17684995}, {126494, 17971715},
2539
  {126495, 17971971}, {126496, 2}, {126497, 17695235}, {126498, 17693443},
2540
  {126499, 2}, {126500, 17732611}, {126501, 2}, {126503, 17693955},
2541
  {126504, 2}, {126505, 16912131}, {126506, 17720323}, {126507, 17722627},
2542
  {126508, 17694467}, {126509, 17729539}, {126510, 17706499}, {126511, 17713155},
2543
  {126512, 17715203}, {126513, 17708547}, {126514, 17718275}, {126515, 2},
2544
  {126516, 17756675}, {126517, 17698307}, {126518, 17701379}, {126519, 17696515},
2545
  {126520, 2}, {126521, 17709571}, {126522, 2}, {126523, 17714179},
2546
  {126524, 2}, {126530, 17693443}, {126531, 2}, {126535, 17693955},
2547
  {126536, 2}, {126537, 16912131}, {126538, 2}, {126539, 17722627},
2548
  {126540, 2}, {126541, 17729539}, {126542, 17706499}, {126543, 17713155},
2549
  {126544, 2}, {126545, 17708547}, {126546, 17718275}, {126547, 2},
2550
  {126548, 17756675}, {126549, 2}, {126551, 17696515}, {126552, 2},
2551
  {126553, 17709571}, {126554, 2}, {126555, 17714179}, {126556, 2},
2552
  {126557, 17684995}, {126558, 2}, {126559, 17971971}, {126560, 2},
2553
  {126561, 17695235}, {126562, 17693443}, {126563, 2}, {126564, 17732611},
2554
  {126565, 2}, {126567, 17693955}, {126568, 17711619}, {126569, 16912131},
2555
  {126570, 17720323}, {126571, 2}, {126572, 17694467}, {126573, 17729539},
2556
  {126574, 17706499}, {126575, 17713155}, {126576, 17715203}, {126577, 17708547},
2557
  {126578, 17718275}, {126579, 2}, {126580, 17756675}, {126581, 17698307},
2558
  {126582, 17701379}, {126583, 17696515}, {126584, 2}, {126585, 17709571},
2559
  {126586, 17712643}, {126587, 17714179}, {126588, 17971459}, {126589, 2},
2560
  {126590, 17971715}, {126591, 2}, {126592, 16910595}, {126593, 17695235},
2561
  {126594, 17693443}, {126595, 17846019}, {126596, 17732611}, {126597, 16911107},
2562
  {126598, 17743107}, {126599, 17693955}, {126600, 17711619}, {126601, 16912131},
2563
  {126602, 2}, {126603, 17722627}, {126604, 17694467}, {126605, 17729539},
2564
  {126606, 17706499}, {126607, 17713155}, {126608, 17715203}, {126609, 17708547},
2565
  {126610, 17718275}, {126611, 17736707}, {126612, 17756675}, {126613, 17698307},
2566
  {126614, 17701379}, {126615, 17696515}, {126616, 17736195}, {126617, 17709571},
2567
  {126618, 17712643}, {126619, 17714179}, {126620, 2}, {126625, 17695235},
2568
  {126626, 17693443}, {126627, 17846019}, {126628, 2}, {126629, 16911107},
2569
  {126630, 17743107}, {126631, 17693955}, {126632, 17711619}, {126633, 16912131},
2570
  {126634, 2}, {126635, 17722627}, {126636, 17694467}, {126637, 17729539},
2571
  {126638, 17706499}, {126639, 17713155}, {126640, 17715203}, {126641, 17708547},
2572
  {126642, 17718275}, {126643, 17736707}, {126644, 17756675}, {126645, 17698307},
2573
  {126646, 17701379}, {126647, 17696515}, {126648, 17736195}, {126649, 17709571},
2574
  {126650, 17712643}, {126651, 17714179}, {126652, 2}, {126704, 1},
2575
  {126706, 2}, {126976, 1}, {127020, 2}, {127024, 1},
2576
  {127124, 2}, {127136, 1}, {127151, 2}, {127153, 1},
2577
  {127168, 2}, {127169, 1}, {127184, 2}, {127185, 1},
2578
  {127222, 2}, {127233, 34749443}, {127234, 34749955}, {127235, 34750467},
2579
  {127236, 34750979}, {127237, 34751491}, {127238, 34752003}, {127239, 34752515},
2580
  {127240, 34753027}, {127241, 34753539}, {127242, 34754051}, {127243, 1},
2581
  {127248, 50655491}, {127249, 50656259}, {127250, 50657027}, {127251, 50657795},
2582
  {127252, 50658563}, {127253, 50659331}, {127254, 50660099}, {127255, 50660867},
2583
  {127256, 50661635}, {127257, 50662403}, {127258, 50663171}, {127259, 50663939},
2584
  {127260, 50664707}, {127261, 50665475}, {127262, 50666243}, {127263, 50667011},
2585
  {127264, 50667779}, {127265, 50668547}, {127266, 50669315}, {127267, 50670083},
2586
  {127268, 50670851}, {127269, 50671619}, {127270, 50672387}, {127271, 50673155},
2587
  {127272, 50673923}, {127273, 50674691}, {127274, 51531779}, {127275, 16777731},
2588
  {127276, 16781571}, {127277, 33554947}, {127278, 34755331}, {127279, 1},
2589
  {127280, 16777219}, {127281, 16777475}, {127282, 16777731}, {127283, 16777987},
2590
  {127284, 16778243}, {127285, 16778499}, {127286, 16778755}, {127287, 16779011},
2591
  {127288, 16779267}, {127289, 16779523}, {127290, 16779779}, {127291, 16780035},
2592
  {127292, 16780291}, {127293, 16780547}, {127294, 16780803}, {127295, 16781059},
2593
  {127296, 16781315}, {127297, 16781571}, {127298, 16781827}, {127299, 16782083},
2594
  {127300, 16782339}, {127301, 16782595}, {127302, 16782851}, {127303, 16783107},
2595
  {127304, 16783363}, {127305, 16783619}, {127306, 34755843}, {127307, 34237187},
2596
  {127308, 34756355}, {127309, 34756867}, {127310, 51534595}, {127311, 34758147},
2597
  {127312, 1}, {127338, 34220035}, {127339, 34200067}, {127340, 34758659},
2598
  {127341, 1}, {127376, 34759171}, {127377, 1}, {127406, 2},
2599
  {127462, 1}, {127488, 34759683}, {127489, 34760195}, {127490, 17318403},
2600
  {127491, 2}, {127504, 17168387}, {127505, 17983491}, {127506, 17983747},
2601
  {127507, 17362179}, {127508, 17153795}, {127509, 17984003}, {127510, 17984259},
2602
  {127511, 17235971}, {127512, 17984515}, {127513, 17984771}, {127514, 17985027},
2603
  {127515, 17596163}, {127516, 17985283}, {127517, 17985539}, {127518, 17985795},
2604
  {127519, 17986051}, {127520, 17986307}, {127521, 17986563}, {127522, 17177603},
2605
  {127523, 17986819}, {127524, 17987075}, {127525, 17987331}, {127526, 17987587},
2606
  {127527, 17987843}, {127528, 17988099}, {127529, 17152259}, {127530, 17233923},
2607
  {127531, 17988355}, {127532, 17299203}, {127533, 17234691}, {127534, 17299459},
2608
  {127535, 17988611}, {127536, 17191939}, {127537, 17988867}, {127538, 17989123},
2609
  {127539, 17989379}, {127540, 17989635}, {127541, 17989891}, {127542, 17274883},
2610
  {127543, 17170947}, {127544, 17990147}, {127545, 17990403}, {127546, 17990659},
2611
  {127547, 17990915}, {127548, 2}, {127552, 51545603}, {127553, 51546371},
2612
  {127554, 51547139}, {127555, 51547907}, {127556, 51548675}, {127557, 51549443},
2613
  {127558, 51550211}, {127559, 51550979}, {127560, 51551747}, {127561, 2},
2614
  {127568, 17998083}, {127569, 17998339}, {127570, 2}, {127584, 1},
2615
  {127590, 2}, {127744, 1}, {128728, 2}, {128732, 1},
2616
  {128749, 2}, {128752, 1}, {128765, 2}, {128768, 1},
2617
  {128887, 2}, {128891, 1}, {128986, 2}, {128992, 1},
2618
  {129004, 2}, {129008, 1}, {129009, 2}, {129024, 1},
2619
  {129036, 2}, {129040, 1}, {129096, 2}, {129104, 1},
2620
  {129114, 2}, {129120, 1}, {129160, 2}, {129168, 1},
2621
  {129198, 2}, {129200, 1}, {129212, 2}, {129216, 1},
2622
  {129218, 2}, {129280, 1}, {129620, 2}, {129632, 1},
2623
  {129646, 2}, {129648, 1}, {129661, 2}, {129664, 1},
2624
  {129674, 2}, {129679, 1}, {129735, 2}, {129742, 1},
2625
  {129757, 2}, {129759, 1}, {129770, 2}, {129776, 1},
2626
  {129785, 2}, {129792, 1}, {129939, 2}, {129940, 1},
2627
  {130032, 17045507}, {130033, 16786947}, {130034, 16785155}, {130035, 16785411},
2628
  {130036, 16787715}, {130037, 17045763}, {130038, 17046019}, {130039, 17046275},
2629
  {130040, 17046531}, {130041, 17046787}, {130042, 2}, {131072, 1},
2630
  {173792, 2}, {173824, 1}, {177978, 2}, {177984, 1},
2631
  {178206, 2}, {178208, 1}, {183970, 2}, {183984, 1},
2632
  {191457, 2}, {191472, 1}, {192094, 2}, {194560, 17998595},
2633
  {194561, 17998851}, {194562, 17999107}, {194563, 17999363}, {194564, 17999619},
2634
  {194565, 17619971}, {194566, 17999875}, {194567, 18000131}, {194568, 18000387},
2635
  {194569, 18000643}, {194570, 17620227}, {194571, 18000899}, {194572, 18001155},
2636
  {194573, 18001411}, {194574, 17620483}, {194575, 18001667}, {194576, 18001923},
2637
  {194577, 18002179}, {194578, 18002435}, {194579, 18002691}, {194580, 18002947},
2638
  {194581, 17985795}, {194582, 18003203}, {194583, 18003459}, {194584, 18003715},
2639
  {194585, 18003971}, {194586, 18004227}, {194587, 17634563}, {194588, 18004483},
2640
  {194589, 17156355}, {194590, 18004739}, {194591, 18004995}, {194592, 18005251},
2641
  {194593, 18005507}, {194594, 17990403}, {194595, 18005763}, {194596, 18006019},
2642
  {194597, 17635843}, {194598, 17620739}, {194599, 17620995}, {194600, 17636099},
2643
  {194601, 18006275}, {194602, 18006531}, {194603, 17574403}, {194604, 18006787},
2644
  {194605, 17621251}, {194606, 18007043}, {194607, 18007299}, {194608, 18007555},
2645
  {194609, 18007811}, {194612, 18008067}, {194613, 18008323}, {194614, 18008579},
2646
  {194615, 18008835}, {194616, 18009091}, {194617, 18009347}, {194618, 18009603},
2647
  {194619, 18009859}, {194620, 18010115}, {194621, 18010371}, {194622, 18010627},
2648
  {194623, 18010883}, {194624, 18011139}, {194625, 18011395}, {194626, 18011651},
2649
  {194627, 18011907}, {194628, 18012163}, {194629, 18012419}, {194631, 17636611},
2650
  {194632, 18012675}, {194633, 18012931}, {194634, 18013187}, {194635, 18013443},
2651
  {194636, 17621763}, {194637, 18013699}, {194638, 18013955}, {194639, 18014211},
2652
  {194640, 17611523}, {194641, 18014467}, {194642, 18014723}, {194643, 18014979},
2653
  {194644, 18015235}, {194645, 18015491}, {194646, 18015747}, {194647, 18016003},
2654
  {194648, 18016259}, {194649, 18016515}, {194650, 18016771}, {194651, 18017027},
2655
  {194652, 18017283}, {194653, 17984003}, {194654, 18017539}, {194655, 18017795},
2656
  {194656, 18018051}, {194657, 18018307}, {194658, 18018563}, {194659, 18018819},
2657
  {194660, 18019075}, {194661, 18019331}, {194662, 18019587}, {194663, 18019843},
2658
  {194664, 18020099}, {194665, 18020355}, {194666, 18020611}, {194668, 18020867},
2659
  {194669, 18021123}, {194670, 18021379}, {194671, 17573379}, {194672, 18021635},
2660
  {194673, 18021891}, {194674, 18022147}, {194675, 18022403}, {194676, 18022659},
2661
  {194677, 17163011}, {194678, 18022915}, {194679, 18023171}, {194680, 17163523},
2662
  {194681, 18023427}, {194682, 18023683}, {194683, 18023939}, {194684, 18024195},
2663
  {194685, 18024451}, {194686, 18024707}, {194687, 18024963}, {194688, 18025219},
2664
  {194689, 18025475}, {194690, 18025731}, {194691, 18025987}, {194692, 18026243},
2665
  {194693, 18026499}, {194694, 18026755}, {194695, 18027011}, {194696, 18027267},
2666
  {194697, 18027523}, {194698, 18027779}, {194699, 18028035}, {194700, 18028291},
2667
  {194701, 18028547}, {194702, 17560067}, {194703, 18028803}, {194704, 17166083},
2668
  {194705, 18029059}, {194707, 18029315}, {194708, 18029571}, {194710, 18029827},
2669
  {194711, 18030083}, {194712, 18030339}, {194713, 18030595}, {194714, 18030851},
2670
  {194715, 18031107}, {194716, 18031363}, {194717, 18031619}, {194718, 18031875},
2671
  {194719, 18032131}, {194720, 18032387}, {194721, 18032643}, {194722, 18032899},
2672
  {194723, 17623043}, {194724, 18033155}, {194725, 18033411}, {194726, 18033667},
2673
  {194727, 18033923}, {194728, 17639683}, {194729, 18033923}, {194730, 18034179},
2674
  {194731, 17623555}, {194732, 18034435}, {194733, 18034691}, {194734, 18034947},
2675
  {194735, 18035203}, {194736, 17623811}, {194737, 17553155}, {194738, 17425411},
2676
  {194739, 18035459}, {194740, 18035715}, {194741, 18035971}, {194742, 18036227},
2677
  {194743, 18036483}, {194744, 18036739}, {194745, 18036995}, {194746, 18037251},
2678
  {194747, 18037507}, {194748, 18037763}, {194749, 18038019}, {194750, 18038275},
2679
  {194751, 18038531}, {194752, 18038787}, {194753, 18039043}, {194754, 18039299},
2680
  {194755, 18039555}, {194756, 18039811}, {194757, 18040067}, {194758, 18040323},
2681
  {194759, 18040579}, {194760, 17624067}, {194761, 18040835}, {194762, 18041091},
2682
  {194763, 18041347}, {194764, 18041603}, {194765, 18041859}, {194766, 18042115},
2683
  {194767, 17624579}, {194768, 18042371}, {194769, 18042627}, {194770, 18042883},
2684
  {194771, 18043139}, {194772, 18043395}, {194773, 18043651}, {194774, 18043907},
2685
  {194775, 18044163}, {194776, 17560323}, {194777, 17641731}, {194778, 18044419},
2686
  {194779, 18044675}, {194780, 18044931}, {194781, 18045187}, {194782, 18045443},
2687
  {194783, 18045699}, {194784, 18045955}, {194785, 18046211}, {194786, 17624835},
2688
  {194787, 18046467}, {194788, 18046723}, {194789, 18046979}, {194790, 18047235},
2689
  {194791, 17652483}, {194792, 18047491}, {194793, 18047747}, {194794, 18048003},
2690
  {194795, 18048259}, {194796, 18048515}, {194797, 18048771}, {194798, 18049027},
2691
  {194799, 18049283}, {194800, 18049539}, {194801, 18049795}, {194802, 18050051},
2692
  {194803, 18050307}, {194804, 18050563}, {194805, 17577731}, {194806, 18050819},
2693
  {194807, 18051075}, {194808, 18051331}, {194809, 18051587}, {194810, 18051843},
2694
  {194811, 18052099}, {194812, 18052355}, {194813, 18052611}, {194814, 18052867},
2695
  {194815, 18053123}, {194816, 18053379}, {194817, 17625091}, {194818, 17598723},
2696
  {194819, 18053635}, {194820, 18053891}, {194821, 18054147}, {194822, 18054403},
2697
  {194823, 18054659}, {194824, 18054915}, {194825, 18055171}, {194826, 18055427},
2698
  {194827, 17642499}, {194828, 18055683}, {194829, 18055939}, {194830, 18056195},
2699
  {194831, 18056451}, {194832, 18056707}, {194833, 18056963}, {194834, 18057219},
2700
  {194835, 18057475}, {194836, 17642755}, {194837, 18057731}, {194838, 18057987},
2701
  {194839, 18058243}, {194840, 18058499}, {194841, 18058755}, {194842, 18059011},
2702
  {194843, 18059267}, {194844, 18059523}, {194845, 18059779}, {194846, 18060035},
2703
  {194847, 18060291}, {194848, 18060547}, {194849, 17643267}, {194850, 18060803},
2704
  {194851, 18061059}, {194852, 18061315}, {194853, 18061571}, {194854, 18061827},
2705
  {194855, 18062083}, {194856, 18062339}, {194857, 18062595}, {194858, 18062851},
2706
  {194859, 18063107}, {194860, 18063363}, {194862, 18063619}, {194863, 18063875},
2707
  {194864, 17643779}, {194865, 18064131}, {194866, 18064387}, {194867, 18064643},
2708
  {194868, 18064899}, {194869, 18065155}, {194870, 18065411}, {194871, 18065667},
2709
  {194872, 17574147}, {194873, 18065923}, {194874, 18066179}, {194875, 18066435},
2710
  {194876, 18066691}, {194877, 18066947}, {194878, 18067203}, {194879, 18067459},
2711
  {194880, 17645315}, {194881, 18067715}, {194882, 18067971}, {194883, 18068227},
2712
  {194884, 18068483}, {194885, 18068739}, {194886, 18068995}, {194888, 17645571},
2713
  {194889, 17652995}, {194890, 18069251}, {194891, 18069507}, {194892, 18069763},
2714
  {194893, 18070019}, {194894, 18070275}, {194895, 17564675}, {194896, 17646083},
2715
  {194897, 18070531}, {194898, 18070787}, {194899, 17627651}, {194900, 18071043},
2716
  {194901, 18071299}, {194902, 17616643}, {194903, 18071555}, {194904, 18071811},
2717
  {194905, 17628419}, {194906, 18072067}, {194907, 18072323}, {194908, 18072579},
2718
  {194909, 18072835}, {194911, 18073091}, {194912, 18073347}, {194913, 18073603},
2719
  {194914, 18073859}, {194915, 18074115}, {194916, 18074371}, {194917, 18074627},
2720
  {194918, 18074883}, {194919, 18075139}, {194920, 18075395}, {194921, 18075651},
2721
  {194922, 18075907}, {194923, 18076163}, {194924, 18076419}, {194925, 18076675},
2722
  {194926, 18076931}, {194927, 18077187}, {194928, 18077443}, {194929, 18077699},
2723
  {194930, 18077955}, {194931, 18078211}, {194932, 18078467}, {194933, 18078723},
2724
  {194934, 18078979}, {194935, 18079235}, {194936, 18079491}, {194937, 18079747},
2725
  {194938, 17629955}, {194939, 18080003}, {194940, 18080259}, {194941, 18080515},
2726
  {194942, 18080771}, {194943, 18081027}, {194944, 18081283}, {194945, 18081539},
2727
  {194946, 18081795}, {194947, 18082051}, {194948, 18082307}, {194949, 18082563},
2728
  {194950, 18082819}, {194951, 18083075}, {194952, 18083331}, {194953, 18083587},
2729
  {194954, 18083843}, {194955, 18029315}, {194956, 18084099}, {194957, 18084355},
2730
  {194958, 18084611}, {194959, 18084867}, {194960, 18085123}, {194961, 18085379},
2731
  {194962, 18085635}, {194963, 18085891}, {194964, 18086147}, {194965, 18086403},
2732
  {194966, 18086659}, {194967, 18086915}, {194968, 17578499}, {194969, 18087171},
2733
  {194970, 18087427}, {194971, 18087683}, {194972, 18087939}, {194973, 18088195},
2734
  {194974, 18088451}, {194975, 17630723}, {194976, 18088707}, {194977, 18088963},
2735
  {194978, 18089219}, {194979, 18089475}, {194980, 18089731}, {194981, 18089987},
2736
  {194982, 18090243}, {194983, 18090499}, {194984, 18090755}, {194985, 18091011},
2737
  {194986, 18091267}, {194987, 18091523}, {194988, 18091779}, {194989, 18092035},
2738
  {194990, 18092291}, {194991, 18092547}, {194992, 18092803}, {194993, 18093059},
2739
  {194994, 18093315}, {194995, 18093571}, {194996, 17563395}, {194997, 18093827},
2740
  {194998, 18094083}, {194999, 18094339}, {195000, 18094595}, {195001, 18094851},
2741
  {195002, 18095107}, {195003, 17647875}, {195004, 18095363}, {195005, 18095619},
2742
  {195006, 18095875}, {195007, 18096131}, {195008, 18096387}, {195009, 18096643},
2743
  {195010, 18096899}, {195011, 18097155}, {195012, 17189123}, {195013, 18097411},
2744
  {195014, 18097667}, {195015, 18097923}, {195016, 18098179}, {195017, 18098435},
2745
  {195018, 18098691}, {195019, 18098947}, {195020, 18099203}, {195021, 18099459},
2746
  {195022, 18099715}, {195023, 18099971}, {195024, 17649155}, {195025, 17649411},
2747
  {195026, 17190915}, {195027, 18100227}, {195028, 18100483}, {195029, 18100739},
2748
  {195030, 18100995}, {195031, 18101251}, {195032, 18101507}, {195033, 18101763},
2749
  {195034, 18102019}, {195035, 18102275}, {195036, 18102531}, {195037, 18102787},
2750
  {195038, 18103043}, {195039, 17649667}, {195040, 18103299}, {195041, 18103555},
2751
  {195042, 18103811}, {195043, 18104067}, {195044, 18104323}, {195045, 18104579},
2752
  {195046, 18104835}, {195047, 18105091}, {195048, 18105347}, {195049, 18105603},
2753
  {195050, 18105859}, {195051, 18106115}, {195052, 18106371}, {195053, 18106627},
2754
  {195054, 18106883}, {195055, 18107139}, {195056, 18107395}, {195057, 18107651},
2755
  {195058, 18107907}, {195059, 18108163}, {195060, 18108419}, {195061, 18108675},
2756
  {195062, 18108931}, {195063, 18109187}, {195064, 18109443}, {195065, 18109699},
2757
  {195066, 18109955}, {195067, 18110211}, {195068, 18110467}, {195069, 18110723},
2758
  {195070, 17651203}, {195072, 18110979}, {195073, 18111235}, {195074, 18111491},
2759
  {195075, 18111747}, {195076, 18112003}, {195077, 18112259}, {195078, 18112515},
2760
  {195079, 18112771}, {195080, 18113027}, {195081, 18113283}, {195082, 17651459},
2761
  {195083, 18113539}, {195084, 18113795}, {195085, 18114051}, {195086, 18114307},
2762
  {195087, 18114563}, {195088, 18114819}, {195089, 18115075}, {195090, 18115331},
2763
  {195091, 18115587}, {195092, 18115843}, {195093, 17203203}, {195094, 18116099},
2764
  {195095, 17204227}, {195096, 18116355}, {195097, 18116611}, {195098, 18116867},
2765
  {195099, 18117123}, {195100, 17205507}, {195101, 18117379}, {195102, 2},
2766
  {196608, 1}, {201547, 2}, {201552, 1}, {205744, 2},
2767
  {917760, 0}, {918000, 2}
2768
};
2769
2770
2771
} // namespace ada::idna
2772
#endif // ADA_IDNA_TABLES_H
2773
/* end file src/mapping_tables.cpp */
2774
2775
namespace ada::idna {
2776
2777
// This can be greatly accelerated. For now we just use a simply
2778
// binary search. In practice, you should *not* do that.
2779
79.8k
uint32_t find_range_index(uint32_t key) {
2780
  ////////////////
2781
  // This could be implemented with std::lower_bound, but we roll our own
2782
  // because we want to allow further optimizations in the future.
2783
  ////////////////
2784
79.8k
  uint32_t len = std::size(table);
2785
79.8k
  uint32_t low = 0;
2786
79.8k
  uint32_t high = len - 1;
2787
1.07M
  while (low <= high) {
2788
1.02M
    uint32_t middle_index = (low + high) >> 1;  // cannot overflow
2789
1.02M
    uint32_t middle_value = table[middle_index][0];
2790
1.02M
    if (middle_value < key) {
2791
312k
      low = middle_index + 1;
2792
710k
    } else if (middle_value > key) {
2793
682k
      high = middle_index - 1;
2794
682k
    } else {
2795
27.9k
      return middle_index;  // perfect match
2796
27.9k
    }
2797
1.02M
  }
2798
51.9k
  return low == 0 ? 0 : low - 1;
2799
79.8k
}
2800
2801
1.79k
void ascii_map(char* input, size_t length) {
2802
5.37k
  auto broadcast = [](uint8_t v) -> uint64_t {
2803
5.37k
    return 0x101010101010101ull * v;
2804
5.37k
  };
2805
1.79k
  uint64_t broadcast_80 = broadcast(0x80);
2806
1.79k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
2807
1.79k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2808
1.79k
  size_t i = 0;
2809
2810
7.50k
  for (; i + 7 < length; i += 8) {
2811
5.71k
    uint64_t word{};
2812
5.71k
    memcpy(&word, input + i, sizeof(word));
2813
5.71k
    word ^=
2814
5.71k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2815
5.71k
    memcpy(input + i, &word, sizeof(word));
2816
5.71k
  }
2817
1.79k
  if (i < length) {
2818
1.56k
    uint64_t word{};
2819
1.56k
    memcpy(&word, input + i, length - i);
2820
1.56k
    word ^=
2821
1.56k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2822
1.56k
    memcpy(input + i, &word, length - i);
2823
1.56k
  }
2824
1.79k
}
2825
2826
// Map the characters according to IDNA, returning the empty string on error.
2827
6.12k
std::u32string map(std::u32string_view input) {
2828
  //  [Map](https://www.unicode.org/reports/tr46/#ProcessingStepMap).
2829
  //  For each code point in the domain_name string, look up the status
2830
  //  value in Section 5, [IDNA Mapping
2831
  //  Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table),
2832
  //  and take the following actions:
2833
  //    * disallowed: Leave the code point unchanged in the string, and
2834
  //    record that there was an error.
2835
  //    * ignored: Remove the code point from the string. This is
2836
  //    equivalent to mapping the code point to an empty string.
2837
  //    * mapped: Replace the code point in the string by the value for
2838
  //    the mapping in Section 5, [IDNA Mapping
2839
  //    Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table).
2840
  //    * valid: Leave the code point unchanged in the string.
2841
6.12k
  static std::u32string error = U"";
2842
6.12k
  std::u32string answer;
2843
6.12k
  answer.reserve(input.size());
2844
79.8k
  for (char32_t x : input) {
2845
79.8k
    size_t index = find_range_index(x);
2846
79.8k
    uint32_t descriptor = table[index][1];
2847
79.8k
    uint8_t code = uint8_t(descriptor);
2848
79.8k
    switch (code) {
2849
433
      case 0:
2850
433
        break;  // nothing to do, ignored
2851
56.9k
      case 1:
2852
56.9k
        answer.push_back(x);  // valid, we just copy it to output
2853
56.9k
        break;
2854
166
      case 2:
2855
166
        return error;  // disallowed
2856
      // case 3 :
2857
22.3k
      default:
2858
        // We have a mapping
2859
22.3k
        {
2860
22.3k
          size_t char_count = (descriptor >> 24);
2861
22.3k
          uint16_t char_index = uint16_t(descriptor >> 8);
2862
162k
          for (size_t idx = char_index; idx < char_index + char_count; idx++) {
2863
140k
            answer.push_back(mappings[idx]);
2864
140k
          }
2865
22.3k
        }
2866
79.8k
    }
2867
79.8k
  }
2868
5.95k
  return answer;
2869
6.12k
}
2870
}  // namespace ada::idna
2871
/* end file src/mapping.cpp */
2872
/* begin file src/normalization.cpp */
2873
/* begin file src/normalization_tables.cpp */
2874
// IDNA  15.0.0
2875
2876
// clang-format off
2877
#ifndef ADA_IDNA_NORMALIZATION_TABLES_H
2878
#define ADA_IDNA_NORMALIZATION_TABLES_H
2879
#include <cstdint>
2880
2881
/**
2882
 * Unicode Standard Annex #15
2883
 *
2884
 * UNICODE NORMALIZATION FORMS
2885
 * https://www.unicode.org/reports/tr15/
2886
 *
2887
 * See https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/data/data_norm.h for reference.
2888
 */
2889
2890
namespace ada::idna {
2891
2892
const uint8_t decomposition_index[4352] = {
2893
    0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  9,  10, 11, 12, 13, 14, 15, 7,  7,
2894
    7,  7,  7,  7,  7,  7,  7,  7,  16, 7,  17, 18, 19, 20, 21, 22, 23, 24, 7,
2895
    7,  7,  7,  7,  25, 7,  26, 27, 28, 29, 30, 31, 32, 33, 7,  7,  7,  7,  7,
2896
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2897
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2898
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2899
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2900
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2901
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  34, 35, 7,  7,  7,
2902
    36, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2903
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2904
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2905
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2906
    7,  7,  37, 38, 39, 40, 41, 42, 43, 7,  7,  7,  7,  7,  7,  7,  44, 7,  7,
2907
    7,  7,  7,  7,  7,  7,  45, 46, 7,  47, 48, 49, 7,  7,  7,  50, 7,  7,  7,
2908
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2909
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2910
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2911
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2912
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2913
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2914
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2915
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2916
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2917
    7,  7,  7,  7,  7,  7,  7,  7,  7,  51, 7,  52, 53, 54, 55, 56, 7,  7,  7,
2918
    7,  7,  7,  7,  7,  57, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  58,
2919
    59, 7,  60, 61, 62, 7,  7,  7,  7,  7,  7,  7,  7,  63, 7,  7,  7,  7,  7,
2920
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2921
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2922
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2923
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2924
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2925
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2926
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2927
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2928
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2929
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2930
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2931
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2932
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2933
    64, 65, 66, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2934
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2935
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2936
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2937
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2938
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2939
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2940
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2941
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2942
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2943
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2944
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2945
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2946
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2947
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2948
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2949
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2950
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2951
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2952
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2953
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2954
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2955
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2956
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2957
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2958
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2959
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2960
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2961
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2962
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2963
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2964
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2965
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2966
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2967
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2968
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2969
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2970
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2971
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2972
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2973
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2974
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2975
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2976
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2977
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2978
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2979
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2980
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2981
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2982
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2983
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2984
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2985
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2986
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2987
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2988
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2989
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2990
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2991
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2992
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2993
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2994
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2995
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2996
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2997
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2998
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2999
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3000
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3001
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3002
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3003
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3004
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3005
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3006
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3007
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3008
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3009
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3010
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3011
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3012
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3013
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3014
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3015
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3016
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3017
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3018
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3019
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3020
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3021
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3022
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3023
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3024
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3025
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3026
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3027
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3028
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3029
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3030
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3031
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3032
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3033
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3034
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3035
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3036
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3037
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3038
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3039
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3040
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3041
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3042
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3043
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3044
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3045
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3046
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3047
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3048
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3049
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3050
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3051
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3052
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3053
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3054
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3055
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3056
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3057
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3058
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3059
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3060
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3061
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3062
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3063
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3064
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3065
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3066
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3067
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3068
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3069
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3070
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3071
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3072
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3073
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3074
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3075
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3076
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3077
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3078
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3079
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3080
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3081
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3082
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3083
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3084
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3085
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3086
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3087
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3088
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3089
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3090
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3091
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3092
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3093
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3094
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3095
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3096
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3097
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3098
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3099
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3100
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3101
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3102
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3103
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3104
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3105
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3106
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3107
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3108
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3109
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3110
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3111
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3112
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3113
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3114
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3115
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3116
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3117
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3118
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3119
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3120
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3121
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3122
    7};
3123
3124
const uint16_t decomposition_block[67][257] = {
3125
    {4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3126
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3127
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3128
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3129
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3130
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3131
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3132
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3133
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3134
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3135
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   5,   8,   8,   8,   8,
3136
     8,   8,   8,   9,   16,  17,  20,  20,  20,  20,  21,  28,  28,  29,  33,
3137
     37,  45,  48,  48,  49,  57,  61,  64,  65,  77,  89,  100, 100, 108, 116,
3138
     124, 132, 140, 148, 148, 156, 164, 172, 180, 188, 196, 204, 212, 220, 220,
3139
     228, 236, 244, 252, 260, 268, 268, 268, 276, 284, 292, 300, 308, 308, 308,
3140
     316, 324, 332, 340, 348, 356, 356, 364, 372, 380, 388, 396, 404, 412, 420,
3141
     428, 428, 436, 444, 452, 460, 468, 476, 476, 476, 484, 492, 500, 508, 516,
3142
     516, 524},
3143
    {524,  532,  540,  548,  556,  564,  572,  580,  588,  596,  604,  612,
3144
     620,  628,  636,  644,  652,  652,  652,  660,  668,  676,  684,  692,
3145
     700,  708,  716,  724,  732,  740,  748,  756,  764,  772,  780,  788,
3146
     796,  804,  812,  812,  812,  820,  828,  836,  844,  852,  860,  868,
3147
     876,  884,  885,  893,  900,  908,  916,  924,  932,  932,  940,  948,
3148
     956,  964,  972,  981,  989,  996,  996,  996,  1004, 1012, 1020, 1028,
3149
     1036, 1045, 1052, 1052, 1052, 1060, 1068, 1076, 1084, 1092, 1100, 1100,
3150
     1100, 1108, 1116, 1124, 1132, 1140, 1148, 1156, 1164, 1172, 1180, 1188,
3151
     1196, 1204, 1212, 1220, 1228, 1236, 1244, 1244, 1244, 1252, 1260, 1268,
3152
     1276, 1284, 1292, 1300, 1308, 1316, 1324, 1332, 1340, 1348, 1356, 1364,
3153
     1372, 1380, 1388, 1396, 1404, 1412, 1420, 1429, 1432, 1432, 1432, 1432,
3154
     1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3155
     1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3156
     1432, 1432, 1432, 1432, 1432, 1440, 1448, 1448, 1448, 1448, 1448, 1448,
3157
     1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1456, 1464, 1464, 1464,
3158
     1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464,
3159
     1464, 1464, 1464, 1464, 1465, 1477, 1489, 1501, 1509, 1517, 1525, 1533,
3160
     1541, 1548, 1556, 1564, 1572, 1580, 1588, 1596, 1604, 1612, 1624, 1636,
3161
     1648, 1660, 1672, 1684, 1696, 1708, 1708, 1720, 1732, 1744, 1756, 1764,
3162
     1772, 1772, 1772, 1780, 1788, 1796, 1804, 1812, 1820, 1832, 1844, 1852,
3163
     1860, 1869, 1877, 1885, 1892, 1900, 1908, 1908, 1908, 1916, 1924, 1936,
3164
     1948, 1956, 1964, 1972, 1980},
3165
    {1980, 1988, 1996, 2004, 2012, 2020, 2028, 2036, 2044, 2052, 2060, 2068,
3166
     2076, 2084, 2092, 2100, 2108, 2116, 2124, 2132, 2140, 2148, 2156, 2164,
3167
     2172, 2180, 2188, 2196, 2204, 2204, 2204, 2212, 2220, 2220, 2220, 2220,
3168
     2220, 2220, 2220, 2228, 2236, 2244, 2252, 2264, 2276, 2288, 2300, 2308,
3169
     2316, 2328, 2340, 2348, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3170
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3171
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3172
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3173
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3174
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3175
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3176
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3177
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3178
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3179
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2357, 2361, 2365, 2369,
3180
     2373, 2377, 2381, 2385, 2389, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3181
     2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3182
     2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3183
     2393, 2401, 2409, 2417, 2425, 2433, 2440, 2440, 2441, 2445, 2449, 2453,
3184
     2457, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3185
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3186
     2460, 2460, 2460, 2460, 2460},
3187
    {2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3188
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3189
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3190
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3191
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3192
     2460, 2460, 2460, 2460, 2460, 2464, 2468, 2468, 2472, 2480, 2480, 2480,
3193
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3194
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3195
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3196
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2484, 2484, 2484,
3197
     2484, 2484, 2485, 2492, 2492, 2492, 2492, 2496, 2496, 2496, 2496, 2496,
3198
     2497, 2506, 2512, 2520, 2524, 2532, 2540, 2548, 2548, 2556, 2556, 2564,
3199
     2572, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3200
     2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3201
     2584, 2584, 2584, 2592, 2600, 2608, 2616, 2624, 2632, 2644, 2644, 2644,
3202
     2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644,
3203
     2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2652,
3204
     2660, 2668, 2676, 2684, 2685, 2689, 2693, 2698, 2706, 2713, 2717, 2720,
3205
     2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3206
     2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3207
     2721, 2725, 2729, 2732, 2733, 2737, 2740, 2740, 2740, 2741, 2744, 2744,
3208
     2744, 2744, 2744, 2744, 2744},
3209
    {2744, 2752, 2760, 2760, 2768, 2768, 2768, 2768, 2776, 2776, 2776, 2776,
3210
     2776, 2784, 2792, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800,
3211
     2800, 2800, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3212
     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3213
     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2816, 2816,
3214
     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816,
3215
     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2824, 2832, 2832,
3216
     2840, 2840, 2840, 2840, 2848, 2848, 2848, 2848, 2848, 2856, 2864, 2872,
3217
     2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872,
3218
     2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2880,
3219
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3220
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3221
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3222
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3223
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3224
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3225
     2888, 2888, 2896, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904,
3226
     2904, 2904, 2904, 2904, 2904, 2912, 2920, 2928, 2936, 2936, 2936, 2944,
3227
     2952, 2952, 2952, 2960, 2968, 2976, 2984, 2992, 3000, 3000, 3000, 3008,
3228
     3016, 3024, 3032, 3040, 3048, 3048, 3048, 3056, 3064, 3072, 3080, 3088,
3229
     3096, 3104, 3112, 3120, 3128, 3136, 3144, 3144, 3144, 3152, 3160, 3160,
3230
     3160, 3160, 3160, 3160, 3160},
3231
    {3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3232
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3233
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3234
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3235
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3236
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3237
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3238
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3239
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3240
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3241
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3242
     3160, 3160, 3160, 3161, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3243
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3244
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3245
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3246
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3247
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3248
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3249
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3250
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3251
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3252
     3168, 3168, 3168, 3168, 3168},
3253
    {3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3254
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3255
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3176,
3256
     3184, 3192, 3200, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3257
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3258
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3259
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3260
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3261
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3262
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3209, 3217, 3225,
3263
     3233, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3264
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3265
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3266
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3267
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3268
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3269
     3240, 3248, 3248, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256,
3270
     3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3264, 3264, 3264, 3264,
3271
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3272
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3273
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3274
     3264, 3264, 3264, 3264, 3264},
3275
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3276
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3277
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3278
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3279
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3280
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3281
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3282
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3283
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3284
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3285
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
3286
    {3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3287
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3288
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3289
     3264, 3264, 3264, 3264, 3264, 3264, 3272, 3272, 3272, 3272, 3272, 3272,
3290
     3272, 3272, 3280, 3280, 3280, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3291
     3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3292
     3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3293
     3288, 3288, 3288, 3288, 3288, 3296, 3304, 3312, 3320, 3328, 3336, 3344,
3294
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3295
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3296
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3297
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3298
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3299
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3300
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3301
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3302
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3303
     3360, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368,
3304
     3368, 3368, 3368, 3368, 3368, 3376, 3384, 3384, 3392, 3392, 3392, 3392,
3305
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3306
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3307
     3392, 3392, 3392, 3392, 3392},
3308
    {3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3309
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3310
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3311
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3312
     3392, 3392, 3392, 3392, 3400, 3400, 3400, 3408, 3408, 3408, 3408, 3408,
3313
     3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3314
     3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3315
     3408, 3408, 3408, 3408, 3408, 3408, 3416, 3424, 3432, 3432, 3432, 3440,
3316
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3317
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3318
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3319
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3320
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3321
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3322
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3323
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3324
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3325
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3326
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3327
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3328
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3329
     3440, 3440, 3440, 3440, 3440},
3330
    {3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3331
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3332
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3333
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3334
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3335
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3336
     3440, 3448, 3448, 3448, 3456, 3464, 3464, 3464, 3464, 3464, 3464, 3464,
3337
     3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3472, 3480, 3480,
3338
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3339
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3340
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3341
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3342
     3480, 3480, 3480, 3480, 3480, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3343
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3344
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3345
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3346
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3496,
3347
     3504, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3348
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3349
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3350
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3351
     3512, 3512, 3512, 3512, 3512},
3352
    {3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3353
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3354
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3355
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3356
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3357
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3358
     3512, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3359
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3360
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3361
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3362
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3363
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3364
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3365
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3366
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3367
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3368
     3520, 3528, 3528, 3528, 3528, 3528, 3528, 3528, 3536, 3544, 3544, 3552,
3369
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3370
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3371
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3372
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3373
     3564, 3564, 3564, 3564, 3564},
3374
    {3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3375
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3376
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3377
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3378
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3379
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3380
     3564, 3564, 3564, 3572, 3580, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3381
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3382
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3383
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3384
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3385
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3386
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3387
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3388
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3389
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3390
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3391
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3392
     3588, 3588, 3588, 3596, 3596, 3604, 3616, 3624, 3624, 3624, 3624, 3624,
3393
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3394
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3395
     3624, 3624, 3624, 3624, 3624},
3396
    {3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3397
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3398
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3399
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3400
     3624, 3624, 3624, 3625, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3401
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3402
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3403
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3404
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3405
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3406
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3407
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3408
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3409
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3410
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3633,
3411
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3412
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3413
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3414
     3640, 3640, 3640, 3640, 3641, 3649, 3656, 3656, 3656, 3656, 3656, 3656,
3415
     3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3416
     3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3417
     3656, 3656, 3656, 3656, 3656},
3418
    {3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3419
     3657, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3420
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3421
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3422
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3423
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3668, 3668, 3668, 3668,
3424
     3668, 3668, 3668, 3668, 3668, 3668, 3676, 3676, 3676, 3676, 3676, 3684,
3425
     3684, 3684, 3684, 3684, 3692, 3692, 3692, 3692, 3692, 3700, 3700, 3700,
3426
     3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3708, 3708,
3427
     3708, 3708, 3708, 3708, 3708, 3708, 3708, 3708, 3716, 3716, 3724, 3733,
3428
     3744, 3753, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3772, 3772,
3429
     3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772,
3430
     3772, 3772, 3772, 3772, 3780, 3780, 3780, 3780, 3780, 3780, 3780, 3780,
3431
     3780, 3780, 3788, 3788, 3788, 3788, 3788, 3796, 3796, 3796, 3796, 3796,
3432
     3804, 3804, 3804, 3804, 3804, 3812, 3812, 3812, 3812, 3812, 3812, 3812,
3433
     3812, 3812, 3812, 3812, 3812, 3812, 3820, 3820, 3820, 3820, 3820, 3820,
3434
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3435
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3436
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3437
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3438
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3439
     3820, 3820, 3820, 3820, 3820},
3440
    {3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3441
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3442
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3443
     3820, 3820, 3820, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3444
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3445
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3446
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3447
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3448
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3449
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3450
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3451
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3452
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3453
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3454
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3455
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3456
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3457
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3458
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3459
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3460
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3461
     3829, 3832, 3832, 3832, 3832},
3462
    {3832, 3832, 3832, 3832, 3832, 3832, 3832, 3840, 3840, 3848, 3848, 3856,
3463
     3856, 3864, 3864, 3872, 3872, 3872, 3872, 3880, 3880, 3880, 3880, 3880,
3464
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3465
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3466
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3467
     3888, 3888, 3896, 3896, 3896, 3904, 3912, 3912, 3920, 3920, 3920, 3920,
3468
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3469
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3470
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3471
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3472
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3473
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3474
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3475
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3476
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3477
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3478
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3479
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3480
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3481
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3482
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3483
     3920, 3920, 3920, 3920, 3920},
3484
    {3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3485
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3486
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3487
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3921, 3925, 3929, 3932,
3488
     3933, 3937, 3941, 3945, 3949, 3953, 3957, 3961, 3965, 3969, 3973, 3976,
3489
     3977, 3981, 3985, 3989, 3993, 3997, 4001, 4005, 4009, 4013, 4017, 4021,
3490
     4025, 4029, 4033, 4037, 4041, 4045, 4048, 4049, 4053, 4057, 4061, 4065,
3491
     4069, 4073, 4077, 4081, 4085, 4089, 4093, 4097, 4101, 4105, 4109, 4113,
3492
     4117, 4121, 4125, 4129, 4133, 4137, 4141, 4145, 4149, 4153, 4157, 4160,
3493
     4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160,
3494
     4161, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3495
     4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3496
     4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4165,
3497
     4169, 4173, 4177, 4181, 4185, 4189, 4193, 4197, 4201, 4205, 4209, 4213,
3498
     4217, 4221, 4225, 4229, 4233, 4237, 4241, 4245, 4249, 4253, 4257, 4261,
3499
     4265, 4269, 4273, 4277, 4281, 4285, 4289, 4293, 4297, 4301, 4305, 4309,
3500
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3501
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3502
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3503
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3504
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3505
     4312, 4312, 4312, 4312, 4312},
3506
    {4312, 4320, 4328, 4336, 4344, 4352, 4360, 4368, 4376, 4388, 4400, 4408,
3507
     4416, 4424, 4432, 4440, 4448, 4456, 4464, 4472, 4480, 4492, 4504, 4516,
3508
     4528, 4536, 4544, 4552, 4560, 4572, 4584, 4592, 4600, 4608, 4616, 4624,
3509
     4632, 4640, 4648, 4656, 4664, 4672, 4680, 4688, 4696, 4704, 4712, 4724,
3510
     4736, 4744, 4752, 4760, 4768, 4776, 4784, 4792, 4800, 4812, 4824, 4832,
3511
     4840, 4848, 4856, 4864, 4872, 4880, 4888, 4896, 4904, 4912, 4920, 4928,
3512
     4936, 4944, 4952, 4960, 4968, 4980, 4992, 5004, 5016, 5028, 5040, 5052,
3513
     5064, 5072, 5080, 5088, 5096, 5104, 5112, 5120, 5128, 5140, 5152, 5160,
3514
     5168, 5176, 5184, 5192, 5200, 5212, 5224, 5236, 5248, 5260, 5272, 5280,
3515
     5288, 5296, 5304, 5312, 5320, 5328, 5336, 5344, 5352, 5360, 5368, 5376,
3516
     5384, 5396, 5408, 5420, 5432, 5440, 5448, 5456, 5464, 5472, 5480, 5488,
3517
     5496, 5504, 5512, 5520, 5528, 5536, 5544, 5552, 5560, 5568, 5576, 5584,
3518
     5592, 5600, 5608, 5616, 5624, 5632, 5640, 5648, 5656, 5664, 5673, 5682,
3519
     5688, 5688, 5688, 5688, 5688, 5696, 5704, 5712, 5720, 5732, 5744, 5756,
3520
     5768, 5780, 5792, 5804, 5816, 5828, 5840, 5852, 5864, 5876, 5888, 5900,
3521
     5912, 5924, 5936, 5948, 5960, 5968, 5976, 5984, 5992, 6000, 6008, 6020,
3522
     6032, 6044, 6056, 6068, 6080, 6092, 6104, 6116, 6128, 6136, 6144, 6152,
3523
     6160, 6168, 6176, 6184, 6192, 6204, 6216, 6228, 6240, 6252, 6264, 6276,
3524
     6288, 6300, 6312, 6324, 6336, 6348, 6360, 6372, 6384, 6396, 6408, 6420,
3525
     6432, 6440, 6448, 6456, 6464, 6476, 6488, 6500, 6512, 6524, 6536, 6548,
3526
     6560, 6572, 6584, 6592, 6600, 6608, 6616, 6624, 6632, 6640, 6648, 6648,
3527
     6648, 6648, 6648, 6648, 6648},
3528
    {6648, 6656, 6664, 6676, 6688, 6700, 6712, 6724, 6736, 6744, 6752, 6764,
3529
     6776, 6788, 6800, 6812, 6824, 6832, 6840, 6852, 6864, 6876, 6888, 6888,
3530
     6888, 6896, 6904, 6916, 6928, 6940, 6952, 6952, 6952, 6960, 6968, 6980,
3531
     6992, 7004, 7016, 7028, 7040, 7048, 7056, 7068, 7080, 7092, 7104, 7116,
3532
     7128, 7136, 7144, 7156, 7168, 7180, 7192, 7204, 7216, 7224, 7232, 7244,
3533
     7256, 7268, 7280, 7292, 7304, 7312, 7320, 7332, 7344, 7356, 7368, 7368,
3534
     7368, 7376, 7384, 7396, 7408, 7420, 7432, 7432, 7432, 7440, 7448, 7460,
3535
     7472, 7484, 7496, 7508, 7520, 7520, 7528, 7528, 7540, 7540, 7552, 7552,
3536
     7564, 7572, 7580, 7592, 7604, 7616, 7628, 7640, 7652, 7660, 7668, 7680,
3537
     7692, 7704, 7716, 7728, 7740, 7748, 7756, 7764, 7772, 7780, 7788, 7796,
3538
     7804, 7812, 7820, 7828, 7836, 7844, 7852, 7852, 7852, 7864, 7876, 7892,
3539
     7908, 7924, 7940, 7956, 7972, 7984, 7996, 8012, 8028, 8044, 8060, 8076,
3540
     8092, 8104, 8116, 8132, 8148, 8164, 8180, 8196, 8212, 8224, 8236, 8252,
3541
     8268, 8284, 8300, 8316, 8332, 8344, 8356, 8372, 8388, 8404, 8420, 8436,
3542
     8452, 8464, 8476, 8492, 8508, 8524, 8540, 8556, 8572, 8580, 8588, 8600,
3543
     8608, 8620, 8620, 8628, 8640, 8648, 8656, 8664, 8672, 8681, 8688, 8693,
3544
     8701, 8710, 8716, 8728, 8736, 8748, 8748, 8756, 8768, 8776, 8784, 8792,
3545
     8800, 8810, 8818, 8826, 8832, 8840, 8848, 8860, 8872, 8872, 8872, 8880,
3546
     8892, 8900, 8908, 8916, 8924, 8926, 8934, 8942, 8948, 8956, 8964, 8976,
3547
     8988, 8996, 9004, 9012, 9024, 9032, 9040, 9048, 9056, 9066, 9074, 9080,
3548
     9084, 9084, 9084, 9096, 9104, 9116, 9116, 9124, 9136, 9144, 9152, 9160,
3549
     9168, 9178, 9181, 9188, 9190},
3550
    {9190, 9194, 9197, 9201, 9205, 9209, 9213, 9217, 9221, 9225, 9229, 9232,
3551
     9232, 9232, 9232, 9232, 9232, 9233, 9236, 9236, 9236, 9236, 9236, 9237,
3552
     9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244,
3553
     9245, 9249, 9257, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9269,
3554
     9272, 9272, 9272, 9273, 9281, 9292, 9293, 9301, 9312, 9312, 9312, 9312,
3555
     9313, 9320, 9321, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9329,
3556
     9337, 9345, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352,
3557
     9352, 9352, 9352, 9353, 9368, 9368, 9368, 9368, 9368, 9368, 9368, 9369,
3558
     9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372,
3559
     9372, 9372, 9372, 9372, 9373, 9377, 9380, 9380, 9381, 9385, 9389, 9393,
3560
     9397, 9401, 9405, 9409, 9413, 9417, 9421, 9425, 9429, 9433, 9437, 9441,
3561
     9445, 9449, 9453, 9457, 9461, 9465, 9469, 9473, 9477, 9481, 9485, 9488,
3562
     9489, 9493, 9497, 9501, 9505, 9509, 9513, 9517, 9521, 9525, 9529, 9533,
3563
     9537, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540,
3564
     9541, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3565
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3566
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3567
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3568
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3569
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3570
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3571
     9548, 9548, 9548, 9548, 9549},
3572
    {9549,  9561,  9573,  9577,  9584,  9585,  9597,  9609,  9612,  9613,
3573
     9621,  9625,  9629,  9633,  9637,  9641,  9645,  9649,  9653,  9657,
3574
     9660,  9661,  9665,  9672,  9672,  9673,  9677,  9681,  9685,  9689,
3575
     9692,  9692,  9693,  9701,  9713,  9720,  9721,  9724,  9724,  9728,
3576
     9729,  9732,  9732,  9736,  9745,  9749,  9752,  9753,  9757,  9761,
3577
     9764,  9765,  9769,  9773,  9777,  9781,  9785,  9789,  9792,  9793,
3578
     9805,  9809,  9813,  9817,  9821,  9824,  9824,  9824,  9824,  9825,
3579
     9829,  9833,  9837,  9841,  9844,  9844,  9844,  9844,  9844,  9844,
3580
     9845,  9857,  9869,  9885,  9897,  9909,  9921,  9933,  9945,  9957,
3581
     9969,  9981,  9993,  10005, 10017, 10029, 10037, 10041, 10049, 10061,
3582
     10069, 10073, 10081, 10093, 10109, 10117, 10121, 10129, 10141, 10145,
3583
     10149, 10153, 10157, 10161, 10169, 10181, 10189, 10193, 10201, 10213,
3584
     10229, 10237, 10241, 10249, 10261, 10265, 10269, 10273, 10276, 10276,
3585
     10276, 10276, 10276, 10276, 10276, 10276, 10276, 10277, 10288, 10288,
3586
     10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288,
3587
     10288, 10288, 10288, 10288, 10288, 10296, 10304, 10304, 10304, 10304,
3588
     10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304,
3589
     10304, 10304, 10304, 10304, 10304, 10312, 10312, 10312, 10312, 10312,
3590
     10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3591
     10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3592
     10312, 10312, 10312, 10312, 10312, 10312, 10320, 10328, 10336, 10336,
3593
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3594
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3595
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3596
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3597
     10336, 10336, 10336, 10336, 10336, 10336, 10336},
3598
    {10336, 10336, 10336, 10336, 10336, 10344, 10344, 10344, 10344, 10344,
3599
     10352, 10352, 10352, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3600
     10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3601
     10360, 10360, 10360, 10360, 10360, 10360, 10360, 10368, 10368, 10376,
3602
     10376, 10376, 10376, 10376, 10377, 10385, 10396, 10397, 10405, 10416,
3603
     10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416,
3604
     10416, 10416, 10416, 10416, 10416, 10416, 10424, 10424, 10424, 10432,
3605
     10432, 10432, 10440, 10440, 10448, 10448, 10448, 10448, 10448, 10448,
3606
     10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448,
3607
     10448, 10448, 10448, 10448, 10448, 10448, 10448, 10456, 10456, 10464,
3608
     10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464,
3609
     10472, 10480, 10488, 10496, 10504, 10504, 10504, 10512, 10520, 10520,
3610
     10520, 10528, 10536, 10536, 10536, 10536, 10536, 10536, 10536, 10544,
3611
     10552, 10552, 10552, 10560, 10568, 10568, 10568, 10576, 10584, 10584,
3612
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3613
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3614
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3615
     10584, 10584, 10584, 10592, 10600, 10608, 10616, 10616, 10616, 10616,
3616
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3617
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3618
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3619
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3620
     10616, 10616, 10616, 10616, 10616, 10624, 10632, 10640, 10648, 10648,
3621
     10648, 10648, 10648, 10648, 10648, 10656, 10664, 10672, 10680, 10680,
3622
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3623
     10680, 10680, 10680, 10680, 10680, 10680, 10680},
3624
    {10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3625
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3626
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3627
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3628
     10680, 10680, 10684, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3629
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3630
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3631
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3632
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3633
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3634
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3635
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3636
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3637
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3638
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3639
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3640
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3641
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3642
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3643
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3644
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3645
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3646
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3647
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3648
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3649
     10688, 10688, 10688, 10688, 10688, 10688, 10688},
3650
    {10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3651
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3652
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3653
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3654
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3655
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3656
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3657
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3658
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3659
     10688, 10688, 10688, 10688, 10688, 10688, 10689, 10693, 10697, 10701,
3660
     10705, 10709, 10713, 10717, 10721, 10725, 10733, 10741, 10749, 10757,
3661
     10765, 10773, 10781, 10789, 10797, 10805, 10813, 10825, 10837, 10849,
3662
     10861, 10873, 10885, 10897, 10909, 10921, 10937, 10953, 10969, 10985,
3663
     11001, 11017, 11033, 11049, 11065, 11081, 11097, 11105, 11113, 11121,
3664
     11129, 11137, 11145, 11153, 11161, 11169, 11181, 11193, 11205, 11217,
3665
     11229, 11241, 11253, 11265, 11277, 11289, 11301, 11313, 11325, 11337,
3666
     11349, 11361, 11373, 11385, 11397, 11409, 11421, 11433, 11445, 11457,
3667
     11469, 11481, 11493, 11505, 11517, 11529, 11541, 11553, 11565, 11577,
3668
     11589, 11601, 11613, 11617, 11621, 11625, 11629, 11633, 11637, 11641,
3669
     11645, 11649, 11653, 11657, 11661, 11665, 11669, 11673, 11677, 11681,
3670
     11685, 11689, 11693, 11697, 11701, 11705, 11709, 11713, 11717, 11721,
3671
     11725, 11729, 11733, 11737, 11741, 11745, 11749, 11753, 11757, 11761,
3672
     11765, 11769, 11773, 11777, 11781, 11785, 11789, 11793, 11797, 11801,
3673
     11805, 11809, 11813, 11817, 11821, 11824, 11824, 11824, 11824, 11824,
3674
     11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3675
     11824, 11824, 11824, 11824, 11824, 11824, 11824},
3676
    {11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3677
     11824, 11824, 11825, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3678
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3679
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3680
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3681
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3682
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3683
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3684
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3685
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3686
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3687
     11840, 11840, 11840, 11840, 11840, 11840, 11841, 11853, 11861, 11872,
3688
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3689
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3690
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3691
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3692
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3693
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3694
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3695
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3696
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3697
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3698
     11872, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3699
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3700
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3701
     11880, 11880, 11880, 11880, 11880, 11880, 11880},
3702
    {11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3703
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3704
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3705
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3706
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3707
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3708
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3709
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3710
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3711
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3712
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3713
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3714
     11880, 11880, 11880, 11880, 11881, 11885, 11888, 11888, 11888, 11888,
3715
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3716
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3717
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3718
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3719
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3720
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3721
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3722
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3723
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3724
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3725
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3726
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3727
     11888, 11888, 11888, 11888, 11888, 11888, 11888},
3728
    {11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3729
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3730
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3731
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3732
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3733
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3734
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3735
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3736
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3737
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3738
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3739
     11888, 11889, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3740
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3741
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3742
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3743
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3744
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3745
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3746
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3747
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3748
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3749
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3750
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3751
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3752
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3753
     11892, 11892, 11892, 11892, 11892, 11892, 11892},
3754
    {11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3755
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3756
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3757
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3758
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3759
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3760
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3761
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3762
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3763
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3764
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3765
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3766
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3767
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3768
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3769
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11893,
3770
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3771
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3772
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3773
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3774
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3775
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3776
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3777
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3778
     11896, 11896, 11896, 11897, 11900, 11900, 11900, 11900, 11900, 11900,
3779
     11900, 11900, 11900, 11900, 11900, 11900, 11901},
3780
    {11901, 11905, 11909, 11913, 11917, 11921, 11925, 11929, 11933, 11937,
3781
     11941, 11945, 11949, 11953, 11957, 11961, 11965, 11969, 11973, 11977,
3782
     11981, 11985, 11989, 11993, 11997, 12001, 12005, 12009, 12013, 12017,
3783
     12021, 12025, 12029, 12033, 12037, 12041, 12045, 12049, 12053, 12057,
3784
     12061, 12065, 12069, 12073, 12077, 12081, 12085, 12089, 12093, 12097,
3785
     12101, 12105, 12109, 12113, 12117, 12121, 12125, 12129, 12133, 12137,
3786
     12141, 12145, 12149, 12153, 12157, 12161, 12165, 12169, 12173, 12177,
3787
     12181, 12185, 12189, 12193, 12197, 12201, 12205, 12209, 12213, 12217,
3788
     12221, 12225, 12229, 12233, 12237, 12241, 12245, 12249, 12253, 12257,
3789
     12261, 12265, 12269, 12273, 12277, 12281, 12285, 12289, 12293, 12297,
3790
     12301, 12305, 12309, 12313, 12317, 12321, 12325, 12329, 12333, 12337,
3791
     12341, 12345, 12349, 12353, 12357, 12361, 12365, 12369, 12373, 12377,
3792
     12381, 12385, 12389, 12393, 12397, 12401, 12405, 12409, 12413, 12417,
3793
     12421, 12425, 12429, 12433, 12437, 12441, 12445, 12449, 12453, 12457,
3794
     12461, 12465, 12469, 12473, 12477, 12481, 12485, 12489, 12493, 12497,
3795
     12501, 12505, 12509, 12513, 12517, 12521, 12525, 12529, 12533, 12537,
3796
     12541, 12545, 12549, 12553, 12557, 12561, 12565, 12569, 12573, 12577,
3797
     12581, 12585, 12589, 12593, 12597, 12601, 12605, 12609, 12613, 12617,
3798
     12621, 12625, 12629, 12633, 12637, 12641, 12645, 12649, 12653, 12657,
3799
     12661, 12665, 12669, 12673, 12677, 12681, 12685, 12689, 12693, 12697,
3800
     12701, 12705, 12709, 12713, 12717, 12721, 12725, 12729, 12733, 12737,
3801
     12741, 12745, 12749, 12753, 12756, 12756, 12756, 12756, 12756, 12756,
3802
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3803
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3804
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3805
     12756, 12756, 12756, 12756, 12756, 12756, 12757},
3806
    {12757, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3807
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3808
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3809
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3810
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3811
     12760, 12760, 12760, 12760, 12761, 12764, 12765, 12769, 12773, 12776,
3812
     12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776,
3813
     12776, 12776, 12776, 12776, 12776, 12776, 12776, 12784, 12784, 12792,
3814
     12792, 12800, 12800, 12808, 12808, 12816, 12816, 12824, 12824, 12832,
3815
     12832, 12840, 12840, 12848, 12848, 12856, 12856, 12864, 12864, 12872,
3816
     12872, 12872, 12880, 12880, 12888, 12888, 12896, 12896, 12896, 12896,
3817
     12896, 12896, 12896, 12904, 12912, 12912, 12920, 12928, 12928, 12936,
3818
     12944, 12944, 12952, 12960, 12960, 12968, 12976, 12976, 12976, 12976,
3819
     12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976,
3820
     12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12984,
3821
     12984, 12984, 12984, 12984, 12984, 12985, 12993, 13000, 13000, 13009,
3822
     13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016,
3823
     13016, 13016, 13016, 13024, 13024, 13032, 13032, 13040, 13040, 13048,
3824
     13048, 13056, 13056, 13064, 13064, 13072, 13072, 13080, 13080, 13088,
3825
     13088, 13096, 13096, 13104, 13104, 13112, 13112, 13112, 13120, 13120,
3826
     13128, 13128, 13136, 13136, 13136, 13136, 13136, 13136, 13136, 13144,
3827
     13152, 13152, 13160, 13168, 13168, 13176, 13184, 13184, 13192, 13200,
3828
     13200, 13208, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3829
     13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3830
     13216, 13216, 13216, 13216, 13216, 13224, 13224, 13224, 13232, 13240,
3831
     13248, 13256, 13256, 13256, 13256, 13265, 13272},
3832
    {13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3833
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3834
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3835
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3836
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13273,
3837
     13277, 13281, 13285, 13289, 13293, 13297, 13301, 13305, 13309, 13313,
3838
     13317, 13321, 13325, 13329, 13333, 13337, 13341, 13345, 13349, 13353,
3839
     13357, 13361, 13365, 13369, 13373, 13377, 13381, 13385, 13389, 13393,
3840
     13397, 13401, 13405, 13409, 13413, 13417, 13421, 13425, 13429, 13433,
3841
     13437, 13441, 13445, 13449, 13453, 13457, 13461, 13465, 13469, 13473,
3842
     13477, 13481, 13485, 13489, 13493, 13497, 13501, 13505, 13509, 13513,
3843
     13517, 13521, 13525, 13529, 13533, 13537, 13541, 13545, 13549, 13553,
3844
     13557, 13561, 13565, 13569, 13573, 13577, 13581, 13585, 13589, 13593,
3845
     13597, 13601, 13605, 13609, 13613, 13617, 13621, 13625, 13629, 13633,
3846
     13637, 13641, 13645, 13648, 13648, 13648, 13649, 13653, 13657, 13661,
3847
     13665, 13669, 13673, 13677, 13681, 13685, 13689, 13693, 13697, 13701,
3848
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3849
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3850
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3851
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3852
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3853
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3854
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3855
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3856
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3857
     13704, 13704, 13704, 13704, 13704, 13704, 13705},
3858
    {13705, 13717, 13729, 13741, 13753, 13765, 13777, 13789, 13801, 13813,
3859
     13825, 13837, 13849, 13861, 13873, 13889, 13905, 13921, 13937, 13953,
3860
     13969, 13985, 14001, 14017, 14033, 14049, 14065, 14081, 14097, 14113,
3861
     14141, 14164, 14165, 14177, 14189, 14201, 14213, 14225, 14237, 14249,
3862
     14261, 14273, 14285, 14297, 14309, 14321, 14333, 14345, 14357, 14369,
3863
     14381, 14393, 14405, 14417, 14429, 14441, 14453, 14465, 14477, 14489,
3864
     14501, 14513, 14525, 14537, 14549, 14561, 14573, 14585, 14597, 14601,
3865
     14605, 14609, 14612, 14612, 14612, 14612, 14612, 14612, 14612, 14612,
3866
     14613, 14625, 14633, 14641, 14649, 14657, 14665, 14673, 14681, 14689,
3867
     14697, 14705, 14713, 14721, 14729, 14737, 14745, 14749, 14753, 14757,
3868
     14761, 14765, 14769, 14773, 14777, 14781, 14785, 14789, 14793, 14797,
3869
     14801, 14809, 14817, 14825, 14833, 14841, 14849, 14857, 14865, 14873,
3870
     14881, 14889, 14897, 14905, 14913, 14933, 14949, 14956, 14957, 14961,
3871
     14965, 14969, 14973, 14977, 14981, 14985, 14989, 14993, 14997, 15001,
3872
     15005, 15009, 15013, 15017, 15021, 15025, 15029, 15033, 15037, 15041,
3873
     15045, 15049, 15053, 15057, 15061, 15065, 15069, 15073, 15077, 15081,
3874
     15085, 15089, 15093, 15097, 15101, 15105, 15109, 15113, 15117, 15121,
3875
     15125, 15129, 15133, 15137, 15141, 15145, 15149, 15153, 15161, 15169,
3876
     15177, 15185, 15193, 15201, 15209, 15217, 15225, 15233, 15241, 15249,
3877
     15257, 15265, 15273, 15281, 15289, 15297, 15305, 15313, 15321, 15329,
3878
     15337, 15345, 15357, 15369, 15381, 15389, 15401, 15409, 15421, 15425,
3879
     15429, 15433, 15437, 15441, 15445, 15449, 15453, 15457, 15461, 15465,
3880
     15469, 15473, 15477, 15481, 15485, 15489, 15493, 15497, 15501, 15505,
3881
     15509, 15513, 15517, 15521, 15525, 15529, 15533, 15537, 15541, 15545,
3882
     15549, 15553, 15557, 15561, 15565, 15569, 15573, 15577, 15581, 15585,
3883
     15589, 15593, 15597, 15601, 15605, 15609, 15617},
3884
    {15617, 15637, 15653, 15673, 15685, 15705, 15717, 15729, 15753, 15769,
3885
     15781, 15793, 15805, 15821, 15837, 15853, 15869, 15885, 15901, 15917,
3886
     15941, 15949, 15973, 15997, 16017, 16033, 16057, 16081, 16097, 16109,
3887
     16121, 16137, 16153, 16173, 16193, 16205, 16217, 16233, 16245, 16257,
3888
     16265, 16273, 16285, 16297, 16321, 16337, 16357, 16381, 16397, 16409,
3889
     16421, 16445, 16461, 16485, 16497, 16517, 16529, 16545, 16557, 16573,
3890
     16593, 16609, 16629, 16645, 16653, 16673, 16685, 16697, 16713, 16725,
3891
     16737, 16749, 16769, 16785, 16793, 16817, 16829, 16849, 16865, 16881,
3892
     16893, 16905, 16921, 16929, 16945, 16965, 16973, 16997, 17009, 17017,
3893
     17025, 17033, 17041, 17049, 17057, 17065, 17073, 17081, 17089, 17101,
3894
     17113, 17125, 17137, 17149, 17161, 17173, 17185, 17197, 17209, 17221,
3895
     17233, 17245, 17257, 17269, 17281, 17289, 17297, 17309, 17317, 17325,
3896
     17333, 17345, 17357, 17365, 17373, 17381, 17389, 17397, 17413, 17421,
3897
     17429, 17437, 17445, 17453, 17461, 17469, 17477, 17489, 17505, 17513,
3898
     17521, 17529, 17537, 17545, 17553, 17561, 17573, 17585, 17597, 17609,
3899
     17617, 17625, 17633, 17641, 17649, 17657, 17665, 17673, 17681, 17689,
3900
     17701, 17713, 17721, 17733, 17745, 17757, 17765, 17777, 17789, 17805,
3901
     17813, 17825, 17837, 17849, 17861, 17881, 17905, 17913, 17921, 17929,
3902
     17937, 17945, 17953, 17961, 17969, 17977, 17985, 17993, 18001, 18009,
3903
     18017, 18025, 18033, 18041, 18049, 18065, 18073, 18081, 18089, 18105,
3904
     18117, 18125, 18133, 18141, 18149, 18157, 18165, 18173, 18181, 18189,
3905
     18197, 18209, 18217, 18225, 18237, 18249, 18257, 18273, 18285, 18293,
3906
     18301, 18309, 18317, 18329, 18341, 18349, 18357, 18365, 18373, 18381,
3907
     18389, 18397, 18405, 18413, 18425, 18437, 18449, 18461, 18473, 18485,
3908
     18497, 18509, 18521, 18533, 18545, 18557, 18569, 18581, 18593, 18605,
3909
     18617, 18629, 18641, 18653, 18665, 18677, 18688},
3910
    {18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3911
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3912
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3913
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3914
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3915
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3916
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3917
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3918
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3919
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3920
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3921
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3922
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3923
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3924
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3925
     18688, 18688, 18688, 18688, 18688, 18688, 18689, 18693, 18696, 18696,
3926
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3927
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3928
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3929
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3930
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3931
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3932
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3933
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3934
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3935
     18696, 18696, 18696, 18696, 18696, 18696, 18696},
3936
    {18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3937
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3938
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3939
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3940
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3941
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3942
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3943
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3944
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3945
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3946
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3947
     18696, 18696, 18697, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3948
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3949
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3950
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3951
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3952
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3953
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3954
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3955
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3956
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3957
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3958
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3959
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3960
     18700, 18700, 18701, 18705, 18709, 18712, 18712, 18712, 18713, 18717,
3961
     18720, 18720, 18720, 18720, 18720, 18720, 18720},
3962
    {18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3963
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3964
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3965
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3966
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3967
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3968
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3969
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3970
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3971
     18720, 18720, 18721, 18725, 18729, 18733, 18736, 18736, 18736, 18736,
3972
     18736, 18736, 18736, 18736, 18736, 18737, 18740, 18740, 18740, 18740,
3973
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3974
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3975
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3976
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3977
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3978
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3979
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3980
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3981
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3982
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3983
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3984
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3985
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3986
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3987
     18740, 18740, 18740, 18740, 18740, 18740, 18740},
3988
    {18740, 18744, 18748, 18752, 18756, 18760, 18764, 18768, 18772, 18776,
3989
     18780, 18784, 18788, 18792, 18796, 18800, 18804, 18808, 18812, 18816,
3990
     18820, 18824, 18828, 18832, 18836, 18840, 18844, 18848, 18852, 18856,
3991
     18860, 18864, 18868, 18872, 18876, 18880, 18884, 18888, 18892, 18896,
3992
     18900, 18904, 18908, 18912, 18916, 18920, 18924, 18928, 18932, 18936,
3993
     18940, 18944, 18948, 18952, 18956, 18960, 18964, 18968, 18972, 18976,
3994
     18980, 18984, 18988, 18992, 18996, 19000, 19004, 19008, 19012, 19016,
3995
     19020, 19024, 19028, 19032, 19036, 19040, 19044, 19048, 19052, 19056,
3996
     19060, 19064, 19068, 19072, 19076, 19080, 19084, 19088, 19092, 19096,
3997
     19100, 19104, 19108, 19112, 19116, 19120, 19124, 19128, 19132, 19136,
3998
     19140, 19144, 19148, 19152, 19156, 19160, 19164, 19168, 19172, 19176,
3999
     19180, 19184, 19188, 19192, 19196, 19200, 19204, 19208, 19212, 19216,
4000
     19220, 19224, 19228, 19232, 19236, 19240, 19244, 19248, 19252, 19256,
4001
     19260, 19264, 19268, 19272, 19276, 19280, 19284, 19288, 19292, 19296,
4002
     19300, 19304, 19308, 19312, 19316, 19320, 19324, 19328, 19332, 19336,
4003
     19340, 19344, 19348, 19352, 19356, 19360, 19364, 19368, 19372, 19376,
4004
     19380, 19384, 19388, 19392, 19396, 19400, 19404, 19408, 19412, 19416,
4005
     19420, 19424, 19428, 19432, 19436, 19440, 19444, 19448, 19452, 19456,
4006
     19460, 19464, 19468, 19472, 19476, 19480, 19484, 19488, 19492, 19496,
4007
     19500, 19504, 19508, 19512, 19516, 19520, 19524, 19528, 19532, 19536,
4008
     19540, 19544, 19548, 19552, 19556, 19560, 19564, 19568, 19572, 19576,
4009
     19580, 19584, 19588, 19592, 19596, 19600, 19604, 19608, 19612, 19616,
4010
     19620, 19624, 19628, 19632, 19636, 19640, 19644, 19648, 19652, 19656,
4011
     19660, 19664, 19668, 19672, 19676, 19680, 19684, 19688, 19692, 19696,
4012
     19700, 19704, 19708, 19712, 19716, 19720, 19724, 19728, 19732, 19736,
4013
     19740, 19744, 19748, 19752, 19756, 19760, 19764},
4014
    {19764, 19768, 19772, 19776, 19780, 19784, 19788, 19792, 19796, 19800,
4015
     19804, 19808, 19812, 19816, 19820, 19820, 19820, 19824, 19824, 19828,
4016
     19828, 19828, 19832, 19836, 19840, 19844, 19848, 19852, 19856, 19860,
4017
     19864, 19868, 19868, 19872, 19872, 19876, 19876, 19876, 19880, 19884,
4018
     19884, 19884, 19884, 19888, 19892, 19896, 19900, 19904, 19908, 19912,
4019
     19916, 19920, 19924, 19928, 19932, 19936, 19940, 19944, 19948, 19952,
4020
     19956, 19960, 19964, 19968, 19972, 19976, 19980, 19984, 19988, 19992,
4021
     19996, 20000, 20004, 20008, 20012, 20016, 20020, 20024, 20028, 20032,
4022
     20036, 20040, 20044, 20048, 20052, 20056, 20060, 20064, 20068, 20072,
4023
     20076, 20080, 20084, 20088, 20092, 20096, 20100, 20104, 20108, 20112,
4024
     20116, 20120, 20124, 20128, 20132, 20136, 20140, 20144, 20148, 20152,
4025
     20156, 20156, 20156, 20160, 20164, 20168, 20172, 20176, 20180, 20184,
4026
     20188, 20192, 20196, 20200, 20204, 20208, 20212, 20216, 20220, 20224,
4027
     20228, 20232, 20236, 20240, 20244, 20248, 20252, 20256, 20260, 20264,
4028
     20268, 20272, 20276, 20280, 20284, 20288, 20292, 20296, 20300, 20304,
4029
     20308, 20312, 20316, 20320, 20324, 20328, 20332, 20336, 20340, 20344,
4030
     20348, 20352, 20356, 20360, 20364, 20368, 20372, 20376, 20380, 20384,
4031
     20388, 20392, 20396, 20400, 20404, 20408, 20412, 20416, 20420, 20424,
4032
     20428, 20432, 20436, 20440, 20444, 20448, 20452, 20456, 20460, 20464,
4033
     20468, 20472, 20476, 20480, 20484, 20488, 20492, 20496, 20500, 20504,
4034
     20508, 20512, 20516, 20520, 20524, 20528, 20532, 20536, 20540, 20544,
4035
     20548, 20552, 20556, 20560, 20564, 20568, 20572, 20576, 20580, 20580,
4036
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4037
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4038
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4039
     20580, 20580, 20580, 20580, 20580, 20580, 20581},
4040
    {20581, 20589, 20597, 20605, 20617, 20629, 20637, 20644, 20644, 20644,
4041
     20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20645,
4042
     20653, 20661, 20669, 20677, 20684, 20684, 20684, 20684, 20684, 20684,
4043
     20692, 20692, 20701, 20705, 20709, 20713, 20717, 20721, 20725, 20729,
4044
     20733, 20737, 20740, 20748, 20756, 20768, 20780, 20788, 20796, 20804,
4045
     20812, 20820, 20828, 20836, 20844, 20852, 20852, 20860, 20868, 20876,
4046
     20884, 20892, 20892, 20900, 20900, 20908, 20916, 20916, 20924, 20932,
4047
     20932, 20940, 20948, 20956, 20964, 20972, 20980, 20988, 20996, 21005,
4048
     21013, 21017, 21021, 21025, 21029, 21033, 21037, 21041, 21045, 21049,
4049
     21053, 21057, 21061, 21065, 21069, 21073, 21077, 21081, 21085, 21089,
4050
     21093, 21097, 21101, 21105, 21109, 21113, 21117, 21121, 21125, 21129,
4051
     21133, 21137, 21141, 21145, 21149, 21153, 21157, 21161, 21165, 21169,
4052
     21173, 21177, 21181, 21185, 21189, 21193, 21197, 21201, 21205, 21209,
4053
     21213, 21217, 21221, 21225, 21229, 21233, 21237, 21241, 21245, 21249,
4054
     21253, 21257, 21261, 21265, 21269, 21273, 21277, 21281, 21285, 21289,
4055
     21293, 21297, 21301, 21305, 21309, 21313, 21317, 21321, 21325, 21329,
4056
     21333, 21337, 21341, 21345, 21349, 21357, 21365, 21369, 21373, 21377,
4057
     21381, 21385, 21389, 21393, 21397, 21401, 21405, 21413, 21420, 21420,
4058
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4059
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4060
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4061
     21420, 21421, 21425, 21429, 21433, 21437, 21441, 21445, 21449, 21453,
4062
     21457, 21461, 21469, 21473, 21477, 21481, 21485, 21489, 21493, 21497,
4063
     21501, 21505, 21509, 21513, 21517, 21529, 21541, 21553, 21565, 21577,
4064
     21589, 21601, 21613, 21625, 21637, 21649, 21661, 21673, 21685, 21697,
4065
     21709, 21721, 21733, 21737, 21741, 21745, 21749},
4066
    {21749, 21761, 21773, 21785, 21797, 21809, 21817, 21825, 21833, 21841,
4067
     21849, 21857, 21865, 21873, 21881, 21889, 21897, 21905, 21913, 21921,
4068
     21929, 21937, 21945, 21953, 21961, 21969, 21977, 21985, 21993, 22001,
4069
     22009, 22017, 22025, 22033, 22041, 22049, 22057, 22065, 22073, 22081,
4070
     22089, 22097, 22105, 22113, 22121, 22129, 22137, 22145, 22153, 22161,
4071
     22169, 22177, 22185, 22193, 22201, 22209, 22217, 22225, 22233, 22241,
4072
     22249, 22257, 22265, 22273, 22281, 22289, 22297, 22305, 22313, 22321,
4073
     22329, 22337, 22345, 22353, 22361, 22369, 22377, 22385, 22393, 22401,
4074
     22409, 22417, 22425, 22433, 22441, 22449, 22457, 22465, 22473, 22481,
4075
     22489, 22497, 22505, 22513, 22521, 22533, 22545, 22557, 22569, 22581,
4076
     22593, 22605, 22617, 22629, 22641, 22653, 22665, 22673, 22681, 22689,
4077
     22697, 22705, 22713, 22721, 22729, 22737, 22745, 22753, 22761, 22769,
4078
     22777, 22785, 22793, 22801, 22809, 22817, 22825, 22833, 22841, 22849,
4079
     22857, 22865, 22873, 22881, 22889, 22897, 22905, 22913, 22921, 22929,
4080
     22937, 22945, 22953, 22961, 22969, 22977, 22985, 22993, 23001, 23009,
4081
     23017, 23025, 23037, 23049, 23061, 23073, 23085, 23093, 23101, 23109,
4082
     23117, 23125, 23133, 23141, 23149, 23157, 23165, 23173, 23181, 23189,
4083
     23197, 23205, 23213, 23221, 23229, 23237, 23245, 23253, 23261, 23269,
4084
     23277, 23285, 23293, 23301, 23309, 23317, 23325, 23333, 23341, 23349,
4085
     23357, 23365, 23373, 23381, 23389, 23397, 23405, 23413, 23421, 23429,
4086
     23437, 23445, 23453, 23461, 23469, 23477, 23485, 23493, 23501, 23509,
4087
     23517, 23525, 23533, 23541, 23549, 23557, 23565, 23573, 23581, 23589,
4088
     23597, 23605, 23613, 23621, 23633, 23645, 23653, 23661, 23669, 23677,
4089
     23685, 23693, 23701, 23709, 23717, 23725, 23733, 23741, 23749, 23757,
4090
     23765, 23773, 23781, 23793, 23805, 23817, 23825, 23833, 23841, 23849,
4091
     23857, 23865, 23873, 23881, 23889, 23897, 23905},
4092
    {23905, 23913, 23921, 23929, 23937, 23945, 23953, 23961, 23969, 23977,
4093
     23985, 23993, 24001, 24009, 24017, 24025, 24033, 24041, 24049, 24057,
4094
     24065, 24073, 24081, 24089, 24097, 24105, 24113, 24121, 24129, 24137,
4095
     24145, 24153, 24161, 24169, 24177, 24185, 24193, 24201, 24209, 24217,
4096
     24225, 24233, 24241, 24249, 24257, 24265, 24273, 24281, 24289, 24297,
4097
     24305, 24313, 24321, 24329, 24337, 24345, 24353, 24361, 24369, 24377,
4098
     24385, 24393, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4099
     24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4100
     24401, 24413, 24425, 24437, 24449, 24461, 24473, 24485, 24497, 24509,
4101
     24521, 24533, 24545, 24557, 24569, 24581, 24593, 24605, 24617, 24629,
4102
     24641, 24653, 24665, 24677, 24689, 24701, 24713, 24725, 24737, 24749,
4103
     24761, 24773, 24785, 24797, 24809, 24821, 24833, 24845, 24857, 24869,
4104
     24881, 24893, 24905, 24917, 24929, 24941, 24953, 24965, 24977, 24989,
4105
     25001, 25013, 25025, 25037, 25049, 25061, 25073, 25085, 25097, 25109,
4106
     25121, 25133, 25145, 25157, 25168, 25168, 25169, 25181, 25193, 25205,
4107
     25217, 25229, 25241, 25253, 25265, 25277, 25289, 25301, 25313, 25325,
4108
     25337, 25349, 25361, 25373, 25385, 25397, 25409, 25421, 25433, 25445,
4109
     25457, 25469, 25481, 25493, 25505, 25517, 25529, 25541, 25553, 25565,
4110
     25577, 25589, 25601, 25613, 25625, 25637, 25649, 25661, 25673, 25685,
4111
     25697, 25709, 25721, 25733, 25745, 25757, 25769, 25781, 25793, 25805,
4112
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4113
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4114
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4115
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4116
     25817, 25829, 25841, 25857, 25873, 25889, 25905, 25921, 25937, 25953,
4117
     25965, 26037, 26069, 26084, 26084, 26084, 26084},
4118
    {26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084,
4119
     26084, 26084, 26084, 26084, 26084, 26084, 26085, 26089, 26093, 26097,
4120
     26101, 26105, 26109, 26113, 26117, 26121, 26132, 26132, 26132, 26132,
4121
     26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132,
4122
     26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26133, 26141,
4123
     26145, 26149, 26153, 26157, 26161, 26165, 26169, 26173, 26177, 26181,
4124
     26185, 26189, 26193, 26197, 26201, 26205, 26209, 26213, 26217, 26220,
4125
     26220, 26221, 26225, 26229, 26237, 26245, 26253, 26261, 26265, 26269,
4126
     26273, 26277, 26281, 26284, 26285, 26289, 26293, 26297, 26301, 26305,
4127
     26309, 26313, 26317, 26321, 26325, 26329, 26333, 26337, 26341, 26345,
4128
     26349, 26353, 26357, 26360, 26361, 26365, 26369, 26373, 26376, 26376,
4129
     26376, 26376, 26377, 26385, 26393, 26400, 26401, 26408, 26409, 26417,
4130
     26425, 26433, 26441, 26449, 26457, 26465, 26473, 26481, 26489, 26493,
4131
     26501, 26509, 26517, 26525, 26533, 26541, 26549, 26557, 26565, 26573,
4132
     26581, 26589, 26593, 26597, 26601, 26605, 26609, 26613, 26617, 26621,
4133
     26625, 26629, 26633, 26637, 26641, 26645, 26649, 26653, 26657, 26661,
4134
     26665, 26669, 26673, 26677, 26681, 26685, 26689, 26693, 26697, 26701,
4135
     26705, 26709, 26713, 26717, 26721, 26725, 26729, 26733, 26737, 26741,
4136
     26745, 26749, 26753, 26757, 26761, 26765, 26769, 26773, 26777, 26781,
4137
     26785, 26789, 26793, 26797, 26801, 26805, 26809, 26813, 26817, 26821,
4138
     26825, 26829, 26833, 26837, 26841, 26845, 26849, 26853, 26857, 26861,
4139
     26865, 26869, 26873, 26877, 26881, 26885, 26889, 26893, 26897, 26901,
4140
     26905, 26909, 26913, 26917, 26921, 26925, 26929, 26933, 26937, 26941,
4141
     26945, 26949, 26953, 26957, 26961, 26965, 26969, 26973, 26977, 26981,
4142
     26985, 26989, 26993, 26997, 27001, 27005, 27017, 27029, 27041, 27053,
4143
     27065, 27077, 27085, 27092, 27092, 27092, 27092},
4144
    {27092, 27093, 27097, 27101, 27105, 27109, 27113, 27117, 27121, 27125,
4145
     27129, 27133, 27137, 27141, 27145, 27149, 27153, 27157, 27161, 27165,
4146
     27169, 27173, 27177, 27181, 27185, 27189, 27193, 27197, 27201, 27205,
4147
     27209, 27213, 27217, 27221, 27225, 27229, 27233, 27237, 27241, 27245,
4148
     27249, 27253, 27257, 27261, 27265, 27269, 27273, 27277, 27281, 27285,
4149
     27289, 27293, 27297, 27301, 27305, 27309, 27313, 27317, 27321, 27325,
4150
     27329, 27333, 27337, 27341, 27345, 27349, 27353, 27357, 27361, 27365,
4151
     27369, 27373, 27377, 27381, 27385, 27389, 27393, 27397, 27401, 27405,
4152
     27409, 27413, 27417, 27421, 27425, 27429, 27433, 27437, 27441, 27445,
4153
     27449, 27453, 27457, 27461, 27465, 27469, 27473, 27477, 27481, 27485,
4154
     27489, 27493, 27497, 27501, 27505, 27509, 27513, 27517, 27521, 27525,
4155
     27529, 27533, 27537, 27541, 27545, 27549, 27553, 27557, 27561, 27565,
4156
     27569, 27573, 27577, 27581, 27585, 27589, 27593, 27597, 27601, 27605,
4157
     27609, 27613, 27617, 27621, 27625, 27629, 27633, 27637, 27641, 27645,
4158
     27649, 27653, 27657, 27661, 27665, 27669, 27673, 27677, 27681, 27685,
4159
     27689, 27693, 27697, 27701, 27705, 27709, 27713, 27717, 27721, 27725,
4160
     27729, 27733, 27737, 27741, 27745, 27749, 27753, 27757, 27761, 27765,
4161
     27769, 27773, 27777, 27781, 27785, 27789, 27793, 27797, 27801, 27805,
4162
     27809, 27813, 27817, 27821, 27825, 27829, 27833, 27837, 27841, 27845,
4163
     27849, 27852, 27852, 27852, 27853, 27857, 27861, 27865, 27869, 27873,
4164
     27876, 27876, 27877, 27881, 27885, 27889, 27893, 27897, 27900, 27900,
4165
     27901, 27905, 27909, 27913, 27917, 27921, 27924, 27924, 27925, 27929,
4166
     27933, 27936, 27936, 27936, 27937, 27941, 27945, 27949, 27957, 27961,
4167
     27965, 27968, 27969, 27973, 27977, 27981, 27985, 27989, 27993, 27996,
4168
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4169
     27996, 27996, 27996, 27996, 27996, 27996, 27996},
4170
    {27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4171
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4172
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4173
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4174
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4175
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4176
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4177
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4178
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4179
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4180
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4181
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4182
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27997,
4183
     28001, 28005, 28009, 28013, 28016, 28017, 28021, 28025, 28029, 28033,
4184
     28037, 28041, 28045, 28049, 28053, 28057, 28061, 28065, 28069, 28073,
4185
     28077, 28081, 28085, 28089, 28093, 28097, 28101, 28105, 28109, 28113,
4186
     28117, 28121, 28125, 28129, 28133, 28137, 28141, 28145, 28149, 28153,
4187
     28157, 28161, 28165, 28169, 28173, 28177, 28181, 28184, 28185, 28189,
4188
     28193, 28197, 28201, 28205, 28209, 28213, 28217, 28220, 28220, 28220,
4189
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4190
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4191
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4192
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4193
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4194
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4195
     28220, 28220, 28220, 28220, 28220, 28220, 28220},
4196
    {28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4197
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4198
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4199
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4200
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4201
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4202
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4203
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4204
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4205
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4206
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4207
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4208
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4209
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4210
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4211
     28220, 28220, 28220, 28220, 28220, 28228, 28228, 28236, 28236, 28236,
4212
     28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236,
4213
     28236, 28236, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4214
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4215
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4216
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4217
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4218
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4219
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4220
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4221
     28244, 28244, 28244, 28244, 28244, 28244, 28244},
4222
    {28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4223
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4224
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4225
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4226
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28252, 28260, 28260,
4227
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4228
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4229
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4230
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4231
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4232
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4233
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4234
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4235
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4236
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4237
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4238
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4239
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4240
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4241
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4242
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4243
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4244
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4245
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4246
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4247
     28260, 28260, 28260, 28260, 28260, 28260, 28260},
4248
    {28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4249
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4250
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4251
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4252
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4253
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4254
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4255
     28260, 28260, 28260, 28260, 28260, 28260, 28268, 28276, 28276, 28276,
4256
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4257
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4258
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4259
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4260
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4261
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4262
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4263
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4264
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4265
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4266
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4267
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4268
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4269
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4270
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4271
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4272
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4273
     28276, 28276, 28276, 28276, 28276, 28276, 28276},
4274
    {28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4275
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4276
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4277
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4278
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4279
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4280
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4281
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4282
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4283
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4284
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4285
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4286
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4287
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4288
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4289
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4290
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4291
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4292
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28284, 28292,
4293
     28292, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4294
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4295
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4296
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4297
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4298
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4299
     28300, 28300, 28300, 28300, 28300, 28300, 28300},
4300
    {28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4301
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4302
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4303
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4304
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4305
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4306
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4307
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4308
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4309
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4310
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4311
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4312
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4313
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4314
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4315
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4316
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4317
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4318
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28308, 28316, 28316,
4319
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4320
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4321
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4322
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4323
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4324
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4325
     28316, 28316, 28316, 28316, 28316, 28316, 28316},
4326
    {28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4327
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4328
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4329
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4330
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4331
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28324, 28324, 28324,
4332
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4333
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4334
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4335
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4336
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4337
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4338
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4339
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4340
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4341
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4342
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4343
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4344
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4345
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4346
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4347
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4348
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4349
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4350
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4351
     28324, 28324, 28324, 28324, 28324, 28324, 28324},
4352
    {28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4353
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4354
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4355
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4356
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4357
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4358
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4359
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4360
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4361
     28324, 28324, 28324, 28324, 28324, 28332, 28340, 28352, 28364, 28376,
4362
     28388, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4363
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4364
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4365
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4366
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4367
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4368
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4369
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4370
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28408, 28416,
4371
     28428, 28440, 28452, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4372
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4373
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4374
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4375
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4376
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4377
     28464, 28464, 28464, 28464, 28464, 28464, 28464},
4378
    {28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4379
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4380
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4381
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4382
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4383
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4384
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4385
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4386
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4387
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4388
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4389
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4390
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4391
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4392
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4393
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4394
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4395
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4396
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4397
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4398
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4399
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4400
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4401
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4402
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4403
     28464, 28464, 28464, 28464, 28464, 28464, 28465},
4404
    {28465, 28469, 28473, 28477, 28481, 28485, 28489, 28493, 28497, 28501,
4405
     28505, 28509, 28513, 28517, 28521, 28525, 28529, 28533, 28537, 28541,
4406
     28545, 28549, 28553, 28557, 28561, 28565, 28569, 28573, 28577, 28581,
4407
     28585, 28589, 28593, 28597, 28601, 28605, 28609, 28613, 28617, 28621,
4408
     28625, 28629, 28633, 28637, 28641, 28645, 28649, 28653, 28657, 28661,
4409
     28665, 28669, 28673, 28677, 28681, 28685, 28689, 28693, 28697, 28701,
4410
     28705, 28709, 28713, 28717, 28721, 28725, 28729, 28733, 28737, 28741,
4411
     28745, 28749, 28753, 28757, 28761, 28765, 28769, 28773, 28777, 28781,
4412
     28785, 28789, 28793, 28797, 28801, 28804, 28805, 28809, 28813, 28817,
4413
     28821, 28825, 28829, 28833, 28837, 28841, 28845, 28849, 28853, 28857,
4414
     28861, 28865, 28869, 28873, 28877, 28881, 28885, 28889, 28893, 28897,
4415
     28901, 28905, 28909, 28913, 28917, 28921, 28925, 28929, 28933, 28937,
4416
     28941, 28945, 28949, 28953, 28957, 28961, 28965, 28969, 28973, 28977,
4417
     28981, 28985, 28989, 28993, 28997, 29001, 29005, 29009, 29013, 29017,
4418
     29021, 29025, 29029, 29033, 29037, 29041, 29045, 29049, 29053, 29057,
4419
     29061, 29065, 29069, 29073, 29077, 29081, 29085, 29088, 29089, 29093,
4420
     29096, 29096, 29097, 29100, 29100, 29101, 29105, 29108, 29108, 29109,
4421
     29113, 29117, 29121, 29124, 29125, 29129, 29133, 29137, 29141, 29145,
4422
     29149, 29153, 29157, 29161, 29165, 29169, 29172, 29173, 29176, 29177,
4423
     29181, 29185, 29189, 29193, 29197, 29201, 29204, 29205, 29209, 29213,
4424
     29217, 29221, 29225, 29229, 29233, 29237, 29241, 29245, 29249, 29253,
4425
     29257, 29261, 29265, 29269, 29273, 29277, 29281, 29285, 29289, 29293,
4426
     29297, 29301, 29305, 29309, 29313, 29317, 29321, 29325, 29329, 29333,
4427
     29337, 29341, 29345, 29349, 29353, 29357, 29361, 29365, 29369, 29373,
4428
     29377, 29381, 29385, 29389, 29393, 29397, 29401, 29405, 29409, 29413,
4429
     29417, 29421, 29425, 29429, 29433, 29437, 29441},
4430
    {29441, 29445, 29449, 29453, 29457, 29461, 29464, 29465, 29469, 29473,
4431
     29477, 29480, 29480, 29481, 29485, 29489, 29493, 29497, 29501, 29505,
4432
     29509, 29512, 29513, 29517, 29521, 29525, 29529, 29533, 29537, 29540,
4433
     29541, 29545, 29549, 29553, 29557, 29561, 29565, 29569, 29573, 29577,
4434
     29581, 29585, 29589, 29593, 29597, 29601, 29605, 29609, 29613, 29617,
4435
     29621, 29625, 29629, 29633, 29637, 29641, 29645, 29649, 29652, 29653,
4436
     29657, 29661, 29665, 29668, 29669, 29673, 29677, 29681, 29685, 29688,
4437
     29689, 29692, 29692, 29692, 29693, 29697, 29701, 29705, 29709, 29713,
4438
     29717, 29720, 29721, 29725, 29729, 29733, 29737, 29741, 29745, 29749,
4439
     29753, 29757, 29761, 29765, 29769, 29773, 29777, 29781, 29785, 29789,
4440
     29793, 29797, 29801, 29805, 29809, 29813, 29817, 29821, 29825, 29829,
4441
     29833, 29837, 29841, 29845, 29849, 29853, 29857, 29861, 29865, 29869,
4442
     29873, 29877, 29881, 29885, 29889, 29893, 29897, 29901, 29905, 29909,
4443
     29913, 29917, 29921, 29925, 29929, 29933, 29937, 29941, 29945, 29949,
4444
     29953, 29957, 29961, 29965, 29969, 29973, 29977, 29981, 29985, 29989,
4445
     29993, 29997, 30001, 30005, 30009, 30013, 30017, 30021, 30025, 30029,
4446
     30033, 30037, 30041, 30045, 30049, 30053, 30057, 30061, 30065, 30069,
4447
     30073, 30077, 30081, 30085, 30089, 30093, 30097, 30101, 30105, 30109,
4448
     30113, 30117, 30121, 30125, 30129, 30133, 30137, 30141, 30145, 30149,
4449
     30153, 30157, 30161, 30165, 30169, 30173, 30177, 30181, 30185, 30189,
4450
     30193, 30197, 30201, 30205, 30209, 30213, 30217, 30221, 30225, 30229,
4451
     30233, 30237, 30241, 30245, 30249, 30253, 30257, 30261, 30265, 30269,
4452
     30273, 30277, 30281, 30285, 30289, 30293, 30297, 30301, 30305, 30309,
4453
     30313, 30317, 30321, 30325, 30329, 30333, 30337, 30341, 30345, 30349,
4454
     30353, 30357, 30361, 30365, 30369, 30373, 30377, 30381, 30385, 30389,
4455
     30393, 30397, 30401, 30405, 30409, 30413, 30417},
4456
    {30417, 30421, 30425, 30429, 30433, 30437, 30441, 30445, 30449, 30453,
4457
     30457, 30461, 30465, 30469, 30473, 30477, 30481, 30485, 30489, 30493,
4458
     30497, 30501, 30505, 30509, 30513, 30517, 30521, 30525, 30529, 30533,
4459
     30537, 30541, 30545, 30549, 30553, 30557, 30561, 30565, 30569, 30573,
4460
     30577, 30581, 30585, 30589, 30593, 30597, 30601, 30605, 30609, 30613,
4461
     30617, 30621, 30625, 30629, 30633, 30637, 30641, 30645, 30649, 30653,
4462
     30657, 30661, 30665, 30669, 30673, 30677, 30681, 30685, 30689, 30693,
4463
     30697, 30701, 30705, 30709, 30713, 30717, 30721, 30725, 30729, 30733,
4464
     30737, 30741, 30745, 30749, 30753, 30757, 30761, 30765, 30769, 30773,
4465
     30777, 30781, 30785, 30789, 30793, 30797, 30801, 30805, 30809, 30813,
4466
     30817, 30821, 30825, 30829, 30833, 30837, 30841, 30845, 30849, 30853,
4467
     30857, 30861, 30865, 30869, 30873, 30877, 30881, 30885, 30889, 30893,
4468
     30897, 30901, 30905, 30909, 30913, 30917, 30921, 30925, 30929, 30933,
4469
     30937, 30941, 30945, 30949, 30953, 30957, 30961, 30965, 30969, 30973,
4470
     30977, 30981, 30985, 30989, 30993, 30997, 31001, 31005, 31009, 31013,
4471
     31017, 31021, 31025, 31029, 31033, 31037, 31041, 31045, 31049, 31053,
4472
     31057, 31061, 31065, 31069, 31073, 31077, 31080, 31080, 31081, 31085,
4473
     31089, 31093, 31097, 31101, 31105, 31109, 31113, 31117, 31121, 31125,
4474
     31129, 31133, 31137, 31141, 31145, 31149, 31153, 31157, 31161, 31165,
4475
     31169, 31173, 31177, 31181, 31185, 31189, 31193, 31197, 31201, 31205,
4476
     31209, 31213, 31217, 31221, 31225, 31229, 31233, 31237, 31241, 31245,
4477
     31249, 31253, 31257, 31261, 31265, 31269, 31273, 31277, 31281, 31285,
4478
     31289, 31293, 31297, 31301, 31305, 31309, 31313, 31317, 31321, 31325,
4479
     31329, 31333, 31337, 31341, 31345, 31349, 31353, 31357, 31361, 31365,
4480
     31369, 31373, 31377, 31381, 31385, 31389, 31393, 31397, 31401, 31405,
4481
     31409, 31413, 31417, 31421, 31425, 31429, 31433},
4482
    {31433, 31437, 31441, 31445, 31449, 31453, 31457, 31461, 31465, 31469,
4483
     31473, 31477, 31481, 31485, 31489, 31493, 31497, 31501, 31505, 31509,
4484
     31513, 31517, 31521, 31525, 31529, 31533, 31537, 31541, 31545, 31549,
4485
     31553, 31557, 31561, 31565, 31569, 31573, 31577, 31581, 31585, 31589,
4486
     31593, 31597, 31601, 31605, 31609, 31613, 31617, 31621, 31625, 31629,
4487
     31633, 31637, 31641, 31645, 31649, 31653, 31657, 31661, 31665, 31669,
4488
     31673, 31677, 31681, 31685, 31689, 31693, 31697, 31701, 31705, 31709,
4489
     31713, 31717, 31721, 31725, 31729, 31733, 31737, 31741, 31745, 31749,
4490
     31753, 31757, 31761, 31765, 31769, 31773, 31777, 31781, 31785, 31789,
4491
     31793, 31797, 31801, 31805, 31809, 31813, 31817, 31821, 31825, 31829,
4492
     31833, 31837, 31841, 31845, 31849, 31853, 31857, 31861, 31865, 31869,
4493
     31873, 31877, 31881, 31885, 31889, 31893, 31897, 31901, 31905, 31909,
4494
     31913, 31917, 31921, 31925, 31929, 31933, 31937, 31941, 31945, 31949,
4495
     31953, 31957, 31961, 31965, 31969, 31973, 31977, 31981, 31985, 31989,
4496
     31993, 31997, 32001, 32005, 32009, 32013, 32017, 32021, 32025, 32029,
4497
     32033, 32037, 32041, 32045, 32049, 32053, 32057, 32061, 32065, 32069,
4498
     32073, 32077, 32081, 32085, 32089, 32093, 32097, 32101, 32105, 32109,
4499
     32113, 32117, 32121, 32125, 32129, 32133, 32137, 32141, 32145, 32149,
4500
     32153, 32157, 32161, 32165, 32169, 32173, 32177, 32181, 32185, 32189,
4501
     32193, 32197, 32201, 32205, 32209, 32213, 32217, 32221, 32225, 32229,
4502
     32233, 32237, 32241, 32245, 32248, 32248, 32249, 32253, 32257, 32261,
4503
     32265, 32269, 32273, 32277, 32281, 32285, 32289, 32293, 32297, 32301,
4504
     32305, 32309, 32313, 32317, 32321, 32325, 32329, 32333, 32337, 32341,
4505
     32345, 32349, 32353, 32357, 32361, 32365, 32369, 32373, 32377, 32381,
4506
     32385, 32389, 32393, 32397, 32401, 32405, 32409, 32413, 32417, 32421,
4507
     32425, 32429, 32433, 32437, 32441, 32445, 32448},
4508
    {32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4509
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4510
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4511
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4512
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32449, 32453,
4513
     32457, 32461, 32465, 32469, 32473, 32477, 32481, 32485, 32489, 32493,
4514
     32497, 32501, 32505, 32509, 32513, 32517, 32521, 32525, 32529, 32533,
4515
     32537, 32541, 32545, 32549, 32553, 32557, 32561, 32565, 32569, 32573,
4516
     32577, 32581, 32585, 32589, 32593, 32597, 32601, 32605, 32609, 32613,
4517
     32617, 32621, 32625, 32629, 32633, 32637, 32641, 32645, 32649, 32653,
4518
     32657, 32661, 32665, 32669, 32673, 32677, 32681, 32685, 32689, 32693,
4519
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4520
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4521
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4522
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4523
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4524
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4525
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4526
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4527
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4528
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4529
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4530
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4531
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4532
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4533
     32696, 32696, 32696, 32696, 32696, 32696, 32696},
4534
    {32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4535
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4536
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4537
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4538
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4539
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4540
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4541
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4542
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4543
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4544
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4545
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4546
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4547
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4548
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4549
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4550
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4551
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4552
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4553
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4554
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4555
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4556
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4557
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4558
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4559
     32696, 32696, 32696, 32696, 32696, 32696, 32697},
4560
    {32697, 32701, 32705, 32709, 32712, 32713, 32717, 32721, 32725, 32729,
4561
     32733, 32737, 32741, 32745, 32749, 32753, 32757, 32761, 32765, 32769,
4562
     32773, 32777, 32781, 32785, 32789, 32793, 32797, 32801, 32805, 32809,
4563
     32813, 32817, 32820, 32821, 32825, 32828, 32829, 32832, 32832, 32833,
4564
     32836, 32837, 32841, 32845, 32849, 32853, 32857, 32861, 32865, 32869,
4565
     32873, 32876, 32877, 32881, 32885, 32889, 32892, 32893, 32896, 32897,
4566
     32900, 32900, 32900, 32900, 32900, 32900, 32901, 32904, 32904, 32904,
4567
     32904, 32905, 32908, 32909, 32912, 32913, 32916, 32917, 32921, 32925,
4568
     32928, 32929, 32933, 32936, 32937, 32940, 32940, 32941, 32944, 32945,
4569
     32948, 32949, 32952, 32953, 32956, 32957, 32960, 32961, 32965, 32968,
4570
     32969, 32972, 32972, 32973, 32977, 32981, 32985, 32988, 32989, 32993,
4571
     32997, 33001, 33005, 33009, 33013, 33016, 33017, 33021, 33025, 33029,
4572
     33032, 33033, 33037, 33041, 33045, 33048, 33049, 33052, 33053, 33057,
4573
     33061, 33065, 33069, 33073, 33077, 33081, 33085, 33089, 33092, 33093,
4574
     33097, 33101, 33105, 33109, 33113, 33117, 33121, 33125, 33129, 33133,
4575
     33137, 33141, 33145, 33149, 33153, 33157, 33160, 33160, 33160, 33160,
4576
     33160, 33161, 33165, 33169, 33172, 33173, 33177, 33181, 33185, 33189,
4577
     33192, 33193, 33197, 33201, 33205, 33209, 33213, 33217, 33221, 33225,
4578
     33229, 33233, 33237, 33241, 33245, 33249, 33253, 33257, 33260, 33260,
4579
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4580
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4581
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4582
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4583
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4584
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4585
     33260, 33260, 33260, 33260, 33260, 33260, 33260},
4586
    {33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4587
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4588
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4589
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4590
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4591
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4592
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4593
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4594
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4595
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4596
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4597
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4598
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4599
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4600
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4601
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4602
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4603
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4604
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4605
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4606
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4607
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4608
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4609
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4610
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4611
     33260, 33260, 33260, 33260, 33260, 33260, 33261},
4612
    {33261, 33269, 33277, 33285, 33293, 33301, 33309, 33317, 33325, 33333,
4613
     33341, 33348, 33348, 33348, 33348, 33348, 33349, 33361, 33373, 33385,
4614
     33397, 33409, 33421, 33433, 33445, 33457, 33469, 33481, 33493, 33505,
4615
     33517, 33529, 33541, 33553, 33565, 33577, 33589, 33601, 33613, 33625,
4616
     33637, 33649, 33661, 33673, 33677, 33681, 33689, 33696, 33697, 33701,
4617
     33705, 33709, 33713, 33717, 33721, 33725, 33729, 33733, 33737, 33741,
4618
     33745, 33749, 33753, 33757, 33761, 33765, 33769, 33773, 33777, 33781,
4619
     33785, 33789, 33793, 33797, 33801, 33809, 33817, 33825, 33833, 33845,
4620
     33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4621
     33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4622
     33852, 33852, 33852, 33852, 33852, 33852, 33853, 33861, 33869, 33876,
4623
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4624
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4625
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4626
     33876, 33876, 33876, 33876, 33877, 33884, 33884, 33884, 33884, 33884,
4627
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4628
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4629
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4630
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4631
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4632
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4633
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4634
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4635
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4636
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4637
     33884, 33884, 33884, 33884, 33884, 33884, 33885},
4638
    {33885, 33893, 33901, 33904, 33904, 33904, 33904, 33904, 33904, 33904,
4639
     33904, 33904, 33904, 33904, 33904, 33904, 33905, 33909, 33913, 33917,
4640
     33925, 33929, 33933, 33937, 33941, 33945, 33949, 33953, 33957, 33961,
4641
     33965, 33969, 33973, 33977, 33981, 33985, 33989, 33993, 33997, 34001,
4642
     34005, 34009, 34013, 34017, 34021, 34025, 34029, 34033, 34037, 34041,
4643
     34045, 34049, 34053, 34057, 34061, 34065, 34069, 34073, 34077, 34081,
4644
     34084, 34084, 34084, 34084, 34085, 34097, 34109, 34121, 34133, 34145,
4645
     34157, 34169, 34181, 34192, 34192, 34192, 34192, 34192, 34192, 34192,
4646
     34193, 34197, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4647
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4648
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4649
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4650
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4651
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4652
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4653
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4654
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4655
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4656
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4657
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4658
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4659
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4660
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4661
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4662
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4663
     34200, 34200, 34200, 34200, 34200, 34200, 34200},
4664
    {34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4665
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4666
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4667
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4668
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4669
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4670
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4671
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4672
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4673
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4674
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4675
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4676
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4677
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4678
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4679
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4680
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4681
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4682
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4683
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4684
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4685
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4686
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4687
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4688
     34201, 34205, 34209, 34213, 34217, 34221, 34225, 34229, 34233, 34237,
4689
     34240, 34240, 34240, 34240, 34240, 34240, 34240},
4690
    {34240, 34244, 34248, 34252, 34256, 34260, 34264, 34268, 34272, 34276,
4691
     34280, 34284, 34288, 34292, 34296, 34300, 34304, 34308, 34312, 34316,
4692
     34320, 34324, 34328, 34332, 34336, 34340, 34344, 34348, 34352, 34356,
4693
     34360, 34364, 34368, 34372, 34376, 34380, 34384, 34388, 34392, 34396,
4694
     34400, 34404, 34408, 34412, 34416, 34420, 34424, 34428, 34432, 34436,
4695
     34440, 34444, 34448, 34452, 34456, 34460, 34464, 34468, 34472, 34476,
4696
     34480, 34484, 34488, 34492, 34496, 34500, 34504, 34508, 34512, 34516,
4697
     34520, 34524, 34528, 34532, 34536, 34540, 34544, 34548, 34552, 34556,
4698
     34560, 34564, 34568, 34572, 34576, 34580, 34584, 34588, 34592, 34596,
4699
     34600, 34604, 34608, 34612, 34616, 34620, 34624, 34628, 34632, 34636,
4700
     34640, 34644, 34648, 34652, 34656, 34660, 34664, 34668, 34672, 34676,
4701
     34680, 34684, 34688, 34692, 34696, 34700, 34704, 34708, 34712, 34716,
4702
     34720, 34724, 34728, 34732, 34736, 34740, 34744, 34748, 34752, 34756,
4703
     34760, 34764, 34768, 34772, 34776, 34780, 34784, 34788, 34792, 34796,
4704
     34800, 34804, 34808, 34812, 34816, 34820, 34824, 34828, 34832, 34836,
4705
     34840, 34844, 34848, 34852, 34856, 34860, 34864, 34868, 34872, 34876,
4706
     34880, 34884, 34888, 34892, 34896, 34900, 34904, 34908, 34912, 34916,
4707
     34920, 34924, 34928, 34932, 34936, 34940, 34944, 34948, 34952, 34956,
4708
     34960, 34964, 34968, 34972, 34976, 34980, 34984, 34988, 34992, 34996,
4709
     35000, 35004, 35008, 35012, 35016, 35020, 35024, 35028, 35032, 35036,
4710
     35040, 35044, 35048, 35052, 35056, 35060, 35064, 35068, 35072, 35076,
4711
     35080, 35084, 35088, 35092, 35096, 35100, 35104, 35108, 35112, 35116,
4712
     35120, 35124, 35128, 35132, 35136, 35140, 35144, 35148, 35152, 35156,
4713
     35160, 35164, 35168, 35172, 35176, 35180, 35184, 35188, 35192, 35196,
4714
     35200, 35204, 35208, 35212, 35216, 35220, 35224, 35228, 35232, 35236,
4715
     35240, 35244, 35248, 35252, 35256, 35260, 35264},
4716
    {35264, 35268, 35272, 35276, 35280, 35284, 35288, 35292, 35296, 35300,
4717
     35304, 35308, 35312, 35316, 35320, 35324, 35328, 35332, 35336, 35340,
4718
     35344, 35348, 35352, 35356, 35360, 35364, 35368, 35372, 35376, 35380,
4719
     35384, 35388, 35392, 35396, 35400, 35404, 35408, 35412, 35416, 35420,
4720
     35424, 35428, 35432, 35436, 35440, 35444, 35448, 35452, 35456, 35460,
4721
     35464, 35468, 35472, 35476, 35480, 35484, 35488, 35492, 35496, 35500,
4722
     35504, 35508, 35512, 35516, 35520, 35524, 35528, 35532, 35536, 35540,
4723
     35544, 35548, 35552, 35556, 35560, 35564, 35568, 35572, 35576, 35580,
4724
     35584, 35588, 35592, 35596, 35600, 35604, 35608, 35612, 35616, 35620,
4725
     35624, 35628, 35632, 35636, 35640, 35644, 35648, 35652, 35656, 35660,
4726
     35664, 35668, 35672, 35676, 35680, 35684, 35688, 35692, 35696, 35700,
4727
     35704, 35708, 35712, 35716, 35720, 35724, 35728, 35732, 35736, 35740,
4728
     35744, 35748, 35752, 35756, 35760, 35764, 35768, 35772, 35776, 35780,
4729
     35784, 35788, 35792, 35796, 35800, 35804, 35808, 35812, 35816, 35820,
4730
     35824, 35828, 35832, 35836, 35840, 35844, 35848, 35852, 35856, 35860,
4731
     35864, 35868, 35872, 35876, 35880, 35884, 35888, 35892, 35896, 35900,
4732
     35904, 35908, 35912, 35916, 35920, 35924, 35928, 35932, 35936, 35940,
4733
     35944, 35948, 35952, 35956, 35960, 35964, 35968, 35972, 35976, 35980,
4734
     35984, 35988, 35992, 35996, 36000, 36004, 36008, 36012, 36016, 36020,
4735
     36024, 36028, 36032, 36036, 36040, 36044, 36048, 36052, 36056, 36060,
4736
     36064, 36068, 36072, 36076, 36080, 36084, 36088, 36092, 36096, 36100,
4737
     36104, 36108, 36112, 36116, 36120, 36124, 36128, 36132, 36136, 36140,
4738
     36144, 36148, 36152, 36156, 36160, 36164, 36168, 36172, 36176, 36180,
4739
     36184, 36188, 36192, 36196, 36200, 36204, 36208, 36212, 36216, 36220,
4740
     36224, 36228, 36232, 36236, 36240, 36244, 36248, 36252, 36256, 36260,
4741
     36264, 36268, 36272, 36276, 36280, 36284, 36288},
4742
    {36288, 36292, 36296, 36300, 36304, 36308, 36312, 36316, 36320, 36324,
4743
     36328, 36332, 36336, 36340, 36344, 36348, 36352, 36356, 36360, 36364,
4744
     36368, 36372, 36376, 36380, 36384, 36388, 36392, 36396, 36400, 36404,
4745
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4746
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4747
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4748
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4749
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4750
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4751
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4752
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4753
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4754
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4755
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4756
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4757
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4758
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4759
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4760
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4761
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4762
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4763
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4764
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4765
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4766
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4767
     36408, 36408, 36408, 36408, 36408, 36408, 36408}};
4768
const char32_t decomposition_data[9102] = {
4769
    0,      32,     32,     776,    97,     32,     772,    50,     51,
4770
    32,     769,    956,    32,     807,    49,     111,    49,     8260,
4771
    52,     49,     8260,   50,     51,     8260,   52,     65,     768,
4772
    65,     769,    65,     770,    65,     771,    65,     776,    65,
4773
    778,    67,     807,    69,     768,    69,     769,    69,     770,
4774
    69,     776,    73,     768,    73,     769,    73,     770,    73,
4775
    776,    78,     771,    79,     768,    79,     769,    79,     770,
4776
    79,     771,    79,     776,    85,     768,    85,     769,    85,
4777
    770,    85,     776,    89,     769,    97,     768,    97,     769,
4778
    97,     770,    97,     771,    97,     776,    97,     778,    99,
4779
    807,    101,    768,    101,    769,    101,    770,    101,    776,
4780
    105,    768,    105,    769,    105,    770,    105,    776,    110,
4781
    771,    111,    768,    111,    769,    111,    770,    111,    771,
4782
    111,    776,    117,    768,    117,    769,    117,    770,    117,
4783
    776,    121,    769,    121,    776,    65,     772,    97,     772,
4784
    65,     774,    97,     774,    65,     808,    97,     808,    67,
4785
    769,    99,     769,    67,     770,    99,     770,    67,     775,
4786
    99,     775,    67,     780,    99,     780,    68,     780,    100,
4787
    780,    69,     772,    101,    772,    69,     774,    101,    774,
4788
    69,     775,    101,    775,    69,     808,    101,    808,    69,
4789
    780,    101,    780,    71,     770,    103,    770,    71,     774,
4790
    103,    774,    71,     775,    103,    775,    71,     807,    103,
4791
    807,    72,     770,    104,    770,    73,     771,    105,    771,
4792
    73,     772,    105,    772,    73,     774,    105,    774,    73,
4793
    808,    105,    808,    73,     775,    73,     74,     105,    106,
4794
    74,     770,    106,    770,    75,     807,    107,    807,    76,
4795
    769,    108,    769,    76,     807,    108,    807,    76,     780,
4796
    108,    780,    76,     183,    108,    183,    78,     769,    110,
4797
    769,    78,     807,    110,    807,    78,     780,    110,    780,
4798
    700,    110,    79,     772,    111,    772,    79,     774,    111,
4799
    774,    79,     779,    111,    779,    82,     769,    114,    769,
4800
    82,     807,    114,    807,    82,     780,    114,    780,    83,
4801
    769,    115,    769,    83,     770,    115,    770,    83,     807,
4802
    115,    807,    83,     780,    115,    780,    84,     807,    116,
4803
    807,    84,     780,    116,    780,    85,     771,    117,    771,
4804
    85,     772,    117,    772,    85,     774,    117,    774,    85,
4805
    778,    117,    778,    85,     779,    117,    779,    85,     808,
4806
    117,    808,    87,     770,    119,    770,    89,     770,    121,
4807
    770,    89,     776,    90,     769,    122,    769,    90,     775,
4808
    122,    775,    90,     780,    122,    780,    115,    79,     795,
4809
    111,    795,    85,     795,    117,    795,    68,     90,     780,
4810
    68,     122,    780,    100,    122,    780,    76,     74,     76,
4811
    106,    108,    106,    78,     74,     78,     106,    110,    106,
4812
    65,     780,    97,     780,    73,     780,    105,    780,    79,
4813
    780,    111,    780,    85,     780,    117,    780,    85,     776,
4814
    772,    117,    776,    772,    85,     776,    769,    117,    776,
4815
    769,    85,     776,    780,    117,    776,    780,    85,     776,
4816
    768,    117,    776,    768,    65,     776,    772,    97,     776,
4817
    772,    65,     775,    772,    97,     775,    772,    198,    772,
4818
    230,    772,    71,     780,    103,    780,    75,     780,    107,
4819
    780,    79,     808,    111,    808,    79,     808,    772,    111,
4820
    808,    772,    439,    780,    658,    780,    106,    780,    68,
4821
    90,     68,     122,    100,    122,    71,     769,    103,    769,
4822
    78,     768,    110,    768,    65,     778,    769,    97,     778,
4823
    769,    198,    769,    230,    769,    216,    769,    248,    769,
4824
    65,     783,    97,     783,    65,     785,    97,     785,    69,
4825
    783,    101,    783,    69,     785,    101,    785,    73,     783,
4826
    105,    783,    73,     785,    105,    785,    79,     783,    111,
4827
    783,    79,     785,    111,    785,    82,     783,    114,    783,
4828
    82,     785,    114,    785,    85,     783,    117,    783,    85,
4829
    785,    117,    785,    83,     806,    115,    806,    84,     806,
4830
    116,    806,    72,     780,    104,    780,    65,     775,    97,
4831
    775,    69,     807,    101,    807,    79,     776,    772,    111,
4832
    776,    772,    79,     771,    772,    111,    771,    772,    79,
4833
    775,    111,    775,    79,     775,    772,    111,    775,    772,
4834
    89,     772,    121,    772,    104,    614,    106,    114,    633,
4835
    635,    641,    119,    121,    32,     774,    32,     775,    32,
4836
    778,    32,     808,    32,     771,    32,     779,    611,    108,
4837
    115,    120,    661,    768,    769,    787,    776,    769,    697,
4838
    32,     837,    59,     32,     769,    168,    769,    913,    769,
4839
    183,    917,    769,    919,    769,    921,    769,    927,    769,
4840
    933,    769,    937,    769,    953,    776,    769,    921,    776,
4841
    933,    776,    945,    769,    949,    769,    951,    769,    953,
4842
    769,    965,    776,    769,    953,    776,    965,    776,    959,
4843
    769,    965,    769,    969,    769,    946,    952,    933,    978,
4844
    769,    978,    776,    966,    960,    954,    961,    962,    920,
4845
    949,    931,    1045,   768,    1045,   776,    1043,   769,    1030,
4846
    776,    1050,   769,    1048,   768,    1059,   774,    1048,   774,
4847
    1080,   774,    1077,   768,    1077,   776,    1075,   769,    1110,
4848
    776,    1082,   769,    1080,   768,    1091,   774,    1140,   783,
4849
    1141,   783,    1046,   774,    1078,   774,    1040,   774,    1072,
4850
    774,    1040,   776,    1072,   776,    1045,   774,    1077,   774,
4851
    1240,   776,    1241,   776,    1046,   776,    1078,   776,    1047,
4852
    776,    1079,   776,    1048,   772,    1080,   772,    1048,   776,
4853
    1080,   776,    1054,   776,    1086,   776,    1256,   776,    1257,
4854
    776,    1069,   776,    1101,   776,    1059,   772,    1091,   772,
4855
    1059,   776,    1091,   776,    1059,   779,    1091,   779,    1063,
4856
    776,    1095,   776,    1067,   776,    1099,   776,    1381,   1410,
4857
    1575,   1619,   1575,   1620,   1608,   1620,   1575,   1621,   1610,
4858
    1620,   1575,   1652,   1608,   1652,   1735,   1652,   1610,   1652,
4859
    1749,   1620,   1729,   1620,   1746,   1620,   2344,   2364,   2352,
4860
    2364,   2355,   2364,   2325,   2364,   2326,   2364,   2327,   2364,
4861
    2332,   2364,   2337,   2364,   2338,   2364,   2347,   2364,   2351,
4862
    2364,   2503,   2494,   2503,   2519,   2465,   2492,   2466,   2492,
4863
    2479,   2492,   2610,   2620,   2616,   2620,   2582,   2620,   2583,
4864
    2620,   2588,   2620,   2603,   2620,   2887,   2902,   2887,   2878,
4865
    2887,   2903,   2849,   2876,   2850,   2876,   2962,   3031,   3014,
4866
    3006,   3015,   3006,   3014,   3031,   3142,   3158,   3263,   3285,
4867
    3270,   3285,   3270,   3286,   3270,   3266,   3270,   3266,   3285,
4868
    3398,   3390,   3399,   3390,   3398,   3415,   3545,   3530,   3545,
4869
    3535,   3545,   3535,   3530,   3545,   3551,   3661,   3634,   3789,
4870
    3762,   3755,   3737,   3755,   3745,   3851,   3906,   4023,   3916,
4871
    4023,   3921,   4023,   3926,   4023,   3931,   4023,   3904,   4021,
4872
    3953,   3954,   3953,   3956,   4018,   3968,   4018,   3953,   3968,
4873
    4019,   3968,   4019,   3953,   3968,   3953,   3968,   3986,   4023,
4874
    3996,   4023,   4001,   4023,   4006,   4023,   4011,   4023,   3984,
4875
    4021,   4133,   4142,   4316,   6917,   6965,   6919,   6965,   6921,
4876
    6965,   6923,   6965,   6925,   6965,   6929,   6965,   6970,   6965,
4877
    6972,   6965,   6974,   6965,   6975,   6965,   6978,   6965,   65,
4878
    198,    66,     68,     69,     398,    71,     72,     73,     74,
4879
    75,     76,     77,     78,     79,     546,    80,     82,     84,
4880
    85,     87,     97,     592,    593,    7426,   98,     100,    101,
4881
    601,    603,    604,    103,    107,    109,    331,    111,    596,
4882
    7446,   7447,   112,    116,    117,    7453,   623,    118,    7461,
4883
    946,    947,    948,    966,    967,    105,    114,    117,    118,
4884
    946,    947,    961,    966,    967,    1085,   594,    99,     597,
4885
    240,    604,    102,    607,    609,    613,    616,    617,    618,
4886
    7547,   669,    621,    7557,   671,    625,    624,    626,    627,
4887
    628,    629,    632,    642,    643,    427,    649,    650,    7452,
4888
    651,    652,    122,    656,    657,    658,    952,    65,     805,
4889
    97,     805,    66,     775,    98,     775,    66,     803,    98,
4890
    803,    66,     817,    98,     817,    67,     807,    769,    99,
4891
    807,    769,    68,     775,    100,    775,    68,     803,    100,
4892
    803,    68,     817,    100,    817,    68,     807,    100,    807,
4893
    68,     813,    100,    813,    69,     772,    768,    101,    772,
4894
    768,    69,     772,    769,    101,    772,    769,    69,     813,
4895
    101,    813,    69,     816,    101,    816,    69,     807,    774,
4896
    101,    807,    774,    70,     775,    102,    775,    71,     772,
4897
    103,    772,    72,     775,    104,    775,    72,     803,    104,
4898
    803,    72,     776,    104,    776,    72,     807,    104,    807,
4899
    72,     814,    104,    814,    73,     816,    105,    816,    73,
4900
    776,    769,    105,    776,    769,    75,     769,    107,    769,
4901
    75,     803,    107,    803,    75,     817,    107,    817,    76,
4902
    803,    108,    803,    76,     803,    772,    108,    803,    772,
4903
    76,     817,    108,    817,    76,     813,    108,    813,    77,
4904
    769,    109,    769,    77,     775,    109,    775,    77,     803,
4905
    109,    803,    78,     775,    110,    775,    78,     803,    110,
4906
    803,    78,     817,    110,    817,    78,     813,    110,    813,
4907
    79,     771,    769,    111,    771,    769,    79,     771,    776,
4908
    111,    771,    776,    79,     772,    768,    111,    772,    768,
4909
    79,     772,    769,    111,    772,    769,    80,     769,    112,
4910
    769,    80,     775,    112,    775,    82,     775,    114,    775,
4911
    82,     803,    114,    803,    82,     803,    772,    114,    803,
4912
    772,    82,     817,    114,    817,    83,     775,    115,    775,
4913
    83,     803,    115,    803,    83,     769,    775,    115,    769,
4914
    775,    83,     780,    775,    115,    780,    775,    83,     803,
4915
    775,    115,    803,    775,    84,     775,    116,    775,    84,
4916
    803,    116,    803,    84,     817,    116,    817,    84,     813,
4917
    116,    813,    85,     804,    117,    804,    85,     816,    117,
4918
    816,    85,     813,    117,    813,    85,     771,    769,    117,
4919
    771,    769,    85,     772,    776,    117,    772,    776,    86,
4920
    771,    118,    771,    86,     803,    118,    803,    87,     768,
4921
    119,    768,    87,     769,    119,    769,    87,     776,    119,
4922
    776,    87,     775,    119,    775,    87,     803,    119,    803,
4923
    88,     775,    120,    775,    88,     776,    120,    776,    89,
4924
    775,    121,    775,    90,     770,    122,    770,    90,     803,
4925
    122,    803,    90,     817,    122,    817,    104,    817,    116,
4926
    776,    119,    778,    121,    778,    97,     702,    383,    775,
4927
    65,     803,    97,     803,    65,     777,    97,     777,    65,
4928
    770,    769,    97,     770,    769,    65,     770,    768,    97,
4929
    770,    768,    65,     770,    777,    97,     770,    777,    65,
4930
    770,    771,    97,     770,    771,    65,     803,    770,    97,
4931
    803,    770,    65,     774,    769,    97,     774,    769,    65,
4932
    774,    768,    97,     774,    768,    65,     774,    777,    97,
4933
    774,    777,    65,     774,    771,    97,     774,    771,    65,
4934
    803,    774,    97,     803,    774,    69,     803,    101,    803,
4935
    69,     777,    101,    777,    69,     771,    101,    771,    69,
4936
    770,    769,    101,    770,    769,    69,     770,    768,    101,
4937
    770,    768,    69,     770,    777,    101,    770,    777,    69,
4938
    770,    771,    101,    770,    771,    69,     803,    770,    101,
4939
    803,    770,    73,     777,    105,    777,    73,     803,    105,
4940
    803,    79,     803,    111,    803,    79,     777,    111,    777,
4941
    79,     770,    769,    111,    770,    769,    79,     770,    768,
4942
    111,    770,    768,    79,     770,    777,    111,    770,    777,
4943
    79,     770,    771,    111,    770,    771,    79,     803,    770,
4944
    111,    803,    770,    79,     795,    769,    111,    795,    769,
4945
    79,     795,    768,    111,    795,    768,    79,     795,    777,
4946
    111,    795,    777,    79,     795,    771,    111,    795,    771,
4947
    79,     795,    803,    111,    795,    803,    85,     803,    117,
4948
    803,    85,     777,    117,    777,    85,     795,    769,    117,
4949
    795,    769,    85,     795,    768,    117,    795,    768,    85,
4950
    795,    777,    117,    795,    777,    85,     795,    771,    117,
4951
    795,    771,    85,     795,    803,    117,    795,    803,    89,
4952
    768,    121,    768,    89,     803,    121,    803,    89,     777,
4953
    121,    777,    89,     771,    121,    771,    945,    787,    945,
4954
    788,    945,    787,    768,    945,    788,    768,    945,    787,
4955
    769,    945,    788,    769,    945,    787,    834,    945,    788,
4956
    834,    913,    787,    913,    788,    913,    787,    768,    913,
4957
    788,    768,    913,    787,    769,    913,    788,    769,    913,
4958
    787,    834,    913,    788,    834,    949,    787,    949,    788,
4959
    949,    787,    768,    949,    788,    768,    949,    787,    769,
4960
    949,    788,    769,    917,    787,    917,    788,    917,    787,
4961
    768,    917,    788,    768,    917,    787,    769,    917,    788,
4962
    769,    951,    787,    951,    788,    951,    787,    768,    951,
4963
    788,    768,    951,    787,    769,    951,    788,    769,    951,
4964
    787,    834,    951,    788,    834,    919,    787,    919,    788,
4965
    919,    787,    768,    919,    788,    768,    919,    787,    769,
4966
    919,    788,    769,    919,    787,    834,    919,    788,    834,
4967
    953,    787,    953,    788,    953,    787,    768,    953,    788,
4968
    768,    953,    787,    769,    953,    788,    769,    953,    787,
4969
    834,    953,    788,    834,    921,    787,    921,    788,    921,
4970
    787,    768,    921,    788,    768,    921,    787,    769,    921,
4971
    788,    769,    921,    787,    834,    921,    788,    834,    959,
4972
    787,    959,    788,    959,    787,    768,    959,    788,    768,
4973
    959,    787,    769,    959,    788,    769,    927,    787,    927,
4974
    788,    927,    787,    768,    927,    788,    768,    927,    787,
4975
    769,    927,    788,    769,    965,    787,    965,    788,    965,
4976
    787,    768,    965,    788,    768,    965,    787,    769,    965,
4977
    788,    769,    965,    787,    834,    965,    788,    834,    933,
4978
    788,    933,    788,    768,    933,    788,    769,    933,    788,
4979
    834,    969,    787,    969,    788,    969,    787,    768,    969,
4980
    788,    768,    969,    787,    769,    969,    788,    769,    969,
4981
    787,    834,    969,    788,    834,    937,    787,    937,    788,
4982
    937,    787,    768,    937,    788,    768,    937,    787,    769,
4983
    937,    788,    769,    937,    787,    834,    937,    788,    834,
4984
    945,    768,    945,    769,    949,    768,    949,    769,    951,
4985
    768,    951,    769,    953,    768,    953,    769,    959,    768,
4986
    959,    769,    965,    768,    965,    769,    969,    768,    969,
4987
    769,    945,    787,    837,    945,    788,    837,    945,    787,
4988
    768,    837,    945,    788,    768,    837,    945,    787,    769,
4989
    837,    945,    788,    769,    837,    945,    787,    834,    837,
4990
    945,    788,    834,    837,    913,    787,    837,    913,    788,
4991
    837,    913,    787,    768,    837,    913,    788,    768,    837,
4992
    913,    787,    769,    837,    913,    788,    769,    837,    913,
4993
    787,    834,    837,    913,    788,    834,    837,    951,    787,
4994
    837,    951,    788,    837,    951,    787,    768,    837,    951,
4995
    788,    768,    837,    951,    787,    769,    837,    951,    788,
4996
    769,    837,    951,    787,    834,    837,    951,    788,    834,
4997
    837,    919,    787,    837,    919,    788,    837,    919,    787,
4998
    768,    837,    919,    788,    768,    837,    919,    787,    769,
4999
    837,    919,    788,    769,    837,    919,    787,    834,    837,
5000
    919,    788,    834,    837,    969,    787,    837,    969,    788,
5001
    837,    969,    787,    768,    837,    969,    788,    768,    837,
5002
    969,    787,    769,    837,    969,    788,    769,    837,    969,
5003
    787,    834,    837,    969,    788,    834,    837,    937,    787,
5004
    837,    937,    788,    837,    937,    787,    768,    837,    937,
5005
    788,    768,    837,    937,    787,    769,    837,    937,    788,
5006
    769,    837,    937,    787,    834,    837,    937,    788,    834,
5007
    837,    945,    774,    945,    772,    945,    768,    837,    945,
5008
    837,    945,    769,    837,    945,    834,    945,    834,    837,
5009
    913,    774,    913,    772,    913,    768,    913,    769,    913,
5010
    837,    32,     787,    953,    32,     787,    32,     834,    168,
5011
    834,    951,    768,    837,    951,    837,    951,    769,    837,
5012
    951,    834,    951,    834,    837,    917,    768,    917,    769,
5013
    919,    768,    919,    769,    919,    837,    8127,   768,    8127,
5014
    769,    8127,   834,    953,    774,    953,    772,    953,    776,
5015
    768,    953,    776,    769,    953,    834,    953,    776,    834,
5016
    921,    774,    921,    772,    921,    768,    921,    769,    8190,
5017
    768,    8190,   769,    8190,   834,    965,    774,    965,    772,
5018
    965,    776,    768,    965,    776,    769,    961,    787,    961,
5019
    788,    965,    834,    965,    776,    834,    933,    774,    933,
5020
    772,    933,    768,    933,    769,    929,    788,    168,    768,
5021
    168,    769,    96,     969,    768,    837,    969,    837,    969,
5022
    769,    837,    969,    834,    969,    834,    837,    927,    768,
5023
    927,    769,    937,    768,    937,    769,    937,    837,    180,
5024
    32,     788,    8194,   8195,   32,     32,     32,     32,     32,
5025
    32,     32,     32,     32,     8208,   32,     819,    46,     46,
5026
    46,     46,     46,     46,     32,     8242,   8242,   8242,   8242,
5027
    8242,   8245,   8245,   8245,   8245,   8245,   33,     33,     32,
5028
    773,    63,     63,     63,     33,     33,     63,     8242,   8242,
5029
    8242,   8242,   32,     48,     105,    52,     53,     54,     55,
5030
    56,     57,     43,     8722,   61,     40,     41,     110,    48,
5031
    49,     50,     51,     52,     53,     54,     55,     56,     57,
5032
    43,     8722,   61,     40,     41,     97,     101,    111,    120,
5033
    601,    104,    107,    108,    109,    110,    112,    115,    116,
5034
    82,     115,    97,     47,     99,     97,     47,     115,    67,
5035
    176,    67,     99,     47,     111,    99,     47,     117,    400,
5036
    176,    70,     103,    72,     72,     72,     104,    295,    73,
5037
    73,     76,     108,    78,     78,     111,    80,     81,     82,
5038
    82,     82,     83,     77,     84,     69,     76,     84,     77,
5039
    90,     937,    90,     75,     65,     778,    66,     67,     101,
5040
    69,     70,     77,     111,    1488,   1489,   1490,   1491,   105,
5041
    70,     65,     88,     960,    947,    915,    928,    8721,   68,
5042
    100,    101,    105,    106,    49,     8260,   55,     49,     8260,
5043
    57,     49,     8260,   49,     48,     49,     8260,   51,     50,
5044
    8260,   51,     49,     8260,   53,     50,     8260,   53,     51,
5045
    8260,   53,     52,     8260,   53,     49,     8260,   54,     53,
5046
    8260,   54,     49,     8260,   56,     51,     8260,   56,     53,
5047
    8260,   56,     55,     8260,   56,     49,     8260,   73,     73,
5048
    73,     73,     73,     73,     73,     86,     86,     86,     73,
5049
    86,     73,     73,     86,     73,     73,     73,     73,     88,
5050
    88,     88,     73,     88,     73,     73,     76,     67,     68,
5051
    77,     105,    105,    105,    105,    105,    105,    105,    118,
5052
    118,    118,    105,    118,    105,    105,    118,    105,    105,
5053
    105,    105,    120,    120,    120,    105,    120,    105,    105,
5054
    108,    99,     100,    109,    48,     8260,   51,     8592,   824,
5055
    8594,   824,    8596,   824,    8656,   824,    8660,   824,    8658,
5056
    824,    8707,   824,    8712,   824,    8715,   824,    8739,   824,
5057
    8741,   824,    8747,   8747,   8747,   8747,   8747,   8750,   8750,
5058
    8750,   8750,   8750,   8764,   824,    8771,   824,    8773,   824,
5059
    8776,   824,    61,     824,    8801,   824,    8781,   824,    60,
5060
    824,    62,     824,    8804,   824,    8805,   824,    8818,   824,
5061
    8819,   824,    8822,   824,    8823,   824,    8826,   824,    8827,
5062
    824,    8834,   824,    8835,   824,    8838,   824,    8839,   824,
5063
    8866,   824,    8872,   824,    8873,   824,    8875,   824,    8828,
5064
    824,    8829,   824,    8849,   824,    8850,   824,    8882,   824,
5065
    8883,   824,    8884,   824,    8885,   824,    12296,  12297,  49,
5066
    50,     51,     52,     53,     54,     55,     56,     57,     49,
5067
    48,     49,     49,     49,     50,     49,     51,     49,     52,
5068
    49,     53,     49,     54,     49,     55,     49,     56,     49,
5069
    57,     50,     48,     40,     49,     41,     40,     50,     41,
5070
    40,     51,     41,     40,     52,     41,     40,     53,     41,
5071
    40,     54,     41,     40,     55,     41,     40,     56,     41,
5072
    40,     57,     41,     40,     49,     48,     41,     40,     49,
5073
    49,     41,     40,     49,     50,     41,     40,     49,     51,
5074
    41,     40,     49,     52,     41,     40,     49,     53,     41,
5075
    40,     49,     54,     41,     40,     49,     55,     41,     40,
5076
    49,     56,     41,     40,     49,     57,     41,     40,     50,
5077
    48,     41,     49,     46,     50,     46,     51,     46,     52,
5078
    46,     53,     46,     54,     46,     55,     46,     56,     46,
5079
    57,     46,     49,     48,     46,     49,     49,     46,     49,
5080
    50,     46,     49,     51,     46,     49,     52,     46,     49,
5081
    53,     46,     49,     54,     46,     49,     55,     46,     49,
5082
    56,     46,     49,     57,     46,     50,     48,     46,     40,
5083
    97,     41,     40,     98,     41,     40,     99,     41,     40,
5084
    100,    41,     40,     101,    41,     40,     102,    41,     40,
5085
    103,    41,     40,     104,    41,     40,     105,    41,     40,
5086
    106,    41,     40,     107,    41,     40,     108,    41,     40,
5087
    109,    41,     40,     110,    41,     40,     111,    41,     40,
5088
    112,    41,     40,     113,    41,     40,     114,    41,     40,
5089
    115,    41,     40,     116,    41,     40,     117,    41,     40,
5090
    118,    41,     40,     119,    41,     40,     120,    41,     40,
5091
    121,    41,     40,     122,    41,     65,     66,     67,     68,
5092
    69,     70,     71,     72,     73,     74,     75,     76,     77,
5093
    78,     79,     80,     81,     82,     83,     84,     85,     86,
5094
    87,     88,     89,     90,     97,     98,     99,     100,    101,
5095
    102,    103,    104,    105,    106,    107,    108,    109,    110,
5096
    111,    112,    113,    114,    115,    116,    117,    118,    119,
5097
    120,    121,    122,    48,     8747,   8747,   8747,   8747,   58,
5098
    58,     61,     61,     61,     61,     61,     61,     10973,  824,
5099
    106,    86,     11617,  27597,  40863,  19968,  20008,  20022,  20031,
5100
    20057,  20101,  20108,  20128,  20154,  20799,  20837,  20843,  20866,
5101
    20886,  20907,  20960,  20981,  20992,  21147,  21241,  21269,  21274,
5102
    21304,  21313,  21340,  21353,  21378,  21430,  21448,  21475,  22231,
5103
    22303,  22763,  22786,  22794,  22805,  22823,  22899,  23376,  23424,
5104
    23544,  23567,  23586,  23608,  23662,  23665,  24027,  24037,  24049,
5105
    24062,  24178,  24186,  24191,  24308,  24318,  24331,  24339,  24400,
5106
    24417,  24435,  24515,  25096,  25142,  25163,  25903,  25908,  25991,
5107
    26007,  26020,  26041,  26080,  26085,  26352,  26376,  26408,  27424,
5108
    27490,  27513,  27571,  27595,  27604,  27611,  27663,  27668,  27700,
5109
    28779,  29226,  29238,  29243,  29247,  29255,  29273,  29275,  29356,
5110
    29572,  29577,  29916,  29926,  29976,  29983,  29992,  30000,  30091,
5111
    30098,  30326,  30333,  30382,  30399,  30446,  30683,  30690,  30707,
5112
    31034,  31160,  31166,  31348,  31435,  31481,  31859,  31992,  32566,
5113
    32593,  32650,  32701,  32769,  32780,  32786,  32819,  32895,  32905,
5114
    33251,  33258,  33267,  33276,  33292,  33307,  33311,  33390,  33394,
5115
    33400,  34381,  34411,  34880,  34892,  34915,  35198,  35211,  35282,
5116
    35328,  35895,  35910,  35925,  35960,  35997,  36196,  36208,  36275,
5117
    36523,  36554,  36763,  36784,  36789,  37009,  37193,  37318,  37324,
5118
    37329,  38263,  38272,  38428,  38582,  38585,  38632,  38737,  38750,
5119
    38754,  38761,  38859,  38893,  38899,  38913,  39080,  39131,  39135,
5120
    39318,  39321,  39340,  39592,  39640,  39647,  39717,  39727,  39730,
5121
    39740,  39770,  40165,  40565,  40575,  40613,  40635,  40643,  40653,
5122
    40657,  40697,  40701,  40718,  40723,  40736,  40763,  40778,  40786,
5123
    40845,  40860,  40864,  32,     12306,  21313,  21316,  21317,  12363,
5124
    12441,  12365,  12441,  12367,  12441,  12369,  12441,  12371,  12441,
5125
    12373,  12441,  12375,  12441,  12377,  12441,  12379,  12441,  12381,
5126
    12441,  12383,  12441,  12385,  12441,  12388,  12441,  12390,  12441,
5127
    12392,  12441,  12399,  12441,  12399,  12442,  12402,  12441,  12402,
5128
    12442,  12405,  12441,  12405,  12442,  12408,  12441,  12408,  12442,
5129
    12411,  12441,  12411,  12442,  12358,  12441,  32,     12441,  32,
5130
    12442,  12445,  12441,  12424,  12426,  12459,  12441,  12461,  12441,
5131
    12463,  12441,  12465,  12441,  12467,  12441,  12469,  12441,  12471,
5132
    12441,  12473,  12441,  12475,  12441,  12477,  12441,  12479,  12441,
5133
    12481,  12441,  12484,  12441,  12486,  12441,  12488,  12441,  12495,
5134
    12441,  12495,  12442,  12498,  12441,  12498,  12442,  12501,  12441,
5135
    12501,  12442,  12504,  12441,  12504,  12442,  12507,  12441,  12507,
5136
    12442,  12454,  12441,  12527,  12441,  12528,  12441,  12529,  12441,
5137
    12530,  12441,  12541,  12441,  12467,  12488,  4352,   4353,   4522,
5138
    4354,   4524,   4525,   4355,   4356,   4357,   4528,   4529,   4530,
5139
    4531,   4532,   4533,   4378,   4358,   4359,   4360,   4385,   4361,
5140
    4362,   4363,   4364,   4365,   4366,   4367,   4368,   4369,   4370,
5141
    4449,   4450,   4451,   4452,   4453,   4454,   4455,   4456,   4457,
5142
    4458,   4459,   4460,   4461,   4462,   4463,   4464,   4465,   4466,
5143
    4467,   4468,   4469,   4448,   4372,   4373,   4551,   4552,   4556,
5144
    4558,   4563,   4567,   4569,   4380,   4573,   4575,   4381,   4382,
5145
    4384,   4386,   4387,   4391,   4393,   4395,   4396,   4397,   4398,
5146
    4399,   4402,   4406,   4416,   4423,   4428,   4593,   4594,   4439,
5147
    4440,   4441,   4484,   4485,   4488,   4497,   4498,   4500,   4510,
5148
    4513,   19968,  20108,  19977,  22235,  19978,  20013,  19979,  30002,
5149
    20057,  19993,  19969,  22825,  22320,  20154,  40,     4352,   41,
5150
    40,     4354,   41,     40,     4355,   41,     40,     4357,   41,
5151
    40,     4358,   41,     40,     4359,   41,     40,     4361,   41,
5152
    40,     4363,   41,     40,     4364,   41,     40,     4366,   41,
5153
    40,     4367,   41,     40,     4368,   41,     40,     4369,   41,
5154
    40,     4370,   41,     40,     4352,   4449,   41,     40,     4354,
5155
    4449,   41,     40,     4355,   4449,   41,     40,     4357,   4449,
5156
    41,     40,     4358,   4449,   41,     40,     4359,   4449,   41,
5157
    40,     4361,   4449,   41,     40,     4363,   4449,   41,     40,
5158
    4364,   4449,   41,     40,     4366,   4449,   41,     40,     4367,
5159
    4449,   41,     40,     4368,   4449,   41,     40,     4369,   4449,
5160
    41,     40,     4370,   4449,   41,     40,     4364,   4462,   41,
5161
    40,     4363,   4457,   4364,   4453,   4523,   41,     40,     4363,
5162
    4457,   4370,   4462,   41,     40,     19968,  41,     40,     20108,
5163
    41,     40,     19977,  41,     40,     22235,  41,     40,     20116,
5164
    41,     40,     20845,  41,     40,     19971,  41,     40,     20843,
5165
    41,     40,     20061,  41,     40,     21313,  41,     40,     26376,
5166
    41,     40,     28779,  41,     40,     27700,  41,     40,     26408,
5167
    41,     40,     37329,  41,     40,     22303,  41,     40,     26085,
5168
    41,     40,     26666,  41,     40,     26377,  41,     40,     31038,
5169
    41,     40,     21517,  41,     40,     29305,  41,     40,     36001,
5170
    41,     40,     31069,  41,     40,     21172,  41,     40,     20195,
5171
    41,     40,     21628,  41,     40,     23398,  41,     40,     30435,
5172
    41,     40,     20225,  41,     40,     36039,  41,     40,     21332,
5173
    41,     40,     31085,  41,     40,     20241,  41,     40,     33258,
5174
    41,     40,     33267,  41,     21839,  24188,  25991,  31631,  80,
5175
    84,     69,     50,     49,     50,     50,     50,     51,     50,
5176
    52,     50,     53,     50,     54,     50,     55,     50,     56,
5177
    50,     57,     51,     48,     51,     49,     51,     50,     51,
5178
    51,     51,     52,     51,     53,     4352,   4354,   4355,   4357,
5179
    4358,   4359,   4361,   4363,   4364,   4366,   4367,   4368,   4369,
5180
    4370,   4352,   4449,   4354,   4449,   4355,   4449,   4357,   4449,
5181
    4358,   4449,   4359,   4449,   4361,   4449,   4363,   4449,   4364,
5182
    4449,   4366,   4449,   4367,   4449,   4368,   4449,   4369,   4449,
5183
    4370,   4449,   4366,   4449,   4535,   4352,   4457,   4364,   4462,
5184
    4363,   4468,   4363,   4462,   19968,  20108,  19977,  22235,  20116,
5185
    20845,  19971,  20843,  20061,  21313,  26376,  28779,  27700,  26408,
5186
    37329,  22303,  26085,  26666,  26377,  31038,  21517,  29305,  36001,
5187
    31069,  21172,  31192,  30007,  22899,  36969,  20778,  21360,  27880,
5188
    38917,  20241,  20889,  27491,  19978,  20013,  19979,  24038,  21491,
5189
    21307,  23447,  23398,  30435,  20225,  36039,  21332,  22812,  51,
5190
    54,     51,     55,     51,     56,     51,     57,     52,     48,
5191
    52,     49,     52,     50,     52,     51,     52,     52,     52,
5192
    53,     52,     54,     52,     55,     52,     56,     52,     57,
5193
    53,     48,     49,     26376,  50,     26376,  51,     26376,  52,
5194
    26376,  53,     26376,  54,     26376,  55,     26376,  56,     26376,
5195
    57,     26376,  49,     48,     26376,  49,     49,     26376,  49,
5196
    50,     26376,  72,     103,    101,    114,    103,    101,    86,
5197
    76,     84,     68,     12450,  12452,  12454,  12456,  12458,  12459,
5198
    12461,  12463,  12465,  12467,  12469,  12471,  12473,  12475,  12477,
5199
    12479,  12481,  12484,  12486,  12488,  12490,  12491,  12492,  12493,
5200
    12494,  12495,  12498,  12501,  12504,  12507,  12510,  12511,  12512,
5201
    12513,  12514,  12516,  12518,  12520,  12521,  12522,  12523,  12524,
5202
    12525,  12527,  12528,  12529,  12530,  20196,  21644,  12450,  12495,
5203
    12442,  12540,  12488,  12450,  12523,  12501,  12449,  12450,  12531,
5204
    12504,  12442,  12450,  12450,  12540,  12523,  12452,  12491,  12531,
5205
    12463,  12441,  12452,  12531,  12481,  12454,  12457,  12531,  12456,
5206
    12473,  12463,  12540,  12488,  12441,  12456,  12540,  12459,  12540,
5207
    12458,  12531,  12473,  12458,  12540,  12512,  12459,  12452,  12522,
5208
    12459,  12521,  12483,  12488,  12459,  12525,  12522,  12540,  12459,
5209
    12441,  12525,  12531,  12459,  12441,  12531,  12510,  12461,  12441,
5210
    12459,  12441,  12461,  12441,  12491,  12540,  12461,  12517,  12522,
5211
    12540,  12461,  12441,  12523,  12479,  12441,  12540,  12461,  12525,
5212
    12461,  12525,  12463,  12441,  12521,  12512,  12461,  12525,  12513,
5213
    12540,  12488,  12523,  12461,  12525,  12527,  12483,  12488,  12463,
5214
    12441,  12521,  12512,  12463,  12441,  12521,  12512,  12488,  12531,
5215
    12463,  12523,  12475,  12441,  12452,  12525,  12463,  12525,  12540,
5216
    12493,  12465,  12540,  12473,  12467,  12523,  12490,  12467,  12540,
5217
    12507,  12442,  12469,  12452,  12463,  12523,  12469,  12531,  12481,
5218
    12540,  12512,  12471,  12522,  12531,  12463,  12441,  12475,  12531,
5219
    12481,  12475,  12531,  12488,  12479,  12441,  12540,  12473,  12486,
5220
    12441,  12471,  12488,  12441,  12523,  12488,  12531,  12490,  12494,
5221
    12494,  12483,  12488,  12495,  12452,  12484,  12495,  12442,  12540,
5222
    12475,  12531,  12488,  12495,  12442,  12540,  12484,  12495,  12441,
5223
    12540,  12524,  12523,  12498,  12442,  12450,  12473,  12488,  12523,
5224
    12498,  12442,  12463,  12523,  12498,  12442,  12467,  12498,  12441,
5225
    12523,  12501,  12449,  12521,  12483,  12488,  12441,  12501,  12451,
5226
    12540,  12488,  12501,  12441,  12483,  12471,  12455,  12523,  12501,
5227
    12521,  12531,  12504,  12463,  12479,  12540,  12523,  12504,  12442,
5228
    12477,  12504,  12442,  12491,  12498,  12504,  12523,  12484,  12504,
5229
    12442,  12531,  12473,  12504,  12442,  12540,  12471,  12441,  12504,
5230
    12441,  12540,  12479,  12507,  12442,  12452,  12531,  12488,  12507,
5231
    12441,  12523,  12488,  12507,  12531,  12507,  12442,  12531,  12488,
5232
    12441,  12507,  12540,  12523,  12507,  12540,  12531,  12510,  12452,
5233
    12463,  12525,  12510,  12452,  12523,  12510,  12483,  12495,  12510,
5234
    12523,  12463,  12510,  12531,  12471,  12519,  12531,  12511,  12463,
5235
    12525,  12531,  12511,  12522,  12511,  12522,  12495,  12441,  12540,
5236
    12523,  12513,  12459,  12441,  12513,  12459,  12441,  12488,  12531,
5237
    12513,  12540,  12488,  12523,  12516,  12540,  12488,  12441,  12516,
5238
    12540,  12523,  12518,  12450,  12531,  12522,  12483,  12488,  12523,
5239
    12522,  12521,  12523,  12498,  12442,  12540,  12523,  12540,  12501,
5240
    12441,  12523,  12524,  12512,  12524,  12531,  12488,  12465,  12441,
5241
    12531,  12527,  12483,  12488,  48,     28857,  49,     28857,  50,
5242
    28857,  51,     28857,  52,     28857,  53,     28857,  54,     28857,
5243
    55,     28857,  56,     28857,  57,     28857,  49,     48,     28857,
5244
    49,     49,     28857,  49,     50,     28857,  49,     51,     28857,
5245
    49,     52,     28857,  49,     53,     28857,  49,     54,     28857,
5246
    49,     55,     28857,  49,     56,     28857,  49,     57,     28857,
5247
    50,     48,     28857,  50,     49,     28857,  50,     50,     28857,
5248
    50,     51,     28857,  50,     52,     28857,  104,    80,     97,
5249
    100,    97,     65,     85,     98,     97,     114,    111,    86,
5250
    112,    99,     100,    109,    100,    109,    50,     100,    109,
5251
    51,     73,     85,     24179,  25104,  26157,  21644,  22823,  27491,
5252
    26126,  27835,  26666,  24335,  20250,  31038,  112,    65,     110,
5253
    65,     956,    65,     109,    65,     107,    65,     75,     66,
5254
    77,     66,     71,     66,     99,     97,     108,    107,    99,
5255
    97,     108,    112,    70,     110,    70,     956,    70,     956,
5256
    103,    109,    103,    107,    103,    72,     122,    107,    72,
5257
    122,    77,     72,     122,    71,     72,     122,    84,     72,
5258
    122,    956,    108,    109,    108,    100,    108,    107,    108,
5259
    102,    109,    110,    109,    956,    109,    109,    109,    99,
5260
    109,    107,    109,    109,    109,    50,     99,     109,    50,
5261
    109,    50,     107,    109,    50,     109,    109,    51,     99,
5262
    109,    51,     109,    51,     107,    109,    51,     109,    8725,
5263
    115,    109,    8725,   115,    50,     80,     97,     107,    80,
5264
    97,     77,     80,     97,     71,     80,     97,     114,    97,
5265
    100,    114,    97,     100,    8725,   115,    114,    97,     100,
5266
    8725,   115,    50,     112,    115,    110,    115,    956,    115,
5267
    109,    115,    112,    86,     110,    86,     956,    86,     109,
5268
    86,     107,    86,     77,     86,     112,    87,     110,    87,
5269
    956,    87,     109,    87,     107,    87,     77,     87,     107,
5270
    937,    77,     937,    97,     46,     109,    46,     66,     113,
5271
    99,     99,     99,     100,    67,     8725,   107,    103,    67,
5272
    111,    46,     100,    66,     71,     121,    104,    97,     72,
5273
    80,     105,    110,    75,     75,     75,     77,     107,    116,
5274
    108,    109,    108,    110,    108,    111,    103,    108,    120,
5275
    109,    98,     109,    105,    108,    109,    111,    108,    80,
5276
    72,     112,    46,     109,    46,     80,     80,     77,     80,
5277
    82,     115,    114,    83,     118,    87,     98,     86,     8725,
5278
    109,    65,     8725,   109,    49,     26085,  50,     26085,  51,
5279
    26085,  52,     26085,  53,     26085,  54,     26085,  55,     26085,
5280
    56,     26085,  57,     26085,  49,     48,     26085,  49,     49,
5281
    26085,  49,     50,     26085,  49,     51,     26085,  49,     52,
5282
    26085,  49,     53,     26085,  49,     54,     26085,  49,     55,
5283
    26085,  49,     56,     26085,  49,     57,     26085,  50,     48,
5284
    26085,  50,     49,     26085,  50,     50,     26085,  50,     51,
5285
    26085,  50,     52,     26085,  50,     53,     26085,  50,     54,
5286
    26085,  50,     55,     26085,  50,     56,     26085,  50,     57,
5287
    26085,  51,     48,     26085,  51,     49,     26085,  103,    97,
5288
    108,    1098,   1100,   42863,  67,     70,     81,     294,    339,
5289
    42791,  43831,  619,    43858,  653,    35912,  26356,  36554,  36040,
5290
    28369,  20018,  21477,  40860,  40860,  22865,  37329,  21895,  22856,
5291
    25078,  30313,  32645,  34367,  34746,  35064,  37007,  27138,  27931,
5292
    28889,  29662,  33853,  37226,  39409,  20098,  21365,  27396,  29211,
5293
    34349,  40478,  23888,  28651,  34253,  35172,  25289,  33240,  34847,
5294
    24266,  26391,  28010,  29436,  37070,  20358,  20919,  21214,  25796,
5295
    27347,  29200,  30439,  32769,  34310,  34396,  36335,  38706,  39791,
5296
    40442,  30860,  31103,  32160,  33737,  37636,  40575,  35542,  22751,
5297
    24324,  31840,  32894,  29282,  30922,  36034,  38647,  22744,  23650,
5298
    27155,  28122,  28431,  32047,  32311,  38475,  21202,  32907,  20956,
5299
    20940,  31260,  32190,  33777,  38517,  35712,  25295,  27138,  35582,
5300
    20025,  23527,  24594,  29575,  30064,  21271,  30971,  20415,  24489,
5301
    19981,  27852,  25976,  32034,  21443,  22622,  30465,  33865,  35498,
5302
    27578,  36784,  27784,  25342,  33509,  25504,  30053,  20142,  20841,
5303
    20937,  26753,  31975,  33391,  35538,  37327,  21237,  21570,  22899,
5304
    24300,  26053,  28670,  31018,  38317,  39530,  40599,  40654,  21147,
5305
    26310,  27511,  36706,  24180,  24976,  25088,  25754,  28451,  29001,
5306
    29833,  31178,  32244,  32879,  36646,  34030,  36899,  37706,  21015,
5307
    21155,  21693,  28872,  35010,  35498,  24265,  24565,  25467,  27566,
5308
    31806,  29557,  20196,  22265,  23527,  23994,  24604,  29618,  29801,
5309
    32666,  32838,  37428,  38646,  38728,  38936,  20363,  31150,  37300,
5310
    38584,  24801,  20102,  20698,  23534,  23615,  26009,  27138,  29134,
5311
    30274,  34044,  36988,  40845,  26248,  38446,  21129,  26491,  26611,
5312
    27969,  28316,  29705,  30041,  30827,  32016,  39006,  20845,  25134,
5313
    38520,  20523,  23833,  28138,  36650,  24459,  24900,  26647,  29575,
5314
    38534,  21033,  21519,  23653,  26131,  26446,  26792,  27877,  29702,
5315
    30178,  32633,  35023,  35041,  37324,  38626,  21311,  28346,  21533,
5316
    29136,  29848,  34298,  38563,  40023,  40607,  26519,  28107,  33256,
5317
    31435,  31520,  31890,  29376,  28825,  35672,  20160,  33590,  21050,
5318
    20999,  24230,  25299,  31958,  23429,  27934,  26292,  36667,  34892,
5319
    38477,  35211,  24275,  20800,  21952,  22618,  26228,  20958,  29482,
5320
    30410,  31036,  31070,  31077,  31119,  38742,  31934,  32701,  34322,
5321
    35576,  36920,  37117,  39151,  39164,  39208,  40372,  37086,  38583,
5322
    20398,  20711,  20813,  21193,  21220,  21329,  21917,  22022,  22120,
5323
    22592,  22696,  23652,  23662,  24724,  24936,  24974,  25074,  25935,
5324
    26082,  26257,  26757,  28023,  28186,  28450,  29038,  29227,  29730,
5325
    30865,  31038,  31049,  31048,  31056,  31062,  31069,  31117,  31118,
5326
    31296,  31361,  31680,  32244,  32265,  32321,  32626,  32773,  33261,
5327
    33401,  33401,  33879,  35088,  35222,  35585,  35641,  36051,  36104,
5328
    36790,  36920,  38627,  38911,  38971,  24693,  148206, 33304,  20006,
5329
    20917,  20840,  20352,  20805,  20864,  21191,  21242,  21917,  21845,
5330
    21913,  21986,  22618,  22707,  22852,  22868,  23138,  23336,  24274,
5331
    24281,  24425,  24493,  24792,  24910,  24840,  24974,  24928,  25074,
5332
    25140,  25540,  25628,  25682,  25942,  26228,  26391,  26395,  26454,
5333
    27513,  27578,  27969,  28379,  28363,  28450,  28702,  29038,  30631,
5334
    29237,  29359,  29482,  29809,  29958,  30011,  30237,  30239,  30410,
5335
    30427,  30452,  30538,  30528,  30924,  31409,  31680,  31867,  32091,
5336
    32244,  32574,  32773,  33618,  33775,  34681,  35137,  35206,  35222,
5337
    35519,  35576,  35531,  35585,  35582,  35565,  35641,  35722,  36104,
5338
    36664,  36978,  37273,  37494,  38524,  38627,  38742,  38875,  38911,
5339
    38923,  38971,  39698,  40860,  141386, 141380, 144341, 15261,  16408,
5340
    16441,  152137, 154832, 163539, 40771,  40846,  102,    102,    102,
5341
    105,    102,    108,    102,    102,    105,    102,    102,    108,
5342
    115,    116,    115,    116,    1396,   1398,   1396,   1381,   1396,
5343
    1387,   1406,   1398,   1396,   1389,   1497,   1460,   1522,   1463,
5344
    1506,   1488,   1491,   1492,   1499,   1500,   1501,   1512,   1514,
5345
    43,     1513,   1473,   1513,   1474,   1513,   1468,   1473,   1513,
5346
    1468,   1474,   1488,   1463,   1488,   1464,   1488,   1468,   1489,
5347
    1468,   1490,   1468,   1491,   1468,   1492,   1468,   1493,   1468,
5348
    1494,   1468,   1496,   1468,   1497,   1468,   1498,   1468,   1499,
5349
    1468,   1500,   1468,   1502,   1468,   1504,   1468,   1505,   1468,
5350
    1507,   1468,   1508,   1468,   1510,   1468,   1511,   1468,   1512,
5351
    1468,   1513,   1468,   1514,   1468,   1493,   1465,   1489,   1471,
5352
    1499,   1471,   1508,   1471,   1488,   1500,   1649,   1649,   1659,
5353
    1659,   1659,   1659,   1662,   1662,   1662,   1662,   1664,   1664,
5354
    1664,   1664,   1658,   1658,   1658,   1658,   1663,   1663,   1663,
5355
    1663,   1657,   1657,   1657,   1657,   1700,   1700,   1700,   1700,
5356
    1702,   1702,   1702,   1702,   1668,   1668,   1668,   1668,   1667,
5357
    1667,   1667,   1667,   1670,   1670,   1670,   1670,   1671,   1671,
5358
    1671,   1671,   1677,   1677,   1676,   1676,   1678,   1678,   1672,
5359
    1672,   1688,   1688,   1681,   1681,   1705,   1705,   1705,   1705,
5360
    1711,   1711,   1711,   1711,   1715,   1715,   1715,   1715,   1713,
5361
    1713,   1713,   1713,   1722,   1722,   1723,   1723,   1723,   1723,
5362
    1749,   1620,   1749,   1620,   1729,   1729,   1729,   1729,   1726,
5363
    1726,   1726,   1726,   1746,   1746,   1746,   1620,   1746,   1620,
5364
    1709,   1709,   1709,   1709,   1735,   1735,   1734,   1734,   1736,
5365
    1736,   1735,   1652,   1739,   1739,   1733,   1733,   1737,   1737,
5366
    1744,   1744,   1744,   1744,   1609,   1609,   1610,   1620,   1575,
5367
    1610,   1620,   1575,   1610,   1620,   1749,   1610,   1620,   1749,
5368
    1610,   1620,   1608,   1610,   1620,   1608,   1610,   1620,   1735,
5369
    1610,   1620,   1735,   1610,   1620,   1734,   1610,   1620,   1734,
5370
    1610,   1620,   1736,   1610,   1620,   1736,   1610,   1620,   1744,
5371
    1610,   1620,   1744,   1610,   1620,   1744,   1610,   1620,   1609,
5372
    1610,   1620,   1609,   1610,   1620,   1609,   1740,   1740,   1740,
5373
    1740,   1610,   1620,   1580,   1610,   1620,   1581,   1610,   1620,
5374
    1605,   1610,   1620,   1609,   1610,   1620,   1610,   1576,   1580,
5375
    1576,   1581,   1576,   1582,   1576,   1605,   1576,   1609,   1576,
5376
    1610,   1578,   1580,   1578,   1581,   1578,   1582,   1578,   1605,
5377
    1578,   1609,   1578,   1610,   1579,   1580,   1579,   1605,   1579,
5378
    1609,   1579,   1610,   1580,   1581,   1580,   1605,   1581,   1580,
5379
    1581,   1605,   1582,   1580,   1582,   1581,   1582,   1605,   1587,
5380
    1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,   1581,
5381
    1589,   1605,   1590,   1580,   1590,   1581,   1590,   1582,   1590,
5382
    1605,   1591,   1581,   1591,   1605,   1592,   1605,   1593,   1580,
5383
    1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,   1601,
5384
    1581,   1601,   1582,   1601,   1605,   1601,   1609,   1601,   1610,
5385
    1602,   1581,   1602,   1605,   1602,   1609,   1602,   1610,   1603,
5386
    1575,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5387
    1603,   1605,   1603,   1609,   1603,   1610,   1604,   1580,   1604,
5388
    1581,   1604,   1582,   1604,   1605,   1604,   1609,   1604,   1610,
5389
    1605,   1580,   1605,   1581,   1605,   1582,   1605,   1605,   1605,
5390
    1609,   1605,   1610,   1606,   1580,   1606,   1581,   1606,   1582,
5391
    1606,   1605,   1606,   1609,   1606,   1610,   1607,   1580,   1607,
5392
    1605,   1607,   1609,   1607,   1610,   1610,   1580,   1610,   1581,
5393
    1610,   1582,   1610,   1605,   1610,   1609,   1610,   1610,   1584,
5394
    1648,   1585,   1648,   1609,   1648,   32,     1612,   1617,   32,
5395
    1613,   1617,   32,     1614,   1617,   32,     1615,   1617,   32,
5396
    1616,   1617,   32,     1617,   1648,   1610,   1620,   1585,   1610,
5397
    1620,   1586,   1610,   1620,   1605,   1610,   1620,   1606,   1610,
5398
    1620,   1609,   1610,   1620,   1610,   1576,   1585,   1576,   1586,
5399
    1576,   1605,   1576,   1606,   1576,   1609,   1576,   1610,   1578,
5400
    1585,   1578,   1586,   1578,   1605,   1578,   1606,   1578,   1609,
5401
    1578,   1610,   1579,   1585,   1579,   1586,   1579,   1605,   1579,
5402
    1606,   1579,   1609,   1579,   1610,   1601,   1609,   1601,   1610,
5403
    1602,   1609,   1602,   1610,   1603,   1575,   1603,   1604,   1603,
5404
    1605,   1603,   1609,   1603,   1610,   1604,   1605,   1604,   1609,
5405
    1604,   1610,   1605,   1575,   1605,   1605,   1606,   1585,   1606,
5406
    1586,   1606,   1605,   1606,   1606,   1606,   1609,   1606,   1610,
5407
    1609,   1648,   1610,   1585,   1610,   1586,   1610,   1605,   1610,
5408
    1606,   1610,   1609,   1610,   1610,   1610,   1620,   1580,   1610,
5409
    1620,   1581,   1610,   1620,   1582,   1610,   1620,   1605,   1610,
5410
    1620,   1607,   1576,   1580,   1576,   1581,   1576,   1582,   1576,
5411
    1605,   1576,   1607,   1578,   1580,   1578,   1581,   1578,   1582,
5412
    1578,   1605,   1578,   1607,   1579,   1605,   1580,   1581,   1580,
5413
    1605,   1581,   1580,   1581,   1605,   1582,   1580,   1582,   1605,
5414
    1587,   1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,
5415
    1581,   1589,   1582,   1589,   1605,   1590,   1580,   1590,   1581,
5416
    1590,   1582,   1590,   1605,   1591,   1581,   1592,   1605,   1593,
5417
    1580,   1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,
5418
    1601,   1581,   1601,   1582,   1601,   1605,   1602,   1581,   1602,
5419
    1605,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5420
    1603,   1605,   1604,   1580,   1604,   1581,   1604,   1582,   1604,
5421
    1605,   1604,   1607,   1605,   1580,   1605,   1581,   1605,   1582,
5422
    1605,   1605,   1606,   1580,   1606,   1581,   1606,   1582,   1606,
5423
    1605,   1606,   1607,   1607,   1580,   1607,   1605,   1607,   1648,
5424
    1610,   1580,   1610,   1581,   1610,   1582,   1610,   1605,   1610,
5425
    1607,   1610,   1620,   1605,   1610,   1620,   1607,   1576,   1605,
5426
    1576,   1607,   1578,   1605,   1578,   1607,   1579,   1605,   1579,
5427
    1607,   1587,   1605,   1587,   1607,   1588,   1605,   1588,   1607,
5428
    1603,   1604,   1603,   1605,   1604,   1605,   1606,   1605,   1606,
5429
    1607,   1610,   1605,   1610,   1607,   1600,   1614,   1617,   1600,
5430
    1615,   1617,   1600,   1616,   1617,   1591,   1609,   1591,   1610,
5431
    1593,   1609,   1593,   1610,   1594,   1609,   1594,   1610,   1587,
5432
    1609,   1587,   1610,   1588,   1609,   1588,   1610,   1581,   1609,
5433
    1581,   1610,   1580,   1609,   1580,   1610,   1582,   1609,   1582,
5434
    1610,   1589,   1609,   1589,   1610,   1590,   1609,   1590,   1610,
5435
    1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1588,
5436
    1585,   1587,   1585,   1589,   1585,   1590,   1585,   1591,   1609,
5437
    1591,   1610,   1593,   1609,   1593,   1610,   1594,   1609,   1594,
5438
    1610,   1587,   1609,   1587,   1610,   1588,   1609,   1588,   1610,
5439
    1581,   1609,   1581,   1610,   1580,   1609,   1580,   1610,   1582,
5440
    1609,   1582,   1610,   1589,   1609,   1589,   1610,   1590,   1609,
5441
    1590,   1610,   1588,   1580,   1588,   1581,   1588,   1582,   1588,
5442
    1605,   1588,   1585,   1587,   1585,   1589,   1585,   1590,   1585,
5443
    1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1587,
5444
    1607,   1588,   1607,   1591,   1605,   1587,   1580,   1587,   1581,
5445
    1587,   1582,   1588,   1580,   1588,   1581,   1588,   1582,   1591,
5446
    1605,   1592,   1605,   1575,   1611,   1575,   1611,   1578,   1580,
5447
    1605,   1578,   1581,   1580,   1578,   1581,   1580,   1578,   1581,
5448
    1605,   1578,   1582,   1605,   1578,   1605,   1580,   1578,   1605,
5449
    1581,   1578,   1605,   1582,   1580,   1605,   1581,   1580,   1605,
5450
    1581,   1581,   1605,   1610,   1581,   1605,   1609,   1587,   1581,
5451
    1580,   1587,   1580,   1581,   1587,   1580,   1609,   1587,   1605,
5452
    1581,   1587,   1605,   1581,   1587,   1605,   1580,   1587,   1605,
5453
    1605,   1587,   1605,   1605,   1589,   1581,   1581,   1589,   1581,
5454
    1581,   1589,   1605,   1605,   1588,   1581,   1605,   1588,   1581,
5455
    1605,   1588,   1580,   1610,   1588,   1605,   1582,   1588,   1605,
5456
    1582,   1588,   1605,   1605,   1588,   1605,   1605,   1590,   1581,
5457
    1609,   1590,   1582,   1605,   1590,   1582,   1605,   1591,   1605,
5458
    1581,   1591,   1605,   1581,   1591,   1605,   1605,   1591,   1605,
5459
    1610,   1593,   1580,   1605,   1593,   1605,   1605,   1593,   1605,
5460
    1605,   1593,   1605,   1609,   1594,   1605,   1605,   1594,   1605,
5461
    1610,   1594,   1605,   1609,   1601,   1582,   1605,   1601,   1582,
5462
    1605,   1602,   1605,   1581,   1602,   1605,   1605,   1604,   1581,
5463
    1605,   1604,   1581,   1610,   1604,   1581,   1609,   1604,   1580,
5464
    1580,   1604,   1580,   1580,   1604,   1582,   1605,   1604,   1582,
5465
    1605,   1604,   1605,   1581,   1604,   1605,   1581,   1605,   1581,
5466
    1580,   1605,   1581,   1605,   1605,   1581,   1610,   1605,   1580,
5467
    1581,   1605,   1580,   1605,   1605,   1582,   1580,   1605,   1582,
5468
    1605,   1605,   1580,   1582,   1607,   1605,   1580,   1607,   1605,
5469
    1605,   1606,   1581,   1605,   1606,   1581,   1609,   1606,   1580,
5470
    1605,   1606,   1580,   1605,   1606,   1580,   1609,   1606,   1605,
5471
    1610,   1606,   1605,   1609,   1610,   1605,   1605,   1610,   1605,
5472
    1605,   1576,   1582,   1610,   1578,   1580,   1610,   1578,   1580,
5473
    1609,   1578,   1582,   1610,   1578,   1582,   1609,   1578,   1605,
5474
    1610,   1578,   1605,   1609,   1580,   1605,   1610,   1580,   1581,
5475
    1609,   1580,   1605,   1609,   1587,   1582,   1609,   1589,   1581,
5476
    1610,   1588,   1581,   1610,   1590,   1581,   1610,   1604,   1580,
5477
    1610,   1604,   1605,   1610,   1610,   1581,   1610,   1610,   1580,
5478
    1610,   1610,   1605,   1610,   1605,   1605,   1610,   1602,   1605,
5479
    1610,   1606,   1581,   1610,   1602,   1605,   1581,   1604,   1581,
5480
    1605,   1593,   1605,   1610,   1603,   1605,   1610,   1606,   1580,
5481
    1581,   1605,   1582,   1610,   1604,   1580,   1605,   1603,   1605,
5482
    1605,   1604,   1580,   1605,   1606,   1580,   1581,   1580,   1581,
5483
    1610,   1581,   1580,   1610,   1605,   1580,   1610,   1601,   1605,
5484
    1610,   1576,   1581,   1610,   1603,   1605,   1605,   1593,   1580,
5485
    1605,   1589,   1605,   1605,   1587,   1582,   1610,   1606,   1580,
5486
    1610,   1589,   1604,   1746,   1602,   1604,   1746,   1575,   1604,
5487
    1604,   1607,   1575,   1603,   1576,   1585,   1605,   1581,   1605,
5488
    1583,   1589,   1604,   1593,   1605,   1585,   1587,   1608,   1604,
5489
    1593,   1604,   1610,   1607,   1608,   1587,   1604,   1605,   1589,
5490
    1604,   1609,   1589,   1604,   1609,   32,     1575,   1604,   1604,
5491
    1607,   32,     1593,   1604,   1610,   1607,   32,     1608,   1587,
5492
    1604,   1605,   1580,   1604,   32,     1580,   1604,   1575,   1604,
5493
    1607,   1585,   1740,   1575,   1604,   44,     12289,  12290,  58,
5494
    59,     33,     63,     12310,  12311,  46,     46,     46,     46,
5495
    46,     8212,   8211,   95,     95,     40,     41,     123,    125,
5496
    12308,  12309,  12304,  12305,  12298,  12299,  12296,  12297,  12300,
5497
    12301,  12302,  12303,  91,     93,     32,     773,    32,     773,
5498
    32,     773,    32,     773,    95,     95,     95,     44,     12289,
5499
    46,     59,     58,     63,     33,     8212,   40,     41,     123,
5500
    125,    12308,  12309,  35,     38,     42,     43,     45,     60,
5501
    62,     61,     92,     36,     37,     64,     32,     1611,   1600,
5502
    1611,   32,     1612,   32,     1613,   32,     1614,   1600,   1614,
5503
    32,     1615,   1600,   1615,   32,     1616,   1600,   1616,   32,
5504
    1617,   1600,   1617,   32,     1618,   1600,   1618,   1569,   1575,
5505
    1619,   1575,   1619,   1575,   1620,   1575,   1620,   1608,   1620,
5506
    1608,   1620,   1575,   1621,   1575,   1621,   1610,   1620,   1610,
5507
    1620,   1610,   1620,   1610,   1620,   1575,   1575,   1576,   1576,
5508
    1576,   1576,   1577,   1577,   1578,   1578,   1578,   1578,   1579,
5509
    1579,   1579,   1579,   1580,   1580,   1580,   1580,   1581,   1581,
5510
    1581,   1581,   1582,   1582,   1582,   1582,   1583,   1583,   1584,
5511
    1584,   1585,   1585,   1586,   1586,   1587,   1587,   1587,   1587,
5512
    1588,   1588,   1588,   1588,   1589,   1589,   1589,   1589,   1590,
5513
    1590,   1590,   1590,   1591,   1591,   1591,   1591,   1592,   1592,
5514
    1592,   1592,   1593,   1593,   1593,   1593,   1594,   1594,   1594,
5515
    1594,   1601,   1601,   1601,   1601,   1602,   1602,   1602,   1602,
5516
    1603,   1603,   1603,   1603,   1604,   1604,   1604,   1604,   1605,
5517
    1605,   1605,   1605,   1606,   1606,   1606,   1606,   1607,   1607,
5518
    1607,   1607,   1608,   1608,   1609,   1609,   1610,   1610,   1610,
5519
    1610,   1604,   1575,   1619,   1604,   1575,   1619,   1604,   1575,
5520
    1620,   1604,   1575,   1620,   1604,   1575,   1621,   1604,   1575,
5521
    1621,   1604,   1575,   1604,   1575,   33,     34,     35,     36,
5522
    37,     38,     39,     40,     41,     42,     43,     44,     45,
5523
    46,     47,     48,     49,     50,     51,     52,     53,     54,
5524
    55,     56,     57,     58,     59,     60,     61,     62,     63,
5525
    64,     65,     66,     67,     68,     69,     70,     71,     72,
5526
    73,     74,     75,     76,     77,     78,     79,     80,     81,
5527
    82,     83,     84,     85,     86,     87,     88,     89,     90,
5528
    91,     92,     93,     94,     95,     96,     97,     98,     99,
5529
    100,    101,    102,    103,    104,    105,    106,    107,    108,
5530
    109,    110,    111,    112,    113,    114,    115,    116,    117,
5531
    118,    119,    120,    121,    122,    123,    124,    125,    126,
5532
    10629,  10630,  12290,  12300,  12301,  12289,  12539,  12530,  12449,
5533
    12451,  12453,  12455,  12457,  12515,  12517,  12519,  12483,  12540,
5534
    12450,  12452,  12454,  12456,  12458,  12459,  12461,  12463,  12465,
5535
    12467,  12469,  12471,  12473,  12475,  12477,  12479,  12481,  12484,
5536
    12486,  12488,  12490,  12491,  12492,  12493,  12494,  12495,  12498,
5537
    12501,  12504,  12507,  12510,  12511,  12512,  12513,  12514,  12516,
5538
    12518,  12520,  12521,  12522,  12523,  12524,  12525,  12527,  12531,
5539
    12441,  12442,  4448,   4352,   4353,   4522,   4354,   4524,   4525,
5540
    4355,   4356,   4357,   4528,   4529,   4530,   4531,   4532,   4533,
5541
    4378,   4358,   4359,   4360,   4385,   4361,   4362,   4363,   4364,
5542
    4365,   4366,   4367,   4368,   4369,   4370,   4449,   4450,   4451,
5543
    4452,   4453,   4454,   4455,   4456,   4457,   4458,   4459,   4460,
5544
    4461,   4462,   4463,   4464,   4465,   4466,   4467,   4468,   4469,
5545
    162,    163,    172,    32,     772,    166,    165,    8361,   9474,
5546
    8592,   8593,   8594,   8595,   9632,   9675,   720,    721,    230,
5547
    665,    595,    675,    43878,  677,    676,    598,    599,    7569,
5548
    600,    606,    681,    612,    610,    608,    667,    295,    668,
5549
    615,    644,    682,    683,    620,    122628, 42894,  622,    122629,
5550
    654,    122630, 248,    630,    631,    113,    634,    122632, 637,
5551
    638,    640,    680,    678,    43879,  679,    648,    11377,  655,
5552
    673,    674,    664,    448,    449,    450,    122634, 122654, 69785,
5553
    69818,  69787,  69818,  69797,  69818,  69937,  69927,  69938,  69927,
5554
    70471,  70462,  70471,  70487,  70841,  70842,  70841,  70832,  70841,
5555
    70845,  71096,  71087,  71097,  71087,  71989,  71984,  119127, 119141,
5556
    119128, 119141, 119128, 119141, 119150, 119128, 119141, 119151, 119128,
5557
    119141, 119152, 119128, 119141, 119153, 119128, 119141, 119154, 119225,
5558
    119141, 119226, 119141, 119225, 119141, 119150, 119226, 119141, 119150,
5559
    119225, 119141, 119151, 119226, 119141, 119151, 65,     66,     67,
5560
    68,     69,     70,     71,     72,     73,     74,     75,     76,
5561
    77,     78,     79,     80,     81,     82,     83,     84,     85,
5562
    86,     87,     88,     89,     90,     97,     98,     99,     100,
5563
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5564
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5565
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5566
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5567
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5568
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5569
    103,    105,    106,    107,    108,    109,    110,    111,    112,
5570
    113,    114,    115,    116,    117,    118,    119,    120,    121,
5571
    122,    65,     66,     67,     68,     69,     70,     71,     72,
5572
    73,     74,     75,     76,     77,     78,     79,     80,     81,
5573
    82,     83,     84,     85,     86,     87,     88,     89,     90,
5574
    97,     98,     99,     100,    101,    102,    103,    104,    105,
5575
    106,    107,    108,    109,    110,    111,    112,    113,    114,
5576
    115,    116,    117,    118,    119,    120,    121,    122,    65,
5577
    67,     68,     71,     74,     75,     78,     79,     80,     81,
5578
    83,     84,     85,     86,     87,     88,     89,     90,     97,
5579
    98,     99,     100,    102,    104,    105,    106,    107,    108,
5580
    109,    110,    112,    113,    114,    115,    116,    117,    118,
5581
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5582
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5583
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5584
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5585
    103,    104,    105,    106,    107,    108,    109,    110,    111,
5586
    112,    113,    114,    115,    116,    117,    118,    119,    120,
5587
    121,    122,    65,     66,     68,     69,     70,     71,     74,
5588
    75,     76,     77,     78,     79,     80,     81,     83,     84,
5589
    85,     86,     87,     88,     89,     97,     98,     99,     100,
5590
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5591
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5592
    119,    120,    121,    122,    65,     66,     68,     69,     70,
5593
    71,     73,     74,     75,     76,     77,     79,     83,     84,
5594
    85,     86,     87,     88,     89,     97,     98,     99,     100,
5595
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5596
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5597
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5598
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5599
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5600
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5601
    103,    104,    105,    106,    107,    108,    109,    110,    111,
5602
    112,    113,    114,    115,    116,    117,    118,    119,    120,
5603
    121,    122,    65,     66,     67,     68,     69,     70,     71,
5604
    72,     73,     74,     75,     76,     77,     78,     79,     80,
5605
    81,     82,     83,     84,     85,     86,     87,     88,     89,
5606
    90,     97,     98,     99,     100,    101,    102,    103,    104,
5607
    105,    106,    107,    108,    109,    110,    111,    112,    113,
5608
    114,    115,    116,    117,    118,    119,    120,    121,    122,
5609
    65,     66,     67,     68,     69,     70,     71,     72,     73,
5610
    74,     75,     76,     77,     78,     79,     80,     81,     82,
5611
    83,     84,     85,     86,     87,     88,     89,     90,     97,
5612
    98,     99,     100,    101,    102,    103,    104,    105,    106,
5613
    107,    108,    109,    110,    111,    112,    113,    114,    115,
5614
    116,    117,    118,    119,    120,    121,    122,    65,     66,
5615
    67,     68,     69,     70,     71,     72,     73,     74,     75,
5616
    76,     77,     78,     79,     80,     81,     82,     83,     84,
5617
    85,     86,     87,     88,     89,     90,     97,     98,     99,
5618
    100,    101,    102,    103,    104,    105,    106,    107,    108,
5619
    109,    110,    111,    112,    113,    114,    115,    116,    117,
5620
    118,    119,    120,    121,    122,    65,     66,     67,     68,
5621
    69,     70,     71,     72,     73,     74,     75,     76,     77,
5622
    78,     79,     80,     81,     82,     83,     84,     85,     86,
5623
    87,     88,     89,     90,     97,     98,     99,     100,    101,
5624
    102,    103,    104,    105,    106,    107,    108,    109,    110,
5625
    111,    112,    113,    114,    115,    116,    117,    118,    119,
5626
    120,    121,    122,    65,     66,     67,     68,     69,     70,
5627
    71,     72,     73,     74,     75,     76,     77,     78,     79,
5628
    80,     81,     82,     83,     84,     85,     86,     87,     88,
5629
    89,     90,     97,     98,     99,     100,    101,    102,    103,
5630
    104,    105,    106,    107,    108,    109,    110,    111,    112,
5631
    113,    114,    115,    116,    117,    118,    119,    120,    121,
5632
    122,    305,    567,    913,    914,    915,    916,    917,    918,
5633
    919,    920,    921,    922,    923,    924,    925,    926,    927,
5634
    928,    929,    920,    931,    932,    933,    934,    935,    936,
5635
    937,    8711,   945,    946,    947,    948,    949,    950,    951,
5636
    952,    953,    954,    955,    956,    957,    958,    959,    960,
5637
    961,    962,    963,    964,    965,    966,    967,    968,    969,
5638
    8706,   949,    952,    954,    966,    961,    960,    913,    914,
5639
    915,    916,    917,    918,    919,    920,    921,    922,    923,
5640
    924,    925,    926,    927,    928,    929,    920,    931,    932,
5641
    933,    934,    935,    936,    937,    8711,   945,    946,    947,
5642
    948,    949,    950,    951,    952,    953,    954,    955,    956,
5643
    957,    958,    959,    960,    961,    962,    963,    964,    965,
5644
    966,    967,    968,    969,    8706,   949,    952,    954,    966,
5645
    961,    960,    913,    914,    915,    916,    917,    918,    919,
5646
    920,    921,    922,    923,    924,    925,    926,    927,    928,
5647
    929,    920,    931,    932,    933,    934,    935,    936,    937,
5648
    8711,   945,    946,    947,    948,    949,    950,    951,    952,
5649
    953,    954,    955,    956,    957,    958,    959,    960,    961,
5650
    962,    963,    964,    965,    966,    967,    968,    969,    8706,
5651
    949,    952,    954,    966,    961,    960,    913,    914,    915,
5652
    916,    917,    918,    919,    920,    921,    922,    923,    924,
5653
    925,    926,    927,    928,    929,    920,    931,    932,    933,
5654
    934,    935,    936,    937,    8711,   945,    946,    947,    948,
5655
    949,    950,    951,    952,    953,    954,    955,    956,    957,
5656
    958,    959,    960,    961,    962,    963,    964,    965,    966,
5657
    967,    968,    969,    8706,   949,    952,    954,    966,    961,
5658
    960,    913,    914,    915,    916,    917,    918,    919,    920,
5659
    921,    922,    923,    924,    925,    926,    927,    928,    929,
5660
    920,    931,    932,    933,    934,    935,    936,    937,    8711,
5661
    945,    946,    947,    948,    949,    950,    951,    952,    953,
5662
    954,    955,    956,    957,    958,    959,    960,    961,    962,
5663
    963,    964,    965,    966,    967,    968,    969,    8706,   949,
5664
    952,    954,    966,    961,    960,    988,    989,    48,     49,
5665
    50,     51,     52,     53,     54,     55,     56,     57,     48,
5666
    49,     50,     51,     52,     53,     54,     55,     56,     57,
5667
    48,     49,     50,     51,     52,     53,     54,     55,     56,
5668
    57,     48,     49,     50,     51,     52,     53,     54,     55,
5669
    56,     57,     48,     49,     50,     51,     52,     53,     54,
5670
    55,     56,     57,     1072,   1073,   1074,   1075,   1076,   1077,
5671
    1078,   1079,   1080,   1082,   1083,   1084,   1086,   1087,   1088,
5672
    1089,   1090,   1091,   1092,   1093,   1094,   1095,   1096,   1099,
5673
    1101,   1102,   42633,  1241,   1110,   1112,   1257,   1199,   1231,
5674
    1072,   1073,   1074,   1075,   1076,   1077,   1078,   1079,   1080,
5675
    1082,   1083,   1086,   1087,   1089,   1091,   1092,   1093,   1094,
5676
    1095,   1096,   1098,   1099,   1169,   1110,   1109,   1119,   1195,
5677
    42577,  1201,   1575,   1576,   1580,   1583,   1608,   1586,   1581,
5678
    1591,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5679
    1589,   1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,
5680
    1592,   1594,   1646,   1722,   1697,   1647,   1576,   1580,   1607,
5681
    1581,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5682
    1589,   1602,   1588,   1578,   1579,   1582,   1590,   1594,   1580,
5683
    1581,   1610,   1604,   1606,   1587,   1593,   1589,   1602,   1588,
5684
    1582,   1590,   1594,   1722,   1647,   1576,   1580,   1607,   1581,
5685
    1591,   1610,   1603,   1605,   1606,   1587,   1593,   1601,   1589,
5686
    1602,   1588,   1578,   1579,   1582,   1590,   1592,   1594,   1646,
5687
    1697,   1575,   1576,   1580,   1583,   1607,   1608,   1586,   1581,
5688
    1591,   1610,   1604,   1605,   1606,   1587,   1593,   1601,   1589,
5689
    1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,   1592,
5690
    1594,   1576,   1580,   1583,   1608,   1586,   1581,   1591,   1610,
5691
    1604,   1605,   1606,   1587,   1593,   1601,   1589,   1602,   1585,
5692
    1588,   1578,   1579,   1582,   1584,   1590,   1592,   1594,   48,
5693
    46,     48,     44,     49,     44,     50,     44,     51,     44,
5694
    52,     44,     53,     44,     54,     44,     55,     44,     56,
5695
    44,     57,     44,     40,     65,     41,     40,     66,     41,
5696
    40,     67,     41,     40,     68,     41,     40,     69,     41,
5697
    40,     70,     41,     40,     71,     41,     40,     72,     41,
5698
    40,     73,     41,     40,     74,     41,     40,     75,     41,
5699
    40,     76,     41,     40,     77,     41,     40,     78,     41,
5700
    40,     79,     41,     40,     80,     41,     40,     81,     41,
5701
    40,     82,     41,     40,     83,     41,     40,     84,     41,
5702
    40,     85,     41,     40,     86,     41,     40,     87,     41,
5703
    40,     88,     41,     40,     89,     41,     40,     90,     41,
5704
    12308,  83,     12309,  67,     82,     67,     68,     87,     90,
5705
    65,     66,     67,     68,     69,     70,     71,     72,     73,
5706
    74,     75,     76,     77,     78,     79,     80,     81,     82,
5707
    83,     84,     85,     86,     87,     88,     89,     90,     72,
5708
    86,     77,     86,     83,     68,     83,     83,     80,     80,
5709
    86,     87,     67,     77,     67,     77,     68,     77,     82,
5710
    68,     74,     12411,  12363,  12467,  12467,  12469,  25163,  23383,
5711
    21452,  12486,  12441,  20108,  22810,  35299,  22825,  20132,  26144,
5712
    28961,  26009,  21069,  24460,  20877,  26032,  21021,  32066,  29983,
5713
    36009,  22768,  21561,  28436,  25237,  25429,  19968,  19977,  36938,
5714
    24038,  20013,  21491,  25351,  36208,  25171,  31105,  31354,  21512,
5715
    28288,  26377,  26376,  30003,  21106,  21942,  37197,  12308,  26412,
5716
    12309,  12308,  19977,  12309,  12308,  20108,  12309,  12308,  23433,
5717
    12309,  12308,  28857,  12309,  12308,  25171,  12309,  12308,  30423,
5718
    12309,  12308,  21213,  12309,  12308,  25943,  12309,  24471,  21487,
5719
    48,     49,     50,     51,     52,     53,     54,     55,     56,
5720
    57,     20029,  20024,  20033,  131362, 20320,  20398,  20411,  20482,
5721
    20602,  20633,  20711,  20687,  13470,  132666, 20813,  20820,  20836,
5722
    20855,  132380, 13497,  20839,  20877,  132427, 20887,  20900,  20172,
5723
    20908,  20917,  168415, 20981,  20995,  13535,  21051,  21062,  21106,
5724
    21111,  13589,  21191,  21193,  21220,  21242,  21253,  21254,  21271,
5725
    21321,  21329,  21338,  21363,  21373,  21375,  21375,  21375,  133676,
5726
    28784,  21450,  21471,  133987, 21483,  21489,  21510,  21662,  21560,
5727
    21576,  21608,  21666,  21750,  21776,  21843,  21859,  21892,  21892,
5728
    21913,  21931,  21939,  21954,  22294,  22022,  22295,  22097,  22132,
5729
    20999,  22766,  22478,  22516,  22541,  22411,  22578,  22577,  22700,
5730
    136420, 22770,  22775,  22790,  22810,  22818,  22882,  136872, 136938,
5731
    23020,  23067,  23079,  23000,  23142,  14062,  14076,  23304,  23358,
5732
    23358,  137672, 23491,  23512,  23527,  23539,  138008, 23551,  23558,
5733
    24403,  23586,  14209,  23648,  23662,  23744,  23693,  138724, 23875,
5734
    138726, 23918,  23915,  23932,  24033,  24034,  14383,  24061,  24104,
5735
    24125,  24169,  14434,  139651, 14460,  24240,  24243,  24246,  24266,
5736
    172946, 24318,  140081, 140081, 33281,  24354,  24354,  14535,  144056,
5737
    156122, 24418,  24427,  14563,  24474,  24525,  24535,  24569,  24705,
5738
    14650,  14620,  24724,  141012, 24775,  24904,  24908,  24910,  24908,
5739
    24954,  24974,  25010,  24996,  25007,  25054,  25074,  25078,  25104,
5740
    25115,  25181,  25265,  25300,  25424,  142092, 25405,  25340,  25448,
5741
    25475,  25572,  142321, 25634,  25541,  25513,  14894,  25705,  25726,
5742
    25757,  25719,  14956,  25935,  25964,  143370, 26083,  26360,  26185,
5743
    15129,  26257,  15112,  15076,  20882,  20885,  26368,  26268,  32941,
5744
    17369,  26391,  26395,  26401,  26462,  26451,  144323, 15177,  26618,
5745
    26501,  26706,  26757,  144493, 26766,  26655,  26900,  15261,  26946,
5746
    27043,  27114,  27304,  145059, 27355,  15384,  27425,  145575, 27476,
5747
    15438,  27506,  27551,  27578,  27579,  146061, 138507, 146170, 27726,
5748
    146620, 27839,  27853,  27751,  27926,  27966,  28023,  27969,  28009,
5749
    28024,  28037,  146718, 27956,  28207,  28270,  15667,  28363,  28359,
5750
    147153, 28153,  28526,  147294, 147342, 28614,  28729,  28702,  28699,
5751
    15766,  28746,  28797,  28791,  28845,  132389, 28997,  148067, 29084,
5752
    148395, 29224,  29237,  29264,  149000, 29312,  29333,  149301, 149524,
5753
    29562,  29579,  16044,  29605,  16056,  16056,  29767,  29788,  29809,
5754
    29829,  29898,  16155,  29988,  150582, 30014,  150674, 30064,  139679,
5755
    30224,  151457, 151480, 151620, 16380,  16392,  30452,  151795, 151794,
5756
    151833, 151859, 30494,  30495,  30495,  30538,  16441,  30603,  16454,
5757
    16534,  152605, 30798,  30860,  30924,  16611,  153126, 31062,  153242,
5758
    153285, 31119,  31211,  16687,  31296,  31306,  31311,  153980, 154279,
5759
    154279, 31470,  16898,  154539, 31686,  31689,  16935,  154752, 31954,
5760
    17056,  31976,  31971,  32000,  155526, 32099,  17153,  32199,  32258,
5761
    32325,  17204,  156200, 156231, 17241,  156377, 32634,  156478, 32661,
5762
    32762,  32773,  156890, 156963, 32864,  157096, 32880,  144223, 17365,
5763
    32946,  33027,  17419,  33086,  23221,  157607, 157621, 144275, 144284,
5764
    33281,  33284,  36766,  17515,  33425,  33419,  33437,  21171,  33457,
5765
    33459,  33469,  33510,  158524, 33509,  33565,  33635,  33709,  33571,
5766
    33725,  33767,  33879,  33619,  33738,  33740,  33756,  158774, 159083,
5767
    158933, 17707,  34033,  34035,  34070,  160714, 34148,  159532, 17757,
5768
    17761,  159665, 159954, 17771,  34384,  34396,  34407,  34409,  34473,
5769
    34440,  34574,  34530,  34681,  34600,  34667,  34694,  17879,  34785,
5770
    34817,  17913,  34912,  34915,  161383, 35031,  35038,  17973,  35066,
5771
    13499,  161966, 162150, 18110,  18119,  35488,  35565,  35722,  35925,
5772
    162984, 36011,  36033,  36123,  36215,  163631, 133124, 36299,  36284,
5773
    36336,  133342, 36564,  36664,  165330, 165357, 37012,  37105,  37137,
5774
    165678, 37147,  37432,  37591,  37592,  37500,  37881,  37909,  166906,
5775
    38283,  18837,  38327,  167287, 18918,  38595,  23986,  38691,  168261,
5776
    168474, 19054,  19062,  38880,  168970, 19122,  169110, 38923,  38923,
5777
    38953,  169398, 39138,  19251,  39209,  39335,  39362,  39422,  19406,
5778
    170800, 39698,  40000,  40189,  19662,  19693,  40295,  172238, 19704,
5779
    172293, 172558, 172689, 40635,  19798,  40697,  40702,  40709,  40719,
5780
    40726,  40763,  173568};
5781
5782
const uint8_t canonical_combining_class_index[4352] = {
5783
    0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 0,  0,
5784
    15, 0,  0,  0,  16, 17, 18, 19, 20, 21, 22, 0,  0,  23, 0,  0,  0,  0,  0,
5785
    0,  0,  0,  0,  0,  0,  24, 25, 0,  0,  26, 0,  0,  0,  0,  0,  0,  0,  0,
5786
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5787
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5788
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5789
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5790
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5791
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  27, 0,  28, 29, 30,
5792
    31, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5793
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5794
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5795
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5796
    0,  0,  0,  0,  32, 0,  0,  33, 0,  0,  34, 35, 36, 0,  0,  0,  0,  0,  0,
5797
    37, 0,  0,  38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,  52,
5798
    53, 0,  54, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5799
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5800
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5801
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5802
    0,  55, 56, 0,  0,  0,  57, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5803
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5804
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5805
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5806
    0,  0,  0,  0,  0,  0,  0,  58, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5807
    0,  0,  0,  0,  0,  0,  0,  0,  0,  59, 60, 0,  0,  0,  0,  0,  0,  0,  0,
5808
    0,  0,  0,  0,  0,  61, 56, 62, 0,  63, 0,  0,  0,  64, 65, 0,  0,  0,  0,
5809
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5810
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5811
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5812
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5813
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5814
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5815
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5816
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5817
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5818
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5819
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5820
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5821
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5822
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5823
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5824
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5825
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5826
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5827
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5828
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5829
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5830
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5831
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5832
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5833
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5834
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5835
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5836
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5837
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5838
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5839
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5840
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5841
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5842
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5843
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5844
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5845
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5846
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5847
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5848
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5849
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5850
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5851
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5852
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5853
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5854
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5855
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5856
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5857
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5858
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5859
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5860
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5861
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5862
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5863
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5864
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5865
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5866
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5867
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5868
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5869
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5870
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5871
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5872
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5873
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5874
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5875
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5876
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5877
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5878
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5879
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5880
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5881
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5882
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5883
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5884
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5885
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5886
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5887
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5888
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5889
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5890
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5891
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5892
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5893
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5894
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5895
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5896
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5897
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5898
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5899
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5900
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5901
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5902
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5903
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5904
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5905
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5906
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5907
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5908
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5909
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5910
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5911
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5912
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5913
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5914
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5915
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5916
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5917
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5918
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5919
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5920
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5921
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5922
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5923
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5924
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5925
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5926
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5927
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5928
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5929
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5930
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5931
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5932
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5933
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5934
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5935
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5936
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5937
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5938
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5939
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5940
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5941
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5942
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5943
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5944
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5945
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5946
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5947
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5948
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5949
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5950
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5951
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5952
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5953
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5954
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5955
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5956
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5957
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5958
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5959
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5960
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5961
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5962
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5963
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5964
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5965
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5966
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5967
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5968
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5969
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5970
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5971
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5972
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5973
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5974
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5975
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5976
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5977
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5978
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5979
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5980
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5981
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5982
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5983
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5984
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5985
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5986
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5987
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5988
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5989
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5990
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5991
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5992
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5993
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5994
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5995
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5996
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5997
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5998
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5999
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6000
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6001
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6002
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6003
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6004
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6005
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6006
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6007
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6008
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6009
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6010
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6011
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6012
    0};
6013
const uint8_t canonical_combining_class_block[67][256] = {
6014
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6015
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6016
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6017
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6018
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6019
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6020
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6021
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6022
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6023
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6024
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6025
    {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6026
     230, 230, 230, 230, 230, 230, 232, 220, 220, 220, 220, 232, 216, 220, 220,
6027
     220, 220, 220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220,
6028
     220, 220, 220, 220, 220, 220, 220, 1,   1,   1,   1,   1,   220, 220, 220,
6029
     220, 230, 230, 230, 230, 230, 230, 230, 230, 240, 230, 220, 220, 220, 230,
6030
     230, 230, 220, 220, 0,   230, 230, 230, 220, 220, 220, 220, 230, 232, 220,
6031
     220, 230, 233, 234, 234, 233, 234, 234, 233, 230, 230, 230, 230, 230, 230,
6032
     230, 230, 230, 230, 230, 230, 230, 0,   0,   0,   0,   0,   0,   0,   0,
6033
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6034
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6035
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6036
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6037
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6038
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6039
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6040
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6041
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6042
     0},
6043
    {0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6044
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6045
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6046
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6047
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6048
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230,
6049
     230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6050
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6051
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6052
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6053
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6054
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6055
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6056
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6057
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6058
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6059
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6060
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6061
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6062
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6063
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6064
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 230, 230, 230, 230,
6065
     220, 230, 230, 230, 222, 220, 230, 230, 230, 230, 230, 230, 220, 220, 220,
6066
     220, 220, 220, 230, 230, 220, 230, 230, 222, 228, 230, 10,  11,  12,  13,
6067
     14,  15,  16,  17,  18,  19,  19,  20,  21,  22,  0,   23,  0,   24,  25,
6068
     0,   230, 220, 0,   18,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6069
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6070
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6071
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6072
     0},
6073
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6074
     0,   230, 230, 230, 230, 230, 230, 230, 230, 30,  31,  32,  0,   0,   0,
6075
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6076
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6077
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6078
     27,  28,  29,  30,  31,  32,  33,  34,  230, 230, 220, 220, 230, 230, 230,
6079
     230, 230, 220, 230, 230, 220, 0,   0,   0,   0,   0,   0,   0,   0,   0,
6080
     0,   0,   0,   0,   0,   0,   0,   35,  0,   0,   0,   0,   0,   0,   0,
6081
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6082
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6083
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6084
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6085
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6086
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6087
     0,   0,   0,   0,   230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230,
6088
     230, 230, 220, 230, 0,   0,   230, 230, 0,   220, 230, 230, 220, 0,   0,
6089
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6090
     0},
6091
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6092
     0,   0,   36,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6093
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6094
     0,   0,   0,   230, 220, 230, 230, 220, 230, 230, 220, 220, 220, 230, 220,
6095
     220, 230, 220, 230, 230, 230, 220, 230, 220, 230, 220, 230, 220, 230, 230,
6096
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6097
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6098
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6099
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6100
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6101
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6102
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6103
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6104
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6105
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6106
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 230,
6107
     230, 230, 220, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 0,
6108
     0},
6109
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6110
     0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 0,   230, 230, 230,
6111
     230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 0,   230, 230, 230, 230,
6112
     230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6113
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6114
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   220,
6115
     220, 220, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6116
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6117
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6118
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6119
     0,   0,   230, 220, 220, 220, 230, 230, 230, 230, 0,   0,   0,   0,   0,
6120
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6121
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6122
     0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 230, 220, 220, 220,
6123
     220, 220, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6124
     230, 0,   220, 230, 230, 220, 230, 230, 220, 230, 230, 230, 220, 220, 220,
6125
     27,  28,  29,  230, 230, 230, 220, 230, 230, 220, 220, 230, 230, 230, 230,
6126
     230},
6127
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6128
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6129
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   7,   0,   0,   0, 0, 0,
6130
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0, 0, 230, 220, 230, 230, 0, 0, 0,
6131
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6132
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6133
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6134
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6135
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6136
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6137
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6138
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0},
6139
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6140
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6141
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6142
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6143
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6144
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6145
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6146
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
6147
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6148
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6149
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6150
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6151
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6152
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6153
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6154
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6155
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6156
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6157
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6158
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6159
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6160
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6161
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6162
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6163
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6164
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 84, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6165
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6166
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6167
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6168
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 7, 0, 0, 0,
6169
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6170
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6171
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0},
6172
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6173
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6174
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6175
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6176
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6177
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6178
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6179
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6180
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6181
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6182
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6183
    {0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6184
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6185
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6186
     0,   0,   103, 103, 9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6187
     107, 107, 107, 107, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6188
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6189
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6190
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6191
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6192
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6193
     0,   0,   0,   0,   118, 118, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6194
     0,   0,   122, 122, 122, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6195
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6196
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6197
     0,   0,   0,   0},
6198
    {0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6199
     0,   0, 0,   0,   0,   0,   0, 0, 0,   220, 220, 0,   0,   0, 0,
6200
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6201
     0,   0, 0,   0,   0,   0,   0, 0, 220, 0,   220, 0,   216, 0, 0,
6202
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6203
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6204
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6205
     0,   0, 0,   0,   0,   0,   0, 0, 129, 130, 0,   132, 0,   0, 0,
6206
     0,   0, 130, 130, 130, 130, 0, 0, 130, 0,   230, 230, 9,   0, 230,
6207
     230, 0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6208
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6209
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6210
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6211
     0,   0, 0,   220, 0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6212
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6213
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6214
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6215
     0},
6216
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6217
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6218
     0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6219
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6220
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6221
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0,
6222
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6223
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6224
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6225
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6226
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6227
    {0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6228
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6229
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6230
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6231
     0, 0, 0, 0, 0, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6232
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6233
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6234
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6235
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6236
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6237
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6238
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0},
6239
    {0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0,
6240
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6241
     0, 0, 0, 0, 9, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6242
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6243
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6244
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6245
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6246
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6247
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6248
     0, 0, 0, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6249
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6250
    {0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6251
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6252
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6253
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6254
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6255
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6256
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6257
     0, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6258
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6259
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6260
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6261
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6262
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6263
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 230, 220, 0, 0, 0, 0, 0, 0,
6264
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6265
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6266
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6267
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6268
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6269
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6270
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6271
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6272
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6273
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6274
     0,   0,   0,   0,   0,   0,   0,   0,   230, 220, 0,   0,   0,   0,   0,
6275
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6276
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6277
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6278
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6279
     0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6280
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230,
6281
     230, 230, 230, 230, 230, 0,   0,   220, 0,   0,   0,   0,   0,   0,   0,
6282
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6283
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6284
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230,
6285
     230, 220, 220, 220, 220, 220, 220, 230, 230, 220, 0,   220, 220, 230, 230,
6286
     220, 220, 230, 230, 230, 230, 230, 220, 230, 230, 230, 230, 0,   0,   0,
6287
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6288
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6289
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6290
     0},
6291
    {0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6292
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6293
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   7,   0,   0,   0,   0,
6294
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0,   0,   0,   0,   0,   0,
6295
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6296
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 230, 230, 230, 230, 230,
6297
     230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6298
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6299
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   9,
6300
     9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6301
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6302
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6303
     0,   0,   7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   9,   9,   0,   0,   0,
6304
     0,   0,   0, 0, 0, 0, 0, 0, 0},
6305
    {0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6306
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6307
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6308
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   7,   0,   0,   0,   0,
6309
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6310
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6311
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6312
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6313
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6314
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6315
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6316
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6317
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6318
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230,
6319
     230, 0, 1, 220, 220, 220, 220, 220, 230, 230, 220, 220, 220, 220, 230,
6320
     0,   1, 1, 1,   1,   1,   1,   1,   0,   0,   0,   0,   220, 0,   0,
6321
     0,   0, 0, 0,   230, 0,   0,   0,   230, 230, 0,   0,   0,   0,   0,
6322
     0},
6323
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6324
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6325
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6326
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6327
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6328
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6329
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6330
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6331
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6332
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6333
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6334
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6335
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 220,
6336
     230, 230, 230, 230, 230, 230, 230, 220, 230, 230, 234, 214, 220, 202, 230,
6337
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6338
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6339
     230, 230, 230, 230, 230, 230, 232, 228, 228, 220, 218, 230, 233, 220, 230,
6340
     220},
6341
    {0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6342
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6343
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6344
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6345
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6346
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6347
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6348
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6349
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6350
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6351
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6352
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6353
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6354
     230, 230, 1, 1, 230, 230, 230, 230, 1,   1,   1, 230, 230, 0,   0,   0,
6355
     0,   230, 0, 0, 0,   1,   1,   230, 220, 230, 1, 1,   220, 220, 220, 220,
6356
     230, 0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0},
6357
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6358
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6359
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6360
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6361
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6362
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6363
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6364
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6365
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6366
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6367
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230,
6368
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6369
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6370
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6371
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6372
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6373
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6374
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6375
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6376
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6377
     0,   0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,
6378
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6379
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6380
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6381
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6382
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6383
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6384
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6385
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6386
     230},
6387
    {0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6388
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6389
     0, 0, 218, 228, 232, 222, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6390
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6391
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6392
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6393
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6394
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0,
6395
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6396
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6397
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6398
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6399
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0},
6400
    {0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6401
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6402
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6403
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6404
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6405
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6406
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6407
     0,   0,   0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,
6408
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6409
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230,
6410
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6411
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6412
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6413
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6414
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6415
     230, 230, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0},
6416
    {0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6417
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6418
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   9,
6419
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6420
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6421
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6422
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6423
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6424
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6425
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6426
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6427
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6428
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6429
     0,   9,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6430
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6431
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6432
     230, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6433
     0},
6434
    {0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6435
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220,
6436
     220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6437
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
6438
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6439
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6440
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6441
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6442
     0,   0,   0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6443
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6444
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6445
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6446
    {0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6447
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6448
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6449
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6450
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6451
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6452
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6453
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6454
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6455
     0,   0,   0, 0,   0, 230, 0, 230, 230, 220, 0, 0, 230, 230, 0, 0, 0, 0, 0,
6456
     230, 230, 0, 230, 0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6457
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6458
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 9,
6459
     0,   0,   0, 0,   0, 0,   0, 0,   0},
6460
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6461
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6462
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6463
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6464
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6465
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6466
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6467
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6468
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6469
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0,
6470
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6471
    {0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6472
     0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6473
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6474
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6475
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6476
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6477
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6478
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6479
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6480
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6481
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0},
6482
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6483
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6484
     0,   0,   230, 230, 230, 230, 230, 230, 230, 220, 220, 220, 220, 220, 220,
6485
     220, 230, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6486
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6487
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6488
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6489
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6490
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6491
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6492
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6493
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6494
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6495
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6496
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6497
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6498
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6499
     0},
6500
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6501
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6502
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6503
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6504
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6505
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6506
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6507
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6508
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6509
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6510
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0},
6511
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6512
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6513
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6514
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6515
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6516
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6517
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6518
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6519
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6520
     0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6521
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0},
6522
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6523
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6524
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6525
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6526
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6527
     0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6528
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6529
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6530
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6531
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6532
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6533
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0},
6534
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 220, 0, 230, 0,   0, 0,   0,
6535
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6536
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   230, 1, 220, 0,
6537
     0, 0, 0, 9, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6538
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6539
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6540
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6541
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6542
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6543
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6544
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6545
     0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 0, 0, 0,   0, 0,   0,   0, 0,   0,
6546
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0},
6547
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6548
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0, 0, 0, 0,
6549
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6550
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6551
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6552
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6553
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6554
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6555
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6556
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6557
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6558
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6559
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6560
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6561
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6562
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6563
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6564
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6565
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6566
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 230, 230, 0, 0, 0,
6567
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6568
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6569
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6570
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220},
6571
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6572
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6573
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6574
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 220, 220,
6575
     230, 230, 230, 220, 230, 220, 220, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6576
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6577
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6578
     0,   0,   0,   0,   230, 220, 230, 220, 0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6579
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6580
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6581
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6582
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6583
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6584
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6585
     0,   0,   0,   0},
6586
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6587
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6588
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,
6589
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6590
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
6591
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6592
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6593
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0,
6594
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6595
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6596
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6597
    {230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6598
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6599
     0,   0,   0,   0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6600
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6601
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6602
     0,   0,   0,   0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6603
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6604
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6605
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6606
     0,   0,   0,   0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6607
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6608
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6609
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6610
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6611
     0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6612
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6613
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6614
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6615
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6616
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6617
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6618
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 0, 0, 0, 0, 0,
6619
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6620
    {0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6621
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6622
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6623
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   7,   7,   0, 0, 0,
6624
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   9, 0, 0,
6625
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6626
     0,   0,   0,   0,   0,   0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0,
6627
     230, 230, 230, 230, 230, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6628
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6629
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6630
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6631
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6632
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6633
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6634
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6635
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0},
6636
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6637
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6638
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 7,   0,
6639
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0,
6640
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6641
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6642
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6643
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6644
     0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6645
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6646
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6647
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6648
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6649
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6650
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6651
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6652
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6653
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6654
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
6655
     7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6656
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6657
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6658
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6659
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6660
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
6661
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6662
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6663
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6664
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6665
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0,
6666
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6667
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6668
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6669
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6670
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
6671
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6672
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6673
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6674
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6675
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6676
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6677
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6678
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6679
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6680
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6681
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6682
     0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6683
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6684
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6685
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6686
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6687
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6688
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6689
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6690
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6691
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6692
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6693
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 7, 0, 0, 0, 0,
6694
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6695
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6696
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6697
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6698
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6699
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6700
     0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6701
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6702
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6703
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6704
     0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
6705
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6706
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6707
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6708
     0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6709
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6710
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6711
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6712
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6713
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6714
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6715
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
6716
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6717
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6718
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6719
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6720
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6721
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6722
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6723
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6724
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6725
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6726
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0,
6727
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6728
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6729
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6730
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6731
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6732
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6733
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6734
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6735
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6736
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6737
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0,
6738
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6739
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6740
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6741
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6742
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6743
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6744
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6745
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6746
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6747
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6748
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6749
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6750
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6751
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6752
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6753
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6754
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6755
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6756
     1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6757
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6758
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6759
     0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0,
6760
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6761
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6762
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6763
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6764
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6765
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6766
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6767
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6768
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6769
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0},
6770
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6771
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6772
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6773
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6774
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6775
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6776
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6777
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6778
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6779
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6780
     6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6781
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6782
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6783
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6784
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6785
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6786
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6787
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6788
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6789
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6790
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6791
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6792
    {0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6793
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6794
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6795
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6796
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6797
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6798
     0,   0,   0,   0, 0, 216, 216, 1,   1,   1,   0,   0,   0,   226, 216, 216,
6799
     216, 216, 216, 0, 0, 0,   0,   0,   0,   0,   0,   220, 220, 220, 220, 220,
6800
     220, 220, 220, 0, 0, 230, 230, 230, 230, 230, 220, 220, 0,   0,   0,   0,
6801
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6802
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   230, 230, 230, 230, 0,   0,
6803
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6804
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6805
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6806
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6807
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0},
6808
    {0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6809
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6810
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6811
     230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6812
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6813
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6814
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6815
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6816
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6817
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6818
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6819
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6820
    {230, 230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 230, 230, 230, 230,
6821
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230, 230,
6822
     230, 230, 230, 230, 0,   230, 230, 0,   230, 230, 230, 230, 230, 0,   0,
6823
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6824
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6825
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6826
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6827
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6828
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6829
     0,   0,   0,   0,   0,   0,   0,   0,   230, 0,   0,   0,   0,   0,   0,
6830
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6831
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6832
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6833
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6834
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6835
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6836
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6837
     0},
6838
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6839
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6840
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6841
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6842
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6843
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6844
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6845
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   230, 0,
6846
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6847
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6848
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0,   0,
6849
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6850
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6851
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6852
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6853
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6854
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6855
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6856
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6857
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6858
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6859
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6860
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 232, 220, 230, 0, 0,
6861
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6862
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6863
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6864
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6865
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6866
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6867
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6868
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6869
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6870
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6871
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6872
     0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 220, 220, 220, 220, 0, 0, 0, 0, 0,
6873
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6874
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0},
6875
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6876
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6877
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6878
     0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 7, 0, 0, 0, 0, 0,
6879
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6880
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6881
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6882
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6883
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6884
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6885
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6886
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6887
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0}};
6888
6889
const uint8_t composition_index[4352] = {
6890
    0, 1, 2, 3, 4,  5,  6, 5, 5,  7,  5, 8,  9,  10, 5, 5, 11, 5,  5, 5, 5, 5,
6891
    5, 5, 5, 5, 5,  12, 5, 5, 13, 14, 5, 15, 16, 5,  5, 5, 5,  5,  5, 5, 5, 5,
6892
    5, 5, 5, 5, 17, 5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6893
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6894
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6895
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6896
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6897
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6898
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6899
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6900
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6901
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6902
    5, 5, 5, 5, 5,  5,  5, 5, 18, 19, 5, 20, 21, 22, 5, 5, 5,  23, 5, 5, 5, 5,
6903
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6904
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6905
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6906
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6907
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6908
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6909
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6910
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6911
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6912
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6913
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6914
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6915
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6916
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6917
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6918
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6919
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6920
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6921
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6922
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6923
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6924
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6925
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6926
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6927
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6928
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6929
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6930
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6931
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6932
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6933
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6934
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6935
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6936
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6937
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6938
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6939
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6940
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6941
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6942
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6943
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6944
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6945
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6946
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6947
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6948
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6949
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6950
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6951
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6952
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6953
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6954
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6955
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6956
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6957
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6958
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6959
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6960
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6961
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6962
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6963
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6964
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6965
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6966
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6967
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6968
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6969
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6970
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6971
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6972
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6973
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6974
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6975
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6976
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6977
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6978
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6979
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6980
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6981
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6982
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6983
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6984
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6985
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6986
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6987
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6988
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6989
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6990
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6991
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6992
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6993
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6994
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6995
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6996
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6997
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6998
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6999
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7000
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7001
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7002
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7003
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7004
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7005
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7006
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7007
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7008
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7009
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7010
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7011
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7012
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7013
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7014
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7015
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7016
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7017
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7018
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7019
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7020
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7021
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7022
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7023
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7024
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7025
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7026
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7027
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7028
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7029
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7030
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7031
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7032
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7033
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7034
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7035
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7036
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7037
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7038
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7039
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7040
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7041
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7042
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7043
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7044
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7045
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7046
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7047
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7048
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7049
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7050
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7051
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7052
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7053
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7054
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7055
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7056
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7057
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7058
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7059
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7060
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7061
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7062
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7063
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7064
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7065
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7066
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7067
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7068
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7069
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7070
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7071
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7072
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7073
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7074
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7075
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7076
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7077
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7078
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7079
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7080
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7081
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7082
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7083
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7084
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7085
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7086
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7087
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5};
7088
const uint16_t composition_block[67][257] = {
7089
    {1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7090
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7091
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7092
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7093
     1,   3,   5,   7,   7,   7,   39,  45,  55,  67,  101, 103, 117, 131, 161,
7094
     163, 173, 185, 191, 209, 241, 245, 245, 261, 275, 289, 327, 331, 343, 347,
7095
     365, 377, 377, 377, 377, 377, 377, 377, 409, 415, 425, 437, 471, 473, 487,
7096
     503, 531, 535, 545, 557, 563, 581, 613, 617, 617, 633, 647, 663, 701, 705,
7097
     719, 723, 743, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7098
     755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7099
     755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7100
     755, 755, 755, 755, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7101
     761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7102
     769, 769, 771, 773, 777, 779, 779, 779, 787, 787, 787, 787, 787, 789, 789,
7103
     789, 789, 789, 797, 803, 805, 805, 807, 807, 807, 807, 815, 815, 815, 815,
7104
     815, 815, 823, 823, 825, 827, 831, 833, 833, 833, 841, 841, 841, 841, 841,
7105
     843, 843, 843, 843, 843, 851, 857, 859, 859, 861, 861, 861, 861, 869, 869,
7106
     869, 869},
7107
    {869, 869, 869, 877, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885,
7108
     885, 885, 885, 885, 889, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7109
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7110
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7111
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7112
     893, 893, 897, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901,
7113
     901, 903, 905, 905, 905, 905, 905, 907, 909, 909, 909, 909, 909, 909, 909,
7114
     911, 913, 915, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917,
7115
     917, 917, 917, 917, 917, 917, 917, 917, 919, 919, 919, 919, 919, 919, 919,
7116
     919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919,
7117
     919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 929, 939, 939, 939,
7118
     939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 949, 959, 959, 959,
7119
     959, 959, 959, 959, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7120
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7121
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7122
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 963, 965, 965, 965, 965,
7123
     965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7124
     965, 965},
7125
    {965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7126
     965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7127
     965, 965, 965, 965, 965, 965, 965, 965, 965, 967, 969, 971, 973, 973, 973,
7128
     973, 973, 975, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7129
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7130
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7131
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7132
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7133
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7134
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 979, 979, 979,
7135
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7136
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7137
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7138
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7139
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7140
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7141
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7142
     979, 979},
7143
    {979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7144
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7145
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7146
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7147
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7148
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7149
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7150
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7151
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7152
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7153
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7154
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7155
     979,  979,  993,  993,  993,  993,  1001, 1001, 1011, 1011, 1025, 1025,
7156
     1025, 1025, 1025, 1025, 1033, 1033, 1035, 1035, 1035, 1035, 1047, 1047,
7157
     1047, 1047, 1057, 1057, 1057, 1059, 1059, 1061, 1061, 1061, 1077, 1077,
7158
     1077, 1077, 1085, 1085, 1097, 1097, 1113, 1113, 1113, 1113, 1113, 1113,
7159
     1121, 1121, 1125, 1125, 1125, 1125, 1141, 1141, 1141, 1141, 1153, 1159,
7160
     1165, 1165, 1165, 1167, 1167, 1167, 1167, 1171, 1171, 1171, 1171, 1171,
7161
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7162
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7163
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7164
     1171, 1171, 1171, 1171, 1171},
7165
    {1171, 1171, 1171, 1171, 1171, 1171, 1171, 1173, 1173, 1173, 1173, 1173,
7166
     1173, 1173, 1173, 1173, 1173, 1177, 1177, 1177, 1179, 1179, 1185, 1189,
7167
     1191, 1199, 1199, 1201, 1201, 1201, 1201, 1203, 1203, 1203, 1203, 1203,
7168
     1211, 1211, 1211, 1211, 1213, 1213, 1213, 1213, 1215, 1215, 1217, 1217,
7169
     1217, 1221, 1221, 1221, 1223, 1223, 1229, 1233, 1235, 1243, 1243, 1245,
7170
     1245, 1245, 1245, 1247, 1247, 1247, 1247, 1247, 1255, 1255, 1255, 1255,
7171
     1257, 1257, 1257, 1257, 1259, 1259, 1261, 1261, 1261, 1261, 1261, 1261,
7172
     1261, 1261, 1261, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7173
     1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7174
     1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1265, 1267, 1267,
7175
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7176
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7177
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7178
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7179
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7180
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7181
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7182
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7183
     1267, 1269, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271,
7184
     1271, 1271, 1271, 1271, 1271, 1273, 1275, 1275, 1275, 1275, 1275, 1275,
7185
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7186
     1275, 1275, 1275, 1275, 1275},
7187
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7188
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7189
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7190
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7191
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7192
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7193
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7194
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7195
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7196
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7197
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
7198
    {1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7199
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7200
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7201
     1275, 1275, 1275, 1275, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7202
     1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7203
     1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7204
     1281, 1283, 1283, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7205
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7206
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7207
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7208
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7209
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7210
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7211
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7212
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7213
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7214
     1285, 1285, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
7215
     1287, 1287, 1287, 1287, 1287, 1287, 1287, 1289, 1289, 1289, 1291, 1291,
7216
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7217
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7218
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7219
     1291, 1291, 1291, 1291, 1291},
7220
    {1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7221
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7222
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7223
     1291, 1291, 1291, 1291, 1291, 1293, 1293, 1293, 1293, 1293, 1293, 1293,
7224
     1293, 1295, 1295, 1295, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7225
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7226
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7227
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7228
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7229
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7230
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7231
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7232
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7233
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7234
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7235
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7236
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1301, 1301, 1301, 1301,
7237
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7238
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7239
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7240
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7241
     1301, 1301, 1301, 1301, 1301},
7242
    {1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7243
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7244
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7245
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7246
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7247
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7248
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7249
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7250
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7251
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7252
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7253
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7254
     1307, 1307, 1307, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7255
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7256
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7257
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7258
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1313, 1315, 1315, 1315, 1315,
7259
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7260
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7261
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7262
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7263
     1315, 1315, 1315, 1315, 1315},
7264
    {1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7265
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7266
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7267
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7268
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7269
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1317,
7270
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7271
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7272
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7273
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7274
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7275
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7276
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7277
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7278
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7279
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7280
     1319, 1319, 1319, 1319, 1319, 1319, 1319, 1325, 1325, 1325, 1325, 1327,
7281
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7282
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7283
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7284
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7285
     1327, 1327, 1327, 1327, 1327},
7286
    {1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7287
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7288
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7289
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7290
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7291
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1331,
7292
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7293
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7294
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7295
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7296
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7297
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7298
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7299
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7300
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7301
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7302
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7303
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7304
     1333, 1333, 1339, 1339, 1339, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7305
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7306
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7307
     1341, 1341, 1341, 1341, 1341},
7308
    {1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7309
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7310
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7311
     1341, 1341, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7312
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7313
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7314
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7315
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7316
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7317
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7318
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7319
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7320
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7321
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7322
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7323
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7324
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7325
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7326
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7327
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7328
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7329
     1343, 1343, 1343, 1343, 1343},
7330
    {1343, 1343, 1343, 1343, 1343, 1343, 1345, 1345, 1347, 1347, 1349, 1349,
7331
     1351, 1351, 1353, 1353, 1353, 1353, 1355, 1355, 1355, 1355, 1355, 1355,
7332
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7333
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7334
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1357,
7335
     1357, 1359, 1359, 1361, 1363, 1363, 1363, 1365, 1365, 1365, 1365, 1365,
7336
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7337
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7338
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7339
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7340
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7341
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7342
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7343
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7344
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7345
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7346
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7347
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7348
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7349
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7350
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7351
     1365, 1365, 1365, 1365, 1365},
7352
    {1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7353
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7354
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7355
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7356
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1367, 1369, 1369, 1369, 1369,
7357
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7358
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7359
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1371, 1373, 1373, 1373, 1373,
7360
     1373, 1373, 1373, 1375, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7361
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7362
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7363
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7364
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7365
     1377, 1377, 1377, 1377, 1377, 1381, 1385, 1385, 1385, 1385, 1385, 1385,
7366
     1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385,
7367
     1385, 1385, 1385, 1385, 1385, 1387, 1389, 1389, 1389, 1389, 1389, 1389,
7368
     1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389,
7369
     1389, 1391, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7370
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7371
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7372
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7373
     1393, 1393, 1393, 1393, 1393},
7374
    {1393, 1401, 1409, 1411, 1413, 1415, 1417, 1419, 1421, 1429, 1437, 1439,
7375
     1441, 1443, 1445, 1447, 1449, 1453, 1457, 1457, 1457, 1457, 1457, 1457,
7376
     1457, 1461, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1473, 1481, 1483,
7377
     1485, 1487, 1489, 1491, 1493, 1501, 1509, 1511, 1513, 1515, 1517, 1519,
7378
     1521, 1527, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1539, 1545, 1545,
7379
     1545, 1545, 1545, 1545, 1545, 1549, 1553, 1553, 1553, 1553, 1553, 1553,
7380
     1553, 1557, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1567, 1573, 1573,
7381
     1573, 1573, 1573, 1573, 1573, 1573, 1579, 1579, 1579, 1579, 1579, 1579,
7382
     1579, 1587, 1595, 1597, 1599, 1601, 1603, 1605, 1607, 1615, 1623, 1625,
7383
     1627, 1629, 1631, 1633, 1635, 1637, 1637, 1637, 1637, 1639, 1639, 1639,
7384
     1639, 1639, 1639, 1639, 1639, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7385
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7386
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7387
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7388
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7389
     1641, 1641, 1641, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643,
7390
     1649, 1649, 1649, 1649, 1649, 1649, 1649, 1651, 1651, 1651, 1651, 1651,
7391
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7392
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7393
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7394
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1653, 1653, 1653, 1653, 1653,
7395
     1653, 1653, 1653, 1659, 1659},
7396
    {1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7397
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7398
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7399
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7400
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7401
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7402
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7403
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7404
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7405
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7406
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7407
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7408
     1659, 1661, 1661, 1663, 1663, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7409
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7410
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7411
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7412
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7413
     1665, 1665, 1665, 1665, 1665, 1667, 1667, 1669, 1669, 1671, 1671, 1671,
7414
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7415
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7416
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7417
     1671, 1671, 1671, 1671, 1671},
7418
    {1671, 1671, 1671, 1671, 1673, 1673, 1673, 1673, 1673, 1675, 1675, 1675,
7419
     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7420
     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7421
     1679, 1679, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7422
     1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7423
     1681, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1685, 1685, 1687, 1687,
7424
     1687, 1689, 1689, 1689, 1689, 1689, 1691, 1691, 1691, 1691, 1691, 1691,
7425
     1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691,
7426
     1691, 1691, 1693, 1693, 1693, 1695, 1697, 1697, 1697, 1697, 1697, 1697,
7427
     1697, 1697, 1697, 1697, 1697, 1697, 1697, 1699, 1701, 1701, 1701, 1703,
7428
     1705, 1705, 1705, 1707, 1709, 1711, 1713, 1713, 1713, 1713, 1713, 1715,
7429
     1717, 1717, 1717, 1719, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
7430
     1721, 1721, 1723, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725,
7431
     1725, 1725, 1725, 1725, 1725, 1725, 1725, 1727, 1727, 1727, 1727, 1727,
7432
     1727, 1729, 1731, 1731, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1735,
7433
     1737, 1739, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7434
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7435
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7436
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7437
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7438
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7439
     1741, 1741, 1741, 1741, 1741},
7440
    {1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7441
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7442
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7443
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7444
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7445
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1743,
7446
     1743, 1743, 1743, 1743, 1745, 1745, 1747, 1747, 1749, 1749, 1751, 1751,
7447
     1753, 1753, 1755, 1755, 1757, 1757, 1759, 1759, 1761, 1761, 1763, 1763,
7448
     1765, 1765, 1767, 1767, 1767, 1769, 1769, 1771, 1771, 1773, 1773, 1773,
7449
     1773, 1773, 1773, 1773, 1777, 1777, 1777, 1781, 1781, 1781, 1785, 1785,
7450
     1785, 1789, 1789, 1789, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7451
     1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7452
     1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7453
     1793, 1793, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1797,
7454
     1797, 1797, 1797, 1797, 1799, 1799, 1801, 1801, 1803, 1803, 1805, 1805,
7455
     1807, 1807, 1809, 1809, 1811, 1811, 1813, 1813, 1815, 1815, 1817, 1817,
7456
     1819, 1819, 1821, 1821, 1821, 1823, 1823, 1825, 1825, 1827, 1827, 1827,
7457
     1827, 1827, 1827, 1827, 1831, 1831, 1831, 1835, 1835, 1835, 1839, 1839,
7458
     1839, 1843, 1843, 1843, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7459
     1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7460
     1849, 1851, 1853, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855,
7461
     1855, 1855, 1857, 1857, 1857},
7462
    {1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7463
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7464
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7465
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7466
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7467
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7468
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7469
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7470
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7471
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7472
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7473
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7474
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1859, 1859,
7475
     1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1863, 1863,
7476
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7477
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7478
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7479
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7480
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7481
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7482
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7483
     1863, 1863, 1863, 1863, 1863},
7484
    {1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7485
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7486
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7487
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7488
     1863, 1863, 1865, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7489
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7490
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7491
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7492
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7493
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7494
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7495
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7496
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7497
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7498
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7499
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7500
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7501
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7502
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7503
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7504
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7505
     1867, 1867, 1867, 1867, 1867},
7506
    {1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7507
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7508
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7509
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7510
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7511
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7512
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7513
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7514
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7515
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7516
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7517
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7518
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7519
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7520
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7521
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7522
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7523
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7524
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7525
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7526
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7527
     1871, 1871, 1871, 1871, 1871},
7528
    {1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7529
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7530
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7531
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7532
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7533
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7534
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7535
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7536
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7537
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7538
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7539
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7540
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7541
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7542
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7543
     1871, 1871, 1871, 1871, 1871, 1871, 1877, 1877, 1877, 1877, 1877, 1877,
7544
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7545
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7546
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7547
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7548
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7549
     1877, 1877, 1877, 1877, 1877},
7550
    {1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7551
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7552
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7553
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7554
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7555
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7556
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7557
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7558
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7559
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7560
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7561
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7562
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7563
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7564
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7565
     1877, 1877, 1877, 1877, 1877, 1879, 1881, 1881, 1881, 1881, 1881, 1881,
7566
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7567
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7568
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7569
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7570
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7571
     1881, 1881, 1881, 1881, 1881},
7572
    {1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7573
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7574
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7575
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7576
     1881, 1881, 1881, 1881, 1881, 1881, 1883, 1883, 1883, 1883, 1883, 1883,
7577
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7578
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7579
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7580
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7581
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7582
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7583
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7584
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7585
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7586
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7587
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7588
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7589
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7590
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7591
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7592
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7593
     1883, 1883, 1883, 1883, 1883}};
7594
const char32_t composition_data[1883] = {
7595
    0,     824,   8814,  824,   8800,  824,   8815,  768,   192,   769,   193,
7596
    770,   194,   771,   195,   772,   256,   774,   258,   775,   550,   776,
7597
    196,   777,   7842,  778,   197,   780,   461,   783,   512,   785,   514,
7598
    803,   7840,  805,   7680,  808,   260,   775,   7682,  803,   7684,  817,
7599
    7686,  769,   262,   770,   264,   775,   266,   780,   268,   807,   199,
7600
    775,   7690,  780,   270,   803,   7692,  807,   7696,  813,   7698,  817,
7601
    7694,  768,   200,   769,   201,   770,   202,   771,   7868,  772,   274,
7602
    774,   276,   775,   278,   776,   203,   777,   7866,  780,   282,   783,
7603
    516,   785,   518,   803,   7864,  807,   552,   808,   280,   813,   7704,
7604
    816,   7706,  775,   7710,  769,   500,   770,   284,   772,   7712,  774,
7605
    286,   775,   288,   780,   486,   807,   290,   770,   292,   775,   7714,
7606
    776,   7718,  780,   542,   803,   7716,  807,   7720,  814,   7722,  768,
7607
    204,   769,   205,   770,   206,   771,   296,   772,   298,   774,   300,
7608
    775,   304,   776,   207,   777,   7880,  780,   463,   783,   520,   785,
7609
    522,   803,   7882,  808,   302,   816,   7724,  770,   308,   769,   7728,
7610
    780,   488,   803,   7730,  807,   310,   817,   7732,  769,   313,   780,
7611
    317,   803,   7734,  807,   315,   813,   7740,  817,   7738,  769,   7742,
7612
    775,   7744,  803,   7746,  768,   504,   769,   323,   771,   209,   775,
7613
    7748,  780,   327,   803,   7750,  807,   325,   813,   7754,  817,   7752,
7614
    768,   210,   769,   211,   770,   212,   771,   213,   772,   332,   774,
7615
    334,   775,   558,   776,   214,   777,   7886,  779,   336,   780,   465,
7616
    783,   524,   785,   526,   795,   416,   803,   7884,  808,   490,   769,
7617
    7764,  775,   7766,  769,   340,   775,   7768,  780,   344,   783,   528,
7618
    785,   530,   803,   7770,  807,   342,   817,   7774,  769,   346,   770,
7619
    348,   775,   7776,  780,   352,   803,   7778,  806,   536,   807,   350,
7620
    775,   7786,  780,   356,   803,   7788,  806,   538,   807,   354,   813,
7621
    7792,  817,   7790,  768,   217,   769,   218,   770,   219,   771,   360,
7622
    772,   362,   774,   364,   776,   220,   777,   7910,  778,   366,   779,
7623
    368,   780,   467,   783,   532,   785,   534,   795,   431,   803,   7908,
7624
    804,   7794,  808,   370,   813,   7798,  816,   7796,  771,   7804,  803,
7625
    7806,  768,   7808,  769,   7810,  770,   372,   775,   7814,  776,   7812,
7626
    803,   7816,  775,   7818,  776,   7820,  768,   7922,  769,   221,   770,
7627
    374,   771,   7928,  772,   562,   775,   7822,  776,   376,   777,   7926,
7628
    803,   7924,  769,   377,   770,   7824,  775,   379,   780,   381,   803,
7629
    7826,  817,   7828,  768,   224,   769,   225,   770,   226,   771,   227,
7630
    772,   257,   774,   259,   775,   551,   776,   228,   777,   7843,  778,
7631
    229,   780,   462,   783,   513,   785,   515,   803,   7841,  805,   7681,
7632
    808,   261,   775,   7683,  803,   7685,  817,   7687,  769,   263,   770,
7633
    265,   775,   267,   780,   269,   807,   231,   775,   7691,  780,   271,
7634
    803,   7693,  807,   7697,  813,   7699,  817,   7695,  768,   232,   769,
7635
    233,   770,   234,   771,   7869,  772,   275,   774,   277,   775,   279,
7636
    776,   235,   777,   7867,  780,   283,   783,   517,   785,   519,   803,
7637
    7865,  807,   553,   808,   281,   813,   7705,  816,   7707,  775,   7711,
7638
    769,   501,   770,   285,   772,   7713,  774,   287,   775,   289,   780,
7639
    487,   807,   291,   770,   293,   775,   7715,  776,   7719,  780,   543,
7640
    803,   7717,  807,   7721,  814,   7723,  817,   7830,  768,   236,   769,
7641
    237,   770,   238,   771,   297,   772,   299,   774,   301,   776,   239,
7642
    777,   7881,  780,   464,   783,   521,   785,   523,   803,   7883,  808,
7643
    303,   816,   7725,  770,   309,   780,   496,   769,   7729,  780,   489,
7644
    803,   7731,  807,   311,   817,   7733,  769,   314,   780,   318,   803,
7645
    7735,  807,   316,   813,   7741,  817,   7739,  769,   7743,  775,   7745,
7646
    803,   7747,  768,   505,   769,   324,   771,   241,   775,   7749,  780,
7647
    328,   803,   7751,  807,   326,   813,   7755,  817,   7753,  768,   242,
7648
    769,   243,   770,   244,   771,   245,   772,   333,   774,   335,   775,
7649
    559,   776,   246,   777,   7887,  779,   337,   780,   466,   783,   525,
7650
    785,   527,   795,   417,   803,   7885,  808,   491,   769,   7765,  775,
7651
    7767,  769,   341,   775,   7769,  780,   345,   783,   529,   785,   531,
7652
    803,   7771,  807,   343,   817,   7775,  769,   347,   770,   349,   775,
7653
    7777,  780,   353,   803,   7779,  806,   537,   807,   351,   775,   7787,
7654
    776,   7831,  780,   357,   803,   7789,  806,   539,   807,   355,   813,
7655
    7793,  817,   7791,  768,   249,   769,   250,   770,   251,   771,   361,
7656
    772,   363,   774,   365,   776,   252,   777,   7911,  778,   367,   779,
7657
    369,   780,   468,   783,   533,   785,   535,   795,   432,   803,   7909,
7658
    804,   7795,  808,   371,   813,   7799,  816,   7797,  771,   7805,  803,
7659
    7807,  768,   7809,  769,   7811,  770,   373,   775,   7815,  776,   7813,
7660
    778,   7832,  803,   7817,  775,   7819,  776,   7821,  768,   7923,  769,
7661
    253,   770,   375,   771,   7929,  772,   563,   775,   7823,  776,   255,
7662
    777,   7927,  778,   7833,  803,   7925,  769,   378,   770,   7825,  775,
7663
    380,   780,   382,   803,   7827,  817,   7829,  768,   8173,  769,   901,
7664
    834,   8129,  768,   7846,  769,   7844,  771,   7850,  777,   7848,  772,
7665
    478,   769,   506,   769,   508,   772,   482,   769,   7688,  768,   7872,
7666
    769,   7870,  771,   7876,  777,   7874,  769,   7726,  768,   7890,  769,
7667
    7888,  771,   7894,  777,   7892,  769,   7756,  772,   556,   776,   7758,
7668
    772,   554,   769,   510,   768,   475,   769,   471,   772,   469,   780,
7669
    473,   768,   7847,  769,   7845,  771,   7851,  777,   7849,  772,   479,
7670
    769,   507,   769,   509,   772,   483,   769,   7689,  768,   7873,  769,
7671
    7871,  771,   7877,  777,   7875,  769,   7727,  768,   7891,  769,   7889,
7672
    771,   7895,  777,   7893,  769,   7757,  772,   557,   776,   7759,  772,
7673
    555,   769,   511,   768,   476,   769,   472,   772,   470,   780,   474,
7674
    768,   7856,  769,   7854,  771,   7860,  777,   7858,  768,   7857,  769,
7675
    7855,  771,   7861,  777,   7859,  768,   7700,  769,   7702,  768,   7701,
7676
    769,   7703,  768,   7760,  769,   7762,  768,   7761,  769,   7763,  775,
7677
    7780,  775,   7781,  775,   7782,  775,   7783,  769,   7800,  769,   7801,
7678
    776,   7802,  776,   7803,  775,   7835,  768,   7900,  769,   7898,  771,
7679
    7904,  777,   7902,  803,   7906,  768,   7901,  769,   7899,  771,   7905,
7680
    777,   7903,  803,   7907,  768,   7914,  769,   7912,  771,   7918,  777,
7681
    7916,  803,   7920,  768,   7915,  769,   7913,  771,   7919,  777,   7917,
7682
    803,   7921,  780,   494,   772,   492,   772,   493,   772,   480,   772,
7683
    481,   774,   7708,  774,   7709,  772,   560,   772,   561,   780,   495,
7684
    768,   8122,  769,   902,   772,   8121,  774,   8120,  787,   7944,  788,
7685
    7945,  837,   8124,  768,   8136,  769,   904,   787,   7960,  788,   7961,
7686
    768,   8138,  769,   905,   787,   7976,  788,   7977,  837,   8140,  768,
7687
    8154,  769,   906,   772,   8153,  774,   8152,  776,   938,   787,   7992,
7688
    788,   7993,  768,   8184,  769,   908,   787,   8008,  788,   8009,  788,
7689
    8172,  768,   8170,  769,   910,   772,   8169,  774,   8168,  776,   939,
7690
    788,   8025,  768,   8186,  769,   911,   787,   8040,  788,   8041,  837,
7691
    8188,  837,   8116,  837,   8132,  768,   8048,  769,   940,   772,   8113,
7692
    774,   8112,  787,   7936,  788,   7937,  834,   8118,  837,   8115,  768,
7693
    8050,  769,   941,   787,   7952,  788,   7953,  768,   8052,  769,   942,
7694
    787,   7968,  788,   7969,  834,   8134,  837,   8131,  768,   8054,  769,
7695
    943,   772,   8145,  774,   8144,  776,   970,   787,   7984,  788,   7985,
7696
    834,   8150,  768,   8056,  769,   972,   787,   8000,  788,   8001,  787,
7697
    8164,  788,   8165,  768,   8058,  769,   973,   772,   8161,  774,   8160,
7698
    776,   971,   787,   8016,  788,   8017,  834,   8166,  768,   8060,  769,
7699
    974,   787,   8032,  788,   8033,  834,   8182,  837,   8179,  768,   8146,
7700
    769,   912,   834,   8151,  768,   8162,  769,   944,   834,   8167,  837,
7701
    8180,  769,   979,   776,   980,   776,   1031,  774,   1232,  776,   1234,
7702
    769,   1027,  768,   1024,  774,   1238,  776,   1025,  774,   1217,  776,
7703
    1244,  776,   1246,  768,   1037,  772,   1250,  774,   1049,  776,   1252,
7704
    769,   1036,  776,   1254,  772,   1262,  774,   1038,  776,   1264,  779,
7705
    1266,  776,   1268,  776,   1272,  776,   1260,  774,   1233,  776,   1235,
7706
    769,   1107,  768,   1104,  774,   1239,  776,   1105,  774,   1218,  776,
7707
    1245,  776,   1247,  768,   1117,  772,   1251,  774,   1081,  776,   1253,
7708
    769,   1116,  776,   1255,  772,   1263,  774,   1118,  776,   1265,  779,
7709
    1267,  776,   1269,  776,   1273,  776,   1261,  776,   1111,  783,   1142,
7710
    783,   1143,  776,   1242,  776,   1243,  776,   1258,  776,   1259,  1619,
7711
    1570,  1620,  1571,  1621,  1573,  1620,  1572,  1620,  1574,  1620,  1730,
7712
    1620,  1747,  1620,  1728,  2364,  2345,  2364,  2353,  2364,  2356,  2494,
7713
    2507,  2519,  2508,  2878,  2891,  2902,  2888,  2903,  2892,  3031,  2964,
7714
    3006,  3018,  3031,  3020,  3006,  3019,  3158,  3144,  3285,  3264,  3266,
7715
    3274,  3285,  3271,  3286,  3272,  3285,  3275,  3390,  3402,  3415,  3404,
7716
    3390,  3403,  3530,  3546,  3535,  3548,  3551,  3550,  3530,  3549,  4142,
7717
    4134,  6965,  6918,  6965,  6920,  6965,  6922,  6965,  6924,  6965,  6926,
7718
    6965,  6930,  6965,  6971,  6965,  6973,  6965,  6976,  6965,  6977,  6965,
7719
    6979,  772,   7736,  772,   7737,  772,   7772,  772,   7773,  775,   7784,
7720
    775,   7785,  770,   7852,  774,   7862,  770,   7853,  774,   7863,  770,
7721
    7878,  770,   7879,  770,   7896,  770,   7897,  768,   7938,  769,   7940,
7722
    834,   7942,  837,   8064,  768,   7939,  769,   7941,  834,   7943,  837,
7723
    8065,  837,   8066,  837,   8067,  837,   8068,  837,   8069,  837,   8070,
7724
    837,   8071,  768,   7946,  769,   7948,  834,   7950,  837,   8072,  768,
7725
    7947,  769,   7949,  834,   7951,  837,   8073,  837,   8074,  837,   8075,
7726
    837,   8076,  837,   8077,  837,   8078,  837,   8079,  768,   7954,  769,
7727
    7956,  768,   7955,  769,   7957,  768,   7962,  769,   7964,  768,   7963,
7728
    769,   7965,  768,   7970,  769,   7972,  834,   7974,  837,   8080,  768,
7729
    7971,  769,   7973,  834,   7975,  837,   8081,  837,   8082,  837,   8083,
7730
    837,   8084,  837,   8085,  837,   8086,  837,   8087,  768,   7978,  769,
7731
    7980,  834,   7982,  837,   8088,  768,   7979,  769,   7981,  834,   7983,
7732
    837,   8089,  837,   8090,  837,   8091,  837,   8092,  837,   8093,  837,
7733
    8094,  837,   8095,  768,   7986,  769,   7988,  834,   7990,  768,   7987,
7734
    769,   7989,  834,   7991,  768,   7994,  769,   7996,  834,   7998,  768,
7735
    7995,  769,   7997,  834,   7999,  768,   8002,  769,   8004,  768,   8003,
7736
    769,   8005,  768,   8010,  769,   8012,  768,   8011,  769,   8013,  768,
7737
    8018,  769,   8020,  834,   8022,  768,   8019,  769,   8021,  834,   8023,
7738
    768,   8027,  769,   8029,  834,   8031,  768,   8034,  769,   8036,  834,
7739
    8038,  837,   8096,  768,   8035,  769,   8037,  834,   8039,  837,   8097,
7740
    837,   8098,  837,   8099,  837,   8100,  837,   8101,  837,   8102,  837,
7741
    8103,  768,   8042,  769,   8044,  834,   8046,  837,   8104,  768,   8043,
7742
    769,   8045,  834,   8047,  837,   8105,  837,   8106,  837,   8107,  837,
7743
    8108,  837,   8109,  837,   8110,  837,   8111,  837,   8114,  837,   8130,
7744
    837,   8178,  837,   8119,  768,   8141,  769,   8142,  834,   8143,  837,
7745
    8135,  837,   8183,  768,   8157,  769,   8158,  834,   8159,  824,   8602,
7746
    824,   8603,  824,   8622,  824,   8653,  824,   8655,  824,   8654,  824,
7747
    8708,  824,   8713,  824,   8716,  824,   8740,  824,   8742,  824,   8769,
7748
    824,   8772,  824,   8775,  824,   8777,  824,   8813,  824,   8802,  824,
7749
    8816,  824,   8817,  824,   8820,  824,   8821,  824,   8824,  824,   8825,
7750
    824,   8832,  824,   8833,  824,   8928,  824,   8929,  824,   8836,  824,
7751
    8837,  824,   8840,  824,   8841,  824,   8930,  824,   8931,  824,   8876,
7752
    824,   8877,  824,   8878,  824,   8879,  824,   8938,  824,   8939,  824,
7753
    8940,  824,   8941,  12441, 12436, 12441, 12364, 12441, 12366, 12441, 12368,
7754
    12441, 12370, 12441, 12372, 12441, 12374, 12441, 12376, 12441, 12378, 12441,
7755
    12380, 12441, 12382, 12441, 12384, 12441, 12386, 12441, 12389, 12441, 12391,
7756
    12441, 12393, 12441, 12400, 12442, 12401, 12441, 12403, 12442, 12404, 12441,
7757
    12406, 12442, 12407, 12441, 12409, 12442, 12410, 12441, 12412, 12442, 12413,
7758
    12441, 12446, 12441, 12532, 12441, 12460, 12441, 12462, 12441, 12464, 12441,
7759
    12466, 12441, 12468, 12441, 12470, 12441, 12472, 12441, 12474, 12441, 12476,
7760
    12441, 12478, 12441, 12480, 12441, 12482, 12441, 12485, 12441, 12487, 12441,
7761
    12489, 12441, 12496, 12442, 12497, 12441, 12499, 12442, 12500, 12441, 12502,
7762
    12442, 12503, 12441, 12505, 12442, 12506, 12441, 12508, 12442, 12509, 12441,
7763
    12535, 12441, 12536, 12441, 12537, 12441, 12538, 12441, 12542, 69818, 69786,
7764
    69818, 69788, 69818, 69803, 69927, 69934, 69927, 69935, 70462, 70475, 70487,
7765
    70476, 70832, 70844, 70842, 70843, 70845, 70846, 71087, 71098, 71087, 71099,
7766
    71984, 71992};
7767
7768
}  // namespace ada::idna
7769
#endif  // ADA_IDNA_NORMALIZATION_TABLES_H
7770
/* end file src/normalization_tables.cpp */
7771
7772
namespace ada::idna {
7773
7774
// See
7775
// https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/impl_norm.h#L467
7776
constexpr char32_t hangul_sbase = 0xAC00;
7777
constexpr char32_t hangul_tbase = 0x11A7;
7778
constexpr char32_t hangul_vbase = 0x1161;
7779
constexpr char32_t hangul_lbase = 0x1100;
7780
constexpr char32_t hangul_lcount = 19;
7781
constexpr char32_t hangul_vcount = 21;
7782
constexpr char32_t hangul_tcount = 28;
7783
constexpr char32_t hangul_ncount = hangul_vcount * hangul_tcount;
7784
constexpr char32_t hangul_scount =
7785
    hangul_lcount * hangul_vcount * hangul_tcount;
7786
7787
std::pair<bool, size_t> compute_decomposition_length(
7788
5.87k
    const std::u32string_view input) noexcept {
7789
5.87k
  bool decomposition_needed{false};
7790
5.87k
  size_t additional_elements{0};
7791
161k
  for (char32_t current_character : input) {
7792
161k
    size_t decomposition_length{0};
7793
7794
161k
    if (current_character >= hangul_sbase &&
7795
5.81k
        current_character < hangul_sbase + hangul_scount) {
7796
3.89k
      decomposition_length = 2;
7797
3.89k
      if ((current_character - hangul_sbase) % hangul_tcount) {
7798
2.84k
        decomposition_length = 3;
7799
2.84k
      }
7800
157k
    } else if (current_character < 0x110000) {
7801
157k
      const uint8_t di = decomposition_index[current_character >> 8];
7802
157k
      const uint16_t* const decomposition =
7803
157k
          decomposition_block[di] + (current_character % 256);
7804
157k
      decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
7805
157k
      if ((decomposition_length > 0) && (decomposition[0] & 1)) {
7806
0
        decomposition_length = 0;
7807
0
      }
7808
157k
    }
7809
161k
    if (decomposition_length != 0) {
7810
8.58k
      decomposition_needed = true;
7811
8.58k
      additional_elements += decomposition_length - 1;
7812
8.58k
    }
7813
161k
  }
7814
5.87k
  return {decomposition_needed, additional_elements};
7815
5.87k
}
7816
7817
2.18k
void decompose(std::u32string& input, size_t additional_elements) {
7818
2.18k
  input.resize(input.size() + additional_elements);
7819
2.18k
  for (size_t descending_idx = input.size(),
7820
2.18k
              input_count = descending_idx - additional_elements;
7821
48.3k
       input_count--;) {
7822
46.1k
    if (input[input_count] >= hangul_sbase &&
7823
4.95k
        input[input_count] < hangul_sbase + hangul_scount) {
7824
      // Hangul decomposition.
7825
3.89k
      char32_t s_index = input[input_count] - hangul_sbase;
7826
3.89k
      if (s_index % hangul_tcount != 0) {
7827
2.84k
        input[--descending_idx] = hangul_tbase + s_index % hangul_tcount;
7828
2.84k
      }
7829
3.89k
      input[--descending_idx] =
7830
3.89k
          hangul_vbase + (s_index % hangul_ncount) / hangul_tcount;
7831
3.89k
      input[--descending_idx] = hangul_lbase + s_index / hangul_ncount;
7832
42.2k
    } else if (input[input_count] < 0x110000) {
7833
      // Check decomposition_data.
7834
42.2k
      const uint16_t* decomposition =
7835
42.2k
          decomposition_block[decomposition_index[input[input_count] >> 8]] +
7836
42.2k
          (input[input_count] % 256);
7837
42.2k
      uint16_t decomposition_length =
7838
42.2k
          (decomposition[1] >> 2) - (decomposition[0] >> 2);
7839
42.2k
      if (decomposition_length > 0 && (decomposition[0] & 1)) {
7840
0
        decomposition_length = 0;
7841
0
      }
7842
42.2k
      if (decomposition_length > 0) {
7843
        // Non-recursive decomposition.
7844
16.2k
        while (decomposition_length-- > 0) {
7845
11.5k
          input[--descending_idx] = decomposition_data[(decomposition[0] >> 2) +
7846
11.5k
                                                       decomposition_length];
7847
11.5k
        }
7848
37.6k
      } else {
7849
        // No decomposition.
7850
37.6k
        input[--descending_idx] = input[input_count];
7851
37.6k
      }
7852
42.2k
    } else {
7853
      // Non-Unicode character.
7854
0
      input[--descending_idx] = input[input_count];
7855
0
    }
7856
46.1k
  }
7857
2.18k
}
7858
7859
339k
uint8_t get_ccc(char32_t c) noexcept {
7860
339k
  return c < 0x110000 ? canonical_combining_class_block
7861
339k
                            [canonical_combining_class_index[c >> 8]][c % 256]
7862
339k
                      : 0;
7863
339k
}
7864
7865
5.87k
void sort_marks(std::u32string& input) {
7866
175k
  for (size_t idx = 1; idx < input.size(); idx++) {
7867
169k
    uint8_t ccc = get_ccc(input[idx]);
7868
169k
    if (ccc == 0) {
7869
159k
      continue;
7870
159k
    }  // Skip non-combining characters.
7871
9.95k
    auto current_character = input[idx];
7872
9.95k
    size_t back_idx = idx;
7873
11.9k
    while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) {
7874
1.97k
      input[back_idx] = input[back_idx - 1];
7875
1.97k
      back_idx--;
7876
1.97k
    }
7877
9.95k
    input[back_idx] = current_character;
7878
9.95k
  }
7879
5.87k
}
7880
7881
5.87k
void decompose_nfc(std::u32string& input) {
7882
  /**
7883
   * Decompose the domain_name string to Unicode Normalization Form C.
7884
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepDecompose
7885
   */
7886
5.87k
  auto [decomposition_needed, additional_elements] =
7887
5.87k
      compute_decomposition_length(input);
7888
5.87k
  if (decomposition_needed) {
7889
2.18k
    decompose(input, additional_elements);
7890
2.18k
  }
7891
5.87k
  sort_marks(input);
7892
5.87k
}
7893
7894
5.87k
void compose(std::u32string& input) {
7895
  /**
7896
   * Compose the domain_name string to Unicode Normalization Form C.
7897
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepCompose
7898
   */
7899
5.87k
  size_t input_count{0};
7900
5.87k
  size_t composition_count{0};
7901
164k
  for (; input_count < input.size(); input_count++, composition_count++) {
7902
158k
    input[composition_count] = input[input_count];
7903
158k
    if (input[input_count] >= hangul_lbase &&
7904
41.3k
        input[input_count] < hangul_lbase + hangul_lcount) {
7905
5.27k
      if (input_count + 1 < input.size() &&
7906
5.08k
          input[input_count + 1] >= hangul_vbase &&
7907
4.25k
          input[input_count + 1] < hangul_vbase + hangul_vcount) {
7908
3.92k
        input[composition_count] =
7909
3.92k
            hangul_sbase +
7910
3.92k
            ((input[input_count] - hangul_lbase) * hangul_vcount +
7911
3.92k
             input[input_count + 1] - hangul_vbase) *
7912
3.92k
                hangul_tcount;
7913
3.92k
        input_count++;
7914
3.92k
        if (input_count + 1 < input.size() &&
7915
3.72k
            input[input_count + 1] > hangul_tbase &&
7916
3.03k
            input[input_count + 1] < hangul_tbase + hangul_tcount) {
7917
2.84k
          input[composition_count] += input[++input_count] - hangul_tbase;
7918
2.84k
        }
7919
3.92k
      }
7920
153k
    } else if (input[input_count] >= hangul_sbase &&
7921
1.66k
               input[input_count] < hangul_sbase + hangul_scount) {
7922
0
      if ((input[input_count] - hangul_sbase) % hangul_tcount &&
7923
0
          input_count + 1 < input.size() &&
7924
0
          input[input_count + 1] > hangul_tbase &&
7925
0
          input[input_count + 1] < hangul_tbase + hangul_tcount) {
7926
0
        input[composition_count] += input[++input_count] - hangul_tbase;
7927
0
      }
7928
153k
    } else if (input[input_count] < 0x110000) {
7929
153k
      const uint16_t* composition =
7930
153k
          &composition_block[composition_index[input[input_count] >> 8]]
7931
153k
                            [input[input_count] % 256];
7932
153k
      size_t initial_composition_count = composition_count;
7933
163k
      for (int32_t previous_ccc = -1; input_count + 1 < input.size();
7934
158k
           input_count++) {
7935
158k
        uint8_t ccc = get_ccc(input[input_count + 1]);
7936
7937
158k
        if (composition[1] != composition[0] && previous_ccc < ccc) {
7938
          // Try finding a composition.
7939
47.7k
          int left = composition[0];
7940
47.7k
          int right = composition[1];
7941
135k
          while (left + 2 < right) {
7942
            // mean without overflow
7943
87.7k
            int middle = left + (((right - left) >> 1) & ~1);
7944
87.7k
            if (composition_data[middle] <= input[input_count + 1]) {
7945
12.0k
              left = middle;
7946
12.0k
            }
7947
87.7k
            if (composition_data[middle] >= input[input_count + 1]) {
7948
81.1k
              right = middle;
7949
81.1k
            }
7950
87.7k
          }
7951
47.7k
          if (composition_data[left] == input[input_count + 1]) {
7952
6.58k
            input[initial_composition_count] = composition_data[left + 1];
7953
6.58k
            composition =
7954
6.58k
                &composition_block
7955
6.58k
                    [composition_index[composition_data[left + 1] >> 8]]
7956
6.58k
                    [composition_data[left + 1] % 256];
7957
6.58k
            continue;
7958
6.58k
          }
7959
47.7k
        }
7960
7961
151k
        if (ccc == 0) {
7962
148k
          break;
7963
148k
        }  // Not a combining character.
7964
3.43k
        previous_ccc = ccc;
7965
3.43k
        input[++composition_count] = input[input_count + 1];
7966
3.43k
      }
7967
153k
    }
7968
158k
  }
7969
7970
5.87k
  if (composition_count < input_count) {
7971
2.20k
    input.resize(composition_count);
7972
2.20k
  }
7973
5.87k
}
7974
7975
5.87k
void normalize(std::u32string& input) {
7976
  /**
7977
   * Normalize the domain_name string to Unicode Normalization Form C.
7978
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepNormalize
7979
   */
7980
5.87k
  decompose_nfc(input);
7981
5.87k
  compose(input);
7982
5.87k
}
7983
7984
}  // namespace ada::idna
7985
/* end file src/normalization.cpp */
7986
/* begin file src/punycode.cpp */
7987
7988
#include <cstdint>
7989
7990
namespace ada::idna {
7991
7992
constexpr int32_t base = 36;
7993
constexpr int32_t tmin = 1;
7994
constexpr int32_t tmax = 26;
7995
constexpr int32_t skew = 38;
7996
constexpr int32_t damp = 700;
7997
constexpr int32_t initial_bias = 72;
7998
constexpr uint32_t initial_n = 128;
7999
8000
34.6k
static constexpr int32_t char_to_digit_value(char value) {
8001
34.6k
  if (value >= 'a' && value <= 'z') return value - 'a';
8002
3.68k
  if (value >= '0' && value <= '9') return value - '0' + 26;
8003
54
  return -1;
8004
3.68k
}
8005
8006
122k
static constexpr char digit_to_char(int32_t digit) {
8007
122k
  return digit < 26 ? char(digit + 97) : char(digit + 22);
8008
122k
}
8009
8010
85.2k
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
8011
85.2k
  if (firsttime) {
8012
12.5k
    d = d / damp;
8013
72.6k
  } else {
8014
72.6k
    d = d / 2;
8015
72.6k
  }
8016
85.2k
  d += d / n;
8017
85.2k
  int32_t k = 0;
8018
103k
  while (d > ((base - tmin) * tmax) / 2) {
8019
18.2k
    d /= base - tmin;
8020
18.2k
    k += base;
8021
18.2k
  }
8022
85.2k
  return k + (((base - tmin + 1) * d) / (d + skew));
8023
85.2k
}
8024
8025
3.73k
bool punycode_to_utf32(std::string_view input, std::u32string &out) {
8026
  // See https://github.com/whatwg/url/issues/803
8027
3.73k
  if (input.starts_with("xn--")) {
8028
3
    return false;
8029
3
  }
8030
3.73k
  int32_t written_out{0};
8031
3.73k
  out.reserve(out.size() + input.size());
8032
3.73k
  uint32_t n = initial_n;
8033
3.73k
  int32_t i = 0;
8034
3.73k
  int32_t bias = initial_bias;
8035
  // grab ascii content
8036
3.73k
  size_t end_of_ascii = input.find_last_of('-');
8037
3.73k
  if (end_of_ascii != std::string_view::npos) {
8038
3.68k
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8039
3.68k
      if (c >= 0x80) {
8040
0
        return false;
8041
0
      }
8042
3.68k
      out.push_back(c);
8043
3.68k
      written_out++;
8044
3.68k
    }
8045
368
    input.remove_prefix(end_of_ascii + 1);
8046
368
  }
8047
28.4k
  while (!input.empty()) {
8048
24.8k
    int32_t oldi = i;
8049
24.8k
    int32_t w = 1;
8050
34.7k
    for (int32_t k = base;; k += base) {
8051
34.7k
      if (input.empty()) {
8052
79
        return false;
8053
79
      }
8054
34.6k
      uint8_t code_point = input.front();
8055
34.6k
      input.remove_prefix(1);
8056
34.6k
      int32_t digit = char_to_digit_value(code_point);
8057
34.6k
      if (digit < 0) {
8058
54
        return false;
8059
54
      }
8060
34.6k
      if (digit > (0x7fffffff - i) / w) {
8061
8
        return false;
8062
8
      }
8063
34.5k
      i = i + digit * w;
8064
34.5k
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8065
34.5k
      if (digit < t) {
8066
24.7k
        break;
8067
24.7k
      }
8068
9.88k
      if (w > 0x7fffffff / (base - t)) {
8069
0
        return false;
8070
0
      }
8071
9.88k
      w = w * (base - t);
8072
9.88k
    }
8073
24.7k
    bias = adapt(i - oldi, written_out + 1, oldi == 0);
8074
24.7k
    if (i / (written_out + 1) > int32_t(0x7fffffff - n)) {
8075
23
      return false;
8076
23
    }
8077
24.6k
    n = n + i / (written_out + 1);
8078
24.6k
    i = i % (written_out + 1);
8079
24.6k
    if (n < 0x80) {
8080
0
      return false;
8081
0
    }
8082
24.6k
    out.insert(out.begin() + i, n);
8083
24.6k
    written_out++;
8084
24.6k
    ++i;
8085
24.6k
  }
8086
3.56k
  return true;
8087
3.73k
}
8088
8089
0
bool verify_punycode(std::string_view input) {
8090
0
  if (input.starts_with("xn--")) {
8091
0
    return false;
8092
0
  }
8093
0
  size_t written_out{0};
8094
0
  uint32_t n = initial_n;
8095
0
  int32_t i = 0;
8096
0
  int32_t bias = initial_bias;
8097
  // grab ascii content
8098
0
  size_t end_of_ascii = input.find_last_of('-');
8099
0
  if (end_of_ascii != std::string_view::npos) {
8100
0
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8101
0
      if (c >= 0x80) {
8102
0
        return false;
8103
0
      }
8104
0
      written_out++;
8105
0
    }
8106
0
    input.remove_prefix(end_of_ascii + 1);
8107
0
  }
8108
0
  while (!input.empty()) {
8109
0
    int32_t oldi = i;
8110
0
    int32_t w = 1;
8111
0
    for (int32_t k = base;; k += base) {
8112
0
      if (input.empty()) {
8113
0
        return false;
8114
0
      }
8115
0
      uint8_t code_point = input.front();
8116
0
      input.remove_prefix(1);
8117
0
      int32_t digit = char_to_digit_value(code_point);
8118
0
      if (digit < 0) {
8119
0
        return false;
8120
0
      }
8121
0
      if (digit > (0x7fffffff - i) / w) {
8122
0
        return false;
8123
0
      }
8124
0
      i = i + digit * w;
8125
0
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8126
0
      if (digit < t) {
8127
0
        break;
8128
0
      }
8129
0
      if (w > 0x7fffffff / (base - t)) {
8130
0
        return false;
8131
0
      }
8132
0
      w = w * (base - t);
8133
0
    }
8134
0
    bias = adapt(i - oldi, int32_t(written_out + 1), oldi == 0);
8135
0
    if (i / (written_out + 1) > 0x7fffffff - n) {
8136
0
      return false;
8137
0
    }
8138
0
    n = n + i / int32_t(written_out + 1);
8139
0
    i = i % int32_t(written_out + 1);
8140
0
    if (n < 0x80) {
8141
0
      return false;
8142
0
    }
8143
0
    written_out++;
8144
0
    ++i;
8145
0
  }
8146
8147
0
  return true;
8148
0
}
8149
8150
9.05k
bool utf32_to_punycode(std::u32string_view input, std::string &out) {
8151
9.05k
  out.reserve(input.size() + out.size());
8152
9.05k
  uint32_t n = initial_n;
8153
9.05k
  int32_t d = 0;
8154
9.05k
  int32_t bias = initial_bias;
8155
9.05k
  size_t h = 0;
8156
  // first push the ascii content
8157
74.2k
  for (uint32_t c : input) {
8158
74.2k
    if (c < 0x80) {
8159
13.7k
      ++h;
8160
13.7k
      out.push_back(char(c));
8161
13.7k
    }
8162
74.2k
    if (c > 0x10ffff || (c >= 0xd800 && c < 0xe000)) {
8163
0
      return false;
8164
0
    }
8165
74.2k
  }
8166
9.05k
  size_t b = h;
8167
9.05k
  if (b > 0) {
8168
2.32k
    out.push_back('-');
8169
2.32k
  }
8170
37.1k
  while (h < input.size()) {
8171
28.0k
    uint32_t m = 0x10FFFF;
8172
694k
    for (auto code_point : input) {
8173
694k
      if (code_point >= n && code_point < m) m = code_point;
8174
694k
    }
8175
8176
28.0k
    if ((m - n) > (0x7fffffff - d) / (h + 1)) {
8177
0
      return false;
8178
0
    }
8179
28.0k
    d = d + int32_t((m - n) * (h + 1));
8180
28.0k
    n = m;
8181
694k
    for (auto c : input) {
8182
694k
      if (c < n) {
8183
383k
        if (d == 0x7fffffff) {
8184
0
          return false;
8185
0
        }
8186
383k
        ++d;
8187
383k
      }
8188
694k
      if (c == n) {
8189
60.5k
        int32_t q = d;
8190
122k
        for (int32_t k = base;; k += base) {
8191
122k
          int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8192
8193
122k
          if (q < t) {
8194
60.5k
            break;
8195
60.5k
          }
8196
62.2k
          out.push_back(digit_to_char(t + ((q - t) % (base - t))));
8197
62.2k
          q = (q - t) / (base - t);
8198
62.2k
        }
8199
60.5k
        out.push_back(digit_to_char(q));
8200
60.5k
        bias = adapt(d, int32_t(h + 1), h == b);
8201
60.5k
        d = 0;
8202
60.5k
        ++h;
8203
60.5k
      }
8204
694k
    }
8205
28.0k
    ++d;
8206
28.0k
    ++n;
8207
28.0k
  }
8208
9.05k
  return true;
8209
9.05k
}
8210
8211
}  // namespace ada::idna
8212
/* end file src/punycode.cpp */
8213
/* begin file src/validity.cpp */
8214
#include <algorithm>
8215
#include <string_view>
8216
8217
namespace ada::idna {
8218
8219
enum direction : uint8_t {
8220
  NONE,
8221
  BN,
8222
  CS,
8223
  ES,
8224
  ON,
8225
  EN,
8226
  L,
8227
  R,
8228
  NSM,
8229
  AL,
8230
  AN,
8231
  ET,
8232
  WS,
8233
  RLO,
8234
  LRO,
8235
  PDF,
8236
  RLE,
8237
  RLI,
8238
  FSI,
8239
  PDI,
8240
  LRI,
8241
  B,
8242
  S,
8243
  LRE
8244
};
8245
8246
struct directions {
8247
  uint32_t start_code;
8248
  uint32_t final_code;
8249
  direction direct;
8250
};
8251
8252
static directions dir_table[] = {
8253
    {0x0, 0x8, direction::BN},          {0x9, 0x9, direction::S},
8254
    {0xa, 0xa, direction::B},           {0xb, 0xb, direction::S},
8255
    {0xc, 0xc, direction::WS},          {0xd, 0xd, direction::B},
8256
    {0xe, 0x1b, direction::BN},         {0x1c, 0x1e, direction::B},
8257
    {0x1f, 0x1f, direction::S},         {0x20, 0x20, direction::WS},
8258
    {0x21, 0x22, direction::ON},        {0x23, 0x25, direction::ET},
8259
    {0x26, 0x2a, direction::ON},        {0x2b, 0x2b, direction::ES},
8260
    {0x2c, 0x2c, direction::CS},        {0x2d, 0x2d, direction::ES},
8261
    {0x2e, 0x2f, direction::CS},        {0x30, 0x39, direction::EN},
8262
    {0x3a, 0x3a, direction::CS},        {0x3b, 0x40, direction::ON},
8263
    {0x41, 0x5a, direction::L},         {0x5b, 0x60, direction::ON},
8264
    {0x61, 0x7a, direction::L},         {0x7b, 0x7e, direction::ON},
8265
    {0x7f, 0x84, direction::BN},        {0x85, 0x85, direction::B},
8266
    {0x86, 0x9f, direction::BN},        {0xa0, 0xa0, direction::CS},
8267
    {0xa1, 0xa1, direction::ON},        {0xa2, 0xa5, direction::ET},
8268
    {0xa6, 0xa9, direction::ON},        {0xaa, 0xaa, direction::L},
8269
    {0xab, 0xac, direction::ON},        {0xad, 0xad, direction::BN},
8270
    {0xae, 0xaf, direction::ON},        {0xb0, 0xb1, direction::ET},
8271
    {0xb2, 0xb3, direction::EN},        {0xb4, 0xb4, direction::ON},
8272
    {0xb5, 0xb5, direction::L},         {0xb6, 0xb8, direction::ON},
8273
    {0xb9, 0xb9, direction::EN},        {0xba, 0xba, direction::L},
8274
    {0xbb, 0xbf, direction::ON},        {0xc0, 0xd6, direction::L},
8275
    {0xd7, 0xd7, direction::ON},        {0xd8, 0xf6, direction::L},
8276
    {0xf7, 0xf7, direction::ON},        {0xf8, 0x2b8, direction::L},
8277
    {0x2b9, 0x2ba, direction::ON},      {0x2bb, 0x2c1, direction::L},
8278
    {0x2c2, 0x2cf, direction::ON},      {0x2d0, 0x2d1, direction::L},
8279
    {0x2d2, 0x2df, direction::ON},      {0x2e0, 0x2e4, direction::L},
8280
    {0x2e5, 0x2ed, direction::ON},      {0x2ee, 0x2ee, direction::L},
8281
    {0x2ef, 0x2ff, direction::ON},      {0x300, 0x36f, direction::NSM},
8282
    {0x370, 0x373, direction::L},       {0x374, 0x375, direction::ON},
8283
    {0x376, 0x377, direction::L},       {0x37a, 0x37d, direction::L},
8284
    {0x37e, 0x37e, direction::ON},      {0x37f, 0x37f, direction::L},
8285
    {0x384, 0x385, direction::ON},      {0x386, 0x386, direction::L},
8286
    {0x387, 0x387, direction::ON},      {0x388, 0x38a, direction::L},
8287
    {0x38c, 0x38c, direction::L},       {0x38e, 0x3a1, direction::L},
8288
    {0x3a3, 0x3f5, direction::L},       {0x3f6, 0x3f6, direction::ON},
8289
    {0x3f7, 0x482, direction::L},       {0x483, 0x489, direction::NSM},
8290
    {0x48a, 0x52f, direction::L},       {0x531, 0x556, direction::L},
8291
    {0x559, 0x589, direction::L},       {0x58a, 0x58a, direction::ON},
8292
    {0x58d, 0x58e, direction::ON},      {0x58f, 0x58f, direction::ET},
8293
    {0x591, 0x5bd, direction::NSM},     {0x5be, 0x5be, direction::R},
8294
    {0x5bf, 0x5bf, direction::NSM},     {0x5c0, 0x5c0, direction::R},
8295
    {0x5c1, 0x5c2, direction::NSM},     {0x5c3, 0x5c3, direction::R},
8296
    {0x5c4, 0x5c5, direction::NSM},     {0x5c6, 0x5c6, direction::R},
8297
    {0x5c7, 0x5c7, direction::NSM},     {0x5d0, 0x5ea, direction::R},
8298
    {0x5ef, 0x5f4, direction::R},       {0x600, 0x605, direction::AN},
8299
    {0x606, 0x607, direction::ON},      {0x608, 0x608, direction::AL},
8300
    {0x609, 0x60a, direction::ET},      {0x60b, 0x60b, direction::AL},
8301
    {0x60c, 0x60c, direction::CS},      {0x60d, 0x60d, direction::AL},
8302
    {0x60e, 0x60f, direction::ON},      {0x610, 0x61a, direction::NSM},
8303
    {0x61b, 0x61c, direction::AL},      {0x61e, 0x64a, direction::AL},
8304
    {0x64b, 0x65f, direction::NSM},     {0x660, 0x669, direction::AN},
8305
    {0x66a, 0x66a, direction::ET},      {0x66b, 0x66c, direction::AN},
8306
    {0x66d, 0x66f, direction::AL},      {0x670, 0x670, direction::NSM},
8307
    {0x671, 0x6d5, direction::AL},      {0x6d6, 0x6dc, direction::NSM},
8308
    {0x6dd, 0x6dd, direction::AN},      {0x6de, 0x6de, direction::ON},
8309
    {0x6df, 0x6e4, direction::NSM},     {0x6e5, 0x6e6, direction::AL},
8310
    {0x6e7, 0x6e8, direction::NSM},     {0x6e9, 0x6e9, direction::ON},
8311
    {0x6ea, 0x6ed, direction::NSM},     {0x6ee, 0x6ef, direction::AL},
8312
    {0x6f0, 0x6f9, direction::EN},      {0x6fa, 0x70d, direction::AL},
8313
    {0x70f, 0x710, direction::AL},      {0x711, 0x711, direction::NSM},
8314
    {0x712, 0x72f, direction::AL},      {0x730, 0x74a, direction::NSM},
8315
    {0x74d, 0x7a5, direction::AL},      {0x7a6, 0x7b0, direction::NSM},
8316
    {0x7b1, 0x7b1, direction::AL},      {0x7c0, 0x7ea, direction::R},
8317
    {0x7eb, 0x7f3, direction::NSM},     {0x7f4, 0x7f5, direction::R},
8318
    {0x7f6, 0x7f9, direction::ON},      {0x7fa, 0x7fa, direction::R},
8319
    {0x7fd, 0x7fd, direction::NSM},     {0x7fe, 0x815, direction::R},
8320
    {0x816, 0x819, direction::NSM},     {0x81a, 0x81a, direction::R},
8321
    {0x81b, 0x823, direction::NSM},     {0x824, 0x824, direction::R},
8322
    {0x825, 0x827, direction::NSM},     {0x828, 0x828, direction::R},
8323
    {0x829, 0x82d, direction::NSM},     {0x830, 0x83e, direction::R},
8324
    {0x840, 0x858, direction::R},       {0x859, 0x85b, direction::NSM},
8325
    {0x85e, 0x85e, direction::R},       {0x860, 0x86a, direction::AL},
8326
    {0x8a0, 0x8b4, direction::AL},      {0x8b6, 0x8c7, direction::AL},
8327
    {0x8d3, 0x8e1, direction::NSM},     {0x8e2, 0x8e2, direction::AN},
8328
    {0x8e3, 0x902, direction::NSM},     {0x903, 0x939, direction::L},
8329
    {0x93a, 0x93a, direction::NSM},     {0x93b, 0x93b, direction::L},
8330
    {0x93c, 0x93c, direction::NSM},     {0x93d, 0x940, direction::L},
8331
    {0x941, 0x948, direction::NSM},     {0x949, 0x94c, direction::L},
8332
    {0x94d, 0x94d, direction::NSM},     {0x94e, 0x950, direction::L},
8333
    {0x951, 0x957, direction::NSM},     {0x958, 0x961, direction::L},
8334
    {0x962, 0x963, direction::NSM},     {0x964, 0x980, direction::L},
8335
    {0x981, 0x981, direction::NSM},     {0x982, 0x983, direction::L},
8336
    {0x985, 0x98c, direction::L},       {0x98f, 0x990, direction::L},
8337
    {0x993, 0x9a8, direction::L},       {0x9aa, 0x9b0, direction::L},
8338
    {0x9b2, 0x9b2, direction::L},       {0x9b6, 0x9b9, direction::L},
8339
    {0x9bc, 0x9bc, direction::NSM},     {0x9bd, 0x9c0, direction::L},
8340
    {0x9c1, 0x9c4, direction::NSM},     {0x9c7, 0x9c8, direction::L},
8341
    {0x9cb, 0x9cc, direction::L},       {0x9cd, 0x9cd, direction::NSM},
8342
    {0x9ce, 0x9ce, direction::L},       {0x9d7, 0x9d7, direction::L},
8343
    {0x9dc, 0x9dd, direction::L},       {0x9df, 0x9e1, direction::L},
8344
    {0x9e2, 0x9e3, direction::NSM},     {0x9e6, 0x9f1, direction::L},
8345
    {0x9f2, 0x9f3, direction::ET},      {0x9f4, 0x9fa, direction::L},
8346
    {0x9fb, 0x9fb, direction::ET},      {0x9fc, 0x9fd, direction::L},
8347
    {0x9fe, 0x9fe, direction::NSM},     {0xa01, 0xa02, direction::NSM},
8348
    {0xa03, 0xa03, direction::L},       {0xa05, 0xa0a, direction::L},
8349
    {0xa0f, 0xa10, direction::L},       {0xa13, 0xa28, direction::L},
8350
    {0xa2a, 0xa30, direction::L},       {0xa32, 0xa33, direction::L},
8351
    {0xa35, 0xa36, direction::L},       {0xa38, 0xa39, direction::L},
8352
    {0xa3c, 0xa3c, direction::NSM},     {0xa3e, 0xa40, direction::L},
8353
    {0xa41, 0xa42, direction::NSM},     {0xa47, 0xa48, direction::NSM},
8354
    {0xa4b, 0xa4d, direction::NSM},     {0xa51, 0xa51, direction::NSM},
8355
    {0xa59, 0xa5c, direction::L},       {0xa5e, 0xa5e, direction::L},
8356
    {0xa66, 0xa6f, direction::L},       {0xa70, 0xa71, direction::NSM},
8357
    {0xa72, 0xa74, direction::L},       {0xa75, 0xa75, direction::NSM},
8358
    {0xa76, 0xa76, direction::L},       {0xa81, 0xa82, direction::NSM},
8359
    {0xa83, 0xa83, direction::L},       {0xa85, 0xa8d, direction::L},
8360
    {0xa8f, 0xa91, direction::L},       {0xa93, 0xaa8, direction::L},
8361
    {0xaaa, 0xab0, direction::L},       {0xab2, 0xab3, direction::L},
8362
    {0xab5, 0xab9, direction::L},       {0xabc, 0xabc, direction::NSM},
8363
    {0xabd, 0xac0, direction::L},       {0xac1, 0xac5, direction::NSM},
8364
    {0xac7, 0xac8, direction::NSM},     {0xac9, 0xac9, direction::L},
8365
    {0xacb, 0xacc, direction::L},       {0xacd, 0xacd, direction::NSM},
8366
    {0xad0, 0xad0, direction::L},       {0xae0, 0xae1, direction::L},
8367
    {0xae2, 0xae3, direction::NSM},     {0xae6, 0xaf0, direction::L},
8368
    {0xaf1, 0xaf1, direction::ET},      {0xaf9, 0xaf9, direction::L},
8369
    {0xafa, 0xaff, direction::NSM},     {0xb01, 0xb01, direction::NSM},
8370
    {0xb02, 0xb03, direction::L},       {0xb05, 0xb0c, direction::L},
8371
    {0xb0f, 0xb10, direction::L},       {0xb13, 0xb28, direction::L},
8372
    {0xb2a, 0xb30, direction::L},       {0xb32, 0xb33, direction::L},
8373
    {0xb35, 0xb39, direction::L},       {0xb3c, 0xb3c, direction::NSM},
8374
    {0xb3d, 0xb3e, direction::L},       {0xb3f, 0xb3f, direction::NSM},
8375
    {0xb40, 0xb40, direction::L},       {0xb41, 0xb44, direction::NSM},
8376
    {0xb47, 0xb48, direction::L},       {0xb4b, 0xb4c, direction::L},
8377
    {0xb4d, 0xb4d, direction::NSM},     {0xb55, 0xb56, direction::NSM},
8378
    {0xb57, 0xb57, direction::L},       {0xb5c, 0xb5d, direction::L},
8379
    {0xb5f, 0xb61, direction::L},       {0xb62, 0xb63, direction::NSM},
8380
    {0xb66, 0xb77, direction::L},       {0xb82, 0xb82, direction::NSM},
8381
    {0xb83, 0xb83, direction::L},       {0xb85, 0xb8a, direction::L},
8382
    {0xb8e, 0xb90, direction::L},       {0xb92, 0xb95, direction::L},
8383
    {0xb99, 0xb9a, direction::L},       {0xb9c, 0xb9c, direction::L},
8384
    {0xb9e, 0xb9f, direction::L},       {0xba3, 0xba4, direction::L},
8385
    {0xba8, 0xbaa, direction::L},       {0xbae, 0xbb9, direction::L},
8386
    {0xbbe, 0xbbf, direction::L},       {0xbc0, 0xbc0, direction::NSM},
8387
    {0xbc1, 0xbc2, direction::L},       {0xbc6, 0xbc8, direction::L},
8388
    {0xbca, 0xbcc, direction::L},       {0xbcd, 0xbcd, direction::NSM},
8389
    {0xbd0, 0xbd0, direction::L},       {0xbd7, 0xbd7, direction::L},
8390
    {0xbe6, 0xbf2, direction::L},       {0xbf3, 0xbf8, direction::ON},
8391
    {0xbf9, 0xbf9, direction::ET},      {0xbfa, 0xbfa, direction::ON},
8392
    {0xc00, 0xc00, direction::NSM},     {0xc01, 0xc03, direction::L},
8393
    {0xc04, 0xc04, direction::NSM},     {0xc05, 0xc0c, direction::L},
8394
    {0xc0e, 0xc10, direction::L},       {0xc12, 0xc28, direction::L},
8395
    {0xc2a, 0xc39, direction::L},       {0xc3d, 0xc3d, direction::L},
8396
    {0xc3e, 0xc40, direction::NSM},     {0xc41, 0xc44, direction::L},
8397
    {0xc46, 0xc48, direction::NSM},     {0xc4a, 0xc4d, direction::NSM},
8398
    {0xc55, 0xc56, direction::NSM},     {0xc58, 0xc5a, direction::L},
8399
    {0xc60, 0xc61, direction::L},       {0xc62, 0xc63, direction::NSM},
8400
    {0xc66, 0xc6f, direction::L},       {0xc77, 0xc77, direction::L},
8401
    {0xc78, 0xc7e, direction::ON},      {0xc7f, 0xc80, direction::L},
8402
    {0xc81, 0xc81, direction::NSM},     {0xc82, 0xc8c, direction::L},
8403
    {0xc8e, 0xc90, direction::L},       {0xc92, 0xca8, direction::L},
8404
    {0xcaa, 0xcb3, direction::L},       {0xcb5, 0xcb9, direction::L},
8405
    {0xcbc, 0xcbc, direction::NSM},     {0xcbd, 0xcc4, direction::L},
8406
    {0xcc6, 0xcc8, direction::L},       {0xcca, 0xccb, direction::L},
8407
    {0xccc, 0xccd, direction::NSM},     {0xcd5, 0xcd6, direction::L},
8408
    {0xcde, 0xcde, direction::L},       {0xce0, 0xce1, direction::L},
8409
    {0xce2, 0xce3, direction::NSM},     {0xce6, 0xcef, direction::L},
8410
    {0xcf1, 0xcf2, direction::L},       {0xd00, 0xd01, direction::NSM},
8411
    {0xd02, 0xd0c, direction::L},       {0xd0e, 0xd10, direction::L},
8412
    {0xd12, 0xd3a, direction::L},       {0xd3b, 0xd3c, direction::NSM},
8413
    {0xd3d, 0xd40, direction::L},       {0xd41, 0xd44, direction::NSM},
8414
    {0xd46, 0xd48, direction::L},       {0xd4a, 0xd4c, direction::L},
8415
    {0xd4d, 0xd4d, direction::NSM},     {0xd4e, 0xd4f, direction::L},
8416
    {0xd54, 0xd61, direction::L},       {0xd62, 0xd63, direction::NSM},
8417
    {0xd66, 0xd7f, direction::L},       {0xd81, 0xd81, direction::NSM},
8418
    {0xd82, 0xd83, direction::L},       {0xd85, 0xd96, direction::L},
8419
    {0xd9a, 0xdb1, direction::L},       {0xdb3, 0xdbb, direction::L},
8420
    {0xdbd, 0xdbd, direction::L},       {0xdc0, 0xdc6, direction::L},
8421
    {0xdca, 0xdca, direction::NSM},     {0xdcf, 0xdd1, direction::L},
8422
    {0xdd2, 0xdd4, direction::NSM},     {0xdd6, 0xdd6, direction::NSM},
8423
    {0xdd8, 0xddf, direction::L},       {0xde6, 0xdef, direction::L},
8424
    {0xdf2, 0xdf4, direction::L},       {0xe01, 0xe30, direction::L},
8425
    {0xe31, 0xe31, direction::NSM},     {0xe32, 0xe33, direction::L},
8426
    {0xe34, 0xe3a, direction::NSM},     {0xe3f, 0xe3f, direction::ET},
8427
    {0xe40, 0xe46, direction::L},       {0xe47, 0xe4e, direction::NSM},
8428
    {0xe4f, 0xe5b, direction::L},       {0xe81, 0xe82, direction::L},
8429
    {0xe84, 0xe84, direction::L},       {0xe86, 0xe8a, direction::L},
8430
    {0xe8c, 0xea3, direction::L},       {0xea5, 0xea5, direction::L},
8431
    {0xea7, 0xeb0, direction::L},       {0xeb1, 0xeb1, direction::NSM},
8432
    {0xeb2, 0xeb3, direction::L},       {0xeb4, 0xebc, direction::NSM},
8433
    {0xebd, 0xebd, direction::L},       {0xec0, 0xec4, direction::L},
8434
    {0xec6, 0xec6, direction::L},       {0xec8, 0xecd, direction::NSM},
8435
    {0xed0, 0xed9, direction::L},       {0xedc, 0xedf, direction::L},
8436
    {0xf00, 0xf17, direction::L},       {0xf18, 0xf19, direction::NSM},
8437
    {0xf1a, 0xf34, direction::L},       {0xf35, 0xf35, direction::NSM},
8438
    {0xf36, 0xf36, direction::L},       {0xf37, 0xf37, direction::NSM},
8439
    {0xf38, 0xf38, direction::L},       {0xf39, 0xf39, direction::NSM},
8440
    {0xf3a, 0xf3d, direction::ON},      {0xf3e, 0xf47, direction::L},
8441
    {0xf49, 0xf6c, direction::L},       {0xf71, 0xf7e, direction::NSM},
8442
    {0xf7f, 0xf7f, direction::L},       {0xf80, 0xf84, direction::NSM},
8443
    {0xf85, 0xf85, direction::L},       {0xf86, 0xf87, direction::NSM},
8444
    {0xf88, 0xf8c, direction::L},       {0xf8d, 0xf97, direction::NSM},
8445
    {0xf99, 0xfbc, direction::NSM},     {0xfbe, 0xfc5, direction::L},
8446
    {0xfc6, 0xfc6, direction::NSM},     {0xfc7, 0xfcc, direction::L},
8447
    {0xfce, 0xfda, direction::L},       {0x1000, 0x102c, direction::L},
8448
    {0x102d, 0x1030, direction::NSM},   {0x1031, 0x1031, direction::L},
8449
    {0x1032, 0x1037, direction::NSM},   {0x1038, 0x1038, direction::L},
8450
    {0x1039, 0x103a, direction::NSM},   {0x103b, 0x103c, direction::L},
8451
    {0x103d, 0x103e, direction::NSM},   {0x103f, 0x1057, direction::L},
8452
    {0x1058, 0x1059, direction::NSM},   {0x105a, 0x105d, direction::L},
8453
    {0x105e, 0x1060, direction::NSM},   {0x1061, 0x1070, direction::L},
8454
    {0x1071, 0x1074, direction::NSM},   {0x1075, 0x1081, direction::L},
8455
    {0x1082, 0x1082, direction::NSM},   {0x1083, 0x1084, direction::L},
8456
    {0x1085, 0x1086, direction::NSM},   {0x1087, 0x108c, direction::L},
8457
    {0x108d, 0x108d, direction::NSM},   {0x108e, 0x109c, direction::L},
8458
    {0x109d, 0x109d, direction::NSM},   {0x109e, 0x10c5, direction::L},
8459
    {0x10c7, 0x10c7, direction::L},     {0x10cd, 0x10cd, direction::L},
8460
    {0x10d0, 0x1248, direction::L},     {0x124a, 0x124d, direction::L},
8461
    {0x1250, 0x1256, direction::L},     {0x1258, 0x1258, direction::L},
8462
    {0x125a, 0x125d, direction::L},     {0x1260, 0x1288, direction::L},
8463
    {0x128a, 0x128d, direction::L},     {0x1290, 0x12b0, direction::L},
8464
    {0x12b2, 0x12b5, direction::L},     {0x12b8, 0x12be, direction::L},
8465
    {0x12c0, 0x12c0, direction::L},     {0x12c2, 0x12c5, direction::L},
8466
    {0x12c8, 0x12d6, direction::L},     {0x12d8, 0x1310, direction::L},
8467
    {0x1312, 0x1315, direction::L},     {0x1318, 0x135a, direction::L},
8468
    {0x135d, 0x135f, direction::NSM},   {0x1360, 0x137c, direction::L},
8469
    {0x1380, 0x138f, direction::L},     {0x1390, 0x1399, direction::ON},
8470
    {0x13a0, 0x13f5, direction::L},     {0x13f8, 0x13fd, direction::L},
8471
    {0x1400, 0x1400, direction::ON},    {0x1401, 0x167f, direction::L},
8472
    {0x1680, 0x1680, direction::WS},    {0x1681, 0x169a, direction::L},
8473
    {0x169b, 0x169c, direction::ON},    {0x16a0, 0x16f8, direction::L},
8474
    {0x1700, 0x170c, direction::L},     {0x170e, 0x1711, direction::L},
8475
    {0x1712, 0x1714, direction::NSM},   {0x1720, 0x1731, direction::L},
8476
    {0x1732, 0x1734, direction::NSM},   {0x1735, 0x1736, direction::L},
8477
    {0x1740, 0x1751, direction::L},     {0x1752, 0x1753, direction::NSM},
8478
    {0x1760, 0x176c, direction::L},     {0x176e, 0x1770, direction::L},
8479
    {0x1772, 0x1773, direction::NSM},   {0x1780, 0x17b3, direction::L},
8480
    {0x17b4, 0x17b5, direction::NSM},   {0x17b6, 0x17b6, direction::L},
8481
    {0x17b7, 0x17bd, direction::NSM},   {0x17be, 0x17c5, direction::L},
8482
    {0x17c6, 0x17c6, direction::NSM},   {0x17c7, 0x17c8, direction::L},
8483
    {0x17c9, 0x17d3, direction::NSM},   {0x17d4, 0x17da, direction::L},
8484
    {0x17db, 0x17db, direction::ET},    {0x17dc, 0x17dc, direction::L},
8485
    {0x17dd, 0x17dd, direction::NSM},   {0x17e0, 0x17e9, direction::L},
8486
    {0x17f0, 0x17f9, direction::ON},    {0x1800, 0x180a, direction::ON},
8487
    {0x180b, 0x180d, direction::NSM},   {0x180e, 0x180e, direction::BN},
8488
    {0x1810, 0x1819, direction::L},     {0x1820, 0x1878, direction::L},
8489
    {0x1880, 0x1884, direction::L},     {0x1885, 0x1886, direction::NSM},
8490
    {0x1887, 0x18a8, direction::L},     {0x18a9, 0x18a9, direction::NSM},
8491
    {0x18aa, 0x18aa, direction::L},     {0x18b0, 0x18f5, direction::L},
8492
    {0x1900, 0x191e, direction::L},     {0x1920, 0x1922, direction::NSM},
8493
    {0x1923, 0x1926, direction::L},     {0x1927, 0x1928, direction::NSM},
8494
    {0x1929, 0x192b, direction::L},     {0x1930, 0x1931, direction::L},
8495
    {0x1932, 0x1932, direction::NSM},   {0x1933, 0x1938, direction::L},
8496
    {0x1939, 0x193b, direction::NSM},   {0x1940, 0x1940, direction::ON},
8497
    {0x1944, 0x1945, direction::ON},    {0x1946, 0x196d, direction::L},
8498
    {0x1970, 0x1974, direction::L},     {0x1980, 0x19ab, direction::L},
8499
    {0x19b0, 0x19c9, direction::L},     {0x19d0, 0x19da, direction::L},
8500
    {0x19de, 0x19ff, direction::ON},    {0x1a00, 0x1a16, direction::L},
8501
    {0x1a17, 0x1a18, direction::NSM},   {0x1a19, 0x1a1a, direction::L},
8502
    {0x1a1b, 0x1a1b, direction::NSM},   {0x1a1e, 0x1a55, direction::L},
8503
    {0x1a56, 0x1a56, direction::NSM},   {0x1a57, 0x1a57, direction::L},
8504
    {0x1a58, 0x1a5e, direction::NSM},   {0x1a60, 0x1a60, direction::NSM},
8505
    {0x1a61, 0x1a61, direction::L},     {0x1a62, 0x1a62, direction::NSM},
8506
    {0x1a63, 0x1a64, direction::L},     {0x1a65, 0x1a6c, direction::NSM},
8507
    {0x1a6d, 0x1a72, direction::L},     {0x1a73, 0x1a7c, direction::NSM},
8508
    {0x1a7f, 0x1a7f, direction::NSM},   {0x1a80, 0x1a89, direction::L},
8509
    {0x1a90, 0x1a99, direction::L},     {0x1aa0, 0x1aad, direction::L},
8510
    {0x1ab0, 0x1ac0, direction::NSM},   {0x1b00, 0x1b03, direction::NSM},
8511
    {0x1b04, 0x1b33, direction::L},     {0x1b34, 0x1b34, direction::NSM},
8512
    {0x1b35, 0x1b35, direction::L},     {0x1b36, 0x1b3a, direction::NSM},
8513
    {0x1b3b, 0x1b3b, direction::L},     {0x1b3c, 0x1b3c, direction::NSM},
8514
    {0x1b3d, 0x1b41, direction::L},     {0x1b42, 0x1b42, direction::NSM},
8515
    {0x1b43, 0x1b4b, direction::L},     {0x1b50, 0x1b6a, direction::L},
8516
    {0x1b6b, 0x1b73, direction::NSM},   {0x1b74, 0x1b7c, direction::L},
8517
    {0x1b80, 0x1b81, direction::NSM},   {0x1b82, 0x1ba1, direction::L},
8518
    {0x1ba2, 0x1ba5, direction::NSM},   {0x1ba6, 0x1ba7, direction::L},
8519
    {0x1ba8, 0x1ba9, direction::NSM},   {0x1baa, 0x1baa, direction::L},
8520
    {0x1bab, 0x1bad, direction::NSM},   {0x1bae, 0x1be5, direction::L},
8521
    {0x1be6, 0x1be6, direction::NSM},   {0x1be7, 0x1be7, direction::L},
8522
    {0x1be8, 0x1be9, direction::NSM},   {0x1bea, 0x1bec, direction::L},
8523
    {0x1bed, 0x1bed, direction::NSM},   {0x1bee, 0x1bee, direction::L},
8524
    {0x1bef, 0x1bf1, direction::NSM},   {0x1bf2, 0x1bf3, direction::L},
8525
    {0x1bfc, 0x1c2b, direction::L},     {0x1c2c, 0x1c33, direction::NSM},
8526
    {0x1c34, 0x1c35, direction::L},     {0x1c36, 0x1c37, direction::NSM},
8527
    {0x1c3b, 0x1c49, direction::L},     {0x1c4d, 0x1c88, direction::L},
8528
    {0x1c90, 0x1cba, direction::L},     {0x1cbd, 0x1cc7, direction::L},
8529
    {0x1cd0, 0x1cd2, direction::NSM},   {0x1cd3, 0x1cd3, direction::L},
8530
    {0x1cd4, 0x1ce0, direction::NSM},   {0x1ce1, 0x1ce1, direction::L},
8531
    {0x1ce2, 0x1ce8, direction::NSM},   {0x1ce9, 0x1cec, direction::L},
8532
    {0x1ced, 0x1ced, direction::NSM},   {0x1cee, 0x1cf3, direction::L},
8533
    {0x1cf4, 0x1cf4, direction::NSM},   {0x1cf5, 0x1cf7, direction::L},
8534
    {0x1cf8, 0x1cf9, direction::NSM},   {0x1cfa, 0x1cfa, direction::L},
8535
    {0x1d00, 0x1dbf, direction::L},     {0x1dc0, 0x1df9, direction::NSM},
8536
    {0x1dfb, 0x1dff, direction::NSM},   {0x1e00, 0x1f15, direction::L},
8537
    {0x1f18, 0x1f1d, direction::L},     {0x1f20, 0x1f45, direction::L},
8538
    {0x1f48, 0x1f4d, direction::L},     {0x1f50, 0x1f57, direction::L},
8539
    {0x1f59, 0x1f59, direction::L},     {0x1f5b, 0x1f5b, direction::L},
8540
    {0x1f5d, 0x1f5d, direction::L},     {0x1f5f, 0x1f7d, direction::L},
8541
    {0x1f80, 0x1fb4, direction::L},     {0x1fb6, 0x1fbc, direction::L},
8542
    {0x1fbd, 0x1fbd, direction::ON},    {0x1fbe, 0x1fbe, direction::L},
8543
    {0x1fbf, 0x1fc1, direction::ON},    {0x1fc2, 0x1fc4, direction::L},
8544
    {0x1fc6, 0x1fcc, direction::L},     {0x1fcd, 0x1fcf, direction::ON},
8545
    {0x1fd0, 0x1fd3, direction::L},     {0x1fd6, 0x1fdb, direction::L},
8546
    {0x1fdd, 0x1fdf, direction::ON},    {0x1fe0, 0x1fec, direction::L},
8547
    {0x1fed, 0x1fef, direction::ON},    {0x1ff2, 0x1ff4, direction::L},
8548
    {0x1ff6, 0x1ffc, direction::L},     {0x1ffd, 0x1ffe, direction::ON},
8549
    {0x2000, 0x200a, direction::WS},    {0x200b, 0x200d, direction::BN},
8550
    {0x200e, 0x200e, direction::L},     {0x200f, 0x200f, direction::R},
8551
    {0x2010, 0x2027, direction::ON},    {0x2028, 0x2028, direction::WS},
8552
    {0x2029, 0x2029, direction::B},     {0x202a, 0x202a, direction::LRE},
8553
    {0x202b, 0x202b, direction::RLE},   {0x202c, 0x202c, direction::PDF},
8554
    {0x202d, 0x202d, direction::LRO},   {0x202e, 0x202e, direction::RLO},
8555
    {0x202f, 0x202f, direction::CS},    {0x2030, 0x2034, direction::ET},
8556
    {0x2035, 0x2043, direction::ON},    {0x2044, 0x2044, direction::CS},
8557
    {0x2045, 0x205e, direction::ON},    {0x205f, 0x205f, direction::WS},
8558
    {0x2060, 0x2064, direction::BN},    {0x2066, 0x2066, direction::LRI},
8559
    {0x2067, 0x2067, direction::RLI},   {0x2068, 0x2068, direction::FSI},
8560
    {0x2069, 0x2069, direction::PDI},   {0x206a, 0x206f, direction::BN},
8561
    {0x2070, 0x2070, direction::EN},    {0x2071, 0x2071, direction::L},
8562
    {0x2074, 0x2079, direction::EN},    {0x207a, 0x207b, direction::ES},
8563
    {0x207c, 0x207e, direction::ON},    {0x207f, 0x207f, direction::L},
8564
    {0x2080, 0x2089, direction::EN},    {0x208a, 0x208b, direction::ES},
8565
    {0x208c, 0x208e, direction::ON},    {0x2090, 0x209c, direction::L},
8566
    {0x20a0, 0x20bf, direction::ET},    {0x20d0, 0x20f0, direction::NSM},
8567
    {0x2100, 0x2101, direction::ON},    {0x2102, 0x2102, direction::L},
8568
    {0x2103, 0x2106, direction::ON},    {0x2107, 0x2107, direction::L},
8569
    {0x2108, 0x2109, direction::ON},    {0x210a, 0x2113, direction::L},
8570
    {0x2114, 0x2114, direction::ON},    {0x2115, 0x2115, direction::L},
8571
    {0x2116, 0x2118, direction::ON},    {0x2119, 0x211d, direction::L},
8572
    {0x211e, 0x2123, direction::ON},    {0x2124, 0x2124, direction::L},
8573
    {0x2125, 0x2125, direction::ON},    {0x2126, 0x2126, direction::L},
8574
    {0x2127, 0x2127, direction::ON},    {0x2128, 0x2128, direction::L},
8575
    {0x2129, 0x2129, direction::ON},    {0x212a, 0x212d, direction::L},
8576
    {0x212e, 0x212e, direction::ET},    {0x212f, 0x2139, direction::L},
8577
    {0x213a, 0x213b, direction::ON},    {0x213c, 0x213f, direction::L},
8578
    {0x2140, 0x2144, direction::ON},    {0x2145, 0x2149, direction::L},
8579
    {0x214a, 0x214d, direction::ON},    {0x214e, 0x214f, direction::L},
8580
    {0x2150, 0x215f, direction::ON},    {0x2160, 0x2188, direction::L},
8581
    {0x2189, 0x218b, direction::ON},    {0x2190, 0x2211, direction::ON},
8582
    {0x2212, 0x2212, direction::ES},    {0x2213, 0x2213, direction::ET},
8583
    {0x2214, 0x2335, direction::ON},    {0x2336, 0x237a, direction::L},
8584
    {0x237b, 0x2394, direction::ON},    {0x2395, 0x2395, direction::L},
8585
    {0x2396, 0x2426, direction::ON},    {0x2440, 0x244a, direction::ON},
8586
    {0x2460, 0x2487, direction::ON},    {0x2488, 0x249b, direction::EN},
8587
    {0x249c, 0x24e9, direction::L},     {0x24ea, 0x26ab, direction::ON},
8588
    {0x26ac, 0x26ac, direction::L},     {0x26ad, 0x27ff, direction::ON},
8589
    {0x2800, 0x28ff, direction::L},     {0x2900, 0x2b73, direction::ON},
8590
    {0x2b76, 0x2b95, direction::ON},    {0x2b97, 0x2bff, direction::ON},
8591
    {0x2c00, 0x2c2e, direction::L},     {0x2c30, 0x2c5e, direction::L},
8592
    {0x2c60, 0x2ce4, direction::L},     {0x2ce5, 0x2cea, direction::ON},
8593
    {0x2ceb, 0x2cee, direction::L},     {0x2cef, 0x2cf1, direction::NSM},
8594
    {0x2cf2, 0x2cf3, direction::L},     {0x2cf9, 0x2cff, direction::ON},
8595
    {0x2d00, 0x2d25, direction::L},     {0x2d27, 0x2d27, direction::L},
8596
    {0x2d2d, 0x2d2d, direction::L},     {0x2d30, 0x2d67, direction::L},
8597
    {0x2d6f, 0x2d70, direction::L},     {0x2d7f, 0x2d7f, direction::NSM},
8598
    {0x2d80, 0x2d96, direction::L},     {0x2da0, 0x2da6, direction::L},
8599
    {0x2da8, 0x2dae, direction::L},     {0x2db0, 0x2db6, direction::L},
8600
    {0x2db8, 0x2dbe, direction::L},     {0x2dc0, 0x2dc6, direction::L},
8601
    {0x2dc8, 0x2dce, direction::L},     {0x2dd0, 0x2dd6, direction::L},
8602
    {0x2dd8, 0x2dde, direction::L},     {0x2de0, 0x2dff, direction::NSM},
8603
    {0x2e00, 0x2e52, direction::ON},    {0x2e80, 0x2e99, direction::ON},
8604
    {0x2e9b, 0x2ef3, direction::ON},    {0x2f00, 0x2fd5, direction::ON},
8605
    {0x2ff0, 0x2ffb, direction::ON},    {0x3000, 0x3000, direction::WS},
8606
    {0x3001, 0x3004, direction::ON},    {0x3005, 0x3007, direction::L},
8607
    {0x3008, 0x3020, direction::ON},    {0x3021, 0x3029, direction::L},
8608
    {0x302a, 0x302d, direction::NSM},   {0x302e, 0x302f, direction::L},
8609
    {0x3030, 0x3030, direction::ON},    {0x3031, 0x3035, direction::L},
8610
    {0x3036, 0x3037, direction::ON},    {0x3038, 0x303c, direction::L},
8611
    {0x303d, 0x303f, direction::ON},    {0x3041, 0x3096, direction::L},
8612
    {0x3099, 0x309a, direction::NSM},   {0x309b, 0x309c, direction::ON},
8613
    {0x309d, 0x309f, direction::L},     {0x30a0, 0x30a0, direction::ON},
8614
    {0x30a1, 0x30fa, direction::L},     {0x30fb, 0x30fb, direction::ON},
8615
    {0x30fc, 0x30ff, direction::L},     {0x3105, 0x312f, direction::L},
8616
    {0x3131, 0x318e, direction::L},     {0x3190, 0x31bf, direction::L},
8617
    {0x31c0, 0x31e3, direction::ON},    {0x31f0, 0x321c, direction::L},
8618
    {0x321d, 0x321e, direction::ON},    {0x3220, 0x324f, direction::L},
8619
    {0x3250, 0x325f, direction::ON},    {0x3260, 0x327b, direction::L},
8620
    {0x327c, 0x327e, direction::ON},    {0x327f, 0x32b0, direction::L},
8621
    {0x32b1, 0x32bf, direction::ON},    {0x32c0, 0x32cb, direction::L},
8622
    {0x32cc, 0x32cf, direction::ON},    {0x32d0, 0x3376, direction::L},
8623
    {0x3377, 0x337a, direction::ON},    {0x337b, 0x33dd, direction::L},
8624
    {0x33de, 0x33df, direction::ON},    {0x33e0, 0x33fe, direction::L},
8625
    {0x33ff, 0x33ff, direction::ON},    {0x3400, 0x4dbf, direction::L},
8626
    {0x4dc0, 0x4dff, direction::ON},    {0x4e00, 0x9ffc, direction::L},
8627
    {0xa000, 0xa48c, direction::L},     {0xa490, 0xa4c6, direction::ON},
8628
    {0xa4d0, 0xa60c, direction::L},     {0xa60d, 0xa60f, direction::ON},
8629
    {0xa610, 0xa62b, direction::L},     {0xa640, 0xa66e, direction::L},
8630
    {0xa66f, 0xa672, direction::NSM},   {0xa673, 0xa673, direction::ON},
8631
    {0xa674, 0xa67d, direction::NSM},   {0xa67e, 0xa67f, direction::ON},
8632
    {0xa680, 0xa69d, direction::L},     {0xa69e, 0xa69f, direction::NSM},
8633
    {0xa6a0, 0xa6ef, direction::L},     {0xa6f0, 0xa6f1, direction::NSM},
8634
    {0xa6f2, 0xa6f7, direction::L},     {0xa700, 0xa721, direction::ON},
8635
    {0xa722, 0xa787, direction::L},     {0xa788, 0xa788, direction::ON},
8636
    {0xa789, 0xa7bf, direction::L},     {0xa7c2, 0xa7ca, direction::L},
8637
    {0xa7f5, 0xa801, direction::L},     {0xa802, 0xa802, direction::NSM},
8638
    {0xa803, 0xa805, direction::L},     {0xa806, 0xa806, direction::NSM},
8639
    {0xa807, 0xa80a, direction::L},     {0xa80b, 0xa80b, direction::NSM},
8640
    {0xa80c, 0xa824, direction::L},     {0xa825, 0xa826, direction::NSM},
8641
    {0xa827, 0xa827, direction::L},     {0xa828, 0xa82b, direction::ON},
8642
    {0xa82c, 0xa82c, direction::NSM},   {0xa830, 0xa837, direction::L},
8643
    {0xa838, 0xa839, direction::ET},    {0xa840, 0xa873, direction::L},
8644
    {0xa874, 0xa877, direction::ON},    {0xa880, 0xa8c3, direction::L},
8645
    {0xa8c4, 0xa8c5, direction::NSM},   {0xa8ce, 0xa8d9, direction::L},
8646
    {0xa8e0, 0xa8f1, direction::NSM},   {0xa8f2, 0xa8fe, direction::L},
8647
    {0xa8ff, 0xa8ff, direction::NSM},   {0xa900, 0xa925, direction::L},
8648
    {0xa926, 0xa92d, direction::NSM},   {0xa92e, 0xa946, direction::L},
8649
    {0xa947, 0xa951, direction::NSM},   {0xa952, 0xa953, direction::L},
8650
    {0xa95f, 0xa97c, direction::L},     {0xa980, 0xa982, direction::NSM},
8651
    {0xa983, 0xa9b2, direction::L},     {0xa9b3, 0xa9b3, direction::NSM},
8652
    {0xa9b4, 0xa9b5, direction::L},     {0xa9b6, 0xa9b9, direction::NSM},
8653
    {0xa9ba, 0xa9bb, direction::L},     {0xa9bc, 0xa9bd, direction::NSM},
8654
    {0xa9be, 0xa9cd, direction::L},     {0xa9cf, 0xa9d9, direction::L},
8655
    {0xa9de, 0xa9e4, direction::L},     {0xa9e5, 0xa9e5, direction::NSM},
8656
    {0xa9e6, 0xa9fe, direction::L},     {0xaa00, 0xaa28, direction::L},
8657
    {0xaa29, 0xaa2e, direction::NSM},   {0xaa2f, 0xaa30, direction::L},
8658
    {0xaa31, 0xaa32, direction::NSM},   {0xaa33, 0xaa34, direction::L},
8659
    {0xaa35, 0xaa36, direction::NSM},   {0xaa40, 0xaa42, direction::L},
8660
    {0xaa43, 0xaa43, direction::NSM},   {0xaa44, 0xaa4b, direction::L},
8661
    {0xaa4c, 0xaa4c, direction::NSM},   {0xaa4d, 0xaa4d, direction::L},
8662
    {0xaa50, 0xaa59, direction::L},     {0xaa5c, 0xaa7b, direction::L},
8663
    {0xaa7c, 0xaa7c, direction::NSM},   {0xaa7d, 0xaaaf, direction::L},
8664
    {0xaab0, 0xaab0, direction::NSM},   {0xaab1, 0xaab1, direction::L},
8665
    {0xaab2, 0xaab4, direction::NSM},   {0xaab5, 0xaab6, direction::L},
8666
    {0xaab7, 0xaab8, direction::NSM},   {0xaab9, 0xaabd, direction::L},
8667
    {0xaabe, 0xaabf, direction::NSM},   {0xaac0, 0xaac0, direction::L},
8668
    {0xaac1, 0xaac1, direction::NSM},   {0xaac2, 0xaac2, direction::L},
8669
    {0xaadb, 0xaaeb, direction::L},     {0xaaec, 0xaaed, direction::NSM},
8670
    {0xaaee, 0xaaf5, direction::L},     {0xaaf6, 0xaaf6, direction::NSM},
8671
    {0xab01, 0xab06, direction::L},     {0xab09, 0xab0e, direction::L},
8672
    {0xab11, 0xab16, direction::L},     {0xab20, 0xab26, direction::L},
8673
    {0xab28, 0xab2e, direction::L},     {0xab30, 0xab69, direction::L},
8674
    {0xab6a, 0xab6b, direction::ON},    {0xab70, 0xabe4, direction::L},
8675
    {0xabe5, 0xabe5, direction::NSM},   {0xabe6, 0xabe7, direction::L},
8676
    {0xabe8, 0xabe8, direction::NSM},   {0xabe9, 0xabec, direction::L},
8677
    {0xabed, 0xabed, direction::NSM},   {0xabf0, 0xabf9, direction::L},
8678
    {0xac00, 0xd7a3, direction::L},     {0xd7b0, 0xd7c6, direction::L},
8679
    {0xd7cb, 0xd7fb, direction::L},     {0xd800, 0xfa6d, direction::L},
8680
    {0xfa70, 0xfad9, direction::L},     {0xfb00, 0xfb06, direction::L},
8681
    {0xfb13, 0xfb17, direction::L},     {0xfb1d, 0xfb1d, direction::R},
8682
    {0xfb1e, 0xfb1e, direction::NSM},   {0xfb1f, 0xfb28, direction::R},
8683
    {0xfb29, 0xfb29, direction::ES},    {0xfb2a, 0xfb36, direction::R},
8684
    {0xfb38, 0xfb3c, direction::R},     {0xfb3e, 0xfb3e, direction::R},
8685
    {0xfb40, 0xfb41, direction::R},     {0xfb43, 0xfb44, direction::R},
8686
    {0xfb46, 0xfb4f, direction::R},     {0xfb50, 0xfbc1, direction::AL},
8687
    {0xfbd3, 0xfd3d, direction::AL},    {0xfd3e, 0xfd3f, direction::ON},
8688
    {0xfd50, 0xfd8f, direction::AL},    {0xfd92, 0xfdc7, direction::AL},
8689
    {0xfdf0, 0xfdfc, direction::AL},    {0xfdfd, 0xfdfd, direction::ON},
8690
    {0xfe00, 0xfe0f, direction::NSM},   {0xfe10, 0xfe19, direction::ON},
8691
    {0xfe20, 0xfe2f, direction::NSM},   {0xfe30, 0xfe4f, direction::ON},
8692
    {0xfe50, 0xfe50, direction::CS},    {0xfe51, 0xfe51, direction::ON},
8693
    {0xfe52, 0xfe52, direction::CS},    {0xfe54, 0xfe54, direction::ON},
8694
    {0xfe55, 0xfe55, direction::CS},    {0xfe56, 0xfe5e, direction::ON},
8695
    {0xfe5f, 0xfe5f, direction::ET},    {0xfe60, 0xfe61, direction::ON},
8696
    {0xfe62, 0xfe63, direction::ES},    {0xfe64, 0xfe66, direction::ON},
8697
    {0xfe68, 0xfe68, direction::ON},    {0xfe69, 0xfe6a, direction::ET},
8698
    {0xfe6b, 0xfe6b, direction::ON},    {0xfe70, 0xfe74, direction::AL},
8699
    {0xfe76, 0xfefc, direction::AL},    {0xfeff, 0xfeff, direction::BN},
8700
    {0xff01, 0xff02, direction::ON},    {0xff03, 0xff05, direction::ET},
8701
    {0xff06, 0xff0a, direction::ON},    {0xff0b, 0xff0b, direction::ES},
8702
    {0xff0c, 0xff0c, direction::CS},    {0xff0d, 0xff0d, direction::ES},
8703
    {0xff0e, 0xff0f, direction::CS},    {0xff10, 0xff19, direction::EN},
8704
    {0xff1a, 0xff1a, direction::CS},    {0xff1b, 0xff20, direction::ON},
8705
    {0xff21, 0xff3a, direction::L},     {0xff3b, 0xff40, direction::ON},
8706
    {0xff41, 0xff5a, direction::L},     {0xff5b, 0xff65, direction::ON},
8707
    {0xff66, 0xffbe, direction::L},     {0xffc2, 0xffc7, direction::L},
8708
    {0xffca, 0xffcf, direction::L},     {0xffd2, 0xffd7, direction::L},
8709
    {0xffda, 0xffdc, direction::L},     {0xffe0, 0xffe1, direction::ET},
8710
    {0xffe2, 0xffe4, direction::ON},    {0xffe5, 0xffe6, direction::ET},
8711
    {0xffe8, 0xffee, direction::ON},    {0xfff9, 0xfffd, direction::ON},
8712
    {0x10000, 0x1000b, direction::L},   {0x1000d, 0x10026, direction::L},
8713
    {0x10028, 0x1003a, direction::L},   {0x1003c, 0x1003d, direction::L},
8714
    {0x1003f, 0x1004d, direction::L},   {0x10050, 0x1005d, direction::L},
8715
    {0x10080, 0x100fa, direction::L},   {0x10100, 0x10100, direction::L},
8716
    {0x10101, 0x10101, direction::ON},  {0x10102, 0x10102, direction::L},
8717
    {0x10107, 0x10133, direction::L},   {0x10137, 0x1013f, direction::L},
8718
    {0x10140, 0x1018c, direction::ON},  {0x1018d, 0x1018e, direction::L},
8719
    {0x10190, 0x1019c, direction::ON},  {0x101a0, 0x101a0, direction::ON},
8720
    {0x101d0, 0x101fc, direction::L},   {0x101fd, 0x101fd, direction::NSM},
8721
    {0x10280, 0x1029c, direction::L},   {0x102a0, 0x102d0, direction::L},
8722
    {0x102e0, 0x102e0, direction::NSM}, {0x102e1, 0x102fb, direction::EN},
8723
    {0x10300, 0x10323, direction::L},   {0x1032d, 0x1034a, direction::L},
8724
    {0x10350, 0x10375, direction::L},   {0x10376, 0x1037a, direction::NSM},
8725
    {0x10380, 0x1039d, direction::L},   {0x1039f, 0x103c3, direction::L},
8726
    {0x103c8, 0x103d5, direction::L},   {0x10400, 0x1049d, direction::L},
8727
    {0x104a0, 0x104a9, direction::L},   {0x104b0, 0x104d3, direction::L},
8728
    {0x104d8, 0x104fb, direction::L},   {0x10500, 0x10527, direction::L},
8729
    {0x10530, 0x10563, direction::L},   {0x1056f, 0x1056f, direction::L},
8730
    {0x10600, 0x10736, direction::L},   {0x10740, 0x10755, direction::L},
8731
    {0x10760, 0x10767, direction::L},   {0x10800, 0x10805, direction::R},
8732
    {0x10808, 0x10808, direction::R},   {0x1080a, 0x10835, direction::R},
8733
    {0x10837, 0x10838, direction::R},   {0x1083c, 0x1083c, direction::R},
8734
    {0x1083f, 0x10855, direction::R},   {0x10857, 0x1089e, direction::R},
8735
    {0x108a7, 0x108af, direction::R},   {0x108e0, 0x108f2, direction::R},
8736
    {0x108f4, 0x108f5, direction::R},   {0x108fb, 0x1091b, direction::R},
8737
    {0x1091f, 0x1091f, direction::ON},  {0x10920, 0x10939, direction::R},
8738
    {0x1093f, 0x1093f, direction::R},   {0x10980, 0x109b7, direction::R},
8739
    {0x109bc, 0x109cf, direction::R},   {0x109d2, 0x10a00, direction::R},
8740
    {0x10a01, 0x10a03, direction::NSM}, {0x10a05, 0x10a06, direction::NSM},
8741
    {0x10a0c, 0x10a0f, direction::NSM}, {0x10a10, 0x10a13, direction::R},
8742
    {0x10a15, 0x10a17, direction::R},   {0x10a19, 0x10a35, direction::R},
8743
    {0x10a38, 0x10a3a, direction::NSM}, {0x10a3f, 0x10a3f, direction::NSM},
8744
    {0x10a40, 0x10a48, direction::R},   {0x10a50, 0x10a58, direction::R},
8745
    {0x10a60, 0x10a9f, direction::R},   {0x10ac0, 0x10ae4, direction::R},
8746
    {0x10ae5, 0x10ae6, direction::NSM}, {0x10aeb, 0x10af6, direction::R},
8747
    {0x10b00, 0x10b35, direction::R},   {0x10b39, 0x10b3f, direction::ON},
8748
    {0x10b40, 0x10b55, direction::R},   {0x10b58, 0x10b72, direction::R},
8749
    {0x10b78, 0x10b91, direction::R},   {0x10b99, 0x10b9c, direction::R},
8750
    {0x10ba9, 0x10baf, direction::R},   {0x10c00, 0x10c48, direction::R},
8751
    {0x10c80, 0x10cb2, direction::R},   {0x10cc0, 0x10cf2, direction::R},
8752
    {0x10cfa, 0x10cff, direction::R},   {0x10d00, 0x10d23, direction::AL},
8753
    {0x10d24, 0x10d27, direction::NSM}, {0x10d30, 0x10d39, direction::AN},
8754
    {0x10e60, 0x10e7e, direction::AN},  {0x10e80, 0x10ea9, direction::R},
8755
    {0x10eab, 0x10eac, direction::NSM}, {0x10ead, 0x10ead, direction::R},
8756
    {0x10eb0, 0x10eb1, direction::R},   {0x10f00, 0x10f27, direction::R},
8757
    {0x10f30, 0x10f45, direction::AL},  {0x10f46, 0x10f50, direction::NSM},
8758
    {0x10f51, 0x10f59, direction::AL},  {0x10fb0, 0x10fcb, direction::R},
8759
    {0x10fe0, 0x10ff6, direction::R},   {0x11000, 0x11000, direction::L},
8760
    {0x11001, 0x11001, direction::NSM}, {0x11002, 0x11037, direction::L},
8761
    {0x11038, 0x11046, direction::NSM}, {0x11047, 0x1104d, direction::L},
8762
    {0x11052, 0x11065, direction::ON},  {0x11066, 0x1106f, direction::L},
8763
    {0x1107f, 0x11081, direction::NSM}, {0x11082, 0x110b2, direction::L},
8764
    {0x110b3, 0x110b6, direction::NSM}, {0x110b7, 0x110b8, direction::L},
8765
    {0x110b9, 0x110ba, direction::NSM}, {0x110bb, 0x110c1, direction::L},
8766
    {0x110cd, 0x110cd, direction::L},   {0x110d0, 0x110e8, direction::L},
8767
    {0x110f0, 0x110f9, direction::L},   {0x11100, 0x11102, direction::NSM},
8768
    {0x11103, 0x11126, direction::L},   {0x11127, 0x1112b, direction::NSM},
8769
    {0x1112c, 0x1112c, direction::L},   {0x1112d, 0x11134, direction::NSM},
8770
    {0x11136, 0x11147, direction::L},   {0x11150, 0x11172, direction::L},
8771
    {0x11173, 0x11173, direction::NSM}, {0x11174, 0x11176, direction::L},
8772
    {0x11180, 0x11181, direction::NSM}, {0x11182, 0x111b5, direction::L},
8773
    {0x111b6, 0x111be, direction::NSM}, {0x111bf, 0x111c8, direction::L},
8774
    {0x111c9, 0x111cc, direction::NSM}, {0x111cd, 0x111ce, direction::L},
8775
    {0x111cf, 0x111cf, direction::NSM}, {0x111d0, 0x111df, direction::L},
8776
    {0x111e1, 0x111f4, direction::L},   {0x11200, 0x11211, direction::L},
8777
    {0x11213, 0x1122e, direction::L},   {0x1122f, 0x11231, direction::NSM},
8778
    {0x11232, 0x11233, direction::L},   {0x11234, 0x11234, direction::NSM},
8779
    {0x11235, 0x11235, direction::L},   {0x11236, 0x11237, direction::NSM},
8780
    {0x11238, 0x1123d, direction::L},   {0x1123e, 0x1123e, direction::NSM},
8781
    {0x11280, 0x11286, direction::L},   {0x11288, 0x11288, direction::L},
8782
    {0x1128a, 0x1128d, direction::L},   {0x1128f, 0x1129d, direction::L},
8783
    {0x1129f, 0x112a9, direction::L},   {0x112b0, 0x112de, direction::L},
8784
    {0x112df, 0x112df, direction::NSM}, {0x112e0, 0x112e2, direction::L},
8785
    {0x112e3, 0x112ea, direction::NSM}, {0x112f0, 0x112f9, direction::L},
8786
    {0x11300, 0x11301, direction::NSM}, {0x11302, 0x11303, direction::L},
8787
    {0x11305, 0x1130c, direction::L},   {0x1130f, 0x11310, direction::L},
8788
    {0x11313, 0x11328, direction::L},   {0x1132a, 0x11330, direction::L},
8789
    {0x11332, 0x11333, direction::L},   {0x11335, 0x11339, direction::L},
8790
    {0x1133b, 0x1133c, direction::NSM}, {0x1133d, 0x1133f, direction::L},
8791
    {0x11340, 0x11340, direction::NSM}, {0x11341, 0x11344, direction::L},
8792
    {0x11347, 0x11348, direction::L},   {0x1134b, 0x1134d, direction::L},
8793
    {0x11350, 0x11350, direction::L},   {0x11357, 0x11357, direction::L},
8794
    {0x1135d, 0x11363, direction::L},   {0x11366, 0x1136c, direction::NSM},
8795
    {0x11370, 0x11374, direction::NSM}, {0x11400, 0x11437, direction::L},
8796
    {0x11438, 0x1143f, direction::NSM}, {0x11440, 0x11441, direction::L},
8797
    {0x11442, 0x11444, direction::NSM}, {0x11445, 0x11445, direction::L},
8798
    {0x11446, 0x11446, direction::NSM}, {0x11447, 0x1145b, direction::L},
8799
    {0x1145d, 0x1145d, direction::L},   {0x1145e, 0x1145e, direction::NSM},
8800
    {0x1145f, 0x11461, direction::L},   {0x11480, 0x114b2, direction::L},
8801
    {0x114b3, 0x114b8, direction::NSM}, {0x114b9, 0x114b9, direction::L},
8802
    {0x114ba, 0x114ba, direction::NSM}, {0x114bb, 0x114be, direction::L},
8803
    {0x114bf, 0x114c0, direction::NSM}, {0x114c1, 0x114c1, direction::L},
8804
    {0x114c2, 0x114c3, direction::NSM}, {0x114c4, 0x114c7, direction::L},
8805
    {0x114d0, 0x114d9, direction::L},   {0x11580, 0x115b1, direction::L},
8806
    {0x115b2, 0x115b5, direction::NSM}, {0x115b8, 0x115bb, direction::L},
8807
    {0x115bc, 0x115bd, direction::NSM}, {0x115be, 0x115be, direction::L},
8808
    {0x115bf, 0x115c0, direction::NSM}, {0x115c1, 0x115db, direction::L},
8809
    {0x115dc, 0x115dd, direction::NSM}, {0x11600, 0x11632, direction::L},
8810
    {0x11633, 0x1163a, direction::NSM}, {0x1163b, 0x1163c, direction::L},
8811
    {0x1163d, 0x1163d, direction::NSM}, {0x1163e, 0x1163e, direction::L},
8812
    {0x1163f, 0x11640, direction::NSM}, {0x11641, 0x11644, direction::L},
8813
    {0x11650, 0x11659, direction::L},   {0x11660, 0x1166c, direction::ON},
8814
    {0x11680, 0x116aa, direction::L},   {0x116ab, 0x116ab, direction::NSM},
8815
    {0x116ac, 0x116ac, direction::L},   {0x116ad, 0x116ad, direction::NSM},
8816
    {0x116ae, 0x116af, direction::L},   {0x116b0, 0x116b5, direction::NSM},
8817
    {0x116b6, 0x116b6, direction::L},   {0x116b7, 0x116b7, direction::NSM},
8818
    {0x116b8, 0x116b8, direction::L},   {0x116c0, 0x116c9, direction::L},
8819
    {0x11700, 0x1171a, direction::L},   {0x1171d, 0x1171f, direction::NSM},
8820
    {0x11720, 0x11721, direction::L},   {0x11722, 0x11725, direction::NSM},
8821
    {0x11726, 0x11726, direction::L},   {0x11727, 0x1172b, direction::NSM},
8822
    {0x11730, 0x1173f, direction::L},   {0x11800, 0x1182e, direction::L},
8823
    {0x1182f, 0x11837, direction::NSM}, {0x11838, 0x11838, direction::L},
8824
    {0x11839, 0x1183a, direction::NSM}, {0x1183b, 0x1183b, direction::L},
8825
    {0x118a0, 0x118f2, direction::L},   {0x118ff, 0x11906, direction::L},
8826
    {0x11909, 0x11909, direction::L},   {0x1190c, 0x11913, direction::L},
8827
    {0x11915, 0x11916, direction::L},   {0x11918, 0x11935, direction::L},
8828
    {0x11937, 0x11938, direction::L},   {0x1193b, 0x1193c, direction::NSM},
8829
    {0x1193d, 0x1193d, direction::L},   {0x1193e, 0x1193e, direction::NSM},
8830
    {0x1193f, 0x11942, direction::L},   {0x11943, 0x11943, direction::NSM},
8831
    {0x11944, 0x11946, direction::L},   {0x11950, 0x11959, direction::L},
8832
    {0x119a0, 0x119a7, direction::L},   {0x119aa, 0x119d3, direction::L},
8833
    {0x119d4, 0x119d7, direction::NSM}, {0x119da, 0x119db, direction::NSM},
8834
    {0x119dc, 0x119df, direction::L},   {0x119e0, 0x119e0, direction::NSM},
8835
    {0x119e1, 0x119e4, direction::L},   {0x11a00, 0x11a00, direction::L},
8836
    {0x11a01, 0x11a06, direction::NSM}, {0x11a07, 0x11a08, direction::L},
8837
    {0x11a09, 0x11a0a, direction::NSM}, {0x11a0b, 0x11a32, direction::L},
8838
    {0x11a33, 0x11a38, direction::NSM}, {0x11a39, 0x11a3a, direction::L},
8839
    {0x11a3b, 0x11a3e, direction::NSM}, {0x11a3f, 0x11a46, direction::L},
8840
    {0x11a47, 0x11a47, direction::NSM}, {0x11a50, 0x11a50, direction::L},
8841
    {0x11a51, 0x11a56, direction::NSM}, {0x11a57, 0x11a58, direction::L},
8842
    {0x11a59, 0x11a5b, direction::NSM}, {0x11a5c, 0x11a89, direction::L},
8843
    {0x11a8a, 0x11a96, direction::NSM}, {0x11a97, 0x11a97, direction::L},
8844
    {0x11a98, 0x11a99, direction::NSM}, {0x11a9a, 0x11aa2, direction::L},
8845
    {0x11ac0, 0x11af8, direction::L},   {0x11c00, 0x11c08, direction::L},
8846
    {0x11c0a, 0x11c2f, direction::L},   {0x11c30, 0x11c36, direction::NSM},
8847
    {0x11c38, 0x11c3d, direction::NSM}, {0x11c3e, 0x11c45, direction::L},
8848
    {0x11c50, 0x11c6c, direction::L},   {0x11c70, 0x11c8f, direction::L},
8849
    {0x11c92, 0x11ca7, direction::NSM}, {0x11ca9, 0x11ca9, direction::L},
8850
    {0x11caa, 0x11cb0, direction::NSM}, {0x11cb1, 0x11cb1, direction::L},
8851
    {0x11cb2, 0x11cb3, direction::NSM}, {0x11cb4, 0x11cb4, direction::L},
8852
    {0x11cb5, 0x11cb6, direction::NSM}, {0x11d00, 0x11d06, direction::L},
8853
    {0x11d08, 0x11d09, direction::L},   {0x11d0b, 0x11d30, direction::L},
8854
    {0x11d31, 0x11d36, direction::NSM}, {0x11d3a, 0x11d3a, direction::NSM},
8855
    {0x11d3c, 0x11d3d, direction::NSM}, {0x11d3f, 0x11d45, direction::NSM},
8856
    {0x11d46, 0x11d46, direction::L},   {0x11d47, 0x11d47, direction::NSM},
8857
    {0x11d50, 0x11d59, direction::L},   {0x11d60, 0x11d65, direction::L},
8858
    {0x11d67, 0x11d68, direction::L},   {0x11d6a, 0x11d8e, direction::L},
8859
    {0x11d90, 0x11d91, direction::NSM}, {0x11d93, 0x11d94, direction::L},
8860
    {0x11d95, 0x11d95, direction::NSM}, {0x11d96, 0x11d96, direction::L},
8861
    {0x11d97, 0x11d97, direction::NSM}, {0x11d98, 0x11d98, direction::L},
8862
    {0x11da0, 0x11da9, direction::L},   {0x11ee0, 0x11ef2, direction::L},
8863
    {0x11ef3, 0x11ef4, direction::NSM}, {0x11ef5, 0x11ef8, direction::L},
8864
    {0x11fb0, 0x11fb0, direction::L},   {0x11fc0, 0x11fd4, direction::L},
8865
    {0x11fd5, 0x11fdc, direction::ON},  {0x11fdd, 0x11fe0, direction::ET},
8866
    {0x11fe1, 0x11ff1, direction::ON},  {0x11fff, 0x12399, direction::L},
8867
    {0x12400, 0x1246e, direction::L},   {0x12470, 0x12474, direction::L},
8868
    {0x12480, 0x12543, direction::L},   {0x13000, 0x1342e, direction::L},
8869
    {0x13430, 0x13438, direction::L},   {0x14400, 0x14646, direction::L},
8870
    {0x16800, 0x16a38, direction::L},   {0x16a40, 0x16a5e, direction::L},
8871
    {0x16a60, 0x16a69, direction::L},   {0x16a6e, 0x16a6f, direction::L},
8872
    {0x16ad0, 0x16aed, direction::L},   {0x16af0, 0x16af4, direction::NSM},
8873
    {0x16af5, 0x16af5, direction::L},   {0x16b00, 0x16b2f, direction::L},
8874
    {0x16b30, 0x16b36, direction::NSM}, {0x16b37, 0x16b45, direction::L},
8875
    {0x16b50, 0x16b59, direction::L},   {0x16b5b, 0x16b61, direction::L},
8876
    {0x16b63, 0x16b77, direction::L},   {0x16b7d, 0x16b8f, direction::L},
8877
    {0x16e40, 0x16e9a, direction::L},   {0x16f00, 0x16f4a, direction::L},
8878
    {0x16f4f, 0x16f4f, direction::NSM}, {0x16f50, 0x16f87, direction::L},
8879
    {0x16f8f, 0x16f92, direction::NSM}, {0x16f93, 0x16f9f, direction::L},
8880
    {0x16fe0, 0x16fe1, direction::L},   {0x16fe2, 0x16fe2, direction::ON},
8881
    {0x16fe3, 0x16fe3, direction::L},   {0x16fe4, 0x16fe4, direction::NSM},
8882
    {0x16ff0, 0x16ff1, direction::L},   {0x17000, 0x187f7, direction::L},
8883
    {0x18800, 0x18cd5, direction::L},   {0x18d00, 0x18d08, direction::L},
8884
    {0x1b000, 0x1b11e, direction::L},   {0x1b150, 0x1b152, direction::L},
8885
    {0x1b164, 0x1b167, direction::L},   {0x1b170, 0x1b2fb, direction::L},
8886
    {0x1bc00, 0x1bc6a, direction::L},   {0x1bc70, 0x1bc7c, direction::L},
8887
    {0x1bc80, 0x1bc88, direction::L},   {0x1bc90, 0x1bc99, direction::L},
8888
    {0x1bc9c, 0x1bc9c, direction::L},   {0x1bc9d, 0x1bc9e, direction::NSM},
8889
    {0x1bc9f, 0x1bc9f, direction::L},   {0x1bca0, 0x1bca3, direction::BN},
8890
    {0x1d000, 0x1d0f5, direction::L},   {0x1d100, 0x1d126, direction::L},
8891
    {0x1d129, 0x1d166, direction::L},   {0x1d167, 0x1d169, direction::NSM},
8892
    {0x1d16a, 0x1d172, direction::L},   {0x1d173, 0x1d17a, direction::BN},
8893
    {0x1d17b, 0x1d182, direction::NSM}, {0x1d183, 0x1d184, direction::L},
8894
    {0x1d185, 0x1d18b, direction::NSM}, {0x1d18c, 0x1d1a9, direction::L},
8895
    {0x1d1aa, 0x1d1ad, direction::NSM}, {0x1d1ae, 0x1d1e8, direction::L},
8896
    {0x1d200, 0x1d241, direction::ON},  {0x1d242, 0x1d244, direction::NSM},
8897
    {0x1d245, 0x1d245, direction::ON},  {0x1d2e0, 0x1d2f3, direction::L},
8898
    {0x1d300, 0x1d356, direction::ON},  {0x1d360, 0x1d378, direction::L},
8899
    {0x1d400, 0x1d454, direction::L},   {0x1d456, 0x1d49c, direction::L},
8900
    {0x1d49e, 0x1d49f, direction::L},   {0x1d4a2, 0x1d4a2, direction::L},
8901
    {0x1d4a5, 0x1d4a6, direction::L},   {0x1d4a9, 0x1d4ac, direction::L},
8902
    {0x1d4ae, 0x1d4b9, direction::L},   {0x1d4bb, 0x1d4bb, direction::L},
8903
    {0x1d4bd, 0x1d4c3, direction::L},   {0x1d4c5, 0x1d505, direction::L},
8904
    {0x1d507, 0x1d50a, direction::L},   {0x1d50d, 0x1d514, direction::L},
8905
    {0x1d516, 0x1d51c, direction::L},   {0x1d51e, 0x1d539, direction::L},
8906
    {0x1d53b, 0x1d53e, direction::L},   {0x1d540, 0x1d544, direction::L},
8907
    {0x1d546, 0x1d546, direction::L},   {0x1d54a, 0x1d550, direction::L},
8908
    {0x1d552, 0x1d6a5, direction::L},   {0x1d6a8, 0x1d6da, direction::L},
8909
    {0x1d6db, 0x1d6db, direction::ON},  {0x1d6dc, 0x1d714, direction::L},
8910
    {0x1d715, 0x1d715, direction::ON},  {0x1d716, 0x1d74e, direction::L},
8911
    {0x1d74f, 0x1d74f, direction::ON},  {0x1d750, 0x1d788, direction::L},
8912
    {0x1d789, 0x1d789, direction::ON},  {0x1d78a, 0x1d7c2, direction::L},
8913
    {0x1d7c3, 0x1d7c3, direction::ON},  {0x1d7c4, 0x1d7cb, direction::L},
8914
    {0x1d7ce, 0x1d7ff, direction::EN},  {0x1d800, 0x1d9ff, direction::L},
8915
    {0x1da00, 0x1da36, direction::NSM}, {0x1da37, 0x1da3a, direction::L},
8916
    {0x1da3b, 0x1da6c, direction::NSM}, {0x1da6d, 0x1da74, direction::L},
8917
    {0x1da75, 0x1da75, direction::NSM}, {0x1da76, 0x1da83, direction::L},
8918
    {0x1da84, 0x1da84, direction::NSM}, {0x1da85, 0x1da8b, direction::L},
8919
    {0x1da9b, 0x1da9f, direction::NSM}, {0x1daa1, 0x1daaf, direction::NSM},
8920
    {0x1e000, 0x1e006, direction::NSM}, {0x1e008, 0x1e018, direction::NSM},
8921
    {0x1e01b, 0x1e021, direction::NSM}, {0x1e023, 0x1e024, direction::NSM},
8922
    {0x1e026, 0x1e02a, direction::NSM}, {0x1e100, 0x1e12c, direction::L},
8923
    {0x1e130, 0x1e136, direction::NSM}, {0x1e137, 0x1e13d, direction::L},
8924
    {0x1e140, 0x1e149, direction::L},   {0x1e14e, 0x1e14f, direction::L},
8925
    {0x1e2c0, 0x1e2eb, direction::L},   {0x1e2ec, 0x1e2ef, direction::NSM},
8926
    {0x1e2f0, 0x1e2f9, direction::L},   {0x1e2ff, 0x1e2ff, direction::ET},
8927
    {0x1e800, 0x1e8c4, direction::R},   {0x1e8c7, 0x1e8cf, direction::R},
8928
    {0x1e8d0, 0x1e8d6, direction::NSM}, {0x1e900, 0x1e943, direction::R},
8929
    {0x1e944, 0x1e94a, direction::NSM}, {0x1e94b, 0x1e94b, direction::R},
8930
    {0x1e950, 0x1e959, direction::R},   {0x1e95e, 0x1e95f, direction::R},
8931
    {0x1ec71, 0x1ecb4, direction::AL},  {0x1ed01, 0x1ed3d, direction::AL},
8932
    {0x1ee00, 0x1ee03, direction::AL},  {0x1ee05, 0x1ee1f, direction::AL},
8933
    {0x1ee21, 0x1ee22, direction::AL},  {0x1ee24, 0x1ee24, direction::AL},
8934
    {0x1ee27, 0x1ee27, direction::AL},  {0x1ee29, 0x1ee32, direction::AL},
8935
    {0x1ee34, 0x1ee37, direction::AL},  {0x1ee39, 0x1ee39, direction::AL},
8936
    {0x1ee3b, 0x1ee3b, direction::AL},  {0x1ee42, 0x1ee42, direction::AL},
8937
    {0x1ee47, 0x1ee47, direction::AL},  {0x1ee49, 0x1ee49, direction::AL},
8938
    {0x1ee4b, 0x1ee4b, direction::AL},  {0x1ee4d, 0x1ee4f, direction::AL},
8939
    {0x1ee51, 0x1ee52, direction::AL},  {0x1ee54, 0x1ee54, direction::AL},
8940
    {0x1ee57, 0x1ee57, direction::AL},  {0x1ee59, 0x1ee59, direction::AL},
8941
    {0x1ee5b, 0x1ee5b, direction::AL},  {0x1ee5d, 0x1ee5d, direction::AL},
8942
    {0x1ee5f, 0x1ee5f, direction::AL},  {0x1ee61, 0x1ee62, direction::AL},
8943
    {0x1ee64, 0x1ee64, direction::AL},  {0x1ee67, 0x1ee6a, direction::AL},
8944
    {0x1ee6c, 0x1ee72, direction::AL},  {0x1ee74, 0x1ee77, direction::AL},
8945
    {0x1ee79, 0x1ee7c, direction::AL},  {0x1ee7e, 0x1ee7e, direction::AL},
8946
    {0x1ee80, 0x1ee89, direction::AL},  {0x1ee8b, 0x1ee9b, direction::AL},
8947
    {0x1eea1, 0x1eea3, direction::AL},  {0x1eea5, 0x1eea9, direction::AL},
8948
    {0x1eeab, 0x1eebb, direction::AL},  {0x1eef0, 0x1eef1, direction::ON},
8949
    {0x1f000, 0x1f02b, direction::ON},  {0x1f030, 0x1f093, direction::ON},
8950
    {0x1f0a0, 0x1f0ae, direction::ON},  {0x1f0b1, 0x1f0bf, direction::ON},
8951
    {0x1f0c1, 0x1f0cf, direction::ON},  {0x1f0d1, 0x1f0f5, direction::ON},
8952
    {0x1f100, 0x1f10a, direction::EN},  {0x1f10b, 0x1f10f, direction::ON},
8953
    {0x1f110, 0x1f12e, direction::L},   {0x1f12f, 0x1f12f, direction::ON},
8954
    {0x1f130, 0x1f169, direction::L},   {0x1f16a, 0x1f16f, direction::ON},
8955
    {0x1f170, 0x1f1ac, direction::L},   {0x1f1ad, 0x1f1ad, direction::ON},
8956
    {0x1f1e6, 0x1f202, direction::L},   {0x1f210, 0x1f23b, direction::L},
8957
    {0x1f240, 0x1f248, direction::L},   {0x1f250, 0x1f251, direction::L},
8958
    {0x1f260, 0x1f265, direction::ON},  {0x1f300, 0x1f6d7, direction::ON},
8959
    {0x1f6e0, 0x1f6ec, direction::ON},  {0x1f6f0, 0x1f6fc, direction::ON},
8960
    {0x1f700, 0x1f773, direction::ON},  {0x1f780, 0x1f7d8, direction::ON},
8961
    {0x1f7e0, 0x1f7eb, direction::ON},  {0x1f800, 0x1f80b, direction::ON},
8962
    {0x1f810, 0x1f847, direction::ON},  {0x1f850, 0x1f859, direction::ON},
8963
    {0x1f860, 0x1f887, direction::ON},  {0x1f890, 0x1f8ad, direction::ON},
8964
    {0x1f8b0, 0x1f8b1, direction::ON},  {0x1f900, 0x1f978, direction::ON},
8965
    {0x1f97a, 0x1f9cb, direction::ON},  {0x1f9cd, 0x1fa53, direction::ON},
8966
    {0x1fa60, 0x1fa6d, direction::ON},  {0x1fa70, 0x1fa74, direction::ON},
8967
    {0x1fa78, 0x1fa7a, direction::ON},  {0x1fa80, 0x1fa86, direction::ON},
8968
    {0x1fa90, 0x1faa8, direction::ON},  {0x1fab0, 0x1fab6, direction::ON},
8969
    {0x1fac0, 0x1fac2, direction::ON},  {0x1fad0, 0x1fad6, direction::ON},
8970
    {0x1fb00, 0x1fb92, direction::ON},  {0x1fb94, 0x1fbca, direction::ON},
8971
    {0x1fbf0, 0x1fbf9, direction::EN},  {0x20000, 0x2a6dd, direction::L},
8972
    {0x2a700, 0x2b734, direction::L},   {0x2b740, 0x2b81d, direction::L},
8973
    {0x2b820, 0x2cea1, direction::L},   {0x2ceb0, 0x2ebe0, direction::L},
8974
    {0x2f800, 0x2fa1d, direction::L},   {0x30000, 0x3134a, direction::L},
8975
    {0xe0001, 0xe0001, direction::BN},  {0xe0020, 0xe007f, direction::BN},
8976
    {0xe0100, 0xe01ef, direction::NSM}, {0xf0000, 0xffffd, direction::L},
8977
    {0x100000, 0x10fffd, direction::L}};
8978
8979
// CheckJoiners and CheckBidi are true for URL specification.
8980
8981
95.1k
inline static direction find_direction(uint32_t code_point) noexcept {
8982
95.1k
  auto it = std::lower_bound(
8983
95.1k
      std::begin(dir_table), std::end(dir_table), code_point,
8984
989k
      [](const directions& d, uint32_t c) { return d.final_code < c; });
8985
8986
  // next check is almost surely in vain, but we use it for safety.
8987
95.1k
  if (it == std::end(dir_table)) {
8988
0
    return direction::NONE;
8989
0
  }
8990
  // We have that d.final_code >= c.
8991
95.1k
  if (code_point >= it->start_code) {
8992
93.9k
    return it->direct;
8993
93.9k
  }
8994
1.15k
  return direction::NONE;
8995
95.1k
}
8996
8997
inline static size_t find_last_not_of_nsm(
8998
11.3k
    const std::u32string_view label) noexcept {
8999
12.3k
  for (int i = static_cast<int>(label.size() - 1); i >= 0; i--)
9000
12.3k
    if (find_direction(label[i]) != direction::NSM) return i;
9001
9002
0
  return std::u32string_view::npos;
9003
11.3k
}
9004
9005
// An RTL label is a label that contains at least one character of type R, AL,
9006
// or AN. https://www.rfc-editor.org/rfc/rfc5893#section-2
9007
11.3k
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
9008
11.3k
  const size_t mask =
9009
11.3k
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
9010
9011
11.3k
  size_t directions = 0;
9012
84.6k
  for (size_t i = 0; i < label.size(); i++) {
9013
73.2k
    directions |= 1u << find_direction(label[i]);
9014
73.2k
  }
9015
11.3k
  return (directions & mask) != 0;
9016
11.3k
}
9017
9018
12.6k
bool is_label_valid(const std::u32string_view label) {
9019
12.6k
  if (label.empty()) {
9020
0
    return true;
9021
0
  }
9022
9023
  ///////////////
9024
  // We have a normalization step which ensures that we are in NFC.
9025
  // If we receive punycode, we normalize and check that the normalized
9026
  // version matches the original.
9027
  // --------------------------------------
9028
  // The label must be in Unicode Normalization Form NFC.
9029
9030
  // Current URL standard indicatest that CheckHyphens is set to false.
9031
  // ---------------------------------------
9032
  // If CheckHyphens, the label must not contain a U+002D HYPHEN-MINUS character
9033
  // in both the third and fourth positions. If CheckHyphens, the label must
9034
  // neither begin nor end with a U+002D HYPHEN-MINUS character.
9035
9036
  // This is not necessary because we segment the
9037
  // labels by '.'.
9038
  // ---------------------------------------
9039
  // The label must not contain a U+002E ( . ) FULL STOP.
9040
  // if (label.find('.') != std::string_view::npos) return false;
9041
9042
  // The label must not begin with a combining mark, that is:
9043
  // General_Category=Mark.
9044
12.6k
  constexpr static uint32_t combining[] = {
9045
12.6k
      0x300,   0x301,   0x302,   0x303,   0x304,   0x305,   0x306,   0x307,
9046
12.6k
      0x308,   0x309,   0x30a,   0x30b,   0x30c,   0x30d,   0x30e,   0x30f,
9047
12.6k
      0x310,   0x311,   0x312,   0x313,   0x314,   0x315,   0x316,   0x317,
9048
12.6k
      0x318,   0x319,   0x31a,   0x31b,   0x31c,   0x31d,   0x31e,   0x31f,
9049
12.6k
      0x320,   0x321,   0x322,   0x323,   0x324,   0x325,   0x326,   0x327,
9050
12.6k
      0x328,   0x329,   0x32a,   0x32b,   0x32c,   0x32d,   0x32e,   0x32f,
9051
12.6k
      0x330,   0x331,   0x332,   0x333,   0x334,   0x335,   0x336,   0x337,
9052
12.6k
      0x338,   0x339,   0x33a,   0x33b,   0x33c,   0x33d,   0x33e,   0x33f,
9053
12.6k
      0x340,   0x341,   0x342,   0x343,   0x344,   0x345,   0x346,   0x347,
9054
12.6k
      0x348,   0x349,   0x34a,   0x34b,   0x34c,   0x34d,   0x34e,   0x34f,
9055
12.6k
      0x350,   0x351,   0x352,   0x353,   0x354,   0x355,   0x356,   0x357,
9056
12.6k
      0x358,   0x359,   0x35a,   0x35b,   0x35c,   0x35d,   0x35e,   0x35f,
9057
12.6k
      0x360,   0x361,   0x362,   0x363,   0x364,   0x365,   0x366,   0x367,
9058
12.6k
      0x368,   0x369,   0x36a,   0x36b,   0x36c,   0x36d,   0x36e,   0x36f,
9059
12.6k
      0x483,   0x484,   0x485,   0x486,   0x487,   0x488,   0x489,   0x591,
9060
12.6k
      0x592,   0x593,   0x594,   0x595,   0x596,   0x597,   0x598,   0x599,
9061
12.6k
      0x59a,   0x59b,   0x59c,   0x59d,   0x59e,   0x59f,   0x5a0,   0x5a1,
9062
12.6k
      0x5a2,   0x5a3,   0x5a4,   0x5a5,   0x5a6,   0x5a7,   0x5a8,   0x5a9,
9063
12.6k
      0x5aa,   0x5ab,   0x5ac,   0x5ad,   0x5ae,   0x5af,   0x5b0,   0x5b1,
9064
12.6k
      0x5b2,   0x5b3,   0x5b4,   0x5b5,   0x5b6,   0x5b7,   0x5b8,   0x5b9,
9065
12.6k
      0x5ba,   0x5bb,   0x5bc,   0x5bd,   0x5bf,   0x5c1,   0x5c2,   0x5c4,
9066
12.6k
      0x5c5,   0x5c7,   0x610,   0x611,   0x612,   0x613,   0x614,   0x615,
9067
12.6k
      0x616,   0x617,   0x618,   0x619,   0x61a,   0x64b,   0x64c,   0x64d,
9068
12.6k
      0x64e,   0x64f,   0x650,   0x651,   0x652,   0x653,   0x654,   0x655,
9069
12.6k
      0x656,   0x657,   0x658,   0x659,   0x65a,   0x65b,   0x65c,   0x65d,
9070
12.6k
      0x65e,   0x65f,   0x670,   0x6d6,   0x6d7,   0x6d8,   0x6d9,   0x6da,
9071
12.6k
      0x6db,   0x6dc,   0x6df,   0x6e0,   0x6e1,   0x6e2,   0x6e3,   0x6e4,
9072
12.6k
      0x6e7,   0x6e8,   0x6ea,   0x6eb,   0x6ec,   0x6ed,   0x711,   0x730,
9073
12.6k
      0x731,   0x732,   0x733,   0x734,   0x735,   0x736,   0x737,   0x738,
9074
12.6k
      0x739,   0x73a,   0x73b,   0x73c,   0x73d,   0x73e,   0x73f,   0x740,
9075
12.6k
      0x741,   0x742,   0x743,   0x744,   0x745,   0x746,   0x747,   0x748,
9076
12.6k
      0x749,   0x74a,   0x7a6,   0x7a7,   0x7a8,   0x7a9,   0x7aa,   0x7ab,
9077
12.6k
      0x7ac,   0x7ad,   0x7ae,   0x7af,   0x7b0,   0x7eb,   0x7ec,   0x7ed,
9078
12.6k
      0x7ee,   0x7ef,   0x7f0,   0x7f1,   0x7f2,   0x7f3,   0x7fd,   0x816,
9079
12.6k
      0x817,   0x818,   0x819,   0x81b,   0x81c,   0x81d,   0x81e,   0x81f,
9080
12.6k
      0x820,   0x821,   0x822,   0x823,   0x825,   0x826,   0x827,   0x829,
9081
12.6k
      0x82a,   0x82b,   0x82c,   0x82d,   0x859,   0x85a,   0x85b,   0x8d3,
9082
12.6k
      0x8d4,   0x8d5,   0x8d6,   0x8d7,   0x8d8,   0x8d9,   0x8da,   0x8db,
9083
12.6k
      0x8dc,   0x8dd,   0x8de,   0x8df,   0x8e0,   0x8e1,   0x8e3,   0x8e4,
9084
12.6k
      0x8e5,   0x8e6,   0x8e7,   0x8e8,   0x8e9,   0x8ea,   0x8eb,   0x8ec,
9085
12.6k
      0x8ed,   0x8ee,   0x8ef,   0x8f0,   0x8f1,   0x8f2,   0x8f3,   0x8f4,
9086
12.6k
      0x8f5,   0x8f6,   0x8f7,   0x8f8,   0x8f9,   0x8fa,   0x8fb,   0x8fc,
9087
12.6k
      0x8fd,   0x8fe,   0x8ff,   0x900,   0x901,   0x902,   0x903,   0x93a,
9088
12.6k
      0x93b,   0x93c,   0x93e,   0x93f,   0x940,   0x941,   0x942,   0x943,
9089
12.6k
      0x944,   0x945,   0x946,   0x947,   0x948,   0x949,   0x94a,   0x94b,
9090
12.6k
      0x94c,   0x94d,   0x94e,   0x94f,   0x951,   0x952,   0x953,   0x954,
9091
12.6k
      0x955,   0x956,   0x957,   0x962,   0x963,   0x981,   0x982,   0x983,
9092
12.6k
      0x9bc,   0x9be,   0x9bf,   0x9c0,   0x9c1,   0x9c2,   0x9c3,   0x9c4,
9093
12.6k
      0x9c7,   0x9c8,   0x9cb,   0x9cc,   0x9cd,   0x9d7,   0x9e2,   0x9e3,
9094
12.6k
      0x9fe,   0xa01,   0xa02,   0xa03,   0xa3c,   0xa3e,   0xa3f,   0xa40,
9095
12.6k
      0xa41,   0xa42,   0xa47,   0xa48,   0xa4b,   0xa4c,   0xa4d,   0xa51,
9096
12.6k
      0xa70,   0xa71,   0xa75,   0xa81,   0xa82,   0xa83,   0xabc,   0xabe,
9097
12.6k
      0xabf,   0xac0,   0xac1,   0xac2,   0xac3,   0xac4,   0xac5,   0xac7,
9098
12.6k
      0xac8,   0xac9,   0xacb,   0xacc,   0xacd,   0xae2,   0xae3,   0xafa,
9099
12.6k
      0xafb,   0xafc,   0xafd,   0xafe,   0xaff,   0xb01,   0xb02,   0xb03,
9100
12.6k
      0xb3c,   0xb3e,   0xb3f,   0xb40,   0xb41,   0xb42,   0xb43,   0xb44,
9101
12.6k
      0xb47,   0xb48,   0xb4b,   0xb4c,   0xb4d,   0xb55,   0xb56,   0xb57,
9102
12.6k
      0xb62,   0xb63,   0xb82,   0xbbe,   0xbbf,   0xbc0,   0xbc1,   0xbc2,
9103
12.6k
      0xbc6,   0xbc7,   0xbc8,   0xbca,   0xbcb,   0xbcc,   0xbcd,   0xbd7,
9104
12.6k
      0xc00,   0xc01,   0xc02,   0xc03,   0xc04,   0xc3e,   0xc3f,   0xc40,
9105
12.6k
      0xc41,   0xc42,   0xc43,   0xc44,   0xc46,   0xc47,   0xc48,   0xc4a,
9106
12.6k
      0xc4b,   0xc4c,   0xc4d,   0xc55,   0xc56,   0xc62,   0xc63,   0xc81,
9107
12.6k
      0xc82,   0xc83,   0xcbc,   0xcbe,   0xcbf,   0xcc0,   0xcc1,   0xcc2,
9108
12.6k
      0xcc3,   0xcc4,   0xcc6,   0xcc7,   0xcc8,   0xcca,   0xccb,   0xccc,
9109
12.6k
      0xccd,   0xcd5,   0xcd6,   0xce2,   0xce3,   0xd00,   0xd01,   0xd02,
9110
12.6k
      0xd03,   0xd3b,   0xd3c,   0xd3e,   0xd3f,   0xd40,   0xd41,   0xd42,
9111
12.6k
      0xd43,   0xd44,   0xd46,   0xd47,   0xd48,   0xd4a,   0xd4b,   0xd4c,
9112
12.6k
      0xd4d,   0xd57,   0xd62,   0xd63,   0xd81,   0xd82,   0xd83,   0xdca,
9113
12.6k
      0xdcf,   0xdd0,   0xdd1,   0xdd2,   0xdd3,   0xdd4,   0xdd6,   0xdd8,
9114
12.6k
      0xdd9,   0xdda,   0xddb,   0xddc,   0xddd,   0xdde,   0xddf,   0xdf2,
9115
12.6k
      0xdf3,   0xe31,   0xe34,   0xe35,   0xe36,   0xe37,   0xe38,   0xe39,
9116
12.6k
      0xe3a,   0xe47,   0xe48,   0xe49,   0xe4a,   0xe4b,   0xe4c,   0xe4d,
9117
12.6k
      0xe4e,   0xeb1,   0xeb4,   0xeb5,   0xeb6,   0xeb7,   0xeb8,   0xeb9,
9118
12.6k
      0xeba,   0xebb,   0xebc,   0xec8,   0xec9,   0xeca,   0xecb,   0xecc,
9119
12.6k
      0xecd,   0xf18,   0xf19,   0xf35,   0xf37,   0xf39,   0xf3e,   0xf3f,
9120
12.6k
      0xf71,   0xf72,   0xf73,   0xf74,   0xf75,   0xf76,   0xf77,   0xf78,
9121
12.6k
      0xf79,   0xf7a,   0xf7b,   0xf7c,   0xf7d,   0xf7e,   0xf7f,   0xf80,
9122
12.6k
      0xf81,   0xf82,   0xf83,   0xf84,   0xf86,   0xf87,   0xf8d,   0xf8e,
9123
12.6k
      0xf8f,   0xf90,   0xf91,   0xf92,   0xf93,   0xf94,   0xf95,   0xf96,
9124
12.6k
      0xf97,   0xf99,   0xf9a,   0xf9b,   0xf9c,   0xf9d,   0xf9e,   0xf9f,
9125
12.6k
      0xfa0,   0xfa1,   0xfa2,   0xfa3,   0xfa4,   0xfa5,   0xfa6,   0xfa7,
9126
12.6k
      0xfa8,   0xfa9,   0xfaa,   0xfab,   0xfac,   0xfad,   0xfae,   0xfaf,
9127
12.6k
      0xfb0,   0xfb1,   0xfb2,   0xfb3,   0xfb4,   0xfb5,   0xfb6,   0xfb7,
9128
12.6k
      0xfb8,   0xfb9,   0xfba,   0xfbb,   0xfbc,   0xfc6,   0x102b,  0x102c,
9129
12.6k
      0x102d,  0x102e,  0x102f,  0x1030,  0x1031,  0x1032,  0x1033,  0x1034,
9130
12.6k
      0x1035,  0x1036,  0x1037,  0x1038,  0x1039,  0x103a,  0x103b,  0x103c,
9131
12.6k
      0x103d,  0x103e,  0x1056,  0x1057,  0x1058,  0x1059,  0x105e,  0x105f,
9132
12.6k
      0x1060,  0x1062,  0x1063,  0x1064,  0x1067,  0x1068,  0x1069,  0x106a,
9133
12.6k
      0x106b,  0x106c,  0x106d,  0x1071,  0x1072,  0x1073,  0x1074,  0x1082,
9134
12.6k
      0x1083,  0x1084,  0x1085,  0x1086,  0x1087,  0x1088,  0x1089,  0x108a,
9135
12.6k
      0x108b,  0x108c,  0x108d,  0x108f,  0x109a,  0x109b,  0x109c,  0x109d,
9136
12.6k
      0x135d,  0x135e,  0x135f,  0x1712,  0x1713,  0x1714,  0x1732,  0x1733,
9137
12.6k
      0x1734,  0x1752,  0x1753,  0x1772,  0x1773,  0x17b4,  0x17b5,  0x17b6,
9138
12.6k
      0x17b7,  0x17b8,  0x17b9,  0x17ba,  0x17bb,  0x17bc,  0x17bd,  0x17be,
9139
12.6k
      0x17bf,  0x17c0,  0x17c1,  0x17c2,  0x17c3,  0x17c4,  0x17c5,  0x17c6,
9140
12.6k
      0x17c7,  0x17c8,  0x17c9,  0x17ca,  0x17cb,  0x17cc,  0x17cd,  0x17ce,
9141
12.6k
      0x17cf,  0x17d0,  0x17d1,  0x17d2,  0x17d3,  0x17dd,  0x180b,  0x180c,
9142
12.6k
      0x180d,  0x1885,  0x1886,  0x18a9,  0x1920,  0x1921,  0x1922,  0x1923,
9143
12.6k
      0x1924,  0x1925,  0x1926,  0x1927,  0x1928,  0x1929,  0x192a,  0x192b,
9144
12.6k
      0x1930,  0x1931,  0x1932,  0x1933,  0x1934,  0x1935,  0x1936,  0x1937,
9145
12.6k
      0x1938,  0x1939,  0x193a,  0x193b,  0x1a17,  0x1a18,  0x1a19,  0x1a1a,
9146
12.6k
      0x1a1b,  0x1a55,  0x1a56,  0x1a57,  0x1a58,  0x1a59,  0x1a5a,  0x1a5b,
9147
12.6k
      0x1a5c,  0x1a5d,  0x1a5e,  0x1a60,  0x1a61,  0x1a62,  0x1a63,  0x1a64,
9148
12.6k
      0x1a65,  0x1a66,  0x1a67,  0x1a68,  0x1a69,  0x1a6a,  0x1a6b,  0x1a6c,
9149
12.6k
      0x1a6d,  0x1a6e,  0x1a6f,  0x1a70,  0x1a71,  0x1a72,  0x1a73,  0x1a74,
9150
12.6k
      0x1a75,  0x1a76,  0x1a77,  0x1a78,  0x1a79,  0x1a7a,  0x1a7b,  0x1a7c,
9151
12.6k
      0x1a7f,  0x1ab0,  0x1ab1,  0x1ab2,  0x1ab3,  0x1ab4,  0x1ab5,  0x1ab6,
9152
12.6k
      0x1ab7,  0x1ab8,  0x1ab9,  0x1aba,  0x1abb,  0x1abc,  0x1abd,  0x1abe,
9153
12.6k
      0x1abf,  0x1ac0,  0x1b00,  0x1b01,  0x1b02,  0x1b03,  0x1b04,  0x1b34,
9154
12.6k
      0x1b35,  0x1b36,  0x1b37,  0x1b38,  0x1b39,  0x1b3a,  0x1b3b,  0x1b3c,
9155
12.6k
      0x1b3d,  0x1b3e,  0x1b3f,  0x1b40,  0x1b41,  0x1b42,  0x1b43,  0x1b44,
9156
12.6k
      0x1b6b,  0x1b6c,  0x1b6d,  0x1b6e,  0x1b6f,  0x1b70,  0x1b71,  0x1b72,
9157
12.6k
      0x1b73,  0x1b80,  0x1b81,  0x1b82,  0x1ba1,  0x1ba2,  0x1ba3,  0x1ba4,
9158
12.6k
      0x1ba5,  0x1ba6,  0x1ba7,  0x1ba8,  0x1ba9,  0x1baa,  0x1bab,  0x1bac,
9159
12.6k
      0x1bad,  0x1be6,  0x1be7,  0x1be8,  0x1be9,  0x1bea,  0x1beb,  0x1bec,
9160
12.6k
      0x1bed,  0x1bee,  0x1bef,  0x1bf0,  0x1bf1,  0x1bf2,  0x1bf3,  0x1c24,
9161
12.6k
      0x1c25,  0x1c26,  0x1c27,  0x1c28,  0x1c29,  0x1c2a,  0x1c2b,  0x1c2c,
9162
12.6k
      0x1c2d,  0x1c2e,  0x1c2f,  0x1c30,  0x1c31,  0x1c32,  0x1c33,  0x1c34,
9163
12.6k
      0x1c35,  0x1c36,  0x1c37,  0x1cd0,  0x1cd1,  0x1cd2,  0x1cd4,  0x1cd5,
9164
12.6k
      0x1cd6,  0x1cd7,  0x1cd8,  0x1cd9,  0x1cda,  0x1cdb,  0x1cdc,  0x1cdd,
9165
12.6k
      0x1cde,  0x1cdf,  0x1ce0,  0x1ce1,  0x1ce2,  0x1ce3,  0x1ce4,  0x1ce5,
9166
12.6k
      0x1ce6,  0x1ce7,  0x1ce8,  0x1ced,  0x1cf4,  0x1cf7,  0x1cf8,  0x1cf9,
9167
12.6k
      0x1dc0,  0x1dc1,  0x1dc2,  0x1dc3,  0x1dc4,  0x1dc5,  0x1dc6,  0x1dc7,
9168
12.6k
      0x1dc8,  0x1dc9,  0x1dca,  0x1dcb,  0x1dcc,  0x1dcd,  0x1dce,  0x1dcf,
9169
12.6k
      0x1dd0,  0x1dd1,  0x1dd2,  0x1dd3,  0x1dd4,  0x1dd5,  0x1dd6,  0x1dd7,
9170
12.6k
      0x1dd8,  0x1dd9,  0x1dda,  0x1ddb,  0x1ddc,  0x1ddd,  0x1dde,  0x1ddf,
9171
12.6k
      0x1de0,  0x1de1,  0x1de2,  0x1de3,  0x1de4,  0x1de5,  0x1de6,  0x1de7,
9172
12.6k
      0x1de8,  0x1de9,  0x1dea,  0x1deb,  0x1dec,  0x1ded,  0x1dee,  0x1def,
9173
12.6k
      0x1df0,  0x1df1,  0x1df2,  0x1df3,  0x1df4,  0x1df5,  0x1df6,  0x1df7,
9174
12.6k
      0x1df8,  0x1df9,  0x1dfb,  0x1dfc,  0x1dfd,  0x1dfe,  0x1dff,  0x20d0,
9175
12.6k
      0x20d1,  0x20d2,  0x20d3,  0x20d4,  0x20d5,  0x20d6,  0x20d7,  0x20d8,
9176
12.6k
      0x20d9,  0x20da,  0x20db,  0x20dc,  0x20dd,  0x20de,  0x20df,  0x20e0,
9177
12.6k
      0x20e1,  0x20e2,  0x20e3,  0x20e4,  0x20e5,  0x20e6,  0x20e7,  0x20e8,
9178
12.6k
      0x20e9,  0x20ea,  0x20eb,  0x20ec,  0x20ed,  0x20ee,  0x20ef,  0x20f0,
9179
12.6k
      0x2cef,  0x2cf0,  0x2cf1,  0x2d7f,  0x2de0,  0x2de1,  0x2de2,  0x2de3,
9180
12.6k
      0x2de4,  0x2de5,  0x2de6,  0x2de7,  0x2de8,  0x2de9,  0x2dea,  0x2deb,
9181
12.6k
      0x2dec,  0x2ded,  0x2dee,  0x2def,  0x2df0,  0x2df1,  0x2df2,  0x2df3,
9182
12.6k
      0x2df4,  0x2df5,  0x2df6,  0x2df7,  0x2df8,  0x2df9,  0x2dfa,  0x2dfb,
9183
12.6k
      0x2dfc,  0x2dfd,  0x2dfe,  0x2dff,  0x302a,  0x302b,  0x302c,  0x302d,
9184
12.6k
      0x302e,  0x302f,  0x3099,  0x309a,  0xa66f,  0xa670,  0xa671,  0xa672,
9185
12.6k
      0xa674,  0xa675,  0xa676,  0xa677,  0xa678,  0xa679,  0xa67a,  0xa67b,
9186
12.6k
      0xa67c,  0xa67d,  0xa69e,  0xa69f,  0xa6f0,  0xa6f1,  0xa802,  0xa806,
9187
12.6k
      0xa80b,  0xa823,  0xa824,  0xa825,  0xa826,  0xa827,  0xa82c,  0xa880,
9188
12.6k
      0xa881,  0xa8b4,  0xa8b5,  0xa8b6,  0xa8b7,  0xa8b8,  0xa8b9,  0xa8ba,
9189
12.6k
      0xa8bb,  0xa8bc,  0xa8bd,  0xa8be,  0xa8bf,  0xa8c0,  0xa8c1,  0xa8c2,
9190
12.6k
      0xa8c3,  0xa8c4,  0xa8c5,  0xa8e0,  0xa8e1,  0xa8e2,  0xa8e3,  0xa8e4,
9191
12.6k
      0xa8e5,  0xa8e6,  0xa8e7,  0xa8e8,  0xa8e9,  0xa8ea,  0xa8eb,  0xa8ec,
9192
12.6k
      0xa8ed,  0xa8ee,  0xa8ef,  0xa8f0,  0xa8f1,  0xa8ff,  0xa926,  0xa927,
9193
12.6k
      0xa928,  0xa929,  0xa92a,  0xa92b,  0xa92c,  0xa92d,  0xa947,  0xa948,
9194
12.6k
      0xa949,  0xa94a,  0xa94b,  0xa94c,  0xa94d,  0xa94e,  0xa94f,  0xa950,
9195
12.6k
      0xa951,  0xa952,  0xa953,  0xa980,  0xa981,  0xa982,  0xa983,  0xa9b3,
9196
12.6k
      0xa9b4,  0xa9b5,  0xa9b6,  0xa9b7,  0xa9b8,  0xa9b9,  0xa9ba,  0xa9bb,
9197
12.6k
      0xa9bc,  0xa9bd,  0xa9be,  0xa9bf,  0xa9c0,  0xa9e5,  0xaa29,  0xaa2a,
9198
12.6k
      0xaa2b,  0xaa2c,  0xaa2d,  0xaa2e,  0xaa2f,  0xaa30,  0xaa31,  0xaa32,
9199
12.6k
      0xaa33,  0xaa34,  0xaa35,  0xaa36,  0xaa43,  0xaa4c,  0xaa4d,  0xaa7b,
9200
12.6k
      0xaa7c,  0xaa7d,  0xaab0,  0xaab2,  0xaab3,  0xaab4,  0xaab7,  0xaab8,
9201
12.6k
      0xaabe,  0xaabf,  0xaac1,  0xaaeb,  0xaaec,  0xaaed,  0xaaee,  0xaaef,
9202
12.6k
      0xaaf5,  0xaaf6,  0xabe3,  0xabe4,  0xabe5,  0xabe6,  0xabe7,  0xabe8,
9203
12.6k
      0xabe9,  0xabea,  0xabec,  0xabed,  0xfb1e,  0xfe00,  0xfe01,  0xfe02,
9204
12.6k
      0xfe03,  0xfe04,  0xfe05,  0xfe06,  0xfe07,  0xfe08,  0xfe09,  0xfe0a,
9205
12.6k
      0xfe0b,  0xfe0c,  0xfe0d,  0xfe0e,  0xfe0f,  0xfe20,  0xfe21,  0xfe22,
9206
12.6k
      0xfe23,  0xfe24,  0xfe25,  0xfe26,  0xfe27,  0xfe28,  0xfe29,  0xfe2a,
9207
12.6k
      0xfe2b,  0xfe2c,  0xfe2d,  0xfe2e,  0xfe2f,  0x101fd, 0x102e0, 0x10376,
9208
12.6k
      0x10377, 0x10378, 0x10379, 0x1037a, 0x10a01, 0x10a02, 0x10a03, 0x10a05,
9209
12.6k
      0x10a06, 0x10a0c, 0x10a0d, 0x10a0e, 0x10a0f, 0x10a38, 0x10a39, 0x10a3a,
9210
12.6k
      0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d25, 0x10d26, 0x10d27, 0x10eab,
9211
12.6k
      0x10eac, 0x10f46, 0x10f47, 0x10f48, 0x10f49, 0x10f4a, 0x10f4b, 0x10f4c,
9212
12.6k
      0x10f4d, 0x10f4e, 0x10f4f, 0x10f50, 0x11000, 0x11001, 0x11002, 0x11038,
9213
12.6k
      0x11039, 0x1103a, 0x1103b, 0x1103c, 0x1103d, 0x1103e, 0x1103f, 0x11040,
9214
12.6k
      0x11041, 0x11042, 0x11043, 0x11044, 0x11045, 0x11046, 0x1107f, 0x11080,
9215
12.6k
      0x11081, 0x11082, 0x110b0, 0x110b1, 0x110b2, 0x110b3, 0x110b4, 0x110b5,
9216
12.6k
      0x110b6, 0x110b7, 0x110b8, 0x110b9, 0x110ba, 0x11100, 0x11101, 0x11102,
9217
12.6k
      0x11127, 0x11128, 0x11129, 0x1112a, 0x1112b, 0x1112c, 0x1112d, 0x1112e,
9218
12.6k
      0x1112f, 0x11130, 0x11131, 0x11132, 0x11133, 0x11134, 0x11145, 0x11146,
9219
12.6k
      0x11173, 0x11180, 0x11181, 0x11182, 0x111b3, 0x111b4, 0x111b5, 0x111b6,
9220
12.6k
      0x111b7, 0x111b8, 0x111b9, 0x111ba, 0x111bb, 0x111bc, 0x111bd, 0x111be,
9221
12.6k
      0x111bf, 0x111c0, 0x111c9, 0x111ca, 0x111cb, 0x111cc, 0x111ce, 0x111cf,
9222
12.6k
      0x1122c, 0x1122d, 0x1122e, 0x1122f, 0x11230, 0x11231, 0x11232, 0x11233,
9223
12.6k
      0x11234, 0x11235, 0x11236, 0x11237, 0x1123e, 0x112df, 0x112e0, 0x112e1,
9224
12.6k
      0x112e2, 0x112e3, 0x112e4, 0x112e5, 0x112e6, 0x112e7, 0x112e8, 0x112e9,
9225
12.6k
      0x112ea, 0x11300, 0x11301, 0x11302, 0x11303, 0x1133b, 0x1133c, 0x1133e,
9226
12.6k
      0x1133f, 0x11340, 0x11341, 0x11342, 0x11343, 0x11344, 0x11347, 0x11348,
9227
12.6k
      0x1134b, 0x1134c, 0x1134d, 0x11357, 0x11362, 0x11363, 0x11366, 0x11367,
9228
12.6k
      0x11368, 0x11369, 0x1136a, 0x1136b, 0x1136c, 0x11370, 0x11371, 0x11372,
9229
12.6k
      0x11373, 0x11374, 0x11435, 0x11436, 0x11437, 0x11438, 0x11439, 0x1143a,
9230
12.6k
      0x1143b, 0x1143c, 0x1143d, 0x1143e, 0x1143f, 0x11440, 0x11441, 0x11442,
9231
12.6k
      0x11443, 0x11444, 0x11445, 0x11446, 0x1145e, 0x114b0, 0x114b1, 0x114b2,
9232
12.6k
      0x114b3, 0x114b4, 0x114b5, 0x114b6, 0x114b7, 0x114b8, 0x114b9, 0x114ba,
9233
12.6k
      0x114bb, 0x114bc, 0x114bd, 0x114be, 0x114bf, 0x114c0, 0x114c1, 0x114c2,
9234
12.6k
      0x114c3, 0x115af, 0x115b0, 0x115b1, 0x115b2, 0x115b3, 0x115b4, 0x115b5,
9235
12.6k
      0x115b8, 0x115b9, 0x115ba, 0x115bb, 0x115bc, 0x115bd, 0x115be, 0x115bf,
9236
12.6k
      0x115c0, 0x115dc, 0x115dd, 0x11630, 0x11631, 0x11632, 0x11633, 0x11634,
9237
12.6k
      0x11635, 0x11636, 0x11637, 0x11638, 0x11639, 0x1163a, 0x1163b, 0x1163c,
9238
12.6k
      0x1163d, 0x1163e, 0x1163f, 0x11640, 0x116ab, 0x116ac, 0x116ad, 0x116ae,
9239
12.6k
      0x116af, 0x116b0, 0x116b1, 0x116b2, 0x116b3, 0x116b4, 0x116b5, 0x116b6,
9240
12.6k
      0x116b7, 0x1171d, 0x1171e, 0x1171f, 0x11720, 0x11721, 0x11722, 0x11723,
9241
12.6k
      0x11724, 0x11725, 0x11726, 0x11727, 0x11728, 0x11729, 0x1172a, 0x1172b,
9242
12.6k
      0x1182c, 0x1182d, 0x1182e, 0x1182f, 0x11830, 0x11831, 0x11832, 0x11833,
9243
12.6k
      0x11834, 0x11835, 0x11836, 0x11837, 0x11838, 0x11839, 0x1183a, 0x11930,
9244
12.6k
      0x11931, 0x11932, 0x11933, 0x11934, 0x11935, 0x11937, 0x11938, 0x1193b,
9245
12.6k
      0x1193c, 0x1193d, 0x1193e, 0x11940, 0x11942, 0x11943, 0x119d1, 0x119d2,
9246
12.6k
      0x119d3, 0x119d4, 0x119d5, 0x119d6, 0x119d7, 0x119da, 0x119db, 0x119dc,
9247
12.6k
      0x119dd, 0x119de, 0x119df, 0x119e0, 0x119e4, 0x11a01, 0x11a02, 0x11a03,
9248
12.6k
      0x11a04, 0x11a05, 0x11a06, 0x11a07, 0x11a08, 0x11a09, 0x11a0a, 0x11a33,
9249
12.6k
      0x11a34, 0x11a35, 0x11a36, 0x11a37, 0x11a38, 0x11a39, 0x11a3b, 0x11a3c,
9250
12.6k
      0x11a3d, 0x11a3e, 0x11a47, 0x11a51, 0x11a52, 0x11a53, 0x11a54, 0x11a55,
9251
12.6k
      0x11a56, 0x11a57, 0x11a58, 0x11a59, 0x11a5a, 0x11a5b, 0x11a8a, 0x11a8b,
9252
12.6k
      0x11a8c, 0x11a8d, 0x11a8e, 0x11a8f, 0x11a90, 0x11a91, 0x11a92, 0x11a93,
9253
12.6k
      0x11a94, 0x11a95, 0x11a96, 0x11a97, 0x11a98, 0x11a99, 0x11c2f, 0x11c30,
9254
12.6k
      0x11c31, 0x11c32, 0x11c33, 0x11c34, 0x11c35, 0x11c36, 0x11c38, 0x11c39,
9255
12.6k
      0x11c3a, 0x11c3b, 0x11c3c, 0x11c3d, 0x11c3e, 0x11c3f, 0x11c92, 0x11c93,
9256
12.6k
      0x11c94, 0x11c95, 0x11c96, 0x11c97, 0x11c98, 0x11c99, 0x11c9a, 0x11c9b,
9257
12.6k
      0x11c9c, 0x11c9d, 0x11c9e, 0x11c9f, 0x11ca0, 0x11ca1, 0x11ca2, 0x11ca3,
9258
12.6k
      0x11ca4, 0x11ca5, 0x11ca6, 0x11ca7, 0x11ca9, 0x11caa, 0x11cab, 0x11cac,
9259
12.6k
      0x11cad, 0x11cae, 0x11caf, 0x11cb0, 0x11cb1, 0x11cb2, 0x11cb3, 0x11cb4,
9260
12.6k
      0x11cb5, 0x11cb6, 0x11d31, 0x11d32, 0x11d33, 0x11d34, 0x11d35, 0x11d36,
9261
12.6k
      0x11d3a, 0x11d3c, 0x11d3d, 0x11d3f, 0x11d40, 0x11d41, 0x11d42, 0x11d43,
9262
12.6k
      0x11d44, 0x11d45, 0x11d47, 0x11d8a, 0x11d8b, 0x11d8c, 0x11d8d, 0x11d8e,
9263
12.6k
      0x11d90, 0x11d91, 0x11d93, 0x11d94, 0x11d95, 0x11d96, 0x11d97, 0x11ef3,
9264
12.6k
      0x11ef4, 0x11ef5, 0x11ef6, 0x16af0, 0x16af1, 0x16af2, 0x16af3, 0x16af4,
9265
12.6k
      0x16b30, 0x16b31, 0x16b32, 0x16b33, 0x16b34, 0x16b35, 0x16b36, 0x16f4f,
9266
12.6k
      0x16f51, 0x16f52, 0x16f53, 0x16f54, 0x16f55, 0x16f56, 0x16f57, 0x16f58,
9267
12.6k
      0x16f59, 0x16f5a, 0x16f5b, 0x16f5c, 0x16f5d, 0x16f5e, 0x16f5f, 0x16f60,
9268
12.6k
      0x16f61, 0x16f62, 0x16f63, 0x16f64, 0x16f65, 0x16f66, 0x16f67, 0x16f68,
9269
12.6k
      0x16f69, 0x16f6a, 0x16f6b, 0x16f6c, 0x16f6d, 0x16f6e, 0x16f6f, 0x16f70,
9270
12.6k
      0x16f71, 0x16f72, 0x16f73, 0x16f74, 0x16f75, 0x16f76, 0x16f77, 0x16f78,
9271
12.6k
      0x16f79, 0x16f7a, 0x16f7b, 0x16f7c, 0x16f7d, 0x16f7e, 0x16f7f, 0x16f80,
9272
12.6k
      0x16f81, 0x16f82, 0x16f83, 0x16f84, 0x16f85, 0x16f86, 0x16f87, 0x16f8f,
9273
12.6k
      0x16f90, 0x16f91, 0x16f92, 0x16fe4, 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e,
9274
12.6k
      0x1d165, 0x1d166, 0x1d167, 0x1d168, 0x1d169, 0x1d16d, 0x1d16e, 0x1d16f,
9275
12.6k
      0x1d170, 0x1d171, 0x1d172, 0x1d17b, 0x1d17c, 0x1d17d, 0x1d17e, 0x1d17f,
9276
12.6k
      0x1d180, 0x1d181, 0x1d182, 0x1d185, 0x1d186, 0x1d187, 0x1d188, 0x1d189,
9277
12.6k
      0x1d18a, 0x1d18b, 0x1d1aa, 0x1d1ab, 0x1d1ac, 0x1d1ad, 0x1d242, 0x1d243,
9278
12.6k
      0x1d244, 0x1da00, 0x1da01, 0x1da02, 0x1da03, 0x1da04, 0x1da05, 0x1da06,
9279
12.6k
      0x1da07, 0x1da08, 0x1da09, 0x1da0a, 0x1da0b, 0x1da0c, 0x1da0d, 0x1da0e,
9280
12.6k
      0x1da0f, 0x1da10, 0x1da11, 0x1da12, 0x1da13, 0x1da14, 0x1da15, 0x1da16,
9281
12.6k
      0x1da17, 0x1da18, 0x1da19, 0x1da1a, 0x1da1b, 0x1da1c, 0x1da1d, 0x1da1e,
9282
12.6k
      0x1da1f, 0x1da20, 0x1da21, 0x1da22, 0x1da23, 0x1da24, 0x1da25, 0x1da26,
9283
12.6k
      0x1da27, 0x1da28, 0x1da29, 0x1da2a, 0x1da2b, 0x1da2c, 0x1da2d, 0x1da2e,
9284
12.6k
      0x1da2f, 0x1da30, 0x1da31, 0x1da32, 0x1da33, 0x1da34, 0x1da35, 0x1da36,
9285
12.6k
      0x1da3b, 0x1da3c, 0x1da3d, 0x1da3e, 0x1da3f, 0x1da40, 0x1da41, 0x1da42,
9286
12.6k
      0x1da43, 0x1da44, 0x1da45, 0x1da46, 0x1da47, 0x1da48, 0x1da49, 0x1da4a,
9287
12.6k
      0x1da4b, 0x1da4c, 0x1da4d, 0x1da4e, 0x1da4f, 0x1da50, 0x1da51, 0x1da52,
9288
12.6k
      0x1da53, 0x1da54, 0x1da55, 0x1da56, 0x1da57, 0x1da58, 0x1da59, 0x1da5a,
9289
12.6k
      0x1da5b, 0x1da5c, 0x1da5d, 0x1da5e, 0x1da5f, 0x1da60, 0x1da61, 0x1da62,
9290
12.6k
      0x1da63, 0x1da64, 0x1da65, 0x1da66, 0x1da67, 0x1da68, 0x1da69, 0x1da6a,
9291
12.6k
      0x1da6b, 0x1da6c, 0x1da75, 0x1da84, 0x1da9b, 0x1da9c, 0x1da9d, 0x1da9e,
9292
12.6k
      0x1da9f, 0x1daa1, 0x1daa2, 0x1daa3, 0x1daa4, 0x1daa5, 0x1daa6, 0x1daa7,
9293
12.6k
      0x1daa8, 0x1daa9, 0x1daaa, 0x1daab, 0x1daac, 0x1daad, 0x1daae, 0x1daaf,
9294
12.6k
      0x1e000, 0x1e001, 0x1e002, 0x1e003, 0x1e004, 0x1e005, 0x1e006, 0x1e008,
9295
12.6k
      0x1e009, 0x1e00a, 0x1e00b, 0x1e00c, 0x1e00d, 0x1e00e, 0x1e00f, 0x1e010,
9296
12.6k
      0x1e011, 0x1e012, 0x1e013, 0x1e014, 0x1e015, 0x1e016, 0x1e017, 0x1e018,
9297
12.6k
      0x1e01b, 0x1e01c, 0x1e01d, 0x1e01e, 0x1e01f, 0x1e020, 0x1e021, 0x1e023,
9298
12.6k
      0x1e024, 0x1e026, 0x1e027, 0x1e028, 0x1e029, 0x1e02a, 0x1e130, 0x1e131,
9299
12.6k
      0x1e132, 0x1e133, 0x1e134, 0x1e135, 0x1e136, 0x1e2ec, 0x1e2ed, 0x1e2ee,
9300
12.6k
      0x1e2ef, 0x1e8d0, 0x1e8d1, 0x1e8d2, 0x1e8d3, 0x1e8d4, 0x1e8d5, 0x1e8d6,
9301
12.6k
      0x1e944, 0x1e945, 0x1e946, 0x1e947, 0x1e948, 0x1e949, 0x1e94a, 0xe0100,
9302
12.6k
      0xe0101, 0xe0102, 0xe0103, 0xe0104, 0xe0105, 0xe0106, 0xe0107, 0xe0108,
9303
12.6k
      0xe0109, 0xe010a, 0xe010b, 0xe010c, 0xe010d, 0xe010e, 0xe010f, 0xe0110,
9304
12.6k
      0xe0111, 0xe0112, 0xe0113, 0xe0114, 0xe0115, 0xe0116, 0xe0117, 0xe0118,
9305
12.6k
      0xe0119, 0xe011a, 0xe011b, 0xe011c, 0xe011d, 0xe011e, 0xe011f, 0xe0120,
9306
12.6k
      0xe0121, 0xe0122, 0xe0123, 0xe0124, 0xe0125, 0xe0126, 0xe0127, 0xe0128,
9307
12.6k
      0xe0129, 0xe012a, 0xe012b, 0xe012c, 0xe012d, 0xe012e, 0xe012f, 0xe0130,
9308
12.6k
      0xe0131, 0xe0132, 0xe0133, 0xe0134, 0xe0135, 0xe0136, 0xe0137, 0xe0138,
9309
12.6k
      0xe0139, 0xe013a, 0xe013b, 0xe013c, 0xe013d, 0xe013e, 0xe013f, 0xe0140,
9310
12.6k
      0xe0141, 0xe0142, 0xe0143, 0xe0144, 0xe0145, 0xe0146, 0xe0147, 0xe0148,
9311
12.6k
      0xe0149, 0xe014a, 0xe014b, 0xe014c, 0xe014d, 0xe014e, 0xe014f, 0xe0150,
9312
12.6k
      0xe0151, 0xe0152, 0xe0153, 0xe0154, 0xe0155, 0xe0156, 0xe0157, 0xe0158,
9313
12.6k
      0xe0159, 0xe015a, 0xe015b, 0xe015c, 0xe015d, 0xe015e, 0xe015f, 0xe0160,
9314
12.6k
      0xe0161, 0xe0162, 0xe0163, 0xe0164, 0xe0165, 0xe0166, 0xe0167, 0xe0168,
9315
12.6k
      0xe0169, 0xe016a, 0xe016b, 0xe016c, 0xe016d, 0xe016e, 0xe016f, 0xe0170,
9316
12.6k
      0xe0171, 0xe0172, 0xe0173, 0xe0174, 0xe0175, 0xe0176, 0xe0177, 0xe0178,
9317
12.6k
      0xe0179, 0xe017a, 0xe017b, 0xe017c, 0xe017d, 0xe017e, 0xe017f, 0xe0180,
9318
12.6k
      0xe0181, 0xe0182, 0xe0183, 0xe0184, 0xe0185, 0xe0186, 0xe0187, 0xe0188,
9319
12.6k
      0xe0189, 0xe018a, 0xe018b, 0xe018c, 0xe018d, 0xe018e, 0xe018f, 0xe0190,
9320
12.6k
      0xe0191, 0xe0192, 0xe0193, 0xe0194, 0xe0195, 0xe0196, 0xe0197, 0xe0198,
9321
12.6k
      0xe0199, 0xe019a, 0xe019b, 0xe019c, 0xe019d, 0xe019e, 0xe019f, 0xe01a0,
9322
12.6k
      0xe01a1, 0xe01a2, 0xe01a3, 0xe01a4, 0xe01a5, 0xe01a6, 0xe01a7, 0xe01a8,
9323
12.6k
      0xe01a9, 0xe01aa, 0xe01ab, 0xe01ac, 0xe01ad, 0xe01ae, 0xe01af, 0xe01b0,
9324
12.6k
      0xe01b1, 0xe01b2, 0xe01b3, 0xe01b4, 0xe01b5, 0xe01b6, 0xe01b7, 0xe01b8,
9325
12.6k
      0xe01b9, 0xe01ba, 0xe01bb, 0xe01bc, 0xe01bd, 0xe01be, 0xe01bf, 0xe01c0,
9326
12.6k
      0xe01c1, 0xe01c2, 0xe01c3, 0xe01c4, 0xe01c5, 0xe01c6, 0xe01c7, 0xe01c8,
9327
12.6k
      0xe01c9, 0xe01ca, 0xe01cb, 0xe01cc, 0xe01cd, 0xe01ce, 0xe01cf, 0xe01d0,
9328
12.6k
      0xe01d1, 0xe01d2, 0xe01d3, 0xe01d4, 0xe01d5, 0xe01d6, 0xe01d7, 0xe01d8,
9329
12.6k
      0xe01d9, 0xe01da, 0xe01db, 0xe01dc, 0xe01dd, 0xe01de, 0xe01df, 0xe01e0,
9330
12.6k
      0xe01e1, 0xe01e2, 0xe01e3, 0xe01e4, 0xe01e5, 0xe01e6, 0xe01e7, 0xe01e8,
9331
12.6k
      0xe01e9, 0xe01ea, 0xe01eb, 0xe01ec, 0xe01ed, 0xe01ee, 0xe01ef};
9332
12.6k
  if (std::binary_search(std::begin(combining), std::end(combining),
9333
12.6k
                         label.front())) {
9334
53
    return false;
9335
53
  }
9336
  // We verify this next step as part of the mapping:
9337
  // ---------------------------------------------
9338
  // Each code point in the label must only have certain status values
9339
  // according to Section 5, IDNA Mapping Table:
9340
  // - For Transitional Processing, each value must be valid.
9341
  // - For Nontransitional Processing, each value must be either valid or
9342
  // deviation.
9343
9344
  // If CheckJoiners, the label must satisfy the ContextJ rules from Appendix
9345
  // A, in The Unicode Code Points and Internationalized Domain Names for
9346
  // Applications (IDNA) [IDNA2008].
9347
12.5k
  constexpr static uint32_t virama[] = {
9348
12.5k
      0x094D,  0x09CD,  0x0A4D,  0x0ACD,  0x0B4D,  0x0BCD,  0x0C4D,  0x0CCD,
9349
12.5k
      0x0D3B,  0x0D3C,  0x0D4D,  0x0DCA,  0x0E3A,  0x0EBA,  0x0F84,  0x1039,
9350
12.5k
      0x103A,  0x1714,  0x1734,  0x17D2,  0x1A60,  0x1B44,  0x1BAA,  0x1BAB,
9351
12.5k
      0x1BF2,  0x1BF3,  0x2D7F,  0xA806,  0xA82C,  0xA8C4,  0xA953,  0xA9C0,
9352
12.5k
      0xAAF6,  0xABED,  0x10A3F, 0x11046, 0x1107F, 0x110B9, 0x11133, 0x11134,
9353
12.5k
      0x111C0, 0x11235, 0x112EA, 0x1134D, 0x11442, 0x114C2, 0x115BF, 0x1163F,
9354
12.5k
      0x116B6, 0x1172B, 0x11839, 0x1193D, 0x1193E, 0x119E0, 0x11A34, 0x11A47,
9355
12.5k
      0x11A99, 0x11C3F, 0x11D44, 0x11D45, 0x11D97};
9356
12.5k
  constexpr static uint32_t R[] = {
9357
12.5k
      0x622, 0x623, 0x624, 0x625, 0x627, 0x629, 0x62f, 0x630, 0x631,
9358
12.5k
      0x632, 0x648, 0x671, 0x672, 0x673, 0x675, 0x676, 0x677, 0x688,
9359
12.5k
      0x689, 0x68a, 0x68b, 0x68c, 0x68d, 0x68e, 0x68f, 0x690, 0x691,
9360
12.5k
      0x692, 0x693, 0x694, 0x695, 0x696, 0x697, 0x698, 0x699, 0x6c0,
9361
12.5k
      0x6c3, 0x6c4, 0x6c5, 0x6c6, 0x6c7, 0x6c8, 0x6c9, 0x6ca, 0x6cb,
9362
12.5k
      0x6cd, 0x6cf, 0x6d2, 0x6d3, 0x6d5, 0x6ee, 0x6ef, 0x710, 0x715,
9363
12.5k
      0x716, 0x717, 0x718, 0x719, 0x71e, 0x728, 0x72a, 0x72c, 0x72f,
9364
12.5k
      0x74d, 0x759, 0x75a, 0x75b, 0x854, 0x8aa, 0x8ab, 0x8ac};
9365
12.5k
  constexpr static uint32_t L[] = {0xa872};
9366
12.5k
  constexpr static uint32_t D[] = {
9367
12.5k
      0x620,  0x626,  0x628,  0x62a,  0x62b,  0x62c,  0x62d,  0x62e,  0x633,
9368
12.5k
      0x634,  0x635,  0x636,  0x637,  0x638,  0x639,  0x63a,  0x63b,  0x63c,
9369
12.5k
      0x63d,  0x63e,  0x63f,  0x641,  0x642,  0x643,  0x644,  0x645,  0x646,
9370
12.5k
      0x647,  0x649,  0x64a,  0x66e,  0x66f,  0x678,  0x679,  0x67a,  0x67b,
9371
12.5k
      0x67c,  0x67d,  0x67e,  0x67f,  0x680,  0x681,  0x682,  0x683,  0x684,
9372
12.5k
      0x685,  0x686,  0x687,  0x69a,  0x69b,  0x69c,  0x69d,  0x69e,  0x69f,
9373
12.5k
      0x6a0,  0x6a1,  0x6a2,  0x6a3,  0x6a4,  0x6a5,  0x6a6,  0x6a7,  0x6a8,
9374
12.5k
      0x6a9,  0x6aa,  0x6ab,  0x6ac,  0x6ad,  0x6ae,  0x6af,  0x6b0,  0x6b1,
9375
12.5k
      0x6b2,  0x6b3,  0x6b4,  0x6b5,  0x6b6,  0x6b7,  0x6b8,  0x6b9,  0x6ba,
9376
12.5k
      0x6bb,  0x6bc,  0x6bd,  0x6be,  0x6bf,  0x6c1,  0x6c2,  0x6cc,  0x6ce,
9377
12.5k
      0x6d0,  0x6d1,  0x6fa,  0x6fb,  0x6fc,  0x6ff,  0x712,  0x713,  0x714,
9378
12.5k
      0x71a,  0x71b,  0x71c,  0x71d,  0x71f,  0x720,  0x721,  0x722,  0x723,
9379
12.5k
      0x724,  0x725,  0x726,  0x727,  0x729,  0x72b,  0x72d,  0x72e,  0x74e,
9380
12.5k
      0x74f,  0x750,  0x751,  0x752,  0x753,  0x754,  0x755,  0x756,  0x757,
9381
12.5k
      0x758,  0x75c,  0x75d,  0x75e,  0x75f,  0x760,  0x761,  0x762,  0x763,
9382
12.5k
      0x764,  0x765,  0x766,  0x850,  0x851,  0x852,  0x853,  0x855,  0x8a0,
9383
12.5k
      0x8a2,  0x8a3,  0x8a4,  0x8a5,  0x8a6,  0x8a7,  0x8a8,  0x8a9,  0x1807,
9384
12.5k
      0x1820, 0x1821, 0x1822, 0x1823, 0x1824, 0x1825, 0x1826, 0x1827, 0x1828,
9385
12.5k
      0x1829, 0x182a, 0x182b, 0x182c, 0x182d, 0x182e, 0x182f, 0x1830, 0x1831,
9386
12.5k
      0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837, 0x1838, 0x1839, 0x183a,
9387
12.5k
      0x183b, 0x183c, 0x183d, 0x183e, 0x183f, 0x1840, 0x1841, 0x1842, 0x1843,
9388
12.5k
      0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x184a, 0x184b, 0x184c,
9389
12.5k
      0x184d, 0x184e, 0x184f, 0x1850, 0x1851, 0x1852, 0x1853, 0x1854, 0x1855,
9390
12.5k
      0x1856, 0x1857, 0x1858, 0x1859, 0x185a, 0x185b, 0x185c, 0x185d, 0x185e,
9391
12.5k
      0x185f, 0x1860, 0x1861, 0x1862, 0x1863, 0x1864, 0x1865, 0x1866, 0x1867,
9392
12.5k
      0x1868, 0x1869, 0x186a, 0x186b, 0x186c, 0x186d, 0x186e, 0x186f, 0x1870,
9393
12.5k
      0x1871, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, 0x1877, 0x1887, 0x1888,
9394
12.5k
      0x1889, 0x188a, 0x188b, 0x188c, 0x188d, 0x188e, 0x188f, 0x1890, 0x1891,
9395
12.5k
      0x1892, 0x1893, 0x1894, 0x1895, 0x1896, 0x1897, 0x1898, 0x1899, 0x189a,
9396
12.5k
      0x189b, 0x189c, 0x189d, 0x189e, 0x189f, 0x18a0, 0x18a1, 0x18a2, 0x18a3,
9397
12.5k
      0x18a4, 0x18a5, 0x18a6, 0x18a7, 0x18a8, 0x18aa, 0xa840, 0xa841, 0xa842,
9398
12.5k
      0xa843, 0xa844, 0xa845, 0xa846, 0xa847, 0xa848, 0xa849, 0xa84a, 0xa84b,
9399
12.5k
      0xa84c, 0xa84d, 0xa84e, 0xa84f, 0xa850, 0xa851, 0xa852, 0xa853, 0xa854,
9400
12.5k
      0xa855, 0xa856, 0xa857, 0xa858, 0xa859, 0xa85a, 0xa85b, 0xa85c, 0xa85d,
9401
12.5k
      0xa85e, 0xa85f, 0xa860, 0xa861, 0xa862, 0xa863, 0xa864, 0xa865, 0xa866,
9402
12.5k
      0xa867, 0xa868, 0xa869, 0xa86a, 0xa86b, 0xa86c, 0xa86d, 0xa86e, 0xa86f,
9403
12.5k
      0xa870, 0xa871};
9404
9405
95.7k
  for (size_t i = 0; i < label.size(); i++) {
9406
84.3k
    uint32_t c = label[i];
9407
84.3k
    if (c == 0x200c) {
9408
874
      if (i > 0) {
9409
861
        if (std::binary_search(std::begin(virama), std::end(virama),
9410
861
                               label[i - 1])) {
9411
101
          return true;
9412
101
        }
9413
861
      }
9414
773
      if ((i == 0) || (i + 1 >= label.size())) {
9415
90
        return false;
9416
90
      }
9417
      // we go backward looking for L or D
9418
1.35k
      auto is_l_or_d = [](uint32_t code) {
9419
1.35k
        return std::binary_search(std::begin(L), std::end(L), code) ||
9420
1.25k
               std::binary_search(std::begin(D), std::end(D), code);
9421
1.35k
      };
9422
1.74k
      auto is_r_or_d = [](uint32_t code) {
9423
1.74k
        return std::binary_search(std::begin(R), std::end(R), code) ||
9424
1.53k
               std::binary_search(std::begin(D), std::end(D), code);
9425
1.74k
      };
9426
683
      std::u32string_view before = label.substr(0, i);
9427
683
      std::u32string_view after = label.substr(i + 1);
9428
683
      return (std::find_if(before.begin(), before.end(), is_l_or_d) !=
9429
683
              before.end()) &&
9430
623
             (std::find_if(after.begin(), after.end(), is_r_or_d) !=
9431
623
              after.end());
9432
83.4k
    } else if (c == 0x200d) {
9433
290
      if (i > 0) {
9434
286
        if (std::binary_search(std::begin(virama), std::end(virama),
9435
286
                               label[i - 1])) {
9436
232
          return true;
9437
232
        }
9438
286
      }
9439
58
      return false;
9440
290
    }
9441
84.3k
  }
9442
9443
  // If CheckBidi, and if the domain name is a  Bidi domain name, then the label
9444
  // must satisfy all six of the numbered conditions in [IDNA2008] RFC 5893,
9445
  // Section 2.
9446
9447
  // The following rule, consisting of six conditions, applies to labels
9448
  // in Bidi domain names.  The requirements that this rule satisfies are
9449
  // described in Section 3.  All of the conditions must be satisfied for
9450
  // the rule to be satisfied.
9451
  //
9452
  //  1.  The first character must be a character with Bidi property L, R,
9453
  //     or AL.  If it has the R or AL property, it is an RTL label; if it
9454
  //     has the L property, it is an LTR label.
9455
  //
9456
  //  2.  In an RTL label, only characters with the Bidi properties R, AL,
9457
  //      AN, EN, ES, CS, ET, ON, BN, or NSM are allowed.
9458
  //
9459
  //   3.  In an RTL label, the end of the label must be a character with
9460
  //       Bidi property R, AL, EN, or AN, followed by zero or more
9461
  //       characters with Bidi property NSM.
9462
  //
9463
  //   4.  In an RTL label, if an EN is present, no AN may be present, and
9464
  //       vice versa.
9465
  //
9466
  //  5.  In an LTR label, only characters with the Bidi properties L, EN,
9467
  //       ES, CS, ET, ON, BN, or NSM are allowed.
9468
  //
9469
  //   6.  In an LTR label, the end of the label must be a character with
9470
  //       Bidi property L or EN, followed by zero or more characters with
9471
  //       Bidi property NSM.
9472
9473
11.3k
  size_t last_non_nsm_char = find_last_not_of_nsm(label);
9474
11.3k
  if (last_non_nsm_char == std::u32string_view::npos) {
9475
0
    return false;
9476
0
  }
9477
9478
  // A "Bidi domain name" is a domain name that contains at least one RTL label.
9479
  // The following rule, consisting of six conditions, applies to labels in Bidi
9480
  // domain names.
9481
11.3k
  if (is_rtl_label(label)) {
9482
    // The first character must be a character with Bidi property L, R,
9483
    // or AL. If it has the R or AL property, it is an RTL label; if it
9484
    // has the L property, it is an LTR label.
9485
9486
2.03k
    if (find_direction(label[0]) == direction::L) {
9487
      // Eval as LTR
9488
9489
      // In an LTR label, only characters with the Bidi properties L, EN,
9490
      // ES, CS, ET, ON, BN, or NSM are allowed.
9491
2.66k
      for (size_t i = 0; i < last_non_nsm_char; i++) {
9492
2.44k
        const direction d = find_direction(label[i]);
9493
2.44k
        if (!(d == direction::L || d == direction::EN || d == direction::ES ||
9494
1.32k
              d == direction::CS || d == direction::ET || d == direction::ON ||
9495
689
              d == direction::BN || d == direction::NSM)) {
9496
50
          return false;
9497
50
        }
9498
9499
2.39k
        if ((i == last_non_nsm_char) &&
9500
0
            !(d == direction::L || d == direction::EN)) {
9501
0
          return false;
9502
0
        }
9503
2.39k
      }
9504
9505
221
      return true;
9506
9507
1.76k
    } else {
9508
      // Eval as RTL
9509
9510
1.76k
      bool has_an = false;
9511
1.76k
      bool has_en = false;
9512
6.61k
      for (size_t i = 0; i <= last_non_nsm_char; i++) {
9513
4.99k
        const direction d = find_direction(label[i]);
9514
9515
        // NOLINTBEGIN(bugprone-assignment-in-if-condition)
9516
        // In an RTL label, if an EN is present, no AN may be present, and vice
9517
        // versa.
9518
4.99k
        if ((d == direction::EN && ((has_en = true) && has_an)) ||
9519
4.99k
            (d == direction::AN && ((has_an = true) && has_en))) {
9520
9
          return false;
9521
9
        }
9522
        // NOLINTEND(bugprone-assignment-in-if-condition)
9523
9524
4.99k
        if (!(d == direction::R || d == direction::AL || d == direction::AN ||
9525
2.22k
              d == direction::EN || d == direction::ES || d == direction::CS ||
9526
1.29k
              d == direction::ET || d == direction::ON || d == direction::BN ||
9527
347
              d == direction::NSM)) {
9528
112
          return false;
9529
112
        }
9530
9531
4.87k
        if (i == last_non_nsm_char &&
9532
1.64k
            !(d == direction::R || d == direction::AL || d == direction::AN ||
9533
157
              d == direction::EN)) {
9534
26
          return false;
9535
26
        }
9536
4.87k
      }
9537
9538
1.62k
      return true;
9539
1.76k
    }
9540
2.03k
  }
9541
9542
9.35k
  return true;
9543
11.3k
}
9544
9545
}  // namespace ada::idna
9546
/* end file src/validity.cpp */
9547
/* begin file src/to_ascii.cpp */
9548
9549
#include <algorithm>
9550
#include <cstdint>
9551
#include <ranges>
9552
9553
9554
#ifdef ADA_USE_SIMDUTF
9555
#include "simdutf.h"
9556
#endif
9557
9558
namespace ada::idna {
9559
9560
13.8k
bool constexpr is_ascii(std::u32string_view view) {
9561
23.7k
  for (uint32_t c : view) {
9562
23.7k
    if (c >= 0x80) {
9563
12.9k
      return false;
9564
12.9k
    }
9565
23.7k
  }
9566
861
  return true;
9567
13.8k
}
9568
9569
4.89k
bool constexpr is_ascii(std::string_view view) {
9570
71.6k
  for (uint8_t c : view) {
9571
71.6k
    if (c >= 0x80) {
9572
3.10k
      return false;
9573
3.10k
    }
9574
71.6k
  }
9575
1.79k
  return true;
9576
4.89k
}
9577
9578
constexpr static uint8_t is_forbidden_domain_code_point_table[] = {
9579
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9580
    1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
9581
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
9582
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
9583
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9584
    0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9585
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9586
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9587
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9588
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9589
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
9590
9591
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
9592
9593
0
inline bool is_forbidden_domain_code_point(const char c) noexcept {
9594
0
  return is_forbidden_domain_code_point_table[uint8_t(c)];
9595
0
}
9596
9597
0
bool contains_forbidden_domain_code_point(std::string_view view) {
9598
0
  return std::ranges::any_of(view, is_forbidden_domain_code_point);
9599
0
}
9600
9601
// We return "" on error.
9602
1.79k
static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9603
1.79k
  static const std::string error = "";
9604
  // copy and map
9605
  // we could be more efficient by avoiding the copy when unnecessary.
9606
1.79k
  std::string mapped_string = std::string(ut8_string);
9607
1.79k
  ascii_map(mapped_string.data(), mapped_string.size());
9608
1.79k
  std::string out;
9609
1.79k
  size_t label_start = 0;
9610
9611
8.19k
  while (label_start != mapped_string.size()) {
9612
6.83k
    size_t loc_dot = mapped_string.find('.', label_start);
9613
6.83k
    bool is_last_label = (loc_dot == std::string_view::npos);
9614
6.83k
    size_t label_size = is_last_label ? mapped_string.size() - label_start
9615
6.83k
                                      : loc_dot - label_start;
9616
6.83k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9617
6.83k
    std::string_view label_view(mapped_string.data() + label_start, label_size);
9618
6.83k
    label_start += label_size_with_dot;
9619
6.83k
    if (label_size == 0) {
9620
      // empty label? Nothing to do.
9621
4.64k
    } else if (label_view.starts_with("xn--")) {
9622
      // The xn-- part is the expensive game.
9623
2.44k
      out.append(label_view);
9624
2.44k
      std::string_view puny_segment_ascii(
9625
2.44k
          out.data() + out.size() - label_view.size() + 4,
9626
2.44k
          label_view.size() - 4);
9627
2.44k
      std::u32string tmp_buffer;
9628
2.44k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9629
2.44k
      if (!is_ok) {
9630
115
        return error;
9631
115
      }
9632
      // If the input is just ASCII, it should not have been encoded
9633
      // as punycode.
9634
      // https://github.com/whatwg/url/issues/760
9635
2.33k
      if (is_ascii(tmp_buffer)) {
9636
88
        return error;
9637
88
      }
9638
2.24k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9639
2.24k
      if (tmp_buffer != post_map) {
9640
136
        return error;
9641
136
      }
9642
2.10k
      std::u32string pre_normal = post_map;
9643
2.10k
      normalize(post_map);
9644
2.10k
      if (post_map != pre_normal) {
9645
66
        return error;
9646
66
      }
9647
2.04k
      if (post_map.empty()) {
9648
0
        return error;
9649
0
      }
9650
2.04k
      if (!is_label_valid(post_map)) {
9651
29
        return error;
9652
29
      }
9653
2.20k
    } else {
9654
2.20k
      out.append(label_view);
9655
2.20k
    }
9656
6.40k
    if (!is_last_label) {
9657
5.14k
      out.push_back('.');
9658
5.14k
    }
9659
6.40k
  }
9660
1.35k
  return out;
9661
1.79k
}
9662
9663
// We return "" on error.
9664
4.89k
std::string to_ascii(std::string_view ut8_string) {
9665
4.89k
  if (is_ascii(ut8_string)) {
9666
1.79k
    return from_ascii_to_ascii(ut8_string);
9667
1.79k
  }
9668
3.10k
  static const std::string error = "";
9669
  // We convert to UTF-32
9670
9671
#ifdef ADA_USE_SIMDUTF
9672
  size_t utf32_length =
9673
      simdutf::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9674
  std::u32string utf32(utf32_length, '\0');
9675
  size_t actual_utf32_length = simdutf::convert_utf8_to_utf32(
9676
      ut8_string.data(), ut8_string.size(), utf32.data());
9677
#else
9678
3.10k
  size_t utf32_length =
9679
3.10k
      ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9680
3.10k
  std::u32string utf32(utf32_length, '\0');
9681
3.10k
  size_t actual_utf32_length = ada::idna::utf8_to_utf32(
9682
3.10k
      ut8_string.data(), ut8_string.size(), utf32.data());
9683
3.10k
#endif
9684
3.10k
  if (actual_utf32_length == 0) {
9685
377
    return error;
9686
377
  }
9687
  // mapping
9688
2.72k
  utf32 = ada::idna::map(utf32);
9689
2.72k
  normalize(utf32);
9690
2.72k
  std::string out;
9691
2.72k
  size_t label_start = 0;
9692
9693
14.4k
  while (label_start != utf32.size()) {
9694
12.5k
    size_t loc_dot = utf32.find('.', label_start);
9695
12.5k
    bool is_last_label = (loc_dot == std::string_view::npos);
9696
12.5k
    size_t label_size =
9697
12.5k
        is_last_label ? utf32.size() - label_start : loc_dot - label_start;
9698
12.5k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9699
12.5k
    std::u32string_view label_view(utf32.data() + label_start, label_size);
9700
12.5k
    label_start += label_size_with_dot;
9701
12.5k
    if (label_size == 0) {
9702
      // empty label? Nothing to do.
9703
11.5k
    } else if (label_view.starts_with(U"xn--")) {
9704
      // we do not need to check, e.g., Xn-- because mapping goes to lower case
9705
26.6k
      for (char32_t c : label_view) {
9706
26.6k
        if (c >= 0x80) {
9707
15
          return error;
9708
15
        }
9709
26.5k
        out += (unsigned char)(c);
9710
26.5k
      }
9711
1.28k
      std::string_view puny_segment_ascii(
9712
1.28k
          out.data() + out.size() - label_view.size() + 4,
9713
1.28k
          label_view.size() - 4);
9714
1.28k
      std::u32string tmp_buffer;
9715
1.28k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9716
1.28k
      if (!is_ok) {
9717
52
        return error;
9718
52
      }
9719
      // If the input is just ASCII, it should not have been encoded
9720
      // as punycode.
9721
      // https://github.com/whatwg/url/issues/760
9722
1.23k
      if (is_ascii(tmp_buffer)) {
9723
82
        return error;
9724
82
      }
9725
1.15k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9726
1.15k
      if (tmp_buffer != post_map) {
9727
115
        return error;
9728
115
      }
9729
1.03k
      std::u32string pre_normal = post_map;
9730
1.03k
      normalize(post_map);
9731
1.03k
      if (post_map != pre_normal) {
9732
45
        return error;
9733
45
      }
9734
994
      if (post_map.empty()) {
9735
0
        return error;
9736
0
      }
9737
994
      if (!is_label_valid(post_map)) {
9738
12
        return error;
9739
12
      }
9740
10.2k
    } else {
9741
      // The fast path here is an ascii label.
9742
10.2k
      if (is_ascii(label_view)) {
9743
        // no validation needed.
9744
3.33k
        for (char32_t c : label_view) {
9745
3.33k
          out += (unsigned char)(c);
9746
3.33k
        }
9747
9.57k
      } else {
9748
        // slow path.
9749
        // first check validity.
9750
9.57k
        if (!is_label_valid(label_view)) {
9751
521
          return error;
9752
521
        }
9753
        // It is valid! So now we must encode it as punycode...
9754
9.05k
        out.append("xn--");
9755
9.05k
        bool is_ok = ada::idna::utf32_to_punycode(label_view, out);
9756
9.05k
        if (!is_ok) {
9757
0
          return error;
9758
0
        }
9759
9.05k
      }
9760
10.2k
    }
9761
11.7k
    if (!is_last_label) {
9762
9.94k
      out.push_back('.');
9763
9.94k
    }
9764
11.7k
  }
9765
1.88k
  return out;
9766
2.72k
}
9767
}  // namespace ada::idna
9768
/* end file src/to_ascii.cpp */
9769
/* begin file src/to_unicode.cpp */
9770
9771
#include <algorithm>
9772
#include <string>
9773
9774
9775
#ifdef ADA_USE_SIMDUTF
9776
#include "simdutf.h"
9777
#endif
9778
9779
namespace ada::idna {
9780
0
std::string to_unicode(std::string_view input) {
9781
0
  std::string output;
9782
0
  output.reserve(input.size());
9783
9784
0
  size_t label_start = 0;
9785
0
  while (label_start < input.size()) {
9786
0
    size_t loc_dot = input.find('.', label_start);
9787
0
    bool is_last_label = (loc_dot == std::string_view::npos);
9788
0
    size_t label_size =
9789
0
        is_last_label ? input.size() - label_start : loc_dot - label_start;
9790
0
    auto label_view = std::string_view(input.data() + label_start, label_size);
9791
9792
0
    if (label_view.starts_with("xn--") && ada::idna::is_ascii(label_view)) {
9793
0
      label_view.remove_prefix(4);
9794
0
      if (ada::idna::verify_punycode(label_view)) {
9795
0
        std::u32string tmp_buffer;
9796
0
        if (ada::idna::punycode_to_utf32(label_view, tmp_buffer)) {
9797
#ifdef ADA_USE_SIMDUTF
9798
          auto utf8_size = simdutf::utf8_length_from_utf32(tmp_buffer.data(),
9799
                                                           tmp_buffer.size());
9800
          std::string final_utf8(utf8_size, '\0');
9801
          simdutf::convert_utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9802
                                         final_utf8.data());
9803
#else
9804
0
          auto utf8_size = ada::idna::utf8_length_from_utf32(tmp_buffer.data(),
9805
0
                                                             tmp_buffer.size());
9806
0
          std::string final_utf8(utf8_size, '\0');
9807
0
          ada::idna::utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9808
0
                                   final_utf8.data());
9809
0
#endif
9810
0
          output.append(final_utf8);
9811
0
        } else {
9812
          // ToUnicode never fails.  If any step fails, then the original input
9813
          // sequence is returned immediately in that step.
9814
0
          output.append(
9815
0
              std::string_view(input.data() + label_start, label_size));
9816
0
        }
9817
0
      } else {
9818
0
        output.append(std::string_view(input.data() + label_start, label_size));
9819
0
      }
9820
0
    } else {
9821
0
      output.append(label_view);
9822
0
    }
9823
9824
0
    if (!is_last_label) {
9825
0
      output.push_back('.');
9826
0
    }
9827
9828
0
    label_start += label_size + 1;
9829
0
  }
9830
9831
0
  return output;
9832
0
}
9833
}  // namespace ada::idna
9834
/* end file src/to_unicode.cpp */
9835
/* begin file src/identifier.cpp */
9836
9837
#include <algorithm>
9838
#include <array>
9839
#include <string>
9840
9841
/* begin file src/id_tables.cpp */
9842
// IDNA  16.0.0
9843
9844
// clang-format off
9845
#ifndef ADA_IDNA_IDENTIFIER_TABLES_H
9846
#define ADA_IDNA_IDENTIFIER_TABLES_H
9847
#include <cstdint>
9848
9849
namespace ada::idna {
9850
9851
const uint32_t id_continue[1393][2] =
9852
{
9853
  {48, 57}, {65, 90}, {95, 95}, {97, 122},
9854
  {170, 170}, {181, 181}, {183, 183}, {186, 186},
9855
  {192, 214}, {216, 246}, {248, 442}, {443, 443},
9856
  {444, 447}, {448, 451}, {452, 659}, {660, 660},
9857
  {661, 687}, {688, 705}, {710, 721}, {736, 740},
9858
  {748, 748}, {750, 750}, {768, 879}, {880, 883},
9859
  {884, 884}, {886, 887}, {890, 890}, {891, 893},
9860
  {895, 895}, {902, 902}, {903, 903}, {904, 906},
9861
  {908, 908}, {910, 929}, {931, 1013}, {1015, 1153},
9862
  {1155, 1159}, {1162, 1327}, {1329, 1366}, {1369, 1369},
9863
  {1376, 1416}, {1425, 1469}, {1471, 1471}, {1473, 1474},
9864
  {1476, 1477}, {1479, 1479}, {1488, 1514}, {1519, 1522},
9865
  {1552, 1562}, {1568, 1599}, {1600, 1600}, {1601, 1610},
9866
  {1611, 1631}, {1632, 1641}, {1646, 1647}, {1648, 1648},
9867
  {1649, 1747}, {1749, 1749}, {1750, 1756}, {1759, 1764},
9868
  {1765, 1766}, {1767, 1768}, {1770, 1773}, {1774, 1775},
9869
  {1776, 1785}, {1786, 1788}, {1791, 1791}, {1808, 1808},
9870
  {1809, 1809}, {1810, 1839}, {1840, 1866}, {1869, 1957},
9871
  {1958, 1968}, {1969, 1969}, {1984, 1993}, {1994, 2026},
9872
  {2027, 2035}, {2036, 2037}, {2042, 2042}, {2045, 2045},
9873
  {2048, 2069}, {2070, 2073}, {2074, 2074}, {2075, 2083},
9874
  {2084, 2084}, {2085, 2087}, {2088, 2088}, {2089, 2093},
9875
  {2112, 2136}, {2137, 2139}, {2144, 2154}, {2160, 2183},
9876
  {2185, 2190}, {2199, 2207}, {2208, 2248}, {2249, 2249},
9877
  {2250, 2273}, {2275, 2306}, {2307, 2307}, {2308, 2361},
9878
  {2362, 2362}, {2363, 2363}, {2364, 2364}, {2365, 2365},
9879
  {2366, 2368}, {2369, 2376}, {2377, 2380}, {2381, 2381},
9880
  {2382, 2383}, {2384, 2384}, {2385, 2391}, {2392, 2401},
9881
  {2402, 2403}, {2406, 2415}, {2417, 2417}, {2418, 2432},
9882
  {2433, 2433}, {2434, 2435}, {2437, 2444}, {2447, 2448},
9883
  {2451, 2472}, {2474, 2480}, {2482, 2482}, {2486, 2489},
9884
  {2492, 2492}, {2493, 2493}, {2494, 2496}, {2497, 2500},
9885
  {2503, 2504}, {2507, 2508}, {2509, 2509}, {2510, 2510},
9886
  {2519, 2519}, {2524, 2525}, {2527, 2529}, {2530, 2531},
9887
  {2534, 2543}, {2544, 2545}, {2556, 2556}, {2558, 2558},
9888
  {2561, 2562}, {2563, 2563}, {2565, 2570}, {2575, 2576},
9889
  {2579, 2600}, {2602, 2608}, {2610, 2611}, {2613, 2614},
9890
  {2616, 2617}, {2620, 2620}, {2622, 2624}, {2625, 2626},
9891
  {2631, 2632}, {2635, 2637}, {2641, 2641}, {2649, 2652},
9892
  {2654, 2654}, {2662, 2671}, {2672, 2673}, {2674, 2676},
9893
  {2677, 2677}, {2689, 2690}, {2691, 2691}, {2693, 2701},
9894
  {2703, 2705}, {2707, 2728}, {2730, 2736}, {2738, 2739},
9895
  {2741, 2745}, {2748, 2748}, {2749, 2749}, {2750, 2752},
9896
  {2753, 2757}, {2759, 2760}, {2761, 2761}, {2763, 2764},
9897
  {2765, 2765}, {2768, 2768}, {2784, 2785}, {2786, 2787},
9898
  {2790, 2799}, {2809, 2809}, {2810, 2815}, {2817, 2817},
9899
  {2818, 2819}, {2821, 2828}, {2831, 2832}, {2835, 2856},
9900
  {2858, 2864}, {2866, 2867}, {2869, 2873}, {2876, 2876},
9901
  {2877, 2877}, {2878, 2878}, {2879, 2879}, {2880, 2880},
9902
  {2881, 2884}, {2887, 2888}, {2891, 2892}, {2893, 2893},
9903
  {2901, 2902}, {2903, 2903}, {2908, 2909}, {2911, 2913},
9904
  {2914, 2915}, {2918, 2927}, {2929, 2929}, {2946, 2946},
9905
  {2947, 2947}, {2949, 2954}, {2958, 2960}, {2962, 2965},
9906
  {2969, 2970}, {2972, 2972}, {2974, 2975}, {2979, 2980},
9907
  {2984, 2986}, {2990, 3001}, {3006, 3007}, {3008, 3008},
9908
  {3009, 3010}, {3014, 3016}, {3018, 3020}, {3021, 3021},
9909
  {3024, 3024}, {3031, 3031}, {3046, 3055}, {3072, 3072},
9910
  {3073, 3075}, {3076, 3076}, {3077, 3084}, {3086, 3088},
9911
  {3090, 3112}, {3114, 3129}, {3132, 3132}, {3133, 3133},
9912
  {3134, 3136}, {3137, 3140}, {3142, 3144}, {3146, 3149},
9913
  {3157, 3158}, {3160, 3162}, {3165, 3165}, {3168, 3169},
9914
  {3170, 3171}, {3174, 3183}, {3200, 3200}, {3201, 3201},
9915
  {3202, 3203}, {3205, 3212}, {3214, 3216}, {3218, 3240},
9916
  {3242, 3251}, {3253, 3257}, {3260, 3260}, {3261, 3261},
9917
  {3262, 3262}, {3263, 3263}, {3264, 3268}, {3270, 3270},
9918
  {3271, 3272}, {3274, 3275}, {3276, 3277}, {3285, 3286},
9919
  {3293, 3294}, {3296, 3297}, {3298, 3299}, {3302, 3311},
9920
  {3313, 3314}, {3315, 3315}, {3328, 3329}, {3330, 3331},
9921
  {3332, 3340}, {3342, 3344}, {3346, 3386}, {3387, 3388},
9922
  {3389, 3389}, {3390, 3392}, {3393, 3396}, {3398, 3400},
9923
  {3402, 3404}, {3405, 3405}, {3406, 3406}, {3412, 3414},
9924
  {3415, 3415}, {3423, 3425}, {3426, 3427}, {3430, 3439},
9925
  {3450, 3455}, {3457, 3457}, {3458, 3459}, {3461, 3478},
9926
  {3482, 3505}, {3507, 3515}, {3517, 3517}, {3520, 3526},
9927
  {3530, 3530}, {3535, 3537}, {3538, 3540}, {3542, 3542},
9928
  {3544, 3551}, {3558, 3567}, {3570, 3571}, {3585, 3632},
9929
  {3633, 3633}, {3634, 3635}, {3636, 3642}, {3648, 3653},
9930
  {3654, 3654}, {3655, 3662}, {3664, 3673}, {3713, 3714},
9931
  {3716, 3716}, {3718, 3722}, {3724, 3747}, {3749, 3749},
9932
  {3751, 3760}, {3761, 3761}, {3762, 3763}, {3764, 3772},
9933
  {3773, 3773}, {3776, 3780}, {3782, 3782}, {3784, 3790},
9934
  {3792, 3801}, {3804, 3807}, {3840, 3840}, {3864, 3865},
9935
  {3872, 3881}, {3893, 3893}, {3895, 3895}, {3897, 3897},
9936
  {3902, 3903}, {3904, 3911}, {3913, 3948}, {3953, 3966},
9937
  {3967, 3967}, {3968, 3972}, {3974, 3975}, {3976, 3980},
9938
  {3981, 3991}, {3993, 4028}, {4038, 4038}, {4096, 4138},
9939
  {4139, 4140}, {4141, 4144}, {4145, 4145}, {4146, 4151},
9940
  {4152, 4152}, {4153, 4154}, {4155, 4156}, {4157, 4158},
9941
  {4159, 4159}, {4160, 4169}, {4176, 4181}, {4182, 4183},
9942
  {4184, 4185}, {4186, 4189}, {4190, 4192}, {4193, 4193},
9943
  {4194, 4196}, {4197, 4198}, {4199, 4205}, {4206, 4208},
9944
  {4209, 4212}, {4213, 4225}, {4226, 4226}, {4227, 4228},
9945
  {4229, 4230}, {4231, 4236}, {4237, 4237}, {4238, 4238},
9946
  {4239, 4239}, {4240, 4249}, {4250, 4252}, {4253, 4253},
9947
  {4256, 4293}, {4295, 4295}, {4301, 4301}, {4304, 4346},
9948
  {4348, 4348}, {4349, 4351}, {4352, 4680}, {4682, 4685},
9949
  {4688, 4694}, {4696, 4696}, {4698, 4701}, {4704, 4744},
9950
  {4746, 4749}, {4752, 4784}, {4786, 4789}, {4792, 4798},
9951
  {4800, 4800}, {4802, 4805}, {4808, 4822}, {4824, 4880},
9952
  {4882, 4885}, {4888, 4954}, {4957, 4959}, {4969, 4977},
9953
  {4992, 5007}, {5024, 5109}, {5112, 5117}, {5121, 5740},
9954
  {5743, 5759}, {5761, 5786}, {5792, 5866}, {5870, 5872},
9955
  {5873, 5880}, {5888, 5905}, {5906, 5908}, {5909, 5909},
9956
  {5919, 5937}, {5938, 5939}, {5940, 5940}, {5952, 5969},
9957
  {5970, 5971}, {5984, 5996}, {5998, 6000}, {6002, 6003},
9958
  {6016, 6067}, {6068, 6069}, {6070, 6070}, {6071, 6077},
9959
  {6078, 6085}, {6086, 6086}, {6087, 6088}, {6089, 6099},
9960
  {6103, 6103}, {6108, 6108}, {6109, 6109}, {6112, 6121},
9961
  {6155, 6157}, {6159, 6159}, {6160, 6169}, {6176, 6210},
9962
  {6211, 6211}, {6212, 6264}, {6272, 6276}, {6277, 6278},
9963
  {6279, 6312}, {6313, 6313}, {6314, 6314}, {6320, 6389},
9964
  {6400, 6430}, {6432, 6434}, {6435, 6438}, {6439, 6440},
9965
  {6441, 6443}, {6448, 6449}, {6450, 6450}, {6451, 6456},
9966
  {6457, 6459}, {6470, 6479}, {6480, 6509}, {6512, 6516},
9967
  {6528, 6571}, {6576, 6601}, {6608, 6617}, {6618, 6618},
9968
  {6656, 6678}, {6679, 6680}, {6681, 6682}, {6683, 6683},
9969
  {6688, 6740}, {6741, 6741}, {6742, 6742}, {6743, 6743},
9970
  {6744, 6750}, {6752, 6752}, {6753, 6753}, {6754, 6754},
9971
  {6755, 6756}, {6757, 6764}, {6765, 6770}, {6771, 6780},
9972
  {6783, 6783}, {6784, 6793}, {6800, 6809}, {6823, 6823},
9973
  {6832, 6845}, {6847, 6862}, {6912, 6915}, {6916, 6916},
9974
  {6917, 6963}, {6964, 6964}, {6965, 6965}, {6966, 6970},
9975
  {6971, 6971}, {6972, 6972}, {6973, 6977}, {6978, 6978},
9976
  {6979, 6980}, {6981, 6988}, {6992, 7001}, {7019, 7027},
9977
  {7040, 7041}, {7042, 7042}, {7043, 7072}, {7073, 7073},
9978
  {7074, 7077}, {7078, 7079}, {7080, 7081}, {7082, 7082},
9979
  {7083, 7085}, {7086, 7087}, {7088, 7097}, {7098, 7141},
9980
  {7142, 7142}, {7143, 7143}, {7144, 7145}, {7146, 7148},
9981
  {7149, 7149}, {7150, 7150}, {7151, 7153}, {7154, 7155},
9982
  {7168, 7203}, {7204, 7211}, {7212, 7219}, {7220, 7221},
9983
  {7222, 7223}, {7232, 7241}, {7245, 7247}, {7248, 7257},
9984
  {7258, 7287}, {7288, 7293}, {7296, 7306}, {7312, 7354},
9985
  {7357, 7359}, {7376, 7378}, {7380, 7392}, {7393, 7393},
9986
  {7394, 7400}, {7401, 7404}, {7405, 7405}, {7406, 7411},
9987
  {7412, 7412}, {7413, 7414}, {7415, 7415}, {7416, 7417},
9988
  {7418, 7418}, {7424, 7467}, {7468, 7530}, {7531, 7543},
9989
  {7544, 7544}, {7545, 7578}, {7579, 7615}, {7616, 7679},
9990
  {7680, 7957}, {7960, 7965}, {7968, 8005}, {8008, 8013},
9991
  {8016, 8023}, {8025, 8025}, {8027, 8027}, {8029, 8029},
9992
  {8031, 8061}, {8064, 8116}, {8118, 8124}, {8126, 8126},
9993
  {8130, 8132}, {8134, 8140}, {8144, 8147}, {8150, 8155},
9994
  {8160, 8172}, {8178, 8180}, {8182, 8188}, {8204, 8205},
9995
  {8255, 8256}, {8276, 8276}, {8305, 8305}, {8319, 8319},
9996
  {8336, 8348}, {8400, 8412}, {8417, 8417}, {8421, 8432},
9997
  {8450, 8450}, {8455, 8455}, {8458, 8467}, {8469, 8469},
9998
  {8472, 8472}, {8473, 8477}, {8484, 8484}, {8486, 8486},
9999
  {8488, 8488}, {8490, 8493}, {8494, 8494}, {8495, 8500},
10000
  {8501, 8504}, {8505, 8505}, {8508, 8511}, {8517, 8521},
10001
  {8526, 8526}, {8544, 8578}, {8579, 8580}, {8581, 8584},
10002
  {11264, 11387}, {11388, 11389}, {11390, 11492}, {11499, 11502},
10003
  {11503, 11505}, {11506, 11507}, {11520, 11557}, {11559, 11559},
10004
  {11565, 11565}, {11568, 11623}, {11631, 11631}, {11647, 11647},
10005
  {11648, 11670}, {11680, 11686}, {11688, 11694}, {11696, 11702},
10006
  {11704, 11710}, {11712, 11718}, {11720, 11726}, {11728, 11734},
10007
  {11736, 11742}, {11744, 11775}, {12293, 12293}, {12294, 12294},
10008
  {12295, 12295}, {12321, 12329}, {12330, 12333}, {12334, 12335},
10009
  {12337, 12341}, {12344, 12346}, {12347, 12347}, {12348, 12348},
10010
  {12353, 12438}, {12441, 12442}, {12443, 12444}, {12445, 12446},
10011
  {12447, 12447}, {12449, 12538}, {12539, 12539}, {12540, 12542},
10012
  {12543, 12543}, {12549, 12591}, {12593, 12686}, {12704, 12735},
10013
  {12784, 12799}, {13312, 19903}, {19968, 40980}, {40981, 40981},
10014
  {40982, 42124}, {42192, 42231}, {42232, 42237}, {42240, 42507},
10015
  {42508, 42508}, {42512, 42527}, {42528, 42537}, {42538, 42539},
10016
  {42560, 42605}, {42606, 42606}, {42607, 42607}, {42612, 42621},
10017
  {42623, 42623}, {42624, 42651}, {42652, 42653}, {42654, 42655},
10018
  {42656, 42725}, {42726, 42735}, {42736, 42737}, {42775, 42783},
10019
  {42786, 42863}, {42864, 42864}, {42865, 42887}, {42888, 42888},
10020
  {42891, 42894}, {42895, 42895}, {42896, 42957}, {42960, 42961},
10021
  {42963, 42963}, {42965, 42972}, {42994, 42996}, {42997, 42998},
10022
  {42999, 42999}, {43000, 43001}, {43002, 43002}, {43003, 43009},
10023
  {43010, 43010}, {43011, 43013}, {43014, 43014}, {43015, 43018},
10024
  {43019, 43019}, {43020, 43042}, {43043, 43044}, {43045, 43046},
10025
  {43047, 43047}, {43052, 43052}, {43072, 43123}, {43136, 43137},
10026
  {43138, 43187}, {43188, 43203}, {43204, 43205}, {43216, 43225},
10027
  {43232, 43249}, {43250, 43255}, {43259, 43259}, {43261, 43262},
10028
  {43263, 43263}, {43264, 43273}, {43274, 43301}, {43302, 43309},
10029
  {43312, 43334}, {43335, 43345}, {43346, 43347}, {43360, 43388},
10030
  {43392, 43394}, {43395, 43395}, {43396, 43442}, {43443, 43443},
10031
  {43444, 43445}, {43446, 43449}, {43450, 43451}, {43452, 43453},
10032
  {43454, 43456}, {43471, 43471}, {43472, 43481}, {43488, 43492},
10033
  {43493, 43493}, {43494, 43494}, {43495, 43503}, {43504, 43513},
10034
  {43514, 43518}, {43520, 43560}, {43561, 43566}, {43567, 43568},
10035
  {43569, 43570}, {43571, 43572}, {43573, 43574}, {43584, 43586},
10036
  {43587, 43587}, {43588, 43595}, {43596, 43596}, {43597, 43597},
10037
  {43600, 43609}, {43616, 43631}, {43632, 43632}, {43633, 43638},
10038
  {43642, 43642}, {43643, 43643}, {43644, 43644}, {43645, 43645},
10039
  {43646, 43695}, {43696, 43696}, {43697, 43697}, {43698, 43700},
10040
  {43701, 43702}, {43703, 43704}, {43705, 43709}, {43710, 43711},
10041
  {43712, 43712}, {43713, 43713}, {43714, 43714}, {43739, 43740},
10042
  {43741, 43741}, {43744, 43754}, {43755, 43755}, {43756, 43757},
10043
  {43758, 43759}, {43762, 43762}, {43763, 43764}, {43765, 43765},
10044
  {43766, 43766}, {43777, 43782}, {43785, 43790}, {43793, 43798},
10045
  {43808, 43814}, {43816, 43822}, {43824, 43866}, {43868, 43871},
10046
  {43872, 43880}, {43881, 43881}, {43888, 43967}, {43968, 44002},
10047
  {44003, 44004}, {44005, 44005}, {44006, 44007}, {44008, 44008},
10048
  {44009, 44010}, {44012, 44012}, {44013, 44013}, {44016, 44025},
10049
  {44032, 55203}, {55216, 55238}, {55243, 55291}, {63744, 64109},
10050
  {64112, 64217}, {64256, 64262}, {64275, 64279}, {64285, 64285},
10051
  {64286, 64286}, {64287, 64296}, {64298, 64310}, {64312, 64316},
10052
  {64318, 64318}, {64320, 64321}, {64323, 64324}, {64326, 64433},
10053
  {64467, 64829}, {64848, 64911}, {64914, 64967}, {65008, 65019},
10054
  {65024, 65039}, {65056, 65071}, {65075, 65076}, {65101, 65103},
10055
  {65136, 65140}, {65142, 65276}, {65296, 65305}, {65313, 65338},
10056
  {65343, 65343}, {65345, 65370}, {65381, 65381}, {65382, 65391},
10057
  {65392, 65392}, {65393, 65437}, {65438, 65439}, {65440, 65470},
10058
  {65474, 65479}, {65482, 65487}, {65490, 65495}, {65498, 65500},
10059
  {65536, 65547}, {65549, 65574}, {65576, 65594}, {65596, 65597},
10060
  {65599, 65613}, {65616, 65629}, {65664, 65786}, {65856, 65908},
10061
  {66045, 66045}, {66176, 66204}, {66208, 66256}, {66272, 66272},
10062
  {66304, 66335}, {66349, 66368}, {66369, 66369}, {66370, 66377},
10063
  {66378, 66378}, {66384, 66421}, {66422, 66426}, {66432, 66461},
10064
  {66464, 66499}, {66504, 66511}, {66513, 66517}, {66560, 66639},
10065
  {66640, 66717}, {66720, 66729}, {66736, 66771}, {66776, 66811},
10066
  {66816, 66855}, {66864, 66915}, {66928, 66938}, {66940, 66954},
10067
  {66956, 66962}, {66964, 66965}, {66967, 66977}, {66979, 66993},
10068
  {66995, 67001}, {67003, 67004}, {67008, 67059}, {67072, 67382},
10069
  {67392, 67413}, {67424, 67431}, {67456, 67461}, {67463, 67504},
10070
  {67506, 67514}, {67584, 67589}, {67592, 67592}, {67594, 67637},
10071
  {67639, 67640}, {67644, 67644}, {67647, 67669}, {67680, 67702},
10072
  {67712, 67742}, {67808, 67826}, {67828, 67829}, {67840, 67861},
10073
  {67872, 67897}, {67968, 68023}, {68030, 68031}, {68096, 68096},
10074
  {68097, 68099}, {68101, 68102}, {68108, 68111}, {68112, 68115},
10075
  {68117, 68119}, {68121, 68149}, {68152, 68154}, {68159, 68159},
10076
  {68192, 68220}, {68224, 68252}, {68288, 68295}, {68297, 68324},
10077
  {68325, 68326}, {68352, 68405}, {68416, 68437}, {68448, 68466},
10078
  {68480, 68497}, {68608, 68680}, {68736, 68786}, {68800, 68850},
10079
  {68864, 68899}, {68900, 68903}, {68912, 68921}, {68928, 68937},
10080
  {68938, 68941}, {68942, 68942}, {68943, 68943}, {68944, 68965},
10081
  {68969, 68973}, {68975, 68975}, {68976, 68997}, {69248, 69289},
10082
  {69291, 69292}, {69296, 69297}, {69314, 69316}, {69372, 69375},
10083
  {69376, 69404}, {69415, 69415}, {69424, 69445}, {69446, 69456},
10084
  {69488, 69505}, {69506, 69509}, {69552, 69572}, {69600, 69622},
10085
  {69632, 69632}, {69633, 69633}, {69634, 69634}, {69635, 69687},
10086
  {69688, 69702}, {69734, 69743}, {69744, 69744}, {69745, 69746},
10087
  {69747, 69748}, {69749, 69749}, {69759, 69761}, {69762, 69762},
10088
  {69763, 69807}, {69808, 69810}, {69811, 69814}, {69815, 69816},
10089
  {69817, 69818}, {69826, 69826}, {69840, 69864}, {69872, 69881},
10090
  {69888, 69890}, {69891, 69926}, {69927, 69931}, {69932, 69932},
10091
  {69933, 69940}, {69942, 69951}, {69956, 69956}, {69957, 69958},
10092
  {69959, 69959}, {69968, 70002}, {70003, 70003}, {70006, 70006},
10093
  {70016, 70017}, {70018, 70018}, {70019, 70066}, {70067, 70069},
10094
  {70070, 70078}, {70079, 70080}, {70081, 70084}, {70089, 70092},
10095
  {70094, 70094}, {70095, 70095}, {70096, 70105}, {70106, 70106},
10096
  {70108, 70108}, {70144, 70161}, {70163, 70187}, {70188, 70190},
10097
  {70191, 70193}, {70194, 70195}, {70196, 70196}, {70197, 70197},
10098
  {70198, 70199}, {70206, 70206}, {70207, 70208}, {70209, 70209},
10099
  {70272, 70278}, {70280, 70280}, {70282, 70285}, {70287, 70301},
10100
  {70303, 70312}, {70320, 70366}, {70367, 70367}, {70368, 70370},
10101
  {70371, 70378}, {70384, 70393}, {70400, 70401}, {70402, 70403},
10102
  {70405, 70412}, {70415, 70416}, {70419, 70440}, {70442, 70448},
10103
  {70450, 70451}, {70453, 70457}, {70459, 70460}, {70461, 70461},
10104
  {70462, 70463}, {70464, 70464}, {70465, 70468}, {70471, 70472},
10105
  {70475, 70477}, {70480, 70480}, {70487, 70487}, {70493, 70497},
10106
  {70498, 70499}, {70502, 70508}, {70512, 70516}, {70528, 70537},
10107
  {70539, 70539}, {70542, 70542}, {70544, 70581}, {70583, 70583},
10108
  {70584, 70586}, {70587, 70592}, {70594, 70594}, {70597, 70597},
10109
  {70599, 70602}, {70604, 70605}, {70606, 70606}, {70607, 70607},
10110
  {70608, 70608}, {70609, 70609}, {70610, 70610}, {70611, 70611},
10111
  {70625, 70626}, {70656, 70708}, {70709, 70711}, {70712, 70719},
10112
  {70720, 70721}, {70722, 70724}, {70725, 70725}, {70726, 70726},
10113
  {70727, 70730}, {70736, 70745}, {70750, 70750}, {70751, 70753},
10114
  {70784, 70831}, {70832, 70834}, {70835, 70840}, {70841, 70841},
10115
  {70842, 70842}, {70843, 70846}, {70847, 70848}, {70849, 70849},
10116
  {70850, 70851}, {70852, 70853}, {70855, 70855}, {70864, 70873},
10117
  {71040, 71086}, {71087, 71089}, {71090, 71093}, {71096, 71099},
10118
  {71100, 71101}, {71102, 71102}, {71103, 71104}, {71128, 71131},
10119
  {71132, 71133}, {71168, 71215}, {71216, 71218}, {71219, 71226},
10120
  {71227, 71228}, {71229, 71229}, {71230, 71230}, {71231, 71232},
10121
  {71236, 71236}, {71248, 71257}, {71296, 71338}, {71339, 71339},
10122
  {71340, 71340}, {71341, 71341}, {71342, 71343}, {71344, 71349},
10123
  {71350, 71350}, {71351, 71351}, {71352, 71352}, {71360, 71369},
10124
  {71376, 71395}, {71424, 71450}, {71453, 71453}, {71454, 71454},
10125
  {71455, 71455}, {71456, 71457}, {71458, 71461}, {71462, 71462},
10126
  {71463, 71467}, {71472, 71481}, {71488, 71494}, {71680, 71723},
10127
  {71724, 71726}, {71727, 71735}, {71736, 71736}, {71737, 71738},
10128
  {71840, 71903}, {71904, 71913}, {71935, 71942}, {71945, 71945},
10129
  {71948, 71955}, {71957, 71958}, {71960, 71983}, {71984, 71989},
10130
  {71991, 71992}, {71995, 71996}, {71997, 71997}, {71998, 71998},
10131
  {71999, 71999}, {72000, 72000}, {72001, 72001}, {72002, 72002},
10132
  {72003, 72003}, {72016, 72025}, {72096, 72103}, {72106, 72144},
10133
  {72145, 72147}, {72148, 72151}, {72154, 72155}, {72156, 72159},
10134
  {72160, 72160}, {72161, 72161}, {72163, 72163}, {72164, 72164},
10135
  {72192, 72192}, {72193, 72202}, {72203, 72242}, {72243, 72248},
10136
  {72249, 72249}, {72250, 72250}, {72251, 72254}, {72263, 72263},
10137
  {72272, 72272}, {72273, 72278}, {72279, 72280}, {72281, 72283},
10138
  {72284, 72329}, {72330, 72342}, {72343, 72343}, {72344, 72345},
10139
  {72349, 72349}, {72368, 72440}, {72640, 72672}, {72688, 72697},
10140
  {72704, 72712}, {72714, 72750}, {72751, 72751}, {72752, 72758},
10141
  {72760, 72765}, {72766, 72766}, {72767, 72767}, {72768, 72768},
10142
  {72784, 72793}, {72818, 72847}, {72850, 72871}, {72873, 72873},
10143
  {72874, 72880}, {72881, 72881}, {72882, 72883}, {72884, 72884},
10144
  {72885, 72886}, {72960, 72966}, {72968, 72969}, {72971, 73008},
10145
  {73009, 73014}, {73018, 73018}, {73020, 73021}, {73023, 73029},
10146
  {73030, 73030}, {73031, 73031}, {73040, 73049}, {73056, 73061},
10147
  {73063, 73064}, {73066, 73097}, {73098, 73102}, {73104, 73105},
10148
  {73107, 73108}, {73109, 73109}, {73110, 73110}, {73111, 73111},
10149
  {73112, 73112}, {73120, 73129}, {73440, 73458}, {73459, 73460},
10150
  {73461, 73462}, {73472, 73473}, {73474, 73474}, {73475, 73475},
10151
  {73476, 73488}, {73490, 73523}, {73524, 73525}, {73526, 73530},
10152
  {73534, 73535}, {73536, 73536}, {73537, 73537}, {73538, 73538},
10153
  {73552, 73561}, {73562, 73562}, {73648, 73648}, {73728, 74649},
10154
  {74752, 74862}, {74880, 75075}, {77712, 77808}, {77824, 78895},
10155
  {78912, 78912}, {78913, 78918}, {78919, 78933}, {78944, 82938},
10156
  {82944, 83526}, {90368, 90397}, {90398, 90409}, {90410, 90412},
10157
  {90413, 90415}, {90416, 90425}, {92160, 92728}, {92736, 92766},
10158
  {92768, 92777}, {92784, 92862}, {92864, 92873}, {92880, 92909},
10159
  {92912, 92916}, {92928, 92975}, {92976, 92982}, {92992, 92995},
10160
  {93008, 93017}, {93027, 93047}, {93053, 93071}, {93504, 93506},
10161
  {93507, 93546}, {93547, 93548}, {93552, 93561}, {93760, 93823},
10162
  {93952, 94026}, {94031, 94031}, {94032, 94032}, {94033, 94087},
10163
  {94095, 94098}, {94099, 94111}, {94176, 94177}, {94179, 94179},
10164
  {94180, 94180}, {94192, 94193}, {94208, 100343}, {100352, 101589},
10165
  {101631, 101640}, {110576, 110579}, {110581, 110587}, {110589, 110590},
10166
  {110592, 110882}, {110898, 110898}, {110928, 110930}, {110933, 110933},
10167
  {110948, 110951}, {110960, 111355}, {113664, 113770}, {113776, 113788},
10168
  {113792, 113800}, {113808, 113817}, {113821, 113822}, {118000, 118009},
10169
  {118528, 118573}, {118576, 118598}, {119141, 119142}, {119143, 119145},
10170
  {119149, 119154}, {119163, 119170}, {119173, 119179}, {119210, 119213},
10171
  {119362, 119364}, {119808, 119892}, {119894, 119964}, {119966, 119967},
10172
  {119970, 119970}, {119973, 119974}, {119977, 119980}, {119982, 119993},
10173
  {119995, 119995}, {119997, 120003}, {120005, 120069}, {120071, 120074},
10174
  {120077, 120084}, {120086, 120092}, {120094, 120121}, {120123, 120126},
10175
  {120128, 120132}, {120134, 120134}, {120138, 120144}, {120146, 120485},
10176
  {120488, 120512}, {120514, 120538}, {120540, 120570}, {120572, 120596},
10177
  {120598, 120628}, {120630, 120654}, {120656, 120686}, {120688, 120712},
10178
  {120714, 120744}, {120746, 120770}, {120772, 120779}, {120782, 120831},
10179
  {121344, 121398}, {121403, 121452}, {121461, 121461}, {121476, 121476},
10180
  {121499, 121503}, {121505, 121519}, {122624, 122633}, {122634, 122634},
10181
  {122635, 122654}, {122661, 122666}, {122880, 122886}, {122888, 122904},
10182
  {122907, 122913}, {122915, 122916}, {122918, 122922}, {122928, 122989},
10183
  {123023, 123023}, {123136, 123180}, {123184, 123190}, {123191, 123197},
10184
  {123200, 123209}, {123214, 123214}, {123536, 123565}, {123566, 123566},
10185
  {123584, 123627}, {123628, 123631}, {123632, 123641}, {124112, 124138},
10186
  {124139, 124139}, {124140, 124143}, {124144, 124153}, {124368, 124397},
10187
  {124398, 124399}, {124400, 124400}, {124401, 124410}, {124896, 124902},
10188
  {124904, 124907}, {124909, 124910}, {124912, 124926}, {124928, 125124},
10189
  {125136, 125142}, {125184, 125251}, {125252, 125258}, {125259, 125259},
10190
  {125264, 125273}, {126464, 126467}, {126469, 126495}, {126497, 126498},
10191
  {126500, 126500}, {126503, 126503}, {126505, 126514}, {126516, 126519},
10192
  {126521, 126521}, {126523, 126523}, {126530, 126530}, {126535, 126535},
10193
  {126537, 126537}, {126539, 126539}, {126541, 126543}, {126545, 126546},
10194
  {126548, 126548}, {126551, 126551}, {126553, 126553}, {126555, 126555},
10195
  {126557, 126557}, {126559, 126559}, {126561, 126562}, {126564, 126564},
10196
  {126567, 126570}, {126572, 126578}, {126580, 126583}, {126585, 126588},
10197
  {126590, 126590}, {126592, 126601}, {126603, 126619}, {126625, 126627},
10198
  {126629, 126633}, {126635, 126651}, {130032, 130041}, {131072, 173791},
10199
  {173824, 177977}, {177984, 178205}, {178208, 183969}, {183984, 191456},
10200
  {191472, 192093}, {194560, 195101}, {196608, 201546}, {201552, 205743},
10201
  {917760, 917999}
10202
};
10203
const uint32_t id_start[763][2] =
10204
{
10205
  {65, 90}, {97, 122}, {170, 170}, {181, 181},
10206
  {186, 186}, {192, 214}, {216, 246}, {248, 442},
10207
  {443, 443}, {444, 447}, {448, 451}, {452, 659},
10208
  {660, 660}, {661, 687}, {688, 705}, {710, 721},
10209
  {736, 740}, {748, 748}, {750, 750}, {880, 883},
10210
  {884, 884}, {886, 887}, {890, 890}, {891, 893},
10211
  {895, 895}, {902, 902}, {904, 906}, {908, 908},
10212
  {910, 929}, {931, 1013}, {1015, 1153}, {1162, 1327},
10213
  {1329, 1366}, {1369, 1369}, {1376, 1416}, {1488, 1514},
10214
  {1519, 1522}, {1568, 1599}, {1600, 1600}, {1601, 1610},
10215
  {1646, 1647}, {1649, 1747}, {1749, 1749}, {1765, 1766},
10216
  {1774, 1775}, {1786, 1788}, {1791, 1791}, {1808, 1808},
10217
  {1810, 1839}, {1869, 1957}, {1969, 1969}, {1994, 2026},
10218
  {2036, 2037}, {2042, 2042}, {2048, 2069}, {2074, 2074},
10219
  {2084, 2084}, {2088, 2088}, {2112, 2136}, {2144, 2154},
10220
  {2160, 2183}, {2185, 2190}, {2208, 2248}, {2249, 2249},
10221
  {2308, 2361}, {2365, 2365}, {2384, 2384}, {2392, 2401},
10222
  {2417, 2417}, {2418, 2432}, {2437, 2444}, {2447, 2448},
10223
  {2451, 2472}, {2474, 2480}, {2482, 2482}, {2486, 2489},
10224
  {2493, 2493}, {2510, 2510}, {2524, 2525}, {2527, 2529},
10225
  {2544, 2545}, {2556, 2556}, {2565, 2570}, {2575, 2576},
10226
  {2579, 2600}, {2602, 2608}, {2610, 2611}, {2613, 2614},
10227
  {2616, 2617}, {2649, 2652}, {2654, 2654}, {2674, 2676},
10228
  {2693, 2701}, {2703, 2705}, {2707, 2728}, {2730, 2736},
10229
  {2738, 2739}, {2741, 2745}, {2749, 2749}, {2768, 2768},
10230
  {2784, 2785}, {2809, 2809}, {2821, 2828}, {2831, 2832},
10231
  {2835, 2856}, {2858, 2864}, {2866, 2867}, {2869, 2873},
10232
  {2877, 2877}, {2908, 2909}, {2911, 2913}, {2929, 2929},
10233
  {2947, 2947}, {2949, 2954}, {2958, 2960}, {2962, 2965},
10234
  {2969, 2970}, {2972, 2972}, {2974, 2975}, {2979, 2980},
10235
  {2984, 2986}, {2990, 3001}, {3024, 3024}, {3077, 3084},
10236
  {3086, 3088}, {3090, 3112}, {3114, 3129}, {3133, 3133},
10237
  {3160, 3162}, {3165, 3165}, {3168, 3169}, {3200, 3200},
10238
  {3205, 3212}, {3214, 3216}, {3218, 3240}, {3242, 3251},
10239
  {3253, 3257}, {3261, 3261}, {3293, 3294}, {3296, 3297},
10240
  {3313, 3314}, {3332, 3340}, {3342, 3344}, {3346, 3386},
10241
  {3389, 3389}, {3406, 3406}, {3412, 3414}, {3423, 3425},
10242
  {3450, 3455}, {3461, 3478}, {3482, 3505}, {3507, 3515},
10243
  {3517, 3517}, {3520, 3526}, {3585, 3632}, {3634, 3635},
10244
  {3648, 3653}, {3654, 3654}, {3713, 3714}, {3716, 3716},
10245
  {3718, 3722}, {3724, 3747}, {3749, 3749}, {3751, 3760},
10246
  {3762, 3763}, {3773, 3773}, {3776, 3780}, {3782, 3782},
10247
  {3804, 3807}, {3840, 3840}, {3904, 3911}, {3913, 3948},
10248
  {3976, 3980}, {4096, 4138}, {4159, 4159}, {4176, 4181},
10249
  {4186, 4189}, {4193, 4193}, {4197, 4198}, {4206, 4208},
10250
  {4213, 4225}, {4238, 4238}, {4256, 4293}, {4295, 4295},
10251
  {4301, 4301}, {4304, 4346}, {4348, 4348}, {4349, 4351},
10252
  {4352, 4680}, {4682, 4685}, {4688, 4694}, {4696, 4696},
10253
  {4698, 4701}, {4704, 4744}, {4746, 4749}, {4752, 4784},
10254
  {4786, 4789}, {4792, 4798}, {4800, 4800}, {4802, 4805},
10255
  {4808, 4822}, {4824, 4880}, {4882, 4885}, {4888, 4954},
10256
  {4992, 5007}, {5024, 5109}, {5112, 5117}, {5121, 5740},
10257
  {5743, 5759}, {5761, 5786}, {5792, 5866}, {5870, 5872},
10258
  {5873, 5880}, {5888, 5905}, {5919, 5937}, {5952, 5969},
10259
  {5984, 5996}, {5998, 6000}, {6016, 6067}, {6103, 6103},
10260
  {6108, 6108}, {6176, 6210}, {6211, 6211}, {6212, 6264},
10261
  {6272, 6276}, {6277, 6278}, {6279, 6312}, {6314, 6314},
10262
  {6320, 6389}, {6400, 6430}, {6480, 6509}, {6512, 6516},
10263
  {6528, 6571}, {6576, 6601}, {6656, 6678}, {6688, 6740},
10264
  {6823, 6823}, {6917, 6963}, {6981, 6988}, {7043, 7072},
10265
  {7086, 7087}, {7098, 7141}, {7168, 7203}, {7245, 7247},
10266
  {7258, 7287}, {7288, 7293}, {7296, 7306}, {7312, 7354},
10267
  {7357, 7359}, {7401, 7404}, {7406, 7411}, {7413, 7414},
10268
  {7418, 7418}, {7424, 7467}, {7468, 7530}, {7531, 7543},
10269
  {7544, 7544}, {7545, 7578}, {7579, 7615}, {7680, 7957},
10270
  {7960, 7965}, {7968, 8005}, {8008, 8013}, {8016, 8023},
10271
  {8025, 8025}, {8027, 8027}, {8029, 8029}, {8031, 8061},
10272
  {8064, 8116}, {8118, 8124}, {8126, 8126}, {8130, 8132},
10273
  {8134, 8140}, {8144, 8147}, {8150, 8155}, {8160, 8172},
10274
  {8178, 8180}, {8182, 8188}, {8305, 8305}, {8319, 8319},
10275
  {8336, 8348}, {8450, 8450}, {8455, 8455}, {8458, 8467},
10276
  {8469, 8469}, {8472, 8472}, {8473, 8477}, {8484, 8484},
10277
  {8486, 8486}, {8488, 8488}, {8490, 8493}, {8494, 8494},
10278
  {8495, 8500}, {8501, 8504}, {8505, 8505}, {8508, 8511},
10279
  {8517, 8521}, {8526, 8526}, {8544, 8578}, {8579, 8580},
10280
  {8581, 8584}, {11264, 11387}, {11388, 11389}, {11390, 11492},
10281
  {11499, 11502}, {11506, 11507}, {11520, 11557}, {11559, 11559},
10282
  {11565, 11565}, {11568, 11623}, {11631, 11631}, {11648, 11670},
10283
  {11680, 11686}, {11688, 11694}, {11696, 11702}, {11704, 11710},
10284
  {11712, 11718}, {11720, 11726}, {11728, 11734}, {11736, 11742},
10285
  {12293, 12293}, {12294, 12294}, {12295, 12295}, {12321, 12329},
10286
  {12337, 12341}, {12344, 12346}, {12347, 12347}, {12348, 12348},
10287
  {12353, 12438}, {12443, 12444}, {12445, 12446}, {12447, 12447},
10288
  {12449, 12538}, {12540, 12542}, {12543, 12543}, {12549, 12591},
10289
  {12593, 12686}, {12704, 12735}, {12784, 12799}, {13312, 19903},
10290
  {19968, 40980}, {40981, 40981}, {40982, 42124}, {42192, 42231},
10291
  {42232, 42237}, {42240, 42507}, {42508, 42508}, {42512, 42527},
10292
  {42538, 42539}, {42560, 42605}, {42606, 42606}, {42623, 42623},
10293
  {42624, 42651}, {42652, 42653}, {42656, 42725}, {42726, 42735},
10294
  {42775, 42783}, {42786, 42863}, {42864, 42864}, {42865, 42887},
10295
  {42888, 42888}, {42891, 42894}, {42895, 42895}, {42896, 42957},
10296
  {42960, 42961}, {42963, 42963}, {42965, 42972}, {42994, 42996},
10297
  {42997, 42998}, {42999, 42999}, {43000, 43001}, {43002, 43002},
10298
  {43003, 43009}, {43011, 43013}, {43015, 43018}, {43020, 43042},
10299
  {43072, 43123}, {43138, 43187}, {43250, 43255}, {43259, 43259},
10300
  {43261, 43262}, {43274, 43301}, {43312, 43334}, {43360, 43388},
10301
  {43396, 43442}, {43471, 43471}, {43488, 43492}, {43494, 43494},
10302
  {43495, 43503}, {43514, 43518}, {43520, 43560}, {43584, 43586},
10303
  {43588, 43595}, {43616, 43631}, {43632, 43632}, {43633, 43638},
10304
  {43642, 43642}, {43646, 43695}, {43697, 43697}, {43701, 43702},
10305
  {43705, 43709}, {43712, 43712}, {43714, 43714}, {43739, 43740},
10306
  {43741, 43741}, {43744, 43754}, {43762, 43762}, {43763, 43764},
10307
  {43777, 43782}, {43785, 43790}, {43793, 43798}, {43808, 43814},
10308
  {43816, 43822}, {43824, 43866}, {43868, 43871}, {43872, 43880},
10309
  {43881, 43881}, {43888, 43967}, {43968, 44002}, {44032, 55203},
10310
  {55216, 55238}, {55243, 55291}, {63744, 64109}, {64112, 64217},
10311
  {64256, 64262}, {64275, 64279}, {64285, 64285}, {64287, 64296},
10312
  {64298, 64310}, {64312, 64316}, {64318, 64318}, {64320, 64321},
10313
  {64323, 64324}, {64326, 64433}, {64467, 64829}, {64848, 64911},
10314
  {64914, 64967}, {65008, 65019}, {65136, 65140}, {65142, 65276},
10315
  {65313, 65338}, {65345, 65370}, {65382, 65391}, {65392, 65392},
10316
  {65393, 65437}, {65438, 65439}, {65440, 65470}, {65474, 65479},
10317
  {65482, 65487}, {65490, 65495}, {65498, 65500}, {65536, 65547},
10318
  {65549, 65574}, {65576, 65594}, {65596, 65597}, {65599, 65613},
10319
  {65616, 65629}, {65664, 65786}, {65856, 65908}, {66176, 66204},
10320
  {66208, 66256}, {66304, 66335}, {66349, 66368}, {66369, 66369},
10321
  {66370, 66377}, {66378, 66378}, {66384, 66421}, {66432, 66461},
10322
  {66464, 66499}, {66504, 66511}, {66513, 66517}, {66560, 66639},
10323
  {66640, 66717}, {66736, 66771}, {66776, 66811}, {66816, 66855},
10324
  {66864, 66915}, {66928, 66938}, {66940, 66954}, {66956, 66962},
10325
  {66964, 66965}, {66967, 66977}, {66979, 66993}, {66995, 67001},
10326
  {67003, 67004}, {67008, 67059}, {67072, 67382}, {67392, 67413},
10327
  {67424, 67431}, {67456, 67461}, {67463, 67504}, {67506, 67514},
10328
  {67584, 67589}, {67592, 67592}, {67594, 67637}, {67639, 67640},
10329
  {67644, 67644}, {67647, 67669}, {67680, 67702}, {67712, 67742},
10330
  {67808, 67826}, {67828, 67829}, {67840, 67861}, {67872, 67897},
10331
  {67968, 68023}, {68030, 68031}, {68096, 68096}, {68112, 68115},
10332
  {68117, 68119}, {68121, 68149}, {68192, 68220}, {68224, 68252},
10333
  {68288, 68295}, {68297, 68324}, {68352, 68405}, {68416, 68437},
10334
  {68448, 68466}, {68480, 68497}, {68608, 68680}, {68736, 68786},
10335
  {68800, 68850}, {68864, 68899}, {68938, 68941}, {68942, 68942},
10336
  {68943, 68943}, {68944, 68965}, {68975, 68975}, {68976, 68997},
10337
  {69248, 69289}, {69296, 69297}, {69314, 69316}, {69376, 69404},
10338
  {69415, 69415}, {69424, 69445}, {69488, 69505}, {69552, 69572},
10339
  {69600, 69622}, {69635, 69687}, {69745, 69746}, {69749, 69749},
10340
  {69763, 69807}, {69840, 69864}, {69891, 69926}, {69956, 69956},
10341
  {69959, 69959}, {69968, 70002}, {70006, 70006}, {70019, 70066},
10342
  {70081, 70084}, {70106, 70106}, {70108, 70108}, {70144, 70161},
10343
  {70163, 70187}, {70207, 70208}, {70272, 70278}, {70280, 70280},
10344
  {70282, 70285}, {70287, 70301}, {70303, 70312}, {70320, 70366},
10345
  {70405, 70412}, {70415, 70416}, {70419, 70440}, {70442, 70448},
10346
  {70450, 70451}, {70453, 70457}, {70461, 70461}, {70480, 70480},
10347
  {70493, 70497}, {70528, 70537}, {70539, 70539}, {70542, 70542},
10348
  {70544, 70581}, {70583, 70583}, {70609, 70609}, {70611, 70611},
10349
  {70656, 70708}, {70727, 70730}, {70751, 70753}, {70784, 70831},
10350
  {70852, 70853}, {70855, 70855}, {71040, 71086}, {71128, 71131},
10351
  {71168, 71215}, {71236, 71236}, {71296, 71338}, {71352, 71352},
10352
  {71424, 71450}, {71488, 71494}, {71680, 71723}, {71840, 71903},
10353
  {71935, 71942}, {71945, 71945}, {71948, 71955}, {71957, 71958},
10354
  {71960, 71983}, {71999, 71999}, {72001, 72001}, {72096, 72103},
10355
  {72106, 72144}, {72161, 72161}, {72163, 72163}, {72192, 72192},
10356
  {72203, 72242}, {72250, 72250}, {72272, 72272}, {72284, 72329},
10357
  {72349, 72349}, {72368, 72440}, {72640, 72672}, {72704, 72712},
10358
  {72714, 72750}, {72768, 72768}, {72818, 72847}, {72960, 72966},
10359
  {72968, 72969}, {72971, 73008}, {73030, 73030}, {73056, 73061},
10360
  {73063, 73064}, {73066, 73097}, {73112, 73112}, {73440, 73458},
10361
  {73474, 73474}, {73476, 73488}, {73490, 73523}, {73648, 73648},
10362
  {73728, 74649}, {74752, 74862}, {74880, 75075}, {77712, 77808},
10363
  {77824, 78895}, {78913, 78918}, {78944, 82938}, {82944, 83526},
10364
  {90368, 90397}, {92160, 92728}, {92736, 92766}, {92784, 92862},
10365
  {92880, 92909}, {92928, 92975}, {92992, 92995}, {93027, 93047},
10366
  {93053, 93071}, {93504, 93506}, {93507, 93546}, {93547, 93548},
10367
  {93760, 93823}, {93952, 94026}, {94032, 94032}, {94099, 94111},
10368
  {94176, 94177}, {94179, 94179}, {94208, 100343}, {100352, 101589},
10369
  {101631, 101640}, {110576, 110579}, {110581, 110587}, {110589, 110590},
10370
  {110592, 110882}, {110898, 110898}, {110928, 110930}, {110933, 110933},
10371
  {110948, 110951}, {110960, 111355}, {113664, 113770}, {113776, 113788},
10372
  {113792, 113800}, {113808, 113817}, {119808, 119892}, {119894, 119964},
10373
  {119966, 119967}, {119970, 119970}, {119973, 119974}, {119977, 119980},
10374
  {119982, 119993}, {119995, 119995}, {119997, 120003}, {120005, 120069},
10375
  {120071, 120074}, {120077, 120084}, {120086, 120092}, {120094, 120121},
10376
  {120123, 120126}, {120128, 120132}, {120134, 120134}, {120138, 120144},
10377
  {120146, 120485}, {120488, 120512}, {120514, 120538}, {120540, 120570},
10378
  {120572, 120596}, {120598, 120628}, {120630, 120654}, {120656, 120686},
10379
  {120688, 120712}, {120714, 120744}, {120746, 120770}, {120772, 120779},
10380
  {122624, 122633}, {122634, 122634}, {122635, 122654}, {122661, 122666},
10381
  {122928, 122989}, {123136, 123180}, {123191, 123197}, {123214, 123214},
10382
  {123536, 123565}, {123584, 123627}, {124112, 124138}, {124139, 124139},
10383
  {124368, 124397}, {124400, 124400}, {124896, 124902}, {124904, 124907},
10384
  {124909, 124910}, {124912, 124926}, {124928, 125124}, {125184, 125251},
10385
  {125259, 125259}, {126464, 126467}, {126469, 126495}, {126497, 126498},
10386
  {126500, 126500}, {126503, 126503}, {126505, 126514}, {126516, 126519},
10387
  {126521, 126521}, {126523, 126523}, {126530, 126530}, {126535, 126535},
10388
  {126537, 126537}, {126539, 126539}, {126541, 126543}, {126545, 126546},
10389
  {126548, 126548}, {126551, 126551}, {126553, 126553}, {126555, 126555},
10390
  {126557, 126557}, {126559, 126559}, {126561, 126562}, {126564, 126564},
10391
  {126567, 126570}, {126572, 126578}, {126580, 126583}, {126585, 126588},
10392
  {126590, 126590}, {126592, 126601}, {126603, 126619}, {126625, 126627},
10393
  {126629, 126633}, {126635, 126651}, {131072, 173791}, {173824, 177977},
10394
  {177984, 178205}, {178208, 183969}, {183984, 191456}, {191472, 192093},
10395
  {194560, 195101}, {196608, 201546}, {201552, 205743}
10396
};
10397
10398
10399
} // namespace ada::idna
10400
#endif // ADA_IDNA_IDENTIFIER_TABLES_H
10401
/* end file src/id_tables.cpp */
10402
10403
namespace ada::idna {
10404
0
constexpr bool is_ascii_letter(char32_t c) noexcept {
10405
0
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
10406
0
}
10407
10408
0
constexpr bool is_ascii_letter_or_digit(char32_t c) noexcept {
10409
0
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
10410
0
         (c >= '0' && c <= '9');
10411
0
}
10412
10413
0
bool valid_name_code_point(char32_t code_point, bool first) {
10414
  // https://tc39.es/ecma262/#prod-IdentifierStart
10415
  // Fast paths:
10416
0
  if (first &&
10417
0
      (code_point == '$' || code_point == '_' || is_ascii_letter(code_point))) {
10418
0
    return true;
10419
0
  }
10420
0
  if (!first && (code_point == '$' || is_ascii_letter_or_digit(code_point))) {
10421
0
    return true;
10422
0
  }
10423
  // Slow path...
10424
0
  if (code_point == 0xffffffff) {
10425
0
    return false;  // minimal error handling
10426
0
  }
10427
0
  if (first) {
10428
0
    auto iter = std::lower_bound(
10429
0
        std::begin(ada::idna::id_start), std::end(ada::idna::id_start),
10430
0
        code_point,
10431
0
        [](const uint32_t* range, uint32_t cp) { return range[1] < cp; });
10432
0
    return iter != std::end(id_start) && code_point >= (*iter)[0];
10433
0
  } else {
10434
0
    auto iter = std::lower_bound(
10435
0
        std::begin(id_continue), std::end(id_continue), code_point,
10436
0
        [](const uint32_t* range, uint32_t cp) { return range[1] < cp; });
10437
0
    return iter != std::end(id_start) && code_point >= (*iter)[0];
10438
0
  }
10439
0
}
10440
}  // namespace ada::idna
10441
/* end file src/identifier.cpp */
10442
/* end file src/idna.cpp */
10443
/* end file src/ada_idna.cpp */
10444
ADA_POP_DISABLE_WARNINGS
10445
10446
#include <algorithm>
10447
#if ADA_SSSE3
10448
#include <tmmintrin.h>
10449
#elif ADA_NEON
10450
#include <arm_neon.h>
10451
#elif ADA_SSE2
10452
#include <emmintrin.h>
10453
#elif ADA_LSX
10454
#include <lsxintrin.h>
10455
#elif ADA_RVV
10456
#include <riscv_vector.h>
10457
#endif
10458
10459
#include <ranges>
10460
10461
namespace ada::unicode {
10462
10463
50.7k
constexpr bool is_tabs_or_newline(char c) noexcept {
10464
50.7k
  return c == '\r' || c == '\n' || c == '\t';
10465
50.7k
}
10466
10467
20.0k
constexpr uint64_t broadcast(uint8_t v) noexcept {
10468
20.0k
  return 0x101010101010101ull * v;
10469
20.0k
}
10470
10471
6.67k
constexpr bool to_lower_ascii(char* input, size_t length) noexcept {
10472
6.67k
  uint64_t broadcast_80 = broadcast(0x80);
10473
6.67k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
10474
6.67k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
10475
6.67k
  uint64_t non_ascii = 0;
10476
6.67k
  size_t i = 0;
10477
10478
7.35k
  for (; i + 7 < length; i += 8) {
10479
680
    uint64_t word{};
10480
680
    memcpy(&word, input + i, sizeof(word));
10481
680
    non_ascii |= (word & broadcast_80);
10482
680
    word ^=
10483
680
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10484
680
    memcpy(input + i, &word, sizeof(word));
10485
680
  }
10486
6.67k
  if (i < length) {
10487
6.64k
    uint64_t word{};
10488
6.64k
    memcpy(&word, input + i, length - i);
10489
6.64k
    non_ascii |= (word & broadcast_80);
10490
6.64k
    word ^=
10491
6.64k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10492
6.64k
    memcpy(input + i, &word, length - i);
10493
6.64k
  }
10494
6.67k
  return non_ascii == 0;
10495
6.67k
}
10496
#if ADA_SSSE3
10497
ada_really_inline bool has_tabs_or_newline(
10498
    std::string_view user_input) noexcept {
10499
  // first check for short strings in which case we do it naively.
10500
  if (user_input.size() < 16) {  // slow path
10501
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10502
  }
10503
  // fast path for long strings (expected to be common)
10504
  // Using SSSE3's _mm_shuffle_epi8 for table lookup (same approach as NEON)
10505
  size_t i = 0;
10506
  // Lookup table where positions 9, 10, 13 contain their own values
10507
  // Everything else is set to 1 so it won't match
10508
  const __m128i rnt =
10509
      _mm_setr_epi8(1, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 0, 0, 13, 0, 0);
10510
  __m128i running = _mm_setzero_si128();
10511
  for (; i + 15 < user_input.size(); i += 16) {
10512
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
10513
    // Shuffle the lookup table using input bytes as indices
10514
    __m128i shuffled = _mm_shuffle_epi8(rnt, word);
10515
    // Compare: if shuffled value matches input, we found \t, \n, or \r
10516
    __m128i matches = _mm_cmpeq_epi8(shuffled, word);
10517
    running = _mm_or_si128(running, matches);
10518
  }
10519
  if (i < user_input.size()) {
10520
    __m128i word = _mm_loadu_si128(
10521
        (const __m128i*)(user_input.data() + user_input.length() - 16));
10522
    __m128i shuffled = _mm_shuffle_epi8(rnt, word);
10523
    __m128i matches = _mm_cmpeq_epi8(shuffled, word);
10524
    running = _mm_or_si128(running, matches);
10525
  }
10526
  return _mm_movemask_epi8(running) != 0;
10527
}
10528
#elif ADA_NEON
10529
ada_really_inline bool has_tabs_or_newline(
10530
    std::string_view user_input) noexcept {
10531
  // first check for short strings in which case we do it naively.
10532
  if (user_input.size() < 16) {  // slow path
10533
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10534
  }
10535
  // fast path for long strings (expected to be common)
10536
  size_t i = 0;
10537
  /**
10538
   * The fastest way to check for `\t` (==9), '\n'(== 10) and `\r` (==13) relies
10539
   * on table lookup instruction. We notice that these are all unique numbers
10540
   * between 0..15. Let's prepare a special register, where we put '\t' in the
10541
   * 9th position, '\n' - 10th and '\r' - 13th. Then we shuffle this register by
10542
   * input register. If the input had `\t` in position X then this shuffled
10543
   * register will also have '\t' in that position. Comparing input with this
10544
   * shuffled register will mark us all interesting characters in the input.
10545
   *
10546
   * credit for algorithmic idea: @aqrit, credit for description:
10547
   * @DenisYaroshevskiy
10548
   */
10549
  static uint8_t rnt_array[16] = {1, 0, 0,  0, 0, 0,  0, 0,
10550
                                  0, 9, 10, 0, 0, 13, 0, 0};
10551
  const uint8x16_t rnt = vld1q_u8(rnt_array);
10552
  // m['0xd', '0xa', '0x9']
10553
  uint8x16_t running{0};
10554
  for (; i + 15 < user_input.size(); i += 16) {
10555
    uint8x16_t word = vld1q_u8((const uint8_t*)user_input.data() + i);
10556
10557
    running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word));
10558
  }
10559
  if (i < user_input.size()) {
10560
    uint8x16_t word =
10561
        vld1q_u8((const uint8_t*)user_input.data() + user_input.length() - 16);
10562
    running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word));
10563
  }
10564
  return vmaxvq_u32(vreinterpretq_u32_u8(running)) != 0;
10565
}
10566
#elif ADA_SSE2
10567
ada_really_inline bool has_tabs_or_newline(
10568
15.7k
    std::string_view user_input) noexcept {
10569
  // first check for short strings in which case we do it naively.
10570
15.7k
  if (user_input.size() < 16) {  // slow path
10571
12.3k
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10572
12.3k
  }
10573
  // fast path for long strings (expected to be common)
10574
3.41k
  size_t i = 0;
10575
3.41k
  const __m128i mask1 = _mm_set1_epi8('\r');
10576
3.41k
  const __m128i mask2 = _mm_set1_epi8('\n');
10577
3.41k
  const __m128i mask3 = _mm_set1_epi8('\t');
10578
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10579
3.41k
  __m128i running{0};
10580
16.5k
  for (; i + 15 < user_input.size(); i += 16) {
10581
13.1k
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
10582
13.1k
    running = _mm_or_si128(
10583
13.1k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10584
13.1k
                                           _mm_cmpeq_epi8(word, mask2))),
10585
13.1k
        _mm_cmpeq_epi8(word, mask3));
10586
13.1k
  }
10587
3.41k
  if (i < user_input.size()) {
10588
3.02k
    __m128i word = _mm_loadu_si128(
10589
3.02k
        (const __m128i*)(user_input.data() + user_input.length() - 16));
10590
3.02k
    running = _mm_or_si128(
10591
3.02k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10592
3.02k
                                           _mm_cmpeq_epi8(word, mask2))),
10593
3.02k
        _mm_cmpeq_epi8(word, mask3));
10594
3.02k
  }
10595
3.41k
  return _mm_movemask_epi8(running) != 0;
10596
15.7k
}
10597
#elif ADA_LSX
10598
ada_really_inline bool has_tabs_or_newline(
10599
    std::string_view user_input) noexcept {
10600
  // first check for short strings in which case we do it naively.
10601
  if (user_input.size() < 16) {  // slow path
10602
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10603
  }
10604
  // fast path for long strings (expected to be common)
10605
  size_t i = 0;
10606
  const __m128i mask1 = __lsx_vrepli_b('\r');
10607
  const __m128i mask2 = __lsx_vrepli_b('\n');
10608
  const __m128i mask3 = __lsx_vrepli_b('\t');
10609
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10610
  __m128i running{0};
10611
  for (; i + 15 < user_input.size(); i += 16) {
10612
    __m128i word = __lsx_vld((const __m128i*)(user_input.data() + i), 0);
10613
    running = __lsx_vor_v(
10614
        __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1),
10615
                                         __lsx_vseq_b(word, mask2))),
10616
        __lsx_vseq_b(word, mask3));
10617
  }
10618
  if (i < user_input.size()) {
10619
    __m128i word = __lsx_vld(
10620
        (const __m128i*)(user_input.data() + user_input.length() - 16), 0);
10621
    running = __lsx_vor_v(
10622
        __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1),
10623
                                         __lsx_vseq_b(word, mask2))),
10624
        __lsx_vseq_b(word, mask3));
10625
  }
10626
  if (__lsx_bz_v(running)) return false;
10627
  return true;
10628
}
10629
#elif ADA_RVV
10630
ada_really_inline bool has_tabs_or_newline(
10631
    std::string_view user_input) noexcept {
10632
  uint8_t* src = (uint8_t*)user_input.data();
10633
  for (size_t vl, n = user_input.size(); n > 0; n -= vl, src += vl) {
10634
    vl = __riscv_vsetvl_e8m1(n);
10635
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
10636
    vbool8_t m1 = __riscv_vmseq(v, '\r', vl);
10637
    vbool8_t m2 = __riscv_vmseq(v, '\n', vl);
10638
    vbool8_t m3 = __riscv_vmseq(v, '\t', vl);
10639
    vbool8_t m = __riscv_vmor(__riscv_vmor(m1, m2, vl), m3, vl);
10640
    long idx = __riscv_vfirst(m, vl);
10641
    if (idx >= 0) return true;
10642
  }
10643
  return false;
10644
}
10645
#else
10646
ada_really_inline bool has_tabs_or_newline(
10647
    std::string_view user_input) noexcept {
10648
  auto has_zero_byte = [](uint64_t v) {
10649
    return ((v - 0x0101010101010101) & ~(v) & 0x8080808080808080);
10650
  };
10651
  size_t i = 0;
10652
  uint64_t mask1 = broadcast('\r');
10653
  uint64_t mask2 = broadcast('\n');
10654
  uint64_t mask3 = broadcast('\t');
10655
  uint64_t running{0};
10656
  for (; i + 7 < user_input.size(); i += 8) {
10657
    uint64_t word{};
10658
    memcpy(&word, user_input.data() + i, sizeof(word));
10659
    uint64_t xor1 = word ^ mask1;
10660
    uint64_t xor2 = word ^ mask2;
10661
    uint64_t xor3 = word ^ mask3;
10662
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
10663
  }
10664
  if (i < user_input.size()) {
10665
    uint64_t word{};
10666
    memcpy(&word, user_input.data() + i, user_input.size() - i);
10667
    uint64_t xor1 = word ^ mask1;
10668
    uint64_t xor2 = word ^ mask2;
10669
    uint64_t xor3 = word ^ mask3;
10670
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
10671
  }
10672
  return running;
10673
}
10674
#endif
10675
10676
// A forbidden host code point is U+0000 NULL, U+0009 TAB, U+000A LF, U+000D CR,
10677
// U+0020 SPACE, U+0023 (#), U+002F (/), U+003A (:), U+003C (<), U+003E (>),
10678
// U+003F (?), U+0040 (@), U+005B ([), U+005C (\), U+005D (]), U+005E (^), or
10679
// U+007C (|).
10680
constexpr static std::array<uint8_t, 256> is_forbidden_host_code_point_table =
10681
    []() consteval {
10682
      std::array<uint8_t, 256> result{};
10683
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10684
                        '>', '?', '@', '[', '\\', ']', '^', '|'}) {
10685
        result[c] = true;
10686
      }
10687
      return result;
10688
    }();
10689
10690
ada_really_inline constexpr bool is_forbidden_host_code_point(
10691
6.74k
    const char c) noexcept {
10692
6.74k
  return is_forbidden_host_code_point_table[uint8_t(c)];
10693
6.74k
}
10694
10695
constexpr static std::array<uint8_t, 256> is_forbidden_domain_code_point_table =
10696
    []() consteval {
10697
      std::array<uint8_t, 256> result{};
10698
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10699
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
10700
        result[c] = true;
10701
      }
10702
      for (uint8_t c = 0; c <= 32; c++) {
10703
        result[c] = true;
10704
      }
10705
      for (size_t c = 127; c < 255; c++) {
10706
        result[c] = true;
10707
      }
10708
      return result;
10709
    }();
10710
10711
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
10712
10713
ada_really_inline constexpr bool is_forbidden_domain_code_point(
10714
155k
    const char c) noexcept {
10715
155k
  return is_forbidden_domain_code_point_table[uint8_t(c)];
10716
155k
}
10717
10718
ada_really_inline constexpr bool contains_forbidden_domain_code_point(
10719
3.19k
    const char* input, size_t length) noexcept {
10720
3.19k
  size_t i = 0;
10721
3.19k
  uint8_t accumulator{};
10722
57.4k
  for (; i + 4 <= length; i += 4) {
10723
54.2k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10724
54.2k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 1])];
10725
54.2k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 2])];
10726
54.2k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 3])];
10727
54.2k
  }
10728
8.31k
  for (; i < length; i++) {
10729
5.11k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10730
5.11k
  }
10731
3.19k
  return accumulator;
10732
3.19k
}
10733
10734
constexpr static std::array<uint8_t, 256>
10735
    is_forbidden_domain_code_point_table_or_upper = []() consteval {
10736
      std::array<uint8_t, 256> result{};
10737
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10738
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
10739
        result[c] = 1;
10740
      }
10741
      for (uint8_t c = 'A'; c <= 'Z'; c++) {
10742
        result[c] = 2;
10743
      }
10744
      for (uint8_t c = 0; c <= 32; c++) {
10745
        result[c] = 1;
10746
      }
10747
      for (size_t c = 127; c < 255; c++) {
10748
        result[c] = 1;
10749
      }
10750
      return result;
10751
    }();
10752
10753
ada_really_inline constexpr uint8_t
10754
contains_forbidden_domain_code_point_or_upper(const char* input,
10755
6.69k
                                              size_t length) noexcept {
10756
6.69k
  size_t i = 0;
10757
6.69k
  uint8_t accumulator{};
10758
47.2k
  for (; i + 4 <= length; i += 4) {
10759
40.5k
    accumulator |=
10760
40.5k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10761
40.5k
    accumulator |=
10762
40.5k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 1])];
10763
40.5k
    accumulator |=
10764
40.5k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 2])];
10765
40.5k
    accumulator |=
10766
40.5k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 3])];
10767
40.5k
  }
10768
17.2k
  for (; i < length; i++) {
10769
10.5k
    accumulator |=
10770
10.5k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10771
10.5k
  }
10772
6.69k
  return accumulator;
10773
6.69k
}
10774
10775
// std::isalnum(c) || c == '+' || c == '-' || c == '.') is true for
10776
constexpr static std::array<bool, 256> is_alnum_plus_table = []() consteval {
10777
  std::array<bool, 256> result{};
10778
  for (size_t c = 0; c < 256; c++) {
10779
    result[c] = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
10780
                (c >= 'A' && c <= 'Z') || c == '+' || c == '-' || c == '.';
10781
  }
10782
  return result;
10783
}();
10784
10785
27.6k
ada_really_inline constexpr bool is_alnum_plus(const char c) noexcept {
10786
27.6k
  return is_alnum_plus_table[uint8_t(c)];
10787
  // A table is almost surely much faster than the
10788
  // following under most compilers: return
10789
  // return (std::isalnum(c) || c == '+' || c == '-' || c == '.');
10790
27.6k
}
10791
10792
5.15k
ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept {
10793
5.15k
  return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
10794
2.69k
         (c >= 'a' && c <= 'f');
10795
5.15k
}
10796
10797
0
ada_really_inline constexpr bool is_ascii_digit(const char c) noexcept {
10798
  // An ASCII digit is a code point in the range U+0030 (0) to U+0039 (9),
10799
  // inclusive.
10800
0
  return (c >= '0' && c <= '9');
10801
0
}
10802
10803
0
ada_really_inline constexpr bool is_ascii(const char32_t c) noexcept {
10804
  // If code point is between U+0000 and U+007F inclusive, then return true.
10805
0
  return c <= 0x7F;
10806
0
}
10807
10808
24.7k
ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept {
10809
24.7k
  return (unsigned char)c <= ' ';
10810
24.7k
}
10811
10812
ada_really_inline constexpr bool is_ascii_tab_or_newline(
10813
10.8k
    const char c) noexcept {
10814
10.8k
  return c == '\t' || c == '\n' || c == '\r';
10815
10.8k
}
10816
10817
constexpr std::string_view table_is_double_dot_path_segment[] = {
10818
    "..", "%2e.", ".%2e", "%2e%2e"};
10819
10820
ada_really_inline constexpr bool is_double_dot_path_segment(
10821
0
    std::string_view input) noexcept {
10822
  // This will catch most cases:
10823
  // The length must be 2,4 or 6.
10824
  // We divide by two and require
10825
  // that the result be between 1 and 3 inclusively.
10826
0
  uint64_t half_length = uint64_t(input.size()) / 2;
10827
0
  if (half_length - 1 > 2) {
10828
0
    return false;
10829
0
  }
10830
  // We have a string of length 2, 4 or 6.
10831
  // We now check the first character:
10832
0
  if ((input[0] != '.') && (input[0] != '%')) {
10833
0
    return false;
10834
0
  }
10835
  // We are unlikely the get beyond this point.
10836
0
  int hash_value = (input.size() + (unsigned)(input[0])) & 3;
10837
0
  const std::string_view target = table_is_double_dot_path_segment[hash_value];
10838
0
  if (target.size() != input.size()) {
10839
0
    return false;
10840
0
  }
10841
  // We almost never get here.
10842
  // Optimizing the rest is relatively unimportant.
10843
0
  auto prefix_equal_unsafe = [](std::string_view a, std::string_view b) {
10844
0
    uint16_t A, B;
10845
0
    memcpy(&A, a.data(), sizeof(A));
10846
0
    memcpy(&B, b.data(), sizeof(B));
10847
0
    return A == B;
10848
0
  };
10849
0
  if (!prefix_equal_unsafe(input, target)) {
10850
0
    return false;
10851
0
  }
10852
0
  for (size_t i = 2; i < input.size(); i++) {
10853
0
    char c = input[i];
10854
0
    if ((uint8_t((c | 0x20) - 0x61) <= 25 ? (c | 0x20) : c) != target[i]) {
10855
0
      return false;
10856
0
    }
10857
0
  }
10858
0
  return true;
10859
  // The above code might be a bit better than the code below. Compilers
10860
  // are not stupid and may use the fact that these strings have length 2,4 and
10861
  // 6 and other tricks.
10862
  // return input == ".." ||
10863
  //  input == ".%2e" || input == ".%2E" ||
10864
  //  input == "%2e." || input == "%2E." ||
10865
  //  input == "%2e%2e" || input == "%2E%2E" || input == "%2E%2e" || input ==
10866
  //  "%2e%2E";
10867
0
}
10868
10869
ada_really_inline constexpr bool is_single_dot_path_segment(
10870
0
    std::string_view input) noexcept {
10871
0
  return input == "." || input == "%2e" || input == "%2E";
10872
0
}
10873
10874
6.97k
ada_really_inline constexpr bool is_lowercase_hex(const char c) noexcept {
10875
6.97k
  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
10876
6.97k
}
10877
10878
constexpr static char hex_to_binary_table[] = {
10879
    0,  1,  2,  3,  4, 5, 6, 7, 8, 9, 0, 0,  0,  0,  0,  0,  0, 10, 11,
10880
    12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0,  0,
10881
    0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
10882
2.61k
unsigned constexpr convert_hex_to_binary(const char c) noexcept {
10883
2.61k
  return hex_to_binary_table[c - '0'];
10884
2.61k
}
10885
10886
326
std::string percent_decode(const std::string_view input, size_t first_percent) {
10887
  // next line is for safety only, we expect users to avoid calling
10888
  // percent_decode when first_percent is outside the range.
10889
326
  if (first_percent == std::string_view::npos) {
10890
0
    return std::string(input);
10891
0
  }
10892
326
  std::string dest;
10893
326
  dest.reserve(input.length());
10894
326
  dest.append(input.substr(0, first_percent));
10895
326
  const char* pointer = input.data() + first_percent;
10896
326
  const char* end = input.data() + input.size();
10897
  // Optimization opportunity: if the following code gets
10898
  // called often, it can be optimized quite a bit.
10899
7.70k
  while (pointer < end) {
10900
7.38k
    const char ch = pointer[0];
10901
7.38k
    size_t remaining = end - pointer - 1;
10902
7.38k
    if (ch != '%' || remaining < 2 ||
10903
1.89k
        (  // ch == '%' && // It is unnecessary to check that ch == '%'.
10904
1.89k
            (!is_ascii_hex_digit(pointer[1]) ||
10905
6.71k
             !is_ascii_hex_digit(pointer[2])))) {
10906
6.71k
      dest += ch;
10907
6.71k
      pointer++;
10908
6.71k
    } else {
10909
667
      unsigned a = convert_hex_to_binary(pointer[1]);
10910
667
      unsigned b = convert_hex_to_binary(pointer[2]);
10911
667
      char c = static_cast<char>(a * 16 + b);
10912
667
      dest += c;
10913
667
      pointer += 3;
10914
667
    }
10915
7.38k
  }
10916
326
  return dest;
10917
326
}
10918
10919
std::string percent_encode(const std::string_view input,
10920
2.05k
                           const uint8_t character_set[]) {
10921
2.32k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10922
2.32k
    return character_sets::bit_at(character_set, c);
10923
2.32k
  });
10924
  // Optimization: Don't iterate if percent encode is not required
10925
2.05k
  if (pointer == input.end()) {
10926
1.79k
    return std::string(input);
10927
1.79k
  }
10928
10929
263
  std::string result;
10930
263
  result.reserve(input.length());  // in the worst case, percent encoding might
10931
                                   // produce 3 characters.
10932
263
  result.append(input.substr(0, std::distance(input.begin(), pointer)));
10933
10934
9.95k
  for (; pointer != input.end(); pointer++) {
10935
9.68k
    if (character_sets::bit_at(character_set, *pointer)) {
10936
7.98k
      result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10937
7.98k
    } else {
10938
1.70k
      result += *pointer;
10939
1.70k
    }
10940
9.68k
  }
10941
10942
263
  return result;
10943
2.05k
}
10944
10945
template <bool append>
10946
bool percent_encode(const std::string_view input, const uint8_t character_set[],
10947
108
                    std::string& out) {
10948
108
  ada_log("percent_encode ", input, " to output string while ",
10949
108
          append ? "appending" : "overwriting");
10950
563
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10951
563
    return character_sets::bit_at(character_set, c);
10952
563
  });
Unexecuted instantiation: ada::unicode::percent_encode<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)::{lambda(char)#1}::operator()(char) const
ada::unicode::percent_encode<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)::{lambda(char)#1}::operator()(char) const
Line
Count
Source
10950
563
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10951
563
    return character_sets::bit_at(character_set, c);
10952
563
  });
10953
108
  ada_log("percent_encode done checking, moved to ",
10954
108
          std::distance(input.begin(), pointer));
10955
10956
  // Optimization: Don't iterate if percent encode is not required
10957
108
  if (pointer == input.end()) {
10958
57
    ada_log("percent_encode encoding not needed.");
10959
57
    return false;
10960
57
  }
10961
51
  if constexpr (!append) {
10962
0
    out.clear();
10963
0
  }
10964
51
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10965
51
          " bytes");
10966
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10967
51
  out.append(input.data(), std::distance(input.begin(), pointer));
10968
51
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10969
51
          " bytes");
10970
1.16k
  for (; pointer != input.end(); pointer++) {
10971
1.11k
    if (character_sets::bit_at(character_set, *pointer)) {
10972
739
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10973
739
    } else {
10974
377
      out += *pointer;
10975
377
    }
10976
1.11k
  }
10977
51
  return true;
10978
108
}
Unexecuted instantiation: bool ada::unicode::percent_encode<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
bool ada::unicode::percent_encode<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Line
Count
Source
10947
108
                    std::string& out) {
10948
108
  ada_log("percent_encode ", input, " to output string while ",
10949
108
          append ? "appending" : "overwriting");
10950
108
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10951
108
    return character_sets::bit_at(character_set, c);
10952
108
  });
10953
108
  ada_log("percent_encode done checking, moved to ",
10954
108
          std::distance(input.begin(), pointer));
10955
10956
  // Optimization: Don't iterate if percent encode is not required
10957
108
  if (pointer == input.end()) {
10958
57
    ada_log("percent_encode encoding not needed.");
10959
57
    return false;
10960
57
  }
10961
  if constexpr (!append) {
10962
    out.clear();
10963
  }
10964
51
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10965
51
          " bytes");
10966
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10967
51
  out.append(input.data(), std::distance(input.begin(), pointer));
10968
51
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10969
51
          " bytes");
10970
1.16k
  for (; pointer != input.end(); pointer++) {
10971
1.11k
    if (character_sets::bit_at(character_set, *pointer)) {
10972
739
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10973
739
    } else {
10974
377
      out += *pointer;
10975
377
    }
10976
1.11k
  }
10977
51
  return true;
10978
108
}
10979
10980
bool to_ascii(std::optional<std::string>& out, const std::string_view plain,
10981
4.89k
              size_t first_percent) {
10982
4.89k
  std::string percent_decoded_buffer;
10983
4.89k
  std::string_view input = plain;
10984
4.89k
  if (first_percent != std::string_view::npos) {
10985
326
    percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
10986
326
    input = percent_decoded_buffer;
10987
326
  }
10988
  // input is a non-empty UTF-8 string, must be percent decoded
10989
4.89k
  std::string idna_ascii = ada::idna::to_ascii(input);
10990
4.89k
  if (idna_ascii.empty() || contains_forbidden_domain_code_point(
10991
3.19k
                                idna_ascii.data(), idna_ascii.size())) {
10992
2.32k
    return false;
10993
2.32k
  }
10994
2.57k
  out = std::move(idna_ascii);
10995
2.57k
  return true;
10996
4.89k
}
10997
10998
std::string percent_encode(const std::string_view input,
10999
171
                           const uint8_t character_set[], size_t index) {
11000
171
  std::string out;
11001
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
11002
171
  out.append(input.data(), index);
11003
171
  auto pointer = input.begin() + index;
11004
4.45k
  for (; pointer != input.end(); pointer++) {
11005
4.28k
    if (character_sets::bit_at(character_set, *pointer)) {
11006
3.44k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
11007
3.44k
    } else {
11008
845
      out += *pointer;
11009
845
    }
11010
4.28k
  }
11011
171
  return out;
11012
171
}
11013
11014
}  // namespace ada::unicode
11015
/* end file src/unicode.cpp */
11016
/* begin file src/serializers.cpp */
11017
#include <array>
11018
#include <charconv>
11019
#include <string>
11020
11021
namespace ada::serializers {
11022
11023
void find_longest_sequence_of_ipv6_pieces(
11024
    const std::array<uint16_t, 8>& address, size_t& compress,
11025
147
    size_t& compress_length) noexcept {
11026
609
  for (size_t i = 0; i < 8; i++) {
11027
502
    if (address[i] == 0) {
11028
210
      size_t next = i + 1;
11029
801
      while (next != 8 && address[next] == 0) ++next;
11030
210
      const size_t count = next - i;
11031
210
      if (compress_length < count) {
11032
149
        compress_length = count;
11033
149
        compress = i;
11034
149
        if (next == 8) break;
11035
109
        i = next;
11036
109
      }
11037
210
    }
11038
502
  }
11039
147
}
11040
11041
147
std::string ipv6(const std::array<uint16_t, 8>& address) noexcept {
11042
147
  size_t compress_length = 0;  // The length of a long sequence of zeros.
11043
147
  size_t compress = 0;         // The start of a long sequence of zeros.
11044
147
  find_longest_sequence_of_ipv6_pieces(address, compress, compress_length);
11045
11046
147
  if (compress_length <= 1) {
11047
    // Optimization opportunity: Find a faster way then snprintf for imploding
11048
    // and return here.
11049
28
    compress = compress_length = 8;
11050
28
  }
11051
11052
147
  std::string output(4 * 8 + 7 + 2, '\0');
11053
147
  size_t piece_index = 0;
11054
147
  char* point = output.data();
11055
147
  char* point_end = output.data() + output.size();
11056
147
  *point++ = '[';
11057
536
  while (true) {
11058
536
    if (piece_index == compress) {
11059
119
      *point++ = ':';
11060
      // If we skip a value initially, we need to write '::', otherwise
11061
      // a single ':' will do since it follows a previous ':'.
11062
119
      if (piece_index == 0) {
11063
59
        *point++ = ':';
11064
59
      }
11065
119
      piece_index += compress_length;
11066
119
      if (piece_index == 8) {
11067
40
        break;
11068
40
      }
11069
119
    }
11070
496
    point = std::to_chars(point, point_end, address[piece_index], 16).ptr;
11071
496
    piece_index++;
11072
496
    if (piece_index == 8) {
11073
107
      break;
11074
107
    }
11075
389
    *point++ = ':';
11076
389
  }
11077
147
  *point++ = ']';
11078
147
  output.resize(point - output.data());
11079
147
  return output;
11080
147
}
11081
11082
977
std::string ipv4(const uint64_t address) noexcept {
11083
977
  std::string output(15, '\0');
11084
977
  char* point = output.data();
11085
977
  char* point_end = output.data() + output.size();
11086
977
  point = std::to_chars(point, point_end, uint8_t(address >> 24)).ptr;
11087
3.90k
  for (int i = 2; i >= 0; i--) {
11088
2.93k
    *point++ = '.';
11089
2.93k
    point = std::to_chars(point, point_end, uint8_t(address >> (i * 8))).ptr;
11090
2.93k
  }
11091
977
  output.resize(point - output.data());
11092
977
  return output;
11093
977
}
11094
11095
}  // namespace ada::serializers
11096
/* end file src/serializers.cpp */
11097
/* begin file src/implementation.cpp */
11098
11099
#include <string_view>
11100
11101
11102
namespace ada {
11103
11104
template <class result_type>
11105
ada_warn_unused tl::expected<result_type, errors> parse(
11106
0
    std::string_view input, const result_type* base_url) {
11107
0
  result_type u =
11108
0
      ada::parser::parse_url_impl<result_type, true>(input, base_url);
11109
0
  if (!u.is_valid) {
11110
0
    return tl::unexpected(errors::type_error);
11111
0
  }
11112
0
  return u;
11113
0
}
Unexecuted instantiation: tl::expected<ada::url, ada::errors> ada::parse<ada::url>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url const*)
Unexecuted instantiation: tl::expected<ada::url_aggregator, ada::errors> ada::parse<ada::url_aggregator>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator const*)
11114
11115
template ada::result<url> parse<url>(std::string_view input,
11116
                                     const url* base_url = nullptr);
11117
template ada::result<url_aggregator> parse<url_aggregator>(
11118
    std::string_view input, const url_aggregator* base_url = nullptr);
11119
11120
0
std::string href_from_file(std::string_view input) {
11121
  // This is going to be much faster than constructing a URL.
11122
0
  std::string tmp_buffer;
11123
0
  std::string_view internal_input;
11124
0
  if (unicode::has_tabs_or_newline(input)) {
11125
0
    tmp_buffer = input;
11126
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
11127
0
    internal_input = tmp_buffer;
11128
0
  } else {
11129
0
    internal_input = input;
11130
0
  }
11131
0
  std::string path;
11132
0
  if (internal_input.empty()) {
11133
0
    path = "/";
11134
0
  } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
11135
0
    helpers::parse_prepared_path(internal_input.substr(1),
11136
0
                                 ada::scheme::type::FILE, path);
11137
0
  } else {
11138
0
    helpers::parse_prepared_path(internal_input, ada::scheme::type::FILE, path);
11139
0
  }
11140
0
  return "file://" + path;
11141
0
}
11142
11143
13.3k
bool can_parse(std::string_view input, const std::string_view* base_input) {
11144
13.3k
  ada::url_aggregator base_aggregator;
11145
13.3k
  ada::url_aggregator* base_pointer = nullptr;
11146
11147
13.3k
  if (base_input != nullptr) {
11148
6.68k
    base_aggregator = ada::parser::parse_url_impl<ada::url_aggregator, false>(
11149
6.68k
        *base_input, nullptr);
11150
6.68k
    if (!base_aggregator.is_valid) {
11151
4.33k
      return false;
11152
4.33k
    }
11153
2.35k
    base_pointer = &base_aggregator;
11154
2.35k
  }
11155
11156
9.04k
  ada::url_aggregator result =
11157
9.04k
      ada::parser::parse_url_impl<ada::url_aggregator, false>(input,
11158
9.04k
                                                              base_pointer);
11159
9.04k
  return result.is_valid;
11160
13.3k
}
11161
11162
0
ada_warn_unused std::string_view to_string(ada::encoding_type type) {
11163
0
  switch (type) {
11164
0
    case ada::encoding_type::UTF8:
11165
0
      return "UTF-8";
11166
0
    case ada::encoding_type::UTF_16LE:
11167
0
      return "UTF-16LE";
11168
0
    case ada::encoding_type::UTF_16BE:
11169
0
      return "UTF-16BE";
11170
0
    default:
11171
0
      unreachable();
11172
0
  }
11173
0
}
11174
11175
}  // namespace ada
11176
/* end file src/implementation.cpp */
11177
/* begin file src/helpers.cpp */
11178
#include <cstring>
11179
#include <sstream>
11180
11181
11182
#if ADA_SSSE3
11183
#include <tmmintrin.h>
11184
#endif
11185
11186
namespace ada::helpers {
11187
11188
template <typename out_iter>
11189
0
void encode_json(std::string_view view, out_iter out) {
11190
  // trivial implementation. could be faster.
11191
0
  const char* hexvalues =
11192
0
      "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
11193
0
  for (uint8_t c : view) {
11194
0
    if (c == '\\') {
11195
0
      *out++ = '\\';
11196
0
      *out++ = '\\';
11197
0
    } else if (c == '"') {
11198
0
      *out++ = '\\';
11199
0
      *out++ = '"';
11200
0
    } else if (c <= 0x1f) {
11201
0
      *out++ = '\\';
11202
0
      *out++ = 'u';
11203
0
      *out++ = '0';
11204
0
      *out++ = '0';
11205
0
      *out++ = hexvalues[2 * c];
11206
0
      *out++ = hexvalues[2 * c + 1];
11207
0
    } else {
11208
0
      *out++ = c;
11209
0
    }
11210
0
  }
11211
0
}
11212
11213
0
ada_unused std::string get_state(ada::state s) {
11214
0
  switch (s) {
11215
0
    case ada::state::AUTHORITY:
11216
0
      return "Authority";
11217
0
    case ada::state::SCHEME_START:
11218
0
      return "Scheme Start";
11219
0
    case ada::state::SCHEME:
11220
0
      return "Scheme";
11221
0
    case ada::state::HOST:
11222
0
      return "Host";
11223
0
    case ada::state::NO_SCHEME:
11224
0
      return "No Scheme";
11225
0
    case ada::state::FRAGMENT:
11226
0
      return "Fragment";
11227
0
    case ada::state::RELATIVE_SCHEME:
11228
0
      return "Relative Scheme";
11229
0
    case ada::state::RELATIVE_SLASH:
11230
0
      return "Relative Slash";
11231
0
    case ada::state::FILE:
11232
0
      return "File";
11233
0
    case ada::state::FILE_HOST:
11234
0
      return "File Host";
11235
0
    case ada::state::FILE_SLASH:
11236
0
      return "File Slash";
11237
0
    case ada::state::PATH_OR_AUTHORITY:
11238
0
      return "Path or Authority";
11239
0
    case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES:
11240
0
      return "Special Authority Ignore Slashes";
11241
0
    case ada::state::SPECIAL_AUTHORITY_SLASHES:
11242
0
      return "Special Authority Slashes";
11243
0
    case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY:
11244
0
      return "Special Relative or Authority";
11245
0
    case ada::state::QUERY:
11246
0
      return "Query";
11247
0
    case ada::state::PATH:
11248
0
      return "Path";
11249
0
    case ada::state::PATH_START:
11250
0
      return "Path Start";
11251
0
    case ada::state::OPAQUE_PATH:
11252
0
      return "Opaque Path";
11253
0
    case ada::state::PORT:
11254
0
      return "Port";
11255
0
    default:
11256
0
      return "unknown state";
11257
0
  }
11258
0
}
11259
11260
ada_really_inline std::optional<std::string_view> prune_hash(
11261
15.7k
    std::string_view& input) noexcept {
11262
  // compiles down to 20--30 instructions including a class to memchr (C
11263
  // function). this function should be quite fast.
11264
15.7k
  size_t location_of_first = input.find('#');
11265
15.7k
  if (location_of_first == std::string_view::npos) {
11266
15.2k
    return std::nullopt;
11267
15.2k
  }
11268
477
  std::string_view hash = input;
11269
477
  hash.remove_prefix(location_of_first + 1);
11270
477
  input.remove_suffix(input.size() - location_of_first);
11271
477
  return hash;
11272
15.7k
}
11273
11274
ada_really_inline bool shorten_path(std::string& path,
11275
0
                                    ada::scheme::type type) noexcept {
11276
  // Let path be url's path.
11277
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
11278
  // Windows drive letter, then return.
11279
0
  if (type == ada::scheme::type::FILE &&
11280
0
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11281
0
    if (checkers::is_normalized_windows_drive_letter(
11282
0
            helpers::substring(path, 1))) {
11283
0
      return false;
11284
0
    }
11285
0
  }
11286
11287
  // Remove path's last item, if any.
11288
0
  size_t last_delimiter = path.rfind('/');
11289
0
  if (last_delimiter != std::string::npos) {
11290
0
    path.erase(last_delimiter);
11291
0
    return true;
11292
0
  }
11293
11294
0
  return false;
11295
0
}
11296
11297
ada_really_inline bool shorten_path(std::string_view& path,
11298
182
                                    ada::scheme::type type) noexcept {
11299
  // Let path be url's path.
11300
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
11301
  // Windows drive letter, then return.
11302
182
  if (type == ada::scheme::type::FILE &&
11303
57
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11304
0
    if (checkers::is_normalized_windows_drive_letter(
11305
0
            helpers::substring(path, 1))) {
11306
0
      return false;
11307
0
    }
11308
0
  }
11309
11310
  // Remove path's last item, if any.
11311
182
  if (!path.empty()) {
11312
66
    size_t slash_loc = path.rfind('/');
11313
66
    if (slash_loc != std::string_view::npos) {
11314
51
      path.remove_suffix(path.size() - slash_loc);
11315
51
      return true;
11316
51
    }
11317
66
  }
11318
11319
131
  return false;
11320
182
}
11321
11322
ada_really_inline void remove_ascii_tab_or_newline(
11323
197
    std::string& input) noexcept {
11324
  // if this ever becomes a performance issue, we could use an approach similar
11325
  // to has_tabs_or_newline
11326
197
  std::erase_if(input, ada::unicode::is_ascii_tab_or_newline);
11327
197
}
11328
11329
ada_really_inline constexpr std::string_view substring(std::string_view input,
11330
0
                                                       size_t pos) noexcept {
11331
0
  ADA_ASSERT_TRUE(pos <= input.size());
11332
  // The following is safer but unneeded if we have the above line:
11333
  // return pos > input.size() ? std::string_view() : input.substr(pos);
11334
0
  return input.substr(pos);
11335
0
}
11336
11337
0
ada_really_inline void resize(std::string_view& input, size_t pos) noexcept {
11338
0
  ADA_ASSERT_TRUE(pos <= input.size());
11339
0
  input.remove_suffix(input.size() - pos);
11340
0
}
11341
11342
// computes the number of trailing zeroes
11343
// this is a private inline function only defined in this source file.
11344
1.41k
ada_really_inline int trailing_zeroes(uint32_t input_num) noexcept {
11345
#ifdef ADA_REGULAR_VISUAL_STUDIO
11346
  unsigned long ret;
11347
  // Search the mask data from least significant bit (LSB)
11348
  // to the most significant bit (MSB) for a set bit (1).
11349
  _BitScanForward(&ret, input_num);
11350
  return (int)ret;
11351
#else   // ADA_REGULAR_VISUAL_STUDIO
11352
1.41k
  return __builtin_ctzl(input_num);
11353
1.41k
#endif  // ADA_REGULAR_VISUAL_STUDIO
11354
1.41k
}
11355
11356
// starting at index location, this finds the next location of a character
11357
// :, /, \\, ? or [. If none is found, view.size() is returned.
11358
// For use within get_host_delimiter_location.
11359
#if ADA_SSSE3
11360
ada_really_inline size_t find_next_host_delimiter_special(
11361
    std::string_view view, size_t location) noexcept {
11362
  // first check for short strings in which case we do it naively.
11363
  if (view.size() - location < 16) {  // slow path
11364
    for (size_t i = location; i < view.size(); i++) {
11365
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11366
          view[i] == '?' || view[i] == '[') {
11367
        return i;
11368
      }
11369
    }
11370
    return size_t(view.size());
11371
  }
11372
  // fast path for long strings (expected to be common)
11373
  // Using SSSE3's _mm_shuffle_epi8 for table lookup (same approach as NEON)
11374
  size_t i = location;
11375
  const __m128i low_mask =
11376
      _mm_setr_epi8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11377
                    0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
11378
  const __m128i high_mask =
11379
      _mm_setr_epi8(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
11380
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11381
  const __m128i fmask = _mm_set1_epi8(0xf);
11382
  const __m128i zero = _mm_setzero_si128();
11383
  for (; i + 15 < view.size(); i += 16) {
11384
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11385
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
11386
    __m128i highpart = _mm_shuffle_epi8(
11387
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
11388
    __m128i classify = _mm_and_si128(lowpart, highpart);
11389
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
11390
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
11391
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
11392
    // avoid false positives.
11393
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
11394
    if (mask != 0) {
11395
      return i + trailing_zeroes(static_cast<uint32_t>(mask));
11396
    }
11397
  }
11398
  if (i < view.size()) {
11399
    __m128i word =
11400
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11401
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
11402
    __m128i highpart = _mm_shuffle_epi8(
11403
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
11404
    __m128i classify = _mm_and_si128(lowpart, highpart);
11405
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
11406
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
11407
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
11408
    // avoid false positives.
11409
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
11410
    if (mask != 0) {
11411
      return view.length() - 16 + trailing_zeroes(static_cast<uint32_t>(mask));
11412
    }
11413
  }
11414
  return size_t(view.size());
11415
}
11416
#elif ADA_NEON
11417
// The ada_make_uint8x16_t macro is necessary because Visual Studio does not
11418
// support direct initialization of uint8x16_t. See
11419
// https://developercommunity.visualstudio.com/t/error-C2078:-too-many-initializers-whe/402911?q=backend+neon
11420
#ifndef ada_make_uint8x16_t
11421
#define ada_make_uint8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
11422
                            x13, x14, x15, x16)                                \
11423
  ([=]() {                                                                     \
11424
    static uint8_t array[16] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8,          \
11425
                                x9, x10, x11, x12, x13, x14, x15, x16};        \
11426
    return vld1q_u8(array);                                                    \
11427
  }())
11428
#endif
11429
11430
ada_really_inline size_t find_next_host_delimiter_special(
11431
    std::string_view view, size_t location) noexcept {
11432
  // first check for short strings in which case we do it naively.
11433
  if (view.size() - location < 16) {  // slow path
11434
    for (size_t i = location; i < view.size(); i++) {
11435
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11436
          view[i] == '?' || view[i] == '[') {
11437
        return i;
11438
      }
11439
    }
11440
    return size_t(view.size());
11441
  }
11442
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
11443
    uint8x16_t bit_mask =
11444
        ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
11445
                            0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
11446
    uint8x16_t minput = vandq_u8(input, bit_mask);
11447
    uint8x16_t tmp = vpaddq_u8(minput, minput);
11448
    tmp = vpaddq_u8(tmp, tmp);
11449
    tmp = vpaddq_u8(tmp, tmp);
11450
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
11451
  };
11452
11453
  // fast path for long strings (expected to be common)
11454
  size_t i = location;
11455
  uint8x16_t low_mask =
11456
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11457
                          0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
11458
  uint8x16_t high_mask =
11459
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
11460
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11461
  uint8x16_t fmask = vmovq_n_u8(0xf);
11462
  uint8x16_t zero{0};
11463
  for (; i + 15 < view.size(); i += 16) {
11464
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
11465
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11466
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11467
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11468
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11469
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11470
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11471
      return i + trailing_zeroes(is_non_zero);
11472
    }
11473
  }
11474
11475
  if (i < view.size()) {
11476
    uint8x16_t word =
11477
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
11478
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11479
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11480
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11481
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11482
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11483
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11484
      return view.length() - 16 + trailing_zeroes(is_non_zero);
11485
    }
11486
  }
11487
  return size_t(view.size());
11488
}
11489
#elif ADA_SSE2
11490
ada_really_inline size_t find_next_host_delimiter_special(
11491
7.67k
    std::string_view view, size_t location) noexcept {
11492
  // first check for short strings in which case we do it naively.
11493
7.67k
  if (view.size() - location < 16) {  // slow path
11494
28.6k
    for (size_t i = location; i < view.size(); i++) {
11495
24.8k
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11496
24.1k
          view[i] == '?' || view[i] == '[') {
11497
1.22k
        return i;
11498
1.22k
      }
11499
24.8k
    }
11500
3.81k
    return size_t(view.size());
11501
5.03k
  }
11502
  // fast path for long strings (expected to be common)
11503
2.63k
  size_t i = location;
11504
2.63k
  const __m128i mask1 = _mm_set1_epi8(':');
11505
2.63k
  const __m128i mask2 = _mm_set1_epi8('/');
11506
2.63k
  const __m128i mask3 = _mm_set1_epi8('\\');
11507
2.63k
  const __m128i mask4 = _mm_set1_epi8('?');
11508
2.63k
  const __m128i mask5 = _mm_set1_epi8('[');
11509
11510
9.81k
  for (; i + 15 < view.size(); i += 16) {
11511
7.97k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11512
7.97k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11513
7.97k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11514
7.97k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11515
7.97k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11516
7.97k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11517
7.97k
    __m128i m = _mm_or_si128(
11518
7.97k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11519
7.97k
    int mask = _mm_movemask_epi8(m);
11520
7.97k
    if (mask != 0) {
11521
796
      return i + trailing_zeroes(mask);
11522
796
    }
11523
7.97k
  }
11524
1.83k
  if (i < view.size()) {
11525
1.58k
    __m128i word =
11526
1.58k
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11527
1.58k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11528
1.58k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11529
1.58k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11530
1.58k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11531
1.58k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11532
1.58k
    __m128i m = _mm_or_si128(
11533
1.58k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11534
1.58k
    int mask = _mm_movemask_epi8(m);
11535
1.58k
    if (mask != 0) {
11536
154
      return view.length() - 16 + trailing_zeroes(mask);
11537
154
    }
11538
1.58k
  }
11539
1.68k
  return size_t(view.length());
11540
1.83k
}
11541
#elif ADA_LSX
11542
ada_really_inline size_t find_next_host_delimiter_special(
11543
    std::string_view view, size_t location) noexcept {
11544
  // first check for short strings in which case we do it naively.
11545
  if (view.size() - location < 16) {  // slow path
11546
    for (size_t i = location; i < view.size(); i++) {
11547
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11548
          view[i] == '?' || view[i] == '[') {
11549
        return i;
11550
      }
11551
    }
11552
    return size_t(view.size());
11553
  }
11554
  // fast path for long strings (expected to be common)
11555
  size_t i = location;
11556
  const __m128i mask1 = __lsx_vrepli_b(':');
11557
  const __m128i mask2 = __lsx_vrepli_b('/');
11558
  const __m128i mask3 = __lsx_vrepli_b('\\');
11559
  const __m128i mask4 = __lsx_vrepli_b('?');
11560
  const __m128i mask5 = __lsx_vrepli_b('[');
11561
11562
  for (; i + 15 < view.size(); i += 16) {
11563
    __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0);
11564
    __m128i m1 = __lsx_vseq_b(word, mask1);
11565
    __m128i m2 = __lsx_vseq_b(word, mask2);
11566
    __m128i m3 = __lsx_vseq_b(word, mask3);
11567
    __m128i m4 = __lsx_vseq_b(word, mask4);
11568
    __m128i m5 = __lsx_vseq_b(word, mask5);
11569
    __m128i m =
11570
        __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5);
11571
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11572
    if (mask != 0) {
11573
      return i + trailing_zeroes(mask);
11574
    }
11575
  }
11576
  if (i < view.size()) {
11577
    __m128i word =
11578
        __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0);
11579
    __m128i m1 = __lsx_vseq_b(word, mask1);
11580
    __m128i m2 = __lsx_vseq_b(word, mask2);
11581
    __m128i m3 = __lsx_vseq_b(word, mask3);
11582
    __m128i m4 = __lsx_vseq_b(word, mask4);
11583
    __m128i m5 = __lsx_vseq_b(word, mask5);
11584
    __m128i m =
11585
        __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5);
11586
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11587
    if (mask != 0) {
11588
      return view.length() - 16 + trailing_zeroes(mask);
11589
    }
11590
  }
11591
  return size_t(view.length());
11592
}
11593
#elif ADA_RVV
11594
ada_really_inline size_t find_next_host_delimiter_special(
11595
    std::string_view view, size_t location) noexcept {
11596
  // The LUT approach was a bit slower on the SpacemiT X60, but I could see it
11597
  // being faster on future hardware.
11598
#if 0
11599
  // LUT generated using: s=":/\\?["; list(zip([((ord(c)>>2)&0xF)for c in s],s))
11600
  static const uint8_t tbl[16] = {
11601
    0xF, 0, 0, 0, 0, 0, '[', '\\', 0, 0, 0, '/', 0, 0, ':', '?'
11602
  };
11603
  vuint8m1_t vtbl = __riscv_vle8_v_u8m1(tbl, 16);
11604
#endif
11605
  uint8_t* src = (uint8_t*)view.data() + location;
11606
  for (size_t vl, n = view.size() - location; n > 0;
11607
       n -= vl, src += vl, location += vl) {
11608
    vl = __riscv_vsetvl_e8m1(n);
11609
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
11610
#if 0
11611
    vuint8m1_t vidx = __riscv_vand(__riscv_vsrl(v, 2, vl), 0xF, vl);
11612
    vuint8m1_t vlut = __riscv_vrgather(vtbl, vidx, vl);
11613
    vbool8_t m = __riscv_vmseq(v, vlut, vl);
11614
#else
11615
    vbool8_t m1 = __riscv_vmseq(v, ':', vl);
11616
    vbool8_t m2 = __riscv_vmseq(v, '/', vl);
11617
    vbool8_t m3 = __riscv_vmseq(v, '?', vl);
11618
    vbool8_t m4 = __riscv_vmseq(v, '[', vl);
11619
    vbool8_t m5 = __riscv_vmseq(v, '\\', vl);
11620
    vbool8_t m = __riscv_vmor(
11621
        __riscv_vmor(__riscv_vmor(m1, m2, vl), __riscv_vmor(m3, m4, vl), vl),
11622
        m5, vl);
11623
#endif
11624
    long idx = __riscv_vfirst(m, vl);
11625
    if (idx >= 0) return location + idx;
11626
  }
11627
  return size_t(view.size());
11628
}
11629
#else
11630
// : / [ \\ ?
11631
static constexpr std::array<uint8_t, 256> special_host_delimiters =
11632
    []() consteval {
11633
      std::array<uint8_t, 256> result{};
11634
      for (int i : {':', '/', '[', '\\', '?'}) {
11635
        result[i] = 1;
11636
      }
11637
      return result;
11638
    }();
11639
// credit: @the-moisrex recommended a table-based approach
11640
ada_really_inline size_t find_next_host_delimiter_special(
11641
    std::string_view view, size_t location) noexcept {
11642
  auto const str = view.substr(location);
11643
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
11644
    if (special_host_delimiters[(uint8_t)*pos]) {
11645
      return pos - str.begin() + location;
11646
    }
11647
  }
11648
  return size_t(view.size());
11649
}
11650
#endif
11651
11652
// starting at index location, this finds the next location of a character
11653
// :, /, ? or [. If none is found, view.size() is returned.
11654
// For use within get_host_delimiter_location.
11655
#if ADA_SSSE3
11656
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11657
                                                  size_t location) noexcept {
11658
  // first check for short strings in which case we do it naively.
11659
  if (view.size() - location < 16) {  // slow path
11660
    for (size_t i = location; i < view.size(); i++) {
11661
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11662
          view[i] == '[') {
11663
        return i;
11664
      }
11665
    }
11666
    return size_t(view.size());
11667
  }
11668
  // fast path for long strings (expected to be common)
11669
  size_t i = location;
11670
  // Lookup tables for bit classification:
11671
  // ':' (0x3A): low[0xA]=0x01, high[0x3]=0x01 -> match
11672
  // '/' (0x2F): low[0xF]=0x02, high[0x2]=0x02 -> match
11673
  // '?' (0x3F): low[0xF]=0x01, high[0x3]=0x01 -> match
11674
  // '[' (0x5B): low[0xB]=0x04, high[0x5]=0x04 -> match
11675
  const __m128i low_mask =
11676
      _mm_setr_epi8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11677
                    0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
11678
  const __m128i high_mask =
11679
      _mm_setr_epi8(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
11680
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11681
  const __m128i fmask = _mm_set1_epi8(0xf);
11682
  const __m128i zero = _mm_setzero_si128();
11683
11684
  for (; i + 15 < view.size(); i += 16) {
11685
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11686
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
11687
    __m128i highpart = _mm_shuffle_epi8(
11688
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
11689
    __m128i classify = _mm_and_si128(lowpart, highpart);
11690
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
11691
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
11692
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
11693
    // avoid false positives.
11694
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
11695
    if (mask != 0) {
11696
      return i + trailing_zeroes(static_cast<uint32_t>(mask));
11697
    }
11698
  }
11699
11700
  if (i < view.size()) {
11701
    __m128i word =
11702
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11703
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
11704
    __m128i highpart = _mm_shuffle_epi8(
11705
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
11706
    __m128i classify = _mm_and_si128(lowpart, highpart);
11707
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
11708
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
11709
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
11710
    // avoid false positives.
11711
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
11712
    if (mask != 0) {
11713
      return view.length() - 16 + trailing_zeroes(static_cast<uint32_t>(mask));
11714
    }
11715
  }
11716
  return size_t(view.size());
11717
}
11718
#elif ADA_NEON
11719
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11720
                                                  size_t location) noexcept {
11721
  // first check for short strings in which case we do it naively.
11722
  if (view.size() - location < 16) {  // slow path
11723
    for (size_t i = location; i < view.size(); i++) {
11724
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11725
          view[i] == '[') {
11726
        return i;
11727
      }
11728
    }
11729
    return size_t(view.size());
11730
  }
11731
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
11732
    uint8x16_t bit_mask =
11733
        ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
11734
                            0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
11735
    uint8x16_t minput = vandq_u8(input, bit_mask);
11736
    uint8x16_t tmp = vpaddq_u8(minput, minput);
11737
    tmp = vpaddq_u8(tmp, tmp);
11738
    tmp = vpaddq_u8(tmp, tmp);
11739
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
11740
  };
11741
11742
  // fast path for long strings (expected to be common)
11743
  size_t i = location;
11744
  uint8x16_t low_mask =
11745
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11746
                          0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
11747
  uint8x16_t high_mask =
11748
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
11749
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11750
  uint8x16_t fmask = vmovq_n_u8(0xf);
11751
  uint8x16_t zero{0};
11752
  for (; i + 15 < view.size(); i += 16) {
11753
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
11754
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11755
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11756
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11757
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11758
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11759
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11760
      return i + trailing_zeroes(is_non_zero);
11761
    }
11762
  }
11763
11764
  if (i < view.size()) {
11765
    uint8x16_t word =
11766
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
11767
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11768
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11769
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11770
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11771
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11772
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11773
      return view.length() - 16 + trailing_zeroes(is_non_zero);
11774
    }
11775
  }
11776
  return size_t(view.size());
11777
}
11778
#elif ADA_SSE2
11779
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11780
955
                                                  size_t location) noexcept {
11781
  // first check for short strings in which case we do it naively.
11782
955
  if (view.size() - location < 16) {  // slow path
11783
1.31k
    for (size_t i = location; i < view.size(); i++) {
11784
1.13k
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11785
1.05k
          view[i] == '[') {
11786
222
        return i;
11787
222
      }
11788
1.13k
    }
11789
178
    return size_t(view.size());
11790
400
  }
11791
  // fast path for long strings (expected to be common)
11792
555
  size_t i = location;
11793
555
  const __m128i mask1 = _mm_set1_epi8(':');
11794
555
  const __m128i mask2 = _mm_set1_epi8('/');
11795
555
  const __m128i mask4 = _mm_set1_epi8('?');
11796
555
  const __m128i mask5 = _mm_set1_epi8('[');
11797
11798
1.02k
  for (; i + 15 < view.size(); i += 16) {
11799
909
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11800
909
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11801
909
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11802
909
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11803
909
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11804
909
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
11805
909
    int mask = _mm_movemask_epi8(m);
11806
909
    if (mask != 0) {
11807
437
      return i + trailing_zeroes(mask);
11808
437
    }
11809
909
  }
11810
118
  if (i < view.size()) {
11811
70
    __m128i word =
11812
70
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11813
70
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11814
70
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11815
70
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11816
70
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11817
70
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
11818
70
    int mask = _mm_movemask_epi8(m);
11819
70
    if (mask != 0) {
11820
24
      return view.length() - 16 + trailing_zeroes(mask);
11821
24
    }
11822
70
  }
11823
94
  return size_t(view.length());
11824
118
}
11825
#elif ADA_LSX
11826
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11827
                                                  size_t location) noexcept {
11828
  // first check for short strings in which case we do it naively.
11829
  if (view.size() - location < 16) {  // slow path
11830
    for (size_t i = location; i < view.size(); i++) {
11831
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11832
          view[i] == '[') {
11833
        return i;
11834
      }
11835
    }
11836
    return size_t(view.size());
11837
  }
11838
  // fast path for long strings (expected to be common)
11839
  size_t i = location;
11840
  const __m128i mask1 = __lsx_vrepli_b(':');
11841
  const __m128i mask2 = __lsx_vrepli_b('/');
11842
  const __m128i mask4 = __lsx_vrepli_b('?');
11843
  const __m128i mask5 = __lsx_vrepli_b('[');
11844
11845
  for (; i + 15 < view.size(); i += 16) {
11846
    __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0);
11847
    __m128i m1 = __lsx_vseq_b(word, mask1);
11848
    __m128i m2 = __lsx_vseq_b(word, mask2);
11849
    __m128i m4 = __lsx_vseq_b(word, mask4);
11850
    __m128i m5 = __lsx_vseq_b(word, mask5);
11851
    __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5));
11852
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11853
    if (mask != 0) {
11854
      return i + trailing_zeroes(mask);
11855
    }
11856
  }
11857
  if (i < view.size()) {
11858
    __m128i word =
11859
        __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0);
11860
    __m128i m1 = __lsx_vseq_b(word, mask1);
11861
    __m128i m2 = __lsx_vseq_b(word, mask2);
11862
    __m128i m4 = __lsx_vseq_b(word, mask4);
11863
    __m128i m5 = __lsx_vseq_b(word, mask5);
11864
    __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5));
11865
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11866
    if (mask != 0) {
11867
      return view.length() - 16 + trailing_zeroes(mask);
11868
    }
11869
  }
11870
  return size_t(view.length());
11871
}
11872
#elif ADA_RVV
11873
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11874
                                                  size_t location) noexcept {
11875
  uint8_t* src = (uint8_t*)view.data() + location;
11876
  for (size_t vl, n = view.size() - location; n > 0;
11877
       n -= vl, src += vl, location += vl) {
11878
    vl = __riscv_vsetvl_e8m1(n);
11879
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
11880
    vbool8_t m1 = __riscv_vmseq(v, ':', vl);
11881
    vbool8_t m2 = __riscv_vmseq(v, '/', vl);
11882
    vbool8_t m3 = __riscv_vmseq(v, '?', vl);
11883
    vbool8_t m4 = __riscv_vmseq(v, '[', vl);
11884
    vbool8_t m =
11885
        __riscv_vmor(__riscv_vmor(m1, m2, vl), __riscv_vmor(m3, m4, vl), vl);
11886
    long idx = __riscv_vfirst(m, vl);
11887
    if (idx >= 0) return location + idx;
11888
  }
11889
  return size_t(view.size());
11890
}
11891
#else
11892
// : / [ ?
11893
static constexpr std::array<uint8_t, 256> host_delimiters = []() consteval {
11894
  std::array<uint8_t, 256> result{};
11895
  for (int i : {':', '/', '?', '['}) {
11896
    result[i] = 1;
11897
  }
11898
  return result;
11899
}();
11900
// credit: @the-moisrex recommended a table-based approach
11901
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11902
                                                  size_t location) noexcept {
11903
  auto const str = view.substr(location);
11904
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
11905
    if (host_delimiters[(uint8_t)*pos]) {
11906
      return pos - str.begin() + location;
11907
    }
11908
  }
11909
  return size_t(view.size());
11910
}
11911
#endif
11912
11913
ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
11914
6.99k
    const bool is_special, std::string_view& view) noexcept {
11915
  /**
11916
   * The spec at https://url.spec.whatwg.org/#hostname-state expects us to
11917
   * compute a variable called insideBrackets but this variable is only used
11918
   * once, to check whether a ':' character was found outside brackets. Exact
11919
   * text: "Otherwise, if c is U+003A (:) and insideBrackets is false, then:".
11920
   * It is conceptually simpler and arguably more efficient to just return a
11921
   * Boolean indicating whether ':' was found outside brackets.
11922
   */
11923
6.99k
  const size_t view_size = view.size();
11924
6.99k
  size_t location = 0;
11925
6.99k
  bool found_colon = false;
11926
  /**
11927
   * Performance analysis:
11928
   *
11929
   * We are basically seeking the end of the hostname which can be indicated
11930
   * by the end of the view, or by one of the characters ':', '/', '?', '\\'
11931
   * (where '\\' is only applicable for special URLs). However, these must
11932
   * appear outside a bracket range. E.g., if you have [something?]fd: then the
11933
   * '?' does not count.
11934
   *
11935
   * So we can skip ahead to the next delimiter, as long as we include '[' in
11936
   * the set of delimiters, and that we handle it first.
11937
   *
11938
   * So the trick is to have a fast function that locates the next delimiter.
11939
   * Unless we find '[', then it only needs to be called once! Ideally, such a
11940
   * function would be provided by the C++ standard library, but it seems that
11941
   * find_first_of is not very fast, so we are forced to roll our own.
11942
   *
11943
   * We do not break into two loops for speed, but for clarity.
11944
   */
11945
6.99k
  if (is_special) {
11946
    // We move to the next delimiter.
11947
6.55k
    location = find_next_host_delimiter_special(view, location);
11948
    // Unless we find '[' then we are going only going to have to call
11949
    // find_next_host_delimiter_special once.
11950
7.67k
    for (; location < view_size;
11951
6.55k
         location = find_next_host_delimiter_special(view, location)) {
11952
2.17k
      if (view[location] == '[') {
11953
1.23k
        location = view.find(']', location);
11954
1.23k
        if (location == std::string_view::npos) {
11955
          // performance: view.find might get translated to a memchr, which
11956
          // has no notion of std::string_view::npos, so the code does not
11957
          // reflect the assembly.
11958
112
          location = view_size;
11959
112
          break;
11960
112
        }
11961
1.23k
      } else {
11962
945
        found_colon = view[location] == ':';
11963
945
        break;
11964
945
      }
11965
2.17k
    }
11966
6.55k
  } else {
11967
    // We move to the next delimiter.
11968
440
    location = find_next_host_delimiter(view, location);
11969
    // Unless we find '[' then we are going only going to have to call
11970
    // find_next_host_delimiter_special once.
11971
955
    for (; location < view_size;
11972
683
         location = find_next_host_delimiter(view, location)) {
11973
683
      if (view[location] == '[') {
11974
531
        location = view.find(']', location);
11975
531
        if (location == std::string_view::npos) {
11976
          // performance: view.find might get translated to a memchr, which
11977
          // has no notion of std::string_view::npos, so the code does not
11978
          // reflect the assembly.
11979
16
          location = view_size;
11980
16
          break;
11981
16
        }
11982
531
      } else {
11983
152
        found_colon = view[location] == ':';
11984
152
        break;
11985
152
      }
11986
683
    }
11987
440
  }
11988
  // performance: remove_suffix may translate into a single instruction.
11989
6.99k
  view.remove_suffix(view_size - location);
11990
6.99k
  return {location, found_colon};
11991
6.99k
}
11992
11993
15.7k
void trim_c0_whitespace(std::string_view& input) noexcept {
11994
17.6k
  while (!input.empty() &&
11995
13.0k
         ada::unicode::is_c0_control_or_space(input.front())) {
11996
1.88k
    input.remove_prefix(1);
11997
1.88k
  }
11998
16.3k
  while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
11999
590
    input.remove_suffix(1);
12000
590
  }
12001
15.7k
}
12002
12003
ada_really_inline void parse_prepared_path(std::string_view input,
12004
                                           ada::scheme::type type,
12005
0
                                           std::string& path) {
12006
0
  ada_log("parse_prepared_path ", input);
12007
0
  uint8_t accumulator = checkers::path_signature(input);
12008
  // Let us first detect a trivial case.
12009
  // If it is special, we check that we have no dot, no %,  no \ and no
12010
  // character needing percent encoding. Otherwise, we check that we have no %,
12011
  // no dot, and no character needing percent encoding.
12012
0
  constexpr uint8_t need_encoding = 1;
12013
0
  constexpr uint8_t backslash_char = 2;
12014
0
  constexpr uint8_t dot_char = 4;
12015
0
  constexpr uint8_t percent_char = 8;
12016
0
  bool special = type != ada::scheme::NOT_SPECIAL;
12017
0
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
12018
0
                                      checkers::is_windows_drive_letter(input));
12019
0
  bool trivial_path =
12020
0
      (special ? (accumulator == 0)
12021
0
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
12022
0
                  0)) &&
12023
0
      (!may_need_slow_file_handling);
12024
0
  if (accumulator == dot_char && !may_need_slow_file_handling) {
12025
    // '4' means that we have at least one dot, but nothing that requires
12026
    // percent encoding or decoding. The only part that is not trivial is
12027
    // that we may have single dots and double dots path segments.
12028
    // If we have such segments, then we either have a path that begins
12029
    // with '.' (easy to check), or we have the sequence './'.
12030
    // Note: input cannot be empty, it must at least contain one character ('.')
12031
    // Note: we know that '\' is not present.
12032
0
    if (input[0] != '.') {
12033
0
      size_t slashdot = 0;
12034
0
      bool dot_is_file = true;
12035
0
      for (;;) {
12036
0
        slashdot = input.find("/.", slashdot);
12037
0
        if (slashdot == std::string_view::npos) {  // common case
12038
0
          break;
12039
0
        } else {  // uncommon
12040
          // only three cases matter: /./, /.. or a final /
12041
0
          slashdot += 2;
12042
0
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
12043
0
                           input[slashdot] == '/');
12044
0
        }
12045
0
      }
12046
0
      trivial_path = dot_is_file;
12047
0
    }
12048
0
  }
12049
0
  if (trivial_path) {
12050
0
    ada_log("parse_path trivial");
12051
0
    path += '/';
12052
0
    path += input;
12053
0
    return;
12054
0
  }
12055
  // We are going to need to look a bit at the path, but let us see if we can
12056
  // ignore percent encoding *and* backslashes *and* percent characters.
12057
  // Except for the trivial case, this is likely to capture 99% of paths out
12058
  // there.
12059
0
  bool fast_path =
12060
0
      (special &&
12061
0
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
12062
0
      (type != ada::scheme::type::FILE);
12063
0
  if (fast_path) {
12064
0
    ada_log("parse_prepared_path fast");
12065
    // Here we don't need to worry about \ or percent encoding.
12066
    // We also do not have a file protocol. We might have dots, however,
12067
    // but dots must as appear as '.', and they cannot be encoded because
12068
    // the symbol '%' is not present.
12069
0
    size_t previous_location = 0;  // We start at 0.
12070
0
    do {
12071
0
      size_t new_location = input.find('/', previous_location);
12072
      // std::string_view path_view = input;
12073
      //  We process the last segment separately:
12074
0
      if (new_location == std::string_view::npos) {
12075
0
        std::string_view path_view = input.substr(previous_location);
12076
0
        if (path_view == "..") {  // The path ends with ..
12077
          // e.g., if you receive ".." with an empty path, you go to "/".
12078
0
          if (path.empty()) {
12079
0
            path = '/';
12080
0
            return;
12081
0
          }
12082
          // Fast case where we have nothing to do:
12083
0
          if (path.back() == '/') {
12084
0
            return;
12085
0
          }
12086
          // If you have the path "/joe/myfriend",
12087
          // then you delete 'myfriend'.
12088
0
          path.resize(path.rfind('/') + 1);
12089
0
          return;
12090
0
        }
12091
0
        path += '/';
12092
0
        if (path_view != ".") {
12093
0
          path.append(path_view);
12094
0
        }
12095
0
        return;
12096
0
      } else {
12097
        // This is a non-final segment.
12098
0
        std::string_view path_view =
12099
0
            input.substr(previous_location, new_location - previous_location);
12100
0
        previous_location = new_location + 1;
12101
0
        if (path_view == "..") {
12102
0
          size_t last_delimiter = path.rfind('/');
12103
0
          if (last_delimiter != std::string::npos) {
12104
0
            path.erase(last_delimiter);
12105
0
          }
12106
0
        } else if (path_view != ".") {
12107
0
          path += '/';
12108
0
          path.append(path_view);
12109
0
        }
12110
0
      }
12111
0
    } while (true);
12112
0
  } else {
12113
0
    ada_log("parse_path slow");
12114
    // we have reached the general case
12115
0
    bool needs_percent_encoding = (accumulator & 1);
12116
0
    std::string path_buffer_tmp;
12117
0
    do {
12118
0
      size_t location = (special && (accumulator & 2))
12119
0
                            ? input.find_first_of("/\\")
12120
0
                            : input.find('/');
12121
0
      std::string_view path_view = input;
12122
0
      if (location != std::string_view::npos) {
12123
0
        path_view.remove_suffix(path_view.size() - location);
12124
0
        input.remove_prefix(location + 1);
12125
0
      }
12126
      // path_buffer is either path_view or it might point at a percent encoded
12127
      // temporary file.
12128
0
      std::string_view path_buffer =
12129
0
          (needs_percent_encoding &&
12130
0
           ada::unicode::percent_encode<false>(
12131
0
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
12132
0
              ? path_buffer_tmp
12133
0
              : path_view;
12134
0
      if (unicode::is_double_dot_path_segment(path_buffer)) {
12135
0
        helpers::shorten_path(path, type);
12136
0
        if (location == std::string_view::npos) {
12137
0
          path += '/';
12138
0
        }
12139
0
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
12140
0
                 (location == std::string_view::npos)) {
12141
0
        path += '/';
12142
0
      }
12143
      // Otherwise, if path_buffer is not a single-dot path segment, then:
12144
0
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
12145
        // If url's scheme is "file", url's path is empty, and path_buffer is a
12146
        // Windows drive letter, then replace the second code point in
12147
        // path_buffer with U+003A (:).
12148
0
        if (type == ada::scheme::type::FILE && path.empty() &&
12149
0
            checkers::is_windows_drive_letter(path_buffer)) {
12150
0
          path += '/';
12151
0
          path += path_buffer[0];
12152
0
          path += ':';
12153
0
          path_buffer.remove_prefix(2);
12154
0
          path.append(path_buffer);
12155
0
        } else {
12156
          // Append path_buffer to url's path.
12157
0
          path += '/';
12158
0
          path.append(path_buffer);
12159
0
        }
12160
0
      }
12161
0
      if (location == std::string_view::npos) {
12162
0
        return;
12163
0
      }
12164
0
    } while (true);
12165
0
  }
12166
0
}
12167
12168
0
bool overlaps(std::string_view input1, const std::string& input2) noexcept {
12169
0
  ada_log("helpers::overlaps check if string_view '", input1, "' [",
12170
0
          input1.size(), " bytes] is part of string '", input2, "' [",
12171
0
          input2.size(), " bytes]");
12172
0
  return !input1.empty() && !input2.empty() && input1.data() >= input2.data() &&
12173
0
         input1.data() < input2.data() + input2.size();
12174
0
}
12175
12176
template <class url_type>
12177
ada_really_inline void strip_trailing_spaces_from_opaque_path(
12178
0
    url_type& url) noexcept {
12179
0
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
12180
0
  if (!url.has_opaque_path) return;
12181
0
  if (url.has_hash()) return;
12182
0
  if (url.has_search()) return;
12183
12184
0
  auto path = std::string(url.get_pathname());
12185
0
  while (!path.empty() && path.back() == ' ') {
12186
0
    path.resize(path.size() - 1);
12187
0
  }
12188
0
  url.update_base_pathname(path);
12189
0
}
Unexecuted instantiation: void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url>(ada::url&)
Unexecuted instantiation: void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url_aggregator>(ada::url_aggregator&)
12190
12191
// @ / \\ ?
12192
static constexpr std::array<uint8_t, 256> authority_delimiter_special =
12193
    []() consteval {
12194
      std::array<uint8_t, 256> result{};
12195
      for (uint8_t i : {'@', '/', '\\', '?'}) {
12196
        result[i] = 1;
12197
      }
12198
      return result;
12199
    }();
12200
// credit: @the-moisrex recommended a table-based approach
12201
ada_really_inline size_t
12202
5.58k
find_authority_delimiter_special(std::string_view view) noexcept {
12203
  // performance note: we might be able to gain further performance
12204
  // with SIMD intrinsics.
12205
9.97k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12206
9.71k
    if (authority_delimiter_special[(uint8_t)*pos]) {
12207
5.32k
      return pos - view.begin();
12208
5.32k
    }
12209
9.71k
  }
12210
256
  return size_t(view.size());
12211
5.58k
}
12212
12213
// @ / ?
12214
static constexpr std::array<uint8_t, 256> authority_delimiter = []() consteval {
12215
  std::array<uint8_t, 256> result{};
12216
  for (uint8_t i : {'@', '/', '?'}) {
12217
    result[i] = 1;
12218
  }
12219
  return result;
12220
}();
12221
// credit: @the-moisrex recommended a table-based approach
12222
ada_really_inline size_t
12223
1.21k
find_authority_delimiter(std::string_view view) noexcept {
12224
  // performance note: we might be able to gain further performance
12225
  // with SIMD instrinsics.
12226
2.77k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12227
2.71k
    if (authority_delimiter[(uint8_t)*pos]) {
12228
1.15k
      return pos - view.begin();
12229
1.15k
    }
12230
2.71k
  }
12231
60
  return size_t(view.size());
12232
1.21k
}
12233
12234
}  // namespace ada::helpers
12235
12236
namespace ada {
12237
0
ada_warn_unused std::string to_string(ada::state state) {
12238
0
  return ada::helpers::get_state(state);
12239
0
}
12240
#undef ada_make_uint8x16_t
12241
}  // namespace ada
12242
/* end file src/helpers.cpp */
12243
/* begin file src/url.cpp */
12244
12245
#include <numeric>
12246
#include <algorithm>
12247
#include <iterator>
12248
#include <ranges>
12249
#include <string>
12250
#include <string_view>
12251
12252
namespace ada {
12253
12254
0
bool url::parse_opaque_host(std::string_view input) {
12255
0
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
12256
0
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
12257
0
    return is_valid = false;
12258
0
  }
12259
12260
  // Return the result of running UTF-8 percent-encode on input using the C0
12261
  // control percent-encode set.
12262
0
  host = ada::unicode::percent_encode(
12263
0
      input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
12264
0
  return true;
12265
0
}
12266
12267
0
bool url::parse_ipv4(std::string_view input) {
12268
0
  ada_log("parse_ipv4 ", input, " [", input.size(), " bytes]");
12269
0
  if (input.back() == '.') {
12270
0
    input.remove_suffix(1);
12271
0
  }
12272
0
  size_t digit_count{0};
12273
0
  int pure_decimal_count = 0;  // entries that are decimal
12274
0
  std::string_view original_input =
12275
0
      input;  // we might use this if pure_decimal_count == 4.
12276
0
  uint64_t ipv4{0};
12277
  // we could unroll for better performance?
12278
0
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
12279
0
    uint32_t
12280
0
        segment_result{};  // If any number exceeds 32 bits, we have an error.
12281
0
    bool is_hex = checkers::has_hex_prefix(input);
12282
0
    if (is_hex && ((input.length() == 2) ||
12283
0
                   ((input.length() > 2) && (input[2] == '.')))) {
12284
      // special case
12285
0
      segment_result = 0;
12286
0
      input.remove_prefix(2);
12287
0
    } else {
12288
0
      std::from_chars_result r{};
12289
0
      if (is_hex) {
12290
0
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
12291
0
                            segment_result, 16);
12292
0
      } else if ((input.length() >= 2) && input[0] == '0' &&
12293
0
                 checkers::is_digit(input[1])) {
12294
0
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
12295
0
                            segment_result, 8);
12296
0
      } else {
12297
0
        pure_decimal_count++;
12298
0
        r = std::from_chars(input.data(), input.data() + input.size(),
12299
0
                            segment_result, 10);
12300
0
      }
12301
0
      if (r.ec != std::errc()) {
12302
0
        return is_valid = false;
12303
0
      }
12304
0
      input.remove_prefix(r.ptr - input.data());
12305
0
    }
12306
0
    if (input.empty()) {
12307
      // We have the last value.
12308
      // At this stage, ipv4 contains digit_count*8 bits.
12309
      // So we have 32-digit_count*8 bits left.
12310
0
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
12311
0
        return is_valid = false;
12312
0
      }
12313
0
      ipv4 <<= (32 - digit_count * 8);
12314
0
      ipv4 |= segment_result;
12315
0
      goto final;
12316
0
    } else {
12317
      // There is more, so that the value must no be larger than 255
12318
      // and we must have a '.'.
12319
0
      if ((segment_result > 255) || (input[0] != '.')) {
12320
0
        return is_valid = false;
12321
0
      }
12322
0
      ipv4 <<= 8;
12323
0
      ipv4 |= segment_result;
12324
0
      input.remove_prefix(1);  // remove '.'
12325
0
    }
12326
0
  }
12327
0
  if ((digit_count != 4) || (!input.empty())) {
12328
0
    return is_valid = false;
12329
0
  }
12330
0
final:
12331
  // We could also check r.ptr to see where the parsing ended.
12332
0
  if (pure_decimal_count == 4) {
12333
0
    host = original_input;  // The original input was already all decimal and we
12334
                            // validated it.
12335
0
  } else {
12336
0
    host = ada::serializers::ipv4(ipv4);  // We have to reserialize the address.
12337
0
  }
12338
0
  host_type = IPV4;
12339
0
  return true;
12340
0
}
12341
12342
0
bool url::parse_ipv6(std::string_view input) {
12343
0
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
12344
12345
0
  if (input.empty()) {
12346
0
    return is_valid = false;
12347
0
  }
12348
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
12349
0
  std::array<uint16_t, 8> address{};
12350
12351
  // Let pieceIndex be 0.
12352
0
  int piece_index = 0;
12353
12354
  // Let compress be null.
12355
0
  std::optional<int> compress{};
12356
12357
  // Let pointer be a pointer for input.
12358
0
  std::string_view::iterator pointer = input.begin();
12359
12360
  // If c is U+003A (:), then:
12361
0
  if (input[0] == ':') {
12362
    // If remaining does not start with U+003A (:), validation error, return
12363
    // failure.
12364
0
    if (input.size() == 1 || input[1] != ':') {
12365
0
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
12366
0
      return is_valid = false;
12367
0
    }
12368
12369
    // Increase pointer by 2.
12370
0
    pointer += 2;
12371
12372
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
12373
0
    compress = ++piece_index;
12374
0
  }
12375
12376
  // While c is not the EOF code point:
12377
0
  while (pointer != input.end()) {
12378
    // If pieceIndex is 8, validation error, return failure.
12379
0
    if (piece_index == 8) {
12380
0
      ada_log("parse_ipv6 piece_index == 8");
12381
0
      return is_valid = false;
12382
0
    }
12383
12384
    // If c is U+003A (:), then:
12385
0
    if (*pointer == ':') {
12386
      // If compress is non-null, validation error, return failure.
12387
0
      if (compress.has_value()) {
12388
0
        ada_log("parse_ipv6 compress is non-null");
12389
0
        return is_valid = false;
12390
0
      }
12391
12392
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
12393
      // then continue.
12394
0
      pointer++;
12395
0
      compress = ++piece_index;
12396
0
      continue;
12397
0
    }
12398
12399
    // Let value and length be 0.
12400
0
    uint16_t value = 0, length = 0;
12401
12402
    // While length is less than 4 and c is an ASCII hex digit,
12403
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
12404
    // increase pointer and length by 1.
12405
0
    while (length < 4 && pointer != input.end() &&
12406
0
           unicode::is_ascii_hex_digit(*pointer)) {
12407
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12408
0
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
12409
0
      pointer++;
12410
0
      length++;
12411
0
    }
12412
12413
    // If c is U+002E (.), then:
12414
0
    if (pointer != input.end() && *pointer == '.') {
12415
      // If length is 0, validation error, return failure.
12416
0
      if (length == 0) {
12417
0
        ada_log("parse_ipv6 length is 0");
12418
0
        return is_valid = false;
12419
0
      }
12420
12421
      // Decrease pointer by length.
12422
0
      pointer -= length;
12423
12424
      // If pieceIndex is greater than 6, validation error, return failure.
12425
0
      if (piece_index > 6) {
12426
0
        ada_log("parse_ipv6 piece_index > 6");
12427
0
        return is_valid = false;
12428
0
      }
12429
12430
      // Let numbersSeen be 0.
12431
0
      int numbers_seen = 0;
12432
12433
      // While c is not the EOF code point:
12434
0
      while (pointer != input.end()) {
12435
        // Let ipv4Piece be null.
12436
0
        std::optional<uint16_t> ipv4_piece{};
12437
12438
        // If numbersSeen is greater than 0, then:
12439
0
        if (numbers_seen > 0) {
12440
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
12441
          // pointer by 1.
12442
0
          if (*pointer == '.' && numbers_seen < 4) {
12443
0
            pointer++;
12444
0
          }
12445
          // Otherwise, validation error, return failure.
12446
0
          else {
12447
0
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
12448
0
            return is_valid = false;
12449
0
          }
12450
0
        }
12451
12452
        // If c is not an ASCII digit, validation error, return failure.
12453
0
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
12454
0
          ada_log(
12455
0
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
12456
0
              "failure");
12457
0
          return is_valid = false;
12458
0
        }
12459
12460
        // While c is an ASCII digit:
12461
0
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
12462
          // Let number be c interpreted as decimal number.
12463
0
          int number = *pointer - '0';
12464
12465
          // If ipv4Piece is null, then set ipv4Piece to number.
12466
0
          if (!ipv4_piece.has_value()) {
12467
0
            ipv4_piece = number;
12468
0
          }
12469
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
12470
0
          else if (ipv4_piece == 0) {
12471
0
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
12472
0
            return is_valid = false;
12473
0
          }
12474
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
12475
0
          else {
12476
0
            ipv4_piece = *ipv4_piece * 10 + number;
12477
0
          }
12478
12479
          // If ipv4Piece is greater than 255, validation error, return failure.
12480
0
          if (ipv4_piece > 255) {
12481
0
            ada_log("parse_ipv6 ipv4_piece > 255");
12482
0
            return is_valid = false;
12483
0
          }
12484
12485
          // Increase pointer by 1.
12486
0
          pointer++;
12487
0
        }
12488
12489
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
12490
        // ipv4Piece.
12491
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12492
0
        address[piece_index] =
12493
0
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
12494
12495
        // Increase numbersSeen by 1.
12496
0
        numbers_seen++;
12497
12498
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
12499
0
        if (numbers_seen == 2 || numbers_seen == 4) {
12500
0
          piece_index++;
12501
0
        }
12502
0
      }
12503
12504
      // If numbersSeen is not 4, validation error, return failure.
12505
0
      if (numbers_seen != 4) {
12506
0
        return is_valid = false;
12507
0
      }
12508
12509
      // Break.
12510
0
      break;
12511
0
    }
12512
    // Otherwise, if c is U+003A (:):
12513
0
    else if ((pointer != input.end()) && (*pointer == ':')) {
12514
      // Increase pointer by 1.
12515
0
      pointer++;
12516
12517
      // If c is the EOF code point, validation error, return failure.
12518
0
      if (pointer == input.end()) {
12519
0
        ada_log(
12520
0
            "parse_ipv6 If c is the EOF code point, validation error, return "
12521
0
            "failure");
12522
0
        return is_valid = false;
12523
0
      }
12524
0
    }
12525
    // Otherwise, if c is not the EOF code point, validation error, return
12526
    // failure.
12527
0
    else if (pointer != input.end()) {
12528
0
      ada_log(
12529
0
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
12530
0
          "error, return failure");
12531
0
      return is_valid = false;
12532
0
    }
12533
12534
    // Set address[pieceIndex] to value.
12535
0
    address[piece_index] = value;
12536
12537
    // Increase pieceIndex by 1.
12538
0
    piece_index++;
12539
0
  }
12540
12541
  // If compress is non-null, then:
12542
0
  if (compress.has_value()) {
12543
    // Let swaps be pieceIndex - compress.
12544
0
    int swaps = piece_index - *compress;
12545
12546
    // Set pieceIndex to 7.
12547
0
    piece_index = 7;
12548
12549
    // While pieceIndex is not 0 and swaps is greater than 0,
12550
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
12551
    // decrease both pieceIndex and swaps by 1.
12552
0
    while (piece_index != 0 && swaps > 0) {
12553
0
      std::swap(address[piece_index], address[*compress + swaps - 1]);
12554
0
      piece_index--;
12555
0
      swaps--;
12556
0
    }
12557
0
  }
12558
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
12559
  // return failure.
12560
0
  else if (piece_index != 8) {
12561
0
    ada_log(
12562
0
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
12563
0
        "error, return failure");
12564
0
    return is_valid = false;
12565
0
  }
12566
0
  host = ada::serializers::ipv6(address);
12567
0
  ada_log("parse_ipv6 ", *host);
12568
0
  host_type = IPV6;
12569
0
  return true;
12570
0
}
12571
12572
template <bool has_state_override>
12573
0
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12574
0
  auto parsed_type = ada::scheme::get_scheme_type(input);
12575
0
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
12576
  /**
12577
   * In the common case, we will immediately recognize a special scheme (e.g.,
12578
   *http, https), in which case, we can go really fast.
12579
   **/
12580
0
  if (is_input_special) {  // fast path!!!
12581
0
    if constexpr (has_state_override) {
12582
      // If url's scheme is not a special scheme and buffer is a special scheme,
12583
      // then return.
12584
0
      if (is_special() != is_input_special) {
12585
0
        return false;
12586
0
      }
12587
12588
      // If url includes credentials or has a non-null port, and buffer is
12589
      // "file", then return.
12590
0
      if ((has_credentials() || port.has_value()) &&
12591
0
          parsed_type == ada::scheme::type::FILE) {
12592
0
        return false;
12593
0
      }
12594
12595
      // If url's scheme is "file" and its host is an empty host, then return.
12596
      // An empty host is the empty string.
12597
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
12598
0
          host.value().empty()) {
12599
0
        return false;
12600
0
      }
12601
0
    }
12602
12603
0
    type = parsed_type;
12604
12605
0
    if constexpr (has_state_override) {
12606
      // This is uncommon.
12607
0
      uint16_t urls_scheme_port = get_special_port();
12608
12609
0
      if (urls_scheme_port) {
12610
        // If url's port is url's scheme's default port, then set url's port to
12611
        // null.
12612
0
        if (port.has_value() && *port == urls_scheme_port) {
12613
0
          port = std::nullopt;
12614
0
        }
12615
0
      }
12616
0
    }
12617
0
  } else {  // slow path
12618
0
    std::string _buffer(input);
12619
    // Next function is only valid if the input is ASCII and returns false
12620
    // otherwise, but it seems that we always have ascii content so we do not
12621
    // need to check the return value.
12622
    // bool is_ascii =
12623
0
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
12624
12625
0
    if constexpr (has_state_override) {
12626
      // If url's scheme is a special scheme and buffer is not a special scheme,
12627
      // then return. If url's scheme is not a special scheme and buffer is a
12628
      // special scheme, then return.
12629
0
      if (is_special() != ada::scheme::is_special(_buffer)) {
12630
0
        return true;
12631
0
      }
12632
12633
      // If url includes credentials or has a non-null port, and buffer is
12634
      // "file", then return.
12635
0
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
12636
0
        return true;
12637
0
      }
12638
12639
      // If url's scheme is "file" and its host is an empty host, then return.
12640
      // An empty host is the empty string.
12641
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
12642
0
          host.value().empty()) {
12643
0
        return true;
12644
0
      }
12645
0
    }
12646
12647
0
    set_scheme(std::move(_buffer));
12648
12649
0
    if constexpr (has_state_override) {
12650
      // This is uncommon.
12651
0
      uint16_t urls_scheme_port = get_special_port();
12652
12653
0
      if (urls_scheme_port) {
12654
        // If url's port is url's scheme's default port, then set url's port to
12655
        // null.
12656
0
        if (port.has_value() && *port == urls_scheme_port) {
12657
0
          port = std::nullopt;
12658
0
        }
12659
0
      }
12660
0
    }
12661
0
  }
12662
12663
0
  return true;
12664
0
}
Unexecuted instantiation: bool ada::url::parse_scheme<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: bool ada::url::parse_scheme<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
12665
12666
0
ada_really_inline bool url::parse_host(std::string_view input) {
12667
0
  ada_log("parse_host ", input, " [", input.size(), " bytes]");
12668
0
  if (input.empty()) {
12669
0
    return is_valid = false;
12670
0
  }  // technically unnecessary.
12671
  // If input starts with U+005B ([), then:
12672
0
  if (input[0] == '[') {
12673
    // If input does not end with U+005D (]), validation error, return failure.
12674
0
    if (input.back() != ']') {
12675
0
      return is_valid = false;
12676
0
    }
12677
0
    ada_log("parse_host ipv6");
12678
12679
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
12680
    // trailing U+005D (]) removed.
12681
0
    input.remove_prefix(1);
12682
0
    input.remove_suffix(1);
12683
0
    return parse_ipv6(input);
12684
0
  }
12685
12686
  // If isNotSpecial is true, then return the result of opaque-host parsing
12687
  // input.
12688
0
  if (!is_special()) {
12689
0
    return parse_opaque_host(input);
12690
0
  }
12691
12692
  // Fast path: try to parse as pure decimal IPv4(a.b.c.d) first.
12693
0
  const uint64_t fast_result = checkers::try_parse_ipv4_fast(input);
12694
0
  if (fast_result < checkers::ipv4_fast_fail) {
12695
    // Fast path succeeded - input is pure decimal IPv4
12696
0
    if (!input.empty() && input.back() == '.') {
12697
0
      host = input.substr(0, input.size() - 1);
12698
0
    } else {
12699
0
      host = input;
12700
0
    }
12701
0
    host_type = IPV4;
12702
0
    ada_log("parse_host fast path decimal ipv4");
12703
0
    return true;
12704
0
  }
12705
  // Let domain be the result of running UTF-8 decode without BOM on the
12706
  // percent-decoding of input. Let asciiDomain be the result of running domain
12707
  // to ASCII with domain and false. The most common case is an ASCII input, in
12708
  // which case we do not need to call the expensive 'to_ascii' if a few
12709
  // conditions are met: no '%' and no 'xn-' subsequence.
12710
0
  std::string buffer = std::string(input);
12711
  // This next function checks that the result is ascii, but we are going to
12712
  // to check anyhow with is_forbidden.
12713
  // bool is_ascii =
12714
0
  unicode::to_lower_ascii(buffer.data(), buffer.size());
12715
0
  bool is_forbidden = unicode::contains_forbidden_domain_code_point(
12716
0
      buffer.data(), buffer.size());
12717
0
  if (is_forbidden == 0 && buffer.find("xn-") == std::string_view::npos) {
12718
    // fast path
12719
0
    host = std::move(buffer);
12720
12721
    // Check for other IPv4 formats (hex, octal, etc.)
12722
0
    if (checkers::is_ipv4(host.value())) {
12723
0
      ada_log("parse_host fast path ipv4");
12724
0
      return parse_ipv4(host.value());
12725
0
    }
12726
0
    ada_log("parse_host fast path ", *host);
12727
0
    return true;
12728
0
  }
12729
0
  ada_log("parse_host calling to_ascii");
12730
0
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
12731
0
  if (!is_valid) {
12732
0
    ada_log("parse_host to_ascii returns false");
12733
0
    return is_valid = false;
12734
0
  }
12735
0
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
12736
0
          " bytes]");
12737
12738
0
  if (std::any_of(host.value().begin(), host.value().end(),
12739
0
                  ada::unicode::is_forbidden_domain_code_point)) {
12740
0
    host = std::nullopt;
12741
0
    return is_valid = false;
12742
0
  }
12743
12744
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
12745
  // asciiDomain.
12746
0
  if (checkers::is_ipv4(host.value())) {
12747
0
    ada_log("parse_host got ipv4 ", *host);
12748
0
    return parse_ipv4(host.value());
12749
0
  }
12750
12751
0
  return true;
12752
0
}
12753
12754
0
ada_really_inline void url::parse_path(std::string_view input) {
12755
0
  ada_log("parse_path ", input);
12756
0
  std::string tmp_buffer;
12757
0
  std::string_view internal_input;
12758
0
  if (unicode::has_tabs_or_newline(input)) {
12759
0
    tmp_buffer = input;
12760
    // Optimization opportunity: Instead of copying and then pruning, we could
12761
    // just directly build the string from user_input.
12762
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12763
0
    internal_input = tmp_buffer;
12764
0
  } else {
12765
0
    internal_input = input;
12766
0
  }
12767
12768
  // If url is special, then:
12769
0
  if (is_special()) {
12770
0
    if (internal_input.empty()) {
12771
0
      path = "/";
12772
0
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
12773
0
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
12774
0
    } else {
12775
0
      helpers::parse_prepared_path(internal_input, type, path);
12776
0
    }
12777
0
  } else if (!internal_input.empty()) {
12778
0
    if (internal_input[0] == '/') {
12779
0
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
12780
0
    } else {
12781
0
      helpers::parse_prepared_path(internal_input, type, path);
12782
0
    }
12783
0
  } else {
12784
0
    if (!host.has_value()) {
12785
0
      path = "/";
12786
0
    }
12787
0
  }
12788
0
}
12789
12790
0
[[nodiscard]] std::string url::to_string() const {
12791
0
  if (!is_valid) {
12792
0
    return "null";
12793
0
  }
12794
0
  std::string answer;
12795
0
  auto back = std::back_insert_iterator(answer);
12796
0
  answer.append("{\n");
12797
0
  answer.append("\t\"protocol\":\"");
12798
0
  helpers::encode_json(get_protocol(), back);
12799
0
  answer.append("\",\n");
12800
0
  if (has_credentials()) {
12801
0
    answer.append("\t\"username\":\"");
12802
0
    helpers::encode_json(username, back);
12803
0
    answer.append("\",\n");
12804
0
    answer.append("\t\"password\":\"");
12805
0
    helpers::encode_json(password, back);
12806
0
    answer.append("\",\n");
12807
0
  }
12808
0
  if (host.has_value()) {
12809
0
    answer.append("\t\"host\":\"");
12810
0
    helpers::encode_json(host.value(), back);
12811
0
    answer.append("\",\n");
12812
0
  }
12813
0
  if (port.has_value()) {
12814
0
    answer.append("\t\"port\":\"");
12815
0
    answer.append(std::to_string(port.value()));
12816
0
    answer.append("\",\n");
12817
0
  }
12818
0
  answer.append("\t\"path\":\"");
12819
0
  helpers::encode_json(path, back);
12820
0
  answer.append("\",\n");
12821
0
  answer.append("\t\"opaque path\":");
12822
0
  answer.append((has_opaque_path ? "true" : "false"));
12823
0
  if (has_search()) {
12824
0
    answer.append(",\n");
12825
0
    answer.append("\t\"query\":\"");
12826
    // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
12827
0
    helpers::encode_json(query.value(), back);
12828
0
    answer.append("\"");
12829
0
  }
12830
0
  if (hash.has_value()) {
12831
0
    answer.append(",\n");
12832
0
    answer.append("\t\"hash\":\"");
12833
0
    helpers::encode_json(hash.value(), back);
12834
0
    answer.append("\"");
12835
0
  }
12836
0
  answer.append("\n}");
12837
0
  return answer;
12838
0
}
12839
12840
0
[[nodiscard]] bool url::has_valid_domain() const noexcept {
12841
0
  if (!host.has_value()) {
12842
0
    return false;
12843
0
  }
12844
0
  return checkers::verify_dns_length(host.value());
12845
0
}
12846
12847
0
[[nodiscard]] std::string url::get_origin() const noexcept {
12848
0
  if (is_special()) {
12849
    // Return a new opaque origin.
12850
0
    if (type == scheme::FILE) {
12851
0
      return "null";
12852
0
    }
12853
0
    return ada::helpers::concat(get_protocol(), "//", get_host());
12854
0
  }
12855
12856
0
  if (non_special_scheme == "blob") {
12857
0
    if (!path.empty()) {
12858
0
      auto result = ada::parse<ada::url>(path);
12859
0
      if (result &&
12860
0
          (result->type == scheme::HTTP || result->type == scheme::HTTPS)) {
12861
        // If pathURL's scheme is not "http" and not "https", then return a
12862
        // new opaque origin.
12863
0
        return ada::helpers::concat(result->get_protocol(), "//",
12864
0
                                    result->get_host());
12865
0
      }
12866
0
    }
12867
0
  }
12868
12869
  // Return a new opaque origin.
12870
0
  return "null";
12871
0
}
12872
12873
0
[[nodiscard]] std::string url::get_protocol() const noexcept {
12874
0
  if (is_special()) {
12875
0
    return helpers::concat(ada::scheme::details::is_special_list[type], ":");
12876
0
  }
12877
  // We only move the 'scheme' if it is non-special.
12878
0
  return helpers::concat(non_special_scheme, ":");
12879
0
}
12880
12881
0
[[nodiscard]] std::string url::get_host() const noexcept {
12882
  // If url's host is null, then return the empty string.
12883
  // If url's port is null, return url's host, serialized.
12884
  // Return url's host, serialized, followed by U+003A (:) and url's port,
12885
  // serialized.
12886
0
  if (!host.has_value()) {
12887
0
    return "";
12888
0
  }
12889
0
  if (port.has_value()) {
12890
0
    return host.value() + ":" + get_port();
12891
0
  }
12892
0
  return host.value();
12893
0
}
12894
12895
0
[[nodiscard]] std::string url::get_hostname() const noexcept {
12896
0
  return host.value_or("");
12897
0
}
12898
12899
0
[[nodiscard]] std::string url::get_search() const noexcept {
12900
  // If this's URL's query is either null or the empty string, then return the
12901
  // empty string. Return U+003F (?), followed by this's URL's query.
12902
0
  return (!query.has_value() || (query.value().empty())) ? ""
12903
0
                                                         : "?" + query.value();
12904
0
}
12905
12906
0
[[nodiscard]] const std::string& url::get_username() const noexcept {
12907
0
  return username;
12908
0
}
12909
12910
0
[[nodiscard]] const std::string& url::get_password() const noexcept {
12911
0
  return password;
12912
0
}
12913
12914
0
[[nodiscard]] std::string url::get_port() const noexcept {
12915
0
  return port.has_value() ? std::to_string(port.value()) : "";
12916
0
}
12917
12918
0
[[nodiscard]] std::string url::get_hash() const noexcept {
12919
  // If this's URL's fragment is either null or the empty string, then return
12920
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
12921
0
  return (!hash.has_value() || (hash.value().empty())) ? ""
12922
0
                                                       : "#" + hash.value();
12923
0
}
12924
12925
template <bool override_hostname>
12926
0
bool url::set_host_or_hostname(const std::string_view input) {
12927
0
  if (has_opaque_path) {
12928
0
    return false;
12929
0
  }
12930
12931
0
  std::optional<std::string> previous_host = host;
12932
0
  std::optional<uint16_t> previous_port = port;
12933
12934
0
  size_t host_end_pos = input.find('#');
12935
0
  std::string _host(input.data(), host_end_pos != std::string_view::npos
12936
0
                                      ? host_end_pos
12937
0
                                      : input.size());
12938
0
  helpers::remove_ascii_tab_or_newline(_host);
12939
0
  std::string_view new_host(_host);
12940
12941
  // If url's scheme is "file", then set state to file host state, instead of
12942
  // host state.
12943
0
  if (type != ada::scheme::type::FILE) {
12944
0
    std::string_view host_view(_host.data(), _host.length());
12945
0
    auto [location, found_colon] =
12946
0
        helpers::get_host_delimiter_location(is_special(), host_view);
12947
12948
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12949
    // Note: the 'found_colon' value is true if and only if a colon was
12950
    // encountered while not inside brackets.
12951
0
    if (found_colon) {
12952
      // If buffer is the empty string, host-missing validation error, return
12953
      // failure.
12954
0
      std::string_view buffer = host_view.substr(0, location);
12955
0
      if (buffer.empty()) {
12956
0
        return false;
12957
0
      }
12958
12959
      // If state override is given and state override is hostname state, then
12960
      // return failure.
12961
0
      if constexpr (override_hostname) {
12962
0
        return false;
12963
0
      }
12964
12965
      // Let host be the result of host parsing buffer with url is not special.
12966
0
      bool succeeded = parse_host(buffer);
12967
0
      if (!succeeded) {
12968
0
        host = std::move(previous_host);
12969
0
        update_base_port(previous_port);
12970
0
        return false;
12971
0
      }
12972
12973
      // Set url's host to host, buffer to the empty string, and state to port
12974
      // state.
12975
0
      std::string_view port_buffer = new_host.substr(location + 1);
12976
0
      if (!port_buffer.empty()) {
12977
0
        set_port(port_buffer);
12978
0
      }
12979
0
      return true;
12980
0
    }
12981
    // Otherwise, if one of the following is true:
12982
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12983
    // - url is special and c is U+005C (\)
12984
0
    else {
12985
      // If url is special and host_view is the empty string, host-missing
12986
      // validation error, return failure.
12987
0
      if (host_view.empty() && is_special()) {
12988
0
        return false;
12989
0
      }
12990
12991
      // Otherwise, if state override is given, host_view is the empty string,
12992
      // and either url includes credentials or url's port is non-null, then
12993
      // return failure.
12994
0
      if (host_view.empty() && (has_credentials() || port.has_value())) {
12995
0
        return false;
12996
0
      }
12997
12998
      // Let host be the result of host parsing host_view with url is not
12999
      // special.
13000
0
      if (host_view.empty() && !is_special()) {
13001
0
        host = "";
13002
0
        return true;
13003
0
      }
13004
13005
0
      bool succeeded = parse_host(host_view);
13006
0
      if (!succeeded) {
13007
0
        host = std::move(previous_host);
13008
0
        update_base_port(previous_port);
13009
0
        return false;
13010
0
      }
13011
0
      return true;
13012
0
    }
13013
0
  }
13014
13015
0
  size_t location = new_host.find_first_of("/\\?");
13016
0
  if (location != std::string_view::npos) {
13017
0
    new_host.remove_suffix(new_host.length() - location);
13018
0
  }
13019
13020
0
  if (new_host.empty()) {
13021
    // Set url's host to the empty string.
13022
0
    host = "";
13023
0
  } else {
13024
    // Let host be the result of host parsing buffer with url is not special.
13025
0
    if (!parse_host(new_host)) {
13026
0
      host = std::move(previous_host);
13027
0
      update_base_port(previous_port);
13028
0
      return false;
13029
0
    }
13030
13031
    // If host is "localhost", then set host to the empty string.
13032
0
    if (host == "localhost") {
13033
0
      host = "";
13034
0
    }
13035
0
  }
13036
0
  return true;
13037
0
}
Unexecuted instantiation: bool ada::url::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: bool ada::url::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
13038
13039
0
bool url::set_host(const std::string_view input) {
13040
0
  return set_host_or_hostname<false>(input);
13041
0
}
13042
13043
0
bool url::set_hostname(const std::string_view input) {
13044
0
  return set_host_or_hostname<true>(input);
13045
0
}
13046
13047
0
bool url::set_username(const std::string_view input) {
13048
0
  if (cannot_have_credentials_or_port()) {
13049
0
    return false;
13050
0
  }
13051
0
  username = ada::unicode::percent_encode(
13052
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
13053
0
  return true;
13054
0
}
13055
13056
0
bool url::set_password(const std::string_view input) {
13057
0
  if (cannot_have_credentials_or_port()) {
13058
0
    return false;
13059
0
  }
13060
0
  password = ada::unicode::percent_encode(
13061
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
13062
0
  return true;
13063
0
}
13064
13065
0
bool url::set_port(const std::string_view input) {
13066
0
  if (cannot_have_credentials_or_port()) {
13067
0
    return false;
13068
0
  }
13069
13070
0
  if (input.empty()) {
13071
0
    port = std::nullopt;
13072
0
    return true;
13073
0
  }
13074
13075
0
  std::string trimmed(input);
13076
0
  helpers::remove_ascii_tab_or_newline(trimmed);
13077
13078
0
  if (trimmed.empty()) {
13079
0
    return true;
13080
0
  }
13081
13082
  // Input should not start with a non-digit character.
13083
0
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
13084
0
    return false;
13085
0
  }
13086
13087
  // Find the first non-digit character to determine the length of digits
13088
0
  auto first_non_digit =
13089
0
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
13090
0
  std::string_view digits_to_parse =
13091
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
13092
13093
  // Revert changes if parse_port fails.
13094
0
  std::optional<uint16_t> previous_port = port;
13095
0
  parse_port(digits_to_parse);
13096
0
  if (is_valid) {
13097
0
    return true;
13098
0
  }
13099
0
  port = std::move(previous_port);
13100
0
  is_valid = true;
13101
0
  return false;
13102
0
}
13103
13104
0
void url::set_hash(const std::string_view input) {
13105
0
  if (input.empty()) {
13106
0
    hash = std::nullopt;
13107
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13108
0
    return;
13109
0
  }
13110
13111
0
  std::string new_value;
13112
0
  new_value = input[0] == '#' ? input.substr(1) : input;
13113
0
  helpers::remove_ascii_tab_or_newline(new_value);
13114
0
  hash = unicode::percent_encode(new_value,
13115
0
                                 ada::character_sets::FRAGMENT_PERCENT_ENCODE);
13116
0
}
13117
13118
0
void url::set_search(const std::string_view input) {
13119
0
  if (input.empty()) {
13120
0
    query = std::nullopt;
13121
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13122
0
    return;
13123
0
  }
13124
13125
0
  std::string new_value;
13126
0
  new_value = input[0] == '?' ? input.substr(1) : input;
13127
0
  helpers::remove_ascii_tab_or_newline(new_value);
13128
13129
0
  auto query_percent_encode_set =
13130
0
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13131
0
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
13132
13133
0
  query = ada::unicode::percent_encode(new_value, query_percent_encode_set);
13134
0
}
13135
13136
0
bool url::set_pathname(const std::string_view input) {
13137
0
  if (has_opaque_path) {
13138
0
    return false;
13139
0
  }
13140
0
  path.clear();
13141
0
  parse_path(input);
13142
0
  return true;
13143
0
}
13144
13145
0
bool url::set_protocol(const std::string_view input) {
13146
0
  std::string view(input);
13147
0
  helpers::remove_ascii_tab_or_newline(view);
13148
0
  if (view.empty()) {
13149
0
    return true;
13150
0
  }
13151
13152
  // Schemes should start with alpha values.
13153
0
  if (!checkers::is_alpha(view[0])) {
13154
0
    return false;
13155
0
  }
13156
13157
0
  view.append(":");
13158
13159
0
  std::string::iterator pointer =
13160
0
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
13161
13162
0
  if (pointer != view.end() && *pointer == ':') {
13163
0
    return parse_scheme<true>(
13164
0
        std::string_view(view.data(), pointer - view.begin()));
13165
0
  }
13166
0
  return false;
13167
0
}
13168
13169
0
bool url::set_href(const std::string_view input) {
13170
0
  ada::result<ada::url> out = ada::parse<ada::url>(input);
13171
13172
0
  if (out) {
13173
0
    *this = *out;
13174
0
  }
13175
13176
0
  return out.has_value();
13177
0
}
13178
13179
}  // namespace ada
13180
/* end file src/url.cpp */
13181
/* begin file src/parser.cpp */
13182
13183
#include <limits>
13184
#include <ranges>
13185
13186
13187
namespace ada::parser {
13188
13189
template <class result_type, bool store_values>
13190
result_type parse_url_impl(std::string_view user_input,
13191
15.7k
                           const result_type* base_url) {
13192
  // We can specialize the implementation per type.
13193
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
13194
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
13195
  // something else } is free (at runtime). This means that ada::url_aggregator
13196
  // and ada::url **do not have to support the exact same API**.
13197
15.7k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13198
15.7k
  constexpr bool result_type_is_ada_url_aggregator =
13199
15.7k
      std::is_same_v<url_aggregator, result_type>;
13200
15.7k
  static_assert(result_type_is_ada_url ||
13201
15.7k
                result_type_is_ada_url_aggregator);  // We don't support
13202
                                                     // anything else for now.
13203
13204
15.7k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13205
15.7k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13206
15.7k
          ")");
13207
13208
15.7k
  state state = state::SCHEME_START;
13209
15.7k
  result_type url{};
13210
13211
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
13212
  // surely the result of a bug or are otherwise a security concern.
13213
15.7k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) [[unlikely]] {
13214
0
    url.is_valid = false;
13215
0
  }
13216
  // Going forward, user_input.size() is in [0,
13217
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
13218
  // base, or the optional_url was invalid, we must return.
13219
15.7k
  if (base_url != nullptr) {
13220
2.35k
    url.is_valid &= base_url->is_valid;
13221
2.35k
  }
13222
15.7k
  if (!url.is_valid) {
13223
0
    return url;
13224
0
  }
13225
15.7k
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
13226
    // Most of the time, we just need user_input.size().
13227
    // In some instances, we may need a bit more.
13228
    ///////////////////////////
13229
    // This is *very* important. This line should *not* be removed
13230
    // hastily. There are principled reasons why reserve is important
13231
    // for performance. If you have a benchmark with small inputs,
13232
    // it may not matter, but in other instances, it could.
13233
    ////
13234
    // This rounds up to the next power of two.
13235
    // We know that user_input.size() is in [0,
13236
    // std::numeric_limits<uint32_t>::max).
13237
0
    uint32_t reserve_capacity =
13238
0
        (0xFFFFFFFF >>
13239
0
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13240
0
        1;
13241
0
    url.reserve(reserve_capacity);
13242
0
  }
13243
15.7k
  std::string tmp_buffer;
13244
15.7k
  std::string_view url_data;
13245
15.7k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13246
197
    tmp_buffer = user_input;
13247
    // Optimization opportunity: Instead of copying and then pruning, we could
13248
    // just directly build the string from user_input.
13249
197
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13250
197
    url_data = tmp_buffer;
13251
15.5k
  } else [[likely]] {
13252
15.5k
    url_data = user_input;
13253
15.5k
  }
13254
13255
  // Leading and trailing control characters are uncommon and easy to deal with
13256
  // (no performance concern).
13257
15.7k
  helpers::trim_c0_whitespace(url_data);
13258
13259
  // Optimization opportunity. Most websites do not have fragment.
13260
15.7k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13261
  // We add it last so that an implementation like ada::url_aggregator
13262
  // can append it last to its internal buffer, thus improving performance.
13263
13264
  // Here url_data no longer has its fragment.
13265
  // We are going to access the data from url_data (it is immutable).
13266
  // At any given time, we are pointing at byte 'input_position' in url_data.
13267
  // The input_position variable should range from 0 to input_size.
13268
  // It is illegal to access url_data at input_size.
13269
15.7k
  size_t input_position = 0;
13270
15.7k
  const size_t input_size = url_data.size();
13271
  // Keep running the following state machine by switching on state.
13272
  // If after a run pointer points to the EOF code point, go to the next step.
13273
  // Otherwise, increase pointer by 1 and continue with the state machine.
13274
  // We never decrement input_position.
13275
66.1k
  while (input_position <= input_size) {
13276
63.2k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13277
63.2k
            " in state ", ada::to_string(state));
13278
63.2k
    switch (state) {
13279
15.7k
      case state::SCHEME_START: {
13280
15.7k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13281
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13282
        // state to scheme state.
13283
15.7k
        if ((input_position != input_size) &&
13284
10.9k
            checkers::is_alpha(url_data[input_position])) {
13285
10.5k
          state = state::SCHEME;
13286
10.5k
          input_position++;
13287
10.5k
        } else {
13288
          // Otherwise, if state override is not given, set state to no scheme
13289
          // state and decrease pointer by 1.
13290
5.23k
          state = state::NO_SCHEME;
13291
5.23k
        }
13292
15.7k
        break;
13293
0
      }
13294
10.5k
      case state::SCHEME: {
13295
10.5k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13296
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13297
        // append c, lowercased, to buffer.
13298
27.7k
        while ((input_position != input_size) &&
13299
27.6k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13300
17.2k
          input_position++;
13301
17.2k
        }
13302
        // Otherwise, if c is U+003A (:), then:
13303
10.5k
        if ((input_position != input_size) &&
13304
10.3k
            (url_data[input_position] == ':')) {
13305
10.2k
          ada_log("SCHEME the scheme should be ",
13306
10.2k
                  url_data.substr(0, input_position));
13307
10.2k
          if constexpr (result_type_is_ada_url) {
13308
0
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13309
0
              return url;
13310
0
            }
13311
10.2k
          } else {
13312
            // we pass the colon along instead of painfully adding it back.
13313
10.2k
            if (!url.parse_scheme_with_colon(
13314
10.2k
                    url_data.substr(0, input_position + 1))) {
13315
0
              return url;
13316
0
            }
13317
10.2k
          }
13318
10.2k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13319
13320
          // If url's scheme is "file", then:
13321
10.2k
          if (url.type == scheme::type::FILE) {
13322
            // Set state to file state.
13323
928
            state = state::FILE;
13324
928
          }
13325
          // Otherwise, if url is special, base is non-null, and base's scheme
13326
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13327
          // != nullptr is false.
13328
9.29k
          else if (url.is_special() && base_url != nullptr &&
13329
1.50k
                   base_url->type == url.type) {
13330
            // Set state to special relative or authority state.
13331
43
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13332
43
          }
13333
          // Otherwise, if url is special, set state to special authority
13334
          // slashes state.
13335
9.24k
          else if (url.is_special()) {
13336
6.66k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13337
6.66k
          }
13338
          // Otherwise, if remaining starts with an U+002F (/), set state to
13339
          // path or authority state and increase pointer by 1.
13340
2.58k
          else if (input_position + 1 < input_size &&
13341
900
                   url_data[input_position + 1] == '/') {
13342
526
            state = state::PATH_OR_AUTHORITY;
13343
526
            input_position++;
13344
526
          }
13345
          // Otherwise, set url's path to the empty string and set state to
13346
          // opaque path state.
13347
2.05k
          else {
13348
2.05k
            state = state::OPAQUE_PATH;
13349
2.05k
          }
13350
10.2k
        }
13351
        // Otherwise, if state override is not given, set buffer to the empty
13352
        // string, state to no scheme state, and start over (from the first code
13353
        // point in input).
13354
284
        else {
13355
284
          state = state::NO_SCHEME;
13356
284
          input_position = 0;
13357
284
          break;
13358
284
        }
13359
10.2k
        input_position++;
13360
10.2k
        break;
13361
10.5k
      }
13362
5.51k
      case state::NO_SCHEME: {
13363
5.51k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13364
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13365
        // validation error, return failure.
13366
5.51k
        if (base_url == nullptr ||
13367
5.06k
            (base_url->has_opaque_path && !fragment.has_value())) {
13368
5.06k
          ada_log("NO_SCHEME validation error");
13369
5.06k
          url.is_valid = false;
13370
5.06k
          return url;
13371
5.06k
        }
13372
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13373
        // set url's scheme to base's scheme, url's path to base's path, url's
13374
        // query to base's query, and set state to fragment state.
13375
454
        else if (base_url->has_opaque_path && fragment.has_value() &&
13376
199
                 input_position == input_size) {
13377
108
          ada_log("NO_SCHEME opaque base with fragment");
13378
108
          url.copy_scheme(*base_url);
13379
108
          url.has_opaque_path = base_url->has_opaque_path;
13380
13381
108
          if constexpr (result_type_is_ada_url) {
13382
0
            url.path = base_url->path;
13383
0
            url.query = base_url->query;
13384
108
          } else {
13385
108
            url.update_base_pathname(base_url->get_pathname());
13386
108
            url.update_base_search(base_url->get_search());
13387
108
          }
13388
108
          url.update_unencoded_base_hash(*fragment);
13389
108
          return url;
13390
108
        }
13391
        // Otherwise, if base's scheme is not "file", set state to relative
13392
        // state and decrease pointer by 1.
13393
346
        else if (base_url->type != scheme::type::FILE) {
13394
242
          ada_log("NO_SCHEME non-file relative path");
13395
242
          state = state::RELATIVE_SCHEME;
13396
242
        }
13397
        // Otherwise, set state to file state and decrease pointer by 1.
13398
104
        else {
13399
104
          ada_log("NO_SCHEME file base type");
13400
104
          state = state::FILE;
13401
104
        }
13402
346
        break;
13403
5.51k
      }
13404
7.15k
      case state::AUTHORITY: {
13405
7.15k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13406
        // most URLs have no @. Having no @ tells us that we don't have to worry
13407
        // about AUTHORITY. Of course, we could have @ and still not have to
13408
        // worry about AUTHORITY.
13409
        // TODO: Instead of just collecting a bool, collect the location of the
13410
        // '@' and do something useful with it.
13411
        // TODO: We could do various processing early on, using a single pass
13412
        // over the string to collect information about it, e.g., telling us
13413
        // whether there is a @ and if so, where (or how many).
13414
13415
        // Check if url data contains an @.
13416
7.15k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13417
6.79k
          state = state::HOST;
13418
6.79k
          break;
13419
6.79k
        }
13420
362
        bool at_sign_seen{false};
13421
362
        bool password_token_seen{false};
13422
        /**
13423
         * We expect something of the sort...
13424
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13425
         * --------^
13426
         */
13427
6.79k
        do {
13428
6.79k
          std::string_view view = url_data.substr(input_position);
13429
          // The delimiters are @, /, ? \\.
13430
6.79k
          size_t location =
13431
6.79k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13432
6.79k
                               : helpers::find_authority_delimiter(view);
13433
6.79k
          std::string_view authority_view = view.substr(0, location);
13434
6.79k
          size_t end_of_authority = input_position + authority_view.size();
13435
          // If c is U+0040 (@), then:
13436
6.79k
          if ((end_of_authority != input_size) &&
13437
6.48k
              (url_data[end_of_authority] == '@')) {
13438
            // If atSignSeen is true, then prepend "%40" to buffer.
13439
6.43k
            if (at_sign_seen) {
13440
6.08k
              if (password_token_seen) {
13441
2.23k
                if constexpr (result_type_is_ada_url) {
13442
0
                  url.password += "%40";
13443
2.23k
                } else {
13444
2.23k
                  url.append_base_password("%40");
13445
2.23k
                }
13446
3.85k
              } else {
13447
3.85k
                if constexpr (result_type_is_ada_url) {
13448
0
                  url.username += "%40";
13449
3.85k
                } else {
13450
3.85k
                  url.append_base_username("%40");
13451
3.85k
                }
13452
3.85k
              }
13453
6.08k
            }
13454
13455
6.43k
            at_sign_seen = true;
13456
13457
6.43k
            if (!password_token_seen) {
13458
4.20k
              size_t password_token_location = authority_view.find(':');
13459
4.20k
              password_token_seen =
13460
4.20k
                  password_token_location != std::string_view::npos;
13461
13462
4.20k
              if constexpr (store_values) {
13463
0
                if (!password_token_seen) {
13464
0
                  if constexpr (result_type_is_ada_url) {
13465
0
                    url.username += unicode::percent_encode(
13466
0
                        authority_view,
13467
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13468
0
                  } else {
13469
0
                    url.append_base_username(unicode::percent_encode(
13470
0
                        authority_view,
13471
0
                        character_sets::USERINFO_PERCENT_ENCODE));
13472
0
                  }
13473
0
                } else {
13474
0
                  if constexpr (result_type_is_ada_url) {
13475
0
                    url.username += unicode::percent_encode(
13476
0
                        authority_view.substr(0, password_token_location),
13477
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13478
0
                    url.password += unicode::percent_encode(
13479
0
                        authority_view.substr(password_token_location + 1),
13480
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13481
0
                  } else {
13482
0
                    url.append_base_username(unicode::percent_encode(
13483
0
                        authority_view.substr(0, password_token_location),
13484
0
                        character_sets::USERINFO_PERCENT_ENCODE));
13485
0
                    url.append_base_password(unicode::percent_encode(
13486
0
                        authority_view.substr(password_token_location + 1),
13487
0
                        character_sets::USERINFO_PERCENT_ENCODE));
13488
0
                  }
13489
0
                }
13490
0
              }
13491
4.20k
            } else if constexpr (store_values) {
13492
0
              if constexpr (result_type_is_ada_url) {
13493
0
                url.password += unicode::percent_encode(
13494
0
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13495
0
              } else {
13496
0
                url.append_base_password(unicode::percent_encode(
13497
0
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13498
0
              }
13499
0
            }
13500
6.43k
          }
13501
          // Otherwise, if one of the following is true:
13502
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13503
          // - url is special and c is U+005C (\)
13504
362
          else if (end_of_authority == input_size ||
13505
46
                   url_data[end_of_authority] == '/' ||
13506
22
                   url_data[end_of_authority] == '?' ||
13507
362
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13508
            // If atSignSeen is true and authority_view is the empty string,
13509
            // validation error, return failure.
13510
362
            if (at_sign_seen && authority_view.empty()) {
13511
162
              url.is_valid = false;
13512
162
              return url;
13513
162
            }
13514
200
            state = state::HOST;
13515
200
            break;
13516
362
          }
13517
6.43k
          if (end_of_authority == input_size) {
13518
0
            if constexpr (store_values) {
13519
0
              if (fragment.has_value()) {
13520
0
                url.update_unencoded_base_hash(*fragment);
13521
0
              }
13522
0
            }
13523
0
            return url;
13524
0
          }
13525
6.43k
          input_position = end_of_authority + 1;
13526
6.43k
        } while (true);
13527
13528
200
        break;
13529
362
      }
13530
200
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
13531
43
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
13532
43
                helpers::substring(url_data, input_position));
13533
13534
        // If c is U+002F (/) and remaining starts with U+002F (/),
13535
        // then set state to special authority ignore slashes state and increase
13536
        // pointer by 1.
13537
43
        if (url_data.substr(input_position, 2) == "//") {
13538
4
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13539
4
          input_position += 2;
13540
39
        } else {
13541
          // Otherwise, validation error, set state to relative state and
13542
          // decrease pointer by 1.
13543
39
          state = state::RELATIVE_SCHEME;
13544
39
        }
13545
13546
43
        break;
13547
362
      }
13548
526
      case state::PATH_OR_AUTHORITY: {
13549
526
        ada_log("PATH_OR_AUTHORITY ",
13550
526
                helpers::substring(url_data, input_position));
13551
13552
        // If c is U+002F (/), then set state to authority state.
13553
526
        if ((input_position != input_size) &&
13554
504
            (url_data[input_position] == '/')) {
13555
474
          state = state::AUTHORITY;
13556
474
          input_position++;
13557
474
        } else {
13558
          // Otherwise, set state to path state, and decrease pointer by 1.
13559
52
          state = state::PATH;
13560
52
        }
13561
13562
526
        break;
13563
362
      }
13564
281
      case state::RELATIVE_SCHEME: {
13565
281
        ada_log("RELATIVE_SCHEME ",
13566
281
                helpers::substring(url_data, input_position));
13567
13568
        // Set url's scheme to base's scheme.
13569
281
        url.copy_scheme(*base_url);
13570
13571
        // If c is U+002F (/), then set state to relative slash state.
13572
281
        if ((input_position != input_size) &&
13573
            // NOLINTNEXTLINE(bugprone-branch-clone)
13574
203
            (url_data[input_position] == '/')) {
13575
67
          ada_log(
13576
67
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
13577
67
              "slash state");
13578
67
          state = state::RELATIVE_SLASH;
13579
214
        } else if (url.is_special() && (input_position != input_size) &&
13580
45
                   (url_data[input_position] == '\\')) {
13581
          // Otherwise, if url is special and c is U+005C (\), validation error,
13582
          // set state to relative slash state.
13583
8
          ada_log(
13584
8
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
13585
8
              "error, set state to relative slash state");
13586
8
          state = state::RELATIVE_SLASH;
13587
206
        } else {
13588
206
          ada_log("RELATIVE_SCHEME otherwise");
13589
          // Set url's username to base's username, url's password to base's
13590
          // password, url's host to base's host, url's port to base's port,
13591
          // url's path to a clone of base's path, and url's query to base's
13592
          // query.
13593
206
          if constexpr (result_type_is_ada_url) {
13594
0
            url.username = base_url->username;
13595
0
            url.password = base_url->password;
13596
0
            url.host = base_url->host;
13597
0
            url.port = base_url->port;
13598
            // cloning the base path includes cloning the has_opaque_path flag
13599
0
            url.has_opaque_path = base_url->has_opaque_path;
13600
0
            url.path = base_url->path;
13601
0
            url.query = base_url->query;
13602
206
          } else {
13603
206
            url.update_base_authority(base_url->get_href(),
13604
206
                                      base_url->get_components());
13605
206
            url.update_host_to_base_host(base_url->get_hostname());
13606
206
            url.update_base_port(base_url->retrieve_base_port());
13607
            // cloning the base path includes cloning the has_opaque_path flag
13608
206
            url.has_opaque_path = base_url->has_opaque_path;
13609
206
            url.update_base_pathname(base_url->get_pathname());
13610
206
            url.update_base_search(base_url->get_search());
13611
206
          }
13612
13613
206
          url.has_opaque_path = base_url->has_opaque_path;
13614
13615
          // If c is U+003F (?), then set url's query to the empty string, and
13616
          // state to query state.
13617
206
          if ((input_position != input_size) &&
13618
128
              (url_data[input_position] == '?')) {
13619
3
            state = state::QUERY;
13620
3
          }
13621
          // Otherwise, if c is not the EOF code point:
13622
203
          else if (input_position != input_size) {
13623
            // Set url's query to null.
13624
125
            url.clear_search();
13625
125
            if constexpr (result_type_is_ada_url) {
13626
              // Shorten url's path.
13627
0
              helpers::shorten_path(url.path, url.type);
13628
125
            } else {
13629
125
              std::string_view path = url.get_pathname();
13630
125
              if (helpers::shorten_path(path, url.type)) {
13631
51
                url.update_base_pathname(std::move(std::string(path)));
13632
51
              }
13633
125
            }
13634
            // Set state to path state and decrease pointer by 1.
13635
125
            state = state::PATH;
13636
125
            break;
13637
125
          }
13638
206
        }
13639
156
        input_position++;
13640
156
        break;
13641
281
      }
13642
75
      case state::RELATIVE_SLASH: {
13643
75
        ada_log("RELATIVE_SLASH ",
13644
75
                helpers::substring(url_data, input_position));
13645
13646
        // If url is special and c is U+002F (/) or U+005C (\), then:
13647
75
        if (url.is_special() && (input_position != input_size) &&
13648
33
            (url_data[input_position] == '/' ||
13649
23
             url_data[input_position] == '\\')) {
13650
          // Set state to special authority ignore slashes state.
13651
11
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13652
11
        }
13653
        // Otherwise, if c is U+002F (/), then set state to authority state.
13654
64
        else if ((input_position != input_size) &&
13655
30
                 (url_data[input_position] == '/')) {
13656
1
          state = state::AUTHORITY;
13657
1
        }
13658
        // Otherwise, set
13659
        // - url's username to base's username,
13660
        // - url's password to base's password,
13661
        // - url's host to base's host,
13662
        // - url's port to base's port,
13663
        // - state to path state, and then, decrease pointer by 1.
13664
63
        else {
13665
63
          if constexpr (result_type_is_ada_url) {
13666
0
            url.username = base_url->username;
13667
0
            url.password = base_url->password;
13668
0
            url.host = base_url->host;
13669
0
            url.port = base_url->port;
13670
63
          } else {
13671
63
            url.update_base_authority(base_url->get_href(),
13672
63
                                      base_url->get_components());
13673
63
            url.update_host_to_base_host(base_url->get_hostname());
13674
63
            url.update_base_port(base_url->retrieve_base_port());
13675
63
          }
13676
63
          state = state::PATH;
13677
63
          break;
13678
63
        }
13679
13680
12
        input_position++;
13681
12
        break;
13682
75
      }
13683
6.66k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13684
6.66k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13685
6.66k
                helpers::substring(url_data, input_position));
13686
13687
        // If c is U+002F (/) and remaining starts with U+002F (/),
13688
        // then set state to special authority ignore slashes state and increase
13689
        // pointer by 1.
13690
6.66k
        if (url_data.substr(input_position, 2) == "//") {
13691
23
          input_position += 2;
13692
23
        }
13693
13694
6.66k
        [[fallthrough]];
13695
6.66k
      }
13696
6.67k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13697
6.67k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13698
6.67k
                helpers::substring(url_data, input_position));
13699
13700
        // If c is neither U+002F (/) nor U+005C (\), then set state to
13701
        // authority state and decrease pointer by 1.
13702
7.28k
        while ((input_position != input_size) &&
13703
7.23k
               ((url_data[input_position] == '/') ||
13704
6.82k
                (url_data[input_position] == '\\'))) {
13705
610
          input_position++;
13706
610
        }
13707
6.67k
        state = state::AUTHORITY;
13708
13709
6.67k
        break;
13710
6.66k
      }
13711
114
      case state::QUERY: {
13712
114
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13713
114
        if constexpr (store_values) {
13714
          // Let queryPercentEncodeSet be the special-query percent-encode set
13715
          // if url is special; otherwise the query percent-encode set.
13716
0
          const uint8_t* query_percent_encode_set =
13717
0
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13718
0
                               : character_sets::QUERY_PERCENT_ENCODE;
13719
13720
          // Percent-encode after encoding, with encoding, buffer, and
13721
          // queryPercentEncodeSet, and append the result to url's query.
13722
0
          url.update_base_search(url_data.substr(input_position),
13723
0
                                 query_percent_encode_set);
13724
0
          ada_log("QUERY update_base_search completed ");
13725
0
          if (fragment.has_value()) {
13726
0
            url.update_unencoded_base_hash(*fragment);
13727
0
          }
13728
0
        }
13729
114
        return url;
13730
6.66k
      }
13731
6.99k
      case state::HOST: {
13732
6.99k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13733
13734
6.99k
        std::string_view host_view = url_data.substr(input_position);
13735
6.99k
        auto [location, found_colon] =
13736
6.99k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13737
6.99k
        input_position = (location != std::string_view::npos)
13738
6.99k
                             ? input_position + location
13739
6.99k
                             : input_size;
13740
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13741
        // Note: the 'found_colon' value is true if and only if a colon was
13742
        // encountered while not inside brackets.
13743
6.99k
        if (found_colon) {
13744
          // If buffer is the empty string, validation error, return failure.
13745
          // Let host be the result of host parsing buffer with url is not
13746
          // special.
13747
965
          ada_log("HOST parsing ", host_view);
13748
965
          if (!url.parse_host(host_view)) {
13749
213
            return url;
13750
213
          }
13751
752
          ada_log("HOST parsing results in ", url.get_hostname());
13752
          // Set url's host to host, buffer to the empty string, and state to
13753
          // port state.
13754
752
          state = state::PORT;
13755
752
          input_position++;
13756
752
        }
13757
        // Otherwise, if one of the following is true:
13758
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13759
        // - url is special and c is U+005C (\)
13760
        // The get_host_delimiter_location function either brings us to
13761
        // the colon outside of the bracket, or to one of those characters.
13762
6.02k
        else {
13763
          // If url is special and host_view is the empty string, validation
13764
          // error, return failure.
13765
6.02k
          if (host_view.empty() && url.is_special()) {
13766
60
            url.is_valid = false;
13767
60
            return url;
13768
60
          }
13769
5.96k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
13770
          // Let host be the result of host parsing host_view with url is not
13771
          // special.
13772
5.96k
          if (host_view.empty()) {
13773
30
            url.update_base_hostname("");
13774
5.93k
          } else if (!url.parse_host(host_view)) {
13775
2.95k
            return url;
13776
2.95k
          }
13777
3.01k
          ada_log("HOST parsing results in ", url.get_hostname(),
13778
3.01k
                  " href=", url.get_href());
13779
13780
          // Set url's host to host, and state to path start state.
13781
3.01k
          state = state::PATH_START;
13782
3.01k
        }
13783
13784
3.76k
        break;
13785
6.99k
      }
13786
3.76k
      case state::OPAQUE_PATH: {
13787
2.05k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13788
2.05k
        std::string_view view = url_data.substr(input_position);
13789
        // If c is U+003F (?), then set url's query to the empty string and
13790
        // state to query state.
13791
2.05k
        size_t location = view.find('?');
13792
2.05k
        if (location != std::string_view::npos) {
13793
56
          view.remove_suffix(view.size() - location);
13794
56
          state = state::QUERY;
13795
56
          input_position += location + 1;
13796
2.00k
        } else {
13797
2.00k
          input_position = input_size + 1;
13798
2.00k
        }
13799
2.05k
        url.has_opaque_path = true;
13800
13801
        // This is a really unlikely scenario in real world. We should not seek
13802
        // to optimize it.
13803
2.05k
        if (view.ends_with(' ')) {
13804
94
          std::string modified_view =
13805
94
              std::string(view.substr(0, view.size() - 1)) + "%20";
13806
94
          url.update_base_pathname(unicode::percent_encode(
13807
94
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13808
1.96k
        } else {
13809
1.96k
          url.update_base_pathname(unicode::percent_encode(
13810
1.96k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13811
1.96k
        }
13812
2.05k
        break;
13813
6.99k
      }
13814
752
      case state::PORT: {
13815
752
        ada_log("PORT ", helpers::substring(url_data, input_position));
13816
752
        std::string_view port_view = url_data.substr(input_position);
13817
752
        input_position += url.parse_port(port_view, true);
13818
752
        if (!url.is_valid) {
13819
138
          return url;
13820
138
        }
13821
614
        state = state::PATH_START;
13822
614
        [[fallthrough]];
13823
614
      }
13824
4.20k
      case state::PATH_START: {
13825
4.20k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13826
13827
        // If url is special, then:
13828
4.20k
        if (url.is_special()) {
13829
          // Set state to path state.
13830
3.91k
          state = state::PATH;
13831
13832
          // Optimization: Avoiding going into PATH state improves the
13833
          // performance of urls ending with /.
13834
3.91k
          if (input_position == input_size) {
13835
3.84k
            if constexpr (store_values) {
13836
0
              url.update_base_pathname("/");
13837
0
              if (fragment.has_value()) {
13838
0
                url.update_unencoded_base_hash(*fragment);
13839
0
              }
13840
0
            }
13841
3.84k
            return url;
13842
3.84k
          }
13843
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
13844
          // by 1. We know that (input_position == input_size) is impossible
13845
          // here, because of the previous if-check.
13846
73
          if ((url_data[input_position] != '/') &&
13847
34
              (url_data[input_position] != '\\')) {
13848
19
            break;
13849
19
          }
13850
73
        }
13851
        // Otherwise, if state override is not given and c is U+003F (?),
13852
        // set url's query to the empty string and state to query state.
13853
288
        else if ((input_position != input_size) &&
13854
39
                 (url_data[input_position] == '?')) {
13855
12
          state = state::QUERY;
13856
12
        }
13857
        // Otherwise, if c is not the EOF code point:
13858
276
        else if (input_position != input_size) {
13859
          // Set state to path state.
13860
27
          state = state::PATH;
13861
13862
          // If c is not U+002F (/), then decrease pointer by 1.
13863
27
          if (url_data[input_position] != '/') {
13864
0
            break;
13865
0
          }
13866
27
        }
13867
13868
342
        input_position++;
13869
342
        break;
13870
4.20k
      }
13871
567
      case state::PATH: {
13872
567
        ada_log("PATH ", helpers::substring(url_data, input_position));
13873
567
        std::string_view view = url_data.substr(input_position);
13874
13875
        // Most time, we do not need percent encoding.
13876
        // Furthermore, we can immediately locate the '?'.
13877
567
        size_t locofquestionmark = view.find('?');
13878
567
        if (locofquestionmark != std::string_view::npos) {
13879
42
          state = state::QUERY;
13880
42
          view.remove_suffix(view.size() - locofquestionmark);
13881
42
          input_position += locofquestionmark + 1;
13882
525
        } else {
13883
525
          input_position = input_size + 1;
13884
525
        }
13885
567
        if constexpr (store_values) {
13886
0
          if constexpr (result_type_is_ada_url) {
13887
0
            helpers::parse_prepared_path(view, url.type, url.path);
13888
0
          } else {
13889
0
            url.consume_prepared_path(view);
13890
0
            ADA_ASSERT_TRUE(url.validate());
13891
0
          }
13892
0
        }
13893
567
        break;
13894
4.20k
      }
13895
848
      case state::FILE_SLASH: {
13896
848
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13897
13898
        // If c is U+002F (/) or U+005C (\), then:
13899
848
        if ((input_position != input_size) &&
13900
818
            (url_data[input_position] == '/' ||
13901
795
             url_data[input_position] == '\\')) {
13902
795
          ada_log("FILE_SLASH c is U+002F or U+005C");
13903
          // Set state to file host state.
13904
795
          state = state::FILE_HOST;
13905
795
          input_position++;
13906
795
        } else {
13907
53
          ada_log("FILE_SLASH otherwise");
13908
          // If base is non-null and base's scheme is "file", then:
13909
          // Note: it is unsafe to do base_url->scheme unless you know that
13910
          // base_url_has_value() is true.
13911
53
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13912
            // Set url's host to base's host.
13913
24
            if constexpr (result_type_is_ada_url) {
13914
0
              url.host = base_url->host;
13915
24
            } else {
13916
24
              url.update_host_to_base_host(base_url->get_host());
13917
24
            }
13918
            // If the code point substring from pointer to the end of input does
13919
            // not start with a Windows drive letter and base's path[0] is a
13920
            // normalized Windows drive letter, then append base's path[0] to
13921
            // url's path.
13922
24
            if (!base_url->get_pathname().empty()) {
13923
0
              if (!checkers::is_windows_drive_letter(
13924
0
                      url_data.substr(input_position))) {
13925
0
                std::string_view first_base_url_path =
13926
0
                    base_url->get_pathname().substr(1);
13927
0
                size_t loc = first_base_url_path.find('/');
13928
0
                if (loc != std::string_view::npos) {
13929
0
                  helpers::resize(first_base_url_path, loc);
13930
0
                }
13931
0
                if (checkers::is_normalized_windows_drive_letter(
13932
0
                        first_base_url_path)) {
13933
0
                  if constexpr (result_type_is_ada_url) {
13934
0
                    url.path += '/';
13935
0
                    url.path += first_base_url_path;
13936
0
                  } else {
13937
0
                    url.append_base_pathname(
13938
0
                        helpers::concat("/", first_base_url_path));
13939
0
                  }
13940
0
                }
13941
0
              }
13942
0
            }
13943
24
          }
13944
13945
          // Set state to path state, and decrease pointer by 1.
13946
53
          state = state::PATH;
13947
53
        }
13948
13949
848
        break;
13950
4.20k
      }
13951
795
      case state::FILE_HOST: {
13952
795
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13953
795
        std::string_view view = url_data.substr(input_position);
13954
13955
795
        size_t location = view.find_first_of("/\\?");
13956
795
        std::string_view file_host_buffer(
13957
795
            view.data(),
13958
795
            (location != std::string_view::npos) ? location : view.size());
13959
13960
795
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13961
13
          state = state::PATH;
13962
782
        } else if (file_host_buffer.empty()) {
13963
          // Set url's host to the empty string.
13964
20
          if constexpr (result_type_is_ada_url) {
13965
0
            url.host = "";
13966
20
          } else {
13967
20
            url.update_base_hostname("");
13968
20
          }
13969
          // Set state to path start state.
13970
20
          state = state::PATH_START;
13971
762
        } else {
13972
762
          size_t consumed_bytes = file_host_buffer.size();
13973
762
          input_position += consumed_bytes;
13974
          // Let host be the result of host parsing buffer with url is not
13975
          // special.
13976
762
          if (!url.parse_host(file_host_buffer)) {
13977
204
            return url;
13978
204
          }
13979
13980
558
          if constexpr (result_type_is_ada_url) {
13981
            // If host is "localhost", then set host to the empty string.
13982
0
            if (url.host.has_value() && url.host.value() == "localhost") {
13983
0
              url.host = "";
13984
0
            }
13985
558
          } else {
13986
558
            if (url.get_hostname() == "localhost") {
13987
8
              url.update_base_hostname("");
13988
8
            }
13989
558
          }
13990
13991
          // Set buffer to the empty string and state to path start state.
13992
558
          state = state::PATH_START;
13993
558
        }
13994
13995
591
        break;
13996
795
      }
13997
1.03k
      case state::FILE: {
13998
1.03k
        ada_log("FILE ", helpers::substring(url_data, input_position));
13999
1.03k
        std::string_view file_view = url_data.substr(input_position);
14000
14001
1.03k
        url.set_protocol_as_file();
14002
1.03k
        if constexpr (result_type_is_ada_url) {
14003
          // Set url's host to the empty string.
14004
0
          url.host = "";
14005
1.03k
        } else {
14006
1.03k
          url.update_base_hostname("");
14007
1.03k
        }
14008
        // If c is U+002F (/) or U+005C (\), then:
14009
1.03k
        if (input_position != input_size &&
14010
938
            (url_data[input_position] == '/' ||
14011
848
             url_data[input_position] == '\\')) {
14012
848
          ada_log("FILE c is U+002F or U+005C");
14013
          // Set state to file slash state.
14014
848
          state = state::FILE_SLASH;
14015
848
        }
14016
        // Otherwise, if base is non-null and base's scheme is "file":
14017
184
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
14018
          // Set url's host to base's host, url's path to a clone of base's
14019
          // path, and url's query to base's query.
14020
88
          ada_log("FILE base non-null");
14021
88
          if constexpr (result_type_is_ada_url) {
14022
0
            url.host = base_url->host;
14023
0
            url.path = base_url->path;
14024
0
            url.query = base_url->query;
14025
88
          } else {
14026
88
            url.update_host_to_base_host(base_url->get_hostname());
14027
88
            url.update_base_pathname(base_url->get_pathname());
14028
88
            url.update_base_search(base_url->get_search());
14029
88
          }
14030
88
          url.has_opaque_path = base_url->has_opaque_path;
14031
14032
          // If c is U+003F (?), then set url's query to the empty string and
14033
          // state to query state.
14034
88
          if (input_position != input_size && url_data[input_position] == '?') {
14035
1
            state = state::QUERY;
14036
1
          }
14037
          // Otherwise, if c is not the EOF code point:
14038
87
          else if (input_position != input_size) {
14039
            // Set url's query to null.
14040
65
            url.clear_search();
14041
            // If the code point substring from pointer to the end of input does
14042
            // not start with a Windows drive letter, then shorten url's path.
14043
65
            if (!checkers::is_windows_drive_letter(file_view)) {
14044
57
              if constexpr (result_type_is_ada_url) {
14045
0
                helpers::shorten_path(url.path, url.type);
14046
57
              } else {
14047
57
                std::string_view path = url.get_pathname();
14048
57
                if (helpers::shorten_path(path, url.type)) {
14049
0
                  url.update_base_pathname(std::move(std::string(path)));
14050
0
                }
14051
57
              }
14052
57
            }
14053
            // Otherwise:
14054
8
            else {
14055
              // Set url's path to an empty list.
14056
8
              url.clear_pathname();
14057
8
              url.has_opaque_path = true;
14058
8
            }
14059
14060
            // Set state to path state and decrease pointer by 1.
14061
65
            state = state::PATH;
14062
65
            break;
14063
65
          }
14064
88
        }
14065
        // Otherwise, set state to path state, and decrease pointer by 1.
14066
96
        else {
14067
96
          ada_log("FILE go to path");
14068
96
          state = state::PATH;
14069
96
          break;
14070
96
        }
14071
14072
871
        input_position++;
14073
871
        break;
14074
1.03k
      }
14075
0
      default:
14076
0
        unreachable();
14077
63.2k
    }
14078
63.2k
  }
14079
2.87k
  if constexpr (store_values) {
14080
0
    if (fragment.has_value()) {
14081
0
      url.update_unencoded_base_hash(*fragment);
14082
0
    }
14083
0
  }
14084
2.87k
  return url;
14085
15.7k
}
Unexecuted instantiation: ada::url ada::parser::parse_url_impl<ada::url, true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url const*)
Unexecuted instantiation: ada::url_aggregator ada::parser::parse_url_impl<ada::url_aggregator, true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator const*)
ada::url_aggregator ada::parser::parse_url_impl<ada::url_aggregator, false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator const*)
Line
Count
Source
13191
15.7k
                           const result_type* base_url) {
13192
  // We can specialize the implementation per type.
13193
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
13194
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
13195
  // something else } is free (at runtime). This means that ada::url_aggregator
13196
  // and ada::url **do not have to support the exact same API**.
13197
15.7k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13198
15.7k
  constexpr bool result_type_is_ada_url_aggregator =
13199
15.7k
      std::is_same_v<url_aggregator, result_type>;
13200
15.7k
  static_assert(result_type_is_ada_url ||
13201
15.7k
                result_type_is_ada_url_aggregator);  // We don't support
13202
                                                     // anything else for now.
13203
13204
15.7k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13205
15.7k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13206
15.7k
          ")");
13207
13208
15.7k
  state state = state::SCHEME_START;
13209
15.7k
  result_type url{};
13210
13211
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
13212
  // surely the result of a bug or are otherwise a security concern.
13213
15.7k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) [[unlikely]] {
13214
0
    url.is_valid = false;
13215
0
  }
13216
  // Going forward, user_input.size() is in [0,
13217
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
13218
  // base, or the optional_url was invalid, we must return.
13219
15.7k
  if (base_url != nullptr) {
13220
2.35k
    url.is_valid &= base_url->is_valid;
13221
2.35k
  }
13222
15.7k
  if (!url.is_valid) {
13223
0
    return url;
13224
0
  }
13225
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
13226
    // Most of the time, we just need user_input.size().
13227
    // In some instances, we may need a bit more.
13228
    ///////////////////////////
13229
    // This is *very* important. This line should *not* be removed
13230
    // hastily. There are principled reasons why reserve is important
13231
    // for performance. If you have a benchmark with small inputs,
13232
    // it may not matter, but in other instances, it could.
13233
    ////
13234
    // This rounds up to the next power of two.
13235
    // We know that user_input.size() is in [0,
13236
    // std::numeric_limits<uint32_t>::max).
13237
    uint32_t reserve_capacity =
13238
        (0xFFFFFFFF >>
13239
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13240
        1;
13241
    url.reserve(reserve_capacity);
13242
  }
13243
15.7k
  std::string tmp_buffer;
13244
15.7k
  std::string_view url_data;
13245
15.7k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13246
197
    tmp_buffer = user_input;
13247
    // Optimization opportunity: Instead of copying and then pruning, we could
13248
    // just directly build the string from user_input.
13249
197
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13250
197
    url_data = tmp_buffer;
13251
15.5k
  } else [[likely]] {
13252
15.5k
    url_data = user_input;
13253
15.5k
  }
13254
13255
  // Leading and trailing control characters are uncommon and easy to deal with
13256
  // (no performance concern).
13257
15.7k
  helpers::trim_c0_whitespace(url_data);
13258
13259
  // Optimization opportunity. Most websites do not have fragment.
13260
15.7k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13261
  // We add it last so that an implementation like ada::url_aggregator
13262
  // can append it last to its internal buffer, thus improving performance.
13263
13264
  // Here url_data no longer has its fragment.
13265
  // We are going to access the data from url_data (it is immutable).
13266
  // At any given time, we are pointing at byte 'input_position' in url_data.
13267
  // The input_position variable should range from 0 to input_size.
13268
  // It is illegal to access url_data at input_size.
13269
15.7k
  size_t input_position = 0;
13270
15.7k
  const size_t input_size = url_data.size();
13271
  // Keep running the following state machine by switching on state.
13272
  // If after a run pointer points to the EOF code point, go to the next step.
13273
  // Otherwise, increase pointer by 1 and continue with the state machine.
13274
  // We never decrement input_position.
13275
66.1k
  while (input_position <= input_size) {
13276
63.2k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13277
63.2k
            " in state ", ada::to_string(state));
13278
63.2k
    switch (state) {
13279
15.7k
      case state::SCHEME_START: {
13280
15.7k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13281
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13282
        // state to scheme state.
13283
15.7k
        if ((input_position != input_size) &&
13284
10.9k
            checkers::is_alpha(url_data[input_position])) {
13285
10.5k
          state = state::SCHEME;
13286
10.5k
          input_position++;
13287
10.5k
        } else {
13288
          // Otherwise, if state override is not given, set state to no scheme
13289
          // state and decrease pointer by 1.
13290
5.23k
          state = state::NO_SCHEME;
13291
5.23k
        }
13292
15.7k
        break;
13293
0
      }
13294
10.5k
      case state::SCHEME: {
13295
10.5k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13296
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13297
        // append c, lowercased, to buffer.
13298
27.7k
        while ((input_position != input_size) &&
13299
27.6k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13300
17.2k
          input_position++;
13301
17.2k
        }
13302
        // Otherwise, if c is U+003A (:), then:
13303
10.5k
        if ((input_position != input_size) &&
13304
10.3k
            (url_data[input_position] == ':')) {
13305
10.2k
          ada_log("SCHEME the scheme should be ",
13306
10.2k
                  url_data.substr(0, input_position));
13307
          if constexpr (result_type_is_ada_url) {
13308
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13309
              return url;
13310
            }
13311
10.2k
          } else {
13312
            // we pass the colon along instead of painfully adding it back.
13313
10.2k
            if (!url.parse_scheme_with_colon(
13314
10.2k
                    url_data.substr(0, input_position + 1))) {
13315
0
              return url;
13316
0
            }
13317
10.2k
          }
13318
10.2k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13319
13320
          // If url's scheme is "file", then:
13321
10.2k
          if (url.type == scheme::type::FILE) {
13322
            // Set state to file state.
13323
928
            state = state::FILE;
13324
928
          }
13325
          // Otherwise, if url is special, base is non-null, and base's scheme
13326
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13327
          // != nullptr is false.
13328
9.29k
          else if (url.is_special() && base_url != nullptr &&
13329
1.50k
                   base_url->type == url.type) {
13330
            // Set state to special relative or authority state.
13331
43
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13332
43
          }
13333
          // Otherwise, if url is special, set state to special authority
13334
          // slashes state.
13335
9.24k
          else if (url.is_special()) {
13336
6.66k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13337
6.66k
          }
13338
          // Otherwise, if remaining starts with an U+002F (/), set state to
13339
          // path or authority state and increase pointer by 1.
13340
2.58k
          else if (input_position + 1 < input_size &&
13341
900
                   url_data[input_position + 1] == '/') {
13342
526
            state = state::PATH_OR_AUTHORITY;
13343
526
            input_position++;
13344
526
          }
13345
          // Otherwise, set url's path to the empty string and set state to
13346
          // opaque path state.
13347
2.05k
          else {
13348
2.05k
            state = state::OPAQUE_PATH;
13349
2.05k
          }
13350
10.2k
        }
13351
        // Otherwise, if state override is not given, set buffer to the empty
13352
        // string, state to no scheme state, and start over (from the first code
13353
        // point in input).
13354
284
        else {
13355
284
          state = state::NO_SCHEME;
13356
284
          input_position = 0;
13357
284
          break;
13358
284
        }
13359
10.2k
        input_position++;
13360
10.2k
        break;
13361
10.5k
      }
13362
5.51k
      case state::NO_SCHEME: {
13363
5.51k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13364
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13365
        // validation error, return failure.
13366
5.51k
        if (base_url == nullptr ||
13367
5.06k
            (base_url->has_opaque_path && !fragment.has_value())) {
13368
5.06k
          ada_log("NO_SCHEME validation error");
13369
5.06k
          url.is_valid = false;
13370
5.06k
          return url;
13371
5.06k
        }
13372
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13373
        // set url's scheme to base's scheme, url's path to base's path, url's
13374
        // query to base's query, and set state to fragment state.
13375
454
        else if (base_url->has_opaque_path && fragment.has_value() &&
13376
199
                 input_position == input_size) {
13377
108
          ada_log("NO_SCHEME opaque base with fragment");
13378
108
          url.copy_scheme(*base_url);
13379
108
          url.has_opaque_path = base_url->has_opaque_path;
13380
13381
          if constexpr (result_type_is_ada_url) {
13382
            url.path = base_url->path;
13383
            url.query = base_url->query;
13384
108
          } else {
13385
108
            url.update_base_pathname(base_url->get_pathname());
13386
108
            url.update_base_search(base_url->get_search());
13387
108
          }
13388
108
          url.update_unencoded_base_hash(*fragment);
13389
108
          return url;
13390
108
        }
13391
        // Otherwise, if base's scheme is not "file", set state to relative
13392
        // state and decrease pointer by 1.
13393
346
        else if (base_url->type != scheme::type::FILE) {
13394
242
          ada_log("NO_SCHEME non-file relative path");
13395
242
          state = state::RELATIVE_SCHEME;
13396
242
        }
13397
        // Otherwise, set state to file state and decrease pointer by 1.
13398
104
        else {
13399
104
          ada_log("NO_SCHEME file base type");
13400
104
          state = state::FILE;
13401
104
        }
13402
346
        break;
13403
5.51k
      }
13404
7.15k
      case state::AUTHORITY: {
13405
7.15k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13406
        // most URLs have no @. Having no @ tells us that we don't have to worry
13407
        // about AUTHORITY. Of course, we could have @ and still not have to
13408
        // worry about AUTHORITY.
13409
        // TODO: Instead of just collecting a bool, collect the location of the
13410
        // '@' and do something useful with it.
13411
        // TODO: We could do various processing early on, using a single pass
13412
        // over the string to collect information about it, e.g., telling us
13413
        // whether there is a @ and if so, where (or how many).
13414
13415
        // Check if url data contains an @.
13416
7.15k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13417
6.79k
          state = state::HOST;
13418
6.79k
          break;
13419
6.79k
        }
13420
362
        bool at_sign_seen{false};
13421
362
        bool password_token_seen{false};
13422
        /**
13423
         * We expect something of the sort...
13424
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13425
         * --------^
13426
         */
13427
6.79k
        do {
13428
6.79k
          std::string_view view = url_data.substr(input_position);
13429
          // The delimiters are @, /, ? \\.
13430
6.79k
          size_t location =
13431
6.79k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13432
6.79k
                               : helpers::find_authority_delimiter(view);
13433
6.79k
          std::string_view authority_view = view.substr(0, location);
13434
6.79k
          size_t end_of_authority = input_position + authority_view.size();
13435
          // If c is U+0040 (@), then:
13436
6.79k
          if ((end_of_authority != input_size) &&
13437
6.48k
              (url_data[end_of_authority] == '@')) {
13438
            // If atSignSeen is true, then prepend "%40" to buffer.
13439
6.43k
            if (at_sign_seen) {
13440
6.08k
              if (password_token_seen) {
13441
                if constexpr (result_type_is_ada_url) {
13442
                  url.password += "%40";
13443
2.23k
                } else {
13444
2.23k
                  url.append_base_password("%40");
13445
2.23k
                }
13446
3.85k
              } else {
13447
                if constexpr (result_type_is_ada_url) {
13448
                  url.username += "%40";
13449
3.85k
                } else {
13450
3.85k
                  url.append_base_username("%40");
13451
3.85k
                }
13452
3.85k
              }
13453
6.08k
            }
13454
13455
6.43k
            at_sign_seen = true;
13456
13457
6.43k
            if (!password_token_seen) {
13458
4.20k
              size_t password_token_location = authority_view.find(':');
13459
4.20k
              password_token_seen =
13460
4.20k
                  password_token_location != std::string_view::npos;
13461
13462
              if constexpr (store_values) {
13463
                if (!password_token_seen) {
13464
                  if constexpr (result_type_is_ada_url) {
13465
                    url.username += unicode::percent_encode(
13466
                        authority_view,
13467
                        character_sets::USERINFO_PERCENT_ENCODE);
13468
                  } else {
13469
                    url.append_base_username(unicode::percent_encode(
13470
                        authority_view,
13471
                        character_sets::USERINFO_PERCENT_ENCODE));
13472
                  }
13473
                } else {
13474
                  if constexpr (result_type_is_ada_url) {
13475
                    url.username += unicode::percent_encode(
13476
                        authority_view.substr(0, password_token_location),
13477
                        character_sets::USERINFO_PERCENT_ENCODE);
13478
                    url.password += unicode::percent_encode(
13479
                        authority_view.substr(password_token_location + 1),
13480
                        character_sets::USERINFO_PERCENT_ENCODE);
13481
                  } else {
13482
                    url.append_base_username(unicode::percent_encode(
13483
                        authority_view.substr(0, password_token_location),
13484
                        character_sets::USERINFO_PERCENT_ENCODE));
13485
                    url.append_base_password(unicode::percent_encode(
13486
                        authority_view.substr(password_token_location + 1),
13487
                        character_sets::USERINFO_PERCENT_ENCODE));
13488
                  }
13489
                }
13490
              }
13491
4.20k
            } else if constexpr (store_values) {
13492
2.23k
              if constexpr (result_type_is_ada_url) {
13493
2.23k
                url.password += unicode::percent_encode(
13494
2.23k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13495
2.23k
              } else {
13496
2.23k
                url.append_base_password(unicode::percent_encode(
13497
2.23k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13498
2.23k
              }
13499
2.23k
            }
13500
6.43k
          }
13501
          // Otherwise, if one of the following is true:
13502
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13503
          // - url is special and c is U+005C (\)
13504
362
          else if (end_of_authority == input_size ||
13505
46
                   url_data[end_of_authority] == '/' ||
13506
22
                   url_data[end_of_authority] == '?' ||
13507
362
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13508
            // If atSignSeen is true and authority_view is the empty string,
13509
            // validation error, return failure.
13510
362
            if (at_sign_seen && authority_view.empty()) {
13511
162
              url.is_valid = false;
13512
162
              return url;
13513
162
            }
13514
200
            state = state::HOST;
13515
200
            break;
13516
362
          }
13517
6.43k
          if (end_of_authority == input_size) {
13518
            if constexpr (store_values) {
13519
              if (fragment.has_value()) {
13520
                url.update_unencoded_base_hash(*fragment);
13521
              }
13522
            }
13523
0
            return url;
13524
0
          }
13525
6.43k
          input_position = end_of_authority + 1;
13526
6.43k
        } while (true);
13527
13528
200
        break;
13529
362
      }
13530
200
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
13531
43
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
13532
43
                helpers::substring(url_data, input_position));
13533
13534
        // If c is U+002F (/) and remaining starts with U+002F (/),
13535
        // then set state to special authority ignore slashes state and increase
13536
        // pointer by 1.
13537
43
        if (url_data.substr(input_position, 2) == "//") {
13538
4
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13539
4
          input_position += 2;
13540
39
        } else {
13541
          // Otherwise, validation error, set state to relative state and
13542
          // decrease pointer by 1.
13543
39
          state = state::RELATIVE_SCHEME;
13544
39
        }
13545
13546
43
        break;
13547
362
      }
13548
526
      case state::PATH_OR_AUTHORITY: {
13549
526
        ada_log("PATH_OR_AUTHORITY ",
13550
526
                helpers::substring(url_data, input_position));
13551
13552
        // If c is U+002F (/), then set state to authority state.
13553
526
        if ((input_position != input_size) &&
13554
504
            (url_data[input_position] == '/')) {
13555
474
          state = state::AUTHORITY;
13556
474
          input_position++;
13557
474
        } else {
13558
          // Otherwise, set state to path state, and decrease pointer by 1.
13559
52
          state = state::PATH;
13560
52
        }
13561
13562
526
        break;
13563
362
      }
13564
281
      case state::RELATIVE_SCHEME: {
13565
281
        ada_log("RELATIVE_SCHEME ",
13566
281
                helpers::substring(url_data, input_position));
13567
13568
        // Set url's scheme to base's scheme.
13569
281
        url.copy_scheme(*base_url);
13570
13571
        // If c is U+002F (/), then set state to relative slash state.
13572
281
        if ((input_position != input_size) &&
13573
            // NOLINTNEXTLINE(bugprone-branch-clone)
13574
203
            (url_data[input_position] == '/')) {
13575
67
          ada_log(
13576
67
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
13577
67
              "slash state");
13578
67
          state = state::RELATIVE_SLASH;
13579
214
        } else if (url.is_special() && (input_position != input_size) &&
13580
45
                   (url_data[input_position] == '\\')) {
13581
          // Otherwise, if url is special and c is U+005C (\), validation error,
13582
          // set state to relative slash state.
13583
8
          ada_log(
13584
8
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
13585
8
              "error, set state to relative slash state");
13586
8
          state = state::RELATIVE_SLASH;
13587
206
        } else {
13588
206
          ada_log("RELATIVE_SCHEME otherwise");
13589
          // Set url's username to base's username, url's password to base's
13590
          // password, url's host to base's host, url's port to base's port,
13591
          // url's path to a clone of base's path, and url's query to base's
13592
          // query.
13593
          if constexpr (result_type_is_ada_url) {
13594
            url.username = base_url->username;
13595
            url.password = base_url->password;
13596
            url.host = base_url->host;
13597
            url.port = base_url->port;
13598
            // cloning the base path includes cloning the has_opaque_path flag
13599
            url.has_opaque_path = base_url->has_opaque_path;
13600
            url.path = base_url->path;
13601
            url.query = base_url->query;
13602
206
          } else {
13603
206
            url.update_base_authority(base_url->get_href(),
13604
206
                                      base_url->get_components());
13605
206
            url.update_host_to_base_host(base_url->get_hostname());
13606
206
            url.update_base_port(base_url->retrieve_base_port());
13607
            // cloning the base path includes cloning the has_opaque_path flag
13608
206
            url.has_opaque_path = base_url->has_opaque_path;
13609
206
            url.update_base_pathname(base_url->get_pathname());
13610
206
            url.update_base_search(base_url->get_search());
13611
206
          }
13612
13613
206
          url.has_opaque_path = base_url->has_opaque_path;
13614
13615
          // If c is U+003F (?), then set url's query to the empty string, and
13616
          // state to query state.
13617
206
          if ((input_position != input_size) &&
13618
128
              (url_data[input_position] == '?')) {
13619
3
            state = state::QUERY;
13620
3
          }
13621
          // Otherwise, if c is not the EOF code point:
13622
203
          else if (input_position != input_size) {
13623
            // Set url's query to null.
13624
125
            url.clear_search();
13625
            if constexpr (result_type_is_ada_url) {
13626
              // Shorten url's path.
13627
              helpers::shorten_path(url.path, url.type);
13628
125
            } else {
13629
125
              std::string_view path = url.get_pathname();
13630
125
              if (helpers::shorten_path(path, url.type)) {
13631
51
                url.update_base_pathname(std::move(std::string(path)));
13632
51
              }
13633
125
            }
13634
            // Set state to path state and decrease pointer by 1.
13635
125
            state = state::PATH;
13636
125
            break;
13637
125
          }
13638
206
        }
13639
156
        input_position++;
13640
156
        break;
13641
281
      }
13642
75
      case state::RELATIVE_SLASH: {
13643
75
        ada_log("RELATIVE_SLASH ",
13644
75
                helpers::substring(url_data, input_position));
13645
13646
        // If url is special and c is U+002F (/) or U+005C (\), then:
13647
75
        if (url.is_special() && (input_position != input_size) &&
13648
33
            (url_data[input_position] == '/' ||
13649
23
             url_data[input_position] == '\\')) {
13650
          // Set state to special authority ignore slashes state.
13651
11
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13652
11
        }
13653
        // Otherwise, if c is U+002F (/), then set state to authority state.
13654
64
        else if ((input_position != input_size) &&
13655
30
                 (url_data[input_position] == '/')) {
13656
1
          state = state::AUTHORITY;
13657
1
        }
13658
        // Otherwise, set
13659
        // - url's username to base's username,
13660
        // - url's password to base's password,
13661
        // - url's host to base's host,
13662
        // - url's port to base's port,
13663
        // - state to path state, and then, decrease pointer by 1.
13664
63
        else {
13665
          if constexpr (result_type_is_ada_url) {
13666
            url.username = base_url->username;
13667
            url.password = base_url->password;
13668
            url.host = base_url->host;
13669
            url.port = base_url->port;
13670
63
          } else {
13671
63
            url.update_base_authority(base_url->get_href(),
13672
63
                                      base_url->get_components());
13673
63
            url.update_host_to_base_host(base_url->get_hostname());
13674
63
            url.update_base_port(base_url->retrieve_base_port());
13675
63
          }
13676
63
          state = state::PATH;
13677
63
          break;
13678
63
        }
13679
13680
12
        input_position++;
13681
12
        break;
13682
75
      }
13683
6.66k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13684
6.66k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13685
6.66k
                helpers::substring(url_data, input_position));
13686
13687
        // If c is U+002F (/) and remaining starts with U+002F (/),
13688
        // then set state to special authority ignore slashes state and increase
13689
        // pointer by 1.
13690
6.66k
        if (url_data.substr(input_position, 2) == "//") {
13691
23
          input_position += 2;
13692
23
        }
13693
13694
6.66k
        [[fallthrough]];
13695
6.66k
      }
13696
6.67k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13697
6.67k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13698
6.67k
                helpers::substring(url_data, input_position));
13699
13700
        // If c is neither U+002F (/) nor U+005C (\), then set state to
13701
        // authority state and decrease pointer by 1.
13702
7.28k
        while ((input_position != input_size) &&
13703
7.23k
               ((url_data[input_position] == '/') ||
13704
6.82k
                (url_data[input_position] == '\\'))) {
13705
610
          input_position++;
13706
610
        }
13707
6.67k
        state = state::AUTHORITY;
13708
13709
6.67k
        break;
13710
6.66k
      }
13711
114
      case state::QUERY: {
13712
114
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13713
        if constexpr (store_values) {
13714
          // Let queryPercentEncodeSet be the special-query percent-encode set
13715
          // if url is special; otherwise the query percent-encode set.
13716
          const uint8_t* query_percent_encode_set =
13717
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13718
                               : character_sets::QUERY_PERCENT_ENCODE;
13719
13720
          // Percent-encode after encoding, with encoding, buffer, and
13721
          // queryPercentEncodeSet, and append the result to url's query.
13722
          url.update_base_search(url_data.substr(input_position),
13723
                                 query_percent_encode_set);
13724
          ada_log("QUERY update_base_search completed ");
13725
          if (fragment.has_value()) {
13726
            url.update_unencoded_base_hash(*fragment);
13727
          }
13728
        }
13729
114
        return url;
13730
6.66k
      }
13731
6.99k
      case state::HOST: {
13732
6.99k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13733
13734
6.99k
        std::string_view host_view = url_data.substr(input_position);
13735
6.99k
        auto [location, found_colon] =
13736
6.99k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13737
6.99k
        input_position = (location != std::string_view::npos)
13738
6.99k
                             ? input_position + location
13739
6.99k
                             : input_size;
13740
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13741
        // Note: the 'found_colon' value is true if and only if a colon was
13742
        // encountered while not inside brackets.
13743
6.99k
        if (found_colon) {
13744
          // If buffer is the empty string, validation error, return failure.
13745
          // Let host be the result of host parsing buffer with url is not
13746
          // special.
13747
965
          ada_log("HOST parsing ", host_view);
13748
965
          if (!url.parse_host(host_view)) {
13749
213
            return url;
13750
213
          }
13751
752
          ada_log("HOST parsing results in ", url.get_hostname());
13752
          // Set url's host to host, buffer to the empty string, and state to
13753
          // port state.
13754
752
          state = state::PORT;
13755
752
          input_position++;
13756
752
        }
13757
        // Otherwise, if one of the following is true:
13758
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13759
        // - url is special and c is U+005C (\)
13760
        // The get_host_delimiter_location function either brings us to
13761
        // the colon outside of the bracket, or to one of those characters.
13762
6.02k
        else {
13763
          // If url is special and host_view is the empty string, validation
13764
          // error, return failure.
13765
6.02k
          if (host_view.empty() && url.is_special()) {
13766
60
            url.is_valid = false;
13767
60
            return url;
13768
60
          }
13769
5.96k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
13770
          // Let host be the result of host parsing host_view with url is not
13771
          // special.
13772
5.96k
          if (host_view.empty()) {
13773
30
            url.update_base_hostname("");
13774
5.93k
          } else if (!url.parse_host(host_view)) {
13775
2.95k
            return url;
13776
2.95k
          }
13777
3.01k
          ada_log("HOST parsing results in ", url.get_hostname(),
13778
3.01k
                  " href=", url.get_href());
13779
13780
          // Set url's host to host, and state to path start state.
13781
3.01k
          state = state::PATH_START;
13782
3.01k
        }
13783
13784
3.76k
        break;
13785
6.99k
      }
13786
3.76k
      case state::OPAQUE_PATH: {
13787
2.05k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13788
2.05k
        std::string_view view = url_data.substr(input_position);
13789
        // If c is U+003F (?), then set url's query to the empty string and
13790
        // state to query state.
13791
2.05k
        size_t location = view.find('?');
13792
2.05k
        if (location != std::string_view::npos) {
13793
56
          view.remove_suffix(view.size() - location);
13794
56
          state = state::QUERY;
13795
56
          input_position += location + 1;
13796
2.00k
        } else {
13797
2.00k
          input_position = input_size + 1;
13798
2.00k
        }
13799
2.05k
        url.has_opaque_path = true;
13800
13801
        // This is a really unlikely scenario in real world. We should not seek
13802
        // to optimize it.
13803
2.05k
        if (view.ends_with(' ')) {
13804
94
          std::string modified_view =
13805
94
              std::string(view.substr(0, view.size() - 1)) + "%20";
13806
94
          url.update_base_pathname(unicode::percent_encode(
13807
94
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13808
1.96k
        } else {
13809
1.96k
          url.update_base_pathname(unicode::percent_encode(
13810
1.96k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13811
1.96k
        }
13812
2.05k
        break;
13813
6.99k
      }
13814
752
      case state::PORT: {
13815
752
        ada_log("PORT ", helpers::substring(url_data, input_position));
13816
752
        std::string_view port_view = url_data.substr(input_position);
13817
752
        input_position += url.parse_port(port_view, true);
13818
752
        if (!url.is_valid) {
13819
138
          return url;
13820
138
        }
13821
614
        state = state::PATH_START;
13822
614
        [[fallthrough]];
13823
614
      }
13824
4.20k
      case state::PATH_START: {
13825
4.20k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13826
13827
        // If url is special, then:
13828
4.20k
        if (url.is_special()) {
13829
          // Set state to path state.
13830
3.91k
          state = state::PATH;
13831
13832
          // Optimization: Avoiding going into PATH state improves the
13833
          // performance of urls ending with /.
13834
3.91k
          if (input_position == input_size) {
13835
            if constexpr (store_values) {
13836
              url.update_base_pathname("/");
13837
              if (fragment.has_value()) {
13838
                url.update_unencoded_base_hash(*fragment);
13839
              }
13840
            }
13841
3.84k
            return url;
13842
3.84k
          }
13843
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
13844
          // by 1. We know that (input_position == input_size) is impossible
13845
          // here, because of the previous if-check.
13846
73
          if ((url_data[input_position] != '/') &&
13847
34
              (url_data[input_position] != '\\')) {
13848
19
            break;
13849
19
          }
13850
73
        }
13851
        // Otherwise, if state override is not given and c is U+003F (?),
13852
        // set url's query to the empty string and state to query state.
13853
288
        else if ((input_position != input_size) &&
13854
39
                 (url_data[input_position] == '?')) {
13855
12
          state = state::QUERY;
13856
12
        }
13857
        // Otherwise, if c is not the EOF code point:
13858
276
        else if (input_position != input_size) {
13859
          // Set state to path state.
13860
27
          state = state::PATH;
13861
13862
          // If c is not U+002F (/), then decrease pointer by 1.
13863
27
          if (url_data[input_position] != '/') {
13864
0
            break;
13865
0
          }
13866
27
        }
13867
13868
342
        input_position++;
13869
342
        break;
13870
4.20k
      }
13871
567
      case state::PATH: {
13872
567
        ada_log("PATH ", helpers::substring(url_data, input_position));
13873
567
        std::string_view view = url_data.substr(input_position);
13874
13875
        // Most time, we do not need percent encoding.
13876
        // Furthermore, we can immediately locate the '?'.
13877
567
        size_t locofquestionmark = view.find('?');
13878
567
        if (locofquestionmark != std::string_view::npos) {
13879
42
          state = state::QUERY;
13880
42
          view.remove_suffix(view.size() - locofquestionmark);
13881
42
          input_position += locofquestionmark + 1;
13882
525
        } else {
13883
525
          input_position = input_size + 1;
13884
525
        }
13885
        if constexpr (store_values) {
13886
          if constexpr (result_type_is_ada_url) {
13887
            helpers::parse_prepared_path(view, url.type, url.path);
13888
          } else {
13889
            url.consume_prepared_path(view);
13890
            ADA_ASSERT_TRUE(url.validate());
13891
          }
13892
        }
13893
567
        break;
13894
4.20k
      }
13895
848
      case state::FILE_SLASH: {
13896
848
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13897
13898
        // If c is U+002F (/) or U+005C (\), then:
13899
848
        if ((input_position != input_size) &&
13900
818
            (url_data[input_position] == '/' ||
13901
795
             url_data[input_position] == '\\')) {
13902
795
          ada_log("FILE_SLASH c is U+002F or U+005C");
13903
          // Set state to file host state.
13904
795
          state = state::FILE_HOST;
13905
795
          input_position++;
13906
795
        } else {
13907
53
          ada_log("FILE_SLASH otherwise");
13908
          // If base is non-null and base's scheme is "file", then:
13909
          // Note: it is unsafe to do base_url->scheme unless you know that
13910
          // base_url_has_value() is true.
13911
53
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13912
            // Set url's host to base's host.
13913
            if constexpr (result_type_is_ada_url) {
13914
              url.host = base_url->host;
13915
24
            } else {
13916
24
              url.update_host_to_base_host(base_url->get_host());
13917
24
            }
13918
            // If the code point substring from pointer to the end of input does
13919
            // not start with a Windows drive letter and base's path[0] is a
13920
            // normalized Windows drive letter, then append base's path[0] to
13921
            // url's path.
13922
24
            if (!base_url->get_pathname().empty()) {
13923
0
              if (!checkers::is_windows_drive_letter(
13924
0
                      url_data.substr(input_position))) {
13925
0
                std::string_view first_base_url_path =
13926
0
                    base_url->get_pathname().substr(1);
13927
0
                size_t loc = first_base_url_path.find('/');
13928
0
                if (loc != std::string_view::npos) {
13929
0
                  helpers::resize(first_base_url_path, loc);
13930
0
                }
13931
0
                if (checkers::is_normalized_windows_drive_letter(
13932
0
                        first_base_url_path)) {
13933
                  if constexpr (result_type_is_ada_url) {
13934
                    url.path += '/';
13935
                    url.path += first_base_url_path;
13936
0
                  } else {
13937
0
                    url.append_base_pathname(
13938
0
                        helpers::concat("/", first_base_url_path));
13939
0
                  }
13940
0
                }
13941
0
              }
13942
0
            }
13943
24
          }
13944
13945
          // Set state to path state, and decrease pointer by 1.
13946
53
          state = state::PATH;
13947
53
        }
13948
13949
848
        break;
13950
4.20k
      }
13951
795
      case state::FILE_HOST: {
13952
795
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13953
795
        std::string_view view = url_data.substr(input_position);
13954
13955
795
        size_t location = view.find_first_of("/\\?");
13956
795
        std::string_view file_host_buffer(
13957
795
            view.data(),
13958
795
            (location != std::string_view::npos) ? location : view.size());
13959
13960
795
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13961
13
          state = state::PATH;
13962
782
        } else if (file_host_buffer.empty()) {
13963
          // Set url's host to the empty string.
13964
          if constexpr (result_type_is_ada_url) {
13965
            url.host = "";
13966
20
          } else {
13967
20
            url.update_base_hostname("");
13968
20
          }
13969
          // Set state to path start state.
13970
20
          state = state::PATH_START;
13971
762
        } else {
13972
762
          size_t consumed_bytes = file_host_buffer.size();
13973
762
          input_position += consumed_bytes;
13974
          // Let host be the result of host parsing buffer with url is not
13975
          // special.
13976
762
          if (!url.parse_host(file_host_buffer)) {
13977
204
            return url;
13978
204
          }
13979
13980
          if constexpr (result_type_is_ada_url) {
13981
            // If host is "localhost", then set host to the empty string.
13982
            if (url.host.has_value() && url.host.value() == "localhost") {
13983
              url.host = "";
13984
            }
13985
558
          } else {
13986
558
            if (url.get_hostname() == "localhost") {
13987
8
              url.update_base_hostname("");
13988
8
            }
13989
558
          }
13990
13991
          // Set buffer to the empty string and state to path start state.
13992
558
          state = state::PATH_START;
13993
558
        }
13994
13995
591
        break;
13996
795
      }
13997
1.03k
      case state::FILE: {
13998
1.03k
        ada_log("FILE ", helpers::substring(url_data, input_position));
13999
1.03k
        std::string_view file_view = url_data.substr(input_position);
14000
14001
1.03k
        url.set_protocol_as_file();
14002
        if constexpr (result_type_is_ada_url) {
14003
          // Set url's host to the empty string.
14004
          url.host = "";
14005
1.03k
        } else {
14006
1.03k
          url.update_base_hostname("");
14007
1.03k
        }
14008
        // If c is U+002F (/) or U+005C (\), then:
14009
1.03k
        if (input_position != input_size &&
14010
938
            (url_data[input_position] == '/' ||
14011
848
             url_data[input_position] == '\\')) {
14012
848
          ada_log("FILE c is U+002F or U+005C");
14013
          // Set state to file slash state.
14014
848
          state = state::FILE_SLASH;
14015
848
        }
14016
        // Otherwise, if base is non-null and base's scheme is "file":
14017
184
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
14018
          // Set url's host to base's host, url's path to a clone of base's
14019
          // path, and url's query to base's query.
14020
88
          ada_log("FILE base non-null");
14021
          if constexpr (result_type_is_ada_url) {
14022
            url.host = base_url->host;
14023
            url.path = base_url->path;
14024
            url.query = base_url->query;
14025
88
          } else {
14026
88
            url.update_host_to_base_host(base_url->get_hostname());
14027
88
            url.update_base_pathname(base_url->get_pathname());
14028
88
            url.update_base_search(base_url->get_search());
14029
88
          }
14030
88
          url.has_opaque_path = base_url->has_opaque_path;
14031
14032
          // If c is U+003F (?), then set url's query to the empty string and
14033
          // state to query state.
14034
88
          if (input_position != input_size && url_data[input_position] == '?') {
14035
1
            state = state::QUERY;
14036
1
          }
14037
          // Otherwise, if c is not the EOF code point:
14038
87
          else if (input_position != input_size) {
14039
            // Set url's query to null.
14040
65
            url.clear_search();
14041
            // If the code point substring from pointer to the end of input does
14042
            // not start with a Windows drive letter, then shorten url's path.
14043
65
            if (!checkers::is_windows_drive_letter(file_view)) {
14044
              if constexpr (result_type_is_ada_url) {
14045
                helpers::shorten_path(url.path, url.type);
14046
57
              } else {
14047
57
                std::string_view path = url.get_pathname();
14048
57
                if (helpers::shorten_path(path, url.type)) {
14049
0
                  url.update_base_pathname(std::move(std::string(path)));
14050
0
                }
14051
57
              }
14052
57
            }
14053
            // Otherwise:
14054
8
            else {
14055
              // Set url's path to an empty list.
14056
8
              url.clear_pathname();
14057
8
              url.has_opaque_path = true;
14058
8
            }
14059
14060
            // Set state to path state and decrease pointer by 1.
14061
65
            state = state::PATH;
14062
65
            break;
14063
65
          }
14064
88
        }
14065
        // Otherwise, set state to path state, and decrease pointer by 1.
14066
96
        else {
14067
96
          ada_log("FILE go to path");
14068
96
          state = state::PATH;
14069
96
          break;
14070
96
        }
14071
14072
871
        input_position++;
14073
871
        break;
14074
1.03k
      }
14075
0
      default:
14076
0
        unreachable();
14077
63.2k
    }
14078
63.2k
  }
14079
  if constexpr (store_values) {
14080
    if (fragment.has_value()) {
14081
      url.update_unencoded_base_hash(*fragment);
14082
    }
14083
  }
14084
2.87k
  return url;
14085
15.7k
}
14086
14087
template url parse_url_impl(std::string_view user_input,
14088
                            const url* base_url = nullptr);
14089
template url_aggregator parse_url_impl(
14090
    std::string_view user_input, const url_aggregator* base_url = nullptr);
14091
14092
template <class result_type>
14093
result_type parse_url(std::string_view user_input,
14094
0
                      const result_type* base_url) {
14095
0
  return parse_url_impl<result_type, true>(user_input, base_url);
14096
0
}
Unexecuted instantiation: ada::url ada::parser::parse_url<ada::url>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url const*)
Unexecuted instantiation: ada::url_aggregator ada::parser::parse_url<ada::url_aggregator>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator const*)
14097
14098
template url parse_url<url>(std::string_view user_input,
14099
                            const url* base_url = nullptr);
14100
template url_aggregator parse_url<url_aggregator>(
14101
    std::string_view user_input, const url_aggregator* base_url = nullptr);
14102
}  // namespace ada::parser
14103
/* end file src/parser.cpp */
14104
/* begin file src/url_components.cpp */
14105
14106
#include <iterator>
14107
#include <string>
14108
14109
namespace ada {
14110
14111
0
[[nodiscard]] std::string url_components::to_string() const {
14112
0
  std::string answer;
14113
0
  auto back = std::back_insert_iterator(answer);
14114
0
  answer.append("{\n");
14115
14116
0
  answer.append("\t\"protocol_end\":\"");
14117
0
  helpers::encode_json(std::to_string(protocol_end), back);
14118
0
  answer.append("\",\n");
14119
14120
0
  answer.append("\t\"username_end\":\"");
14121
0
  helpers::encode_json(std::to_string(username_end), back);
14122
0
  answer.append("\",\n");
14123
14124
0
  answer.append("\t\"host_start\":\"");
14125
0
  helpers::encode_json(std::to_string(host_start), back);
14126
0
  answer.append("\",\n");
14127
14128
0
  answer.append("\t\"host_end\":\"");
14129
0
  helpers::encode_json(std::to_string(host_end), back);
14130
0
  answer.append("\",\n");
14131
14132
0
  answer.append("\t\"port\":\"");
14133
0
  helpers::encode_json(std::to_string(port), back);
14134
0
  answer.append("\",\n");
14135
14136
0
  answer.append("\t\"pathname_start\":\"");
14137
0
  helpers::encode_json(std::to_string(pathname_start), back);
14138
0
  answer.append("\",\n");
14139
14140
0
  answer.append("\t\"search_start\":\"");
14141
0
  helpers::encode_json(std::to_string(search_start), back);
14142
0
  answer.append("\",\n");
14143
14144
0
  answer.append("\t\"hash_start\":\"");
14145
0
  helpers::encode_json(std::to_string(hash_start), back);
14146
0
  answer.append("\",\n");
14147
14148
0
  answer.append("\n}");
14149
0
  return answer;
14150
0
}
14151
14152
}  // namespace ada
14153
/* end file src/url_components.cpp */
14154
/* begin file src/url_aggregator.cpp */
14155
14156
#include <iterator>
14157
#include <ranges>
14158
#include <string>
14159
#include <string_view>
14160
14161
namespace ada {
14162
template <bool has_state_override>
14163
[[nodiscard]] ada_really_inline bool url_aggregator::parse_scheme_with_colon(
14164
10.2k
    const std::string_view input_with_colon) {
14165
10.2k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14166
10.2k
  ADA_ASSERT_TRUE(validate());
14167
10.2k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14168
10.2k
  std::string_view input{input_with_colon};
14169
10.2k
  input.remove_suffix(1);
14170
10.2k
  auto parsed_type = ada::scheme::get_scheme_type(input);
14171
10.2k
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
14172
  /**
14173
   * In the common case, we will immediately recognize a special scheme (e.g.,
14174
   *http, https), in which case, we can go really fast.
14175
   **/
14176
10.2k
  if (is_input_special) {  // fast path!!!
14177
3.54k
    if constexpr (has_state_override) {
14178
      // If url's scheme is not a special scheme and buffer is a special scheme,
14179
      // then return.
14180
0
      if (is_special() != is_input_special) {
14181
0
        return false;
14182
0
      }
14183
14184
      // If url includes credentials or has a non-null port, and buffer is
14185
      // "file", then return.
14186
0
      if ((has_credentials() || components.port != url_components::omitted) &&
14187
0
          parsed_type == ada::scheme::type::FILE) {
14188
0
        return false;
14189
0
      }
14190
14191
      // If url's scheme is "file" and its host is an empty host, then return.
14192
      // An empty host is the empty string.
14193
0
      if (type == ada::scheme::type::FILE &&
14194
0
          components.host_start == components.host_end) {
14195
0
        return false;
14196
0
      }
14197
0
    }
14198
14199
0
    type = parsed_type;
14200
3.54k
    set_scheme_from_view_with_colon(input_with_colon);
14201
14202
3.54k
    if constexpr (has_state_override) {
14203
      // This is uncommon.
14204
0
      uint16_t urls_scheme_port = get_special_port();
14205
14206
      // If url's port is url's scheme's default port, then set url's port to
14207
      // null.
14208
0
      if (components.port == urls_scheme_port) {
14209
0
        clear_port();
14210
0
      }
14211
0
    }
14212
6.67k
  } else {  // slow path
14213
6.67k
    std::string _buffer(input);
14214
    // Next function is only valid if the input is ASCII and returns false
14215
    // otherwise, but it seems that we always have ascii content so we do not
14216
    // need to check the return value.
14217
6.67k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14218
14219
6.67k
    if constexpr (has_state_override) {
14220
      // If url's scheme is a special scheme and buffer is not a special scheme,
14221
      // then return. If url's scheme is not a special scheme and buffer is a
14222
      // special scheme, then return.
14223
0
      if (is_special() != ada::scheme::is_special(_buffer)) {
14224
0
        return true;
14225
0
      }
14226
14227
      // If url includes credentials or has a non-null port, and buffer is
14228
      // "file", then return.
14229
0
      if ((has_credentials() || components.port != url_components::omitted) &&
14230
0
          _buffer == "file") {
14231
0
        return true;
14232
0
      }
14233
14234
      // If url's scheme is "file" and its host is an empty host, then return.
14235
      // An empty host is the empty string.
14236
0
      if (type == ada::scheme::type::FILE &&
14237
0
          components.host_start == components.host_end) {
14238
0
        return true;
14239
0
      }
14240
0
    }
14241
14242
0
    set_scheme(_buffer);
14243
14244
6.67k
    if constexpr (has_state_override) {
14245
      // This is uncommon.
14246
0
      uint16_t urls_scheme_port = get_special_port();
14247
14248
      // If url's port is url's scheme's default port, then set url's port to
14249
      // null.
14250
0
      if (components.port == urls_scheme_port) {
14251
0
        clear_port();
14252
0
      }
14253
0
    }
14254
6.67k
  }
14255
0
  ADA_ASSERT_TRUE(validate());
14256
10.2k
  return true;
14257
10.2k
}
bool ada::url_aggregator::parse_scheme_with_colon<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14164
10.2k
    const std::string_view input_with_colon) {
14165
10.2k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14166
10.2k
  ADA_ASSERT_TRUE(validate());
14167
10.2k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14168
10.2k
  std::string_view input{input_with_colon};
14169
10.2k
  input.remove_suffix(1);
14170
10.2k
  auto parsed_type = ada::scheme::get_scheme_type(input);
14171
10.2k
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
14172
  /**
14173
   * In the common case, we will immediately recognize a special scheme (e.g.,
14174
   *http, https), in which case, we can go really fast.
14175
   **/
14176
10.2k
  if (is_input_special) {  // fast path!!!
14177
    if constexpr (has_state_override) {
14178
      // If url's scheme is not a special scheme and buffer is a special scheme,
14179
      // then return.
14180
      if (is_special() != is_input_special) {
14181
        return false;
14182
      }
14183
14184
      // If url includes credentials or has a non-null port, and buffer is
14185
      // "file", then return.
14186
      if ((has_credentials() || components.port != url_components::omitted) &&
14187
          parsed_type == ada::scheme::type::FILE) {
14188
        return false;
14189
      }
14190
14191
      // If url's scheme is "file" and its host is an empty host, then return.
14192
      // An empty host is the empty string.
14193
      if (type == ada::scheme::type::FILE &&
14194
          components.host_start == components.host_end) {
14195
        return false;
14196
      }
14197
    }
14198
14199
3.54k
    type = parsed_type;
14200
3.54k
    set_scheme_from_view_with_colon(input_with_colon);
14201
14202
    if constexpr (has_state_override) {
14203
      // This is uncommon.
14204
      uint16_t urls_scheme_port = get_special_port();
14205
14206
      // If url's port is url's scheme's default port, then set url's port to
14207
      // null.
14208
      if (components.port == urls_scheme_port) {
14209
        clear_port();
14210
      }
14211
    }
14212
6.67k
  } else {  // slow path
14213
6.67k
    std::string _buffer(input);
14214
    // Next function is only valid if the input is ASCII and returns false
14215
    // otherwise, but it seems that we always have ascii content so we do not
14216
    // need to check the return value.
14217
6.67k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14218
14219
    if constexpr (has_state_override) {
14220
      // If url's scheme is a special scheme and buffer is not a special scheme,
14221
      // then return. If url's scheme is not a special scheme and buffer is a
14222
      // special scheme, then return.
14223
      if (is_special() != ada::scheme::is_special(_buffer)) {
14224
        return true;
14225
      }
14226
14227
      // If url includes credentials or has a non-null port, and buffer is
14228
      // "file", then return.
14229
      if ((has_credentials() || components.port != url_components::omitted) &&
14230
          _buffer == "file") {
14231
        return true;
14232
      }
14233
14234
      // If url's scheme is "file" and its host is an empty host, then return.
14235
      // An empty host is the empty string.
14236
      if (type == ada::scheme::type::FILE &&
14237
          components.host_start == components.host_end) {
14238
        return true;
14239
      }
14240
    }
14241
14242
6.67k
    set_scheme(_buffer);
14243
14244
    if constexpr (has_state_override) {
14245
      // This is uncommon.
14246
      uint16_t urls_scheme_port = get_special_port();
14247
14248
      // If url's port is url's scheme's default port, then set url's port to
14249
      // null.
14250
      if (components.port == urls_scheme_port) {
14251
        clear_port();
14252
      }
14253
    }
14254
6.67k
  }
14255
10.2k
  ADA_ASSERT_TRUE(validate());
14256
10.2k
  return true;
14257
10.2k
}
Unexecuted instantiation: bool ada::url_aggregator::parse_scheme_with_colon<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
14258
14259
389
inline void url_aggregator::copy_scheme(const url_aggregator& u) noexcept {
14260
389
  ada_log("url_aggregator::copy_scheme ", u.buffer);
14261
389
  ADA_ASSERT_TRUE(validate());
14262
  // next line could overflow but unsigned arithmetic has well-defined
14263
  // overflows.
14264
389
  uint32_t new_difference = u.components.protocol_end - components.protocol_end;
14265
389
  type = u.type;
14266
389
  buffer.erase(0, components.protocol_end);
14267
389
  buffer.insert(0, u.get_protocol());
14268
389
  components.protocol_end = u.components.protocol_end;
14269
14270
  // No need to update the components
14271
389
  if (new_difference == 0) {
14272
39
    return;
14273
39
  }
14274
14275
  // Update the rest of the components.
14276
350
  components.username_end += new_difference;
14277
350
  components.host_start += new_difference;
14278
350
  components.host_end += new_difference;
14279
350
  components.pathname_start += new_difference;
14280
350
  if (components.search_start != url_components::omitted) {
14281
0
    components.search_start += new_difference;
14282
0
  }
14283
350
  if (components.hash_start != url_components::omitted) {
14284
0
    components.hash_start += new_difference;
14285
0
  }
14286
350
  ADA_ASSERT_TRUE(validate());
14287
350
}
14288
14289
inline void url_aggregator::set_scheme_from_view_with_colon(
14290
3.54k
    std::string_view new_scheme_with_colon) noexcept {
14291
3.54k
  ada_log("url_aggregator::set_scheme_from_view_with_colon ",
14292
3.54k
          new_scheme_with_colon);
14293
3.54k
  ADA_ASSERT_TRUE(validate());
14294
3.54k
  ADA_ASSERT_TRUE(!new_scheme_with_colon.empty() &&
14295
3.54k
                  new_scheme_with_colon.back() == ':');
14296
  // next line could overflow but unsigned arithmetic has well-defined
14297
  // overflows.
14298
3.54k
  uint32_t new_difference =
14299
3.54k
      uint32_t(new_scheme_with_colon.size()) - components.protocol_end;
14300
14301
3.54k
  if (buffer.empty()) {
14302
3.54k
    buffer.append(new_scheme_with_colon);
14303
3.54k
  } else {
14304
0
    buffer.erase(0, components.protocol_end);
14305
0
    buffer.insert(0, new_scheme_with_colon);
14306
0
  }
14307
3.54k
  components.protocol_end += new_difference;
14308
14309
  // Update the rest of the components.
14310
3.54k
  components.username_end += new_difference;
14311
3.54k
  components.host_start += new_difference;
14312
3.54k
  components.host_end += new_difference;
14313
3.54k
  components.pathname_start += new_difference;
14314
3.54k
  if (components.search_start != url_components::omitted) {
14315
0
    components.search_start += new_difference;
14316
0
  }
14317
3.54k
  if (components.hash_start != url_components::omitted) {
14318
0
    components.hash_start += new_difference;
14319
0
  }
14320
3.54k
  ADA_ASSERT_TRUE(validate());
14321
3.54k
}
14322
14323
6.67k
inline void url_aggregator::set_scheme(std::string_view new_scheme) noexcept {
14324
6.67k
  ada_log("url_aggregator::set_scheme ", new_scheme);
14325
6.67k
  ADA_ASSERT_TRUE(validate());
14326
6.67k
  ADA_ASSERT_TRUE(new_scheme.empty() || new_scheme.back() != ':');
14327
  // next line could overflow but unsigned arithmetic has well-defined
14328
  // overflows.
14329
6.67k
  uint32_t new_difference =
14330
6.67k
      uint32_t(new_scheme.size()) - components.protocol_end + 1;
14331
14332
6.67k
  type = ada::scheme::get_scheme_type(new_scheme);
14333
6.67k
  if (buffer.empty()) {
14334
6.67k
    buffer.append(helpers::concat(new_scheme, ":"));
14335
6.67k
  } else {
14336
0
    buffer.erase(0, components.protocol_end);
14337
0
    buffer.insert(0, helpers::concat(new_scheme, ":"));
14338
0
  }
14339
6.67k
  components.protocol_end = uint32_t(new_scheme.size() + 1);
14340
14341
  // Update the rest of the components.
14342
6.67k
  components.username_end += new_difference;
14343
6.67k
  components.host_start += new_difference;
14344
6.67k
  components.host_end += new_difference;
14345
6.67k
  components.pathname_start += new_difference;
14346
6.67k
  if (components.search_start != url_components::omitted) {
14347
0
    components.search_start += new_difference;
14348
0
  }
14349
6.67k
  if (components.hash_start != url_components::omitted) {
14350
0
    components.hash_start += new_difference;
14351
0
  }
14352
6.67k
  ADA_ASSERT_TRUE(validate());
14353
6.67k
}
14354
14355
0
bool url_aggregator::set_protocol(const std::string_view input) {
14356
0
  ada_log("url_aggregator::set_protocol ", input);
14357
0
  ADA_ASSERT_TRUE(validate());
14358
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14359
0
  std::string view(input);
14360
0
  helpers::remove_ascii_tab_or_newline(view);
14361
0
  if (view.empty()) {
14362
0
    return true;
14363
0
  }
14364
14365
  // Schemes should start with alpha values.
14366
0
  if (!checkers::is_alpha(view[0])) {
14367
0
    return false;
14368
0
  }
14369
14370
0
  view.append(":");
14371
14372
0
  std::string::iterator pointer =
14373
0
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
14374
14375
0
  if (pointer != view.end() && *pointer == ':') {
14376
0
    return parse_scheme_with_colon<true>(
14377
0
        view.substr(0, pointer - view.begin() + 1));
14378
0
  }
14379
0
  return false;
14380
0
}
14381
14382
0
bool url_aggregator::set_username(const std::string_view input) {
14383
0
  ada_log("url_aggregator::set_username '", input, "' ");
14384
0
  ADA_ASSERT_TRUE(validate());
14385
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14386
0
  if (cannot_have_credentials_or_port()) {
14387
0
    return false;
14388
0
  }
14389
0
  size_t idx = ada::unicode::percent_encode_index(
14390
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
14391
0
  if (idx == input.size()) {
14392
0
    update_base_username(input);
14393
0
  } else {
14394
    // We only create a temporary string if we have to!
14395
0
    update_base_username(ada::unicode::percent_encode(
14396
0
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14397
0
  }
14398
0
  ADA_ASSERT_TRUE(validate());
14399
0
  return true;
14400
0
}
14401
14402
0
bool url_aggregator::set_password(const std::string_view input) {
14403
0
  ada_log("url_aggregator::set_password '", input, "'");
14404
0
  ADA_ASSERT_TRUE(validate());
14405
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14406
0
  if (cannot_have_credentials_or_port()) {
14407
0
    return false;
14408
0
  }
14409
0
  size_t idx = ada::unicode::percent_encode_index(
14410
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
14411
0
  if (idx == input.size()) {
14412
0
    update_base_password(input);
14413
0
  } else {
14414
    // We only create a temporary string if we have to!
14415
0
    update_base_password(ada::unicode::percent_encode(
14416
0
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14417
0
  }
14418
0
  ADA_ASSERT_TRUE(validate());
14419
0
  return true;
14420
0
}
14421
14422
0
bool url_aggregator::set_port(const std::string_view input) {
14423
0
  ada_log("url_aggregator::set_port ", input);
14424
0
  ADA_ASSERT_TRUE(validate());
14425
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14426
0
  if (cannot_have_credentials_or_port()) {
14427
0
    return false;
14428
0
  }
14429
14430
0
  if (input.empty()) {
14431
0
    clear_port();
14432
0
    return true;
14433
0
  }
14434
14435
0
  std::string trimmed(input);
14436
0
  helpers::remove_ascii_tab_or_newline(trimmed);
14437
14438
0
  if (trimmed.empty()) {
14439
0
    return true;
14440
0
  }
14441
14442
  // Input should not start with a non-digit character.
14443
0
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
14444
0
    return false;
14445
0
  }
14446
14447
  // Find the first non-digit character to determine the length of digits
14448
0
  auto first_non_digit =
14449
0
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
14450
0
  std::string_view digits_to_parse =
14451
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
14452
14453
  // Revert changes if parse_port fails.
14454
0
  uint32_t previous_port = components.port;
14455
0
  parse_port(digits_to_parse);
14456
0
  if (is_valid) {
14457
0
    return true;
14458
0
  }
14459
0
  update_base_port(previous_port);
14460
0
  is_valid = true;
14461
0
  ADA_ASSERT_TRUE(validate());
14462
0
  return false;
14463
0
}
14464
14465
0
bool url_aggregator::set_pathname(const std::string_view input) {
14466
0
  ada_log("url_aggregator::set_pathname ", input);
14467
0
  ADA_ASSERT_TRUE(validate());
14468
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14469
0
  if (has_opaque_path) {
14470
0
    return false;
14471
0
  }
14472
0
  clear_pathname();
14473
0
  parse_path(input);
14474
0
  if (get_pathname().starts_with("//") && !has_authority() && !has_dash_dot()) {
14475
0
    buffer.insert(components.pathname_start, "/.");
14476
0
    components.pathname_start += 2;
14477
0
  }
14478
0
  ADA_ASSERT_TRUE(validate());
14479
0
  return true;
14480
0
}
14481
14482
0
ada_really_inline void url_aggregator::parse_path(std::string_view input) {
14483
0
  ada_log("url_aggregator::parse_path ", input);
14484
0
  ADA_ASSERT_TRUE(validate());
14485
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14486
0
  std::string tmp_buffer;
14487
0
  std::string_view internal_input;
14488
0
  if (unicode::has_tabs_or_newline(input)) {
14489
0
    tmp_buffer = input;
14490
    // Optimization opportunity: Instead of copying and then pruning, we could
14491
    // just directly build the string from user_input.
14492
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
14493
0
    internal_input = tmp_buffer;
14494
0
  } else {
14495
0
    internal_input = input;
14496
0
  }
14497
14498
  // If url is special, then:
14499
0
  if (is_special()) {
14500
0
    if (internal_input.empty()) {
14501
0
      update_base_pathname("/");
14502
0
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
14503
0
      consume_prepared_path(internal_input.substr(1));
14504
0
    } else {
14505
0
      consume_prepared_path(internal_input);
14506
0
    }
14507
0
  } else if (!internal_input.empty()) {
14508
0
    if (internal_input[0] == '/') {
14509
0
      consume_prepared_path(internal_input.substr(1));
14510
0
    } else {
14511
0
      consume_prepared_path(internal_input);
14512
0
    }
14513
0
  } else {
14514
    // Non-special URLs with an empty host can have their paths erased
14515
    // Path-only URLs cannot have their paths erased
14516
0
    if (components.host_start == components.host_end && !has_authority()) {
14517
0
      update_base_pathname("/");
14518
0
    }
14519
0
  }
14520
0
  ADA_ASSERT_TRUE(validate());
14521
0
}
14522
14523
0
void url_aggregator::set_search(const std::string_view input) {
14524
0
  ada_log("url_aggregator::set_search ", input);
14525
0
  ADA_ASSERT_TRUE(validate());
14526
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14527
0
  if (input.empty()) {
14528
0
    clear_search();
14529
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
14530
0
    return;
14531
0
  }
14532
14533
0
  std::string new_value;
14534
0
  new_value = input[0] == '?' ? input.substr(1) : input;
14535
0
  helpers::remove_ascii_tab_or_newline(new_value);
14536
14537
0
  auto query_percent_encode_set =
14538
0
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
14539
0
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
14540
14541
0
  update_base_search(new_value, query_percent_encode_set);
14542
0
  ADA_ASSERT_TRUE(validate());
14543
0
}
14544
14545
0
void url_aggregator::set_hash(const std::string_view input) {
14546
0
  ada_log("url_aggregator::set_hash ", input);
14547
0
  ADA_ASSERT_TRUE(validate());
14548
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14549
0
  if (input.empty()) {
14550
0
    if (components.hash_start != url_components::omitted) {
14551
0
      buffer.resize(components.hash_start);
14552
0
      components.hash_start = url_components::omitted;
14553
0
    }
14554
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
14555
0
    return;
14556
0
  }
14557
14558
0
  std::string new_value;
14559
0
  new_value = input[0] == '#' ? input.substr(1) : input;
14560
0
  helpers::remove_ascii_tab_or_newline(new_value);
14561
0
  update_unencoded_base_hash(new_value);
14562
0
  ADA_ASSERT_TRUE(validate());
14563
0
}
14564
14565
0
bool url_aggregator::set_href(const std::string_view input) {
14566
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14567
0
  ada_log("url_aggregator::set_href ", input, " [", input.size(), " bytes]");
14568
0
  ada::result<url_aggregator> out = ada::parse<url_aggregator>(input);
14569
0
  ada_log("url_aggregator::set_href, success :", out.has_value());
14570
14571
0
  if (out) {
14572
0
    ada_log("url_aggregator::set_href, parsed ", out->to_string());
14573
    // TODO: Figure out why the following line puts test to never finish.
14574
0
    *this = *out;
14575
0
  }
14576
14577
0
  return out.has_value();
14578
0
}
14579
14580
7.66k
ada_really_inline bool url_aggregator::parse_host(std::string_view input) {
14581
7.66k
  ada_log("url_aggregator:parse_host \"", input, "\" [", input.size(),
14582
7.66k
          " bytes]");
14583
7.66k
  ADA_ASSERT_TRUE(validate());
14584
7.66k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14585
7.66k
  if (input.empty()) {
14586
12
    return is_valid = false;
14587
12
  }  // technically unnecessary.
14588
  // If input starts with U+005B ([), then:
14589
7.65k
  if (input[0] == '[') {
14590
    // If input does not end with U+005D (]), validation error, return failure.
14591
619
    if (input.back() != ']') {
14592
188
      return is_valid = false;
14593
188
    }
14594
431
    ada_log("parse_host ipv6");
14595
14596
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
14597
    // trailing U+005D (]) removed.
14598
431
    input.remove_prefix(1);
14599
431
    input.remove_suffix(1);
14600
431
    return parse_ipv6(input);
14601
619
  }
14602
14603
  // If isNotSpecial is true, then return the result of opaque-host parsing
14604
  // input.
14605
7.03k
  if (!is_special()) {
14606
284
    return parse_opaque_host(input);
14607
284
  }
14608
  // Let domain be the result of running UTF-8 decode without BOM on the
14609
  // percent-decoding of input. Let asciiDomain be the result of running domain
14610
  // to ASCII with domain and false. The most common case is an ASCII input, in
14611
  // which case we do not need to call the expensive 'to_ascii' if a few
14612
  // conditions are met: no '%' and no 'xn-' subsequence.
14613
14614
  // Often, the input does not contain any forbidden code points, and no upper
14615
  // case ASCII letter, then we can just copy it to the buffer. We want to
14616
  // optimize for such a common case.
14617
14618
  // Fast path: try to parse as pure decimal IPv4(a.b.c.d) first.
14619
6.74k
  const uint64_t fast_result = checkers::try_parse_ipv4_fast(input);
14620
6.74k
  if (fast_result < checkers::ipv4_fast_fail) {
14621
    // Fast path succeeded - input is pure decimal IPv4
14622
50
    if (!input.empty() && input.back() == '.') {
14623
24
      update_base_hostname(input.substr(0, input.size() - 1));
14624
26
    } else {
14625
26
      update_base_hostname(input);
14626
26
    }
14627
50
    host_type = IPV4;
14628
50
    ada_log("parse_host fast path decimal ipv4");
14629
50
    ADA_ASSERT_TRUE(validate());
14630
50
    return true;
14631
50
  }
14632
6.69k
  uint8_t is_forbidden_or_upper =
14633
6.69k
      unicode::contains_forbidden_domain_code_point_or_upper(input.data(),
14634
6.69k
                                                             input.size());
14635
  // Minor optimization opportunity:
14636
  // contains_forbidden_domain_code_point_or_upper could be extend to check for
14637
  // the presence of characters that cannot appear in the ipv4 address and we
14638
  // could also check whether x and n and - are present, and so we could skip
14639
  // some of the checks below. However, the gains are likely to be small, and
14640
  // the code would be more complex.
14641
6.69k
  if (is_forbidden_or_upper == 0 &&
14642
2.05k
      input.find("xn-") == std::string_view::npos) {
14643
    // fast path
14644
1.80k
    update_base_hostname(input);
14645
14646
    // Check for other IPv4 formats (hex, octal, etc.)
14647
1.80k
    if (checkers::is_ipv4(get_hostname())) {
14648
1.16k
      ada_log("parse_host fast path ipv4");
14649
1.16k
      return parse_ipv4(get_hostname(), true);
14650
1.16k
    }
14651
638
    ada_log("parse_host fast path ", get_hostname());
14652
638
    return true;
14653
1.80k
  }
14654
  // We have encountered at least one forbidden code point or the input contains
14655
  // 'xn-' (case insensitive), so we need to call 'to_ascii' to perform the full
14656
  // conversion.
14657
14658
4.89k
  ada_log("parse_host calling to_ascii");
14659
4.89k
  std::optional<std::string> host = std::string(get_hostname());
14660
4.89k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
14661
4.89k
  if (!is_valid) {
14662
2.32k
    ada_log("parse_host to_ascii returns false");
14663
2.32k
    return is_valid = false;
14664
2.32k
  }
14665
2.57k
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
14666
2.57k
          " bytes]");
14667
14668
2.57k
  if (std::ranges::any_of(host.value(),
14669
2.57k
                          ada::unicode::is_forbidden_domain_code_point)) {
14670
0
    return is_valid = false;
14671
0
  }
14672
14673
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
14674
  // asciiDomain.
14675
2.57k
  if (checkers::is_ipv4(host.value())) {
14676
345
    ada_log("parse_host got ipv4 ", *host);
14677
345
    return parse_ipv4(host.value(), false);
14678
345
  }
14679
14680
2.22k
  update_base_hostname(host.value());
14681
2.22k
  ADA_ASSERT_TRUE(validate());
14682
2.22k
  return true;
14683
2.57k
}
14684
14685
template <bool override_hostname>
14686
0
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14687
0
  ada_log("url_aggregator::set_host_or_hostname ", input);
14688
0
  ADA_ASSERT_TRUE(validate());
14689
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14690
0
  if (has_opaque_path) {
14691
0
    return false;
14692
0
  }
14693
14694
0
  std::string previous_host(get_hostname());
14695
0
  uint32_t previous_port = components.port;
14696
14697
0
  size_t host_end_pos = input.find('#');
14698
0
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14699
0
                                      ? host_end_pos
14700
0
                                      : input.size());
14701
0
  helpers::remove_ascii_tab_or_newline(_host);
14702
0
  std::string_view new_host(_host);
14703
14704
  // If url's scheme is "file", then set state to file host state, instead of
14705
  // host state.
14706
0
  if (type != ada::scheme::type::FILE) {
14707
0
    std::string_view host_view(_host.data(), _host.length());
14708
0
    auto [location, found_colon] =
14709
0
        helpers::get_host_delimiter_location(is_special(), host_view);
14710
14711
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14712
    // Note: the 'found_colon' value is true if and only if a colon was
14713
    // encountered while not inside brackets.
14714
0
    if (found_colon) {
14715
      // If buffer is the empty string, host-missing validation error, return
14716
      // failure.
14717
0
      std::string_view host_buffer = host_view.substr(0, location);
14718
0
      if (host_buffer.empty()) {
14719
0
        return false;
14720
0
      }
14721
14722
      // If state override is given and state override is hostname state, then
14723
      // return failure.
14724
0
      if constexpr (override_hostname) {
14725
0
        return false;
14726
0
      }
14727
14728
      // Let host be the result of host parsing buffer with url is not special.
14729
0
      bool succeeded = parse_host(host_buffer);
14730
0
      if (!succeeded) {
14731
0
        update_base_hostname(previous_host);
14732
0
        update_base_port(previous_port);
14733
0
        return false;
14734
0
      }
14735
14736
      // Set url's host to host, buffer to the empty string, and state to port
14737
      // state.
14738
0
      std::string_view port_buffer = new_host.substr(location + 1);
14739
0
      if (!port_buffer.empty()) {
14740
0
        set_port(port_buffer);
14741
0
      }
14742
0
      return true;
14743
0
    }
14744
    // Otherwise, if one of the following is true:
14745
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14746
    // - url is special and c is U+005C (\)
14747
0
    else {
14748
      // If url is special and host_view is the empty string, host-missing
14749
      // validation error, return failure.
14750
0
      if (host_view.empty() && is_special()) {
14751
0
        return false;
14752
0
      }
14753
14754
      // Otherwise, if state override is given, host_view is the empty string,
14755
      // and either url includes credentials or url's port is non-null, then
14756
      // return failure.
14757
0
      if (host_view.empty() && (has_credentials() || has_port())) {
14758
0
        return false;
14759
0
      }
14760
14761
      // Let host be the result of host parsing host_view with url is not
14762
      // special.
14763
0
      if (host_view.empty() && !is_special()) {
14764
0
        if (has_hostname()) {
14765
0
          clear_hostname();  // easy!
14766
0
        } else if (has_dash_dot()) {
14767
0
          add_authority_slashes_if_needed();
14768
0
          delete_dash_dot();
14769
0
        }
14770
0
        return true;
14771
0
      }
14772
14773
0
      bool succeeded = parse_host(host_view);
14774
0
      if (!succeeded) {
14775
0
        update_base_hostname(previous_host);
14776
0
        update_base_port(previous_port);
14777
0
        return false;
14778
0
      } else if (has_dash_dot()) {
14779
        // Should remove dash_dot from pathname
14780
0
        delete_dash_dot();
14781
0
      }
14782
0
      return true;
14783
0
    }
14784
0
  }
14785
14786
0
  size_t location = new_host.find_first_of("/\\?");
14787
0
  if (location != std::string_view::npos) {
14788
0
    new_host.remove_suffix(new_host.length() - location);
14789
0
  }
14790
14791
0
  if (new_host.empty()) {
14792
    // Set url's host to the empty string.
14793
0
    clear_hostname();
14794
0
  } else {
14795
    // Let host be the result of host parsing buffer with url is not special.
14796
0
    if (!parse_host(new_host)) {
14797
0
      update_base_hostname(previous_host);
14798
0
      update_base_port(previous_port);
14799
0
      return false;
14800
0
    }
14801
14802
    // If host is "localhost", then set host to the empty string.
14803
0
    if (helpers::substring(buffer, components.host_start,
14804
0
                           components.host_end) == "localhost") {
14805
0
      clear_hostname();
14806
0
    }
14807
0
  }
14808
0
  ADA_ASSERT_TRUE(validate());
14809
0
  return true;
14810
0
}
Unexecuted instantiation: bool ada::url_aggregator::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: bool ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
14811
14812
0
bool url_aggregator::set_host(const std::string_view input) {
14813
0
  ada_log("url_aggregator::set_host '", input, "'");
14814
0
  ADA_ASSERT_TRUE(validate());
14815
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14816
0
  return set_host_or_hostname<false>(input);
14817
0
}
14818
14819
0
bool url_aggregator::set_hostname(const std::string_view input) {
14820
0
  ada_log("url_aggregator::set_hostname '", input, "'");
14821
0
  ADA_ASSERT_TRUE(validate());
14822
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14823
0
  return set_host_or_hostname<true>(input);
14824
0
}
14825
14826
0
[[nodiscard]] std::string url_aggregator::get_origin() const noexcept {
14827
0
  ada_log("url_aggregator::get_origin");
14828
0
  if (is_special()) {
14829
    // Return a new opaque origin.
14830
0
    if (type == scheme::FILE) {
14831
0
      return "null";
14832
0
    }
14833
14834
0
    return helpers::concat(get_protocol(), "//", get_host());
14835
0
  }
14836
14837
0
  if (get_protocol() == "blob:") {
14838
0
    std::string_view path = get_pathname();
14839
0
    if (!path.empty()) {
14840
0
      auto out = ada::parse<ada::url_aggregator>(path);
14841
0
      if (out && (out->type == scheme::HTTP || out->type == scheme::HTTPS)) {
14842
        // If pathURL's scheme is not "http" and not "https", then return a
14843
        // new opaque origin.
14844
0
        return helpers::concat(out->get_protocol(), "//", out->get_host());
14845
0
      }
14846
0
    }
14847
0
  }
14848
14849
  // Return a new opaque origin.
14850
0
  return "null";
14851
0
}
14852
14853
[[nodiscard]] std::string_view url_aggregator::get_username() const noexcept
14854
0
    ada_lifetime_bound {
14855
0
  ada_log("url_aggregator::get_username");
14856
0
  if (has_non_empty_username()) {
14857
0
    return helpers::substring(buffer, components.protocol_end + 2,
14858
0
                              components.username_end);
14859
0
  }
14860
0
  return "";
14861
0
}
14862
14863
[[nodiscard]] std::string_view url_aggregator::get_password() const noexcept
14864
0
    ada_lifetime_bound {
14865
0
  ada_log("url_aggregator::get_password");
14866
0
  if (has_non_empty_password()) {
14867
0
    return helpers::substring(buffer, components.username_end + 1,
14868
0
                              components.host_start);
14869
0
  }
14870
0
  return "";
14871
0
}
14872
14873
[[nodiscard]] std::string_view url_aggregator::get_port() const noexcept
14874
0
    ada_lifetime_bound {
14875
0
  ada_log("url_aggregator::get_port");
14876
0
  if (components.port == url_components::omitted) {
14877
0
    return "";
14878
0
  }
14879
0
  return helpers::substring(buffer, components.host_end + 1,
14880
0
                            components.pathname_start);
14881
0
}
14882
14883
[[nodiscard]] std::string_view url_aggregator::get_hash() const noexcept
14884
0
    ada_lifetime_bound {
14885
0
  ada_log("url_aggregator::get_hash");
14886
  // If this's URL's fragment is either null or the empty string, then return
14887
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
14888
0
  if (components.hash_start == url_components::omitted) {
14889
0
    return "";
14890
0
  }
14891
0
  if (buffer.size() - components.hash_start <= 1) {
14892
0
    return "";
14893
0
  }
14894
0
  return helpers::substring(buffer, components.hash_start);
14895
0
}
14896
14897
[[nodiscard]] std::string_view url_aggregator::get_host() const noexcept
14898
24
    ada_lifetime_bound {
14899
24
  ada_log("url_aggregator::get_host");
14900
  // Technically, we should check if there is a hostname, but
14901
  // the code below works even if there isn't.
14902
  // if(!has_hostname()) { return ""; }
14903
24
  size_t start = components.host_start;
14904
24
  if (components.host_end > components.host_start &&
14905
18
      buffer[components.host_start] == '@') {
14906
0
    start++;
14907
0
  }
14908
  // if we have an empty host, then the space between components.host_end and
14909
  // components.pathname_start may be occupied by /.
14910
24
  if (start == components.host_end) {
14911
6
    return {};
14912
6
  }
14913
18
  return helpers::substring(buffer, start, components.pathname_start);
14914
24
}
14915
14916
[[nodiscard]] std::string_view url_aggregator::get_hostname() const noexcept
14917
8.78k
    ada_lifetime_bound {
14918
8.78k
  ada_log("url_aggregator::get_hostname");
14919
  // Technically, we should check if there is a hostname, but
14920
  // the code below works even if there isn't.
14921
  // if(!has_hostname()) { return ""; }
14922
8.78k
  size_t start = components.host_start;
14923
  // So host_start is not where the host begins.
14924
8.78k
  if (components.host_end > components.host_start &&
14925
3.74k
      buffer[components.host_start] == '@') {
14926
228
    start++;
14927
228
  }
14928
8.78k
  return helpers::substring(buffer, start, components.host_end);
14929
8.78k
}
14930
14931
[[nodiscard]] std::string_view url_aggregator::get_search() const noexcept
14932
402
    ada_lifetime_bound {
14933
402
  ada_log("url_aggregator::get_search");
14934
  // If this's URL's query is either null or the empty string, then return the
14935
  // empty string. Return U+003F (?), followed by this's URL's query.
14936
402
  if (components.search_start == url_components::omitted) {
14937
402
    return "";
14938
402
  }
14939
0
  auto ending_index = uint32_t(buffer.size());
14940
0
  if (components.hash_start != url_components::omitted) {
14941
0
    ending_index = components.hash_start;
14942
0
  }
14943
0
  if (ending_index - components.search_start <= 1) {
14944
0
    return "";
14945
0
  }
14946
0
  return helpers::substring(buffer, components.search_start, ending_index);
14947
0
}
14948
14949
[[nodiscard]] std::string_view url_aggregator::get_protocol() const noexcept
14950
389
    ada_lifetime_bound {
14951
389
  ada_log("url_aggregator::get_protocol");
14952
389
  return helpers::substring(buffer, 0, components.protocol_end);
14953
389
}
14954
14955
0
[[nodiscard]] std::string ada::url_aggregator::to_string() const {
14956
0
  ada_log("url_aggregator::to_string buffer:", buffer, " [", buffer.size(),
14957
0
          " bytes]");
14958
0
  if (!is_valid) {
14959
0
    return "null";
14960
0
  }
14961
14962
0
  std::string answer;
14963
0
  auto back = std::back_insert_iterator(answer);
14964
0
  answer.append("{\n");
14965
14966
0
  answer.append("\t\"buffer\":\"");
14967
0
  helpers::encode_json(buffer, back);
14968
0
  answer.append("\",\n");
14969
14970
0
  answer.append("\t\"protocol\":\"");
14971
0
  helpers::encode_json(get_protocol(), back);
14972
0
  answer.append("\",\n");
14973
14974
0
  if (has_credentials()) {
14975
0
    answer.append("\t\"username\":\"");
14976
0
    helpers::encode_json(get_username(), back);
14977
0
    answer.append("\",\n");
14978
0
    answer.append("\t\"password\":\"");
14979
0
    helpers::encode_json(get_password(), back);
14980
0
    answer.append("\",\n");
14981
0
  }
14982
14983
0
  answer.append("\t\"host\":\"");
14984
0
  helpers::encode_json(get_host(), back);
14985
0
  answer.append("\",\n");
14986
14987
0
  answer.append("\t\"path\":\"");
14988
0
  helpers::encode_json(get_pathname(), back);
14989
0
  answer.append("\",\n");
14990
0
  answer.append("\t\"opaque path\":");
14991
0
  answer.append((has_opaque_path ? "true" : "false"));
14992
0
  answer.append(",\n");
14993
14994
0
  if (components.search_start != url_components::omitted) {
14995
0
    answer.append("\t\"query\":\"");
14996
0
    helpers::encode_json(get_search(), back);
14997
0
    answer.append("\",\n");
14998
0
  }
14999
0
  if (components.hash_start != url_components::omitted) {
15000
0
    answer.append("\t\"fragment\":\"");
15001
0
    helpers::encode_json(get_hash(), back);
15002
0
    answer.append("\",\n");
15003
0
  }
15004
15005
0
  auto convert_offset_to_string = [](uint32_t offset) -> std::string {
15006
0
    if (offset == url_components::omitted) {
15007
0
      return "null";
15008
0
    } else {
15009
0
      return std::to_string(offset);
15010
0
    }
15011
0
  };
15012
15013
0
  answer.append("\t\"protocol_end\":");
15014
0
  answer.append(convert_offset_to_string(components.protocol_end));
15015
0
  answer.append(",\n");
15016
15017
0
  answer.append("\t\"username_end\":");
15018
0
  answer.append(convert_offset_to_string(components.username_end));
15019
0
  answer.append(",\n");
15020
15021
0
  answer.append("\t\"host_start\":");
15022
0
  answer.append(convert_offset_to_string(components.host_start));
15023
0
  answer.append(",\n");
15024
15025
0
  answer.append("\t\"host_end\":");
15026
0
  answer.append(convert_offset_to_string(components.host_end));
15027
0
  answer.append(",\n");
15028
15029
0
  answer.append("\t\"port\":");
15030
0
  answer.append(convert_offset_to_string(components.port));
15031
0
  answer.append(",\n");
15032
15033
0
  answer.append("\t\"pathname_start\":");
15034
0
  answer.append(convert_offset_to_string(components.pathname_start));
15035
0
  answer.append(",\n");
15036
15037
0
  answer.append("\t\"search_start\":");
15038
0
  answer.append(convert_offset_to_string(components.search_start));
15039
0
  answer.append(",\n");
15040
15041
0
  answer.append("\t\"hash_start\":");
15042
0
  answer.append(convert_offset_to_string(components.hash_start));
15043
0
  answer.append("\n}");
15044
15045
0
  return answer;
15046
0
}
15047
15048
0
[[nodiscard]] bool url_aggregator::has_valid_domain() const noexcept {
15049
0
  if (components.host_start == components.host_end) {
15050
0
    return false;
15051
0
  }
15052
0
  return checkers::verify_dns_length(get_hostname());
15053
0
}
15054
15055
1.51k
bool url_aggregator::parse_ipv4(std::string_view input, bool in_place) {
15056
1.51k
  ada_log("parse_ipv4 ", input, " [", input.size(),
15057
1.51k
          " bytes], overlaps with buffer: ",
15058
1.51k
          helpers::overlaps(input, buffer) ? "yes" : "no");
15059
1.51k
  ADA_ASSERT_TRUE(validate());
15060
1.51k
  const bool trailing_dot = (input.back() == '.');
15061
1.51k
  if (trailing_dot) {
15062
38
    input.remove_suffix(1);
15063
38
  }
15064
1.51k
  size_t digit_count{0};
15065
1.51k
  int pure_decimal_count = 0;  // entries that are decimal
15066
1.51k
  uint64_t ipv4{0};
15067
  // we could unroll for better performance?
15068
1.93k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
15069
1.91k
    uint32_t
15070
1.91k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
15071
1.91k
    bool is_hex = checkers::has_hex_prefix(input);
15072
1.91k
    if (is_hex && ((input.length() == 2) ||
15073
602
                   ((input.length() > 2) && (input[2] == '.')))) {
15074
      // special case
15075
58
      segment_result = 0;
15076
58
      input.remove_prefix(2);
15077
1.85k
    } else {
15078
1.85k
      std::from_chars_result r{};
15079
1.85k
      if (is_hex) {
15080
582
        ada_log("parse_ipv4 trying to parse hex number");
15081
582
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
15082
582
                            segment_result, 16);
15083
1.27k
      } else if ((input.length() >= 2) && input[0] == '0' &&
15084
438
                 checkers::is_digit(input[1])) {
15085
351
        ada_log("parse_ipv4 trying to parse octal number");
15086
351
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
15087
351
                            segment_result, 8);
15088
922
      } else {
15089
922
        ada_log("parse_ipv4 trying to parse decimal number");
15090
922
        pure_decimal_count++;
15091
922
        r = std::from_chars(input.data(), input.data() + input.size(),
15092
922
                            segment_result, 10);
15093
922
      }
15094
1.85k
      if (r.ec != std::errc()) {
15095
346
        ada_log("parse_ipv4 parsing failed");
15096
346
        return is_valid = false;
15097
346
      }
15098
1.50k
      ada_log("parse_ipv4 parsed ", segment_result);
15099
1.50k
      input.remove_prefix(r.ptr - input.data());
15100
1.50k
    }
15101
1.56k
    if (input.empty()) {
15102
      // We have the last value.
15103
      // At this stage, ipv4 contains digit_count*8 bits.
15104
      // So we have 32-digit_count*8 bits left.
15105
1.01k
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
15106
34
        return is_valid = false;
15107
34
      }
15108
977
      ipv4 <<= (32 - digit_count * 8);
15109
977
      ipv4 |= segment_result;
15110
977
      goto final;
15111
1.01k
    } else {
15112
      // There is more, so that the value must no be larger than 255
15113
      // and we must have a '.'.
15114
556
      if ((segment_result > 255) || (input[0] != '.')) {
15115
134
        return is_valid = false;
15116
134
      }
15117
422
      ipv4 <<= 8;
15118
422
      ipv4 |= segment_result;
15119
422
      input.remove_prefix(1);  // remove '.'
15120
422
    }
15121
1.56k
  }
15122
22
  if ((digit_count != 4) || (!input.empty())) {
15123
22
    ada_log("parse_ipv4 found invalid (more than 4 numbers or empty) ");
15124
22
    return is_valid = false;
15125
22
  }
15126
977
final:
15127
977
  ada_log("url_aggregator::parse_ipv4 completed ", get_href(),
15128
977
          " host: ", get_host());
15129
15130
  // We could also check r.ptr to see where the parsing ended.
15131
977
  if (in_place && pure_decimal_count == 4 && !trailing_dot) {
15132
0
    ada_log(
15133
0
        "url_aggregator::parse_ipv4 completed and was already correct in the "
15134
0
        "buffer");
15135
    // The original input was already all decimal and we validated it. So we
15136
    // don't need to do anything.
15137
977
  } else {
15138
977
    ada_log("url_aggregator::parse_ipv4 completed and we need to update it");
15139
    // Optimization opportunity: Get rid of unnecessary string return in ipv4
15140
    // serializer.
15141
    // TODO: This is likely a bug because it goes back update_base_hostname, not
15142
    // what we want to do.
15143
977
    update_base_hostname(
15144
977
        ada::serializers::ipv4(ipv4));  // We have to reserialize the address.
15145
977
  }
15146
977
  host_type = IPV4;
15147
977
  ADA_ASSERT_TRUE(validate());
15148
977
  return true;
15149
22
}
15150
15151
431
bool url_aggregator::parse_ipv6(std::string_view input) {
15152
  // TODO: Implement in_place optimization: we know that input points
15153
  // in the buffer, so we can just check whether the buffer is already
15154
  // well formatted.
15155
  // TODO: Find a way to merge parse_ipv6 with url.cpp implementation.
15156
431
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
15157
431
  ADA_ASSERT_TRUE(validate());
15158
431
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15159
431
  if (input.empty()) {
15160
29
    return is_valid = false;
15161
29
  }
15162
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
15163
402
  std::array<uint16_t, 8> address{};
15164
15165
  // Let pieceIndex be 0.
15166
402
  int piece_index = 0;
15167
15168
  // Let compress be null.
15169
402
  std::optional<int> compress{};
15170
15171
  // Let pointer be a pointer for input.
15172
402
  std::string_view::iterator pointer = input.begin();
15173
15174
  // If c is U+003A (:), then:
15175
402
  if (input[0] == ':') {
15176
    // If remaining does not start with U+003A (:), validation error, return
15177
    // failure.
15178
87
    if (input.size() == 1 || input[1] != ':') {
15179
14
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
15180
14
      return is_valid = false;
15181
14
    }
15182
15183
    // Increase pointer by 2.
15184
73
    pointer += 2;
15185
15186
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
15187
73
    compress = ++piece_index;
15188
73
  }
15189
15190
  // While c is not the EOF code point:
15191
1.14k
  while (pointer != input.end()) {
15192
    // If pieceIndex is 8, validation error, return failure.
15193
955
    if (piece_index == 8) {
15194
5
      ada_log("parse_ipv6 piece_index == 8");
15195
5
      return is_valid = false;
15196
5
    }
15197
15198
    // If c is U+003A (:), then:
15199
950
    if (*pointer == ':') {
15200
      // If compress is non-null, validation error, return failure.
15201
78
      if (compress.has_value()) {
15202
3
        ada_log("parse_ipv6 compress is non-null");
15203
3
        return is_valid = false;
15204
3
      }
15205
15206
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
15207
      // then continue.
15208
75
      pointer++;
15209
75
      compress = ++piece_index;
15210
75
      continue;
15211
78
    }
15212
15213
    // Let value and length be 0.
15214
872
    uint16_t value = 0, length = 0;
15215
15216
    // While length is less than 4 and c is an ASCII hex digit,
15217
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
15218
    // increase pointer and length by 1.
15219
2.15k
    while (length < 4 && pointer != input.end() &&
15220
1.94k
           unicode::is_ascii_hex_digit(*pointer)) {
15221
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
15222
1.28k
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
15223
1.28k
      pointer++;
15224
1.28k
      length++;
15225
1.28k
    }
15226
15227
    // If c is U+002E (.), then:
15228
872
    if (pointer != input.end() && *pointer == '.') {
15229
      // If length is 0, validation error, return failure.
15230
91
      if (length == 0) {
15231
3
        ada_log("parse_ipv6 length is 0");
15232
3
        return is_valid = false;
15233
3
      }
15234
15235
      // Decrease pointer by length.
15236
88
      pointer -= length;
15237
15238
      // If pieceIndex is greater than 6, validation error, return failure.
15239
88
      if (piece_index > 6) {
15240
3
        ada_log("parse_ipv6 piece_index > 6");
15241
3
        return is_valid = false;
15242
3
      }
15243
15244
      // Let numbersSeen be 0.
15245
85
      int numbers_seen = 0;
15246
15247
      // While c is not the EOF code point:
15248
252
      while (pointer != input.end()) {
15249
        // Let ipv4Piece be null.
15250
224
        std::optional<uint16_t> ipv4_piece{};
15251
15252
        // If numbersSeen is greater than 0, then:
15253
224
        if (numbers_seen > 0) {
15254
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
15255
          // pointer by 1.
15256
139
          if (*pointer == '.' && numbers_seen < 4) {
15257
124
            pointer++;
15258
124
          } else {
15259
            // Otherwise, validation error, return failure.
15260
15
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
15261
15
            return is_valid = false;
15262
15
          }
15263
139
        }
15264
15265
        // If c is not an ASCII digit, validation error, return failure.
15266
209
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
15267
22
          ada_log(
15268
22
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
15269
22
              "failure");
15270
22
          return is_valid = false;
15271
22
        }
15272
15273
        // While c is an ASCII digit:
15274
470
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
15275
          // Let number be c interpreted as decimal number.
15276
303
          int number = *pointer - '0';
15277
15278
          // If ipv4Piece is null, then set ipv4Piece to number.
15279
303
          if (!ipv4_piece.has_value()) {
15280
187
            ipv4_piece = number;
15281
187
          }
15282
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
15283
116
          else if (ipv4_piece == 0) {
15284
5
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
15285
5
            return is_valid = false;
15286
5
          }
15287
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
15288
111
          else {
15289
111
            ipv4_piece = *ipv4_piece * 10 + number;
15290
111
          }
15291
15292
          // If ipv4Piece is greater than 255, validation error, return failure.
15293
298
          if (ipv4_piece > 255) {
15294
15
            ada_log("parse_ipv6 ipv4_piece > 255");
15295
15
            return is_valid = false;
15296
15
          }
15297
15298
          // Increase pointer by 1.
15299
283
          pointer++;
15300
283
        }
15301
15302
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
15303
        // ipv4Piece.
15304
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
15305
167
        address[piece_index] =
15306
167
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
15307
15308
        // Increase numbersSeen by 1.
15309
167
        numbers_seen++;
15310
15311
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
15312
167
        if (numbers_seen == 2 || numbers_seen == 4) {
15313
67
          piece_index++;
15314
67
        }
15315
167
      }
15316
15317
      // If numbersSeen is not 4, validation error, return failure.
15318
28
      if (numbers_seen != 4) {
15319
14
        return is_valid = false;
15320
14
      }
15321
15322
      // Break.
15323
14
      break;
15324
28
    }
15325
    // Otherwise, if c is U+003A (:):
15326
781
    else if ((pointer != input.end()) && (*pointer == ':')) {
15327
      // Increase pointer by 1.
15328
534
      pointer++;
15329
15330
      // If c is the EOF code point, validation error, return failure.
15331
534
      if (pointer == input.end()) {
15332
5
        ada_log(
15333
5
            "parse_ipv6 If c is the EOF code point, validation error, return "
15334
5
            "failure");
15335
5
        return is_valid = false;
15336
5
      }
15337
534
    }
15338
    // Otherwise, if c is not the EOF code point, validation error, return
15339
    // failure.
15340
247
    else if (pointer != input.end()) {
15341
93
      ada_log(
15342
93
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
15343
93
          "error, return failure");
15344
93
      return is_valid = false;
15345
93
    }
15346
15347
    // Set address[pieceIndex] to value.
15348
683
    address[piece_index] = value;
15349
15350
    // Increase pieceIndex by 1.
15351
683
    piece_index++;
15352
683
  }
15353
15354
  // If compress is non-null, then:
15355
205
  if (compress.has_value()) {
15356
    // Let swaps be pieceIndex - compress.
15357
131
    int swaps = piece_index - *compress;
15358
15359
    // Set pieceIndex to 7.
15360
131
    piece_index = 7;
15361
15362
    // While pieceIndex is not 0 and swaps is greater than 0,
15363
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
15364
    // decrease both pieceIndex and swaps by 1.
15365
367
    while (piece_index != 0 && swaps > 0) {
15366
236
      std::swap(address[piece_index], address[*compress + swaps - 1]);
15367
236
      piece_index--;
15368
236
      swaps--;
15369
236
    }
15370
131
  }
15371
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
15372
  // return failure.
15373
74
  else if (piece_index != 8) {
15374
58
    ada_log(
15375
58
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
15376
58
        "error, return failure");
15377
58
    return is_valid = false;
15378
58
  }
15379
  // TODO: Optimization opportunity: Get rid of unnecessary string creation.
15380
  // TODO: This is likely a bug because it goes back update_base_hostname, not
15381
  // what we want to do.
15382
147
  update_base_hostname(ada::serializers::ipv6(address));
15383
147
  ada_log("parse_ipv6 ", get_hostname());
15384
147
  ADA_ASSERT_TRUE(validate());
15385
147
  host_type = IPV6;
15386
147
  return true;
15387
205
}
15388
15389
284
bool url_aggregator::parse_opaque_host(std::string_view input) {
15390
284
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
15391
284
  ADA_ASSERT_TRUE(validate());
15392
284
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15393
284
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
15394
28
    return is_valid = false;
15395
28
  }
15396
15397
  // Return the result of running UTF-8 percent-encode on input using the C0
15398
  // control percent-encode set.
15399
256
  size_t idx = ada::unicode::percent_encode_index(
15400
256
      input, character_sets::C0_CONTROL_PERCENT_ENCODE);
15401
256
  if (idx == input.size()) {
15402
85
    update_base_hostname(input);
15403
171
  } else {
15404
    // We only create a temporary string if we need to.
15405
171
    update_base_hostname(ada::unicode::percent_encode(
15406
171
        input, character_sets::C0_CONTROL_PERCENT_ENCODE, idx));
15407
171
  }
15408
256
  ADA_ASSERT_TRUE(validate());
15409
256
  return true;
15410
284
}
15411
15412
0
[[nodiscard]] std::string url_aggregator::to_diagram() const {
15413
0
  if (!is_valid) {
15414
0
    return "invalid";
15415
0
  }
15416
0
  std::string answer;
15417
0
  answer.append(buffer);
15418
0
  answer.append(" [");
15419
0
  answer.append(std::to_string(buffer.size()));
15420
0
  answer.append(" bytes]");
15421
0
  answer.append("\n");
15422
  // first line
15423
0
  std::string line1;
15424
0
  line1.resize(buffer.size(), ' ');
15425
0
  if (components.hash_start != url_components::omitted) {
15426
0
    line1[components.hash_start] = '|';
15427
0
  }
15428
0
  if (components.search_start != url_components::omitted) {
15429
0
    line1[components.search_start] = '|';
15430
0
  }
15431
0
  if (components.pathname_start != buffer.size()) {
15432
0
    line1[components.pathname_start] = '|';
15433
0
  }
15434
0
  if (components.host_end != buffer.size()) {
15435
0
    line1[components.host_end] = '|';
15436
0
  }
15437
0
  if (components.host_start != buffer.size()) {
15438
0
    line1[components.host_start] = '|';
15439
0
  }
15440
0
  if (components.username_end != buffer.size()) {
15441
0
    line1[components.username_end] = '|';
15442
0
  }
15443
0
  if (components.protocol_end != buffer.size()) {
15444
0
    line1[components.protocol_end] = '|';
15445
0
  }
15446
0
  answer.append(line1);
15447
0
  answer.append("\n");
15448
15449
0
  std::string line2 = line1;
15450
0
  if (components.hash_start != url_components::omitted) {
15451
0
    line2[components.hash_start] = '`';
15452
0
    line1[components.hash_start] = ' ';
15453
15454
0
    for (size_t i = components.hash_start + 1; i < line2.size(); i++) {
15455
0
      line2[i] = '-';
15456
0
    }
15457
0
    line2.append(" hash_start");
15458
0
    answer.append(line2);
15459
0
    answer.append("\n");
15460
0
  }
15461
15462
0
  std::string line3 = line1;
15463
0
  if (components.search_start != url_components::omitted) {
15464
0
    line3[components.search_start] = '`';
15465
0
    line1[components.search_start] = ' ';
15466
15467
0
    for (size_t i = components.search_start + 1; i < line3.size(); i++) {
15468
0
      line3[i] = '-';
15469
0
    }
15470
0
    line3.append(" search_start ");
15471
0
    line3.append(std::to_string(components.search_start));
15472
0
    answer.append(line3);
15473
0
    answer.append("\n");
15474
0
  }
15475
15476
0
  std::string line4 = line1;
15477
0
  if (components.pathname_start != buffer.size()) {
15478
0
    line4[components.pathname_start] = '`';
15479
0
    line1[components.pathname_start] = ' ';
15480
0
    for (size_t i = components.pathname_start + 1; i < line4.size(); i++) {
15481
0
      line4[i] = '-';
15482
0
    }
15483
0
    line4.append(" pathname_start ");
15484
0
    line4.append(std::to_string(components.pathname_start));
15485
0
    answer.append(line4);
15486
0
    answer.append("\n");
15487
0
  }
15488
15489
0
  std::string line5 = line1;
15490
0
  if (components.host_end != buffer.size()) {
15491
0
    line5[components.host_end] = '`';
15492
0
    line1[components.host_end] = ' ';
15493
15494
0
    for (size_t i = components.host_end + 1; i < line5.size(); i++) {
15495
0
      line5[i] = '-';
15496
0
    }
15497
0
    line5.append(" host_end ");
15498
0
    line5.append(std::to_string(components.host_end));
15499
0
    answer.append(line5);
15500
0
    answer.append("\n");
15501
0
  }
15502
15503
0
  std::string line6 = line1;
15504
0
  if (components.host_start != buffer.size()) {
15505
0
    line6[components.host_start] = '`';
15506
0
    line1[components.host_start] = ' ';
15507
15508
0
    for (size_t i = components.host_start + 1; i < line6.size(); i++) {
15509
0
      line6[i] = '-';
15510
0
    }
15511
0
    line6.append(" host_start ");
15512
0
    line6.append(std::to_string(components.host_start));
15513
0
    answer.append(line6);
15514
0
    answer.append("\n");
15515
0
  }
15516
15517
0
  std::string line7 = line1;
15518
0
  if (components.username_end != buffer.size()) {
15519
0
    line7[components.username_end] = '`';
15520
0
    line1[components.username_end] = ' ';
15521
15522
0
    for (size_t i = components.username_end + 1; i < line7.size(); i++) {
15523
0
      line7[i] = '-';
15524
0
    }
15525
0
    line7.append(" username_end ");
15526
0
    line7.append(std::to_string(components.username_end));
15527
0
    answer.append(line7);
15528
0
    answer.append("\n");
15529
0
  }
15530
15531
0
  std::string line8 = line1;
15532
0
  if (components.protocol_end != buffer.size()) {
15533
0
    line8[components.protocol_end] = '`';
15534
0
    line1[components.protocol_end] = ' ';
15535
15536
0
    for (size_t i = components.protocol_end + 1; i < line8.size(); i++) {
15537
0
      line8[i] = '-';
15538
0
    }
15539
0
    line8.append(" protocol_end ");
15540
0
    line8.append(std::to_string(components.protocol_end));
15541
0
    answer.append(line8);
15542
0
    answer.append("\n");
15543
0
  }
15544
15545
0
  if (components.hash_start == url_components::omitted) {
15546
0
    answer.append("note: hash omitted\n");
15547
0
  }
15548
0
  if (components.search_start == url_components::omitted) {
15549
0
    answer.append("note: search omitted\n");
15550
0
  }
15551
0
  if (components.protocol_end > buffer.size()) {
15552
0
    answer.append("warning: protocol_end overflows\n");
15553
0
  }
15554
0
  if (components.username_end > buffer.size()) {
15555
0
    answer.append("warning: username_end overflows\n");
15556
0
  }
15557
0
  if (components.host_start > buffer.size()) {
15558
0
    answer.append("warning: host_start overflows\n");
15559
0
  }
15560
0
  if (components.host_end > buffer.size()) {
15561
0
    answer.append("warning: host_end overflows\n");
15562
0
  }
15563
0
  if (components.pathname_start > buffer.size()) {
15564
0
    answer.append("warning: pathname_start overflows\n");
15565
0
  }
15566
0
  return answer;
15567
0
}
15568
15569
0
void url_aggregator::delete_dash_dot() {
15570
0
  ada_log("url_aggregator::delete_dash_dot");
15571
0
  ADA_ASSERT_TRUE(validate());
15572
0
  ADA_ASSERT_TRUE(has_dash_dot());
15573
0
  buffer.erase(components.host_end, 2);
15574
0
  components.pathname_start -= 2;
15575
0
  if (components.search_start != url_components::omitted) {
15576
0
    components.search_start -= 2;
15577
0
  }
15578
0
  if (components.hash_start != url_components::omitted) {
15579
0
    components.hash_start -= 2;
15580
0
  }
15581
0
  ADA_ASSERT_TRUE(validate());
15582
0
  ADA_ASSERT_TRUE(!has_dash_dot());
15583
0
}
15584
15585
0
inline void url_aggregator::consume_prepared_path(std::string_view input) {
15586
0
  ada_log("url_aggregator::consume_prepared_path ", input);
15587
  /***
15588
   * This is largely duplicated code from helpers::parse_prepared_path, which is
15589
   * unfortunate. This particular function is nearly identical, except that it
15590
   * is a method on url_aggregator. The idea is that the trivial path (which is
15591
   * very common) merely appends to the buffer. This is the same trivial path as
15592
   * with helpers::parse_prepared_path, except that we have the additional check
15593
   * for is_at_path(). Otherwise, we grab a copy of the current path and we
15594
   * modify it, and then insert it back into the buffer.
15595
   */
15596
0
  uint8_t accumulator = checkers::path_signature(input);
15597
  // Let us first detect a trivial case.
15598
  // If it is special, we check that we have no dot, no %,  no \ and no
15599
  // character needing percent encoding. Otherwise, we check that we have no %,
15600
  // no dot, and no character needing percent encoding.
15601
0
  constexpr uint8_t need_encoding = 1;
15602
0
  constexpr uint8_t backslash_char = 2;
15603
0
  constexpr uint8_t dot_char = 4;
15604
0
  constexpr uint8_t percent_char = 8;
15605
0
  bool special = type != ada::scheme::NOT_SPECIAL;
15606
0
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
15607
0
                                      checkers::is_windows_drive_letter(input));
15608
0
  bool trivial_path =
15609
0
      (special ? (accumulator == 0)
15610
0
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
15611
0
                  0)) &&
15612
0
      (!may_need_slow_file_handling);
15613
0
  if (accumulator == dot_char && !may_need_slow_file_handling) {
15614
    // '4' means that we have at least one dot, but nothing that requires
15615
    // percent encoding or decoding. The only part that is not trivial is
15616
    // that we may have single dots and double dots path segments.
15617
    // If we have such segments, then we either have a path that begins
15618
    // with '.' (easy to check), or we have the sequence './'.
15619
    // Note: input cannot be empty, it must at least contain one character ('.')
15620
    // Note: we know that '\' is not present.
15621
0
    if (input[0] != '.') {
15622
0
      size_t slashdot = 0;
15623
0
      bool dot_is_file = true;
15624
0
      for (;;) {
15625
0
        slashdot = input.find("/.", slashdot);
15626
0
        if (slashdot == std::string_view::npos) {  // common case
15627
0
          break;
15628
0
        } else {  // uncommon
15629
          // only three cases matter: /./, /.. or a final /
15630
0
          slashdot += 2;
15631
0
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
15632
0
                           input[slashdot] == '/');
15633
0
        }
15634
0
      }
15635
0
      trivial_path = dot_is_file;
15636
0
    }
15637
0
  }
15638
0
  if (trivial_path && is_at_path()) {
15639
0
    ada_log("parse_path trivial");
15640
0
    buffer += '/';
15641
0
    buffer += input;
15642
0
    return;
15643
0
  }
15644
0
  std::string path = std::string(get_pathname());
15645
  // We are going to need to look a bit at the path, but let us see if we can
15646
  // ignore percent encoding *and* backslashes *and* percent characters.
15647
  // Except for the trivial case, this is likely to capture 99% of paths out
15648
  // there.
15649
0
  bool fast_path =
15650
0
      (special &&
15651
0
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
15652
0
      (type != ada::scheme::type::FILE);
15653
0
  if (fast_path) {
15654
0
    ada_log("parse_prepared_path fast");
15655
    // Here we don't need to worry about \ or percent encoding.
15656
    // We also do not have a file protocol. We might have dots, however,
15657
    // but dots must as appear as '.', and they cannot be encoded because
15658
    // the symbol '%' is not present.
15659
0
    size_t previous_location = 0;  // We start at 0.
15660
0
    do {
15661
0
      size_t new_location = input.find('/', previous_location);
15662
      // std::string_view path_view = input;
15663
      //  We process the last segment separately:
15664
0
      if (new_location == std::string_view::npos) {
15665
0
        std::string_view path_view = input.substr(previous_location);
15666
0
        if (path_view == "..") {  // The path ends with ..
15667
          // e.g., if you receive ".." with an empty path, you go to "/".
15668
0
          if (path.empty()) {
15669
0
            path = '/';
15670
0
            update_base_pathname(path);
15671
0
            return;
15672
0
          }
15673
          // Fast case where we have nothing to do:
15674
0
          if (path.back() == '/') {
15675
0
            update_base_pathname(path);
15676
0
            return;
15677
0
          }
15678
          // If you have the path "/joe/myfriend",
15679
          // then you delete 'myfriend'.
15680
0
          path.resize(path.rfind('/') + 1);
15681
0
          update_base_pathname(path);
15682
0
          return;
15683
0
        }
15684
0
        path += '/';
15685
0
        if (path_view != ".") {
15686
0
          path.append(path_view);
15687
0
        }
15688
0
        update_base_pathname(path);
15689
0
        return;
15690
0
      } else {
15691
        // This is a non-final segment.
15692
0
        std::string_view path_view =
15693
0
            input.substr(previous_location, new_location - previous_location);
15694
0
        previous_location = new_location + 1;
15695
0
        if (path_view == "..") {
15696
0
          size_t last_delimiter = path.rfind('/');
15697
0
          if (last_delimiter != std::string::npos) {
15698
0
            path.erase(last_delimiter);
15699
0
          }
15700
0
        } else if (path_view != ".") {
15701
0
          path += '/';
15702
0
          path.append(path_view);
15703
0
        }
15704
0
      }
15705
0
    } while (true);
15706
0
  } else {
15707
0
    ada_log("parse_path slow");
15708
    // we have reached the general case
15709
0
    bool needs_percent_encoding = (accumulator & 1);
15710
0
    std::string path_buffer_tmp;
15711
0
    do {
15712
0
      size_t location = (special && (accumulator & 2))
15713
0
                            ? input.find_first_of("/\\")
15714
0
                            : input.find('/');
15715
0
      std::string_view path_view = input;
15716
0
      if (location != std::string_view::npos) {
15717
0
        path_view.remove_suffix(path_view.size() - location);
15718
0
        input.remove_prefix(location + 1);
15719
0
      }
15720
      // path_buffer is either path_view or it might point at a percent encoded
15721
      // temporary string.
15722
0
      std::string_view path_buffer =
15723
0
          (needs_percent_encoding &&
15724
0
           ada::unicode::percent_encode<false>(
15725
0
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
15726
0
              ? path_buffer_tmp
15727
0
              : path_view;
15728
0
      if (unicode::is_double_dot_path_segment(path_buffer)) {
15729
0
        helpers::shorten_path(path, type);
15730
0
        if (location == std::string_view::npos) {
15731
0
          path += '/';
15732
0
        }
15733
0
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
15734
0
                 (location == std::string_view::npos)) {
15735
0
        path += '/';
15736
0
      }
15737
      // Otherwise, if path_buffer is not a single-dot path segment, then:
15738
0
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
15739
        // If url's scheme is "file", url's path is empty, and path_buffer is a
15740
        // Windows drive letter, then replace the second code point in
15741
        // path_buffer with U+003A (:).
15742
0
        if (type == ada::scheme::type::FILE && path.empty() &&
15743
0
            checkers::is_windows_drive_letter(path_buffer)) {
15744
0
          path += '/';
15745
0
          path += path_buffer[0];
15746
0
          path += ':';
15747
0
          path_buffer.remove_prefix(2);
15748
0
          path.append(path_buffer);
15749
0
        } else {
15750
          // Append path_buffer to url's path.
15751
0
          path += '/';
15752
0
          path.append(path_buffer);
15753
0
        }
15754
0
      }
15755
0
      if (location == std::string_view::npos) {
15756
0
        update_base_pathname(path);
15757
0
        return;
15758
0
      }
15759
0
    } while (true);
15760
0
  }
15761
0
}
15762
}  // namespace ada
15763
/* end file src/url_aggregator.cpp */
15764
15765
#if ADA_INCLUDE_URL_PATTERN
15766
/* begin file src/url_pattern.cpp */
15767
#if ADA_INCLUDE_URL_PATTERN
15768
15769
15770
#include <algorithm>
15771
#include <optional>
15772
#include <string>
15773
15774
namespace ada {
15775
15776
tl::expected<url_pattern_init, errors> url_pattern_init::process(
15777
    const url_pattern_init& init, url_pattern_init::process_type type,
15778
    std::optional<std::string_view> protocol,
15779
    std::optional<std::string_view> username,
15780
    std::optional<std::string_view> password,
15781
    std::optional<std::string_view> hostname,
15782
    std::optional<std::string_view> port,
15783
    std::optional<std::string_view> pathname,
15784
    std::optional<std::string_view> search,
15785
0
    std::optional<std::string_view> hash) {
15786
  // Let result be the result of creating a new URLPatternInit.
15787
0
  auto result = url_pattern_init{};
15788
15789
  // If protocol is not null, set result["protocol"] to protocol.
15790
0
  if (protocol.has_value()) result.protocol = *protocol;
15791
15792
  // If username is not null, set result["username"] to username.
15793
0
  if (username.has_value()) result.username = *username;
15794
15795
  // If password is not null, set result["password"] to password.
15796
0
  if (password.has_value()) result.password = *password;
15797
15798
  // If hostname is not null, set result["hostname"] to hostname.
15799
0
  if (hostname.has_value()) result.hostname = *hostname;
15800
15801
  // If port is not null, set result["port"] to port.
15802
0
  if (port.has_value()) result.port = *port;
15803
15804
  // If pathname is not null, set result["pathname"] to pathname.
15805
0
  if (pathname.has_value()) result.pathname = *pathname;
15806
15807
  // If search is not null, set result["search"] to search.
15808
0
  if (search.has_value()) result.search = *search;
15809
15810
  // If hash is not null, set result["hash"] to hash.
15811
0
  if (hash.has_value()) result.hash = *hash;
15812
15813
  // Let baseURL be null.
15814
0
  std::optional<url_aggregator> base_url{};
15815
15816
  // If init["baseURL"] exists:
15817
0
  if (init.base_url.has_value()) {
15818
    // Set baseURL to the result of parsing init["baseURL"].
15819
0
    auto parsing_result = ada::parse<url_aggregator>(*init.base_url);
15820
    // If baseURL is failure, then throw a TypeError.
15821
0
    if (!parsing_result) {
15822
0
      return tl::unexpected(errors::type_error);
15823
0
    }
15824
0
    base_url = std::move(*parsing_result);
15825
15826
    // If init["protocol"] does not exist, then set result["protocol"] to the
15827
    // result of processing a base URL string given baseURL's scheme and type.
15828
0
    if (!init.protocol.has_value()) {
15829
0
      ADA_ASSERT_TRUE(base_url.has_value());
15830
0
      std::string_view base_url_protocol = base_url->get_protocol();
15831
0
      if (base_url_protocol.ends_with(":")) base_url_protocol.remove_suffix(1);
15832
0
      result.protocol =
15833
0
          url_pattern_helpers::process_base_url_string(base_url_protocol, type);
15834
0
    }
15835
15836
    // If type is not "pattern" and init contains none of "protocol",
15837
    // "hostname", "port" and "username", then set result["username"] to the
15838
    // result of processing a base URL string given baseURL's username and type.
15839
0
    if (type != process_type::pattern && !init.protocol && !init.hostname &&
15840
0
        !init.port && !init.username) {
15841
0
      result.username = url_pattern_helpers::process_base_url_string(
15842
0
          base_url->get_username(), type);
15843
0
    }
15844
15845
    // TODO: Optimization opportunity: Merge this with the previous check.
15846
    // If type is not "pattern" and init contains none of "protocol",
15847
    // "hostname", "port", "username" and "password", then set
15848
    // result["password"] to the result of processing a base URL string given
15849
    // baseURL's password and type.
15850
0
    if (type != process_type::pattern && !init.protocol && !init.hostname &&
15851
0
        !init.port && !init.username && !init.password) {
15852
0
      result.password = url_pattern_helpers::process_base_url_string(
15853
0
          base_url->get_password(), type);
15854
0
    }
15855
15856
    // If init contains neither "protocol" nor "hostname", then:
15857
0
    if (!init.protocol && !init.hostname) {
15858
      // Let baseHost be baseURL's host.
15859
      // If baseHost is null, then set baseHost to the empty string.
15860
0
      auto base_host = base_url->get_hostname();
15861
      // Set result["hostname"] to the result of processing a base URL string
15862
      // given baseHost and type.
15863
0
      result.hostname =
15864
0
          url_pattern_helpers::process_base_url_string(base_host, type);
15865
0
    }
15866
15867
    // If init contains none of "protocol", "hostname", and "port", then:
15868
0
    if (!init.protocol && !init.hostname && !init.port) {
15869
      // If baseURL's port is null, then set result["port"] to the empty string.
15870
      // Otherwise, set result["port"] to baseURL's port, serialized.
15871
0
      result.port = base_url->get_port();
15872
0
    }
15873
15874
    // If init contains none of "protocol", "hostname", "port", and "pathname",
15875
    // then set result["pathname"] to the result of processing a base URL string
15876
    // given the result of URL path serializing baseURL and type.
15877
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname) {
15878
0
      result.pathname = url_pattern_helpers::process_base_url_string(
15879
0
          base_url->get_pathname(), type);
15880
0
    }
15881
15882
    // If init contains none of "protocol", "hostname", "port", "pathname", and
15883
    // "search", then:
15884
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname &&
15885
0
        !init.search) {
15886
      // Let baseQuery be baseURL's query.
15887
      // Set result["search"] to the result of processing a base URL string
15888
      // given baseQuery and type.
15889
0
      result.search = url_pattern_helpers::process_base_url_string(
15890
0
          base_url->get_search(), type);
15891
0
    }
15892
15893
    // If init contains none of "protocol", "hostname", "port", "pathname",
15894
    // "search", and "hash", then:
15895
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname &&
15896
0
        !init.search && !init.hash) {
15897
      // Let baseFragment be baseURL's fragment.
15898
      // Set result["hash"] to the result of processing a base URL string given
15899
      // baseFragment and type.
15900
0
      result.hash = url_pattern_helpers::process_base_url_string(
15901
0
          base_url->get_hash(), type);
15902
0
    }
15903
0
  }
15904
15905
  // If init["protocol"] exists, then set result["protocol"] to the result of
15906
  // process protocol for init given init["protocol"] and type.
15907
0
  if (init.protocol) {
15908
0
    auto process_result = process_protocol(*init.protocol, type);
15909
0
    if (!process_result) {
15910
0
      return tl::unexpected(process_result.error());
15911
0
    }
15912
0
    result.protocol = std::move(*process_result);
15913
0
  }
15914
15915
  // If init["username"] exists, then set result["username"] to the result of
15916
  // process username for init given init["username"] and type.
15917
0
  if (init.username.has_value()) {
15918
0
    auto process_result = process_username(*init.username, type);
15919
0
    if (!process_result) {
15920
0
      return tl::unexpected(process_result.error());
15921
0
    }
15922
0
    result.username = std::move(*process_result);
15923
0
  }
15924
15925
  // If init["password"] exists, then set result["password"] to the result of
15926
  // process password for init given init["password"] and type.
15927
0
  if (init.password.has_value()) {
15928
0
    auto process_result = process_password(*init.password, type);
15929
0
    if (!process_result) {
15930
0
      return tl::unexpected(process_result.error());
15931
0
    }
15932
0
    result.password = std::move(*process_result);
15933
0
  }
15934
15935
  // If init["hostname"] exists, then set result["hostname"] to the result of
15936
  // process hostname for init given init["hostname"] and type.
15937
0
  if (init.hostname.has_value()) {
15938
0
    auto process_result = process_hostname(*init.hostname, type);
15939
0
    if (!process_result) {
15940
0
      return tl::unexpected(process_result.error());
15941
0
    }
15942
0
    result.hostname = std::move(*process_result);
15943
0
  }
15944
15945
  // If init["port"] exists, then set result["port"] to the result of process
15946
  // port for init given init["port"], result["protocol"], and type.
15947
0
  if (init.port) {
15948
0
    auto process_result =
15949
0
        process_port(*init.port, result.protocol.value_or("fake"), type);
15950
0
    if (!process_result) {
15951
0
      return tl::unexpected(process_result.error());
15952
0
    }
15953
0
    result.port = std::move(*process_result);
15954
0
  }
15955
15956
  // If init["pathname"] exists:
15957
0
  if (init.pathname.has_value()) {
15958
    // Set result["pathname"] to init["pathname"].
15959
0
    result.pathname = init.pathname;
15960
15961
    // If the following are all true:
15962
    // - baseURL is not null;
15963
    // - baseURL has an opaque path; and
15964
    // - the result of running is an absolute pathname given result["pathname"]
15965
    // and type is false,
15966
0
    if (base_url && !base_url->has_opaque_path &&
15967
0
        !url_pattern_helpers::is_absolute_pathname(*result.pathname, type)) {
15968
      // Let baseURLPath be the result of running process a base URL string
15969
      // given the result of URL path serializing baseURL and type.
15970
      // TODO: Optimization opportunity: Avoid returning a string if no slash
15971
      // exist.
15972
0
      std::string base_url_path = url_pattern_helpers::process_base_url_string(
15973
0
          base_url->get_pathname(), type);
15974
15975
      // Let slash index be the index of the last U+002F (/) code point found in
15976
      // baseURLPath, interpreted as a sequence of code points, or null if there
15977
      // are no instances of the code point.
15978
0
      auto slash_index = base_url_path.find_last_of('/');
15979
15980
      // If slash index is not null:
15981
0
      if (slash_index != std::string::npos) {
15982
        // Let new pathname be the code point substring from 0 to slash index +
15983
        // 1 within baseURLPath.
15984
0
        base_url_path.resize(slash_index + 1);
15985
        // Append result["pathname"] to the end of new pathname.
15986
0
        ADA_ASSERT_TRUE(result.pathname.has_value());
15987
0
        base_url_path.append(std::move(*result.pathname));
15988
        // Set result["pathname"] to new pathname.
15989
0
        result.pathname = std::move(base_url_path);
15990
0
      }
15991
0
    }
15992
15993
    // Set result["pathname"] to the result of process pathname for init given
15994
    // result["pathname"], result["protocol"], and type.
15995
0
    auto pathname_processing_result =
15996
0
        process_pathname(*result.pathname, result.protocol.value_or(""), type);
15997
0
    if (!pathname_processing_result) {
15998
0
      return tl::unexpected(pathname_processing_result.error());
15999
0
    }
16000
0
    result.pathname = std::move(*pathname_processing_result);
16001
0
  }
16002
16003
  // If init["search"] exists then set result["search"] to the result of process
16004
  // search for init given init["search"] and type.
16005
0
  if (init.search) {
16006
0
    auto process_result = process_search(*init.search, type);
16007
0
    if (!process_result) {
16008
0
      return tl::unexpected(process_result.error());
16009
0
    }
16010
0
    result.search = std::move(*process_result);
16011
0
  }
16012
16013
  // If init["hash"] exists then set result["hash"] to the result of process
16014
  // hash for init given init["hash"] and type.
16015
0
  if (init.hash) {
16016
0
    auto process_result = process_hash(*init.hash, type);
16017
0
    if (!process_result) {
16018
0
      return tl::unexpected(process_result.error());
16019
0
    }
16020
0
    result.hash = std::move(*process_result);
16021
0
  }
16022
  // Return result.
16023
0
  return result;
16024
0
}
16025
16026
tl::expected<std::string, errors> url_pattern_init::process_protocol(
16027
0
    std::string_view value, process_type type) {
16028
0
  ada_log("process_protocol=", value, " [", type, "]");
16029
  // Let strippedValue be the given value with a single trailing U+003A (:)
16030
  // removed, if any.
16031
0
  if (value.ends_with(":")) {
16032
0
    value.remove_suffix(1);
16033
0
  }
16034
  // If type is "pattern" then return strippedValue.
16035
0
  if (type == process_type::pattern) {
16036
0
    return std::string(value);
16037
0
  }
16038
  // Return the result of running canonicalize a protocol given strippedValue.
16039
0
  return url_pattern_helpers::canonicalize_protocol(value);
16040
0
}
16041
16042
tl::expected<std::string, errors> url_pattern_init::process_username(
16043
0
    std::string_view value, process_type type) {
16044
  // If type is "pattern" then return value.
16045
0
  if (type == process_type::pattern) {
16046
0
    return std::string(value);
16047
0
  }
16048
  // Return the result of running canonicalize a username given value.
16049
0
  return url_pattern_helpers::canonicalize_username(value);
16050
0
}
16051
16052
tl::expected<std::string, errors> url_pattern_init::process_password(
16053
0
    std::string_view value, process_type type) {
16054
  // If type is "pattern" then return value.
16055
0
  if (type == process_type::pattern) {
16056
0
    return std::string(value);
16057
0
  }
16058
  // Return the result of running canonicalize a password given value.
16059
0
  return url_pattern_helpers::canonicalize_password(value);
16060
0
}
16061
16062
tl::expected<std::string, errors> url_pattern_init::process_hostname(
16063
0
    std::string_view value, process_type type) {
16064
0
  ada_log("process_hostname value=", value, " type=", type);
16065
  // If type is "pattern" then return value.
16066
0
  if (type == process_type::pattern) {
16067
0
    return std::string(value);
16068
0
  }
16069
  // Return the result of running canonicalize a hostname given value.
16070
0
  return url_pattern_helpers::canonicalize_hostname(value);
16071
0
}
16072
16073
tl::expected<std::string, errors> url_pattern_init::process_port(
16074
0
    std::string_view port, std::string_view protocol, process_type type) {
16075
  // If type is "pattern" then return portValue.
16076
0
  if (type == process_type::pattern) {
16077
0
    return std::string(port);
16078
0
  }
16079
  // Return the result of running canonicalize a port given portValue and
16080
  // protocolValue.
16081
0
  return url_pattern_helpers::canonicalize_port_with_protocol(port, protocol);
16082
0
}
16083
16084
tl::expected<std::string, errors> url_pattern_init::process_pathname(
16085
0
    std::string_view value, std::string_view protocol, process_type type) {
16086
  // If type is "pattern" then return pathnameValue.
16087
0
  if (type == process_type::pattern) {
16088
0
    return std::string(value);
16089
0
  }
16090
16091
  // If protocolValue is a special scheme or the empty string, then return the
16092
  // result of running canonicalize a pathname given pathnameValue.
16093
0
  if (protocol.empty() || scheme::is_special(protocol)) {
16094
0
    return url_pattern_helpers::canonicalize_pathname(value);
16095
0
  }
16096
16097
  // Return the result of running canonicalize an opaque pathname given
16098
  // pathnameValue.
16099
0
  return url_pattern_helpers::canonicalize_opaque_pathname(value);
16100
0
}
16101
16102
tl::expected<std::string, errors> url_pattern_init::process_search(
16103
0
    std::string_view value, process_type type) {
16104
  // Let strippedValue be the given value with a single leading U+003F (?)
16105
  // removed, if any.
16106
0
  if (value.starts_with("?")) {
16107
0
    value.remove_prefix(1);
16108
0
  }
16109
  // We cannot assert that the value is no longer starting with a single
16110
  // question mark because technically it can start. The question is whether or
16111
  // not we should remove the first question mark. Ref:
16112
  // https://github.com/ada-url/ada/pull/992 The spec is not clear on this.
16113
16114
  // If type is "pattern" then return strippedValue.
16115
0
  if (type == process_type::pattern) {
16116
0
    return std::string(value);
16117
0
  }
16118
  // Return the result of running canonicalize a search given strippedValue.
16119
0
  return url_pattern_helpers::canonicalize_search(value);
16120
0
}
16121
16122
tl::expected<std::string, errors> url_pattern_init::process_hash(
16123
0
    std::string_view value, process_type type) {
16124
  // Let strippedValue be the given value with a single leading U+0023 (#)
16125
  // removed, if any.
16126
0
  if (value.starts_with("#")) {
16127
0
    value.remove_prefix(1);
16128
0
  }
16129
0
  ADA_ASSERT_TRUE(!value.starts_with("#"));
16130
  // If type is "pattern" then return strippedValue.
16131
0
  if (type == process_type::pattern) {
16132
0
    return std::string(value);
16133
0
  }
16134
  // Return the result of running canonicalize a hash given strippedValue.
16135
0
  return url_pattern_helpers::canonicalize_hash(value);
16136
0
}
16137
16138
}  // namespace ada
16139
16140
#endif  // ADA_INCLUDE_URL_PATTERN
16141
/* end file src/url_pattern.cpp */
16142
/* begin file src/url_pattern_helpers.cpp */
16143
#if ADA_INCLUDE_URL_PATTERN
16144
16145
#include <algorithm>
16146
#include <array>
16147
#include <charconv>
16148
#include <optional>
16149
#include <ranges>
16150
#include <string>
16151
16152
16153
namespace ada::url_pattern_helpers {
16154
16155
std::tuple<std::string, std::vector<std::string>>
16156
generate_regular_expression_and_name_list(
16157
    const std::vector<url_pattern_part>& part_list,
16158
0
    url_pattern_compile_component_options options) {
16159
  // Let result be "^"
16160
0
  std::string result = "^";
16161
  // Reserve capacity to reduce reallocations
16162
0
  result.reserve(part_list.size() * 16);
16163
16164
  // Let name list be a new list
16165
0
  std::vector<std::string> name_list{};
16166
0
  name_list.reserve(part_list.size());
16167
16168
  // Pre-generate segment wildcard regexp if needed (avoids repeated generation)
16169
0
  std::string segment_wildcard_regexp;
16170
16171
  // For each part of part list:
16172
0
  for (const url_pattern_part& part : part_list) {
16173
    // If part's type is "fixed-text":
16174
0
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
16175
      // If part's modifier is "none"
16176
0
      if (part.modifier == url_pattern_part_modifier::none) {
16177
0
        result.append(escape_regexp_string(part.value));
16178
0
      } else {
16179
        // (?:<fixed text>)<modifier>
16180
0
        result.append("(?:");
16181
0
        result.append(escape_regexp_string(part.value));
16182
0
        result.push_back(')');
16183
0
        result.append(convert_modifier_to_string(part.modifier));
16184
0
      }
16185
0
      continue;
16186
0
    }
16187
16188
    // Assert: part's name is not the empty string
16189
0
    ADA_ASSERT_TRUE(!part.name.empty());
16190
0
    name_list.push_back(part.name);
16191
16192
    // Use string_view to avoid copies where possible
16193
0
    std::string_view regexp_value = part.value;
16194
16195
0
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD) {
16196
      // Lazy generate segment wildcard regexp
16197
0
      if (segment_wildcard_regexp.empty()) {
16198
0
        segment_wildcard_regexp = generate_segment_wildcard_regexp(options);
16199
0
      }
16200
0
      regexp_value = segment_wildcard_regexp;
16201
0
    } else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
16202
0
      regexp_value = ".*";
16203
0
    }
16204
16205
    // If part's prefix is the empty string and part's suffix is the empty
16206
    // string
16207
0
    if (part.prefix.empty() && part.suffix.empty()) {
16208
      // If part's modifier is "none" or "optional"
16209
0
      if (part.modifier == url_pattern_part_modifier::none ||
16210
0
          part.modifier == url_pattern_part_modifier::optional) {
16211
        // (<regexp value>)<modifier>
16212
0
        result.push_back('(');
16213
0
        result.append(regexp_value);
16214
0
        result.push_back(')');
16215
0
        result.append(convert_modifier_to_string(part.modifier));
16216
0
      } else {
16217
        // ((?:<regexp value>)<modifier>)
16218
0
        result.append("((?:");
16219
0
        result.append(regexp_value);
16220
0
        result.push_back(')');
16221
0
        result.append(convert_modifier_to_string(part.modifier));
16222
0
        result.push_back(')');
16223
0
      }
16224
0
      continue;
16225
0
    }
16226
16227
    // If part's modifier is "none" or "optional"
16228
0
    if (part.modifier == url_pattern_part_modifier::none ||
16229
0
        part.modifier == url_pattern_part_modifier::optional) {
16230
      // (?:<prefix>(<regexp value>)<suffix>)<modifier>
16231
0
      result.append("(?:");
16232
0
      result.append(escape_regexp_string(part.prefix));
16233
0
      result.push_back('(');
16234
0
      result.append(regexp_value);
16235
0
      result.push_back(')');
16236
0
      result.append(escape_regexp_string(part.suffix));
16237
0
      result.push_back(')');
16238
0
      result.append(convert_modifier_to_string(part.modifier));
16239
0
      continue;
16240
0
    }
16241
16242
    // Assert: part's modifier is "zero-or-more" or "one-or-more"
16243
0
    ADA_ASSERT_TRUE(part.modifier == url_pattern_part_modifier::zero_or_more ||
16244
0
                    part.modifier == url_pattern_part_modifier::one_or_more);
16245
16246
    // Assert: part's prefix is not the empty string or part's suffix is not the
16247
    // empty string
16248
0
    ADA_ASSERT_TRUE(!part.prefix.empty() || !part.suffix.empty());
16249
16250
    // (?:<prefix>((?:<regexp value>)(?:<suffix><prefix>(?:<regexp
16251
    // value>))*)<suffix>)?
16252
    // Append "(?:" to the end of result.
16253
0
    result.append("(?:");
16254
    // Append the result of running escape a regexp string given part's prefix
16255
    // to the end of result.
16256
0
    result.append(escape_regexp_string(part.prefix));
16257
    // Append "((?:" to the end of result.
16258
0
    result.append("((?:");
16259
    // Append regexp value to the end of result.
16260
0
    result.append(regexp_value);
16261
    // Append ")(?:" to the end of result.
16262
0
    result.append(")(?:");
16263
    // Append the result of running escape a regexp string given part's suffix
16264
    // to the end of result.
16265
0
    result.append(escape_regexp_string(part.suffix));
16266
    // Append the result of running escape a regexp string given part's prefix
16267
    // to the end of result.
16268
0
    result.append(escape_regexp_string(part.prefix));
16269
    // Append "(?:" to the end of result.
16270
0
    result.append("(?:");
16271
    // Append regexp value to the end of result.
16272
0
    result.append(regexp_value);
16273
    // Append "))*)" to the end of result.
16274
0
    result.append("))*)");
16275
    // Append the result of running escape a regexp string given part's suffix
16276
    // to the end of result.
16277
0
    result.append(escape_regexp_string(part.suffix));
16278
    // Append ")" to the end of result.
16279
0
    result.append(")");
16280
16281
    // If part's modifier is "zero-or-more" then append "?" to the end of result
16282
0
    if (part.modifier == url_pattern_part_modifier::zero_or_more) {
16283
0
      result += "?";
16284
0
    }
16285
0
  }
16286
16287
  // Append "$" to the end of result
16288
0
  result += "$";
16289
16290
  // Return (result, name list)
16291
0
  return {std::move(result), std::move(name_list)};
16292
0
}
16293
16294
0
bool is_ipv6_address(std::string_view input) noexcept {
16295
  // If input's code point length is less than 2, then return false.
16296
0
  if (input.size() < 2) return false;
16297
16298
  // Let input code points be input interpreted as a list of code points.
16299
  // If input code points[0] is U+005B ([), then return true.
16300
0
  if (input.front() == '[') return true;
16301
  // If input code points[0] is U+007B ({) and input code points[1] is U+005B
16302
  // ([), then return true.
16303
0
  if (input.starts_with("{[")) return true;
16304
  // If input code points[0] is U+005C (\) and input code points[1] is U+005B
16305
  // ([), then return true.
16306
0
  return input.starts_with("\\[");
16307
0
}
16308
16309
std::string_view convert_modifier_to_string(
16310
0
    url_pattern_part_modifier modifier) {
16311
0
  switch (modifier) {
16312
      // If modifier is "zero-or-more", then return "*".
16313
0
    case url_pattern_part_modifier::zero_or_more:
16314
0
      return "*";
16315
    // If modifier is "optional", then return "?".
16316
0
    case url_pattern_part_modifier::optional:
16317
0
      return "?";
16318
    // If modifier is "one-or-more", then return "+".
16319
0
    case url_pattern_part_modifier::one_or_more:
16320
0
      return "+";
16321
    // Return the empty string.
16322
0
    default:
16323
0
      return "";
16324
0
  }
16325
0
}
16326
16327
std::string generate_segment_wildcard_regexp(
16328
0
    url_pattern_compile_component_options options) {
16329
  // Let result be "[^".
16330
0
  std::string result = "[^";
16331
  // Append the result of running escape a regexp string given options's
16332
  // delimiter code point to the end of result.
16333
0
  result.append(escape_regexp_string(options.get_delimiter()));
16334
  // Append "]+?" to the end of result.
16335
0
  result.append("]+?");
16336
  // Return result.
16337
0
  ada_log("generate_segment_wildcard_regexp result: ", result);
16338
0
  return result;
16339
0
}
16340
16341
namespace {
16342
// Unified lookup table for URL pattern character classification
16343
// Bit flags for different character types
16344
constexpr uint8_t CHAR_SCHEME = 1;  // valid in scheme (a-z, A-Z, 0-9, +, -, .)
16345
constexpr uint8_t CHAR_UPPER = 2;   // uppercase letter (needs lowercasing)
16346
constexpr uint8_t CHAR_SIMPLE_HOSTNAME = 4;  // simple hostname (a-z, 0-9, -, .)
16347
constexpr uint8_t CHAR_SIMPLE_PATHNAME =
16348
    8;  // simple pathname (a-z, A-Z, 0-9, /, -, _, ~)
16349
16350
constexpr std::array<uint8_t, 256> char_class_table = []() consteval {
16351
  std::array<uint8_t, 256> table{};
16352
  for (int c = 'a'; c <= 'z'; c++)
16353
    table[c] = CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME | CHAR_SIMPLE_PATHNAME;
16354
  for (int c = 'A'; c <= 'Z'; c++)
16355
    table[c] = CHAR_SCHEME | CHAR_UPPER | CHAR_SIMPLE_PATHNAME;
16356
  for (int c = '0'; c <= '9'; c++)
16357
    table[c] = CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME | CHAR_SIMPLE_PATHNAME;
16358
  table['+'] = CHAR_SCHEME;
16359
  table['-'] = CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME | CHAR_SIMPLE_PATHNAME;
16360
  table['.'] =
16361
      CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME;  // not pathname (needs normalization)
16362
  table['/'] = CHAR_SIMPLE_PATHNAME;
16363
  table['_'] = CHAR_SIMPLE_PATHNAME;
16364
  table['~'] = CHAR_SIMPLE_PATHNAME;
16365
  return table;
16366
}();
16367
}  // namespace
16368
16369
tl::expected<std::string, errors> canonicalize_protocol(
16370
0
    std::string_view input) {
16371
0
  ada_log("canonicalize_protocol called with input=", input);
16372
0
  if (input.empty()) [[unlikely]] {
16373
0
    return "";
16374
0
  }
16375
16376
0
  if (input.ends_with(":")) {
16377
0
    input.remove_suffix(1);
16378
0
  }
16379
16380
  // Fast path: special schemes are already canonical
16381
0
  if (scheme::is_special(input)) {
16382
0
    return std::string(input);
16383
0
  }
16384
16385
  // Fast path: validate scheme chars and check for uppercase
16386
  // First char must be alpha (not +, -, ., or digit)
16387
0
  uint8_t first_flags = char_class_table[static_cast<uint8_t>(input[0])];
16388
0
  if (!(first_flags & CHAR_SCHEME) || input[0] == '+' || input[0] == '-' ||
16389
0
      input[0] == '.' || unicode::is_ascii_digit(input[0])) {
16390
0
    return tl::unexpected(errors::type_error);
16391
0
  }
16392
16393
0
  uint8_t needs_lowercase = first_flags & CHAR_UPPER;
16394
0
  for (size_t i = 1; i < input.size(); i++) {
16395
0
    uint8_t flags = char_class_table[static_cast<uint8_t>(input[i])];
16396
0
    if (!(flags & CHAR_SCHEME)) {
16397
0
      return tl::unexpected(errors::type_error);
16398
0
    }
16399
0
    needs_lowercase |= flags & CHAR_UPPER;
16400
0
  }
16401
16402
0
  if (needs_lowercase == 0) {
16403
0
    return std::string(input);
16404
0
  }
16405
16406
0
  std::string result(input);
16407
0
  unicode::to_lower_ascii(result.data(), result.size());
16408
0
  return result;
16409
0
}
16410
16411
tl::expected<std::string, errors> canonicalize_username(
16412
0
    std::string_view input) {
16413
  // If value is the empty string, return value.
16414
0
  if (input.empty()) [[unlikely]] {
16415
0
    return "";
16416
0
  }
16417
  // Percent-encode the input using the userinfo percent-encode set.
16418
0
  size_t idx = ada::unicode::percent_encode_index(
16419
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
16420
0
  if (idx == input.size()) {
16421
    // No encoding needed, return input as-is
16422
0
    return std::string(input);
16423
0
  }
16424
  // Percent-encode from the first character that needs encoding
16425
0
  return ada::unicode::percent_encode(
16426
0
      input, character_sets::USERINFO_PERCENT_ENCODE, idx);
16427
0
}
16428
16429
tl::expected<std::string, errors> canonicalize_password(
16430
0
    std::string_view input) {
16431
  // If value is the empty string, return value.
16432
0
  if (input.empty()) [[unlikely]] {
16433
0
    return "";
16434
0
  }
16435
  // Percent-encode the input using the userinfo percent-encode set.
16436
0
  size_t idx = ada::unicode::percent_encode_index(
16437
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
16438
0
  if (idx == input.size()) {
16439
    // No encoding needed, return input as-is
16440
0
    return std::string(input);
16441
0
  }
16442
  // Percent-encode from the first character that needs encoding
16443
0
  return ada::unicode::percent_encode(
16444
0
      input, character_sets::USERINFO_PERCENT_ENCODE, idx);
16445
0
}
16446
16447
tl::expected<std::string, errors> canonicalize_hostname(
16448
0
    std::string_view input) {
16449
0
  ada_log("canonicalize_hostname input=", input);
16450
0
  if (input.empty()) [[unlikely]] {
16451
0
    return "";
16452
0
  }
16453
16454
  // Fast path: simple hostnames (lowercase ASCII, digits, -, .) need no IDNA
16455
0
  bool needs_processing = false;
16456
0
  for (char c : input) {
16457
0
    needs_processing |=
16458
0
        !(char_class_table[static_cast<uint8_t>(c)] & CHAR_SIMPLE_HOSTNAME);
16459
0
  }
16460
0
  if (!needs_processing) {
16461
0
    return std::string(input);
16462
0
  }
16463
16464
  // Let dummyURL be a new URL record.
16465
  // Let parseResult be the result of running the basic URL parser given value
16466
  // with dummyURL as url and hostname state as state override.
16467
16468
  // IMPORTANT: The protocol needs to be a special protocol, otherwise the
16469
  // hostname will not be converted using IDNA.
16470
0
  auto url = ada::parse<url_aggregator>("https://dummy.test", nullptr);
16471
0
  ADA_ASSERT_TRUE(url);
16472
  // if (!isValidHostnameInput(hostname)) return kj::none;
16473
0
  if (!url->set_hostname(input)) {
16474
    // If parseResult is failure, then throw a TypeError.
16475
0
    return tl::unexpected(errors::type_error);
16476
0
  }
16477
  // Return dummyURL's host, serialized, or empty string if it is null.
16478
0
  return std::string(url->get_hostname());
16479
0
}
16480
16481
tl::expected<std::string, errors> canonicalize_ipv6_hostname(
16482
0
    std::string_view input) {
16483
0
  ada_log("canonicalize_ipv6_hostname input=", input);
16484
  // TODO: Optimization opportunity: Use lookup table to speed up checking
16485
0
  if (std::ranges::any_of(input, [](char c) {
16486
0
        return c != '[' && c != ']' && c != ':' &&
16487
0
               !unicode::is_ascii_hex_digit(c);
16488
0
      })) {
16489
0
    return tl::unexpected(errors::type_error);
16490
0
  }
16491
  // Append the result of running ASCII lowercase given code point to the end of
16492
  // result.
16493
0
  auto hostname = std::string(input);
16494
0
  unicode::to_lower_ascii(hostname.data(), hostname.size());
16495
0
  return hostname;
16496
0
}
16497
16498
tl::expected<std::string, errors> canonicalize_port(
16499
0
    std::string_view port_value) {
16500
  // If portValue is the empty string, return portValue.
16501
0
  if (port_value.empty()) [[unlikely]] {
16502
0
    return "";
16503
0
  }
16504
16505
  // Remove ASCII tab or newline characters
16506
0
  std::string trimmed(port_value);
16507
0
  helpers::remove_ascii_tab_or_newline(trimmed);
16508
16509
0
  if (trimmed.empty()) {
16510
0
    return "";
16511
0
  }
16512
16513
  // Input should start with a digit character
16514
0
  if (!unicode::is_ascii_digit(trimmed.front())) {
16515
0
    return tl::unexpected(errors::type_error);
16516
0
  }
16517
16518
  // Find the first non-digit character
16519
0
  auto first_non_digit =
16520
0
      std::ranges::find_if_not(trimmed, unicode::is_ascii_digit);
16521
0
  std::string_view digits_to_parse =
16522
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
16523
16524
  // Here we have that a range of ASCII digit characters identified
16525
  // by digits_to_parse. It is none empty.
16526
  // We want to determine whether it is a valid port number (0-65535).
16527
  // Clearly, if the length is greater than 5, it is invalid.
16528
  // If the length is 5, we need to compare lexicographically to "65535".
16529
  // Otherwise it is valid.
16530
0
  if (digits_to_parse.size() == 5) {
16531
0
    if (digits_to_parse > "65535") {
16532
0
      return tl::unexpected(errors::type_error);
16533
0
    }
16534
0
  } else if (digits_to_parse.size() > 5) {
16535
0
    return tl::unexpected(errors::type_error);
16536
0
  }
16537
0
  if (digits_to_parse[0] == '0' && digits_to_parse.size() > 1) {
16538
    // Leading zeros are not allowed for multi-digit ports
16539
0
    return tl::unexpected(errors::type_error);
16540
0
  }
16541
  // It is valid! Most times, we do not need to parse it into an integer.
16542
0
  return std::string(digits_to_parse);
16543
0
}
16544
16545
tl::expected<std::string, errors> canonicalize_port_with_protocol(
16546
0
    std::string_view port_value, std::string_view protocol) {
16547
  // If portValue is the empty string, return portValue.
16548
0
  if (port_value.empty()) [[unlikely]] {
16549
0
    return "";
16550
0
  }
16551
16552
  // Handle empty or trailing colon in protocol
16553
0
  if (protocol.empty()) {
16554
0
    protocol = "fake";
16555
0
  } else if (protocol.ends_with(":")) {
16556
0
    protocol.remove_suffix(1);
16557
0
  }
16558
16559
  // Remove ASCII tab or newline characters
16560
0
  std::string trimmed(port_value);
16561
0
  helpers::remove_ascii_tab_or_newline(trimmed);
16562
16563
0
  if (trimmed.empty()) {
16564
0
    return "";
16565
0
  }
16566
16567
  // Input should start with a digit character
16568
0
  if (!unicode::is_ascii_digit(trimmed.front())) {
16569
0
    return tl::unexpected(errors::type_error);
16570
0
  }
16571
16572
  // Find the first non-digit character
16573
0
  auto first_non_digit =
16574
0
      std::ranges::find_if_not(trimmed, unicode::is_ascii_digit);
16575
0
  std::string_view digits_to_parse =
16576
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
16577
16578
  // Parse the port number
16579
0
  uint16_t parsed_port{};
16580
0
  auto result = std::from_chars(digits_to_parse.data(),
16581
0
                                digits_to_parse.data() + digits_to_parse.size(),
16582
0
                                parsed_port);
16583
16584
0
  if (result.ec == std::errc::result_out_of_range) {
16585
0
    return tl::unexpected(errors::type_error);
16586
0
  }
16587
16588
0
  if (result.ec == std::errc()) {
16589
    // Check if this is the default port for the scheme
16590
0
    uint16_t default_port = scheme::get_special_port(protocol);
16591
16592
    // If it's the default port for a special scheme, return empty string
16593
0
    if (default_port != 0 && default_port == parsed_port) {
16594
0
      return "";
16595
0
    }
16596
16597
    // Successfully parsed, return as string
16598
0
    return std::to_string(parsed_port);
16599
0
  }
16600
16601
0
  return tl::unexpected(errors::type_error);
16602
0
}
16603
16604
tl::expected<std::string, errors> canonicalize_pathname(
16605
0
    std::string_view input) {
16606
0
  if (input.empty()) [[unlikely]] {
16607
0
    return "";
16608
0
  }
16609
16610
  // Fast path: simple pathnames (no . which needs normalization) can be
16611
  // returned as-is
16612
0
  bool needs_processing = false;
16613
0
  for (char c : input) {
16614
0
    needs_processing |=
16615
0
        !(char_class_table[static_cast<uint8_t>(c)] & CHAR_SIMPLE_PATHNAME);
16616
0
  }
16617
0
  if (!needs_processing) {
16618
0
    return std::string(input);
16619
0
  }
16620
16621
  // Let leading slash be true if the first code point in value is U+002F (/)
16622
  // and otherwise false.
16623
0
  const bool leading_slash = input.starts_with("/");
16624
  // Let modified value be "/-" if leading slash is false and otherwise the
16625
  // empty string.
16626
0
  const auto modified_value = leading_slash ? "" : "/-";
16627
0
  const auto full_url =
16628
0
      std::string("fake://fake-url") + modified_value + std::string(input);
16629
0
  if (auto url = ada::parse<url_aggregator>(full_url, nullptr)) {
16630
0
    const auto pathname = url->get_pathname();
16631
    // If leading slash is false, then set result to the code point substring
16632
    // from 2 to the end of the string within result.
16633
0
    return leading_slash ? std::string(pathname)
16634
0
                         : std::string(pathname.substr(2));
16635
0
  }
16636
  // If parseResult is failure, then throw a TypeError.
16637
0
  return tl::unexpected(errors::type_error);
16638
0
}
16639
16640
tl::expected<std::string, errors> canonicalize_opaque_pathname(
16641
0
    std::string_view input) {
16642
  // If value is the empty string, return value.
16643
0
  if (input.empty()) [[unlikely]] {
16644
0
    return "";
16645
0
  }
16646
  // Let dummyURL be a new URL record.
16647
  // Set dummyURL's path to the empty string.
16648
  // Let parseResult be the result of running URL parsing given value with
16649
  // dummyURL as url and opaque path state as state override.
16650
0
  if (auto url =
16651
0
          ada::parse<url_aggregator>("fake:" + std::string(input), nullptr)) {
16652
    // Return the result of URL path serializing dummyURL.
16653
0
    return std::string(url->get_pathname());
16654
0
  }
16655
  // If parseResult is failure, then throw a TypeError.
16656
0
  return tl::unexpected(errors::type_error);
16657
0
}
16658
16659
0
tl::expected<std::string, errors> canonicalize_search(std::string_view input) {
16660
  // If value is the empty string, return value.
16661
0
  if (input.empty()) [[unlikely]] {
16662
0
    return "";
16663
0
  }
16664
  // Remove leading '?' if present
16665
0
  std::string new_value;
16666
0
  new_value = input[0] == '?' ? input.substr(1) : input;
16667
  // Remove ASCII tab or newline characters
16668
0
  helpers::remove_ascii_tab_or_newline(new_value);
16669
16670
0
  if (new_value.empty()) {
16671
0
    return "";
16672
0
  }
16673
16674
  // Percent-encode using QUERY_PERCENT_ENCODE (for non-special URLs)
16675
  // Note: "fake://dummy.test" is not a special URL, so we use
16676
  // QUERY_PERCENT_ENCODE
16677
0
  size_t idx = ada::unicode::percent_encode_index(
16678
0
      new_value, character_sets::QUERY_PERCENT_ENCODE);
16679
0
  if (idx == new_value.size()) {
16680
    // No encoding needed
16681
0
    return new_value;
16682
0
  }
16683
  // Percent-encode from the first character that needs encoding
16684
0
  return ada::unicode::percent_encode(
16685
0
      new_value, character_sets::QUERY_PERCENT_ENCODE, idx);
16686
0
}
16687
16688
0
tl::expected<std::string, errors> canonicalize_hash(std::string_view input) {
16689
  // If value is the empty string, return value.
16690
0
  if (input.empty()) [[unlikely]] {
16691
0
    return "";
16692
0
  }
16693
  // Remove leading '#' if present
16694
0
  std::string new_value;
16695
0
  new_value = input[0] == '#' ? input.substr(1) : input;
16696
  // Remove ASCII tab or newline characters
16697
0
  helpers::remove_ascii_tab_or_newline(new_value);
16698
16699
0
  if (new_value.empty()) {
16700
0
    return "";
16701
0
  }
16702
16703
  // Percent-encode using FRAGMENT_PERCENT_ENCODE
16704
0
  size_t idx = ada::unicode::percent_encode_index(
16705
0
      new_value, character_sets::FRAGMENT_PERCENT_ENCODE);
16706
0
  if (idx == new_value.size()) {
16707
    // No encoding needed
16708
0
    return new_value;
16709
0
  }
16710
  // Percent-encode from the first character that needs encoding
16711
0
  return ada::unicode::percent_encode(
16712
0
      new_value, character_sets::FRAGMENT_PERCENT_ENCODE, idx);
16713
0
}
16714
16715
tl::expected<std::vector<token>, errors> tokenize(std::string_view input,
16716
0
                                                  token_policy policy) {
16717
0
  ada_log("tokenize input: ", input);
16718
  // Let tokenizer be a new tokenizer.
16719
  // Set tokenizer's input to input.
16720
  // Set tokenizer's policy to policy.
16721
0
  auto tokenizer = Tokenizer(input, policy);
16722
  // While tokenizer's index is less than tokenizer's input's code point length:
16723
0
  while (tokenizer.index < tokenizer.input.size()) {
16724
    // Run seek and get the next code point given tokenizer and tokenizer's
16725
    // index.
16726
0
    tokenizer.seek_and_get_next_code_point(tokenizer.index);
16727
16728
    // If tokenizer's code point is U+002A (*):
16729
0
    if (tokenizer.code_point == '*') {
16730
      // Run add a token with default position and length given tokenizer and
16731
      // "asterisk".
16732
0
      tokenizer.add_token_with_defaults(token_type::ASTERISK);
16733
0
      ada_log("add ASTERISK token");
16734
      // Continue.
16735
0
      continue;
16736
0
    }
16737
16738
    // If tokenizer's code point is U+002B (+) or U+003F (?):
16739
0
    if (tokenizer.code_point == '+' || tokenizer.code_point == '?') {
16740
      // Run add a token with default position and length given tokenizer and
16741
      // "other-modifier".
16742
0
      tokenizer.add_token_with_defaults(token_type::OTHER_MODIFIER);
16743
      // Continue.
16744
0
      continue;
16745
0
    }
16746
16747
    // If tokenizer's code point is U+005C (\):
16748
0
    if (tokenizer.code_point == '\\') {
16749
      // If tokenizer's index is equal to tokenizer's input's code point length
16750
      // - 1:
16751
0
      if (tokenizer.index == tokenizer.input.size() - 1) {
16752
        // Run process a tokenizing error given tokenizer, tokenizer's next
16753
        // index, and tokenizer's index.
16754
0
        if (auto error = tokenizer.process_tokenizing_error(
16755
0
                tokenizer.next_index, tokenizer.index)) {
16756
0
          ada_log("process_tokenizing_error failed");
16757
0
          return tl::unexpected(*error);
16758
0
        }
16759
0
        continue;
16760
0
      }
16761
16762
      // Let escaped index be tokenizer's next index.
16763
0
      auto escaped_index = tokenizer.next_index;
16764
      // Run get the next code point given tokenizer.
16765
0
      tokenizer.get_next_code_point();
16766
      // Run add a token with default length given tokenizer, "escaped-char",
16767
      // tokenizer's next index, and escaped index.
16768
0
      tokenizer.add_token_with_default_length(
16769
0
          token_type::ESCAPED_CHAR, tokenizer.next_index, escaped_index);
16770
0
      ada_log("add ESCAPED_CHAR token on next_index ", tokenizer.next_index,
16771
0
              " with escaped index ", escaped_index);
16772
      // Continue.
16773
0
      continue;
16774
0
    }
16775
16776
    // If tokenizer's code point is U+007B ({):
16777
0
    if (tokenizer.code_point == '{') {
16778
      // Run add a token with default position and length given tokenizer and
16779
      // "open".
16780
0
      tokenizer.add_token_with_defaults(token_type::OPEN);
16781
0
      ada_log("add OPEN token");
16782
0
      continue;
16783
0
    }
16784
16785
    // If tokenizer's code point is U+007D (}):
16786
0
    if (tokenizer.code_point == '}') {
16787
      // Run add a token with default position and length given tokenizer and
16788
      // "close".
16789
0
      tokenizer.add_token_with_defaults(token_type::CLOSE);
16790
0
      ada_log("add CLOSE token");
16791
0
      continue;
16792
0
    }
16793
16794
    // If tokenizer's code point is U+003A (:):
16795
0
    if (tokenizer.code_point == ':') {
16796
      // Let name position be tokenizer's next index.
16797
0
      auto name_position = tokenizer.next_index;
16798
      // Let name start be name position.
16799
0
      auto name_start = name_position;
16800
      // While name position is less than tokenizer's input's code point length:
16801
0
      while (name_position < tokenizer.input.size()) {
16802
        // Run seek and get the next code point given tokenizer and name
16803
        // position.
16804
0
        tokenizer.seek_and_get_next_code_point(name_position);
16805
        // Let first code point be true if name position equals name start and
16806
        // false otherwise.
16807
0
        bool first_code_point = name_position == name_start;
16808
        // Let valid code point be the result of running is a valid name code
16809
        // point given tokenizer's code point and first code point.
16810
0
        auto valid_code_point =
16811
0
            idna::valid_name_code_point(tokenizer.code_point, first_code_point);
16812
0
        ada_log("tokenizer.code_point=", uint32_t(tokenizer.code_point),
16813
0
                " first_code_point=", first_code_point,
16814
0
                " valid_code_point=", valid_code_point);
16815
        // If valid code point is false break.
16816
0
        if (!valid_code_point) break;
16817
        // Set name position to tokenizer's next index.
16818
0
        name_position = tokenizer.next_index;
16819
0
      }
16820
16821
      // If name position is less than or equal to name start:
16822
0
      if (name_position <= name_start) {
16823
        // Run process a tokenizing error given tokenizer, name start, and
16824
        // tokenizer's index.
16825
0
        if (auto error = tokenizer.process_tokenizing_error(name_start,
16826
0
                                                            tokenizer.index)) {
16827
0
          ada_log("process_tokenizing_error failed");
16828
0
          return tl::unexpected(*error);
16829
0
        }
16830
        // Continue
16831
0
        continue;
16832
0
      }
16833
16834
      // Run add a token with default length given tokenizer, "name", name
16835
      // position, and name start.
16836
0
      tokenizer.add_token_with_default_length(token_type::NAME, name_position,
16837
0
                                              name_start);
16838
0
      continue;
16839
0
    }
16840
16841
    // If tokenizer's code point is U+0028 (():
16842
0
    if (tokenizer.code_point == '(') {
16843
      // Let depth be 1.
16844
0
      size_t depth = 1;
16845
      // Let regexp position be tokenizer's next index.
16846
0
      auto regexp_position = tokenizer.next_index;
16847
      // Let regexp start be regexp position.
16848
0
      auto regexp_start = regexp_position;
16849
      // Let error be false.
16850
0
      bool error = false;
16851
16852
      // While regexp position is less than tokenizer's input's code point
16853
      // length:
16854
0
      while (regexp_position < tokenizer.input.size()) {
16855
        // Run seek and get the next code point given tokenizer and regexp
16856
        // position.
16857
0
        tokenizer.seek_and_get_next_code_point(regexp_position);
16858
16859
        // TODO: Optimization opportunity: The next 2 if statements can be
16860
        // merged. If the result of running is ASCII given tokenizer's code
16861
        // point is false:
16862
0
        if (!unicode::is_ascii(tokenizer.code_point)) {
16863
          // Run process a tokenizing error given tokenizer, regexp start, and
16864
          // tokenizer's index.
16865
0
          if (auto process_error = tokenizer.process_tokenizing_error(
16866
0
                  regexp_start, tokenizer.index)) {
16867
0
            return tl::unexpected(*process_error);
16868
0
          }
16869
          // Set error to true.
16870
0
          error = true;
16871
0
          break;
16872
0
        }
16873
16874
        // If regexp position equals regexp start and tokenizer's code point is
16875
        // U+003F (?):
16876
0
        if (regexp_position == regexp_start && tokenizer.code_point == '?') {
16877
          // Run process a tokenizing error given tokenizer, regexp start, and
16878
          // tokenizer's index.
16879
0
          if (auto process_error = tokenizer.process_tokenizing_error(
16880
0
                  regexp_start, tokenizer.index)) {
16881
0
            return tl::unexpected(*process_error);
16882
0
          }
16883
          // Set error to true;
16884
0
          error = true;
16885
0
          break;
16886
0
        }
16887
16888
        // If tokenizer's code point is U+005C (\):
16889
0
        if (tokenizer.code_point == '\\') {
16890
          // If regexp position equals tokenizer's input's code point length - 1
16891
0
          if (regexp_position == tokenizer.input.size() - 1) {
16892
            // Run process a tokenizing error given tokenizer, regexp start, and
16893
            // tokenizer's index.
16894
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16895
0
                    regexp_start, tokenizer.index)) {
16896
0
              return tl::unexpected(*process_error);
16897
0
            }
16898
            // Set error to true.
16899
0
            error = true;
16900
0
            break;
16901
0
          }
16902
          // Run get the next code point given tokenizer.
16903
0
          tokenizer.get_next_code_point();
16904
          // If the result of running is ASCII given tokenizer's code point is
16905
          // false:
16906
0
          if (!unicode::is_ascii(tokenizer.code_point)) {
16907
            // Run process a tokenizing error given tokenizer, regexp start, and
16908
            // tokenizer's index.
16909
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16910
0
                    regexp_start, tokenizer.index);
16911
0
                process_error.has_value()) {
16912
0
              return tl::unexpected(*process_error);
16913
0
            }
16914
            // Set error to true.
16915
0
            error = true;
16916
0
            break;
16917
0
          }
16918
          // Set regexp position to tokenizer's next index.
16919
0
          regexp_position = tokenizer.next_index;
16920
0
          continue;
16921
0
        }
16922
16923
        // If tokenizer's code point is U+0029 ()):
16924
0
        if (tokenizer.code_point == ')') {
16925
          // Decrement depth by 1.
16926
0
          depth--;
16927
          // If depth is 0:
16928
0
          if (depth == 0) {
16929
            // Set regexp position to tokenizer's next index.
16930
0
            regexp_position = tokenizer.next_index;
16931
            // Break.
16932
0
            break;
16933
0
          }
16934
0
        } else if (tokenizer.code_point == '(') {
16935
          // Otherwise if tokenizer's code point is U+0028 (():
16936
          // Increment depth by 1.
16937
0
          depth++;
16938
          // If regexp position equals tokenizer's input's code point length -
16939
          // 1:
16940
0
          if (regexp_position == tokenizer.input.size() - 1) {
16941
            // Run process a tokenizing error given tokenizer, regexp start, and
16942
            // tokenizer's index.
16943
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16944
0
                    regexp_start, tokenizer.index)) {
16945
0
              return tl::unexpected(*process_error);
16946
0
            }
16947
            // Set error to true.
16948
0
            error = true;
16949
0
            break;
16950
0
          }
16951
          // Let temporary position be tokenizer's next index.
16952
0
          auto temporary_position = tokenizer.next_index;
16953
          // Run get the next code point given tokenizer.
16954
0
          tokenizer.get_next_code_point();
16955
          // If tokenizer's code point is not U+003F (?):
16956
0
          if (tokenizer.code_point != '?') {
16957
            // Run process a tokenizing error given tokenizer, regexp start, and
16958
            // tokenizer's index.
16959
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16960
0
                    regexp_start, tokenizer.index)) {
16961
0
              return tl::unexpected(*process_error);
16962
0
            }
16963
            // Set error to true.
16964
0
            error = true;
16965
0
            break;
16966
0
          }
16967
          // Set tokenizer's next index to temporary position.
16968
0
          tokenizer.next_index = temporary_position;
16969
0
        }
16970
        // Set regexp position to tokenizer's next index.
16971
0
        regexp_position = tokenizer.next_index;
16972
0
      }
16973
16974
      // If error is true continue.
16975
0
      if (error) continue;
16976
      // If depth is not zero:
16977
0
      if (depth != 0) {
16978
        // Run process a tokenizing error given tokenizer, regexp start, and
16979
        // tokenizer's index.
16980
0
        if (auto process_error = tokenizer.process_tokenizing_error(
16981
0
                regexp_start, tokenizer.index)) {
16982
0
          return tl::unexpected(*process_error);
16983
0
        }
16984
0
        continue;
16985
0
      }
16986
      // Let regexp length be regexp position - regexp start - 1.
16987
0
      auto regexp_length = regexp_position - regexp_start - 1;
16988
      // If regexp length is zero:
16989
0
      if (regexp_length == 0) {
16990
        // Run process a tokenizing error given tokenizer, regexp start, and
16991
        // tokenizer's index.
16992
0
        if (auto process_error = tokenizer.process_tokenizing_error(
16993
0
                regexp_start, tokenizer.index)) {
16994
0
          ada_log("process_tokenizing_error failed");
16995
0
          return tl::unexpected(*process_error);
16996
0
        }
16997
0
        continue;
16998
0
      }
16999
      // Run add a token given tokenizer, "regexp", regexp position, regexp
17000
      // start, and regexp length.
17001
0
      tokenizer.add_token(token_type::REGEXP, regexp_position, regexp_start,
17002
0
                          regexp_length);
17003
0
      continue;
17004
0
    }
17005
    // Run add a token with default position and length given tokenizer and
17006
    // "char".
17007
0
    tokenizer.add_token_with_defaults(token_type::CHAR);
17008
0
  }
17009
  // Run add a token with default length given tokenizer, "end", tokenizer's
17010
  // index, and tokenizer's index.
17011
0
  tokenizer.add_token_with_default_length(token_type::END, tokenizer.index,
17012
0
                                          tokenizer.index);
17013
17014
0
  ada_log("tokenizer.token_list size is: ", tokenizer.token_list.size());
17015
  // Return tokenizer's token list.
17016
0
  return tokenizer.token_list;
17017
0
}
17018
17019
namespace {
17020
constexpr std::array<uint8_t, 256> escape_pattern_table = []() consteval {
17021
  std::array<uint8_t, 256> out{};
17022
  for (auto& c : {'+', '*', '?', ':', '{', '}', '(', ')', '\\'}) {
17023
    out[c] = 1;
17024
  }
17025
  return out;
17026
}();
17027
17028
0
constexpr bool should_escape_pattern_char(char c) {
17029
0
  return escape_pattern_table[static_cast<uint8_t>(c)];
17030
0
}
17031
}  // namespace
17032
17033
0
std::string escape_pattern_string(std::string_view input) {
17034
0
  ada_log("escape_pattern_string called with input=", input);
17035
0
  if (input.empty()) [[unlikely]] {
17036
0
    return "";
17037
0
  }
17038
  // Assert: input is an ASCII string.
17039
0
  ADA_ASSERT_TRUE(ada::idna::is_ascii(input));
17040
  // Let result be the empty string.
17041
0
  std::string result{};
17042
  // Reserve extra space for potential escapes
17043
0
  result.reserve(input.size() * 2);
17044
17045
  // While index is less than input's length:
17046
0
  for (const char c : input) {
17047
0
    if (should_escape_pattern_char(c)) {
17048
      // Append U+005C (\) to the end of result.
17049
0
      result.push_back('\\');
17050
0
    }
17051
    // Append c to the end of result.
17052
0
    result.push_back(c);
17053
0
  }
17054
  // Return result.
17055
0
  return result;
17056
0
}
17057
17058
namespace {
17059
constexpr std::array<uint8_t, 256> escape_regexp_table = []() consteval {
17060
  std::array<uint8_t, 256> out{};
17061
  for (auto& c : {'.', '+', '*', '?', '^', '$', '{', '}', '(', ')', '[', ']',
17062
                  '|', '/', '\\'}) {
17063
    out[c] = 1;
17064
  }
17065
  return out;
17066
}();
17067
17068
0
constexpr bool should_escape_regexp_char(char c) {
17069
0
  return escape_regexp_table[(uint8_t)c];
17070
0
}
17071
}  // namespace
17072
17073
0
std::string escape_regexp_string(std::string_view input) {
17074
  // Assert: input is an ASCII string.
17075
0
  ADA_ASSERT_TRUE(idna::is_ascii(input));
17076
  // Let result be the empty string.
17077
0
  std::string result{};
17078
  // Reserve extra space for potential escapes (worst case: all chars escaped)
17079
0
  result.reserve(input.size() * 2);
17080
0
  for (const char c : input) {
17081
0
    if (should_escape_regexp_char(c)) {
17082
      // Avoid temporary string allocation - directly append characters
17083
0
      result.push_back('\\');
17084
0
      result.push_back(c);
17085
0
    } else {
17086
0
      result.push_back(c);
17087
0
    }
17088
0
  }
17089
0
  return result;
17090
0
}
17091
17092
std::string process_base_url_string(std::string_view input,
17093
0
                                    url_pattern_init::process_type type) {
17094
  // If type is not "pattern" return input.
17095
0
  if (type != url_pattern_init::process_type::pattern) {
17096
0
    return std::string(input);
17097
0
  }
17098
  // Return the result of escaping a pattern string given input.
17099
0
  return escape_pattern_string(input);
17100
0
}
17101
17102
constexpr bool is_absolute_pathname(
17103
0
    std::string_view input, url_pattern_init::process_type type) noexcept {
17104
  // If input is the empty string, then return false.
17105
0
  if (input.empty()) [[unlikely]] {
17106
0
    return false;
17107
0
  }
17108
  // If input[0] is U+002F (/), then return true.
17109
0
  if (input.starts_with("/")) return true;
17110
  // If type is "url", then return false.
17111
0
  if (type == url_pattern_init::process_type::url) return false;
17112
  // If input's code point length is less than 2, then return false.
17113
0
  if (input.size() < 2) return false;
17114
  // If input[0] is U+005C (\) and input[1] is U+002F (/), then return true.
17115
  // If input[0] is U+007B ({) and input[1] is U+002F (/), then return true.
17116
  // Return false.
17117
0
  return input[1] == '/' && (input[0] == '\\' || input[0] == '{');
17118
0
}
17119
17120
std::string generate_pattern_string(
17121
    std::vector<url_pattern_part>& part_list,
17122
0
    url_pattern_compile_component_options& options) {
17123
  // Let result be the empty string.
17124
0
  std::string result{};
17125
  // Let index list be the result of getting the indices for part list.
17126
  // For each index of index list:
17127
0
  for (size_t index = 0; index < part_list.size(); index++) {
17128
    // Let part be part list[index].
17129
    // Use reference to avoid copy
17130
0
    const auto& part = part_list[index];
17131
    // Let previous part be part list[index - 1] if index is greater than 0,
17132
    // otherwise let it be null.
17133
    // Use pointer to avoid copy
17134
0
    const url_pattern_part* previous_part =
17135
0
        index == 0 ? nullptr : &part_list[index - 1];
17136
    // Let next part be part list[index + 1] if index is less than index list's
17137
    // size - 1, otherwise let it be null.
17138
0
    const url_pattern_part* next_part =
17139
0
        index < part_list.size() - 1 ? &part_list[index + 1] : nullptr;
17140
    // If part's type is "fixed-text" then:
17141
0
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
17142
      // If part's modifier is "none" then:
17143
0
      if (part.modifier == url_pattern_part_modifier::none) {
17144
        // Append the result of running escape a pattern string given part's
17145
        // value to the end of result.
17146
0
        result.append(escape_pattern_string(part.value));
17147
0
        continue;
17148
0
      }
17149
      // Append "{" to the end of result.
17150
0
      result += "{";
17151
      // Append the result of running escape a pattern string given part's value
17152
      // to the end of result.
17153
0
      result.append(escape_pattern_string(part.value));
17154
      // Append "}" to the end of result.
17155
0
      result += "}";
17156
      // Append the result of running convert a modifier to a string given
17157
      // part's modifier to the end of result.
17158
0
      result.append(convert_modifier_to_string(part.modifier));
17159
0
      continue;
17160
0
    }
17161
    // Let custom name be true if part's name[0] is not an ASCII digit;
17162
    // otherwise false.
17163
0
    bool custom_name = !unicode::is_ascii_digit(part.name[0]);
17164
    // Let needs grouping be true if at least one of the following are true,
17165
    // otherwise let it be false:
17166
    // - part's suffix is not the empty string.
17167
    // - part's prefix is not the empty string and is not options's prefix code
17168
    // point.
17169
0
    bool needs_grouping =
17170
0
        !part.suffix.empty() ||
17171
0
        (!part.prefix.empty() && part.prefix[0] != options.get_prefix()[0]);
17172
17173
    // If all of the following are true:
17174
    // - needs grouping is false; and
17175
    // - custom name is true; and
17176
    // - part's type is "segment-wildcard"; and
17177
    // - part's modifier is "none"; and
17178
    // - next part is not null; and
17179
    // - next part's prefix is the empty string; and
17180
    // - next part's suffix is the empty string
17181
0
    if (!needs_grouping && custom_name &&
17182
0
        part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
17183
0
        part.modifier == url_pattern_part_modifier::none && next_part &&
17184
0
        next_part->prefix.empty() && next_part->suffix.empty()) {
17185
      // If next part's type is "fixed-text":
17186
0
      if (next_part->type == url_pattern_part_type::FIXED_TEXT) {
17187
        // Set needs grouping to true if the result of running is a valid name
17188
        // code point given next part's value's first code point and the boolean
17189
        // false is true.
17190
0
        if (idna::valid_name_code_point(next_part->value[0], false)) {
17191
0
          needs_grouping = true;
17192
0
        }
17193
0
      } else {
17194
        // Set needs grouping to true if next part's name[0] is an ASCII digit.
17195
0
        needs_grouping = !next_part->name.empty() &&
17196
0
                         unicode::is_ascii_digit(next_part->name[0]);
17197
0
      }
17198
0
    }
17199
17200
    // If all of the following are true:
17201
    // - needs grouping is false; and
17202
    // - part's prefix is the empty string; and
17203
    // - previous part is not null; and
17204
    // - previous part's type is "fixed-text"; and
17205
    // - previous part's value's last code point is options's prefix code point.
17206
    // then set needs grouping to true.
17207
0
    if (!needs_grouping && part.prefix.empty() && previous_part &&
17208
0
        previous_part->type == url_pattern_part_type::FIXED_TEXT &&
17209
0
        !options.get_prefix().empty() &&
17210
0
        previous_part->value.at(previous_part->value.size() - 1) ==
17211
0
            options.get_prefix()[0]) {
17212
0
      needs_grouping = true;
17213
0
    }
17214
17215
    // Assert: part's name is not the empty string or null.
17216
0
    ADA_ASSERT_TRUE(!part.name.empty());
17217
17218
    // If needs grouping is true, then append "{" to the end of result.
17219
0
    if (needs_grouping) {
17220
0
      result.append("{");
17221
0
    }
17222
17223
    // Append the result of running escape a pattern string given part's prefix
17224
    // to the end of result.
17225
0
    result.append(escape_pattern_string(part.prefix));
17226
17227
    // If custom name is true:
17228
0
    if (custom_name) {
17229
      // Append ":" to the end of result.
17230
0
      result.append(":");
17231
      // Append part's name to the end of result.
17232
0
      result.append(part.name);
17233
0
    }
17234
17235
    // If part's type is "regexp" then:
17236
0
    if (part.type == url_pattern_part_type::REGEXP) {
17237
      // Append "(" to the end of result.
17238
0
      result.append("(");
17239
      // Append part's value to the end of result.
17240
0
      result.append(part.value);
17241
      // Append ")" to the end of result.
17242
0
      result.append(")");
17243
0
    } else if (part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
17244
0
               !custom_name) {
17245
      // Otherwise if part's type is "segment-wildcard" and custom name is
17246
      // false: Append "(" to the end of result.
17247
0
      result.append("(");
17248
      // Append the result of running generate a segment wildcard regexp given
17249
      // options to the end of result.
17250
0
      result.append(generate_segment_wildcard_regexp(options));
17251
      // Append ")" to the end of result.
17252
0
      result.append(")");
17253
0
    } else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
17254
      // Otherwise if part's type is "full-wildcard":
17255
      // If custom name is false and one of the following is true:
17256
      // - previous part is null; or
17257
      // - previous part's type is "fixed-text"; or
17258
      // - previous part's modifier is not "none"; or
17259
      // - needs grouping is true; or
17260
      // - part's prefix is not the empty string
17261
      // - then append "*" to the end of result.
17262
0
      if (!custom_name &&
17263
0
          (!previous_part ||
17264
0
           previous_part->type == url_pattern_part_type::FIXED_TEXT ||
17265
0
           previous_part->modifier != url_pattern_part_modifier::none ||
17266
0
           needs_grouping || !part.prefix.empty())) {
17267
0
        result.append("*");
17268
0
      } else {
17269
        // Append "(" to the end of result.
17270
        // Append full wildcard regexp value to the end of result.
17271
        // Append ")" to the end of result.
17272
0
        result.append("(.*)");
17273
0
      }
17274
0
    }
17275
17276
    // If all of the following are true:
17277
    // - part's type is "segment-wildcard"; and
17278
    // - custom name is true; and
17279
    // - part's suffix is not the empty string; and
17280
    // - The result of running is a valid name code point given part's suffix's
17281
    // first code point and the boolean false is true then append U+005C (\) to
17282
    // the end of result.
17283
0
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD && custom_name &&
17284
0
        !part.suffix.empty() &&
17285
0
        idna::valid_name_code_point(part.suffix[0], false)) {
17286
0
      result.append("\\");
17287
0
    }
17288
17289
    // Append the result of running escape a pattern string given part's suffix
17290
    // to the end of result.
17291
0
    result.append(escape_pattern_string(part.suffix));
17292
    // If needs grouping is true, then append "}" to the end of result.
17293
0
    if (needs_grouping) result.append("}");
17294
    // Append the result of running convert a modifier to a string given part's
17295
    // modifier to the end of result.
17296
0
    result.append(convert_modifier_to_string(part.modifier));
17297
0
  }
17298
  // Return result.
17299
0
  return result;
17300
0
}
17301
}  // namespace ada::url_pattern_helpers
17302
17303
#endif  // ADA_INCLUDE_URL_PATTERN
17304
/* end file src/url_pattern_helpers.cpp */
17305
/* begin file src/url_pattern_regex.cpp */
17306
#if ADA_INCLUDE_URL_PATTERN
17307
17308
17309
namespace ada::url_pattern_regex {
17310
17311
#ifdef ADA_USE_UNSAFE_STD_REGEX_PROVIDER
17312
std::optional<std::regex> std_regex_provider::create_instance(
17313
    std::string_view pattern, bool ignore_case) {
17314
  // Let flags be an empty string.
17315
  // If options's ignore case is true then set flags to "vi".
17316
  // Otherwise set flags to "v"
17317
  auto flags = ignore_case
17318
                   ? std::regex::icase | std::regex_constants::ECMAScript
17319
                   : std::regex_constants::ECMAScript;
17320
  try {
17321
    return std::regex(pattern.data(), pattern.size(), flags);
17322
  } catch (const std::regex_error& e) {
17323
    (void)e;
17324
    ada_log("std_regex_provider::create_instance failed:", e.what());
17325
    return std::nullopt;
17326
  }
17327
}
17328
17329
std::optional<std::vector<std::optional<std::string>>>
17330
std_regex_provider::regex_search(std::string_view input,
17331
                                 const std::regex& pattern) {
17332
  // Use iterator-based regex_search to avoid string allocation
17333
  std::match_results<std::string_view::const_iterator> match_result;
17334
  if (!std::regex_search(input.begin(), input.end(), match_result, pattern,
17335
                         std::regex_constants::match_any)) {
17336
    return std::nullopt;
17337
  }
17338
  std::vector<std::optional<std::string>> matches;
17339
  // If input is empty, let's assume the result will be empty as well.
17340
  if (input.empty() || match_result.empty()) {
17341
    return matches;
17342
  }
17343
  matches.reserve(match_result.size());
17344
  for (size_t i = 1; i < match_result.size(); ++i) {
17345
    if (auto entry = match_result[i]; entry.matched) {
17346
      matches.emplace_back(entry.str());
17347
    }
17348
  }
17349
  return matches;
17350
}
17351
17352
bool std_regex_provider::regex_match(std::string_view input,
17353
                                     const std::regex& pattern) {
17354
  return std::regex_match(input.begin(), input.end(), pattern);
17355
}
17356
17357
#endif  // ADA_USE_UNSAFE_STD_REGEX_PROVIDER
17358
17359
}  // namespace ada::url_pattern_regex
17360
17361
#endif  // ADA_INCLUDE_URL_PATTERN
17362
/* end file src/url_pattern_regex.cpp */
17363
#endif  // ADA_INCLUDE_URL_PATTERN
17364
17365
/* begin file src/ada_c.cpp */
17366
17367
0
ada::result<ada::url_aggregator>& get_instance(void* result) noexcept {
17368
0
  return *(ada::result<ada::url_aggregator>*)result;
17369
0
}
17370
17371
extern "C" {
17372
typedef void* ada_url;
17373
typedef void* ada_url_search_params;
17374
typedef void* ada_strings;
17375
typedef void* ada_url_search_params_keys_iter;
17376
typedef void* ada_url_search_params_values_iter;
17377
typedef void* ada_url_search_params_entries_iter;
17378
17379
struct ada_string {
17380
  const char* data;
17381
  size_t length;
17382
};
17383
17384
struct ada_owned_string {
17385
  const char* data;
17386
  size_t length;
17387
};
17388
17389
struct ada_string_pair {
17390
  ada_string key;
17391
  ada_string value;
17392
};
17393
17394
0
ada_string ada_string_create(const char* data, size_t length) {
17395
0
  ada_string out{};
17396
0
  out.data = data;
17397
0
  out.length = length;
17398
0
  return out;
17399
0
}
17400
17401
struct ada_url_components {
17402
  /*
17403
   * By using 32-bit integers, we implicitly assume that the URL string
17404
   * cannot exceed 4 GB.
17405
   *
17406
   * https://user:pass@example.com:1234/foo/bar?baz#quux
17407
   *       |     |    |          | ^^^^|       |   |
17408
   *       |     |    |          | |   |       |   `----- hash_start
17409
   *       |     |    |          | |   |       `--------- search_start
17410
   *       |     |    |          | |   `----------------- pathname_start
17411
   *       |     |    |          | `--------------------- port
17412
   *       |     |    |          `----------------------- host_end
17413
   *       |     |    `---------------------------------- host_start
17414
   *       |     `--------------------------------------- username_end
17415
   *       `--------------------------------------------- protocol_end
17416
   */
17417
  uint32_t protocol_end;
17418
  /**
17419
   * Username end is not `omitted` by default (-1) to make username and password
17420
   * getters less costly to implement.
17421
   */
17422
  uint32_t username_end;
17423
  uint32_t host_start;
17424
  uint32_t host_end;
17425
  uint32_t port;
17426
  uint32_t pathname_start;
17427
  uint32_t search_start;
17428
  uint32_t hash_start;
17429
};
17430
17431
0
ada_url ada_parse(const char* input, size_t length) noexcept {
17432
0
  return new ada::result<ada::url_aggregator>(
17433
0
      ada::parse<ada::url_aggregator>(std::string_view(input, length)));
17434
0
}
17435
17436
ada_url ada_parse_with_base(const char* input, size_t input_length,
17437
0
                            const char* base, size_t base_length) noexcept {
17438
0
  auto base_out =
17439
0
      ada::parse<ada::url_aggregator>(std::string_view(base, base_length));
17440
17441
0
  if (!base_out) {
17442
0
    return new ada::result<ada::url_aggregator>(base_out);
17443
0
  }
17444
17445
0
  return new ada::result<ada::url_aggregator>(ada::parse<ada::url_aggregator>(
17446
0
      std::string_view(input, input_length), &base_out.value()));
17447
0
}
17448
17449
0
bool ada_can_parse(const char* input, size_t length) noexcept {
17450
0
  return ada::can_parse(std::string_view(input, length));
17451
0
}
17452
17453
bool ada_can_parse_with_base(const char* input, size_t input_length,
17454
0
                             const char* base, size_t base_length) noexcept {
17455
0
  std::string_view base_view(base, base_length);
17456
0
  return ada::can_parse(std::string_view(input, input_length), &base_view);
17457
0
}
17458
17459
0
void ada_free(ada_url result) noexcept {
17460
0
  auto* r = (ada::result<ada::url_aggregator>*)result;
17461
0
  delete r;
17462
0
}
17463
17464
0
ada_url ada_copy(ada_url input) noexcept {
17465
0
  ada::result<ada::url_aggregator>& r = get_instance(input);
17466
0
  return new ada::result<ada::url_aggregator>(r);
17467
0
}
17468
17469
0
bool ada_is_valid(ada_url result) noexcept {
17470
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17471
0
  return r.has_value();
17472
0
}
17473
17474
// caller must free the result with ada_free_owned_string
17475
0
ada_owned_string ada_get_origin(ada_url result) noexcept {
17476
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17477
0
  ada_owned_string owned{};
17478
0
  if (!r) {
17479
0
    owned.data = nullptr;
17480
0
    owned.length = 0;
17481
0
    return owned;
17482
0
  }
17483
0
  std::string out = r->get_origin();
17484
0
  owned.length = out.size();
17485
0
  owned.data = new char[owned.length];
17486
0
  memcpy((void*)owned.data, out.data(), owned.length);
17487
0
  return owned;
17488
0
}
17489
17490
0
void ada_free_owned_string(ada_owned_string owned) noexcept {
17491
0
  delete[] owned.data;
17492
0
}
17493
17494
0
ada_string ada_get_href(ada_url result) noexcept {
17495
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17496
0
  if (!r) {
17497
0
    return ada_string_create(nullptr, 0);
17498
0
  }
17499
0
  std::string_view out = r->get_href();
17500
0
  return ada_string_create(out.data(), out.length());
17501
0
}
17502
17503
0
ada_string ada_get_username(ada_url result) noexcept {
17504
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17505
0
  if (!r) {
17506
0
    return ada_string_create(nullptr, 0);
17507
0
  }
17508
0
  std::string_view out = r->get_username();
17509
0
  return ada_string_create(out.data(), out.length());
17510
0
}
17511
17512
0
ada_string ada_get_password(ada_url result) noexcept {
17513
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17514
0
  if (!r) {
17515
0
    return ada_string_create(nullptr, 0);
17516
0
  }
17517
0
  std::string_view out = r->get_password();
17518
0
  return ada_string_create(out.data(), out.length());
17519
0
}
17520
17521
0
ada_string ada_get_port(ada_url result) noexcept {
17522
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17523
0
  if (!r) {
17524
0
    return ada_string_create(nullptr, 0);
17525
0
  }
17526
0
  std::string_view out = r->get_port();
17527
0
  return ada_string_create(out.data(), out.length());
17528
0
}
17529
17530
0
ada_string ada_get_hash(ada_url result) noexcept {
17531
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17532
0
  if (!r) {
17533
0
    return ada_string_create(nullptr, 0);
17534
0
  }
17535
0
  std::string_view out = r->get_hash();
17536
0
  return ada_string_create(out.data(), out.length());
17537
0
}
17538
17539
0
ada_string ada_get_host(ada_url result) noexcept {
17540
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17541
0
  if (!r) {
17542
0
    return ada_string_create(nullptr, 0);
17543
0
  }
17544
0
  std::string_view out = r->get_host();
17545
0
  return ada_string_create(out.data(), out.length());
17546
0
}
17547
17548
0
ada_string ada_get_hostname(ada_url result) noexcept {
17549
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17550
0
  if (!r) {
17551
0
    return ada_string_create(nullptr, 0);
17552
0
  }
17553
0
  std::string_view out = r->get_hostname();
17554
0
  return ada_string_create(out.data(), out.length());
17555
0
}
17556
17557
0
ada_string ada_get_pathname(ada_url result) noexcept {
17558
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17559
0
  if (!r) {
17560
0
    return ada_string_create(nullptr, 0);
17561
0
  }
17562
0
  std::string_view out = r->get_pathname();
17563
0
  return ada_string_create(out.data(), out.length());
17564
0
}
17565
17566
0
ada_string ada_get_search(ada_url result) noexcept {
17567
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17568
0
  if (!r) {
17569
0
    return ada_string_create(nullptr, 0);
17570
0
  }
17571
0
  std::string_view out = r->get_search();
17572
0
  return ada_string_create(out.data(), out.length());
17573
0
}
17574
17575
0
ada_string ada_get_protocol(ada_url result) noexcept {
17576
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17577
0
  if (!r) {
17578
0
    return ada_string_create(nullptr, 0);
17579
0
  }
17580
0
  std::string_view out = r->get_protocol();
17581
0
  return ada_string_create(out.data(), out.length());
17582
0
}
17583
17584
0
uint8_t ada_get_host_type(ada_url result) noexcept {
17585
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17586
0
  if (!r) {
17587
0
    return 0;
17588
0
  }
17589
0
  return r->host_type;
17590
0
}
17591
17592
0
uint8_t ada_get_scheme_type(ada_url result) noexcept {
17593
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17594
0
  if (!r) {
17595
0
    return 0;
17596
0
  }
17597
0
  return r->type;
17598
0
}
17599
17600
0
bool ada_set_href(ada_url result, const char* input, size_t length) noexcept {
17601
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17602
0
  if (!r) {
17603
0
    return false;
17604
0
  }
17605
0
  return r->set_href(std::string_view(input, length));
17606
0
}
17607
17608
0
bool ada_set_host(ada_url result, const char* input, size_t length) noexcept {
17609
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17610
0
  if (!r) {
17611
0
    return false;
17612
0
  }
17613
0
  return r->set_host(std::string_view(input, length));
17614
0
}
17615
17616
bool ada_set_hostname(ada_url result, const char* input,
17617
0
                      size_t length) noexcept {
17618
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17619
0
  if (!r) {
17620
0
    return false;
17621
0
  }
17622
0
  return r->set_hostname(std::string_view(input, length));
17623
0
}
17624
17625
bool ada_set_protocol(ada_url result, const char* input,
17626
0
                      size_t length) noexcept {
17627
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17628
0
  if (!r) {
17629
0
    return false;
17630
0
  }
17631
0
  return r->set_protocol(std::string_view(input, length));
17632
0
}
17633
17634
bool ada_set_username(ada_url result, const char* input,
17635
0
                      size_t length) noexcept {
17636
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17637
0
  if (!r) {
17638
0
    return false;
17639
0
  }
17640
0
  return r->set_username(std::string_view(input, length));
17641
0
}
17642
17643
bool ada_set_password(ada_url result, const char* input,
17644
0
                      size_t length) noexcept {
17645
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17646
0
  if (!r) {
17647
0
    return false;
17648
0
  }
17649
0
  return r->set_password(std::string_view(input, length));
17650
0
}
17651
17652
0
bool ada_set_port(ada_url result, const char* input, size_t length) noexcept {
17653
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17654
0
  if (!r) {
17655
0
    return false;
17656
0
  }
17657
0
  return r->set_port(std::string_view(input, length));
17658
0
}
17659
17660
bool ada_set_pathname(ada_url result, const char* input,
17661
0
                      size_t length) noexcept {
17662
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17663
0
  if (!r) {
17664
0
    return false;
17665
0
  }
17666
0
  return r->set_pathname(std::string_view(input, length));
17667
0
}
17668
17669
/**
17670
 * Update the search/query of the URL.
17671
 *
17672
 * If a URL has `?` as the search value, passing empty string to this function
17673
 * does not remove the attribute. If you need to remove it, please use
17674
 * `ada_clear_search` method.
17675
 */
17676
0
void ada_set_search(ada_url result, const char* input, size_t length) noexcept {
17677
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17678
0
  if (r) {
17679
0
    r->set_search(std::string_view(input, length));
17680
0
  }
17681
0
}
17682
17683
/**
17684
 * Update the hash/fragment of the URL.
17685
 *
17686
 * If a URL has `#` as the hash value, passing empty string to this function
17687
 * does not remove the attribute. If you need to remove it, please use
17688
 * `ada_clear_hash` method.
17689
 */
17690
0
void ada_set_hash(ada_url result, const char* input, size_t length) noexcept {
17691
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17692
0
  if (r) {
17693
0
    r->set_hash(std::string_view(input, length));
17694
0
  }
17695
0
}
17696
17697
0
void ada_clear_port(ada_url result) noexcept {
17698
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17699
0
  if (r) {
17700
0
    r->clear_port();
17701
0
  }
17702
0
}
17703
17704
/**
17705
 * Removes the hash of the URL.
17706
 *
17707
 * Despite `ada_set_hash` method, this function allows the complete
17708
 * removal of the hash attribute, even if it has a value of `#`.
17709
 */
17710
0
void ada_clear_hash(ada_url result) noexcept {
17711
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17712
0
  if (r) {
17713
0
    r->clear_hash();
17714
0
  }
17715
0
}
17716
17717
/**
17718
 * Removes the search of the URL.
17719
 *
17720
 * Despite `ada_set_search` method, this function allows the complete
17721
 * removal of the search attribute, even if it has a value of `?`.
17722
 */
17723
0
void ada_clear_search(ada_url result) noexcept {
17724
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17725
0
  if (r) {
17726
0
    r->clear_search();
17727
0
  }
17728
0
}
17729
17730
0
bool ada_has_credentials(ada_url result) noexcept {
17731
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17732
0
  if (!r) {
17733
0
    return false;
17734
0
  }
17735
0
  return r->has_credentials();
17736
0
}
17737
17738
0
bool ada_has_empty_hostname(ada_url result) noexcept {
17739
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17740
0
  if (!r) {
17741
0
    return false;
17742
0
  }
17743
0
  return r->has_empty_hostname();
17744
0
}
17745
17746
0
bool ada_has_hostname(ada_url result) noexcept {
17747
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17748
0
  if (!r) {
17749
0
    return false;
17750
0
  }
17751
0
  return r->has_hostname();
17752
0
}
17753
17754
0
bool ada_has_non_empty_username(ada_url result) noexcept {
17755
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17756
0
  if (!r) {
17757
0
    return false;
17758
0
  }
17759
0
  return r->has_non_empty_username();
17760
0
}
17761
17762
0
bool ada_has_non_empty_password(ada_url result) noexcept {
17763
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17764
0
  if (!r) {
17765
0
    return false;
17766
0
  }
17767
0
  return r->has_non_empty_password();
17768
0
}
17769
17770
0
bool ada_has_port(ada_url result) noexcept {
17771
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17772
0
  if (!r) {
17773
0
    return false;
17774
0
  }
17775
0
  return r->has_port();
17776
0
}
17777
17778
0
bool ada_has_password(ada_url result) noexcept {
17779
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17780
0
  if (!r) {
17781
0
    return false;
17782
0
  }
17783
0
  return r->has_password();
17784
0
}
17785
17786
0
bool ada_has_hash(ada_url result) noexcept {
17787
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17788
0
  if (!r) {
17789
0
    return false;
17790
0
  }
17791
0
  return r->has_hash();
17792
0
}
17793
17794
0
bool ada_has_search(ada_url result) noexcept {
17795
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17796
0
  if (!r) {
17797
0
    return false;
17798
0
  }
17799
0
  return r->has_search();
17800
0
}
17801
17802
// returns a pointer to the internal url_aggregator::url_components
17803
0
const ada_url_components* ada_get_components(ada_url result) noexcept {
17804
0
  static_assert(sizeof(ada_url_components) == sizeof(ada::url_components));
17805
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17806
0
  if (!r) {
17807
0
    return nullptr;
17808
0
  }
17809
0
  return reinterpret_cast<const ada_url_components*>(&r->get_components());
17810
0
}
17811
17812
0
ada_owned_string ada_idna_to_unicode(const char* input, size_t length) {
17813
0
  std::string out = ada::idna::to_unicode(std::string_view(input, length));
17814
0
  ada_owned_string owned{};
17815
0
  owned.length = out.length();
17816
0
  owned.data = new char[owned.length];
17817
0
  memcpy((void*)owned.data, out.data(), owned.length);
17818
0
  return owned;
17819
0
}
17820
17821
0
ada_owned_string ada_idna_to_ascii(const char* input, size_t length) {
17822
0
  std::string out = ada::idna::to_ascii(std::string_view(input, length));
17823
0
  ada_owned_string owned{};
17824
0
  owned.length = out.size();
17825
0
  owned.data = new char[owned.length];
17826
0
  memcpy((void*)owned.data, out.data(), owned.length);
17827
0
  return owned;
17828
0
}
17829
17830
ada_url_search_params ada_parse_search_params(const char* input,
17831
0
                                              size_t length) {
17832
0
  return new ada::result<ada::url_search_params>(
17833
0
      ada::url_search_params(std::string_view(input, length)));
17834
0
}
17835
17836
0
void ada_free_search_params(ada_url_search_params result) {
17837
0
  auto* r = (ada::result<ada::url_search_params>*)result;
17838
0
  delete r;
17839
0
}
17840
17841
0
ada_owned_string ada_search_params_to_string(ada_url_search_params result) {
17842
0
  ada::result<ada::url_search_params>& r =
17843
0
      *(ada::result<ada::url_search_params>*)result;
17844
0
  if (!r) return ada_owned_string{nullptr, 0};
17845
0
  std::string out = r->to_string();
17846
0
  ada_owned_string owned{};
17847
0
  owned.length = out.size();
17848
0
  owned.data = new char[owned.length];
17849
0
  memcpy((void*)owned.data, out.data(), owned.length);
17850
0
  return owned;
17851
0
}
17852
17853
0
size_t ada_search_params_size(ada_url_search_params result) {
17854
0
  ada::result<ada::url_search_params>& r =
17855
0
      *(ada::result<ada::url_search_params>*)result;
17856
0
  if (!r) {
17857
0
    return 0;
17858
0
  }
17859
0
  return r->size();
17860
0
}
17861
17862
0
void ada_search_params_sort(ada_url_search_params result) {
17863
0
  ada::result<ada::url_search_params>& r =
17864
0
      *(ada::result<ada::url_search_params>*)result;
17865
0
  if (r) {
17866
0
    r->sort();
17867
0
  }
17868
0
}
17869
17870
void ada_search_params_reset(ada_url_search_params result, const char* input,
17871
0
                             size_t length) {
17872
0
  ada::result<ada::url_search_params>& r =
17873
0
      *(ada::result<ada::url_search_params>*)result;
17874
0
  if (r) {
17875
0
    r->reset(std::string_view(input, length));
17876
0
  }
17877
0
}
17878
17879
void ada_search_params_append(ada_url_search_params result, const char* key,
17880
                              size_t key_length, const char* value,
17881
0
                              size_t value_length) {
17882
0
  ada::result<ada::url_search_params>& r =
17883
0
      *(ada::result<ada::url_search_params>*)result;
17884
0
  if (r) {
17885
0
    r->append(std::string_view(key, key_length),
17886
0
              std::string_view(value, value_length));
17887
0
  }
17888
0
}
17889
17890
void ada_search_params_set(ada_url_search_params result, const char* key,
17891
                           size_t key_length, const char* value,
17892
0
                           size_t value_length) {
17893
0
  ada::result<ada::url_search_params>& r =
17894
0
      *(ada::result<ada::url_search_params>*)result;
17895
0
  if (r) {
17896
0
    r->set(std::string_view(key, key_length),
17897
0
           std::string_view(value, value_length));
17898
0
  }
17899
0
}
17900
17901
void ada_search_params_remove(ada_url_search_params result, const char* key,
17902
0
                              size_t key_length) {
17903
0
  ada::result<ada::url_search_params>& r =
17904
0
      *(ada::result<ada::url_search_params>*)result;
17905
0
  if (r) {
17906
0
    r->remove(std::string_view(key, key_length));
17907
0
  }
17908
0
}
17909
17910
void ada_search_params_remove_value(ada_url_search_params result,
17911
                                    const char* key, size_t key_length,
17912
0
                                    const char* value, size_t value_length) {
17913
0
  ada::result<ada::url_search_params>& r =
17914
0
      *(ada::result<ada::url_search_params>*)result;
17915
0
  if (r) {
17916
0
    r->remove(std::string_view(key, key_length),
17917
0
              std::string_view(value, value_length));
17918
0
  }
17919
0
}
17920
17921
bool ada_search_params_has(ada_url_search_params result, const char* key,
17922
0
                           size_t key_length) {
17923
0
  ada::result<ada::url_search_params>& r =
17924
0
      *(ada::result<ada::url_search_params>*)result;
17925
0
  if (!r) {
17926
0
    return false;
17927
0
  }
17928
0
  return r->has(std::string_view(key, key_length));
17929
0
}
17930
17931
bool ada_search_params_has_value(ada_url_search_params result, const char* key,
17932
                                 size_t key_length, const char* value,
17933
0
                                 size_t value_length) {
17934
0
  ada::result<ada::url_search_params>& r =
17935
0
      *(ada::result<ada::url_search_params>*)result;
17936
0
  if (!r) {
17937
0
    return false;
17938
0
  }
17939
0
  return r->has(std::string_view(key, key_length),
17940
0
                std::string_view(value, value_length));
17941
0
}
17942
17943
ada_string ada_search_params_get(ada_url_search_params result, const char* key,
17944
0
                                 size_t key_length) {
17945
0
  ada::result<ada::url_search_params>& r =
17946
0
      *(ada::result<ada::url_search_params>*)result;
17947
0
  if (!r) {
17948
0
    return ada_string_create(nullptr, 0);
17949
0
  }
17950
0
  auto found = r->get(std::string_view(key, key_length));
17951
0
  if (!found.has_value()) {
17952
0
    return ada_string_create(nullptr, 0);
17953
0
  }
17954
0
  return ada_string_create(found->data(), found->length());
17955
0
}
17956
17957
ada_strings ada_search_params_get_all(ada_url_search_params result,
17958
0
                                      const char* key, size_t key_length) {
17959
0
  ada::result<ada::url_search_params>& r =
17960
0
      *(ada::result<ada::url_search_params>*)result;
17961
0
  if (!r) {
17962
0
    return new ada::result<std::vector<std::string>>(
17963
0
        std::vector<std::string>());
17964
0
  }
17965
0
  return new ada::result<std::vector<std::string>>(
17966
0
      r->get_all(std::string_view(key, key_length)));
17967
0
}
17968
17969
ada_url_search_params_keys_iter ada_search_params_get_keys(
17970
0
    ada_url_search_params result) {
17971
0
  ada::result<ada::url_search_params>& r =
17972
0
      *(ada::result<ada::url_search_params>*)result;
17973
0
  if (!r) {
17974
0
    return new ada::result<ada::url_search_params_keys_iter>(
17975
0
        ada::url_search_params_keys_iter());
17976
0
  }
17977
0
  return new ada::result<ada::url_search_params_keys_iter>(r->get_keys());
17978
0
}
17979
17980
ada_url_search_params_values_iter ada_search_params_get_values(
17981
0
    ada_url_search_params result) {
17982
0
  ada::result<ada::url_search_params>& r =
17983
0
      *(ada::result<ada::url_search_params>*)result;
17984
0
  if (!r) {
17985
0
    return new ada::result<ada::url_search_params_values_iter>(
17986
0
        ada::url_search_params_values_iter());
17987
0
  }
17988
0
  return new ada::result<ada::url_search_params_values_iter>(r->get_values());
17989
0
}
17990
17991
ada_url_search_params_entries_iter ada_search_params_get_entries(
17992
0
    ada_url_search_params result) {
17993
0
  ada::result<ada::url_search_params>& r =
17994
0
      *(ada::result<ada::url_search_params>*)result;
17995
0
  if (!r) {
17996
0
    return new ada::result<ada::url_search_params_entries_iter>(
17997
0
        ada::url_search_params_entries_iter());
17998
0
  }
17999
0
  return new ada::result<ada::url_search_params_entries_iter>(r->get_entries());
18000
0
}
18001
18002
0
void ada_free_strings(ada_strings result) {
18003
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
18004
0
  delete r;
18005
0
}
18006
18007
0
size_t ada_strings_size(ada_strings result) {
18008
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
18009
0
  if (!r) {
18010
0
    return 0;
18011
0
  }
18012
0
  return (*r)->size();
18013
0
}
18014
18015
0
ada_string ada_strings_get(ada_strings result, size_t index) {
18016
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
18017
0
  if (!r) {
18018
0
    return ada_string_create(nullptr, 0);
18019
0
  }
18020
0
  std::string_view view = (*r)->at(index);
18021
0
  return ada_string_create(view.data(), view.length());
18022
0
}
18023
18024
0
void ada_free_search_params_keys_iter(ada_url_search_params_keys_iter result) {
18025
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
18026
0
  delete r;
18027
0
}
18028
18029
ada_string ada_search_params_keys_iter_next(
18030
0
    ada_url_search_params_keys_iter result) {
18031
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
18032
0
  if (!r) {
18033
0
    return ada_string_create(nullptr, 0);
18034
0
  }
18035
0
  auto next = (*r)->next();
18036
0
  if (!next.has_value()) {
18037
0
    return ada_string_create(nullptr, 0);
18038
0
  }
18039
0
  return ada_string_create(next->data(), next->length());
18040
0
}
18041
18042
bool ada_search_params_keys_iter_has_next(
18043
0
    ada_url_search_params_keys_iter result) {
18044
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
18045
0
  if (!r) {
18046
0
    return false;
18047
0
  }
18048
0
  return (*r)->has_next();
18049
0
}
18050
18051
void ada_free_search_params_values_iter(
18052
0
    ada_url_search_params_values_iter result) {
18053
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
18054
0
  delete r;
18055
0
}
18056
18057
ada_string ada_search_params_values_iter_next(
18058
0
    ada_url_search_params_values_iter result) {
18059
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
18060
0
  if (!r) {
18061
0
    return ada_string_create(nullptr, 0);
18062
0
  }
18063
0
  auto next = (*r)->next();
18064
0
  if (!next.has_value()) {
18065
0
    return ada_string_create(nullptr, 0);
18066
0
  }
18067
0
  return ada_string_create(next->data(), next->length());
18068
0
}
18069
18070
bool ada_search_params_values_iter_has_next(
18071
0
    ada_url_search_params_values_iter result) {
18072
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
18073
0
  if (!r) {
18074
0
    return false;
18075
0
  }
18076
0
  return (*r)->has_next();
18077
0
}
18078
18079
void ada_free_search_params_entries_iter(
18080
0
    ada_url_search_params_entries_iter result) {
18081
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
18082
0
  delete r;
18083
0
}
18084
18085
ada_string_pair ada_search_params_entries_iter_next(
18086
0
    ada_url_search_params_entries_iter result) {
18087
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
18088
0
  if (!r) return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)};
18089
0
  auto next = (*r)->next();
18090
0
  if (!next.has_value()) {
18091
0
    return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)};
18092
0
  }
18093
0
  return ada_string_pair{
18094
0
      ada_string_create(next->first.data(), next->first.length()),
18095
0
      ada_string_create(next->second.data(), next->second.length())};
18096
0
}
18097
18098
bool ada_search_params_entries_iter_has_next(
18099
0
    ada_url_search_params_entries_iter result) {
18100
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
18101
0
  if (!r) {
18102
0
    return false;
18103
0
  }
18104
0
  return (*r)->has_next();
18105
0
}
18106
18107
typedef struct {
18108
  int major;
18109
  int minor;
18110
  int revision;
18111
} ada_version_components;
18112
18113
0
const char* ada_get_version() { return ADA_VERSION; }
18114
18115
0
ada_version_components ada_get_version_components() {
18116
0
  return ada_version_components{
18117
0
      .major = ada::ADA_VERSION_MAJOR,
18118
0
      .minor = ada::ADA_VERSION_MINOR,
18119
0
      .revision = ada::ADA_VERSION_REVISION,
18120
0
  };
18121
0
}
18122
18123
}  // extern "C"
18124
/* end file src/ada_c.cpp */
18125
/* end file src/ada.cpp */