Coverage Report

Created: 2026-02-26 06:51

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-02-23 21:29:24 -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
14.4k
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
14.4k
  if (view.ends_with('.')) {
21
895
    view.remove_suffix(1);
22
895
    if (view.empty()) {
23
360
      return false;
24
360
    }
25
895
  }
26
14.1k
  char last_char = view.back();
27
14.1k
  bool possible_ipv4 = (last_char >= '0' && last_char <= '9') ||
28
10.7k
                       (last_char >= 'a' && last_char <= 'f') ||
29
7.07k
                       last_char == 'x';
30
14.1k
  if (!possible_ipv4) {
31
6.70k
    return false;
32
6.70k
  }
33
  // From the last character, find the last dot.
34
7.41k
  size_t last_dot = view.rfind('.');
35
7.41k
  if (last_dot != std::string_view::npos) {
36
    // We have at least one dot.
37
1.84k
    view = view.substr(last_dot + 1);
38
1.84k
  }
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
7.41k
  if (std::ranges::all_of(view, ada::checkers::is_digit)) {
43
2.56k
    return true;
44
2.56k
  }
45
  // It could be hex (0x), but not if there is a single character.
46
4.84k
  if (view.size() == 1) {
47
393
    return false;
48
393
  }
49
  // It must start with 0x.
50
4.45k
  if (!view.starts_with("0x")) {
51
3.28k
    return false;
52
3.28k
  }
53
  // We must allow "0x".
54
1.16k
  if (view.size() == 2) {
55
72
    return true;
56
72
  }
57
  // We have 0x followed by some characters, we need to check that they are
58
  // hexadecimals.
59
1.09k
  view.remove_prefix(2);
60
1.09k
  return std::ranges::all_of(view, ada::unicode::is_lowercase_hex);
61
1.16k
}
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
9.66k
    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
9.66k
  size_t i = 0;
94
9.66k
  uint8_t accumulator{};
95
114k
  for (; i + 7 < input.size(); i += 8) {
96
104k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])] |
97
104k
                           path_signature_table[uint8_t(input[i + 1])] |
98
104k
                           path_signature_table[uint8_t(input[i + 2])] |
99
104k
                           path_signature_table[uint8_t(input[i + 3])] |
100
104k
                           path_signature_table[uint8_t(input[i + 4])] |
101
104k
                           path_signature_table[uint8_t(input[i + 5])] |
102
104k
                           path_signature_table[uint8_t(input[i + 6])] |
103
104k
                           path_signature_table[uint8_t(input[i + 7])]);
104
104k
  }
105
40.0k
  for (; i < input.size(); i++) {
106
30.3k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])]);
107
30.3k
  }
108
9.66k
  return accumulator;
109
9.66k
}
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
// NOLINTBEGIN: this is an auto-generated file
140
/* auto-generated on 2026-01-30 12:00:02 -0500. Do not edit! */
141
/* begin file src/idna.cpp */
142
/* begin file src/unicode_transcoding.cpp */
143
144
#include <algorithm>
145
#include <cstdint>
146
#include <cstring>
147
148
namespace ada::idna {
149
150
6.31k
size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) {
151
6.31k
  const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
152
6.31k
  size_t pos = 0;
153
6.31k
  const char32_t* start{utf32_output};
154
236k
  while (pos < len) {
155
    // try to convert the next block of 16 ASCII bytes
156
230k
    if (pos + 16 <= len) {  // if it is safe to read 16 more
157
                            // bytes, check that they are ascii
158
200k
      uint64_t v1;
159
200k
      std::memcpy(&v1, data + pos, sizeof(uint64_t));
160
200k
      uint64_t v2;
161
200k
      std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
162
200k
      uint64_t v{v1 | v2};
163
200k
      if ((v & 0x8080808080808080) == 0) {
164
4.54k
        size_t final_pos = pos + 16;
165
77.1k
        while (pos < final_pos) {
166
72.6k
          *utf32_output++ = char32_t(buf[pos]);
167
72.6k
          pos++;
168
72.6k
        }
169
4.54k
        continue;
170
4.54k
      }
171
200k
    }
172
226k
    uint8_t leading_byte = data[pos];  // leading byte
173
226k
    if (leading_byte < 0b10000000) {
174
      // converting one ASCII byte !!!
175
105k
      *utf32_output++ = char32_t(leading_byte);
176
105k
      pos++;
177
120k
    } else if ((leading_byte & 0b11100000) == 0b11000000) {
178
      // We have a two-byte UTF-8
179
8.88k
      if (pos + 1 >= len) {
180
114
        return 0;
181
114
      }  // minimal bound checking
182
8.76k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
183
36
        return 0;
184
36
      }
185
      // range check
186
8.73k
      uint32_t code_point =
187
8.73k
          (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
188
8.73k
      if (code_point < 0x80 || 0x7ff < code_point) {
189
7
        return 0;
190
7
      }
191
8.72k
      *utf32_output++ = char32_t(code_point);
192
8.72k
      pos += 2;
193
111k
    } else if ((leading_byte & 0b11110000) == 0b11100000) {
194
      // We have a three-byte UTF-8
195
109k
      if (pos + 2 >= len) {
196
35
        return 0;
197
35
      }  // minimal bound checking
198
199
109k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
200
42
        return 0;
201
42
      }
202
109k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
203
38
        return 0;
204
38
      }
205
      // range check
206
109k
      uint32_t code_point = (leading_byte & 0b00001111) << 12 |
207
109k
                            (data[pos + 1] & 0b00111111) << 6 |
208
109k
                            (data[pos + 2] & 0b00111111);
209
109k
      if (code_point < 0x800 || 0xffff < code_point ||
210
109k
          (0xd7ff < code_point && code_point < 0xe000)) {
211
17
        return 0;
212
17
      }
213
109k
      *utf32_output++ = char32_t(code_point);
214
109k
      pos += 3;
215
109k
    } else if ((leading_byte & 0b11111000) == 0b11110000) {  // 0b11110000
216
      // we have a 4-byte UTF-8 word.
217
1.26k
      if (pos + 3 >= len) {
218
19
        return 0;
219
19
      }  // minimal bound checking
220
1.24k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
221
44
        return 0;
222
44
      }
223
1.20k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
224
3
        return 0;
225
3
      }
226
1.20k
      if ((data[pos + 3] & 0b11000000) != 0b10000000) {
227
9
        return 0;
228
9
      }
229
230
      // range check
231
1.19k
      uint32_t code_point = (leading_byte & 0b00000111) << 18 |
232
1.19k
                            (data[pos + 1] & 0b00111111) << 12 |
233
1.19k
                            (data[pos + 2] & 0b00111111) << 6 |
234
1.19k
                            (data[pos + 3] & 0b00111111);
235
1.19k
      if (code_point <= 0xffff || 0x10ffff < code_point) {
236
19
        return 0;
237
19
      }
238
1.17k
      *utf32_output++ = char32_t(code_point);
239
1.17k
      pos += 4;
240
1.17k
    } else {
241
421
      return 0;
242
421
    }
243
226k
  }
244
5.50k
  return utf32_output - start;
245
6.31k
}
246
247
0
size_t utf8_length_from_utf32(const char32_t* buf, size_t len) {
248
  // We are not BOM aware.
249
0
  const uint32_t* p = reinterpret_cast<const uint32_t*>(buf);
250
0
  size_t counter{0};
251
0
  for (size_t i = 0; i != len; ++i) {
252
0
    ++counter;                                      // ASCII
253
0
    counter += static_cast<size_t>(p[i] > 0x7F);    // two-byte
254
0
    counter += static_cast<size_t>(p[i] > 0x7FF);   // three-byte
255
0
    counter += static_cast<size_t>(p[i] > 0xFFFF);  // four-bytes
256
0
  }
257
0
  return counter;
258
0
}
259
260
6.31k
size_t utf32_length_from_utf8(const char* buf, size_t len) {
261
6.31k
  const int8_t* p = reinterpret_cast<const int8_t*>(buf);
262
598k
  return std::count_if(p, std::next(p, len), [](int8_t c) {
263
    // -65 is 0b10111111, anything larger in two-complement's
264
    // should start a new code point.
265
598k
    return c > -65;
266
598k
  });
267
6.31k
}
268
269
0
size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) {
270
0
  const uint32_t* data = reinterpret_cast<const uint32_t*>(buf);
271
0
  size_t pos = 0;
272
0
  const char* start{utf8_output};
273
0
  while (pos < len) {
274
    // try to convert the next block of 2 ASCII characters
275
0
    if (pos + 2 <= len) {  // if it is safe to read 8 more
276
                           // bytes, check that they are ascii
277
0
      uint64_t v;
278
0
      std::memcpy(&v, data + pos, sizeof(uint64_t));
279
0
      if ((v & 0xFFFFFF80FFFFFF80) == 0) {
280
0
        *utf8_output++ = char(buf[pos]);
281
0
        *utf8_output++ = char(buf[pos + 1]);
282
0
        pos += 2;
283
0
        continue;
284
0
      }
285
0
    }
286
0
    uint32_t word = data[pos];
287
0
    if ((word & 0xFFFFFF80) == 0) {
288
      // will generate one UTF-8 bytes
289
0
      *utf8_output++ = char(word);
290
0
      pos++;
291
0
    } else if ((word & 0xFFFFF800) == 0) {
292
      // will generate two UTF-8 bytes
293
      // we have 0b110XXXXX 0b10XXXXXX
294
0
      *utf8_output++ = char((word >> 6) | 0b11000000);
295
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
296
0
      pos++;
297
0
    } else if ((word & 0xFFFF0000) == 0) {
298
      // will generate three UTF-8 bytes
299
      // we have 0b1110XXXX 0b10XXXXXX 0b10XXXXXX
300
0
      if (word >= 0xD800 && word <= 0xDFFF) {
301
0
        return 0;
302
0
      }
303
0
      *utf8_output++ = char((word >> 12) | 0b11100000);
304
0
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
305
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
306
0
      pos++;
307
0
    } else {
308
      // will generate four UTF-8 bytes
309
      // we have 0b11110XXX 0b10XXXXXX 0b10XXXXXX
310
      // 0b10XXXXXX
311
0
      if (word > 0x10FFFF) {
312
0
        return 0;
313
0
      }
314
0
      *utf8_output++ = char((word >> 18) | 0b11110000);
315
0
      *utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
316
0
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
317
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
318
0
      pos++;
319
0
    }
320
0
  }
321
0
  return utf8_output - start;
322
0
}
323
}  // namespace ada::idna
324
/* end file src/unicode_transcoding.cpp */
325
/* begin file src/mapping.cpp */
326
327
#include <algorithm>
328
#include <array>
329
#include <string>
330
331
/* begin file src/mapping_tables.cpp */
332
// IDNA  17.0.0
333
334
// clang-format off
335
#ifndef ADA_IDNA_TABLES_H
336
#define ADA_IDNA_TABLES_H
337
#include <cstdint>
338
339
namespace ada::idna {
340
341
const uint32_t mappings[5264] =
342
{
343
  97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
344
  114, 115, 116, 117, 118, 119, 120, 121, 122, 32, 32, 776, 32, 772, 50, 51, 32, 769,
345
  956, 32, 807, 49, 49, 8260, 52, 49, 8260, 50, 51, 8260, 52, 224, 225, 226, 227,
346
  228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
347
  244, 245, 246, 248, 249, 250, 251, 252, 253, 254, 257, 259, 261, 263, 265, 267,
348
  269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299,
349
  301, 303, 105, 775, 309, 311, 314, 316, 318, 108, 183, 322, 324, 326, 328, 700,
350
  110, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359,
351
  361, 363, 365, 367, 369, 371, 373, 375, 255, 378, 380, 382, 595, 387, 389, 596,
352
  392, 598, 599, 396, 477, 601, 603, 402, 608, 611, 617, 616, 409, 623, 626, 629,
353
  417, 419, 421, 640, 424, 643, 429, 648, 432, 650, 651, 436, 438, 658, 441, 445,
354
  100, 382, 108, 106, 110, 106, 462, 464, 466, 468, 470, 472, 474, 476, 479, 481,
355
  483, 485, 487, 489, 491, 493, 495, 100, 122, 501, 405, 447, 505, 507, 509, 511,
356
  513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535, 537, 539, 541, 543,
357
  414, 547, 549, 551, 553, 555, 557, 559, 561, 563, 11365, 572, 410, 11366, 578, 384,
358
  649, 652, 583, 585, 587, 589, 591, 614, 633, 635, 641, 32, 774, 32, 775, 32, 778,
359
  32, 808, 32, 771, 32, 779, 661, 768, 787, 776, 769, 953, 881, 883, 697, 887, 32,
360
  953, 59, 1011, 32, 776, 769, 940, 941, 942, 943, 972, 973, 974, 945, 946, 947, 948,
361
  949, 950, 951, 952, 954, 955, 957, 958, 959, 960, 961, 963, 964, 965, 966, 967,
362
  968, 969, 970, 971, 983, 985, 987, 989, 991, 993, 995, 997, 999, 1001, 1003, 1005,
363
  1007, 1016, 1019, 891, 892, 893, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111,
364
  1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1072, 1073, 1074, 1075, 1076, 1077,
365
  1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091,
366
  1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1121, 1123,
367
  1125, 1127, 1129, 1131, 1133, 1135, 1137, 1139, 1141, 1143, 1145, 1147, 1149, 1151,
368
  1153, 1163, 1165, 1167, 1169, 1171, 1173, 1175, 1177, 1179, 1181, 1183, 1185, 1187,
369
  1189, 1191, 1193, 1195, 1197, 1199, 1201, 1203, 1205, 1207, 1209, 1211, 1213, 1215,
370
  1231, 1218, 1220, 1222, 1224, 1226, 1228, 1230, 1233, 1235, 1237, 1239, 1241, 1243,
371
  1245, 1247, 1249, 1251, 1253, 1255, 1257, 1259, 1261, 1263, 1265, 1267, 1269, 1271,
372
  1273, 1275, 1277, 1279, 1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, 1297, 1299,
373
  1301, 1303, 1305, 1307, 1309, 1311, 1313, 1315, 1317, 1319, 1321, 1323, 1325, 1327,
374
  1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390,
375
  1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404,
376
  1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1381, 1410, 1575, 1652,
377
  1608, 1652, 1735, 1652, 1610, 1652, 2325, 2364, 2326, 2364, 2327, 2364, 2332, 2364,
378
  2337, 2364, 2338, 2364, 2347, 2364, 2351, 2364, 2465, 2492, 2466, 2492, 2479, 2492,
379
  2610, 2620, 2616, 2620, 2582, 2620, 2583, 2620, 2588, 2620, 2603, 2620, 2849, 2876,
380
  2850, 2876, 3661, 3634, 3789, 3762, 3755, 3737, 3755, 3745, 3851, 3906, 4023, 3916,
381
  4023, 3921, 4023, 3926, 4023, 3931, 4023, 3904, 4021, 3953, 3954, 3953, 3956, 4018,
382
  3968, 4018, 3953, 3968, 4019, 3968, 4019, 3953, 3968, 3986, 4023, 3996, 4023, 4001,
383
  4023, 4006, 4023, 4011, 4023, 3984, 4021, 11520, 11521, 11522, 11523, 11524, 11525,
384
  11526, 11527, 11528, 11529, 11530, 11531, 11532, 11533, 11534, 11535, 11536, 11537,
385
  11538, 11539, 11540, 11541, 11542, 11543, 11544, 11545, 11546, 11547, 11548, 11549,
386
  11550, 11551, 11552, 11553, 11554, 11555, 11556, 11557, 11559, 11565, 4316, 5104,
387
  5105, 5106, 5107, 5108, 5109, 42571, 7306, 4304, 4305, 4306, 4307, 4308, 4309, 4310,
388
  4311, 4312, 4313, 4314, 4315, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325,
389
  4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339,
390
  4340, 4341, 4342, 4343, 4344, 4345, 4346, 4349, 4350, 4351, 592, 593, 7426, 604,
391
  7446, 7447, 7453, 7461, 594, 597, 607, 609, 613, 618, 7547, 669, 621, 7557, 671,
392
  625, 624, 627, 628, 632, 642, 427, 7452, 656, 657, 7681, 7683, 7685, 7687, 7689,
393
  7691, 7693, 7695, 7697, 7699, 7701, 7703, 7705, 7707, 7709, 7711, 7713, 7715, 7717,
394
  7719, 7721, 7723, 7725, 7727, 7729, 7731, 7733, 7735, 7737, 7739, 7741, 7743, 7745,
395
  7747, 7749, 7751, 7753, 7755, 7757, 7759, 7761, 7763, 7765, 7767, 7769, 7771, 7773,
396
  7775, 7777, 7779, 7781, 7783, 7785, 7787, 7789, 7791, 7793, 7795, 7797, 7799, 7801,
397
  7803, 7805, 7807, 7809, 7811, 7813, 7815, 7817, 7819, 7821, 7823, 7825, 7827, 7829,
398
  97, 702, 223, 7841, 7843, 7845, 7847, 7849, 7851, 7853, 7855, 7857, 7859, 7861,
399
  7863, 7865, 7867, 7869, 7871, 7873, 7875, 7877, 7879, 7881, 7883, 7885, 7887, 7889,
400
  7891, 7893, 7895, 7897, 7899, 7901, 7903, 7905, 7907, 7909, 7911, 7913, 7915, 7917,
401
  7919, 7921, 7923, 7925, 7927, 7929, 7931, 7933, 7935, 7936, 7937, 7938, 7939, 7940,
402
  7941, 7942, 7943, 7952, 7953, 7954, 7955, 7956, 7957, 7968, 7969, 7970, 7971, 7972,
403
  7973, 7974, 7975, 7984, 7985, 7986, 7987, 7988, 7989, 7990, 7991, 8000, 8001, 8002,
404
  8003, 8004, 8005, 8017, 8019, 8021, 8023, 8032, 8033, 8034, 8035, 8036, 8037, 8038,
405
  8039, 7936, 953, 7937, 953, 7938, 953, 7939, 953, 7940, 953, 7941, 953, 7942, 953,
406
  7943, 953, 7968, 953, 7969, 953, 7970, 953, 7971, 953, 7972, 953, 7973, 953, 7974,
407
  953, 7975, 953, 8032, 953, 8033, 953, 8034, 953, 8035, 953, 8036, 953, 8037, 953,
408
  8038, 953, 8039, 953, 8048, 953, 945, 953, 940, 953, 8118, 953, 8112, 8113, 32,
409
  787, 32, 834, 32, 776, 834, 8052, 953, 951, 953, 942, 953, 8134, 953, 8050, 32,
410
  787, 768, 32, 787, 769, 32, 787, 834, 912, 8144, 8145, 8054, 32, 788, 768, 32, 788,
411
  769, 32, 788, 834, 944, 8160, 8161, 8058, 8165, 32, 776, 768, 96, 8060, 953, 969,
412
  953, 974, 953, 8182, 953, 8056, 8208, 32, 819, 8242, 8242, 8242, 8242, 8242, 8245,
413
  8245, 8245, 8245, 8245, 33, 33, 32, 773, 63, 63, 63, 33, 33, 63, 48, 53, 54, 55,
414
  56, 57, 43, 8722, 61, 40, 41, 97, 47, 99, 97, 47, 115, 176, 99, 99, 47, 111, 99,
415
  47, 117, 176, 102, 115, 109, 116, 101, 108, 116, 109, 8526, 1488, 1489, 1490, 1491,
416
  102, 97, 120, 8721, 49, 8260, 55, 49, 8260, 57, 49, 8260, 49, 48, 49, 8260, 51,
417
  50, 8260, 51, 49, 8260, 53, 50, 8260, 53, 51, 8260, 53, 52, 8260, 53, 49, 8260,
418
  54, 53, 8260, 54, 49, 8260, 56, 51, 8260, 56, 53, 8260, 56, 55, 8260, 56, 105, 105,
419
  105, 105, 105, 105, 118, 118, 105, 118, 105, 105, 118, 105, 105, 105, 105, 120,
420
  120, 105, 120, 105, 105, 8580, 48, 8260, 51, 8747, 8747, 8747, 8747, 8747, 8750,
421
  8750, 8750, 8750, 8750, 12296, 12297, 49, 50, 49, 51, 49, 52, 49, 53, 49, 54, 49,
422
  55, 49, 56, 49, 57, 50, 48, 40, 49, 41, 40, 50, 41, 40, 51, 41, 40, 52, 41, 40,
423
  53, 41, 40, 54, 41, 40, 55, 41, 40, 56, 41, 40, 57, 41, 40, 49, 48, 41, 40, 49,
424
  49, 41, 40, 49, 50, 41, 40, 49, 51, 41, 40, 49, 52, 41, 40, 49, 53, 41, 40, 49,
425
  54, 41, 40, 49, 55, 41, 40, 49, 56, 41, 40, 49, 57, 41, 40, 50, 48, 41, 40, 97,
426
  41, 40, 98, 41, 40, 99, 41, 40, 100, 41, 40, 101, 41, 40, 102, 41, 40, 103, 41,
427
  40, 104, 41, 40, 105, 41, 40, 106, 41, 40, 107, 41, 40, 108, 41, 40, 109, 41, 40,
428
  110, 41, 40, 111, 41, 40, 112, 41, 40, 113, 41, 40, 114, 41, 40, 115, 41, 40, 116,
429
  41, 40, 117, 41, 40, 118, 41, 40, 119, 41, 40, 120, 41, 40, 121, 41, 40, 122, 41,
430
  58, 58, 61, 61, 61, 10973, 824, 11312, 11313, 11314, 11315, 11316, 11317, 11318,
431
  11319, 11320, 11321, 11322, 11323, 11324, 11325, 11326, 11327, 11328, 11329, 11330,
432
  11331, 11332, 11333, 11334, 11335, 11336, 11337, 11338, 11339, 11340, 11341, 11342,
433
  11343, 11344, 11345, 11346, 11347, 11348, 11349, 11350, 11351, 11352, 11353, 11354,
434
  11355, 11356, 11357, 11358, 11359, 11361, 619, 7549, 637, 11368, 11370, 11372, 11379,
435
  11382, 575, 576, 11393, 11395, 11397, 11399, 11401, 11403, 11405, 11407, 11409,
436
  11411, 11413, 11415, 11417, 11419, 11421, 11423, 11425, 11427, 11429, 11431, 11433,
437
  11435, 11437, 11439, 11441, 11443, 11445, 11447, 11449, 11451, 11453, 11455, 11457,
438
  11459, 11461, 11463, 11465, 11467, 11469, 11471, 11473, 11475, 11477, 11479, 11481,
439
  11483, 11485, 11487, 11489, 11491, 11500, 11502, 11507, 11617, 27597, 40863, 19968,
440
  20008, 20022, 20031, 20057, 20101, 20108, 20128, 20154, 20799, 20837, 20843, 20866,
441
  20886, 20907, 20960, 20981, 20992, 21147, 21241, 21269, 21274, 21304, 21313, 21340,
442
  21353, 21378, 21430, 21448, 21475, 22231, 22303, 22763, 22786, 22794, 22805, 22823,
443
  22899, 23376, 23424, 23544, 23567, 23586, 23608, 23662, 23665, 24027, 24037, 24049,
444
  24062, 24178, 24186, 24191, 24308, 24318, 24331, 24339, 24400, 24417, 24435, 24515,
445
  25096, 25142, 25163, 25903, 25908, 25991, 26007, 26020, 26041, 26080, 26085, 26352,
446
  26376, 26408, 27424, 27490, 27513, 27571, 27595, 27604, 27611, 27663, 27668, 27700,
447
  28779, 29226, 29238, 29243, 29247, 29255, 29273, 29275, 29356, 29572, 29577, 29916,
448
  29926, 29976, 29983, 29992, 30000, 30091, 30098, 30326, 30333, 30382, 30399, 30446,
449
  30683, 30690, 30707, 31034, 31160, 31166, 31348, 31435, 31481, 31859, 31992, 32566,
450
  32593, 32650, 32701, 32769, 32780, 32786, 32819, 32895, 32905, 33251, 33258, 33267,
451
  33276, 33292, 33307, 33311, 33390, 33394, 33400, 34381, 34411, 34880, 34892, 34915,
452
  35198, 35211, 35282, 35328, 35895, 35910, 35925, 35960, 35997, 36196, 36208, 36275,
453
  36523, 36554, 36763, 36784, 36789, 37009, 37193, 37318, 37324, 37329, 38263, 38272,
454
  38428, 38582, 38585, 38632, 38737, 38750, 38754, 38761, 38859, 38893, 38899, 38913,
455
  39080, 39131, 39135, 39318, 39321, 39340, 39592, 39640, 39647, 39717, 39727, 39730,
456
  39740, 39770, 40165, 40565, 40575, 40613, 40635, 40643, 40653, 40657, 40697, 40701,
457
  40718, 40723, 40736, 40763, 40778, 40786, 40845, 40860, 40864, 46, 12306, 21316,
458
  21317, 32, 12441, 32, 12442, 12424, 12426, 12467, 12488, 4352, 4353, 4522, 4354,
459
  4524, 4525, 4355, 4356, 4357, 4528, 4529, 4530, 4531, 4532, 4533, 4378, 4358, 4359,
460
  4360, 4385, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4449, 4450,
461
  4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464,
462
  4465, 4466, 4467, 4468, 4469, 4372, 4373, 4551, 4552, 4556, 4558, 4563, 4567, 4569,
463
  4380, 4573, 4575, 4381, 4382, 4384, 4386, 4387, 4391, 4393, 4395, 4396, 4397, 4398,
464
  4399, 4402, 4406, 4416, 4423, 4428, 4593, 4594, 4439, 4440, 4441, 4484, 4485, 4488,
465
  4497, 4498, 4500, 4510, 4513, 19977, 22235, 19978, 20013, 19979, 30002, 19993, 19969,
466
  22825, 22320, 40, 4352, 41, 40, 4354, 41, 40, 4355, 41, 40, 4357, 41, 40, 4358,
467
  41, 40, 4359, 41, 40, 4361, 41, 40, 4363, 41, 40, 4364, 41, 40, 4366, 41, 40, 4367,
468
  41, 40, 4368, 41, 40, 4369, 41, 40, 4370, 41, 40, 44032, 41, 40, 45208, 41, 40,
469
  45796, 41, 40, 46972, 41, 40, 47560, 41, 40, 48148, 41, 40, 49324, 41, 40, 50500,
470
  41, 40, 51088, 41, 40, 52264, 41, 40, 52852, 41, 40, 53440, 41, 40, 54028, 41, 40,
471
  54616, 41, 40, 51452, 41, 40, 50724, 51204, 41, 40, 50724, 54980, 41, 40, 19968,
472
  41, 40, 20108, 41, 40, 19977, 41, 40, 22235, 41, 40, 20116, 41, 40, 20845, 41, 40,
473
  19971, 41, 40, 20843, 41, 40, 20061, 41, 40, 21313, 41, 40, 26376, 41, 40, 28779,
474
  41, 40, 27700, 41, 40, 26408, 41, 40, 37329, 41, 40, 22303, 41, 40, 26085, 41, 40,
475
  26666, 41, 40, 26377, 41, 40, 31038, 41, 40, 21517, 41, 40, 29305, 41, 40, 36001,
476
  41, 40, 31069, 41, 40, 21172, 41, 40, 20195, 41, 40, 21628, 41, 40, 23398, 41, 40,
477
  30435, 41, 40, 20225, 41, 40, 36039, 41, 40, 21332, 41, 40, 31085, 41, 40, 20241,
478
  41, 40, 33258, 41, 40, 33267, 41, 21839, 24188, 31631, 112, 116, 101, 50, 50, 50,
479
  52, 50, 53, 50, 54, 50, 55, 50, 56, 50, 57, 51, 48, 51, 51, 51, 52, 51, 53, 52280,
480
  44256, 51452, 51032, 50864, 31192, 30007, 36969, 20778, 21360, 27880, 38917, 20889,
481
  27491, 24038, 21491, 21307, 23447, 22812, 51, 54, 51, 55, 51, 56, 51, 57, 52, 48,
482
  52, 52, 52, 53, 52, 54, 52, 55, 52, 56, 52, 57, 53, 48, 49, 26376, 50, 26376, 51,
483
  26376, 52, 26376, 53, 26376, 54, 26376, 55, 26376, 56, 26376, 57, 26376, 49, 48,
484
  26376, 49, 49, 26376, 49, 50, 26376, 104, 103, 101, 114, 103, 101, 118, 108, 116,
485
  100, 12450, 12452, 12454, 12456, 12458, 12459, 12461, 12463, 12465, 12469, 12471,
486
  12473, 12475, 12477, 12479, 12481, 12484, 12486, 12490, 12491, 12492, 12493, 12494,
487
  12495, 12498, 12501, 12504, 12507, 12510, 12511, 12512, 12513, 12514, 12516, 12518,
488
  12520, 12521, 12522, 12523, 12524, 12525, 12527, 12528, 12529, 12530, 20196, 21644,
489
  12450, 12497, 12540, 12488, 12450, 12523, 12501, 12449, 12450, 12531, 12506, 12450,
490
  12450, 12540, 12523, 12452, 12491, 12531, 12464, 12452, 12531, 12481, 12454, 12457,
491
  12531, 12456, 12473, 12463, 12540, 12489, 12456, 12540, 12459, 12540, 12458, 12531,
492
  12473, 12458, 12540, 12512, 12459, 12452, 12522, 12459, 12521, 12483, 12488, 12459,
493
  12525, 12522, 12540, 12460, 12525, 12531, 12460, 12531, 12510, 12462, 12460, 12462,
494
  12491, 12540, 12461, 12517, 12522, 12540, 12462, 12523, 12480, 12540, 12461, 12525,
495
  12461, 12525, 12464, 12521, 12512, 12461, 12525, 12513, 12540, 12488, 12523, 12461,
496
  12525, 12527, 12483, 12488, 12464, 12521, 12512, 12488, 12531, 12463, 12523, 12476,
497
  12452, 12525, 12463, 12525, 12540, 12493, 12465, 12540, 12473, 12467, 12523, 12490,
498
  12467, 12540, 12509, 12469, 12452, 12463, 12523, 12469, 12531, 12481, 12540, 12512,
499
  12471, 12522, 12531, 12464, 12475, 12531, 12481, 12475, 12531, 12488, 12480, 12540,
500
  12473, 12487, 12471, 12489, 12523, 12490, 12494, 12494, 12483, 12488, 12495, 12452,
501
  12484, 12497, 12540, 12475, 12531, 12488, 12497, 12540, 12484, 12496, 12540, 12524,
502
  12523, 12500, 12450, 12473, 12488, 12523, 12500, 12463, 12523, 12500, 12467, 12499,
503
  12523, 12501, 12449, 12521, 12483, 12489, 12501, 12451, 12540, 12488, 12502, 12483,
504
  12471, 12455, 12523, 12501, 12521, 12531, 12504, 12463, 12479, 12540, 12523, 12506,
505
  12477, 12506, 12491, 12498, 12504, 12523, 12484, 12506, 12531, 12473, 12506, 12540,
506
  12472, 12505, 12540, 12479, 12509, 12452, 12531, 12488, 12508, 12523, 12488, 12507,
507
  12531, 12509, 12531, 12489, 12507, 12540, 12523, 12507, 12540, 12531, 12510, 12452,
508
  12463, 12525, 12510, 12452, 12523, 12510, 12483, 12495, 12510, 12523, 12463, 12510,
509
  12531, 12471, 12519, 12531, 12511, 12463, 12525, 12531, 12511, 12522, 12511, 12522,
510
  12496, 12540, 12523, 12513, 12460, 12513, 12460, 12488, 12531, 12516, 12540, 12489,
511
  12516, 12540, 12523, 12518, 12450, 12531, 12522, 12483, 12488, 12523, 12522, 12521,
512
  12523, 12500, 12540, 12523, 12540, 12502, 12523, 12524, 12512, 12524, 12531, 12488,
513
  12466, 12531, 48, 28857, 49, 28857, 50, 28857, 51, 28857, 52, 28857, 53, 28857,
514
  54, 28857, 55, 28857, 56, 28857, 57, 28857, 49, 48, 28857, 49, 49, 28857, 49, 50,
515
  28857, 49, 51, 28857, 49, 52, 28857, 49, 53, 28857, 49, 54, 28857, 49, 55, 28857,
516
  49, 56, 28857, 49, 57, 28857, 50, 48, 28857, 50, 49, 28857, 50, 50, 28857, 50, 51,
517
  28857, 50, 52, 28857, 104, 112, 97, 100, 97, 97, 117, 98, 97, 114, 111, 118, 112,
518
  99, 100, 109, 100, 109, 50, 100, 109, 51, 105, 117, 24179, 25104, 26157, 21644,
519
  22823, 27491, 26126, 27835, 26666, 24335, 20250, 31038, 110, 97, 956, 97, 109, 97,
520
  107, 97, 107, 98, 109, 98, 103, 98, 99, 97, 108, 107, 99, 97, 108, 112, 102, 110,
521
  102, 956, 102, 956, 103, 109, 103, 107, 103, 104, 122, 107, 104, 122, 109, 104,
522
  122, 116, 104, 122, 956, 108, 109, 108, 100, 108, 102, 109, 110, 109, 956, 109,
523
  109, 109, 99, 109, 107, 109, 109, 109, 50, 99, 109, 50, 107, 109, 50, 109, 109,
524
  51, 99, 109, 51, 107, 109, 51, 109, 8725, 115, 109, 8725, 115, 50, 107, 112, 97,
525
  109, 112, 97, 103, 112, 97, 114, 97, 100, 114, 97, 100, 8725, 115, 114, 97, 100,
526
  8725, 115, 50, 112, 115, 110, 115, 956, 115, 109, 115, 112, 118, 110, 118, 956,
527
  118, 109, 118, 107, 118, 112, 119, 110, 119, 956, 119, 109, 119, 107, 119, 107,
528
  969, 109, 969, 98, 113, 99, 8725, 107, 103, 100, 98, 103, 121, 104, 97, 105, 110,
529
  107, 107, 107, 116, 108, 110, 108, 111, 103, 108, 120, 109, 105, 108, 109, 111,
530
  108, 112, 104, 112, 112, 109, 112, 114, 115, 118, 119, 98, 118, 8725, 109, 97, 8725,
531
  109, 49, 26085, 50, 26085, 51, 26085, 52, 26085, 53, 26085, 54, 26085, 55, 26085,
532
  56, 26085, 57, 26085, 49, 48, 26085, 49, 49, 26085, 49, 50, 26085, 49, 51, 26085,
533
  49, 52, 26085, 49, 53, 26085, 49, 54, 26085, 49, 55, 26085, 49, 56, 26085, 49, 57,
534
  26085, 50, 48, 26085, 50, 49, 26085, 50, 50, 26085, 50, 51, 26085, 50, 52, 26085,
535
  50, 53, 26085, 50, 54, 26085, 50, 55, 26085, 50, 56, 26085, 50, 57, 26085, 51, 48,
536
  26085, 51, 49, 26085, 103, 97, 108, 42561, 42563, 42565, 42567, 42569, 42573, 42575,
537
  42577, 42579, 42581, 42583, 42585, 42587, 42589, 42591, 42593, 42595, 42597, 42599,
538
  42601, 42603, 42605, 42625, 42627, 42629, 42631, 42633, 42635, 42637, 42639, 42641,
539
  42643, 42645, 42647, 42649, 42651, 42787, 42789, 42791, 42793, 42795, 42797, 42799,
540
  42803, 42805, 42807, 42809, 42811, 42813, 42815, 42817, 42819, 42821, 42823, 42825,
541
  42827, 42829, 42831, 42833, 42835, 42837, 42839, 42841, 42843, 42845, 42847, 42849,
542
  42851, 42853, 42855, 42857, 42859, 42861, 42863, 42874, 42876, 7545, 42879, 42881,
543
  42883, 42885, 42887, 42892, 42897, 42899, 42903, 42905, 42907, 42909, 42911, 42913,
544
  42915, 42917, 42919, 42921, 620, 670, 647, 43859, 42933, 42935, 42937, 42939, 42941,
545
  42943, 42945, 42947, 42900, 7566, 42952, 42954, 612, 42957, 42959, 42961, 42963,
546
  42965, 42967, 42969, 42971, 411, 42998, 43831, 43858, 653, 5024, 5025, 5026, 5027,
547
  5028, 5029, 5030, 5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041,
548
  5042, 5043, 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055,
549
  5056, 5057, 5058, 5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, 5068, 5069,
550
  5070, 5071, 5072, 5073, 5074, 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083,
551
  5084, 5085, 5086, 5087, 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097,
552
  5098, 5099, 5100, 5101, 5102, 5103, 35912, 26356, 36040, 28369, 20018, 21477, 22865,
553
  21895, 22856, 25078, 30313, 32645, 34367, 34746, 35064, 37007, 27138, 27931, 28889,
554
  29662, 33853, 37226, 39409, 20098, 21365, 27396, 29211, 34349, 40478, 23888, 28651,
555
  34253, 35172, 25289, 33240, 34847, 24266, 26391, 28010, 29436, 37070, 20358, 20919,
556
  21214, 25796, 27347, 29200, 30439, 34310, 34396, 36335, 38706, 39791, 40442, 30860,
557
  31103, 32160, 33737, 37636, 35542, 22751, 24324, 31840, 32894, 29282, 30922, 36034,
558
  38647, 22744, 23650, 27155, 28122, 28431, 32047, 32311, 38475, 21202, 32907, 20956,
559
  20940, 31260, 32190, 33777, 38517, 35712, 25295, 35582, 20025, 23527, 24594, 29575,
560
  30064, 21271, 30971, 20415, 24489, 19981, 27852, 25976, 32034, 21443, 22622, 30465,
561
  33865, 35498, 27578, 27784, 25342, 33509, 25504, 30053, 20142, 20841, 20937, 26753,
562
  31975, 33391, 35538, 37327, 21237, 21570, 24300, 26053, 28670, 31018, 38317, 39530,
563
  40599, 40654, 26310, 27511, 36706, 24180, 24976, 25088, 25754, 28451, 29001, 29833,
564
  31178, 32244, 32879, 36646, 34030, 36899, 37706, 21015, 21155, 21693, 28872, 35010,
565
  24265, 24565, 25467, 27566, 31806, 29557, 22265, 23994, 24604, 29618, 29801, 32666,
566
  32838, 37428, 38646, 38728, 38936, 20363, 31150, 37300, 38584, 24801, 20102, 20698,
567
  23534, 23615, 26009, 29134, 30274, 34044, 36988, 26248, 38446, 21129, 26491, 26611,
568
  27969, 28316, 29705, 30041, 30827, 32016, 39006, 25134, 38520, 20523, 23833, 28138,
569
  36650, 24459, 24900, 26647, 38534, 21033, 21519, 23653, 26131, 26446, 26792, 27877,
570
  29702, 30178, 32633, 35023, 35041, 38626, 21311, 28346, 21533, 29136, 29848, 34298,
571
  38563, 40023, 40607, 26519, 28107, 33256, 31520, 31890, 29376, 28825, 35672, 20160,
572
  33590, 21050, 20999, 24230, 25299, 31958, 23429, 27934, 26292, 36667, 38477, 24275,
573
  20800, 21952, 22618, 26228, 20958, 29482, 30410, 31036, 31070, 31077, 31119, 38742,
574
  31934, 34322, 35576, 36920, 37117, 39151, 39164, 39208, 40372, 37086, 38583, 20398,
575
  20711, 20813, 21193, 21220, 21329, 21917, 22022, 22120, 22592, 22696, 23652, 24724,
576
  24936, 24974, 25074, 25935, 26082, 26257, 26757, 28023, 28186, 28450, 29038, 29227,
577
  29730, 30865, 31049, 31048, 31056, 31062, 31117, 31118, 31296, 31361, 31680, 32265,
578
  32321, 32626, 32773, 33261, 33401, 33879, 35088, 35222, 35585, 35641, 36051, 36104,
579
  36790, 38627, 38911, 38971, 24693, 148206, 33304, 20006, 20917, 20840, 20352, 20805,
580
  20864, 21191, 21242, 21845, 21913, 21986, 22707, 22852, 22868, 23138, 23336, 24274,
581
  24281, 24425, 24493, 24792, 24910, 24840, 24928, 25140, 25540, 25628, 25682, 25942,
582
  26395, 26454, 28379, 28363, 28702, 30631, 29237, 29359, 29809, 29958, 30011, 30237,
583
  30239, 30427, 30452, 30538, 30528, 30924, 31409, 31867, 32091, 32574, 33618, 33775,
584
  34681, 35137, 35206, 35519, 35531, 35565, 35722, 36664, 36978, 37273, 37494, 38524,
585
  38875, 38923, 39698, 141386, 141380, 144341, 15261, 16408, 16441, 152137, 154832,
586
  163539, 40771, 40846, 102, 102, 102, 105, 102, 108, 102, 102, 108, 1396, 1398, 1396,
587
  1381, 1396, 1387, 1406, 1398, 1396, 1389, 1497, 1460, 1522, 1463, 1506, 1492, 1499,
588
  1500, 1501, 1512, 1514, 1513, 1473, 1513, 1474, 1513, 1468, 1473, 1513, 1468, 1474,
589
  1488, 1463, 1488, 1464, 1488, 1468, 1489, 1468, 1490, 1468, 1491, 1468, 1492, 1468,
590
  1493, 1468, 1494, 1468, 1496, 1468, 1497, 1468, 1498, 1468, 1499, 1468, 1500, 1468,
591
  1502, 1468, 1504, 1468, 1505, 1468, 1507, 1468, 1508, 1468, 1510, 1468, 1511, 1468,
592
  1512, 1468, 1514, 1468, 1493, 1465, 1489, 1471, 1499, 1471, 1508, 1471, 1488, 1500,
593
  1649, 1659, 1662, 1664, 1658, 1663, 1657, 1700, 1702, 1668, 1667, 1670, 1671, 1677,
594
  1676, 1678, 1672, 1688, 1681, 1705, 1711, 1715, 1713, 1722, 1723, 1728, 1729, 1726,
595
  1746, 1747, 1709, 1734, 1736, 1739, 1733, 1737, 1744, 1609, 1574, 1575, 1574, 1749,
596
  1574, 1608, 1574, 1735, 1574, 1734, 1574, 1736, 1574, 1744, 1574, 1609, 1740, 1574,
597
  1580, 1574, 1581, 1574, 1605, 1574, 1610, 1576, 1580, 1576, 1581, 1576, 1582, 1576,
598
  1605, 1576, 1609, 1576, 1610, 1578, 1580, 1578, 1581, 1578, 1582, 1578, 1605, 1578,
599
  1609, 1578, 1610, 1579, 1580, 1579, 1605, 1579, 1609, 1579, 1610, 1580, 1581, 1580,
600
  1605, 1581, 1605, 1582, 1580, 1582, 1581, 1582, 1605, 1587, 1580, 1587, 1581, 1587,
601
  1582, 1587, 1605, 1589, 1581, 1589, 1605, 1590, 1580, 1590, 1581, 1590, 1582, 1590,
602
  1605, 1591, 1581, 1591, 1605, 1592, 1605, 1593, 1580, 1593, 1605, 1594, 1580, 1594,
603
  1605, 1601, 1580, 1601, 1581, 1601, 1582, 1601, 1605, 1601, 1609, 1601, 1610, 1602,
604
  1581, 1602, 1605, 1602, 1609, 1602, 1610, 1603, 1575, 1603, 1580, 1603, 1581, 1603,
605
  1582, 1603, 1604, 1603, 1605, 1603, 1609, 1603, 1610, 1604, 1580, 1604, 1581, 1604,
606
  1582, 1604, 1605, 1604, 1609, 1604, 1610, 1605, 1580, 1605, 1605, 1605, 1609, 1605,
607
  1610, 1606, 1580, 1606, 1581, 1606, 1582, 1606, 1605, 1606, 1609, 1606, 1610, 1607,
608
  1580, 1607, 1605, 1607, 1609, 1607, 1610, 1610, 1581, 1610, 1582, 1610, 1609, 1584,
609
  1648, 1585, 1648, 1609, 1648, 32, 1612, 1617, 32, 1613, 1617, 32, 1614, 1617, 32,
610
  1615, 1617, 32, 1616, 1617, 32, 1617, 1648, 1574, 1585, 1574, 1586, 1574, 1606,
611
  1576, 1585, 1576, 1586, 1576, 1606, 1578, 1585, 1578, 1586, 1578, 1606, 1579, 1585,
612
  1579, 1586, 1579, 1606, 1605, 1575, 1606, 1585, 1606, 1586, 1606, 1606, 1610, 1585,
613
  1610, 1586, 1574, 1582, 1574, 1607, 1576, 1607, 1578, 1607, 1589, 1582, 1604, 1607,
614
  1606, 1607, 1607, 1648, 1579, 1607, 1587, 1607, 1588, 1605, 1588, 1607, 1600, 1614,
615
  1617, 1600, 1615, 1617, 1600, 1616, 1617, 1591, 1609, 1591, 1610, 1593, 1609, 1593,
616
  1610, 1594, 1609, 1594, 1610, 1587, 1609, 1587, 1610, 1588, 1609, 1588, 1610, 1581,
617
  1609, 1580, 1609, 1580, 1610, 1582, 1609, 1589, 1609, 1589, 1610, 1590, 1609, 1590,
618
  1610, 1588, 1580, 1588, 1581, 1588, 1582, 1588, 1585, 1587, 1585, 1589, 1585, 1590,
619
  1585, 1575, 1611, 1578, 1580, 1605, 1578, 1581, 1580, 1578, 1581, 1605, 1578, 1582,
620
  1605, 1578, 1605, 1580, 1578, 1605, 1581, 1578, 1605, 1582, 1581, 1605, 1610, 1581,
621
  1605, 1609, 1587, 1581, 1580, 1587, 1580, 1581, 1587, 1580, 1609, 1587, 1605, 1581,
622
  1587, 1605, 1580, 1587, 1605, 1605, 1589, 1581, 1581, 1589, 1605, 1605, 1588, 1581,
623
  1605, 1588, 1580, 1610, 1588, 1605, 1582, 1588, 1605, 1605, 1590, 1581, 1609, 1590,
624
  1582, 1605, 1591, 1605, 1581, 1591, 1605, 1605, 1591, 1605, 1610, 1593, 1580, 1605,
625
  1593, 1605, 1605, 1593, 1605, 1609, 1594, 1605, 1605, 1594, 1605, 1610, 1594, 1605,
626
  1609, 1601, 1582, 1605, 1602, 1605, 1581, 1602, 1605, 1605, 1604, 1581, 1605, 1604,
627
  1581, 1610, 1604, 1581, 1609, 1604, 1580, 1580, 1604, 1582, 1605, 1604, 1605, 1581,
628
  1605, 1581, 1580, 1605, 1581, 1610, 1605, 1580, 1581, 1605, 1582, 1605, 1605, 1580,
629
  1582, 1607, 1605, 1580, 1607, 1605, 1605, 1606, 1581, 1605, 1606, 1581, 1609, 1606,
630
  1580, 1605, 1606, 1580, 1609, 1606, 1605, 1610, 1606, 1605, 1609, 1610, 1605, 1605,
631
  1576, 1582, 1610, 1578, 1580, 1610, 1578, 1580, 1609, 1578, 1582, 1610, 1578, 1582,
632
  1609, 1578, 1605, 1610, 1578, 1605, 1609, 1580, 1605, 1610, 1580, 1581, 1609, 1580,
633
  1605, 1609, 1587, 1582, 1609, 1589, 1581, 1610, 1588, 1581, 1610, 1590, 1581, 1610,
634
  1604, 1580, 1610, 1604, 1605, 1610, 1610, 1580, 1610, 1610, 1605, 1610, 1605, 1605,
635
  1610, 1602, 1605, 1610, 1606, 1581, 1610, 1593, 1605, 1610, 1603, 1605, 1610, 1606,
636
  1580, 1581, 1605, 1582, 1610, 1604, 1580, 1605, 1603, 1605, 1605, 1580, 1581, 1610,
637
  1581, 1580, 1610, 1605, 1580, 1610, 1601, 1605, 1610, 1576, 1581, 1610, 1587, 1582,
638
  1610, 1606, 1580, 1610, 1589, 1604, 1746, 1602, 1604, 1746, 1575, 1604, 1604, 1607,
639
  1575, 1603, 1576, 1585, 1605, 1581, 1605, 1583, 1589, 1604, 1593, 1605, 1585, 1587,
640
  1608, 1604, 1593, 1604, 1610, 1607, 1608, 1587, 1604, 1605, 1589, 1604, 1609, 1589,
641
  1604, 1609, 32, 1575, 1604, 1604, 1607, 32, 1593, 1604, 1610, 1607, 32, 1608, 1587,
642
  1604, 1605, 1580, 1604, 32, 1580, 1604, 1575, 1604, 1607, 1585, 1740, 1575, 1604,
643
  44, 12289, 12310, 12311, 8212, 8211, 95, 123, 125, 12308, 12309, 12304, 12305, 12298,
644
  12299, 12300, 12301, 12302, 12303, 91, 93, 35, 38, 42, 45, 60, 62, 92, 36, 37, 64,
645
  32, 1611, 1600, 1611, 1600, 1617, 32, 1618, 1600, 1618, 1569, 1570, 1571, 1572,
646
  1573, 1577, 1604, 1570, 1604, 1571, 1604, 1573, 34, 39, 94, 124, 126, 10629, 10630,
647
  12539, 12453, 12515, 162, 163, 172, 166, 165, 8361, 9474, 8592, 8593, 8594, 8595,
648
  9632, 9675, 66600, 66601, 66602, 66603, 66604, 66605, 66606, 66607, 66608, 66609,
649
  66610, 66611, 66612, 66613, 66614, 66615, 66616, 66617, 66618, 66619, 66620, 66621,
650
  66622, 66623, 66624, 66625, 66626, 66627, 66628, 66629, 66630, 66631, 66632, 66633,
651
  66634, 66635, 66636, 66637, 66638, 66639, 66776, 66777, 66778, 66779, 66780, 66781,
652
  66782, 66783, 66784, 66785, 66786, 66787, 66788, 66789, 66790, 66791, 66792, 66793,
653
  66794, 66795, 66796, 66797, 66798, 66799, 66800, 66801, 66802, 66803, 66804, 66805,
654
  66806, 66807, 66808, 66809, 66810, 66811, 66967, 66968, 66969, 66970, 66971, 66972,
655
  66973, 66974, 66975, 66976, 66977, 66979, 66980, 66981, 66982, 66983, 66984, 66985,
656
  66986, 66987, 66988, 66989, 66990, 66991, 66992, 66993, 66995, 66996, 66997, 66998,
657
  66999, 67000, 67001, 67003, 67004, 720, 721, 665, 675, 43878, 677, 676, 7569, 600,
658
  606, 681, 610, 667, 668, 615, 644, 682, 683, 122628, 42894, 622, 122629, 654, 122630,
659
  630, 631, 634, 122632, 638, 680, 678, 43879, 679, 11377, 655, 673, 674, 664, 448,
660
  449, 450, 122634, 122654, 68800, 68801, 68802, 68803, 68804, 68805, 68806, 68807,
661
  68808, 68809, 68810, 68811, 68812, 68813, 68814, 68815, 68816, 68817, 68818, 68819,
662
  68820, 68821, 68822, 68823, 68824, 68825, 68826, 68827, 68828, 68829, 68830, 68831,
663
  68832, 68833, 68834, 68835, 68836, 68837, 68838, 68839, 68840, 68841, 68842, 68843,
664
  68844, 68845, 68846, 68847, 68848, 68849, 68850, 68976, 68977, 68978, 68979, 68980,
665
  68981, 68982, 68983, 68984, 68985, 68986, 68987, 68988, 68989, 68990, 68991, 68992,
666
  68993, 68994, 68995, 68996, 68997, 71872, 71873, 71874, 71875, 71876, 71877, 71878,
667
  71879, 71880, 71881, 71882, 71883, 71884, 71885, 71886, 71887, 71888, 71889, 71890,
668
  71891, 71892, 71893, 71894, 71895, 71896, 71897, 71898, 71899, 71900, 71901, 71902,
669
  71903, 93792, 93793, 93794, 93795, 93796, 93797, 93798, 93799, 93800, 93801, 93802,
670
  93803, 93804, 93805, 93806, 93807, 93808, 93809, 93810, 93811, 93812, 93813, 93814,
671
  93815, 93816, 93817, 93818, 93819, 93820, 93821, 93822, 93823, 93883, 93884, 93885,
672
  93886, 93887, 93888, 93889, 93890, 93891, 93892, 93893, 93894, 93895, 93896, 93897,
673
  93898, 93899, 93900, 93901, 93902, 93903, 93904, 93905, 93906, 93907, 119127, 119141,
674
  119128, 119141, 119128, 119141, 119150, 119128, 119141, 119151, 119128, 119141,
675
  119152, 119128, 119141, 119153, 119128, 119141, 119154, 119225, 119141, 119226,
676
  119141, 119225, 119141, 119150, 119226, 119141, 119150, 119225, 119141, 119151,
677
  119226, 119141, 119151, 305, 567, 8711, 8706, 125218, 125219, 125220, 125221, 125222,
678
  125223, 125224, 125225, 125226, 125227, 125228, 125229, 125230, 125231, 125232,
679
  125233, 125234, 125235, 125236, 125237, 125238, 125239, 125240, 125241, 125242,
680
  125243, 125244, 125245, 125246, 125247, 125248, 125249, 125250, 125251, 1646, 1697,
681
  1647, 48, 44, 49, 44, 50, 44, 51, 44, 52, 44, 53, 44, 54, 44, 55, 44, 56, 44, 57,
682
  44, 12308, 115, 12309, 119, 122, 104, 118, 115, 100, 115, 115, 112, 112, 118, 119,
683
  99, 109, 114, 100, 106, 12411, 12363, 12467, 12467, 23383, 21452, 22810, 35299,
684
  20132, 26144, 28961, 21069, 24460, 20877, 26032, 21021, 32066, 36009, 22768, 21561,
685
  28436, 25237, 25429, 36938, 25351, 25171, 31105, 31354, 21512, 28288, 30003, 21106,
686
  21942, 37197, 12308, 26412, 12309, 12308, 19977, 12309, 12308, 20108, 12309, 12308,
687
  23433, 12309, 12308, 28857, 12309, 12308, 25171, 12309, 12308, 30423, 12309, 12308,
688
  21213, 12309, 12308, 25943, 12309, 24471, 21487, 20029, 20024, 20033, 131362, 20320,
689
  20411, 20482, 20602, 20633, 20687, 13470, 132666, 20820, 20836, 20855, 132380, 13497,
690
  20839, 132427, 20887, 20900, 20172, 20908, 168415, 20995, 13535, 21051, 21062, 21111,
691
  13589, 21253, 21254, 21321, 21338, 21363, 21373, 21375, 133676, 28784, 21450, 21471,
692
  133987, 21483, 21489, 21510, 21662, 21560, 21576, 21608, 21666, 21750, 21776, 21843,
693
  21859, 21892, 21931, 21939, 21954, 22294, 22295, 22097, 22132, 22766, 22478, 22516,
694
  22541, 22411, 22578, 22577, 22700, 136420, 22770, 22775, 22790, 22818, 22882, 136872,
695
  136938, 23020, 23067, 23079, 23000, 23142, 14062, 14076, 23304, 23358, 137672, 23491,
696
  23512, 23539, 138008, 23551, 23558, 24403, 14209, 23648, 23744, 23693, 138724, 23875,
697
  138726, 23918, 23915, 23932, 24033, 24034, 14383, 24061, 24104, 24125, 24169, 14434,
698
  139651, 14460, 24240, 24243, 24246, 172946, 140081, 33281, 24354, 14535, 144056,
699
  156122, 24418, 24427, 14563, 24474, 24525, 24535, 24569, 24705, 14650, 14620, 141012,
700
  24775, 24904, 24908, 24954, 25010, 24996, 25007, 25054, 25115, 25181, 25265, 25300,
701
  25424, 142092, 25405, 25340, 25448, 25475, 25572, 142321, 25634, 25541, 25513, 14894,
702
  25705, 25726, 25757, 25719, 14956, 25964, 143370, 26083, 26360, 26185, 15129, 15112,
703
  15076, 20882, 20885, 26368, 26268, 32941, 17369, 26401, 26462, 26451, 144323, 15177,
704
  26618, 26501, 26706, 144493, 26766, 26655, 26900, 26946, 27043, 27114, 27304, 145059,
705
  27355, 15384, 27425, 145575, 27476, 15438, 27506, 27551, 27579, 146061, 138507,
706
  146170, 27726, 146620, 27839, 27853, 27751, 27926, 27966, 28009, 28024, 28037, 146718,
707
  27956, 28207, 28270, 15667, 28359, 147153, 28153, 28526, 147294, 147342, 28614,
708
  28729, 28699, 15766, 28746, 28797, 28791, 28845, 132389, 28997, 148067, 29084, 148395,
709
  29224, 29264, 149000, 29312, 29333, 149301, 149524, 29562, 29579, 16044, 29605,
710
  16056, 29767, 29788, 29829, 29898, 16155, 29988, 150582, 30014, 150674, 139679,
711
  30224, 151457, 151480, 151620, 16380, 16392, 151795, 151794, 151833, 151859, 30494,
712
  30495, 30603, 16454, 16534, 152605, 30798, 16611, 153126, 153242, 153285, 31211,
713
  16687, 31306, 31311, 153980, 154279, 31470, 16898, 154539, 31686, 31689, 16935,
714
  154752, 31954, 17056, 31976, 31971, 32000, 155526, 32099, 17153, 32199, 32258, 32325,
715
  17204, 156200, 156231, 17241, 156377, 32634, 156478, 32661, 32762, 156890, 156963,
716
  32864, 157096, 32880, 144223, 17365, 32946, 33027, 17419, 33086, 23221, 157607,
717
  157621, 144275, 144284, 33284, 36766, 17515, 33425, 33419, 33437, 21171, 33457,
718
  33459, 33469, 33510, 158524, 33565, 33635, 33709, 33571, 33725, 33767, 33619, 33738,
719
  33740, 33756, 158774, 159083, 158933, 17707, 34033, 34035, 34070, 160714, 34148,
720
  159532, 17757, 17761, 159665, 159954, 17771, 34384, 34407, 34409, 34473, 34440,
721
  34574, 34530, 34600, 34667, 34694, 17879, 34785, 34817, 17913, 34912, 161383, 35031,
722
  35038, 17973, 35066, 13499, 161966, 162150, 18110, 18119, 35488, 162984, 36011,
723
  36033, 36123, 36215, 163631, 133124, 36299, 36284, 36336, 133342, 36564, 165330,
724
  165357, 37012, 37105, 37137, 165678, 37147, 37432, 37591, 37592, 37500, 37881, 37909,
725
  166906, 38283, 18837, 38327, 167287, 18918, 38595, 23986, 38691, 168261, 168474,
726
  19054, 19062, 38880, 168970, 19122, 169110, 38953, 169398, 39138, 19251, 39209,
727
  39335, 39362, 39422, 19406, 170800, 40000, 40189, 19662, 19693, 40295, 172238, 19704,
728
  172293, 172558, 172689, 19798, 40702, 40709, 40719, 40726, 173568,
729
730
};
731
const uint32_t table[8198][2] =
732
{
733
  {0, 1}, {65, 16777219}, {66, 16777475}, {67, 16777731},
734
  {68, 16777987}, {69, 16778243}, {70, 16778499}, {71, 16778755},
735
  {72, 16779011}, {73, 16779267}, {74, 16779523}, {75, 16779779},
736
  {76, 16780035}, {77, 16780291}, {78, 16780547}, {79, 16780803},
737
  {80, 16781059}, {81, 16781315}, {82, 16781571}, {83, 16781827},
738
  {84, 16782083}, {85, 16782339}, {86, 16782595}, {87, 16782851},
739
  {88, 16783107}, {89, 16783363}, {90, 16783619}, {91, 1},
740
  {128, 2}, {160, 16783875}, {161, 1}, {168, 33561347},
741
  {169, 1}, {170, 16777219}, {171, 1}, {173, 0},
742
  {174, 1}, {175, 33561859}, {176, 1}, {178, 16785155},
743
  {179, 16785411}, {180, 33562883}, {181, 16786179}, {182, 1},
744
  {184, 33563651}, {185, 16786947}, {186, 16780803}, {187, 1},
745
  {188, 50341635}, {189, 50342403}, {190, 50343171}, {191, 1},
746
  {192, 16789507}, {193, 16789763}, {194, 16790019}, {195, 16790275},
747
  {196, 16790531}, {197, 16790787}, {198, 16791043}, {199, 16791299},
748
  {200, 16791555}, {201, 16791811}, {202, 16792067}, {203, 16792323},
749
  {204, 16792579}, {205, 16792835}, {206, 16793091}, {207, 16793347},
750
  {208, 16793603}, {209, 16793859}, {210, 16794115}, {211, 16794371},
751
  {212, 16794627}, {213, 16794883}, {214, 16795139}, {215, 1},
752
  {216, 16795395}, {217, 16795651}, {218, 16795907}, {219, 16796163},
753
  {220, 16796419}, {221, 16796675}, {222, 16796931}, {223, 1},
754
  {256, 16797187}, {257, 1}, {258, 16797443}, {259, 1},
755
  {260, 16797699}, {261, 1}, {262, 16797955}, {263, 1},
756
  {264, 16798211}, {265, 1}, {266, 16798467}, {267, 1},
757
  {268, 16798723}, {269, 1}, {270, 16798979}, {271, 1},
758
  {272, 16799235}, {273, 1}, {274, 16799491}, {275, 1},
759
  {276, 16799747}, {277, 1}, {278, 16800003}, {279, 1},
760
  {280, 16800259}, {281, 1}, {282, 16800515}, {283, 1},
761
  {284, 16800771}, {285, 1}, {286, 16801027}, {287, 1},
762
  {288, 16801283}, {289, 1}, {290, 16801539}, {291, 1},
763
  {292, 16801795}, {293, 1}, {294, 16802051}, {295, 1},
764
  {296, 16802307}, {297, 1}, {298, 16802563}, {299, 1},
765
  {300, 16802819}, {301, 1}, {302, 16803075}, {303, 1},
766
  {304, 33580547}, {305, 1}, {306, 33556483}, {308, 16803843},
767
  {309, 1}, {310, 16804099}, {311, 1}, {313, 16804355},
768
  {314, 1}, {315, 16804611}, {316, 1}, {317, 16804867},
769
  {318, 1}, {319, 33582339}, {321, 16805635}, {322, 1},
770
  {323, 16805891}, {324, 1}, {325, 16806147}, {326, 1},
771
  {327, 16806403}, {328, 1}, {329, 33583875}, {330, 16807171},
772
  {331, 1}, {332, 16807427}, {333, 1}, {334, 16807683},
773
  {335, 1}, {336, 16807939}, {337, 1}, {338, 16808195},
774
  {339, 1}, {340, 16808451}, {341, 1}, {342, 16808707},
775
  {343, 1}, {344, 16808963}, {345, 1}, {346, 16809219},
776
  {347, 1}, {348, 16809475}, {349, 1}, {350, 16809731},
777
  {351, 1}, {352, 16809987}, {353, 1}, {354, 16810243},
778
  {355, 1}, {356, 16810499}, {357, 1}, {358, 16810755},
779
  {359, 1}, {360, 16811011}, {361, 1}, {362, 16811267},
780
  {363, 1}, {364, 16811523}, {365, 1}, {366, 16811779},
781
  {367, 1}, {368, 16812035}, {369, 1}, {370, 16812291},
782
  {371, 1}, {372, 16812547}, {373, 1}, {374, 16812803},
783
  {375, 1}, {376, 16813059}, {377, 16813315}, {378, 1},
784
  {379, 16813571}, {380, 1}, {381, 16813827}, {382, 1},
785
  {383, 16781827}, {384, 1}, {385, 16814083}, {386, 16814339},
786
  {387, 1}, {388, 16814595}, {389, 1}, {390, 16814851},
787
  {391, 16815107}, {392, 1}, {393, 16815363}, {394, 16815619},
788
  {395, 16815875}, {396, 1}, {398, 16816131}, {399, 16816387},
789
  {400, 16816643}, {401, 16816899}, {402, 1}, {403, 16817155},
790
  {404, 16817411}, {405, 1}, {406, 16817667}, {407, 16817923},
791
  {408, 16818179}, {409, 1}, {412, 16818435}, {413, 16818691},
792
  {414, 1}, {415, 16818947}, {416, 16819203}, {417, 1},
793
  {418, 16819459}, {419, 1}, {420, 16819715}, {421, 1},
794
  {422, 16819971}, {423, 16820227}, {424, 1}, {425, 16820483},
795
  {426, 1}, {428, 16820739}, {429, 1}, {430, 16820995},
796
  {431, 16821251}, {432, 1}, {433, 16821507}, {434, 16821763},
797
  {435, 16822019}, {436, 1}, {437, 16822275}, {438, 1},
798
  {439, 16822531}, {440, 16822787}, {441, 1}, {444, 16823043},
799
  {445, 1}, {452, 33600515}, {455, 33601027}, {458, 33601539},
800
  {461, 16824835}, {462, 1}, {463, 16825091}, {464, 1},
801
  {465, 16825347}, {466, 1}, {467, 16825603}, {468, 1},
802
  {469, 16825859}, {470, 1}, {471, 16826115}, {472, 1},
803
  {473, 16826371}, {474, 1}, {475, 16826627}, {476, 1},
804
  {478, 16826883}, {479, 1}, {480, 16827139}, {481, 1},
805
  {482, 16827395}, {483, 1}, {484, 16827651}, {485, 1},
806
  {486, 16827907}, {487, 1}, {488, 16828163}, {489, 1},
807
  {490, 16828419}, {491, 1}, {492, 16828675}, {493, 1},
808
  {494, 16828931}, {495, 1}, {497, 33606403}, {500, 16829699},
809
  {501, 1}, {502, 16829955}, {503, 16830211}, {504, 16830467},
810
  {505, 1}, {506, 16830723}, {507, 1}, {508, 16830979},
811
  {509, 1}, {510, 16831235}, {511, 1}, {512, 16831491},
812
  {513, 1}, {514, 16831747}, {515, 1}, {516, 16832003},
813
  {517, 1}, {518, 16832259}, {519, 1}, {520, 16832515},
814
  {521, 1}, {522, 16832771}, {523, 1}, {524, 16833027},
815
  {525, 1}, {526, 16833283}, {527, 1}, {528, 16833539},
816
  {529, 1}, {530, 16833795}, {531, 1}, {532, 16834051},
817
  {533, 1}, {534, 16834307}, {535, 1}, {536, 16834563},
818
  {537, 1}, {538, 16834819}, {539, 1}, {540, 16835075},
819
  {541, 1}, {542, 16835331}, {543, 1}, {544, 16835587},
820
  {545, 1}, {546, 16835843}, {547, 1}, {548, 16836099},
821
  {549, 1}, {550, 16836355}, {551, 1}, {552, 16836611},
822
  {553, 1}, {554, 16836867}, {555, 1}, {556, 16837123},
823
  {557, 1}, {558, 16837379}, {559, 1}, {560, 16837635},
824
  {561, 1}, {562, 16837891}, {563, 1}, {570, 16838147},
825
  {571, 16838403}, {572, 1}, {573, 16838659}, {574, 16838915},
826
  {575, 1}, {577, 16839171}, {578, 1}, {579, 16839427},
827
  {580, 16839683}, {581, 16839939}, {582, 16840195}, {583, 1},
828
  {584, 16840451}, {585, 1}, {586, 16840707}, {587, 1},
829
  {588, 16840963}, {589, 1}, {590, 16841219}, {591, 1},
830
  {688, 16779011}, {689, 16841475}, {690, 16779523}, {691, 16781571},
831
  {692, 16841731}, {693, 16841987}, {694, 16842243}, {695, 16782851},
832
  {696, 16783363}, {697, 1}, {728, 33619715}, {729, 33620227},
833
  {730, 33620739}, {731, 33621251}, {732, 33621763}, {733, 33622275},
834
  {734, 1}, {736, 16817411}, {737, 16780035}, {738, 16781827},
835
  {739, 16783107}, {740, 16845571}, {741, 1}, {832, 16845827},
836
  {833, 16785923}, {834, 1}, {835, 16846083}, {836, 33623555},
837
  {837, 16846851}, {838, 1}, {847, 0}, {848, 1},
838
  {880, 16847107}, {881, 1}, {882, 16847363}, {883, 1},
839
  {884, 16847619}, {885, 1}, {886, 16847875}, {887, 1},
840
  {888, 2}, {890, 33625347}, {891, 1}, {894, 16848643},
841
  {895, 16848899}, {896, 2}, {900, 33562883}, {901, 50403587},
842
  {902, 16849923}, {903, 16805379}, {904, 16850179}, {905, 16850435},
843
  {906, 16850691}, {907, 2}, {908, 16850947}, {909, 2},
844
  {910, 16851203}, {911, 16851459}, {912, 1}, {913, 16851715},
845
  {914, 16851971}, {915, 16852227}, {916, 16852483}, {917, 16852739},
846
  {918, 16852995}, {919, 16853251}, {920, 16853507}, {921, 16846851},
847
  {922, 16853763}, {923, 16854019}, {924, 16786179}, {925, 16854275},
848
  {926, 16854531}, {927, 16854787}, {928, 16855043}, {929, 16855299},
849
  {930, 2}, {931, 16855555}, {932, 16855811}, {933, 16856067},
850
  {934, 16856323}, {935, 16856579}, {936, 16856835}, {937, 16857091},
851
  {938, 16857347}, {939, 16857603}, {940, 1}, {975, 16857859},
852
  {976, 16851971}, {977, 16853507}, {978, 16856067}, {979, 16851203},
853
  {980, 16857603}, {981, 16856323}, {982, 16855043}, {983, 1},
854
  {984, 16858115}, {985, 1}, {986, 16858371}, {987, 1},
855
  {988, 16858627}, {989, 1}, {990, 16858883}, {991, 1},
856
  {992, 16859139}, {993, 1}, {994, 16859395}, {995, 1},
857
  {996, 16859651}, {997, 1}, {998, 16859907}, {999, 1},
858
  {1000, 16860163}, {1001, 1}, {1002, 16860419}, {1003, 1},
859
  {1004, 16860675}, {1005, 1}, {1006, 16860931}, {1007, 1},
860
  {1008, 16853763}, {1009, 16855299}, {1010, 16855555}, {1011, 1},
861
  {1012, 16853507}, {1013, 16852739}, {1014, 1}, {1015, 16861187},
862
  {1016, 1}, {1017, 16855555}, {1018, 16861443}, {1019, 1},
863
  {1021, 16861699}, {1022, 16861955}, {1023, 16862211}, {1024, 16862467},
864
  {1025, 16862723}, {1026, 16862979}, {1027, 16863235}, {1028, 16863491},
865
  {1029, 16863747}, {1030, 16864003}, {1031, 16864259}, {1032, 16864515},
866
  {1033, 16864771}, {1034, 16865027}, {1035, 16865283}, {1036, 16865539},
867
  {1037, 16865795}, {1038, 16866051}, {1039, 16866307}, {1040, 16866563},
868
  {1041, 16866819}, {1042, 16867075}, {1043, 16867331}, {1044, 16867587},
869
  {1045, 16867843}, {1046, 16868099}, {1047, 16868355}, {1048, 16868611},
870
  {1049, 16868867}, {1050, 16869123}, {1051, 16869379}, {1052, 16869635},
871
  {1053, 16869891}, {1054, 16870147}, {1055, 16870403}, {1056, 16870659},
872
  {1057, 16870915}, {1058, 16871171}, {1059, 16871427}, {1060, 16871683},
873
  {1061, 16871939}, {1062, 16872195}, {1063, 16872451}, {1064, 16872707},
874
  {1065, 16872963}, {1066, 16873219}, {1067, 16873475}, {1068, 16873731},
875
  {1069, 16873987}, {1070, 16874243}, {1071, 16874499}, {1072, 1},
876
  {1120, 16874755}, {1121, 1}, {1122, 16875011}, {1123, 1},
877
  {1124, 16875267}, {1125, 1}, {1126, 16875523}, {1127, 1},
878
  {1128, 16875779}, {1129, 1}, {1130, 16876035}, {1131, 1},
879
  {1132, 16876291}, {1133, 1}, {1134, 16876547}, {1135, 1},
880
  {1136, 16876803}, {1137, 1}, {1138, 16877059}, {1139, 1},
881
  {1140, 16877315}, {1141, 1}, {1142, 16877571}, {1143, 1},
882
  {1144, 16877827}, {1145, 1}, {1146, 16878083}, {1147, 1},
883
  {1148, 16878339}, {1149, 1}, {1150, 16878595}, {1151, 1},
884
  {1152, 16878851}, {1153, 1}, {1162, 16879107}, {1163, 1},
885
  {1164, 16879363}, {1165, 1}, {1166, 16879619}, {1167, 1},
886
  {1168, 16879875}, {1169, 1}, {1170, 16880131}, {1171, 1},
887
  {1172, 16880387}, {1173, 1}, {1174, 16880643}, {1175, 1},
888
  {1176, 16880899}, {1177, 1}, {1178, 16881155}, {1179, 1},
889
  {1180, 16881411}, {1181, 1}, {1182, 16881667}, {1183, 1},
890
  {1184, 16881923}, {1185, 1}, {1186, 16882179}, {1187, 1},
891
  {1188, 16882435}, {1189, 1}, {1190, 16882691}, {1191, 1},
892
  {1192, 16882947}, {1193, 1}, {1194, 16883203}, {1195, 1},
893
  {1196, 16883459}, {1197, 1}, {1198, 16883715}, {1199, 1},
894
  {1200, 16883971}, {1201, 1}, {1202, 16884227}, {1203, 1},
895
  {1204, 16884483}, {1205, 1}, {1206, 16884739}, {1207, 1},
896
  {1208, 16884995}, {1209, 1}, {1210, 16885251}, {1211, 1},
897
  {1212, 16885507}, {1213, 1}, {1214, 16885763}, {1215, 1},
898
  {1216, 16886019}, {1217, 16886275}, {1218, 1}, {1219, 16886531},
899
  {1220, 1}, {1221, 16886787}, {1222, 1}, {1223, 16887043},
900
  {1224, 1}, {1225, 16887299}, {1226, 1}, {1227, 16887555},
901
  {1228, 1}, {1229, 16887811}, {1230, 1}, {1232, 16888067},
902
  {1233, 1}, {1234, 16888323}, {1235, 1}, {1236, 16888579},
903
  {1237, 1}, {1238, 16888835}, {1239, 1}, {1240, 16889091},
904
  {1241, 1}, {1242, 16889347}, {1243, 1}, {1244, 16889603},
905
  {1245, 1}, {1246, 16889859}, {1247, 1}, {1248, 16890115},
906
  {1249, 1}, {1250, 16890371}, {1251, 1}, {1252, 16890627},
907
  {1253, 1}, {1254, 16890883}, {1255, 1}, {1256, 16891139},
908
  {1257, 1}, {1258, 16891395}, {1259, 1}, {1260, 16891651},
909
  {1261, 1}, {1262, 16891907}, {1263, 1}, {1264, 16892163},
910
  {1265, 1}, {1266, 16892419}, {1267, 1}, {1268, 16892675},
911
  {1269, 1}, {1270, 16892931}, {1271, 1}, {1272, 16893187},
912
  {1273, 1}, {1274, 16893443}, {1275, 1}, {1276, 16893699},
913
  {1277, 1}, {1278, 16893955}, {1279, 1}, {1280, 16894211},
914
  {1281, 1}, {1282, 16894467}, {1283, 1}, {1284, 16894723},
915
  {1285, 1}, {1286, 16894979}, {1287, 1}, {1288, 16895235},
916
  {1289, 1}, {1290, 16895491}, {1291, 1}, {1292, 16895747},
917
  {1293, 1}, {1294, 16896003}, {1295, 1}, {1296, 16896259},
918
  {1297, 1}, {1298, 16896515}, {1299, 1}, {1300, 16896771},
919
  {1301, 1}, {1302, 16897027}, {1303, 1}, {1304, 16897283},
920
  {1305, 1}, {1306, 16897539}, {1307, 1}, {1308, 16897795},
921
  {1309, 1}, {1310, 16898051}, {1311, 1}, {1312, 16898307},
922
  {1313, 1}, {1314, 16898563}, {1315, 1}, {1316, 16898819},
923
  {1317, 1}, {1318, 16899075}, {1319, 1}, {1320, 16899331},
924
  {1321, 1}, {1322, 16899587}, {1323, 1}, {1324, 16899843},
925
  {1325, 1}, {1326, 16900099}, {1327, 1}, {1328, 2},
926
  {1329, 16900355}, {1330, 16900611}, {1331, 16900867}, {1332, 16901123},
927
  {1333, 16901379}, {1334, 16901635}, {1335, 16901891}, {1336, 16902147},
928
  {1337, 16902403}, {1338, 16902659}, {1339, 16902915}, {1340, 16903171},
929
  {1341, 16903427}, {1342, 16903683}, {1343, 16903939}, {1344, 16904195},
930
  {1345, 16904451}, {1346, 16904707}, {1347, 16904963}, {1348, 16905219},
931
  {1349, 16905475}, {1350, 16905731}, {1351, 16905987}, {1352, 16906243},
932
  {1353, 16906499}, {1354, 16906755}, {1355, 16907011}, {1356, 16907267},
933
  {1357, 16907523}, {1358, 16907779}, {1359, 16908035}, {1360, 16908291},
934
  {1361, 16908547}, {1362, 16908803}, {1363, 16909059}, {1364, 16909315},
935
  {1365, 16909571}, {1366, 16909827}, {1367, 2}, {1369, 1},
936
  {1415, 33687299}, {1416, 1}, {1419, 2}, {1421, 1},
937
  {1424, 2}, {1425, 1}, {1480, 2}, {1488, 1},
938
  {1515, 2}, {1519, 1}, {1525, 2}, {1542, 1},
939
  {1564, 2}, {1565, 1}, {1653, 33687811}, {1654, 33688323},
940
  {1655, 33688835}, {1656, 33689347}, {1657, 1}, {1757, 2},
941
  {1758, 1}, {1806, 2}, {1808, 1}, {1867, 2},
942
  {1869, 1}, {1970, 2}, {1984, 1}, {2043, 2},
943
  {2045, 1}, {2094, 2}, {2096, 1}, {2111, 2},
944
  {2112, 1}, {2140, 2}, {2142, 1}, {2143, 2},
945
  {2144, 1}, {2155, 2}, {2160, 1}, {2192, 2},
946
  {2199, 1}, {2274, 2}, {2275, 1}, {2392, 33689859},
947
  {2393, 33690371}, {2394, 33690883}, {2395, 33691395}, {2396, 33691907},
948
  {2397, 33692419}, {2398, 33692931}, {2399, 33693443}, {2400, 1},
949
  {2436, 2}, {2437, 1}, {2445, 2}, {2447, 1},
950
  {2449, 2}, {2451, 1}, {2473, 2}, {2474, 1},
951
  {2481, 2}, {2482, 1}, {2483, 2}, {2486, 1},
952
  {2490, 2}, {2492, 1}, {2501, 2}, {2503, 1},
953
  {2505, 2}, {2507, 1}, {2511, 2}, {2519, 1},
954
  {2520, 2}, {2524, 33693955}, {2525, 33694467}, {2526, 2},
955
  {2527, 33694979}, {2528, 1}, {2532, 2}, {2534, 1},
956
  {2559, 2}, {2561, 1}, {2564, 2}, {2565, 1},
957
  {2571, 2}, {2575, 1}, {2577, 2}, {2579, 1},
958
  {2601, 2}, {2602, 1}, {2609, 2}, {2610, 1},
959
  {2611, 33695491}, {2612, 2}, {2613, 1}, {2614, 33696003},
960
  {2615, 2}, {2616, 1}, {2618, 2}, {2620, 1},
961
  {2621, 2}, {2622, 1}, {2627, 2}, {2631, 1},
962
  {2633, 2}, {2635, 1}, {2638, 2}, {2641, 1},
963
  {2642, 2}, {2649, 33696515}, {2650, 33697027}, {2651, 33697539},
964
  {2652, 1}, {2653, 2}, {2654, 33698051}, {2655, 2},
965
  {2662, 1}, {2679, 2}, {2689, 1}, {2692, 2},
966
  {2693, 1}, {2702, 2}, {2703, 1}, {2706, 2},
967
  {2707, 1}, {2729, 2}, {2730, 1}, {2737, 2},
968
  {2738, 1}, {2740, 2}, {2741, 1}, {2746, 2},
969
  {2748, 1}, {2758, 2}, {2759, 1}, {2762, 2},
970
  {2763, 1}, {2766, 2}, {2768, 1}, {2769, 2},
971
  {2784, 1}, {2788, 2}, {2790, 1}, {2802, 2},
972
  {2809, 1}, {2816, 2}, {2817, 1}, {2820, 2},
973
  {2821, 1}, {2829, 2}, {2831, 1}, {2833, 2},
974
  {2835, 1}, {2857, 2}, {2858, 1}, {2865, 2},
975
  {2866, 1}, {2868, 2}, {2869, 1}, {2874, 2},
976
  {2876, 1}, {2885, 2}, {2887, 1}, {2889, 2},
977
  {2891, 1}, {2894, 2}, {2901, 1}, {2904, 2},
978
  {2908, 33698563}, {2909, 33699075}, {2910, 2}, {2911, 1},
979
  {2916, 2}, {2918, 1}, {2936, 2}, {2946, 1},
980
  {2948, 2}, {2949, 1}, {2955, 2}, {2958, 1},
981
  {2961, 2}, {2962, 1}, {2966, 2}, {2969, 1},
982
  {2971, 2}, {2972, 1}, {2973, 2}, {2974, 1},
983
  {2976, 2}, {2979, 1}, {2981, 2}, {2984, 1},
984
  {2987, 2}, {2990, 1}, {3002, 2}, {3006, 1},
985
  {3011, 2}, {3014, 1}, {3017, 2}, {3018, 1},
986
  {3022, 2}, {3024, 1}, {3025, 2}, {3031, 1},
987
  {3032, 2}, {3046, 1}, {3067, 2}, {3072, 1},
988
  {3085, 2}, {3086, 1}, {3089, 2}, {3090, 1},
989
  {3113, 2}, {3114, 1}, {3130, 2}, {3132, 1},
990
  {3141, 2}, {3142, 1}, {3145, 2}, {3146, 1},
991
  {3150, 2}, {3157, 1}, {3159, 2}, {3160, 1},
992
  {3163, 2}, {3164, 1}, {3166, 2}, {3168, 1},
993
  {3172, 2}, {3174, 1}, {3184, 2}, {3191, 1},
994
  {3213, 2}, {3214, 1}, {3217, 2}, {3218, 1},
995
  {3241, 2}, {3242, 1}, {3252, 2}, {3253, 1},
996
  {3258, 2}, {3260, 1}, {3269, 2}, {3270, 1},
997
  {3273, 2}, {3274, 1}, {3278, 2}, {3285, 1},
998
  {3287, 2}, {3292, 1}, {3295, 2}, {3296, 1},
999
  {3300, 2}, {3302, 1}, {3312, 2}, {3313, 1},
1000
  {3316, 2}, {3328, 1}, {3341, 2}, {3342, 1},
1001
  {3345, 2}, {3346, 1}, {3397, 2}, {3398, 1},
1002
  {3401, 2}, {3402, 1}, {3408, 2}, {3412, 1},
1003
  {3428, 2}, {3430, 1}, {3456, 2}, {3457, 1},
1004
  {3460, 2}, {3461, 1}, {3479, 2}, {3482, 1},
1005
  {3506, 2}, {3507, 1}, {3516, 2}, {3517, 1},
1006
  {3518, 2}, {3520, 1}, {3527, 2}, {3530, 1},
1007
  {3531, 2}, {3535, 1}, {3541, 2}, {3542, 1},
1008
  {3543, 2}, {3544, 1}, {3552, 2}, {3558, 1},
1009
  {3568, 2}, {3570, 1}, {3573, 2}, {3585, 1},
1010
  {3635, 33699587}, {3636, 1}, {3643, 2}, {3647, 1},
1011
  {3676, 2}, {3713, 1}, {3715, 2}, {3716, 1},
1012
  {3717, 2}, {3718, 1}, {3723, 2}, {3724, 1},
1013
  {3748, 2}, {3749, 1}, {3750, 2}, {3751, 1},
1014
  {3763, 33700099}, {3764, 1}, {3774, 2}, {3776, 1},
1015
  {3781, 2}, {3782, 1}, {3783, 2}, {3784, 1},
1016
  {3791, 2}, {3792, 1}, {3802, 2}, {3804, 33700611},
1017
  {3805, 33701123}, {3806, 1}, {3808, 2}, {3840, 1},
1018
  {3852, 16924419}, {3853, 1}, {3907, 33701891}, {3908, 1},
1019
  {3912, 2}, {3913, 1}, {3917, 33702403}, {3918, 1},
1020
  {3922, 33702915}, {3923, 1}, {3927, 33703427}, {3928, 1},
1021
  {3932, 33703939}, {3933, 1}, {3945, 33704451}, {3946, 1},
1022
  {3949, 2}, {3953, 1}, {3955, 33704963}, {3956, 1},
1023
  {3957, 33705475}, {3958, 33705987}, {3959, 50483715}, {3960, 33707267},
1024
  {3961, 50484995}, {3962, 1}, {3969, 33706755}, {3970, 1},
1025
  {3987, 33708547}, {3988, 1}, {3992, 2}, {3993, 1},
1026
  {3997, 33709059}, {3998, 1}, {4002, 33709571}, {4003, 1},
1027
  {4007, 33710083}, {4008, 1}, {4012, 33710595}, {4013, 1},
1028
  {4025, 33711107}, {4026, 1}, {4029, 2}, {4030, 1},
1029
  {4045, 2}, {4046, 1}, {4059, 2}, {4096, 1},
1030
  {4256, 16934403}, {4257, 16934659}, {4258, 16934915}, {4259, 16935171},
1031
  {4260, 16935427}, {4261, 16935683}, {4262, 16935939}, {4263, 16936195},
1032
  {4264, 16936451}, {4265, 16936707}, {4266, 16936963}, {4267, 16937219},
1033
  {4268, 16937475}, {4269, 16937731}, {4270, 16937987}, {4271, 16938243},
1034
  {4272, 16938499}, {4273, 16938755}, {4274, 16939011}, {4275, 16939267},
1035
  {4276, 16939523}, {4277, 16939779}, {4278, 16940035}, {4279, 16940291},
1036
  {4280, 16940547}, {4281, 16940803}, {4282, 16941059}, {4283, 16941315},
1037
  {4284, 16941571}, {4285, 16941827}, {4286, 16942083}, {4287, 16942339},
1038
  {4288, 16942595}, {4289, 16942851}, {4290, 16943107}, {4291, 16943363},
1039
  {4292, 16943619}, {4293, 16943875}, {4294, 2}, {4295, 16944131},
1040
  {4296, 2}, {4301, 16944387}, {4302, 2}, {4304, 1},
1041
  {4348, 16944643}, {4349, 1}, {4447, 0}, {4449, 1},
1042
  {4681, 2}, {4682, 1}, {4686, 2}, {4688, 1},
1043
  {4695, 2}, {4696, 1}, {4697, 2}, {4698, 1},
1044
  {4702, 2}, {4704, 1}, {4745, 2}, {4746, 1},
1045
  {4750, 2}, {4752, 1}, {4785, 2}, {4786, 1},
1046
  {4790, 2}, {4792, 1}, {4799, 2}, {4800, 1},
1047
  {4801, 2}, {4802, 1}, {4806, 2}, {4808, 1},
1048
  {4823, 2}, {4824, 1}, {4881, 2}, {4882, 1},
1049
  {4886, 2}, {4888, 1}, {4955, 2}, {4957, 1},
1050
  {4989, 2}, {4992, 1}, {5018, 2}, {5024, 1},
1051
  {5110, 2}, {5112, 16944899}, {5113, 16945155}, {5114, 16945411},
1052
  {5115, 16945667}, {5116, 16945923}, {5117, 16946179}, {5118, 2},
1053
  {5120, 1}, {5760, 2}, {5761, 1}, {5789, 2},
1054
  {5792, 1}, {5881, 2}, {5888, 1}, {5910, 2},
1055
  {5919, 1}, {5943, 2}, {5952, 1}, {5972, 2},
1056
  {5984, 1}, {5997, 2}, {5998, 1}, {6001, 2},
1057
  {6002, 1}, {6004, 2}, {6016, 1}, {6068, 0},
1058
  {6070, 1}, {6110, 2}, {6112, 1}, {6122, 2},
1059
  {6128, 1}, {6138, 2}, {6144, 1}, {6155, 0},
1060
  {6160, 1}, {6170, 2}, {6176, 1}, {6265, 2},
1061
  {6272, 1}, {6315, 2}, {6320, 1}, {6390, 2},
1062
  {6400, 1}, {6431, 2}, {6432, 1}, {6444, 2},
1063
  {6448, 1}, {6460, 2}, {6464, 1}, {6465, 2},
1064
  {6468, 1}, {6510, 2}, {6512, 1}, {6517, 2},
1065
  {6528, 1}, {6572, 2}, {6576, 1}, {6602, 2},
1066
  {6608, 1}, {6619, 2}, {6622, 1}, {6684, 2},
1067
  {6686, 1}, {6751, 2}, {6752, 1}, {6781, 2},
1068
  {6783, 1}, {6794, 2}, {6800, 1}, {6810, 2},
1069
  {6816, 1}, {6830, 2}, {6832, 1}, {6878, 2},
1070
  {6880, 1}, {6892, 2}, {6912, 1}, {6989, 2},
1071
  {6990, 1}, {7156, 2}, {7164, 1}, {7224, 2},
1072
  {7227, 1}, {7242, 2}, {7245, 1}, {7296, 16867075},
1073
  {7297, 16867587}, {7298, 16870147}, {7299, 16870915}, {7300, 16871171},
1074
  {7302, 16873219}, {7303, 16875011}, {7304, 16946435}, {7305, 16946691},
1075
  {7306, 1}, {7307, 2}, {7312, 16946947}, {7313, 16947203},
1076
  {7314, 16947459}, {7315, 16947715}, {7316, 16947971}, {7317, 16948227},
1077
  {7318, 16948483}, {7319, 16948739}, {7320, 16948995}, {7321, 16949251},
1078
  {7322, 16949507}, {7323, 16949763}, {7324, 16944643}, {7325, 16950019},
1079
  {7326, 16950275}, {7327, 16950531}, {7328, 16950787}, {7329, 16951043},
1080
  {7330, 16951299}, {7331, 16951555}, {7332, 16951811}, {7333, 16952067},
1081
  {7334, 16952323}, {7335, 16952579}, {7336, 16952835}, {7337, 16953091},
1082
  {7338, 16953347}, {7339, 16953603}, {7340, 16953859}, {7341, 16954115},
1083
  {7342, 16954371}, {7343, 16954627}, {7344, 16954883}, {7345, 16955139},
1084
  {7346, 16955395}, {7347, 16955651}, {7348, 16955907}, {7349, 16956163},
1085
  {7350, 16956419}, {7351, 16956675}, {7352, 16956931}, {7353, 16957187},
1086
  {7354, 16957443}, {7355, 2}, {7357, 16957699}, {7358, 16957955},
1087
  {7359, 16958211}, {7360, 1}, {7368, 2}, {7376, 1},
1088
  {7419, 2}, {7424, 1}, {7468, 16777219}, {7469, 16791043},
1089
  {7470, 16777475}, {7471, 1}, {7472, 16777987}, {7473, 16778243},
1090
  {7474, 16816131}, {7475, 16778755}, {7476, 16779011}, {7477, 16779267},
1091
  {7478, 16779523}, {7479, 16779779}, {7480, 16780035}, {7481, 16780291},
1092
  {7482, 16780547}, {7483, 1}, {7484, 16780803}, {7485, 16835843},
1093
  {7486, 16781059}, {7487, 16781571}, {7488, 16782083}, {7489, 16782339},
1094
  {7490, 16782851}, {7491, 16777219}, {7492, 16958467}, {7493, 16958723},
1095
  {7494, 16958979}, {7495, 16777475}, {7496, 16777987}, {7497, 16778243},
1096
  {7498, 16816387}, {7499, 16816643}, {7500, 16959235}, {7501, 16778755},
1097
  {7502, 1}, {7503, 16779779}, {7504, 16780291}, {7505, 16807171},
1098
  {7506, 16780803}, {7507, 16814851}, {7508, 16959491}, {7509, 16959747},
1099
  {7510, 16781059}, {7511, 16782083}, {7512, 16782339}, {7513, 16960003},
1100
  {7514, 16818435}, {7515, 16782595}, {7516, 16960259}, {7517, 16851971},
1101
  {7518, 16852227}, {7519, 16852483}, {7520, 16856323}, {7521, 16856579},
1102
  {7522, 16779267}, {7523, 16781571}, {7524, 16782339}, {7525, 16782595},
1103
  {7526, 16851971}, {7527, 16852227}, {7528, 16855299}, {7529, 16856323},
1104
  {7530, 16856579}, {7531, 1}, {7544, 16869891}, {7545, 1},
1105
  {7579, 16960515}, {7580, 16777731}, {7581, 16960771}, {7582, 16793603},
1106
  {7583, 16959235}, {7584, 16778499}, {7585, 16961027}, {7586, 16961283},
1107
  {7587, 16961539}, {7588, 16817923}, {7589, 16817667}, {7590, 16961795},
1108
  {7591, 16962051}, {7592, 16962307}, {7593, 16962563}, {7594, 16962819},
1109
  {7595, 16963075}, {7596, 16963331}, {7597, 16963587}, {7598, 16818691},
1110
  {7599, 16963843}, {7600, 16964099}, {7601, 16818947}, {7602, 16964355},
1111
  {7603, 16964611}, {7604, 16820483}, {7605, 16964867}, {7606, 16839683},
1112
  {7607, 16821507}, {7608, 16965123}, {7609, 16821763}, {7610, 16839939},
1113
  {7611, 16783619}, {7612, 16965379}, {7613, 16965635}, {7614, 16822531},
1114
  {7615, 16853507}, {7616, 1}, {7680, 16965891}, {7681, 1},
1115
  {7682, 16966147}, {7683, 1}, {7684, 16966403}, {7685, 1},
1116
  {7686, 16966659}, {7687, 1}, {7688, 16966915}, {7689, 1},
1117
  {7690, 16967171}, {7691, 1}, {7692, 16967427}, {7693, 1},
1118
  {7694, 16967683}, {7695, 1}, {7696, 16967939}, {7697, 1},
1119
  {7698, 16968195}, {7699, 1}, {7700, 16968451}, {7701, 1},
1120
  {7702, 16968707}, {7703, 1}, {7704, 16968963}, {7705, 1},
1121
  {7706, 16969219}, {7707, 1}, {7708, 16969475}, {7709, 1},
1122
  {7710, 16969731}, {7711, 1}, {7712, 16969987}, {7713, 1},
1123
  {7714, 16970243}, {7715, 1}, {7716, 16970499}, {7717, 1},
1124
  {7718, 16970755}, {7719, 1}, {7720, 16971011}, {7721, 1},
1125
  {7722, 16971267}, {7723, 1}, {7724, 16971523}, {7725, 1},
1126
  {7726, 16971779}, {7727, 1}, {7728, 16972035}, {7729, 1},
1127
  {7730, 16972291}, {7731, 1}, {7732, 16972547}, {7733, 1},
1128
  {7734, 16972803}, {7735, 1}, {7736, 16973059}, {7737, 1},
1129
  {7738, 16973315}, {7739, 1}, {7740, 16973571}, {7741, 1},
1130
  {7742, 16973827}, {7743, 1}, {7744, 16974083}, {7745, 1},
1131
  {7746, 16974339}, {7747, 1}, {7748, 16974595}, {7749, 1},
1132
  {7750, 16974851}, {7751, 1}, {7752, 16975107}, {7753, 1},
1133
  {7754, 16975363}, {7755, 1}, {7756, 16975619}, {7757, 1},
1134
  {7758, 16975875}, {7759, 1}, {7760, 16976131}, {7761, 1},
1135
  {7762, 16976387}, {7763, 1}, {7764, 16976643}, {7765, 1},
1136
  {7766, 16976899}, {7767, 1}, {7768, 16977155}, {7769, 1},
1137
  {7770, 16977411}, {7771, 1}, {7772, 16977667}, {7773, 1},
1138
  {7774, 16977923}, {7775, 1}, {7776, 16978179}, {7777, 1},
1139
  {7778, 16978435}, {7779, 1}, {7780, 16978691}, {7781, 1},
1140
  {7782, 16978947}, {7783, 1}, {7784, 16979203}, {7785, 1},
1141
  {7786, 16979459}, {7787, 1}, {7788, 16979715}, {7789, 1},
1142
  {7790, 16979971}, {7791, 1}, {7792, 16980227}, {7793, 1},
1143
  {7794, 16980483}, {7795, 1}, {7796, 16980739}, {7797, 1},
1144
  {7798, 16980995}, {7799, 1}, {7800, 16981251}, {7801, 1},
1145
  {7802, 16981507}, {7803, 1}, {7804, 16981763}, {7805, 1},
1146
  {7806, 16982019}, {7807, 1}, {7808, 16982275}, {7809, 1},
1147
  {7810, 16982531}, {7811, 1}, {7812, 16982787}, {7813, 1},
1148
  {7814, 16983043}, {7815, 1}, {7816, 16983299}, {7817, 1},
1149
  {7818, 16983555}, {7819, 1}, {7820, 16983811}, {7821, 1},
1150
  {7822, 16984067}, {7823, 1}, {7824, 16984323}, {7825, 1},
1151
  {7826, 16984579}, {7827, 1}, {7828, 16984835}, {7829, 1},
1152
  {7834, 33762307}, {7835, 16978179}, {7836, 1}, {7838, 16985603},
1153
  {7839, 1}, {7840, 16985859}, {7841, 1}, {7842, 16986115},
1154
  {7843, 1}, {7844, 16986371}, {7845, 1}, {7846, 16986627},
1155
  {7847, 1}, {7848, 16986883}, {7849, 1}, {7850, 16987139},
1156
  {7851, 1}, {7852, 16987395}, {7853, 1}, {7854, 16987651},
1157
  {7855, 1}, {7856, 16987907}, {7857, 1}, {7858, 16988163},
1158
  {7859, 1}, {7860, 16988419}, {7861, 1}, {7862, 16988675},
1159
  {7863, 1}, {7864, 16988931}, {7865, 1}, {7866, 16989187},
1160
  {7867, 1}, {7868, 16989443}, {7869, 1}, {7870, 16989699},
1161
  {7871, 1}, {7872, 16989955}, {7873, 1}, {7874, 16990211},
1162
  {7875, 1}, {7876, 16990467}, {7877, 1}, {7878, 16990723},
1163
  {7879, 1}, {7880, 16990979}, {7881, 1}, {7882, 16991235},
1164
  {7883, 1}, {7884, 16991491}, {7885, 1}, {7886, 16991747},
1165
  {7887, 1}, {7888, 16992003}, {7889, 1}, {7890, 16992259},
1166
  {7891, 1}, {7892, 16992515}, {7893, 1}, {7894, 16992771},
1167
  {7895, 1}, {7896, 16993027}, {7897, 1}, {7898, 16993283},
1168
  {7899, 1}, {7900, 16993539}, {7901, 1}, {7902, 16993795},
1169
  {7903, 1}, {7904, 16994051}, {7905, 1}, {7906, 16994307},
1170
  {7907, 1}, {7908, 16994563}, {7909, 1}, {7910, 16994819},
1171
  {7911, 1}, {7912, 16995075}, {7913, 1}, {7914, 16995331},
1172
  {7915, 1}, {7916, 16995587}, {7917, 1}, {7918, 16995843},
1173
  {7919, 1}, {7920, 16996099}, {7921, 1}, {7922, 16996355},
1174
  {7923, 1}, {7924, 16996611}, {7925, 1}, {7926, 16996867},
1175
  {7927, 1}, {7928, 16997123}, {7929, 1}, {7930, 16997379},
1176
  {7931, 1}, {7932, 16997635}, {7933, 1}, {7934, 16997891},
1177
  {7935, 1}, {7944, 16998147}, {7945, 16998403}, {7946, 16998659},
1178
  {7947, 16998915}, {7948, 16999171}, {7949, 16999427}, {7950, 16999683},
1179
  {7951, 16999939}, {7952, 1}, {7958, 2}, {7960, 17000195},
1180
  {7961, 17000451}, {7962, 17000707}, {7963, 17000963}, {7964, 17001219},
1181
  {7965, 17001475}, {7966, 2}, {7968, 1}, {7976, 17001731},
1182
  {7977, 17001987}, {7978, 17002243}, {7979, 17002499}, {7980, 17002755},
1183
  {7981, 17003011}, {7982, 17003267}, {7983, 17003523}, {7984, 1},
1184
  {7992, 17003779}, {7993, 17004035}, {7994, 17004291}, {7995, 17004547},
1185
  {7996, 17004803}, {7997, 17005059}, {7998, 17005315}, {7999, 17005571},
1186
  {8000, 1}, {8006, 2}, {8008, 17005827}, {8009, 17006083},
1187
  {8010, 17006339}, {8011, 17006595}, {8012, 17006851}, {8013, 17007107},
1188
  {8014, 2}, {8016, 1}, {8024, 2}, {8025, 17007363},
1189
  {8026, 2}, {8027, 17007619}, {8028, 2}, {8029, 17007875},
1190
  {8030, 2}, {8031, 17008131}, {8032, 1}, {8040, 17008387},
1191
  {8041, 17008643}, {8042, 17008899}, {8043, 17009155}, {8044, 17009411},
1192
  {8045, 17009667}, {8046, 17009923}, {8047, 17010179}, {8048, 1},
1193
  {8049, 16849923}, {8050, 1}, {8051, 16850179}, {8052, 1},
1194
  {8053, 16850435}, {8054, 1}, {8055, 16850691}, {8056, 1},
1195
  {8057, 16850947}, {8058, 1}, {8059, 16851203}, {8060, 1},
1196
  {8061, 16851459}, {8062, 2}, {8064, 33787651}, {8065, 33788163},
1197
  {8066, 33788675}, {8067, 33789187}, {8068, 33789699}, {8069, 33790211},
1198
  {8070, 33790723}, {8071, 33791235}, {8072, 33787651}, {8073, 33788163},
1199
  {8074, 33788675}, {8075, 33789187}, {8076, 33789699}, {8077, 33790211},
1200
  {8078, 33790723}, {8079, 33791235}, {8080, 33791747}, {8081, 33792259},
1201
  {8082, 33792771}, {8083, 33793283}, {8084, 33793795}, {8085, 33794307},
1202
  {8086, 33794819}, {8087, 33795331}, {8088, 33791747}, {8089, 33792259},
1203
  {8090, 33792771}, {8091, 33793283}, {8092, 33793795}, {8093, 33794307},
1204
  {8094, 33794819}, {8095, 33795331}, {8096, 33795843}, {8097, 33796355},
1205
  {8098, 33796867}, {8099, 33797379}, {8100, 33797891}, {8101, 33798403},
1206
  {8102, 33798915}, {8103, 33799427}, {8104, 33795843}, {8105, 33796355},
1207
  {8106, 33796867}, {8107, 33797379}, {8108, 33797891}, {8109, 33798403},
1208
  {8110, 33798915}, {8111, 33799427}, {8112, 1}, {8114, 33799939},
1209
  {8115, 33800451}, {8116, 33800963}, {8117, 2}, {8118, 1},
1210
  {8119, 33801475}, {8120, 17024771}, {8121, 17025027}, {8122, 17022723},
1211
  {8123, 16849923}, {8124, 33800451}, {8125, 33802499}, {8126, 16846851},
1212
  {8127, 33802499}, {8128, 33803011}, {8129, 50580739}, {8130, 33804291},
1213
  {8131, 33804803}, {8132, 33805315}, {8133, 2}, {8134, 1},
1214
  {8135, 33805827}, {8136, 17029123}, {8137, 16850179}, {8138, 17027075},
1215
  {8139, 16850435}, {8140, 33804803}, {8141, 50583811}, {8142, 50584579},
1216
  {8143, 50585347}, {8144, 1}, {8147, 17031683}, {8148, 2},
1217
  {8150, 1}, {8152, 17031939}, {8153, 17032195}, {8154, 17032451},
1218
  {8155, 16850691}, {8156, 2}, {8157, 50587139}, {8158, 50587907},
1219
  {8159, 50588675}, {8160, 1}, {8163, 17035011}, {8164, 1},
1220
  {8168, 17035267}, {8169, 17035523}, {8170, 17035779}, {8171, 16851203},
1221
  {8172, 17036035}, {8173, 50590723}, {8174, 50403587}, {8175, 17037059},
1222
  {8176, 2}, {8178, 33814531}, {8179, 33815043}, {8180, 33815555},
1223
  {8181, 2}, {8182, 1}, {8183, 33816067}, {8184, 17039363},
1224
  {8185, 16850947}, {8186, 17037315}, {8187, 16851459}, {8188, 33815043},
1225
  {8189, 33562883}, {8190, 33809923}, {8191, 2}, {8192, 16783875},
1226
  {8203, 0}, {8204, 1}, {8206, 2}, {8208, 1},
1227
  {8209, 17039619}, {8210, 1}, {8215, 33817091}, {8216, 1},
1228
  {8228, 2}, {8231, 1}, {8232, 2}, {8239, 16783875},
1229
  {8240, 1}, {8243, 33817603}, {8244, 50595331}, {8245, 1},
1230
  {8246, 33818883}, {8247, 50596611}, {8248, 1}, {8252, 33820163},
1231
  {8253, 1}, {8254, 33820675}, {8255, 1}, {8263, 33821187},
1232
  {8264, 33821699}, {8265, 33822211}, {8266, 1}, {8279, 67372035},
1233
  {8280, 1}, {8287, 16783875}, {8288, 0}, {8293, 2},
1234
  {8298, 0}, {8304, 17045507}, {8305, 16779267}, {8306, 2},
1235
  {8308, 16787715}, {8309, 17045763}, {8310, 17046019}, {8311, 17046275},
1236
  {8312, 17046531}, {8313, 17046787}, {8314, 17047043}, {8315, 17047299},
1237
  {8316, 17047555}, {8317, 17047811}, {8318, 17048067}, {8319, 16780547},
1238
  {8320, 17045507}, {8321, 16786947}, {8322, 16785155}, {8323, 16785411},
1239
  {8324, 16787715}, {8325, 17045763}, {8326, 17046019}, {8327, 17046275},
1240
  {8328, 17046531}, {8329, 17046787}, {8330, 17047043}, {8331, 17047299},
1241
  {8332, 17047555}, {8333, 17047811}, {8334, 17048067}, {8335, 2},
1242
  {8336, 16777219}, {8337, 16778243}, {8338, 16780803}, {8339, 16783107},
1243
  {8340, 16816387}, {8341, 16779011}, {8342, 16779779}, {8343, 16780035},
1244
  {8344, 16780291}, {8345, 16780547}, {8346, 16781059}, {8347, 16781827},
1245
  {8348, 16782083}, {8349, 2}, {8352, 1}, {8360, 33558787},
1246
  {8361, 1}, {8386, 2}, {8400, 1}, {8433, 2},
1247
  {8448, 50602755}, {8449, 50603523}, {8450, 16777731}, {8451, 33827075},
1248
  {8452, 1}, {8453, 50604803}, {8454, 50605571}, {8455, 16816643},
1249
  {8456, 1}, {8457, 33829123}, {8458, 16778755}, {8459, 16779011},
1250
  {8463, 16802051}, {8464, 16779267}, {8466, 16780035}, {8468, 1},
1251
  {8469, 16780547}, {8470, 33557763}, {8471, 1}, {8473, 16781059},
1252
  {8474, 16781315}, {8475, 16781571}, {8478, 1}, {8480, 33829635},
1253
  {8481, 50607363}, {8482, 33830915}, {8483, 1}, {8484, 16783619},
1254
  {8485, 1}, {8486, 16857091}, {8487, 1}, {8488, 16783619},
1255
  {8489, 1}, {8490, 16779779}, {8491, 16790787}, {8492, 16777475},
1256
  {8493, 16777731}, {8494, 1}, {8495, 16778243}, {8497, 16778499},
1257
  {8498, 17054211}, {8499, 16780291}, {8500, 16780803}, {8501, 17054467},
1258
  {8502, 17054723}, {8503, 17054979}, {8504, 17055235}, {8505, 16779267},
1259
  {8506, 1}, {8507, 50609923}, {8508, 16855043}, {8509, 16852227},
1260
  {8511, 16855043}, {8512, 17056259}, {8513, 1}, {8517, 16777987},
1261
  {8519, 16778243}, {8520, 16779267}, {8521, 16779523}, {8522, 1},
1262
  {8528, 50610947}, {8529, 50611715}, {8530, 67389699}, {8531, 50613507},
1263
  {8532, 50614275}, {8533, 50615043}, {8534, 50615811}, {8535, 50616579},
1264
  {8536, 50617347}, {8537, 50618115}, {8538, 50618883}, {8539, 50619651},
1265
  {8540, 50620419}, {8541, 50621187}, {8542, 50621955}, {8543, 33564419},
1266
  {8544, 16779267}, {8545, 33845507}, {8546, 50623235}, {8547, 33846787},
1267
  {8548, 16782595}, {8549, 33847299}, {8550, 50625027}, {8551, 67403011},
1268
  {8552, 33849603}, {8553, 16783107}, {8554, 33850115}, {8555, 50627843},
1269
  {8556, 16780035}, {8557, 16777731}, {8558, 16777987}, {8559, 16780291},
1270
  {8560, 16779267}, {8561, 33845507}, {8562, 50622723}, {8563, 33846787},
1271
  {8564, 16782595}, {8565, 33847299}, {8566, 50625027}, {8567, 67403011},
1272
  {8568, 33849603}, {8569, 16783107}, {8570, 33850115}, {8571, 50627843},
1273
  {8572, 16780035}, {8573, 16777731}, {8574, 16777987}, {8575, 16780291},
1274
  {8576, 1}, {8579, 17074179}, {8580, 1}, {8585, 50628867},
1275
  {8586, 1}, {8588, 2}, {8592, 1}, {8748, 33852419},
1276
  {8749, 50630147}, {8750, 1}, {8751, 33853699}, {8752, 50631427},
1277
  {8753, 1}, {9001, 17077763}, {9002, 17078019}, {9003, 1},
1278
  {9258, 2}, {9280, 1}, {9291, 2}, {9312, 16786947},
1279
  {9313, 16785155}, {9314, 16785411}, {9315, 16787715}, {9316, 17045763},
1280
  {9317, 17046019}, {9318, 17046275}, {9319, 17046531}, {9320, 17046787},
1281
  {9321, 33835779}, {9322, 33564163}, {9323, 33855491}, {9324, 33856003},
1282
  {9325, 33856515}, {9326, 33857027}, {9327, 33857539}, {9328, 33858051},
1283
  {9329, 33858563}, {9330, 33859075}, {9331, 33859587}, {9332, 50637315},
1284
  {9333, 50638083}, {9334, 50638851}, {9335, 50639619}, {9336, 50640387},
1285
  {9337, 50641155}, {9338, 50641923}, {9339, 50642691}, {9340, 50643459},
1286
  {9341, 67421443}, {9342, 67422467}, {9343, 67423491}, {9344, 67424515},
1287
  {9345, 67425539}, {9346, 67426563}, {9347, 67427587}, {9348, 67428611},
1288
  {9349, 67429635}, {9350, 67430659}, {9351, 67431683}, {9352, 2},
1289
  {9372, 50655491}, {9373, 50656259}, {9374, 50657027}, {9375, 50657795},
1290
  {9376, 50658563}, {9377, 50659331}, {9378, 50660099}, {9379, 50660867},
1291
  {9380, 50661635}, {9381, 50662403}, {9382, 50663171}, {9383, 50663939},
1292
  {9384, 50664707}, {9385, 50665475}, {9386, 50666243}, {9387, 50667011},
1293
  {9388, 50667779}, {9389, 50668547}, {9390, 50669315}, {9391, 50670083},
1294
  {9392, 50670851}, {9393, 50671619}, {9394, 50672387}, {9395, 50673155},
1295
  {9396, 50673923}, {9397, 50674691}, {9398, 16777219}, {9399, 16777475},
1296
  {9400, 16777731}, {9401, 16777987}, {9402, 16778243}, {9403, 16778499},
1297
  {9404, 16778755}, {9405, 16779011}, {9406, 16779267}, {9407, 16779523},
1298
  {9408, 16779779}, {9409, 16780035}, {9410, 16780291}, {9411, 16780547},
1299
  {9412, 16780803}, {9413, 16781059}, {9414, 16781315}, {9415, 16781571},
1300
  {9416, 16781827}, {9417, 16782083}, {9418, 16782339}, {9419, 16782595},
1301
  {9420, 16782851}, {9421, 16783107}, {9422, 16783363}, {9423, 16783619},
1302
  {9424, 16777219}, {9425, 16777475}, {9426, 16777731}, {9427, 16777987},
1303
  {9428, 16778243}, {9429, 16778499}, {9430, 16778755}, {9431, 16779011},
1304
  {9432, 16779267}, {9433, 16779523}, {9434, 16779779}, {9435, 16780035},
1305
  {9436, 16780291}, {9437, 16780547}, {9438, 16780803}, {9439, 16781059},
1306
  {9440, 16781315}, {9441, 16781571}, {9442, 16781827}, {9443, 16782083},
1307
  {9444, 16782339}, {9445, 16782595}, {9446, 16782851}, {9447, 16783107},
1308
  {9448, 16783363}, {9449, 16783619}, {9450, 17045507}, {9451, 1},
1309
  {10764, 67406851}, {10765, 1}, {10868, 50675459}, {10869, 33899011},
1310
  {10870, 50675971}, {10871, 1}, {10972, 33899523}, {10973, 1},
1311
  {11124, 2}, {11126, 1}, {11264, 17122819}, {11265, 17123075},
1312
  {11266, 17123331}, {11267, 17123587}, {11268, 17123843}, {11269, 17124099},
1313
  {11270, 17124355}, {11271, 17124611}, {11272, 17124867}, {11273, 17125123},
1314
  {11274, 17125379}, {11275, 17125635}, {11276, 17125891}, {11277, 17126147},
1315
  {11278, 17126403}, {11279, 17126659}, {11280, 17126915}, {11281, 17127171},
1316
  {11282, 17127427}, {11283, 17127683}, {11284, 17127939}, {11285, 17128195},
1317
  {11286, 17128451}, {11287, 17128707}, {11288, 17128963}, {11289, 17129219},
1318
  {11290, 17129475}, {11291, 17129731}, {11292, 17129987}, {11293, 17130243},
1319
  {11294, 17130499}, {11295, 17130755}, {11296, 17131011}, {11297, 17131267},
1320
  {11298, 17131523}, {11299, 17131779}, {11300, 17132035}, {11301, 17132291},
1321
  {11302, 17132547}, {11303, 17132803}, {11304, 17133059}, {11305, 17133315},
1322
  {11306, 17133571}, {11307, 17133827}, {11308, 17134083}, {11309, 17134339},
1323
  {11310, 17134595}, {11311, 17134851}, {11312, 1}, {11360, 17135107},
1324
  {11361, 1}, {11362, 17135363}, {11363, 17135619}, {11364, 17135875},
1325
  {11365, 1}, {11367, 17136131}, {11368, 1}, {11369, 17136387},
1326
  {11370, 1}, {11371, 17136643}, {11372, 1}, {11373, 16958723},
1327
  {11374, 16963331}, {11375, 16958467}, {11376, 16960515}, {11377, 1},
1328
  {11378, 17136899}, {11379, 1}, {11381, 17137155}, {11382, 1},
1329
  {11388, 16779523}, {11389, 16782595}, {11390, 17137411}, {11391, 17137667},
1330
  {11392, 17137923}, {11393, 1}, {11394, 17138179}, {11395, 1},
1331
  {11396, 17138435}, {11397, 1}, {11398, 17138691}, {11399, 1},
1332
  {11400, 17138947}, {11401, 1}, {11402, 17139203}, {11403, 1},
1333
  {11404, 17139459}, {11405, 1}, {11406, 17139715}, {11407, 1},
1334
  {11408, 17139971}, {11409, 1}, {11410, 17140227}, {11411, 1},
1335
  {11412, 17140483}, {11413, 1}, {11414, 17140739}, {11415, 1},
1336
  {11416, 17140995}, {11417, 1}, {11418, 17141251}, {11419, 1},
1337
  {11420, 17141507}, {11421, 1}, {11422, 17141763}, {11423, 1},
1338
  {11424, 17142019}, {11425, 1}, {11426, 17142275}, {11427, 1},
1339
  {11428, 17142531}, {11429, 1}, {11430, 17142787}, {11431, 1},
1340
  {11432, 17143043}, {11433, 1}, {11434, 17143299}, {11435, 1},
1341
  {11436, 17143555}, {11437, 1}, {11438, 17143811}, {11439, 1},
1342
  {11440, 17144067}, {11441, 1}, {11442, 17144323}, {11443, 1},
1343
  {11444, 17144579}, {11445, 1}, {11446, 17144835}, {11447, 1},
1344
  {11448, 17145091}, {11449, 1}, {11450, 17145347}, {11451, 1},
1345
  {11452, 17145603}, {11453, 1}, {11454, 17145859}, {11455, 1},
1346
  {11456, 17146115}, {11457, 1}, {11458, 17146371}, {11459, 1},
1347
  {11460, 17146627}, {11461, 1}, {11462, 17146883}, {11463, 1},
1348
  {11464, 17147139}, {11465, 1}, {11466, 17147395}, {11467, 1},
1349
  {11468, 17147651}, {11469, 1}, {11470, 17147907}, {11471, 1},
1350
  {11472, 17148163}, {11473, 1}, {11474, 17148419}, {11475, 1},
1351
  {11476, 17148675}, {11477, 1}, {11478, 17148931}, {11479, 1},
1352
  {11480, 17149187}, {11481, 1}, {11482, 17149443}, {11483, 1},
1353
  {11484, 17149699}, {11485, 1}, {11486, 17149955}, {11487, 1},
1354
  {11488, 17150211}, {11489, 1}, {11490, 17150467}, {11491, 1},
1355
  {11499, 17150723}, {11500, 1}, {11501, 17150979}, {11502, 1},
1356
  {11506, 17151235}, {11507, 1}, {11508, 2}, {11513, 1},
1357
  {11558, 2}, {11559, 1}, {11560, 2}, {11565, 1},
1358
  {11566, 2}, {11568, 1}, {11624, 2}, {11631, 17151491},
1359
  {11632, 1}, {11633, 2}, {11647, 1}, {11671, 2},
1360
  {11680, 1}, {11687, 2}, {11688, 1}, {11695, 2},
1361
  {11696, 1}, {11703, 2}, {11704, 1}, {11711, 2},
1362
  {11712, 1}, {11719, 2}, {11720, 1}, {11727, 2},
1363
  {11728, 1}, {11735, 2}, {11736, 1}, {11743, 2},
1364
  {11744, 1}, {11870, 2}, {11904, 1}, {11930, 2},
1365
  {11931, 1}, {11935, 17151747}, {11936, 1}, {12019, 17152003},
1366
  {12020, 2}, {12032, 17152259}, {12033, 17152515}, {12034, 17152771},
1367
  {12035, 17153027}, {12036, 17153283}, {12037, 17153539}, {12038, 17153795},
1368
  {12039, 17154051}, {12040, 17154307}, {12041, 17154563}, {12042, 17154819},
1369
  {12043, 17155075}, {12044, 17155331}, {12045, 17155587}, {12046, 17155843},
1370
  {12047, 17156099}, {12048, 17156355}, {12049, 17156611}, {12050, 17156867},
1371
  {12051, 17157123}, {12052, 17157379}, {12053, 17157635}, {12054, 17157891},
1372
  {12055, 17158147}, {12056, 17158403}, {12057, 17158659}, {12058, 17158915},
1373
  {12059, 17159171}, {12060, 17159427}, {12061, 17159683}, {12062, 17159939},
1374
  {12063, 17160195}, {12064, 17160451}, {12065, 17160707}, {12066, 17160963},
1375
  {12067, 17161219}, {12068, 17161475}, {12069, 17161731}, {12070, 17161987},
1376
  {12071, 17162243}, {12072, 17162499}, {12073, 17162755}, {12074, 17163011},
1377
  {12075, 17163267}, {12076, 17163523}, {12077, 17163779}, {12078, 17164035},
1378
  {12079, 17164291}, {12080, 17164547}, {12081, 17164803}, {12082, 17165059},
1379
  {12083, 17165315}, {12084, 17165571}, {12085, 17165827}, {12086, 17166083},
1380
  {12087, 17166339}, {12088, 17166595}, {12089, 17166851}, {12090, 17167107},
1381
  {12091, 17167363}, {12092, 17167619}, {12093, 17167875}, {12094, 17168131},
1382
  {12095, 17168387}, {12096, 17168643}, {12097, 17168899}, {12098, 17169155},
1383
  {12099, 17169411}, {12100, 17169667}, {12101, 17169923}, {12102, 17170179},
1384
  {12103, 17170435}, {12104, 17170691}, {12105, 17170947}, {12106, 17171203},
1385
  {12107, 17171459}, {12108, 17171715}, {12109, 17171971}, {12110, 17172227},
1386
  {12111, 17172483}, {12112, 17172739}, {12113, 17172995}, {12114, 17173251},
1387
  {12115, 17173507}, {12116, 17173763}, {12117, 17174019}, {12118, 17174275},
1388
  {12119, 17174531}, {12120, 17174787}, {12121, 17175043}, {12122, 17175299},
1389
  {12123, 17175555}, {12124, 17175811}, {12125, 17176067}, {12126, 17176323},
1390
  {12127, 17176579}, {12128, 17176835}, {12129, 17177091}, {12130, 17177347},
1391
  {12131, 17177603}, {12132, 17177859}, {12133, 17178115}, {12134, 17178371},
1392
  {12135, 17178627}, {12136, 17178883}, {12137, 17179139}, {12138, 17179395},
1393
  {12139, 17179651}, {12140, 17179907}, {12141, 17180163}, {12142, 17180419},
1394
  {12143, 17180675}, {12144, 17180931}, {12145, 17181187}, {12146, 17181443},
1395
  {12147, 17181699}, {12148, 17181955}, {12149, 17182211}, {12150, 17182467},
1396
  {12151, 17182723}, {12152, 17182979}, {12153, 17183235}, {12154, 17183491},
1397
  {12155, 17183747}, {12156, 17184003}, {12157, 17184259}, {12158, 17184515},
1398
  {12159, 17184771}, {12160, 17185027}, {12161, 17185283}, {12162, 17185539},
1399
  {12163, 17185795}, {12164, 17186051}, {12165, 17186307}, {12166, 17186563},
1400
  {12167, 17186819}, {12168, 17187075}, {12169, 17187331}, {12170, 17187587},
1401
  {12171, 17187843}, {12172, 17188099}, {12173, 17188355}, {12174, 17188611},
1402
  {12175, 17188867}, {12176, 17189123}, {12177, 17189379}, {12178, 17189635},
1403
  {12179, 17189891}, {12180, 17190147}, {12181, 17190403}, {12182, 17190659},
1404
  {12183, 17190915}, {12184, 17191171}, {12185, 17191427}, {12186, 17191683},
1405
  {12187, 17191939}, {12188, 17192195}, {12189, 17192451}, {12190, 17192707},
1406
  {12191, 17192963}, {12192, 17193219}, {12193, 17193475}, {12194, 17193731},
1407
  {12195, 17193987}, {12196, 17194243}, {12197, 17194499}, {12198, 17194755},
1408
  {12199, 17195011}, {12200, 17195267}, {12201, 17195523}, {12202, 17195779},
1409
  {12203, 17196035}, {12204, 17196291}, {12205, 17196547}, {12206, 17196803},
1410
  {12207, 17197059}, {12208, 17197315}, {12209, 17197571}, {12210, 17197827},
1411
  {12211, 17198083}, {12212, 17198339}, {12213, 17198595}, {12214, 17198851},
1412
  {12215, 17199107}, {12216, 17199363}, {12217, 17199619}, {12218, 17199875},
1413
  {12219, 17200131}, {12220, 17200387}, {12221, 17200643}, {12222, 17200899},
1414
  {12223, 17201155}, {12224, 17201411}, {12225, 17201667}, {12226, 17201923},
1415
  {12227, 17202179}, {12228, 17202435}, {12229, 17202691}, {12230, 17202947},
1416
  {12231, 17203203}, {12232, 17203459}, {12233, 17203715}, {12234, 17203971},
1417
  {12235, 17204227}, {12236, 17204483}, {12237, 17204739}, {12238, 17204995},
1418
  {12239, 17205251}, {12240, 17205507}, {12241, 17205763}, {12242, 17206019},
1419
  {12243, 17206275}, {12244, 17206531}, {12245, 17206787}, {12246, 2},
1420
  {12288, 16783875}, {12289, 1}, {12290, 17207043}, {12291, 1},
1421
  {12342, 17207299}, {12343, 1}, {12344, 17158147}, {12345, 17207555},
1422
  {12346, 17207811}, {12347, 1}, {12352, 2}, {12353, 1},
1423
  {12439, 2}, {12441, 1}, {12443, 33985283}, {12444, 33985795},
1424
  {12445, 1}, {12447, 33986307}, {12448, 1}, {12543, 33986819},
1425
  {12544, 2}, {12549, 1}, {12592, 2}, {12593, 17210115},
1426
  {12594, 17210371}, {12595, 17210627}, {12596, 17210883}, {12597, 17211139},
1427
  {12598, 17211395}, {12599, 17211651}, {12600, 17211907}, {12601, 17212163},
1428
  {12602, 17212419}, {12603, 17212675}, {12604, 17212931}, {12605, 17213187},
1429
  {12606, 17213443}, {12607, 17213699}, {12608, 17213955}, {12609, 17214211},
1430
  {12610, 17214467}, {12611, 17214723}, {12612, 17214979}, {12613, 17215235},
1431
  {12614, 17215491}, {12615, 17215747}, {12616, 17216003}, {12617, 17216259},
1432
  {12618, 17216515}, {12619, 17216771}, {12620, 17217027}, {12621, 17217283},
1433
  {12622, 17217539}, {12623, 17217795}, {12624, 17218051}, {12625, 17218307},
1434
  {12626, 17218563}, {12627, 17218819}, {12628, 17219075}, {12629, 17219331},
1435
  {12630, 17219587}, {12631, 17219843}, {12632, 17220099}, {12633, 17220355},
1436
  {12634, 17220611}, {12635, 17220867}, {12636, 17221123}, {12637, 17221379},
1437
  {12638, 17221635}, {12639, 17221891}, {12640, 17222147}, {12641, 17222403},
1438
  {12642, 17222659}, {12643, 17222915}, {12644, 0}, {12645, 17223171},
1439
  {12646, 17223427}, {12647, 17223683}, {12648, 17223939}, {12649, 17224195},
1440
  {12650, 17224451}, {12651, 17224707}, {12652, 17224963}, {12653, 17225219},
1441
  {12654, 17225475}, {12655, 17225731}, {12656, 17225987}, {12657, 17226243},
1442
  {12658, 17226499}, {12659, 17226755}, {12660, 17227011}, {12661, 17227267},
1443
  {12662, 17227523}, {12663, 17227779}, {12664, 17228035}, {12665, 17228291},
1444
  {12666, 17228547}, {12667, 17228803}, {12668, 17229059}, {12669, 17229315},
1445
  {12670, 17229571}, {12671, 17229827}, {12672, 17230083}, {12673, 17230339},
1446
  {12674, 17230595}, {12675, 17230851}, {12676, 17231107}, {12677, 17231363},
1447
  {12678, 17231619}, {12679, 17231875}, {12680, 17232131}, {12681, 17232387},
1448
  {12682, 17232643}, {12683, 17232899}, {12684, 17233155}, {12685, 17233411},
1449
  {12686, 17233667}, {12687, 2}, {12688, 1}, {12690, 17152259},
1450
  {12691, 17153795}, {12692, 17233923}, {12693, 17234179}, {12694, 17234435},
1451
  {12695, 17234691}, {12696, 17234947}, {12697, 17235203}, {12698, 17153283},
1452
  {12699, 17235459}, {12700, 17235715}, {12701, 17235971}, {12702, 17236227},
1453
  {12703, 17154307}, {12704, 1}, {12774, 2}, {12784, 1},
1454
  {12800, 50790915}, {12801, 50791683}, {12802, 50792451}, {12803, 50793219},
1455
  {12804, 50793987}, {12805, 50794755}, {12806, 50795523}, {12807, 50796291},
1456
  {12808, 50797059}, {12809, 50797827}, {12810, 50798595}, {12811, 50799363},
1457
  {12812, 50800131}, {12813, 50800899}, {12814, 50801667}, {12815, 50802435},
1458
  {12816, 50803203}, {12817, 50803971}, {12818, 50804739}, {12819, 50805507},
1459
  {12820, 50806275}, {12821, 50807043}, {12822, 50807811}, {12823, 50808579},
1460
  {12824, 50809347}, {12825, 50810115}, {12826, 50810883}, {12827, 50811651},
1461
  {12828, 50812419}, {12829, 67590403}, {12830, 67591427}, {12831, 2},
1462
  {12832, 50815235}, {12833, 50816003}, {12834, 50816771}, {12835, 50817539},
1463
  {12836, 50818307}, {12837, 50819075}, {12838, 50819843}, {12839, 50820611},
1464
  {12840, 50821379}, {12841, 50822147}, {12842, 50822915}, {12843, 50823683},
1465
  {12844, 50824451}, {12845, 50825219}, {12846, 50825987}, {12847, 50826755},
1466
  {12848, 50827523}, {12849, 50828291}, {12850, 50829059}, {12851, 50829827},
1467
  {12852, 50830595}, {12853, 50831363}, {12854, 50832131}, {12855, 50832899},
1468
  {12856, 50833667}, {12857, 50834435}, {12858, 50835203}, {12859, 50835971},
1469
  {12860, 50836739}, {12861, 50837507}, {12862, 50838275}, {12863, 50839043},
1470
  {12864, 50839811}, {12865, 50840579}, {12866, 50841347}, {12867, 50842115},
1471
  {12868, 17288451}, {12869, 17288707}, {12870, 17169155}, {12871, 17288963},
1472
  {12872, 1}, {12880, 50843651}, {12881, 33855747}, {12882, 34067203},
1473
  {12883, 33562371}, {12884, 34067715}, {12885, 34068227}, {12886, 34068739},
1474
  {12887, 34069251}, {12888, 34069763}, {12889, 34070275}, {12890, 34070787},
1475
  {12891, 33837571}, {12892, 33836803}, {12893, 34071299}, {12894, 34071811},
1476
  {12895, 34072323}, {12896, 17210115}, {12897, 17210883}, {12898, 17211651},
1477
  {12899, 17212163}, {12900, 17214211}, {12901, 17214467}, {12902, 17215235},
1478
  {12903, 17215747}, {12904, 17216003}, {12905, 17216515}, {12906, 17216771},
1479
  {12907, 17217027}, {12908, 17217283}, {12909, 17217539}, {12910, 17247491},
1480
  {12911, 17248259}, {12912, 17249027}, {12913, 17249795}, {12914, 17250563},
1481
  {12915, 17251331}, {12916, 17252099}, {12917, 17252867}, {12918, 17253635},
1482
  {12919, 17254403}, {12920, 17255171}, {12921, 17255939}, {12922, 17256707},
1483
  {12923, 17257475}, {12924, 34072835}, {12925, 34073347}, {12926, 17296643},
1484
  {12927, 1}, {12928, 17152259}, {12929, 17153795}, {12930, 17233923},
1485
  {12931, 17234179}, {12932, 17264131}, {12933, 17264899}, {12934, 17265667},
1486
  {12935, 17155075}, {12936, 17267203}, {12937, 17158147}, {12938, 17170947},
1487
  {12939, 17174019}, {12940, 17173763}, {12941, 17171203}, {12942, 17194755},
1488
  {12943, 17160195}, {12944, 17170435}, {12945, 17274115}, {12946, 17274883},
1489
  {12947, 17275651}, {12948, 17276419}, {12949, 17277187}, {12950, 17277955},
1490
  {12951, 17278723}, {12952, 17279491}, {12953, 17296899}, {12954, 17297155},
1491
  {12955, 17161731}, {12956, 17297411}, {12957, 17297667}, {12958, 17297923},
1492
  {12959, 17298179}, {12960, 17298435}, {12961, 17286403}, {12962, 17298691},
1493
  {12963, 17298947}, {12964, 17234435}, {12965, 17234691}, {12966, 17234947},
1494
  {12967, 17299203}, {12968, 17299459}, {12969, 17299715}, {12970, 17299971},
1495
  {12971, 17281795}, {12972, 17282563}, {12973, 17283331}, {12974, 17284099},
1496
  {12975, 17284867}, {12976, 17300227}, {12977, 34077699}, {12978, 34078211},
1497
  {12979, 34078723}, {12980, 34079235}, {12981, 34079747}, {12982, 33564931},
1498
  {12983, 34067971}, {12984, 34072067}, {12985, 34080259}, {12986, 34080771},
1499
  {12987, 34081283}, {12988, 34081795}, {12989, 34082307}, {12990, 34082819},
1500
  {12991, 34083331}, {12992, 34083843}, {12993, 34084355}, {12994, 34084867},
1501
  {12995, 34085379}, {12996, 34085891}, {12997, 34086403}, {12998, 34086915},
1502
  {12999, 34087427}, {13000, 34087939}, {13001, 50865667}, {13002, 50866435},
1503
  {13003, 50867203}, {13004, 34090755}, {13005, 50868483}, {13006, 34092035},
1504
  {13007, 50869763}, {13008, 17316099}, {13009, 17316355}, {13010, 17316611},
1505
  {13011, 17316867}, {13012, 17317123}, {13013, 17317379}, {13014, 17317635},
1506
  {13015, 17317891}, {13016, 17318147}, {13017, 17209603}, {13018, 17318403},
1507
  {13019, 17318659}, {13020, 17318915}, {13021, 17319171}, {13022, 17319427},
1508
  {13023, 17319683}, {13024, 17319939}, {13025, 17320195}, {13026, 17320451},
1509
  {13027, 17209859}, {13028, 17320707}, {13029, 17320963}, {13030, 17321219},
1510
  {13031, 17321475}, {13032, 17321731}, {13033, 17321987}, {13034, 17322243},
1511
  {13035, 17322499}, {13036, 17322755}, {13037, 17323011}, {13038, 17323267},
1512
  {13039, 17323523}, {13040, 17323779}, {13041, 17324035}, {13042, 17324291},
1513
  {13043, 17324547}, {13044, 17324803}, {13045, 17325059}, {13046, 17325315},
1514
  {13047, 17325571}, {13048, 17325827}, {13049, 17326083}, {13050, 17326339},
1515
  {13051, 17326595}, {13052, 17326851}, {13053, 17327107}, {13054, 17327363},
1516
  {13055, 34104835}, {13056, 67659779}, {13057, 67660803}, {13058, 67661827},
1517
  {13059, 50885635}, {13060, 67663619}, {13061, 50887427}, {13062, 50888195},
1518
  {13063, 84443395}, {13064, 67667459}, {13065, 50891267}, {13066, 50892035},
1519
  {13067, 50892803}, {13068, 67670787}, {13069, 67671811}, {13070, 50895619},
1520
  {13071, 50896387}, {13072, 34119939}, {13073, 50897667}, {13074, 67675651},
1521
  {13075, 67676675}, {13076, 34123267}, {13077, 84455427}, {13078, 101233923},
1522
  {13079, 84458243}, {13080, 50901507}, {13081, 84459523}, {13082, 84460803},
1523
  {13083, 67684867}, {13084, 50908675}, {13085, 50909443}, {13086, 50910211},
1524
  {13087, 67688195}, {13088, 84466435}, {13089, 67690499}, {13090, 50914307},
1525
  {13091, 50915075}, {13092, 50915843}, {13093, 34139395}, {13094, 34139907},
1526
  {13095, 34128643}, {13096, 34140419}, {13097, 50918147}, {13098, 50918915},
1527
  {13099, 84474115}, {13100, 50920963}, {13101, 67698947}, {13102, 84477187},
1528
  {13103, 50924035}, {13104, 34147587}, {13105, 34148099}, {13106, 84480259},
1529
  {13107, 67704323}, {13108, 84482563}, {13109, 50929411}, {13110, 84484611},
1530
  {13111, 34154243}, {13112, 50931971}, {13113, 50932739}, {13114, 50933507},
1531
  {13115, 50934275}, {13116, 50935043}, {13117, 67713027}, {13118, 50936835},
1532
  {13119, 34160387}, {13120, 50938115}, {13121, 50938883}, {13122, 50939651},
1533
  {13123, 67717635}, {13124, 50941443}, {13125, 50942211}, {13126, 50942979},
1534
  {13127, 84498179}, {13128, 67722243}, {13129, 34168835}, {13130, 84500995},
1535
  {13131, 34170627}, {13132, 67725571}, {13133, 67680003}, {13134, 50949379},
1536
  {13135, 50950147}, {13136, 50950915}, {13137, 67728899}, {13138, 34175491},
1537
  {13139, 50953219}, {13140, 67731203}, {13141, 34177795}, {13142, 84509955},
1538
  {13143, 50904323}, {13144, 34179587}, {13145, 34180099}, {13146, 34180611},
1539
  {13147, 34181123}, {13148, 34181635}, {13149, 34182147}, {13150, 34182659},
1540
  {13151, 34183171}, {13152, 34183683}, {13153, 34184195}, {13154, 50961923},
1541
  {13155, 50962691}, {13156, 50963459}, {13157, 50964227}, {13158, 50964995},
1542
  {13159, 50965763}, {13160, 50966531}, {13161, 50967299}, {13162, 50968067},
1543
  {13163, 50968835}, {13164, 50969603}, {13165, 50970371}, {13166, 50971139},
1544
  {13167, 50971907}, {13168, 50972675}, {13169, 50973443}, {13170, 34196995},
1545
  {13171, 34197507}, {13172, 50975235}, {13173, 34198787}, {13174, 34199299},
1546
  {13175, 34199811}, {13176, 50977539}, {13177, 50978307}, {13178, 34201859},
1547
  {13179, 34202371}, {13180, 34202883}, {13181, 34203395}, {13182, 34203907},
1548
  {13183, 67758851}, {13184, 34196483}, {13185, 34205443}, {13186, 34205955},
1549
  {13187, 34206467}, {13188, 34206979}, {13189, 34207491}, {13190, 34208003},
1550
  {13191, 34208515}, {13192, 50986243}, {13193, 67764227}, {13194, 34210819},
1551
  {13195, 34211331}, {13196, 34211843}, {13197, 34212355}, {13198, 34212867},
1552
  {13199, 34213379}, {13200, 34213891}, {13201, 50991619}, {13202, 50992387},
1553
  {13203, 50990851}, {13204, 50993155}, {13205, 34216707}, {13206, 34217219},
1554
  {13207, 34217731}, {13208, 33556995}, {13209, 34218243}, {13210, 34218755},
1555
  {13211, 34219267}, {13212, 34219779}, {13213, 34220291}, {13214, 34220803},
1556
  {13215, 50998531}, {13216, 50999299}, {13217, 34200579}, {13218, 51000067},
1557
  {13219, 51000835}, {13220, 51001603}, {13221, 34201347}, {13222, 51002371},
1558
  {13223, 51003139}, {13224, 67781123}, {13225, 34196483}, {13226, 51004931},
1559
  {13227, 51005699}, {13228, 51006467}, {13229, 51007235}, {13230, 84562435},
1560
  {13231, 101340931}, {13232, 34233603}, {13233, 34234115}, {13234, 34234627},
1561
  {13235, 34235139}, {13236, 34235651}, {13237, 34236163}, {13238, 34236675},
1562
  {13239, 34237187}, {13240, 34237699}, {13241, 34237187}, {13242, 34238211},
1563
  {13243, 34238723}, {13244, 34239235}, {13245, 34239747}, {13246, 34240259},
1564
  {13247, 34239747}, {13248, 34240771}, {13249, 34241283}, {13250, 2},
1565
  {13251, 34241795}, {13252, 33827331}, {13253, 33554947}, {13254, 67796739},
1566
  {13255, 2}, {13256, 34243331}, {13257, 34243843}, {13258, 34244355},
1567
  {13259, 34196227}, {13260, 34244867}, {13261, 34245379}, {13262, 34220803},
1568
  {13263, 34245891}, {13264, 33557251}, {13265, 34246403}, {13266, 51024131},
1569
  {13267, 34247683}, {13268, 34208003}, {13269, 51025411}, {13270, 51026179},
1570
  {13271, 34249731}, {13272, 2}, {13273, 51027459}, {13274, 34251011},
1571
  {13275, 34231811}, {13276, 34251523}, {13277, 34252035}, {13278, 51029763},
1572
  {13279, 51030531}, {13280, 34254083}, {13281, 34254595}, {13282, 34255107},
1573
  {13283, 34255619}, {13284, 34256131}, {13285, 34256643}, {13286, 34257155},
1574
  {13287, 34257667}, {13288, 34258179}, {13289, 51035907}, {13290, 51036675},
1575
  {13291, 51037443}, {13292, 51038211}, {13293, 51038979}, {13294, 51039747},
1576
  {13295, 51040515}, {13296, 51041283}, {13297, 51042051}, {13298, 51042819},
1577
  {13299, 51043587}, {13300, 51044355}, {13301, 51045123}, {13302, 51045891},
1578
  {13303, 51046659}, {13304, 51047427}, {13305, 51048195}, {13306, 51048963},
1579
  {13307, 51049731}, {13308, 51050499}, {13309, 51051267}, {13310, 51052035},
1580
  {13311, 51052803}, {13312, 1}, {42125, 2}, {42128, 1},
1581
  {42183, 2}, {42192, 1}, {42540, 2}, {42560, 17499139},
1582
  {42561, 1}, {42562, 17499395}, {42563, 1}, {42564, 17499651},
1583
  {42565, 1}, {42566, 17499907}, {42567, 1}, {42568, 17500163},
1584
  {42569, 1}, {42570, 16946435}, {42571, 1}, {42572, 17500419},
1585
  {42573, 1}, {42574, 17500675}, {42575, 1}, {42576, 17500931},
1586
  {42577, 1}, {42578, 17501187}, {42579, 1}, {42580, 17501443},
1587
  {42581, 1}, {42582, 17501699}, {42583, 1}, {42584, 17501955},
1588
  {42585, 1}, {42586, 17502211}, {42587, 1}, {42588, 17502467},
1589
  {42589, 1}, {42590, 17502723}, {42591, 1}, {42592, 17502979},
1590
  {42593, 1}, {42594, 17503235}, {42595, 1}, {42596, 17503491},
1591
  {42597, 1}, {42598, 17503747}, {42599, 1}, {42600, 17504003},
1592
  {42601, 1}, {42602, 17504259}, {42603, 1}, {42604, 17504515},
1593
  {42605, 1}, {42624, 17504771}, {42625, 1}, {42626, 17505027},
1594
  {42627, 1}, {42628, 17505283}, {42629, 1}, {42630, 17505539},
1595
  {42631, 1}, {42632, 17505795}, {42633, 1}, {42634, 17506051},
1596
  {42635, 1}, {42636, 17506307}, {42637, 1}, {42638, 17506563},
1597
  {42639, 1}, {42640, 17506819}, {42641, 1}, {42642, 17507075},
1598
  {42643, 1}, {42644, 17507331}, {42645, 1}, {42646, 17507587},
1599
  {42647, 1}, {42648, 17507843}, {42649, 1}, {42650, 17508099},
1600
  {42651, 1}, {42652, 16873219}, {42653, 16873731}, {42654, 1},
1601
  {42744, 2}, {42752, 1}, {42786, 17508355}, {42787, 1},
1602
  {42788, 17508611}, {42789, 1}, {42790, 17508867}, {42791, 1},
1603
  {42792, 17509123}, {42793, 1}, {42794, 17509379}, {42795, 1},
1604
  {42796, 17509635}, {42797, 1}, {42798, 17509891}, {42799, 1},
1605
  {42802, 17510147}, {42803, 1}, {42804, 17510403}, {42805, 1},
1606
  {42806, 17510659}, {42807, 1}, {42808, 17510915}, {42809, 1},
1607
  {42810, 17511171}, {42811, 1}, {42812, 17511427}, {42813, 1},
1608
  {42814, 17511683}, {42815, 1}, {42816, 17511939}, {42817, 1},
1609
  {42818, 17512195}, {42819, 1}, {42820, 17512451}, {42821, 1},
1610
  {42822, 17512707}, {42823, 1}, {42824, 17512963}, {42825, 1},
1611
  {42826, 17513219}, {42827, 1}, {42828, 17513475}, {42829, 1},
1612
  {42830, 17513731}, {42831, 1}, {42832, 17513987}, {42833, 1},
1613
  {42834, 17514243}, {42835, 1}, {42836, 17514499}, {42837, 1},
1614
  {42838, 17514755}, {42839, 1}, {42840, 17515011}, {42841, 1},
1615
  {42842, 17515267}, {42843, 1}, {42844, 17515523}, {42845, 1},
1616
  {42846, 17515779}, {42847, 1}, {42848, 17516035}, {42849, 1},
1617
  {42850, 17516291}, {42851, 1}, {42852, 17516547}, {42853, 1},
1618
  {42854, 17516803}, {42855, 1}, {42856, 17517059}, {42857, 1},
1619
  {42858, 17517315}, {42859, 1}, {42860, 17517571}, {42861, 1},
1620
  {42862, 17517827}, {42863, 1}, {42864, 17517827}, {42865, 1},
1621
  {42873, 17518083}, {42874, 1}, {42875, 17518339}, {42876, 1},
1622
  {42877, 17518595}, {42878, 17518851}, {42879, 1}, {42880, 17519107},
1623
  {42881, 1}, {42882, 17519363}, {42883, 1}, {42884, 17519619},
1624
  {42885, 1}, {42886, 17519875}, {42887, 1}, {42891, 17520131},
1625
  {42892, 1}, {42893, 16961539}, {42894, 1}, {42896, 17520387},
1626
  {42897, 1}, {42898, 17520643}, {42899, 1}, {42902, 17520899},
1627
  {42903, 1}, {42904, 17521155}, {42905, 1}, {42906, 17521411},
1628
  {42907, 1}, {42908, 17521667}, {42909, 1}, {42910, 17521923},
1629
  {42911, 1}, {42912, 17522179}, {42913, 1}, {42914, 17522435},
1630
  {42915, 1}, {42916, 17522691}, {42917, 1}, {42918, 17522947},
1631
  {42919, 1}, {42920, 17523203}, {42921, 1}, {42922, 16841475},
1632
  {42923, 16959235}, {42924, 16961283}, {42925, 17523459}, {42926, 16961795},
1633
  {42927, 1}, {42928, 17523715}, {42929, 17523971}, {42930, 16962307},
1634
  {42931, 17524227}, {42932, 17524483}, {42933, 1}, {42934, 17524739},
1635
  {42935, 1}, {42936, 17524995}, {42937, 1}, {42938, 17525251},
1636
  {42939, 1}, {42940, 17525507}, {42941, 1}, {42942, 17525763},
1637
  {42943, 1}, {42944, 17526019}, {42945, 1}, {42946, 17526275},
1638
  {42947, 1}, {42948, 17526531}, {42949, 16964611}, {42950, 17526787},
1639
  {42951, 17527043}, {42952, 1}, {42953, 17527299}, {42954, 1},
1640
  {42955, 17527555}, {42956, 17527811}, {42957, 1}, {42958, 17528067},
1641
  {42959, 1}, {42960, 17528323}, {42961, 1}, {42962, 17528579},
1642
  {42963, 1}, {42964, 17528835}, {42965, 1}, {42966, 17529091},
1643
  {42967, 1}, {42968, 17529347}, {42969, 1}, {42970, 17529603},
1644
  {42971, 1}, {42972, 17529859}, {42973, 2}, {42993, 16781827},
1645
  {42994, 16777731}, {42995, 16778499}, {42996, 16781315}, {42997, 17530115},
1646
  {42998, 1}, {43000, 16802051}, {43001, 16808195}, {43002, 1},
1647
  {43053, 2}, {43056, 1}, {43066, 2}, {43072, 1},
1648
  {43128, 2}, {43136, 1}, {43206, 2}, {43214, 1},
1649
  {43226, 2}, {43232, 1}, {43348, 2}, {43359, 1},
1650
  {43389, 2}, {43392, 1}, {43470, 2}, {43471, 1},
1651
  {43482, 2}, {43486, 1}, {43519, 2}, {43520, 1},
1652
  {43575, 2}, {43584, 1}, {43598, 2}, {43600, 1},
1653
  {43610, 2}, {43612, 1}, {43715, 2}, {43739, 1},
1654
  {43767, 2}, {43777, 1}, {43783, 2}, {43785, 1},
1655
  {43791, 2}, {43793, 1}, {43799, 2}, {43808, 1},
1656
  {43815, 2}, {43816, 1}, {43823, 2}, {43824, 1},
1657
  {43868, 17508867}, {43869, 17530371}, {43870, 17135363}, {43871, 17530627},
1658
  {43872, 1}, {43881, 17530883}, {43882, 1}, {43884, 2},
1659
  {43888, 17531139}, {43889, 17531395}, {43890, 17531651}, {43891, 17531907},
1660
  {43892, 17532163}, {43893, 17532419}, {43894, 17532675}, {43895, 17532931},
1661
  {43896, 17533187}, {43897, 17533443}, {43898, 17533699}, {43899, 17533955},
1662
  {43900, 17534211}, {43901, 17534467}, {43902, 17534723}, {43903, 17534979},
1663
  {43904, 17535235}, {43905, 17535491}, {43906, 17535747}, {43907, 17536003},
1664
  {43908, 17536259}, {43909, 17536515}, {43910, 17536771}, {43911, 17537027},
1665
  {43912, 17537283}, {43913, 17537539}, {43914, 17537795}, {43915, 17538051},
1666
  {43916, 17538307}, {43917, 17538563}, {43918, 17538819}, {43919, 17539075},
1667
  {43920, 17539331}, {43921, 17539587}, {43922, 17539843}, {43923, 17540099},
1668
  {43924, 17540355}, {43925, 17540611}, {43926, 17540867}, {43927, 17541123},
1669
  {43928, 17541379}, {43929, 17541635}, {43930, 17541891}, {43931, 17542147},
1670
  {43932, 17542403}, {43933, 17542659}, {43934, 17542915}, {43935, 17543171},
1671
  {43936, 17543427}, {43937, 17543683}, {43938, 17543939}, {43939, 17544195},
1672
  {43940, 17544451}, {43941, 17544707}, {43942, 17544963}, {43943, 17545219},
1673
  {43944, 17545475}, {43945, 17545731}, {43946, 17545987}, {43947, 17546243},
1674
  {43948, 17546499}, {43949, 17546755}, {43950, 17547011}, {43951, 17547267},
1675
  {43952, 17547523}, {43953, 17547779}, {43954, 17548035}, {43955, 17548291},
1676
  {43956, 17548547}, {43957, 17548803}, {43958, 17549059}, {43959, 17549315},
1677
  {43960, 17549571}, {43961, 17549827}, {43962, 17550083}, {43963, 17550339},
1678
  {43964, 17550595}, {43965, 17550851}, {43966, 17551107}, {43967, 17551363},
1679
  {43968, 1}, {44014, 2}, {44016, 1}, {44026, 2},
1680
  {44032, 1}, {55204, 2}, {55216, 1}, {55239, 2},
1681
  {55243, 1}, {55292, 2}, {63744, 17551619}, {63745, 17551875},
1682
  {63746, 17192707}, {63747, 17552131}, {63748, 17552387}, {63749, 17552643},
1683
  {63750, 17552899}, {63751, 17206531}, {63753, 17553155}, {63754, 17194755},
1684
  {63755, 17553411}, {63756, 17553667}, {63757, 17553923}, {63758, 17554179},
1685
  {63759, 17554435}, {63760, 17554691}, {63761, 17554947}, {63762, 17555203},
1686
  {63763, 17555459}, {63764, 17555715}, {63765, 17555971}, {63766, 17556227},
1687
  {63767, 17556483}, {63768, 17556739}, {63769, 17556995}, {63770, 17557251},
1688
  {63771, 17557507}, {63772, 17557763}, {63773, 17558019}, {63774, 17558275},
1689
  {63775, 17558531}, {63776, 17558787}, {63777, 17559043}, {63778, 17559299},
1690
  {63779, 17559555}, {63780, 17559811}, {63781, 17560067}, {63782, 17560323},
1691
  {63783, 17560579}, {63784, 17560835}, {63785, 17561091}, {63786, 17561347},
1692
  {63787, 17561603}, {63788, 17561859}, {63789, 17562115}, {63790, 17562371},
1693
  {63791, 17562627}, {63792, 17562883}, {63793, 17563139}, {63794, 17563395},
1694
  {63795, 17563651}, {63796, 17184003}, {63797, 17563907}, {63798, 17564163},
1695
  {63799, 17564419}, {63800, 17564675}, {63801, 17564931}, {63802, 17565187},
1696
  {63803, 17565443}, {63804, 17565699}, {63805, 17565955}, {63806, 17566211},
1697
  {63807, 17566467}, {63808, 17202691}, {63809, 17566723}, {63810, 17566979},
1698
  {63811, 17567235}, {63812, 17567491}, {63813, 17567747}, {63814, 17568003},
1699
  {63815, 17568259}, {63816, 17568515}, {63817, 17568771}, {63818, 17569027},
1700
  {63819, 17569283}, {63820, 17569539}, {63821, 17569795}, {63822, 17570051},
1701
  {63823, 17570307}, {63824, 17570563}, {63825, 17570819}, {63826, 17571075},
1702
  {63827, 17571331}, {63828, 17571587}, {63829, 17571843}, {63830, 17572099},
1703
  {63831, 17572355}, {63832, 17572611}, {63833, 17572867}, {63834, 17573123},
1704
  {63835, 17573379}, {63836, 17555715}, {63837, 17573635}, {63838, 17573891},
1705
  {63839, 17574147}, {63840, 17574403}, {63841, 17574659}, {63842, 17574915},
1706
  {63843, 17575171}, {63844, 17575427}, {63845, 17575683}, {63846, 17575939},
1707
  {63847, 17576195}, {63848, 17576451}, {63849, 17576707}, {63850, 17576963},
1708
  {63851, 17577219}, {63852, 17577475}, {63853, 17577731}, {63854, 17577987},
1709
  {63855, 17578243}, {63856, 17578499}, {63857, 17193219}, {63858, 17578755},
1710
  {63859, 17579011}, {63860, 17579267}, {63861, 17579523}, {63862, 17579779},
1711
  {63863, 17580035}, {63864, 17580291}, {63865, 17580547}, {63866, 17580803},
1712
  {63867, 17581059}, {63868, 17581315}, {63869, 17581571}, {63870, 17581827},
1713
  {63871, 17582083}, {63872, 17582339}, {63873, 17161731}, {63874, 17582595},
1714
  {63875, 17582851}, {63876, 17583107}, {63877, 17583363}, {63878, 17583619},
1715
  {63879, 17583875}, {63880, 17584131}, {63881, 17584387}, {63882, 17156867},
1716
  {63883, 17584643}, {63884, 17584899}, {63885, 17585155}, {63886, 17585411},
1717
  {63887, 17585667}, {63888, 17585923}, {63889, 17586179}, {63890, 17586435},
1718
  {63891, 17586691}, {63892, 17586947}, {63893, 17587203}, {63894, 17587459},
1719
  {63895, 17587715}, {63896, 17587971}, {63897, 17588227}, {63898, 17588483},
1720
  {63899, 17588739}, {63900, 17588995}, {63901, 17589251}, {63902, 17589507},
1721
  {63903, 17589763}, {63904, 17590019}, {63905, 17578243}, {63906, 17590275},
1722
  {63907, 17590531}, {63908, 17590787}, {63909, 17591043}, {63910, 17591299},
1723
  {63911, 17591555}, {63912, 17327619}, {63913, 17591811}, {63914, 17574147},
1724
  {63915, 17592067}, {63916, 17592323}, {63917, 17592579}, {63918, 17592835},
1725
  {63919, 17593091}, {63920, 17593347}, {63921, 17593603}, {63922, 17593859},
1726
  {63923, 17594115}, {63924, 17594371}, {63925, 17594627}, {63926, 17594883},
1727
  {63927, 17595139}, {63928, 17595395}, {63929, 17595651}, {63930, 17595907},
1728
  {63931, 17596163}, {63932, 17596419}, {63933, 17596675}, {63934, 17596931},
1729
  {63935, 17555715}, {63936, 17597187}, {63937, 17597443}, {63938, 17597699},
1730
  {63939, 17597955}, {63940, 17206275}, {63941, 17598211}, {63942, 17598467},
1731
  {63943, 17598723}, {63944, 17598979}, {63945, 17599235}, {63946, 17599491},
1732
  {63947, 17599747}, {63948, 17600003}, {63949, 17600259}, {63950, 17600515},
1733
  {63951, 17600771}, {63952, 17601027}, {63953, 17264899}, {63954, 17601283},
1734
  {63955, 17601539}, {63956, 17601795}, {63957, 17602051}, {63958, 17602307},
1735
  {63959, 17602563}, {63960, 17602819}, {63961, 17603075}, {63962, 17603331},
1736
  {63963, 17574659}, {63964, 17603587}, {63965, 17603843}, {63966, 17604099},
1737
  {63967, 17604355}, {63968, 17604611}, {63969, 17604867}, {63970, 17605123},
1738
  {63971, 17605379}, {63972, 17605635}, {63973, 17605891}, {63974, 17606147},
1739
  {63975, 17606403}, {63976, 17606659}, {63977, 17194499}, {63978, 17606915},
1740
  {63979, 17607171}, {63980, 17607427}, {63981, 17607683}, {63982, 17607939},
1741
  {63983, 17608195}, {63984, 17608451}, {63985, 17608707}, {63986, 17608963},
1742
  {63987, 17609219}, {63988, 17609475}, {63989, 17609731}, {63990, 17609987},
1743
  {63991, 17181955}, {63992, 17610243}, {63993, 17610499}, {63994, 17610755},
1744
  {63995, 17611011}, {63996, 17611267}, {63997, 17611523}, {63998, 17611779},
1745
  {63999, 17612035}, {64000, 17612291}, {64001, 17612547}, {64002, 17612803},
1746
  {64003, 17613059}, {64004, 17613315}, {64005, 17613571}, {64006, 17613827},
1747
  {64007, 17614083}, {64008, 17188867}, {64009, 17614339}, {64010, 17189635},
1748
  {64011, 17614595}, {64012, 17614851}, {64013, 17615107}, {64014, 1},
1749
  {64016, 17615363}, {64017, 1}, {64018, 17615619}, {64019, 1},
1750
  {64021, 17615875}, {64022, 17616131}, {64023, 17616387}, {64024, 17616643},
1751
  {64025, 17616899}, {64026, 17617155}, {64027, 17617411}, {64028, 17617667},
1752
  {64029, 17617923}, {64030, 17183747}, {64031, 1}, {64032, 17618179},
1753
  {64033, 1}, {64034, 17618435}, {64035, 1}, {64037, 17618691},
1754
  {64038, 17618947}, {64039, 1}, {64042, 17619203}, {64043, 17619459},
1755
  {64044, 17619715}, {64045, 17619971}, {64046, 17620227}, {64047, 17620483},
1756
  {64048, 17620739}, {64049, 17620995}, {64050, 17621251}, {64051, 17621507},
1757
  {64052, 17621763}, {64053, 17622019}, {64054, 17622275}, {64055, 17622531},
1758
  {64056, 17622787}, {64057, 17623043}, {64058, 17623299}, {64059, 17623555},
1759
  {64060, 17163523}, {64061, 17623811}, {64062, 17624067}, {64063, 17624323},
1760
  {64064, 17624579}, {64065, 17624835}, {64066, 17625091}, {64067, 17625347},
1761
  {64068, 17625603}, {64069, 17625859}, {64070, 17626115}, {64071, 17626371},
1762
  {64072, 17626627}, {64073, 17626883}, {64074, 17627139}, {64075, 17627395},
1763
  {64076, 17275651}, {64077, 17627651}, {64078, 17627907}, {64079, 17628163},
1764
  {64080, 17628419}, {64081, 17278723}, {64082, 17628675}, {64083, 17628931},
1765
  {64084, 17629187}, {64085, 17629443}, {64086, 17629699}, {64087, 17587459},
1766
  {64088, 17629955}, {64089, 17630211}, {64090, 17630467}, {64091, 17630723},
1767
  {64092, 17630979}, {64093, 17631235}, {64095, 17631491}, {64096, 17631747},
1768
  {64097, 17632003}, {64098, 17632259}, {64099, 17632515}, {64100, 17632771},
1769
  {64101, 17633027}, {64102, 17633283}, {64103, 17618691}, {64104, 17633539},
1770
  {64105, 17633795}, {64106, 17634051}, {64107, 17634307}, {64108, 17634563},
1771
  {64109, 17634819}, {64110, 2}, {64112, 17635075}, {64113, 17635331},
1772
  {64114, 17635587}, {64115, 17635843}, {64116, 17636099}, {64117, 17636355},
1773
  {64118, 17636611}, {64119, 17636867}, {64120, 17622275}, {64121, 17637123},
1774
  {64122, 17637379}, {64123, 17637635}, {64124, 17615363}, {64125, 17637891},
1775
  {64126, 17638147}, {64127, 17638403}, {64128, 17638659}, {64129, 17638915},
1776
  {64130, 17639171}, {64131, 17639427}, {64132, 17639683}, {64133, 17639939},
1777
  {64134, 17640195}, {64135, 17640451}, {64136, 17640707}, {64137, 17624323},
1778
  {64138, 17640963}, {64139, 17624579}, {64140, 17641219}, {64141, 17641475},
1779
  {64142, 17641731}, {64143, 17641987}, {64144, 17642243}, {64145, 17615619},
1780
  {64146, 17561091}, {64147, 17642499}, {64148, 17642755}, {64149, 17171971},
1781
  {64150, 17578499}, {64151, 17599491}, {64152, 17643011}, {64153, 17643267},
1782
  {64154, 17626371}, {64155, 17643523}, {64156, 17626627}, {64157, 17643779},
1783
  {64158, 17644035}, {64159, 17644291}, {64160, 17616131}, {64161, 17644547},
1784
  {64162, 17644803}, {64163, 17645059}, {64164, 17645315}, {64165, 17645571},
1785
  {64166, 17616387}, {64167, 17645827}, {64168, 17646083}, {64169, 17646339},
1786
  {64170, 17646595}, {64171, 17646851}, {64172, 17647107}, {64173, 17629699},
1787
  {64174, 17647363}, {64175, 17647619}, {64176, 17587459}, {64177, 17647875},
1788
  {64178, 17630723}, {64179, 17648131}, {64180, 17648387}, {64181, 17648643},
1789
  {64182, 17648899}, {64183, 17649155}, {64184, 17632003}, {64185, 17649411},
1790
  {64186, 17618435}, {64187, 17649667}, {64188, 17632259}, {64189, 17573635},
1791
  {64190, 17649923}, {64191, 17632515}, {64192, 17650179}, {64193, 17633027},
1792
  {64194, 17650435}, {64195, 17650691}, {64196, 17650947}, {64197, 17651203},
1793
  {64198, 17651459}, {64199, 17633539}, {64200, 17617667}, {64201, 17651715},
1794
  {64202, 17633795}, {64203, 17651971}, {64204, 17634051}, {64205, 17652227},
1795
  {64206, 17206531}, {64207, 17652483}, {64208, 17652739}, {64209, 17652995},
1796
  {64210, 17653251}, {64211, 17653507}, {64212, 17653763}, {64213, 17654019},
1797
  {64214, 17654275}, {64215, 17654531}, {64216, 17654787}, {64217, 17655043},
1798
  {64218, 2}, {64256, 34432515}, {64257, 34433027}, {64258, 34433539},
1799
  {64259, 51209987}, {64260, 51211267}, {64261, 33559043}, {64263, 2},
1800
  {64275, 34434819}, {64276, 34435331}, {64277, 34435843}, {64278, 34436355},
1801
  {64279, 34436867}, {64280, 2}, {64285, 34437379}, {64286, 1},
1802
  {64287, 34437891}, {64288, 17661187}, {64289, 17054467}, {64290, 17055235},
1803
  {64291, 17661443}, {64292, 17661699}, {64293, 17661955}, {64294, 17662211},
1804
  {64295, 17662467}, {64296, 17662723}, {64297, 17047043}, {64298, 34440195},
1805
  {64299, 34440707}, {64300, 51218435}, {64301, 51219203}, {64302, 34442755},
1806
  {64303, 34443267}, {64304, 34443779}, {64305, 34444291}, {64306, 34444803},
1807
  {64307, 34445315}, {64308, 34445827}, {64309, 34446339}, {64310, 34446851},
1808
  {64311, 2}, {64312, 34447363}, {64313, 34447875}, {64314, 34448387},
1809
  {64315, 34448899}, {64316, 34449411}, {64317, 2}, {64318, 34449923},
1810
  {64319, 2}, {64320, 34450435}, {64321, 34450947}, {64322, 2},
1811
  {64323, 34451459}, {64324, 34451971}, {64325, 2}, {64326, 34452483},
1812
  {64327, 34452995}, {64328, 34453507}, {64329, 34441219}, {64330, 34454019},
1813
  {64331, 34454531}, {64332, 34455043}, {64333, 34455555}, {64334, 34456067},
1814
  {64335, 34456579}, {64336, 17679875}, {64338, 17680131}, {64342, 17680387},
1815
  {64346, 17680643}, {64350, 17680899}, {64354, 17681155}, {64358, 17681411},
1816
  {64362, 17681667}, {64366, 17681923}, {64370, 17682179}, {64374, 17682435},
1817
  {64378, 17682691}, {64382, 17682947}, {64386, 17683203}, {64388, 17683459},
1818
  {64390, 17683715}, {64392, 17683971}, {64394, 17684227}, {64396, 17684483},
1819
  {64398, 17684739}, {64402, 17684995}, {64406, 17685251}, {64410, 17685507},
1820
  {64414, 17685763}, {64416, 17686019}, {64420, 17686275}, {64422, 17686531},
1821
  {64426, 17686787}, {64430, 17687043}, {64432, 17687299}, {64434, 1},
1822
  {64467, 17687555}, {64471, 16911619}, {64473, 17687811}, {64475, 17688067},
1823
  {64477, 33688835}, {64478, 17688323}, {64480, 17688579}, {64482, 17688835},
1824
  {64484, 17689091}, {64488, 17689347}, {64490, 34466819}, {64492, 34467331},
1825
  {64494, 34467843}, {64496, 34468355}, {64498, 34468867}, {64500, 34469379},
1826
  {64502, 34469891}, {64505, 34470403}, {64508, 17693699}, {64512, 34471171},
1827
  {64513, 34471683}, {64514, 34472195}, {64515, 34470403}, {64516, 34472707},
1828
  {64517, 34473219}, {64518, 34473731}, {64519, 34474243}, {64520, 34474755},
1829
  {64521, 34475267}, {64522, 34475779}, {64523, 34476291}, {64524, 34476803},
1830
  {64525, 34477315}, {64526, 34477827}, {64527, 34478339}, {64528, 34478851},
1831
  {64529, 34479363}, {64530, 34479875}, {64531, 34480387}, {64532, 34480899},
1832
  {64533, 34481411}, {64534, 34481923}, {64535, 34481667}, {64536, 34482435},
1833
  {64537, 34482947}, {64538, 34483459}, {64539, 34483971}, {64540, 34484483},
1834
  {64541, 34484995}, {64542, 34485507}, {64543, 34486019}, {64544, 34486531},
1835
  {64545, 34487043}, {64546, 34487555}, {64547, 34488067}, {64548, 34488579},
1836
  {64549, 34489091}, {64550, 34489603}, {64551, 34490115}, {64552, 34490627},
1837
  {64553, 34491139}, {64554, 34491651}, {64555, 34492163}, {64556, 34492675},
1838
  {64557, 34493187}, {64558, 34493699}, {64559, 34494211}, {64560, 34494723},
1839
  {64561, 34495235}, {64562, 34495747}, {64563, 34496259}, {64564, 34496771},
1840
  {64565, 34497283}, {64566, 34497795}, {64567, 34498307}, {64568, 34498819},
1841
  {64569, 34499331}, {64570, 34499843}, {64571, 34500355}, {64572, 34500867},
1842
  {64573, 34501379}, {64574, 34501891}, {64575, 34502403}, {64576, 34502915},
1843
  {64577, 34503427}, {64578, 34503939}, {64579, 34504451}, {64580, 34504963},
1844
  {64581, 34505475}, {64582, 34482179}, {64583, 34482691}, {64584, 34505987},
1845
  {64585, 34506499}, {64586, 34507011}, {64587, 34507523}, {64588, 34508035},
1846
  {64589, 34508547}, {64590, 34509059}, {64591, 34509571}, {64592, 34510083},
1847
  {64593, 34510595}, {64594, 34511107}, {64595, 34511619}, {64596, 34512131},
1848
  {64597, 34481155}, {64598, 34512643}, {64599, 34513155}, {64600, 34505219},
1849
  {64601, 34513667}, {64602, 34512387}, {64603, 34514179}, {64604, 34514691},
1850
  {64605, 34515203}, {64606, 51292931}, {64607, 51293699}, {64608, 51294467},
1851
  {64609, 51295235}, {64610, 51296003}, {64611, 51296771}, {64612, 34520323},
1852
  {64613, 34520835}, {64614, 34472195}, {64615, 34521347}, {64616, 34470403},
1853
  {64617, 34472707}, {64618, 34521859}, {64619, 34522371}, {64620, 34474755},
1854
  {64621, 34522883}, {64622, 34475267}, {64623, 34475779}, {64624, 34523395},
1855
  {64625, 34523907}, {64626, 34477827}, {64627, 34524419}, {64628, 34478339},
1856
  {64629, 34478851}, {64630, 34524931}, {64631, 34525443}, {64632, 34479875},
1857
  {64633, 34525955}, {64634, 34480387}, {64635, 34480899}, {64636, 34495235},
1858
  {64637, 34495747}, {64638, 34497283}, {64639, 34497795}, {64640, 34498307},
1859
  {64641, 34500355}, {64642, 34500867}, {64643, 34501379}, {64644, 34501891},
1860
  {64645, 34503939}, {64646, 34504451}, {64647, 34504963}, {64648, 34526467},
1861
  {64649, 34505987}, {64650, 34526979}, {64651, 34527491}, {64652, 34509059},
1862
  {64653, 34528003}, {64654, 34509571}, {64655, 34510083}, {64656, 34515203},
1863
  {64657, 34528515}, {64658, 34529027}, {64659, 34505219}, {64660, 34507267},
1864
  {64661, 34513667}, {64662, 34512387}, {64663, 34471171}, {64664, 34471683},
1865
  {64665, 34529539}, {64666, 34472195}, {64667, 34530051}, {64668, 34473219},
1866
  {64669, 34473731}, {64670, 34474243}, {64671, 34474755}, {64672, 34530563},
1867
  {64673, 34476291}, {64674, 34476803}, {64675, 34477315}, {64676, 34477827},
1868
  {64677, 34531075}, {64678, 34479875}, {64679, 34481411}, {64680, 34481923},
1869
  {64681, 34481667}, {64682, 34482435}, {64683, 34482947}, {64684, 34483971},
1870
  {64685, 34484483}, {64686, 34484995}, {64687, 34485507}, {64688, 34486019},
1871
  {64689, 34486531}, {64690, 34531587}, {64691, 34487043}, {64692, 34487555},
1872
  {64693, 34488067}, {64694, 34488579}, {64695, 34489091}, {64696, 34489603},
1873
  {64697, 34490627}, {64698, 34491139}, {64699, 34491651}, {64700, 34492163},
1874
  {64701, 34492675}, {64702, 34493187}, {64703, 34493699}, {64704, 34494211},
1875
  {64705, 34494723}, {64706, 34496259}, {64707, 34496771}, {64708, 34498819},
1876
  {64709, 34499331}, {64710, 34499843}, {64711, 34500355}, {64712, 34500867},
1877
  {64713, 34502403}, {64714, 34502915}, {64715, 34503427}, {64716, 34503939},
1878
  {64717, 34532099}, {64718, 34505475}, {64719, 34482179}, {64720, 34482691},
1879
  {64721, 34505987}, {64722, 34507523}, {64723, 34508035}, {64724, 34508547},
1880
  {64725, 34509059}, {64726, 34532611}, {64727, 34510595}, {64728, 34511107},
1881
  {64729, 34533123}, {64730, 34481155}, {64731, 34512643}, {64732, 34513155},
1882
  {64733, 34505219}, {64734, 34510339}, {64735, 34472195}, {64736, 34530051},
1883
  {64737, 34474755}, {64738, 34530563}, {64739, 34477827}, {64740, 34531075},
1884
  {64741, 34479875}, {64742, 34533635}, {64743, 34486019}, {64744, 34534147},
1885
  {64745, 34534659}, {64746, 34535171}, {64747, 34500355}, {64748, 34500867},
1886
  {64749, 34503939}, {64750, 34509059}, {64751, 34532611}, {64752, 34505219},
1887
  {64753, 34510339}, {64754, 51312899}, {64755, 51313667}, {64756, 51314435},
1888
  {64757, 34537987}, {64758, 34538499}, {64759, 34539011}, {64760, 34539523},
1889
  {64761, 34540035}, {64762, 34540547}, {64763, 34541059}, {64764, 34541571},
1890
  {64765, 34542083}, {64766, 34542595}, {64767, 34543107}, {64768, 34512899},
1891
  {64769, 34543619}, {64770, 34544131}, {64771, 34544643}, {64772, 34513411},
1892
  {64773, 34545155}, {64774, 34545667}, {64775, 34546179}, {64776, 34546691},
1893
  {64777, 34547203}, {64778, 34547715}, {64779, 34548227}, {64780, 34534659},
1894
  {64781, 34548739}, {64782, 34549251}, {64783, 34549763}, {64784, 34550275},
1895
  {64785, 34537987}, {64786, 34538499}, {64787, 34539011}, {64788, 34539523},
1896
  {64789, 34540035}, {64790, 34540547}, {64791, 34541059}, {64792, 34541571},
1897
  {64793, 34542083}, {64794, 34542595}, {64795, 34543107}, {64796, 34512899},
1898
  {64797, 34543619}, {64798, 34544131}, {64799, 34544643}, {64800, 34513411},
1899
  {64801, 34545155}, {64802, 34545667}, {64803, 34546179}, {64804, 34546691},
1900
  {64805, 34547203}, {64806, 34547715}, {64807, 34548227}, {64808, 34534659},
1901
  {64809, 34548739}, {64810, 34549251}, {64811, 34549763}, {64812, 34550275},
1902
  {64813, 34547203}, {64814, 34547715}, {64815, 34548227}, {64816, 34534659},
1903
  {64817, 34534147}, {64818, 34535171}, {64819, 34490115}, {64820, 34484483},
1904
  {64821, 34484995}, {64822, 34485507}, {64823, 34547203}, {64824, 34547715},
1905
  {64825, 34548227}, {64826, 34490115}, {64827, 34490627}, {64828, 34550787},
1906
  {64830, 1}, {64848, 51328515}, {64849, 51329283}, {64851, 51330051},
1907
  {64852, 51330819}, {64853, 51331587}, {64854, 51332355}, {64855, 51333123},
1908
  {64856, 51259139}, {64858, 51333891}, {64859, 51334659}, {64860, 51335427},
1909
  {64861, 51336195}, {64862, 51336963}, {64863, 51337731}, {64865, 51338499},
1910
  {64866, 51339267}, {64868, 51340035}, {64870, 51340803}, {64871, 51341571},
1911
  {64873, 51342339}, {64874, 51343107}, {64876, 51343875}, {64878, 51344643},
1912
  {64879, 51345411}, {64881, 51346179}, {64883, 51346947}, {64884, 51347715},
1913
  {64885, 51348483}, {64886, 51349251}, {64888, 51350019}, {64889, 51350787},
1914
  {64890, 51351555}, {64891, 51352323}, {64892, 51353091}, {64894, 51353859},
1915
  {64895, 51354627}, {64896, 51355395}, {64897, 51356163}, {64898, 51356931},
1916
  {64899, 51357699}, {64901, 51358467}, {64903, 51359235}, {64905, 51360003},
1917
  {64906, 51259395}, {64907, 51360771}, {64908, 51361539}, {64909, 51282691},
1918
  {64910, 51259907}, {64911, 51362307}, {64912, 1}, {64914, 51363075},
1919
  {64915, 51363843}, {64916, 51364611}, {64917, 51365379}, {64918, 51366147},
1920
  {64919, 51366915}, {64921, 51367683}, {64922, 51368451}, {64923, 51369219},
1921
  {64924, 51369987}, {64926, 51370755}, {64927, 51371523}, {64928, 51372291},
1922
  {64929, 51373059}, {64930, 51373827}, {64931, 51374595}, {64932, 51375363},
1923
  {64933, 51376131}, {64934, 51376899}, {64935, 51377667}, {64936, 51378435},
1924
  {64937, 51379203}, {64938, 51379971}, {64939, 51380739}, {64940, 51381507},
1925
  {64941, 51382275}, {64942, 51289859}, {64943, 51383043}, {64944, 51383811},
1926
  {64945, 51384579}, {64946, 51385347}, {64947, 51386115}, {64948, 51353859},
1927
  {64949, 51355395}, {64950, 51386883}, {64951, 51387651}, {64952, 51388419},
1928
  {64953, 51389187}, {64954, 51389955}, {64955, 51390723}, {64956, 51389955},
1929
  {64957, 51388419}, {64958, 51391491}, {64959, 51392259}, {64960, 51393027},
1930
  {64961, 51393795}, {64962, 51394563}, {64963, 51390723}, {64964, 51348483},
1931
  {64965, 51340803}, {64966, 51395331}, {64967, 51396099}, {64968, 1},
1932
  {64976, 2}, {65008, 51396867}, {65009, 51397635}, {65010, 68175619},
1933
  {65011, 68176643}, {65012, 68177667}, {65013, 68178691}, {65014, 68179715},
1934
  {65015, 68180739}, {65016, 68181763}, {65017, 51405571}, {65018, 303064579},
1935
  {65019, 135297027}, {65020, 68190211}, {65021, 1}, {65024, 0},
1936
  {65040, 17859587}, {65041, 17859843}, {65042, 2}, {65043, 17121027},
1937
  {65044, 16848643}, {65045, 17042947}, {65046, 17043971}, {65047, 17860099},
1938
  {65048, 17860355}, {65049, 2}, {65056, 1}, {65072, 2},
1939
  {65073, 17860611}, {65074, 17860867}, {65075, 17861123}, {65077, 17047811},
1940
  {65078, 17048067}, {65079, 17861379}, {65080, 17861635}, {65081, 17861891},
1941
  {65082, 17862147}, {65083, 17862403}, {65084, 17862659}, {65085, 17862915},
1942
  {65086, 17863171}, {65087, 17077763}, {65088, 17078019}, {65089, 17863427},
1943
  {65090, 17863683}, {65091, 17863939}, {65092, 17864195}, {65093, 1},
1944
  {65095, 17864451}, {65096, 17864707}, {65097, 33820675}, {65101, 17861123},
1945
  {65104, 17859587}, {65105, 17859843}, {65106, 2}, {65108, 16848643},
1946
  {65109, 17121027}, {65110, 17043971}, {65111, 17042947}, {65112, 17860611},
1947
  {65113, 17047811}, {65114, 17048067}, {65115, 17861379}, {65116, 17861635},
1948
  {65117, 17861891}, {65118, 17862147}, {65119, 17864963}, {65120, 17865219},
1949
  {65121, 17865475}, {65122, 17047043}, {65123, 17865731}, {65124, 17865987},
1950
  {65125, 17866243}, {65126, 17047555}, {65127, 2}, {65128, 17866499},
1951
  {65129, 17866755}, {65130, 17867011}, {65131, 17867267}, {65132, 2},
1952
  {65136, 34644739}, {65137, 34645251}, {65138, 34515715}, {65139, 1},
1953
  {65140, 34516483}, {65141, 2}, {65142, 34517251}, {65143, 34535683},
1954
  {65144, 34518019}, {65145, 34536451}, {65146, 34518787}, {65147, 34537219},
1955
  {65148, 34519555}, {65149, 34645763}, {65150, 34646275}, {65151, 34646787},
1956
  {65152, 17870083}, {65153, 17870339}, {65155, 17870595}, {65157, 17870851},
1957
  {65159, 17871107}, {65161, 17689603}, {65165, 16910595}, {65167, 17696003},
1958
  {65171, 17871363}, {65173, 17699075}, {65177, 17702147}, {65181, 17694211},
1959
  {65185, 17694723}, {65189, 17697283}, {65193, 17846787}, {65195, 17736963},
1960
  {65197, 17737475}, {65199, 17743875}, {65201, 17707267}, {65205, 17757443},
1961
  {65209, 17709315}, {65213, 17710339}, {65217, 17712387}, {65221, 17713411},
1962
  {65225, 17713923}, {65229, 17714947}, {65233, 17715971}, {65237, 17719043},
1963
  {65241, 17721091}, {65245, 17723395}, {65249, 17695235}, {65253, 17730307},
1964
  {65257, 17733379}, {65261, 16911107}, {65263, 17689347}, {65265, 16912131},
1965
  {65269, 34648835}, {65271, 34649347}, {65273, 34649859}, {65275, 34634755},
1966
  {65277, 2}, {65279, 0}, {65280, 2}, {65281, 17042947},
1967
  {65282, 17873155}, {65283, 17864963}, {65284, 17866755}, {65285, 17867011},
1968
  {65286, 17865219}, {65287, 17873411}, {65288, 17047811}, {65289, 17048067},
1969
  {65290, 17865475}, {65291, 17047043}, {65292, 17859587}, {65293, 17865731},
1970
  {65294, 17207043}, {65295, 17048579}, {65296, 17045507}, {65297, 16786947},
1971
  {65298, 16785155}, {65299, 16785411}, {65300, 16787715}, {65301, 17045763},
1972
  {65302, 17046019}, {65303, 17046275}, {65304, 17046531}, {65305, 17046787},
1973
  {65306, 17121027}, {65307, 16848643}, {65308, 17865987}, {65309, 17047555},
1974
  {65310, 17866243}, {65311, 17043971}, {65312, 17867267}, {65313, 16777219},
1975
  {65314, 16777475}, {65315, 16777731}, {65316, 16777987}, {65317, 16778243},
1976
  {65318, 16778499}, {65319, 16778755}, {65320, 16779011}, {65321, 16779267},
1977
  {65322, 16779523}, {65323, 16779779}, {65324, 16780035}, {65325, 16780291},
1978
  {65326, 16780547}, {65327, 16780803}, {65328, 16781059}, {65329, 16781315},
1979
  {65330, 16781571}, {65331, 16781827}, {65332, 16782083}, {65333, 16782339},
1980
  {65334, 16782595}, {65335, 16782851}, {65336, 16783107}, {65337, 16783363},
1981
  {65338, 16783619}, {65339, 17864451}, {65340, 17866499}, {65341, 17864707},
1982
  {65342, 17873667}, {65343, 17861123}, {65344, 17037059}, {65345, 16777219},
1983
  {65346, 16777475}, {65347, 16777731}, {65348, 16777987}, {65349, 16778243},
1984
  {65350, 16778499}, {65351, 16778755}, {65352, 16779011}, {65353, 16779267},
1985
  {65354, 16779523}, {65355, 16779779}, {65356, 16780035}, {65357, 16780291},
1986
  {65358, 16780547}, {65359, 16780803}, {65360, 16781059}, {65361, 16781315},
1987
  {65362, 16781571}, {65363, 16781827}, {65364, 16782083}, {65365, 16782339},
1988
  {65366, 16782595}, {65367, 16782851}, {65368, 16783107}, {65369, 16783363},
1989
  {65370, 16783619}, {65371, 17861379}, {65372, 17873923}, {65373, 17861635},
1990
  {65374, 17874179}, {65375, 17874435}, {65376, 17874691}, {65377, 17207043},
1991
  {65378, 17863427}, {65379, 17863683}, {65380, 17859843}, {65381, 17874947},
1992
  {65382, 17327363}, {65383, 17329923}, {65384, 17372931}, {65385, 17875203},
1993
  {65386, 17374467}, {65387, 17334019}, {65388, 17875459}, {65389, 17344259},
1994
  {65390, 17390083}, {65391, 17339651}, {65392, 17328643}, {65393, 17316099},
1995
  {65394, 17316355}, {65395, 17316611}, {65396, 17316867}, {65397, 17317123},
1996
  {65398, 17317379}, {65399, 17317635}, {65400, 17317891}, {65401, 17318147},
1997
  {65402, 17209603}, {65403, 17318403}, {65404, 17318659}, {65405, 17318915},
1998
  {65406, 17319171}, {65407, 17319427}, {65408, 17319683}, {65409, 17319939},
1999
  {65410, 17320195}, {65411, 17320451}, {65412, 17209859}, {65413, 17320707},
2000
  {65414, 17320963}, {65415, 17321219}, {65416, 17321475}, {65417, 17321731},
2001
  {65418, 17321987}, {65419, 17322243}, {65420, 17322499}, {65421, 17322755},
2002
  {65422, 17323011}, {65423, 17323267}, {65424, 17323523}, {65425, 17323779},
2003
  {65426, 17324035}, {65427, 17324291}, {65428, 17324547}, {65429, 17324803},
2004
  {65430, 17325059}, {65431, 17325315}, {65432, 17325571}, {65433, 17325827},
2005
  {65434, 17326083}, {65435, 17326339}, {65436, 17326595}, {65437, 17330435},
2006
  {65438, 17208323}, {65439, 17208835}, {65440, 0}, {65441, 17210115},
2007
  {65442, 17210371}, {65443, 17210627}, {65444, 17210883}, {65445, 17211139},
2008
  {65446, 17211395}, {65447, 17211651}, {65448, 17211907}, {65449, 17212163},
2009
  {65450, 17212419}, {65451, 17212675}, {65452, 17212931}, {65453, 17213187},
2010
  {65454, 17213443}, {65455, 17213699}, {65456, 17213955}, {65457, 17214211},
2011
  {65458, 17214467}, {65459, 17214723}, {65460, 17214979}, {65461, 17215235},
2012
  {65462, 17215491}, {65463, 17215747}, {65464, 17216003}, {65465, 17216259},
2013
  {65466, 17216515}, {65467, 17216771}, {65468, 17217027}, {65469, 17217283},
2014
  {65470, 17217539}, {65471, 2}, {65474, 17217795}, {65475, 17218051},
2015
  {65476, 17218307}, {65477, 17218563}, {65478, 17218819}, {65479, 17219075},
2016
  {65480, 2}, {65482, 17219331}, {65483, 17219587}, {65484, 17219843},
2017
  {65485, 17220099}, {65486, 17220355}, {65487, 17220611}, {65488, 2},
2018
  {65490, 17220867}, {65491, 17221123}, {65492, 17221379}, {65493, 17221635},
2019
  {65494, 17221891}, {65495, 17222147}, {65496, 2}, {65498, 17222403},
2020
  {65499, 17222659}, {65500, 17222915}, {65501, 2}, {65504, 17875715},
2021
  {65505, 17875971}, {65506, 17876227}, {65507, 33561859}, {65508, 17876483},
2022
  {65509, 17876739}, {65510, 17876995}, {65511, 2}, {65512, 17877251},
2023
  {65513, 17877507}, {65514, 17877763}, {65515, 17878019}, {65516, 17878275},
2024
  {65517, 17878531}, {65518, 17878787}, {65519, 2}, {65536, 1},
2025
  {65548, 2}, {65549, 1}, {65575, 2}, {65576, 1},
2026
  {65595, 2}, {65596, 1}, {65598, 2}, {65599, 1},
2027
  {65614, 2}, {65616, 1}, {65630, 2}, {65664, 1},
2028
  {65787, 2}, {65792, 1}, {65795, 2}, {65799, 1},
2029
  {65844, 2}, {65847, 1}, {65935, 2}, {65936, 1},
2030
  {65949, 2}, {65952, 1}, {65953, 2}, {66000, 1},
2031
  {66046, 2}, {66176, 1}, {66205, 2}, {66208, 1},
2032
  {66257, 2}, {66272, 1}, {66300, 2}, {66304, 1},
2033
  {66340, 2}, {66349, 1}, {66379, 2}, {66384, 1},
2034
  {66427, 2}, {66432, 1}, {66462, 2}, {66463, 1},
2035
  {66500, 2}, {66504, 1}, {66518, 2}, {66560, 17879043},
2036
  {66561, 17879299}, {66562, 17879555}, {66563, 17879811}, {66564, 17880067},
2037
  {66565, 17880323}, {66566, 17880579}, {66567, 17880835}, {66568, 17881091},
2038
  {66569, 17881347}, {66570, 17881603}, {66571, 17881859}, {66572, 17882115},
2039
  {66573, 17882371}, {66574, 17882627}, {66575, 17882883}, {66576, 17883139},
2040
  {66577, 17883395}, {66578, 17883651}, {66579, 17883907}, {66580, 17884163},
2041
  {66581, 17884419}, {66582, 17884675}, {66583, 17884931}, {66584, 17885187},
2042
  {66585, 17885443}, {66586, 17885699}, {66587, 17885955}, {66588, 17886211},
2043
  {66589, 17886467}, {66590, 17886723}, {66591, 17886979}, {66592, 17887235},
2044
  {66593, 17887491}, {66594, 17887747}, {66595, 17888003}, {66596, 17888259},
2045
  {66597, 17888515}, {66598, 17888771}, {66599, 17889027}, {66600, 1},
2046
  {66718, 2}, {66720, 1}, {66730, 2}, {66736, 17889283},
2047
  {66737, 17889539}, {66738, 17889795}, {66739, 17890051}, {66740, 17890307},
2048
  {66741, 17890563}, {66742, 17890819}, {66743, 17891075}, {66744, 17891331},
2049
  {66745, 17891587}, {66746, 17891843}, {66747, 17892099}, {66748, 17892355},
2050
  {66749, 17892611}, {66750, 17892867}, {66751, 17893123}, {66752, 17893379},
2051
  {66753, 17893635}, {66754, 17893891}, {66755, 17894147}, {66756, 17894403},
2052
  {66757, 17894659}, {66758, 17894915}, {66759, 17895171}, {66760, 17895427},
2053
  {66761, 17895683}, {66762, 17895939}, {66763, 17896195}, {66764, 17896451},
2054
  {66765, 17896707}, {66766, 17896963}, {66767, 17897219}, {66768, 17897475},
2055
  {66769, 17897731}, {66770, 17897987}, {66771, 17898243}, {66772, 2},
2056
  {66776, 1}, {66812, 2}, {66816, 1}, {66856, 2},
2057
  {66864, 1}, {66916, 2}, {66927, 1}, {66928, 17898499},
2058
  {66929, 17898755}, {66930, 17899011}, {66931, 17899267}, {66932, 17899523},
2059
  {66933, 17899779}, {66934, 17900035}, {66935, 17900291}, {66936, 17900547},
2060
  {66937, 17900803}, {66938, 17901059}, {66939, 2}, {66940, 17901315},
2061
  {66941, 17901571}, {66942, 17901827}, {66943, 17902083}, {66944, 17902339},
2062
  {66945, 17902595}, {66946, 17902851}, {66947, 17903107}, {66948, 17903363},
2063
  {66949, 17903619}, {66950, 17903875}, {66951, 17904131}, {66952, 17904387},
2064
  {66953, 17904643}, {66954, 17904899}, {66955, 2}, {66956, 17905155},
2065
  {66957, 17905411}, {66958, 17905667}, {66959, 17905923}, {66960, 17906179},
2066
  {66961, 17906435}, {66962, 17906691}, {66963, 2}, {66964, 17906947},
2067
  {66965, 17907203}, {66966, 2}, {66967, 1}, {66978, 2},
2068
  {66979, 1}, {66994, 2}, {66995, 1}, {67002, 2},
2069
  {67003, 1}, {67005, 2}, {67008, 1}, {67060, 2},
2070
  {67072, 1}, {67383, 2}, {67392, 1}, {67414, 2},
2071
  {67424, 1}, {67432, 2}, {67456, 1}, {67457, 17907459},
2072
  {67458, 17907715}, {67459, 16791043}, {67460, 17907971}, {67461, 16814083},
2073
  {67462, 2}, {67463, 17908227}, {67464, 17908483}, {67465, 17908739},
2074
  {67466, 17908995}, {67467, 16815363}, {67468, 16815619}, {67469, 17909251},
2075
  {67470, 17909507}, {67471, 17909763}, {67472, 17910019}, {67473, 17527555},
2076
  {67474, 17910275}, {67475, 16817155}, {67476, 17910531}, {67477, 16802051},
2077
  {67478, 17910787}, {67479, 17911043}, {67480, 17911299}, {67481, 17911555},
2078
  {67482, 17911811}, {67483, 17523459}, {67484, 17912067}, {67485, 17912323},
2079
  {67486, 17912579}, {67487, 17912835}, {67488, 17913091}, {67489, 17913347},
2080
  {67490, 16795395}, {67491, 17913603}, {67492, 17913859}, {67493, 16781315},
2081
  {67494, 17914115}, {67495, 17914371}, {67496, 17135875}, {67497, 17914627},
2082
  {67498, 16819971}, {67499, 17914883}, {67500, 17915139}, {67501, 17915395},
2083
  {67502, 17915651}, {67503, 16820995}, {67504, 17915907}, {67505, 2},
2084
  {67506, 17916163}, {67507, 17916419}, {67508, 17916675}, {67509, 17916931},
2085
  {67510, 17917187}, {67511, 17917443}, {67512, 17917699}, {67513, 17917955},
2086
  {67514, 17918211}, {67515, 2}, {67584, 1}, {67590, 2},
2087
  {67592, 1}, {67593, 2}, {67594, 1}, {67638, 2},
2088
  {67639, 1}, {67641, 2}, {67644, 1}, {67645, 2},
2089
  {67647, 1}, {67670, 2}, {67671, 1}, {67743, 2},
2090
  {67751, 1}, {67760, 2}, {67808, 1}, {67827, 2},
2091
  {67828, 1}, {67830, 2}, {67835, 1}, {67868, 2},
2092
  {67871, 1}, {67898, 2}, {67903, 1}, {67930, 2},
2093
  {67968, 1}, {68024, 2}, {68028, 1}, {68048, 2},
2094
  {68050, 1}, {68100, 2}, {68101, 1}, {68103, 2},
2095
  {68108, 1}, {68116, 2}, {68117, 1}, {68120, 2},
2096
  {68121, 1}, {68150, 2}, {68152, 1}, {68155, 2},
2097
  {68159, 1}, {68169, 2}, {68176, 1}, {68185, 2},
2098
  {68192, 1}, {68256, 2}, {68288, 1}, {68327, 2},
2099
  {68331, 1}, {68343, 2}, {68352, 1}, {68406, 2},
2100
  {68409, 1}, {68438, 2}, {68440, 1}, {68467, 2},
2101
  {68472, 1}, {68498, 2}, {68505, 1}, {68509, 2},
2102
  {68521, 1}, {68528, 2}, {68608, 1}, {68681, 2},
2103
  {68736, 17918467}, {68737, 17918723}, {68738, 17918979}, {68739, 17919235},
2104
  {68740, 17919491}, {68741, 17919747}, {68742, 17920003}, {68743, 17920259},
2105
  {68744, 17920515}, {68745, 17920771}, {68746, 17921027}, {68747, 17921283},
2106
  {68748, 17921539}, {68749, 17921795}, {68750, 17922051}, {68751, 17922307},
2107
  {68752, 17922563}, {68753, 17922819}, {68754, 17923075}, {68755, 17923331},
2108
  {68756, 17923587}, {68757, 17923843}, {68758, 17924099}, {68759, 17924355},
2109
  {68760, 17924611}, {68761, 17924867}, {68762, 17925123}, {68763, 17925379},
2110
  {68764, 17925635}, {68765, 17925891}, {68766, 17926147}, {68767, 17926403},
2111
  {68768, 17926659}, {68769, 17926915}, {68770, 17927171}, {68771, 17927427},
2112
  {68772, 17927683}, {68773, 17927939}, {68774, 17928195}, {68775, 17928451},
2113
  {68776, 17928707}, {68777, 17928963}, {68778, 17929219}, {68779, 17929475},
2114
  {68780, 17929731}, {68781, 17929987}, {68782, 17930243}, {68783, 17930499},
2115
  {68784, 17930755}, {68785, 17931011}, {68786, 17931267}, {68787, 2},
2116
  {68800, 1}, {68851, 2}, {68858, 1}, {68904, 2},
2117
  {68912, 1}, {68922, 2}, {68928, 1}, {68944, 17931523},
2118
  {68945, 17931779}, {68946, 17932035}, {68947, 17932291}, {68948, 17932547},
2119
  {68949, 17932803}, {68950, 17933059}, {68951, 17933315}, {68952, 17933571},
2120
  {68953, 17933827}, {68954, 17934083}, {68955, 17934339}, {68956, 17934595},
2121
  {68957, 17934851}, {68958, 17935107}, {68959, 17935363}, {68960, 17935619},
2122
  {68961, 17935875}, {68962, 17936131}, {68963, 17936387}, {68964, 17936643},
2123
  {68965, 17936899}, {68966, 2}, {68969, 1}, {68998, 2},
2124
  {69006, 1}, {69008, 2}, {69216, 1}, {69247, 2},
2125
  {69248, 1}, {69290, 2}, {69291, 1}, {69294, 2},
2126
  {69296, 1}, {69298, 2}, {69314, 1}, {69320, 2},
2127
  {69328, 1}, {69337, 2}, {69370, 1}, {69416, 2},
2128
  {69424, 1}, {69466, 2}, {69488, 1}, {69514, 2},
2129
  {69552, 1}, {69580, 2}, {69600, 1}, {69623, 2},
2130
  {69632, 1}, {69710, 2}, {69714, 1}, {69750, 2},
2131
  {69759, 1}, {69821, 2}, {69822, 1}, {69827, 2},
2132
  {69840, 1}, {69865, 2}, {69872, 1}, {69882, 2},
2133
  {69888, 1}, {69941, 2}, {69942, 1}, {69960, 2},
2134
  {69968, 1}, {70007, 2}, {70016, 1}, {70112, 2},
2135
  {70113, 1}, {70133, 2}, {70144, 1}, {70162, 2},
2136
  {70163, 1}, {70210, 2}, {70272, 1}, {70279, 2},
2137
  {70280, 1}, {70281, 2}, {70282, 1}, {70286, 2},
2138
  {70287, 1}, {70302, 2}, {70303, 1}, {70314, 2},
2139
  {70320, 1}, {70379, 2}, {70384, 1}, {70394, 2},
2140
  {70400, 1}, {70404, 2}, {70405, 1}, {70413, 2},
2141
  {70415, 1}, {70417, 2}, {70419, 1}, {70441, 2},
2142
  {70442, 1}, {70449, 2}, {70450, 1}, {70452, 2},
2143
  {70453, 1}, {70458, 2}, {70459, 1}, {70469, 2},
2144
  {70471, 1}, {70473, 2}, {70475, 1}, {70478, 2},
2145
  {70480, 1}, {70481, 2}, {70487, 1}, {70488, 2},
2146
  {70493, 1}, {70500, 2}, {70502, 1}, {70509, 2},
2147
  {70512, 1}, {70517, 2}, {70528, 1}, {70538, 2},
2148
  {70539, 1}, {70540, 2}, {70542, 1}, {70543, 2},
2149
  {70544, 1}, {70582, 2}, {70583, 1}, {70593, 2},
2150
  {70594, 1}, {70595, 2}, {70597, 1}, {70598, 2},
2151
  {70599, 1}, {70603, 2}, {70604, 1}, {70614, 2},
2152
  {70615, 1}, {70617, 2}, {70625, 1}, {70627, 2},
2153
  {70656, 1}, {70748, 2}, {70749, 1}, {70754, 2},
2154
  {70784, 1}, {70856, 2}, {70864, 1}, {70874, 2},
2155
  {71040, 1}, {71094, 2}, {71096, 1}, {71134, 2},
2156
  {71168, 1}, {71237, 2}, {71248, 1}, {71258, 2},
2157
  {71264, 1}, {71277, 2}, {71296, 1}, {71354, 2},
2158
  {71360, 1}, {71370, 2}, {71376, 1}, {71396, 2},
2159
  {71424, 1}, {71451, 2}, {71453, 1}, {71468, 2},
2160
  {71472, 1}, {71495, 2}, {71680, 1}, {71740, 2},
2161
  {71840, 17937155}, {71841, 17937411}, {71842, 17937667}, {71843, 17937923},
2162
  {71844, 17938179}, {71845, 17938435}, {71846, 17938691}, {71847, 17938947},
2163
  {71848, 17939203}, {71849, 17939459}, {71850, 17939715}, {71851, 17939971},
2164
  {71852, 17940227}, {71853, 17940483}, {71854, 17940739}, {71855, 17940995},
2165
  {71856, 17941251}, {71857, 17941507}, {71858, 17941763}, {71859, 17942019},
2166
  {71860, 17942275}, {71861, 17942531}, {71862, 17942787}, {71863, 17943043},
2167
  {71864, 17943299}, {71865, 17943555}, {71866, 17943811}, {71867, 17944067},
2168
  {71868, 17944323}, {71869, 17944579}, {71870, 17944835}, {71871, 17945091},
2169
  {71872, 1}, {71923, 2}, {71935, 1}, {71943, 2},
2170
  {71945, 1}, {71946, 2}, {71948, 1}, {71956, 2},
2171
  {71957, 1}, {71959, 2}, {71960, 1}, {71990, 2},
2172
  {71991, 1}, {71993, 2}, {71995, 1}, {72007, 2},
2173
  {72016, 1}, {72026, 2}, {72096, 1}, {72104, 2},
2174
  {72106, 1}, {72152, 2}, {72154, 1}, {72165, 2},
2175
  {72192, 1}, {72264, 2}, {72272, 1}, {72355, 2},
2176
  {72368, 1}, {72441, 2}, {72448, 1}, {72458, 2},
2177
  {72544, 1}, {72552, 2}, {72640, 1}, {72674, 2},
2178
  {72688, 1}, {72698, 2}, {72704, 1}, {72713, 2},
2179
  {72714, 1}, {72759, 2}, {72760, 1}, {72774, 2},
2180
  {72784, 1}, {72813, 2}, {72816, 1}, {72848, 2},
2181
  {72850, 1}, {72872, 2}, {72873, 1}, {72887, 2},
2182
  {72960, 1}, {72967, 2}, {72968, 1}, {72970, 2},
2183
  {72971, 1}, {73015, 2}, {73018, 1}, {73019, 2},
2184
  {73020, 1}, {73022, 2}, {73023, 1}, {73032, 2},
2185
  {73040, 1}, {73050, 2}, {73056, 1}, {73062, 2},
2186
  {73063, 1}, {73065, 2}, {73066, 1}, {73103, 2},
2187
  {73104, 1}, {73106, 2}, {73107, 1}, {73113, 2},
2188
  {73120, 1}, {73130, 2}, {73136, 1}, {73180, 2},
2189
  {73184, 1}, {73194, 2}, {73440, 1}, {73465, 2},
2190
  {73472, 1}, {73489, 2}, {73490, 1}, {73531, 2},
2191
  {73534, 1}, {73563, 2}, {73648, 1}, {73649, 2},
2192
  {73664, 1}, {73714, 2}, {73727, 1}, {74650, 2},
2193
  {74752, 1}, {74863, 2}, {74864, 1}, {74869, 2},
2194
  {74880, 1}, {75076, 2}, {77712, 1}, {77811, 2},
2195
  {77824, 1}, {78896, 2}, {78912, 1}, {78934, 2},
2196
  {78944, 1}, {82939, 2}, {82944, 1}, {83527, 2},
2197
  {90368, 1}, {90426, 2}, {92160, 1}, {92729, 2},
2198
  {92736, 1}, {92767, 2}, {92768, 1}, {92778, 2},
2199
  {92782, 1}, {92863, 2}, {92864, 1}, {92874, 2},
2200
  {92880, 1}, {92910, 2}, {92912, 1}, {92918, 2},
2201
  {92928, 1}, {92998, 2}, {93008, 1}, {93018, 2},
2202
  {93019, 1}, {93026, 2}, {93027, 1}, {93048, 2},
2203
  {93053, 1}, {93072, 2}, {93504, 1}, {93562, 2},
2204
  {93760, 17945347}, {93761, 17945603}, {93762, 17945859}, {93763, 17946115},
2205
  {93764, 17946371}, {93765, 17946627}, {93766, 17946883}, {93767, 17947139},
2206
  {93768, 17947395}, {93769, 17947651}, {93770, 17947907}, {93771, 17948163},
2207
  {93772, 17948419}, {93773, 17948675}, {93774, 17948931}, {93775, 17949187},
2208
  {93776, 17949443}, {93777, 17949699}, {93778, 17949955}, {93779, 17950211},
2209
  {93780, 17950467}, {93781, 17950723}, {93782, 17950979}, {93783, 17951235},
2210
  {93784, 17951491}, {93785, 17951747}, {93786, 17952003}, {93787, 17952259},
2211
  {93788, 17952515}, {93789, 17952771}, {93790, 17953027}, {93791, 17953283},
2212
  {93792, 1}, {93851, 2}, {93856, 17953539}, {93857, 17953795},
2213
  {93858, 17954051}, {93859, 17954307}, {93860, 17954563}, {93861, 17954819},
2214
  {93862, 17955075}, {93863, 17955331}, {93864, 17955587}, {93865, 17955843},
2215
  {93866, 17956099}, {93867, 17956355}, {93868, 17956611}, {93869, 17956867},
2216
  {93870, 17957123}, {93871, 17957379}, {93872, 17957635}, {93873, 17957891},
2217
  {93874, 17958147}, {93875, 17958403}, {93876, 17958659}, {93877, 17958915},
2218
  {93878, 17959171}, {93879, 17959427}, {93880, 17959683}, {93881, 2},
2219
  {93883, 1}, {93908, 2}, {93952, 1}, {94027, 2},
2220
  {94031, 1}, {94088, 2}, {94095, 1}, {94112, 2},
2221
  {94176, 1}, {94181, 2}, {94192, 1}, {94199, 2},
2222
  {94208, 1}, {101590, 2}, {101631, 1}, {101663, 2},
2223
  {101760, 1}, {101875, 2}, {110576, 1}, {110580, 2},
2224
  {110581, 1}, {110588, 2}, {110589, 1}, {110591, 2},
2225
  {110592, 1}, {110883, 2}, {110898, 1}, {110899, 2},
2226
  {110928, 1}, {110931, 2}, {110933, 1}, {110934, 2},
2227
  {110948, 1}, {110952, 2}, {110960, 1}, {111356, 2},
2228
  {113664, 1}, {113771, 2}, {113776, 1}, {113789, 2},
2229
  {113792, 1}, {113801, 2}, {113808, 1}, {113818, 2},
2230
  {113820, 1}, {113824, 0}, {113828, 2}, {117760, 1},
2231
  {117974, 16777219}, {117975, 16777475}, {117976, 16777731}, {117977, 16777987},
2232
  {117978, 16778243}, {117979, 16778499}, {117980, 16778755}, {117981, 16779011},
2233
  {117982, 16779267}, {117983, 16779523}, {117984, 16779779}, {117985, 16780035},
2234
  {117986, 16780291}, {117987, 16780547}, {117988, 16780803}, {117989, 16781059},
2235
  {117990, 16781315}, {117991, 16781571}, {117992, 16781827}, {117993, 16782083},
2236
  {117994, 16782339}, {117995, 16782595}, {117996, 16782851}, {117997, 16783107},
2237
  {117998, 16783363}, {117999, 16783619}, {118000, 17045507}, {118001, 16786947},
2238
  {118002, 16785155}, {118003, 16785411}, {118004, 16787715}, {118005, 17045763},
2239
  {118006, 17046019}, {118007, 17046275}, {118008, 17046531}, {118009, 17046787},
2240
  {118010, 1}, {118013, 2}, {118016, 1}, {118452, 2},
2241
  {118458, 1}, {118481, 2}, {118496, 1}, {118513, 2},
2242
  {118528, 1}, {118574, 2}, {118576, 1}, {118599, 2},
2243
  {118608, 1}, {118724, 2}, {118784, 1}, {119030, 2},
2244
  {119040, 1}, {119079, 2}, {119081, 1}, {119134, 34737155},
2245
  {119135, 34737667}, {119136, 51515395}, {119137, 51516163}, {119138, 51516931},
2246
  {119139, 51517699}, {119140, 51518467}, {119141, 1}, {119155, 0},
2247
  {119163, 1}, {119227, 34742019}, {119228, 34742531}, {119229, 51520259},
2248
  {119230, 51521027}, {119231, 51521795}, {119232, 51522563}, {119233, 1},
2249
  {119275, 2}, {119296, 1}, {119366, 2}, {119488, 1},
2250
  {119508, 2}, {119520, 1}, {119540, 2}, {119552, 1},
2251
  {119639, 2}, {119648, 1}, {119673, 2}, {119808, 16777219},
2252
  {119809, 16777475}, {119810, 16777731}, {119811, 16777987}, {119812, 16778243},
2253
  {119813, 16778499}, {119814, 16778755}, {119815, 16779011}, {119816, 16779267},
2254
  {119817, 16779523}, {119818, 16779779}, {119819, 16780035}, {119820, 16780291},
2255
  {119821, 16780547}, {119822, 16780803}, {119823, 16781059}, {119824, 16781315},
2256
  {119825, 16781571}, {119826, 16781827}, {119827, 16782083}, {119828, 16782339},
2257
  {119829, 16782595}, {119830, 16782851}, {119831, 16783107}, {119832, 16783363},
2258
  {119833, 16783619}, {119834, 16777219}, {119835, 16777475}, {119836, 16777731},
2259
  {119837, 16777987}, {119838, 16778243}, {119839, 16778499}, {119840, 16778755},
2260
  {119841, 16779011}, {119842, 16779267}, {119843, 16779523}, {119844, 16779779},
2261
  {119845, 16780035}, {119846, 16780291}, {119847, 16780547}, {119848, 16780803},
2262
  {119849, 16781059}, {119850, 16781315}, {119851, 16781571}, {119852, 16781827},
2263
  {119853, 16782083}, {119854, 16782339}, {119855, 16782595}, {119856, 16782851},
2264
  {119857, 16783107}, {119858, 16783363}, {119859, 16783619}, {119860, 16777219},
2265
  {119861, 16777475}, {119862, 16777731}, {119863, 16777987}, {119864, 16778243},
2266
  {119865, 16778499}, {119866, 16778755}, {119867, 16779011}, {119868, 16779267},
2267
  {119869, 16779523}, {119870, 16779779}, {119871, 16780035}, {119872, 16780291},
2268
  {119873, 16780547}, {119874, 16780803}, {119875, 16781059}, {119876, 16781315},
2269
  {119877, 16781571}, {119878, 16781827}, {119879, 16782083}, {119880, 16782339},
2270
  {119881, 16782595}, {119882, 16782851}, {119883, 16783107}, {119884, 16783363},
2271
  {119885, 16783619}, {119886, 16777219}, {119887, 16777475}, {119888, 16777731},
2272
  {119889, 16777987}, {119890, 16778243}, {119891, 16778499}, {119892, 16778755},
2273
  {119893, 2}, {119894, 16779267}, {119895, 16779523}, {119896, 16779779},
2274
  {119897, 16780035}, {119898, 16780291}, {119899, 16780547}, {119900, 16780803},
2275
  {119901, 16781059}, {119902, 16781315}, {119903, 16781571}, {119904, 16781827},
2276
  {119905, 16782083}, {119906, 16782339}, {119907, 16782595}, {119908, 16782851},
2277
  {119909, 16783107}, {119910, 16783363}, {119911, 16783619}, {119912, 16777219},
2278
  {119913, 16777475}, {119914, 16777731}, {119915, 16777987}, {119916, 16778243},
2279
  {119917, 16778499}, {119918, 16778755}, {119919, 16779011}, {119920, 16779267},
2280
  {119921, 16779523}, {119922, 16779779}, {119923, 16780035}, {119924, 16780291},
2281
  {119925, 16780547}, {119926, 16780803}, {119927, 16781059}, {119928, 16781315},
2282
  {119929, 16781571}, {119930, 16781827}, {119931, 16782083}, {119932, 16782339},
2283
  {119933, 16782595}, {119934, 16782851}, {119935, 16783107}, {119936, 16783363},
2284
  {119937, 16783619}, {119938, 16777219}, {119939, 16777475}, {119940, 16777731},
2285
  {119941, 16777987}, {119942, 16778243}, {119943, 16778499}, {119944, 16778755},
2286
  {119945, 16779011}, {119946, 16779267}, {119947, 16779523}, {119948, 16779779},
2287
  {119949, 16780035}, {119950, 16780291}, {119951, 16780547}, {119952, 16780803},
2288
  {119953, 16781059}, {119954, 16781315}, {119955, 16781571}, {119956, 16781827},
2289
  {119957, 16782083}, {119958, 16782339}, {119959, 16782595}, {119960, 16782851},
2290
  {119961, 16783107}, {119962, 16783363}, {119963, 16783619}, {119964, 16777219},
2291
  {119965, 2}, {119966, 16777731}, {119967, 16777987}, {119968, 2},
2292
  {119970, 16778755}, {119971, 2}, {119973, 16779523}, {119974, 16779779},
2293
  {119975, 2}, {119977, 16780547}, {119978, 16780803}, {119979, 16781059},
2294
  {119980, 16781315}, {119981, 2}, {119982, 16781827}, {119983, 16782083},
2295
  {119984, 16782339}, {119985, 16782595}, {119986, 16782851}, {119987, 16783107},
2296
  {119988, 16783363}, {119989, 16783619}, {119990, 16777219}, {119991, 16777475},
2297
  {119992, 16777731}, {119993, 16777987}, {119994, 2}, {119995, 16778499},
2298
  {119996, 2}, {119997, 16779011}, {119998, 16779267}, {119999, 16779523},
2299
  {120000, 16779779}, {120001, 16780035}, {120002, 16780291}, {120003, 16780547},
2300
  {120004, 2}, {120005, 16781059}, {120006, 16781315}, {120007, 16781571},
2301
  {120008, 16781827}, {120009, 16782083}, {120010, 16782339}, {120011, 16782595},
2302
  {120012, 16782851}, {120013, 16783107}, {120014, 16783363}, {120015, 16783619},
2303
  {120016, 16777219}, {120017, 16777475}, {120018, 16777731}, {120019, 16777987},
2304
  {120020, 16778243}, {120021, 16778499}, {120022, 16778755}, {120023, 16779011},
2305
  {120024, 16779267}, {120025, 16779523}, {120026, 16779779}, {120027, 16780035},
2306
  {120028, 16780291}, {120029, 16780547}, {120030, 16780803}, {120031, 16781059},
2307
  {120032, 16781315}, {120033, 16781571}, {120034, 16781827}, {120035, 16782083},
2308
  {120036, 16782339}, {120037, 16782595}, {120038, 16782851}, {120039, 16783107},
2309
  {120040, 16783363}, {120041, 16783619}, {120042, 16777219}, {120043, 16777475},
2310
  {120044, 16777731}, {120045, 16777987}, {120046, 16778243}, {120047, 16778499},
2311
  {120048, 16778755}, {120049, 16779011}, {120050, 16779267}, {120051, 16779523},
2312
  {120052, 16779779}, {120053, 16780035}, {120054, 16780291}, {120055, 16780547},
2313
  {120056, 16780803}, {120057, 16781059}, {120058, 16781315}, {120059, 16781571},
2314
  {120060, 16781827}, {120061, 16782083}, {120062, 16782339}, {120063, 16782595},
2315
  {120064, 16782851}, {120065, 16783107}, {120066, 16783363}, {120067, 16783619},
2316
  {120068, 16777219}, {120069, 16777475}, {120070, 2}, {120071, 16777987},
2317
  {120072, 16778243}, {120073, 16778499}, {120074, 16778755}, {120075, 2},
2318
  {120077, 16779523}, {120078, 16779779}, {120079, 16780035}, {120080, 16780291},
2319
  {120081, 16780547}, {120082, 16780803}, {120083, 16781059}, {120084, 16781315},
2320
  {120085, 2}, {120086, 16781827}, {120087, 16782083}, {120088, 16782339},
2321
  {120089, 16782595}, {120090, 16782851}, {120091, 16783107}, {120092, 16783363},
2322
  {120093, 2}, {120094, 16777219}, {120095, 16777475}, {120096, 16777731},
2323
  {120097, 16777987}, {120098, 16778243}, {120099, 16778499}, {120100, 16778755},
2324
  {120101, 16779011}, {120102, 16779267}, {120103, 16779523}, {120104, 16779779},
2325
  {120105, 16780035}, {120106, 16780291}, {120107, 16780547}, {120108, 16780803},
2326
  {120109, 16781059}, {120110, 16781315}, {120111, 16781571}, {120112, 16781827},
2327
  {120113, 16782083}, {120114, 16782339}, {120115, 16782595}, {120116, 16782851},
2328
  {120117, 16783107}, {120118, 16783363}, {120119, 16783619}, {120120, 16777219},
2329
  {120121, 16777475}, {120122, 2}, {120123, 16777987}, {120124, 16778243},
2330
  {120125, 16778499}, {120126, 16778755}, {120127, 2}, {120128, 16779267},
2331
  {120129, 16779523}, {120130, 16779779}, {120131, 16780035}, {120132, 16780291},
2332
  {120133, 2}, {120134, 16780803}, {120135, 2}, {120138, 16781827},
2333
  {120139, 16782083}, {120140, 16782339}, {120141, 16782595}, {120142, 16782851},
2334
  {120143, 16783107}, {120144, 16783363}, {120145, 2}, {120146, 16777219},
2335
  {120147, 16777475}, {120148, 16777731}, {120149, 16777987}, {120150, 16778243},
2336
  {120151, 16778499}, {120152, 16778755}, {120153, 16779011}, {120154, 16779267},
2337
  {120155, 16779523}, {120156, 16779779}, {120157, 16780035}, {120158, 16780291},
2338
  {120159, 16780547}, {120160, 16780803}, {120161, 16781059}, {120162, 16781315},
2339
  {120163, 16781571}, {120164, 16781827}, {120165, 16782083}, {120166, 16782339},
2340
  {120167, 16782595}, {120168, 16782851}, {120169, 16783107}, {120170, 16783363},
2341
  {120171, 16783619}, {120172, 16777219}, {120173, 16777475}, {120174, 16777731},
2342
  {120175, 16777987}, {120176, 16778243}, {120177, 16778499}, {120178, 16778755},
2343
  {120179, 16779011}, {120180, 16779267}, {120181, 16779523}, {120182, 16779779},
2344
  {120183, 16780035}, {120184, 16780291}, {120185, 16780547}, {120186, 16780803},
2345
  {120187, 16781059}, {120188, 16781315}, {120189, 16781571}, {120190, 16781827},
2346
  {120191, 16782083}, {120192, 16782339}, {120193, 16782595}, {120194, 16782851},
2347
  {120195, 16783107}, {120196, 16783363}, {120197, 16783619}, {120198, 16777219},
2348
  {120199, 16777475}, {120200, 16777731}, {120201, 16777987}, {120202, 16778243},
2349
  {120203, 16778499}, {120204, 16778755}, {120205, 16779011}, {120206, 16779267},
2350
  {120207, 16779523}, {120208, 16779779}, {120209, 16780035}, {120210, 16780291},
2351
  {120211, 16780547}, {120212, 16780803}, {120213, 16781059}, {120214, 16781315},
2352
  {120215, 16781571}, {120216, 16781827}, {120217, 16782083}, {120218, 16782339},
2353
  {120219, 16782595}, {120220, 16782851}, {120221, 16783107}, {120222, 16783363},
2354
  {120223, 16783619}, {120224, 16777219}, {120225, 16777475}, {120226, 16777731},
2355
  {120227, 16777987}, {120228, 16778243}, {120229, 16778499}, {120230, 16778755},
2356
  {120231, 16779011}, {120232, 16779267}, {120233, 16779523}, {120234, 16779779},
2357
  {120235, 16780035}, {120236, 16780291}, {120237, 16780547}, {120238, 16780803},
2358
  {120239, 16781059}, {120240, 16781315}, {120241, 16781571}, {120242, 16781827},
2359
  {120243, 16782083}, {120244, 16782339}, {120245, 16782595}, {120246, 16782851},
2360
  {120247, 16783107}, {120248, 16783363}, {120249, 16783619}, {120250, 16777219},
2361
  {120251, 16777475}, {120252, 16777731}, {120253, 16777987}, {120254, 16778243},
2362
  {120255, 16778499}, {120256, 16778755}, {120257, 16779011}, {120258, 16779267},
2363
  {120259, 16779523}, {120260, 16779779}, {120261, 16780035}, {120262, 16780291},
2364
  {120263, 16780547}, {120264, 16780803}, {120265, 16781059}, {120266, 16781315},
2365
  {120267, 16781571}, {120268, 16781827}, {120269, 16782083}, {120270, 16782339},
2366
  {120271, 16782595}, {120272, 16782851}, {120273, 16783107}, {120274, 16783363},
2367
  {120275, 16783619}, {120276, 16777219}, {120277, 16777475}, {120278, 16777731},
2368
  {120279, 16777987}, {120280, 16778243}, {120281, 16778499}, {120282, 16778755},
2369
  {120283, 16779011}, {120284, 16779267}, {120285, 16779523}, {120286, 16779779},
2370
  {120287, 16780035}, {120288, 16780291}, {120289, 16780547}, {120290, 16780803},
2371
  {120291, 16781059}, {120292, 16781315}, {120293, 16781571}, {120294, 16781827},
2372
  {120295, 16782083}, {120296, 16782339}, {120297, 16782595}, {120298, 16782851},
2373
  {120299, 16783107}, {120300, 16783363}, {120301, 16783619}, {120302, 16777219},
2374
  {120303, 16777475}, {120304, 16777731}, {120305, 16777987}, {120306, 16778243},
2375
  {120307, 16778499}, {120308, 16778755}, {120309, 16779011}, {120310, 16779267},
2376
  {120311, 16779523}, {120312, 16779779}, {120313, 16780035}, {120314, 16780291},
2377
  {120315, 16780547}, {120316, 16780803}, {120317, 16781059}, {120318, 16781315},
2378
  {120319, 16781571}, {120320, 16781827}, {120321, 16782083}, {120322, 16782339},
2379
  {120323, 16782595}, {120324, 16782851}, {120325, 16783107}, {120326, 16783363},
2380
  {120327, 16783619}, {120328, 16777219}, {120329, 16777475}, {120330, 16777731},
2381
  {120331, 16777987}, {120332, 16778243}, {120333, 16778499}, {120334, 16778755},
2382
  {120335, 16779011}, {120336, 16779267}, {120337, 16779523}, {120338, 16779779},
2383
  {120339, 16780035}, {120340, 16780291}, {120341, 16780547}, {120342, 16780803},
2384
  {120343, 16781059}, {120344, 16781315}, {120345, 16781571}, {120346, 16781827},
2385
  {120347, 16782083}, {120348, 16782339}, {120349, 16782595}, {120350, 16782851},
2386
  {120351, 16783107}, {120352, 16783363}, {120353, 16783619}, {120354, 16777219},
2387
  {120355, 16777475}, {120356, 16777731}, {120357, 16777987}, {120358, 16778243},
2388
  {120359, 16778499}, {120360, 16778755}, {120361, 16779011}, {120362, 16779267},
2389
  {120363, 16779523}, {120364, 16779779}, {120365, 16780035}, {120366, 16780291},
2390
  {120367, 16780547}, {120368, 16780803}, {120369, 16781059}, {120370, 16781315},
2391
  {120371, 16781571}, {120372, 16781827}, {120373, 16782083}, {120374, 16782339},
2392
  {120375, 16782595}, {120376, 16782851}, {120377, 16783107}, {120378, 16783363},
2393
  {120379, 16783619}, {120380, 16777219}, {120381, 16777475}, {120382, 16777731},
2394
  {120383, 16777987}, {120384, 16778243}, {120385, 16778499}, {120386, 16778755},
2395
  {120387, 16779011}, {120388, 16779267}, {120389, 16779523}, {120390, 16779779},
2396
  {120391, 16780035}, {120392, 16780291}, {120393, 16780547}, {120394, 16780803},
2397
  {120395, 16781059}, {120396, 16781315}, {120397, 16781571}, {120398, 16781827},
2398
  {120399, 16782083}, {120400, 16782339}, {120401, 16782595}, {120402, 16782851},
2399
  {120403, 16783107}, {120404, 16783363}, {120405, 16783619}, {120406, 16777219},
2400
  {120407, 16777475}, {120408, 16777731}, {120409, 16777987}, {120410, 16778243},
2401
  {120411, 16778499}, {120412, 16778755}, {120413, 16779011}, {120414, 16779267},
2402
  {120415, 16779523}, {120416, 16779779}, {120417, 16780035}, {120418, 16780291},
2403
  {120419, 16780547}, {120420, 16780803}, {120421, 16781059}, {120422, 16781315},
2404
  {120423, 16781571}, {120424, 16781827}, {120425, 16782083}, {120426, 16782339},
2405
  {120427, 16782595}, {120428, 16782851}, {120429, 16783107}, {120430, 16783363},
2406
  {120431, 16783619}, {120432, 16777219}, {120433, 16777475}, {120434, 16777731},
2407
  {120435, 16777987}, {120436, 16778243}, {120437, 16778499}, {120438, 16778755},
2408
  {120439, 16779011}, {120440, 16779267}, {120441, 16779523}, {120442, 16779779},
2409
  {120443, 16780035}, {120444, 16780291}, {120445, 16780547}, {120446, 16780803},
2410
  {120447, 16781059}, {120448, 16781315}, {120449, 16781571}, {120450, 16781827},
2411
  {120451, 16782083}, {120452, 16782339}, {120453, 16782595}, {120454, 16782851},
2412
  {120455, 16783107}, {120456, 16783363}, {120457, 16783619}, {120458, 16777219},
2413
  {120459, 16777475}, {120460, 16777731}, {120461, 16777987}, {120462, 16778243},
2414
  {120463, 16778499}, {120464, 16778755}, {120465, 16779011}, {120466, 16779267},
2415
  {120467, 16779523}, {120468, 16779779}, {120469, 16780035}, {120470, 16780291},
2416
  {120471, 16780547}, {120472, 16780803}, {120473, 16781059}, {120474, 16781315},
2417
  {120475, 16781571}, {120476, 16781827}, {120477, 16782083}, {120478, 16782339},
2418
  {120479, 16782595}, {120480, 16782851}, {120481, 16783107}, {120482, 16783363},
2419
  {120483, 16783619}, {120484, 17968899}, {120485, 17969155}, {120486, 2},
2420
  {120488, 16851715}, {120489, 16851971}, {120490, 16852227}, {120491, 16852483},
2421
  {120492, 16852739}, {120493, 16852995}, {120494, 16853251}, {120495, 16853507},
2422
  {120496, 16846851}, {120497, 16853763}, {120498, 16854019}, {120499, 16786179},
2423
  {120500, 16854275}, {120501, 16854531}, {120502, 16854787}, {120503, 16855043},
2424
  {120504, 16855299}, {120505, 16853507}, {120506, 16855555}, {120507, 16855811},
2425
  {120508, 16856067}, {120509, 16856323}, {120510, 16856579}, {120511, 16856835},
2426
  {120512, 16857091}, {120513, 17969411}, {120514, 16851715}, {120515, 16851971},
2427
  {120516, 16852227}, {120517, 16852483}, {120518, 16852739}, {120519, 16852995},
2428
  {120520, 16853251}, {120521, 16853507}, {120522, 16846851}, {120523, 16853763},
2429
  {120524, 16854019}, {120525, 16786179}, {120526, 16854275}, {120527, 16854531},
2430
  {120528, 16854787}, {120529, 16855043}, {120530, 16855299}, {120531, 16855555},
2431
  {120533, 16855811}, {120534, 16856067}, {120535, 16856323}, {120536, 16856579},
2432
  {120537, 16856835}, {120538, 16857091}, {120539, 17969667}, {120540, 16852739},
2433
  {120541, 16853507}, {120542, 16853763}, {120543, 16856323}, {120544, 16855299},
2434
  {120545, 16855043}, {120546, 16851715}, {120547, 16851971}, {120548, 16852227},
2435
  {120549, 16852483}, {120550, 16852739}, {120551, 16852995}, {120552, 16853251},
2436
  {120553, 16853507}, {120554, 16846851}, {120555, 16853763}, {120556, 16854019},
2437
  {120557, 16786179}, {120558, 16854275}, {120559, 16854531}, {120560, 16854787},
2438
  {120561, 16855043}, {120562, 16855299}, {120563, 16853507}, {120564, 16855555},
2439
  {120565, 16855811}, {120566, 16856067}, {120567, 16856323}, {120568, 16856579},
2440
  {120569, 16856835}, {120570, 16857091}, {120571, 17969411}, {120572, 16851715},
2441
  {120573, 16851971}, {120574, 16852227}, {120575, 16852483}, {120576, 16852739},
2442
  {120577, 16852995}, {120578, 16853251}, {120579, 16853507}, {120580, 16846851},
2443
  {120581, 16853763}, {120582, 16854019}, {120583, 16786179}, {120584, 16854275},
2444
  {120585, 16854531}, {120586, 16854787}, {120587, 16855043}, {120588, 16855299},
2445
  {120589, 16855555}, {120591, 16855811}, {120592, 16856067}, {120593, 16856323},
2446
  {120594, 16856579}, {120595, 16856835}, {120596, 16857091}, {120597, 17969667},
2447
  {120598, 16852739}, {120599, 16853507}, {120600, 16853763}, {120601, 16856323},
2448
  {120602, 16855299}, {120603, 16855043}, {120604, 16851715}, {120605, 16851971},
2449
  {120606, 16852227}, {120607, 16852483}, {120608, 16852739}, {120609, 16852995},
2450
  {120610, 16853251}, {120611, 16853507}, {120612, 16846851}, {120613, 16853763},
2451
  {120614, 16854019}, {120615, 16786179}, {120616, 16854275}, {120617, 16854531},
2452
  {120618, 16854787}, {120619, 16855043}, {120620, 16855299}, {120621, 16853507},
2453
  {120622, 16855555}, {120623, 16855811}, {120624, 16856067}, {120625, 16856323},
2454
  {120626, 16856579}, {120627, 16856835}, {120628, 16857091}, {120629, 17969411},
2455
  {120630, 16851715}, {120631, 16851971}, {120632, 16852227}, {120633, 16852483},
2456
  {120634, 16852739}, {120635, 16852995}, {120636, 16853251}, {120637, 16853507},
2457
  {120638, 16846851}, {120639, 16853763}, {120640, 16854019}, {120641, 16786179},
2458
  {120642, 16854275}, {120643, 16854531}, {120644, 16854787}, {120645, 16855043},
2459
  {120646, 16855299}, {120647, 16855555}, {120649, 16855811}, {120650, 16856067},
2460
  {120651, 16856323}, {120652, 16856579}, {120653, 16856835}, {120654, 16857091},
2461
  {120655, 17969667}, {120656, 16852739}, {120657, 16853507}, {120658, 16853763},
2462
  {120659, 16856323}, {120660, 16855299}, {120661, 16855043}, {120662, 16851715},
2463
  {120663, 16851971}, {120664, 16852227}, {120665, 16852483}, {120666, 16852739},
2464
  {120667, 16852995}, {120668, 16853251}, {120669, 16853507}, {120670, 16846851},
2465
  {120671, 16853763}, {120672, 16854019}, {120673, 16786179}, {120674, 16854275},
2466
  {120675, 16854531}, {120676, 16854787}, {120677, 16855043}, {120678, 16855299},
2467
  {120679, 16853507}, {120680, 16855555}, {120681, 16855811}, {120682, 16856067},
2468
  {120683, 16856323}, {120684, 16856579}, {120685, 16856835}, {120686, 16857091},
2469
  {120687, 17969411}, {120688, 16851715}, {120689, 16851971}, {120690, 16852227},
2470
  {120691, 16852483}, {120692, 16852739}, {120693, 16852995}, {120694, 16853251},
2471
  {120695, 16853507}, {120696, 16846851}, {120697, 16853763}, {120698, 16854019},
2472
  {120699, 16786179}, {120700, 16854275}, {120701, 16854531}, {120702, 16854787},
2473
  {120703, 16855043}, {120704, 16855299}, {120705, 16855555}, {120707, 16855811},
2474
  {120708, 16856067}, {120709, 16856323}, {120710, 16856579}, {120711, 16856835},
2475
  {120712, 16857091}, {120713, 17969667}, {120714, 16852739}, {120715, 16853507},
2476
  {120716, 16853763}, {120717, 16856323}, {120718, 16855299}, {120719, 16855043},
2477
  {120720, 16851715}, {120721, 16851971}, {120722, 16852227}, {120723, 16852483},
2478
  {120724, 16852739}, {120725, 16852995}, {120726, 16853251}, {120727, 16853507},
2479
  {120728, 16846851}, {120729, 16853763}, {120730, 16854019}, {120731, 16786179},
2480
  {120732, 16854275}, {120733, 16854531}, {120734, 16854787}, {120735, 16855043},
2481
  {120736, 16855299}, {120737, 16853507}, {120738, 16855555}, {120739, 16855811},
2482
  {120740, 16856067}, {120741, 16856323}, {120742, 16856579}, {120743, 16856835},
2483
  {120744, 16857091}, {120745, 17969411}, {120746, 16851715}, {120747, 16851971},
2484
  {120748, 16852227}, {120749, 16852483}, {120750, 16852739}, {120751, 16852995},
2485
  {120752, 16853251}, {120753, 16853507}, {120754, 16846851}, {120755, 16853763},
2486
  {120756, 16854019}, {120757, 16786179}, {120758, 16854275}, {120759, 16854531},
2487
  {120760, 16854787}, {120761, 16855043}, {120762, 16855299}, {120763, 16855555},
2488
  {120765, 16855811}, {120766, 16856067}, {120767, 16856323}, {120768, 16856579},
2489
  {120769, 16856835}, {120770, 16857091}, {120771, 17969667}, {120772, 16852739},
2490
  {120773, 16853507}, {120774, 16853763}, {120775, 16856323}, {120776, 16855299},
2491
  {120777, 16855043}, {120778, 16858627}, {120780, 2}, {120782, 17045507},
2492
  {120783, 16786947}, {120784, 16785155}, {120785, 16785411}, {120786, 16787715},
2493
  {120787, 17045763}, {120788, 17046019}, {120789, 17046275}, {120790, 17046531},
2494
  {120791, 17046787}, {120792, 17045507}, {120793, 16786947}, {120794, 16785155},
2495
  {120795, 16785411}, {120796, 16787715}, {120797, 17045763}, {120798, 17046019},
2496
  {120799, 17046275}, {120800, 17046531}, {120801, 17046787}, {120802, 17045507},
2497
  {120803, 16786947}, {120804, 16785155}, {120805, 16785411}, {120806, 16787715},
2498
  {120807, 17045763}, {120808, 17046019}, {120809, 17046275}, {120810, 17046531},
2499
  {120811, 17046787}, {120812, 17045507}, {120813, 16786947}, {120814, 16785155},
2500
  {120815, 16785411}, {120816, 16787715}, {120817, 17045763}, {120818, 17046019},
2501
  {120819, 17046275}, {120820, 17046531}, {120821, 17046787}, {120822, 17045507},
2502
  {120823, 16786947}, {120824, 16785155}, {120825, 16785411}, {120826, 16787715},
2503
  {120827, 17045763}, {120828, 17046019}, {120829, 17046275}, {120830, 17046531},
2504
  {120831, 17046787}, {120832, 1}, {121484, 2}, {121499, 1},
2505
  {121504, 2}, {121505, 1}, {121520, 2}, {122624, 1},
2506
  {122655, 2}, {122661, 1}, {122667, 2}, {122880, 1},
2507
  {122887, 2}, {122888, 1}, {122905, 2}, {122907, 1},
2508
  {122914, 2}, {122915, 1}, {122917, 2}, {122918, 1},
2509
  {122923, 2}, {122928, 16866563}, {122929, 16866819}, {122930, 16867075},
2510
  {122931, 16867331}, {122932, 16867587}, {122933, 16867843}, {122934, 16868099},
2511
  {122935, 16868355}, {122936, 16868611}, {122937, 16869123}, {122938, 16869379},
2512
  {122939, 16869635}, {122940, 16870147}, {122941, 16870403}, {122942, 16870659},
2513
  {122943, 16870915}, {122944, 16871171}, {122945, 16871427}, {122946, 16871683},
2514
  {122947, 16871939}, {122948, 16872195}, {122949, 16872451}, {122950, 16872707},
2515
  {122951, 16873475}, {122952, 16873987}, {122953, 16874243}, {122954, 17505795},
2516
  {122955, 16889091}, {122956, 16864003}, {122957, 16864515}, {122958, 16891139},
2517
  {122959, 16883715}, {122960, 16886019}, {122961, 16866563}, {122962, 16866819},
2518
  {122963, 16867075}, {122964, 16867331}, {122965, 16867587}, {122966, 16867843},
2519
  {122967, 16868099}, {122968, 16868355}, {122969, 16868611}, {122970, 16869123},
2520
  {122971, 16869379}, {122972, 16870147}, {122973, 16870403}, {122974, 16870915},
2521
  {122975, 16871427}, {122976, 16871683}, {122977, 16871939}, {122978, 16872195},
2522
  {122979, 16872451}, {122980, 16872707}, {122981, 16873219}, {122982, 16873475},
2523
  {122983, 16879875}, {122984, 16864003}, {122985, 16863747}, {122986, 16866307},
2524
  {122987, 16883203}, {122988, 17500931}, {122989, 16883971}, {122990, 2},
2525
  {123023, 1}, {123024, 2}, {123136, 1}, {123181, 2},
2526
  {123184, 1}, {123198, 2}, {123200, 1}, {123210, 2},
2527
  {123214, 1}, {123216, 2}, {123536, 1}, {123567, 2},
2528
  {123584, 1}, {123642, 2}, {123647, 1}, {123648, 2},
2529
  {124112, 1}, {124154, 2}, {124368, 1}, {124411, 2},
2530
  {124415, 1}, {124416, 2}, {124608, 1}, {124639, 2},
2531
  {124640, 1}, {124662, 2}, {124670, 1}, {124672, 2},
2532
  {124896, 1}, {124903, 2}, {124904, 1}, {124908, 2},
2533
  {124909, 1}, {124911, 2}, {124912, 1}, {124927, 2},
2534
  {124928, 1}, {125125, 2}, {125127, 1}, {125143, 2},
2535
  {125184, 17969923}, {125185, 17970179}, {125186, 17970435}, {125187, 17970691},
2536
  {125188, 17970947}, {125189, 17971203}, {125190, 17971459}, {125191, 17971715},
2537
  {125192, 17971971}, {125193, 17972227}, {125194, 17972483}, {125195, 17972739},
2538
  {125196, 17972995}, {125197, 17973251}, {125198, 17973507}, {125199, 17973763},
2539
  {125200, 17974019}, {125201, 17974275}, {125202, 17974531}, {125203, 17974787},
2540
  {125204, 17975043}, {125205, 17975299}, {125206, 17975555}, {125207, 17975811},
2541
  {125208, 17976067}, {125209, 17976323}, {125210, 17976579}, {125211, 17976835},
2542
  {125212, 17977091}, {125213, 17977347}, {125214, 17977603}, {125215, 17977859},
2543
  {125216, 17978115}, {125217, 17978371}, {125218, 1}, {125260, 2},
2544
  {125264, 1}, {125274, 2}, {125278, 1}, {125280, 2},
2545
  {126065, 1}, {126133, 2}, {126209, 1}, {126270, 2},
2546
  {126464, 16910595}, {126465, 17696003}, {126466, 17694211}, {126467, 17846787},
2547
  {126468, 2}, {126469, 16911107}, {126470, 17743875}, {126471, 17694723},
2548
  {126472, 17712387}, {126473, 16912131}, {126474, 17721091}, {126475, 17723395},
2549
  {126476, 17695235}, {126477, 17730307}, {126478, 17707267}, {126479, 17713923},
2550
  {126480, 17715971}, {126481, 17709315}, {126482, 17719043}, {126483, 17737475},
2551
  {126484, 17757443}, {126485, 17699075}, {126486, 17702147}, {126487, 17697283},
2552
  {126488, 17736963}, {126489, 17710339}, {126490, 17713411}, {126491, 17714947},
2553
  {126492, 17978627}, {126493, 17685763}, {126494, 17978883}, {126495, 17979139},
2554
  {126496, 2}, {126497, 17696003}, {126498, 17694211}, {126499, 2},
2555
  {126500, 17733379}, {126501, 2}, {126503, 17694723}, {126504, 2},
2556
  {126505, 16912131}, {126506, 17721091}, {126507, 17723395}, {126508, 17695235},
2557
  {126509, 17730307}, {126510, 17707267}, {126511, 17713923}, {126512, 17715971},
2558
  {126513, 17709315}, {126514, 17719043}, {126515, 2}, {126516, 17757443},
2559
  {126517, 17699075}, {126518, 17702147}, {126519, 17697283}, {126520, 2},
2560
  {126521, 17710339}, {126522, 2}, {126523, 17714947}, {126524, 2},
2561
  {126530, 17694211}, {126531, 2}, {126535, 17694723}, {126536, 2},
2562
  {126537, 16912131}, {126538, 2}, {126539, 17723395}, {126540, 2},
2563
  {126541, 17730307}, {126542, 17707267}, {126543, 17713923}, {126544, 2},
2564
  {126545, 17709315}, {126546, 17719043}, {126547, 2}, {126548, 17757443},
2565
  {126549, 2}, {126551, 17697283}, {126552, 2}, {126553, 17710339},
2566
  {126554, 2}, {126555, 17714947}, {126556, 2}, {126557, 17685763},
2567
  {126558, 2}, {126559, 17979139}, {126560, 2}, {126561, 17696003},
2568
  {126562, 17694211}, {126563, 2}, {126564, 17733379}, {126565, 2},
2569
  {126567, 17694723}, {126568, 17712387}, {126569, 16912131}, {126570, 17721091},
2570
  {126571, 2}, {126572, 17695235}, {126573, 17730307}, {126574, 17707267},
2571
  {126575, 17713923}, {126576, 17715971}, {126577, 17709315}, {126578, 17719043},
2572
  {126579, 2}, {126580, 17757443}, {126581, 17699075}, {126582, 17702147},
2573
  {126583, 17697283}, {126584, 2}, {126585, 17710339}, {126586, 17713411},
2574
  {126587, 17714947}, {126588, 17978627}, {126589, 2}, {126590, 17978883},
2575
  {126591, 2}, {126592, 16910595}, {126593, 17696003}, {126594, 17694211},
2576
  {126595, 17846787}, {126596, 17733379}, {126597, 16911107}, {126598, 17743875},
2577
  {126599, 17694723}, {126600, 17712387}, {126601, 16912131}, {126602, 2},
2578
  {126603, 17723395}, {126604, 17695235}, {126605, 17730307}, {126606, 17707267},
2579
  {126607, 17713923}, {126608, 17715971}, {126609, 17709315}, {126610, 17719043},
2580
  {126611, 17737475}, {126612, 17757443}, {126613, 17699075}, {126614, 17702147},
2581
  {126615, 17697283}, {126616, 17736963}, {126617, 17710339}, {126618, 17713411},
2582
  {126619, 17714947}, {126620, 2}, {126625, 17696003}, {126626, 17694211},
2583
  {126627, 17846787}, {126628, 2}, {126629, 16911107}, {126630, 17743875},
2584
  {126631, 17694723}, {126632, 17712387}, {126633, 16912131}, {126634, 2},
2585
  {126635, 17723395}, {126636, 17695235}, {126637, 17730307}, {126638, 17707267},
2586
  {126639, 17713923}, {126640, 17715971}, {126641, 17709315}, {126642, 17719043},
2587
  {126643, 17737475}, {126644, 17757443}, {126645, 17699075}, {126646, 17702147},
2588
  {126647, 17697283}, {126648, 17736963}, {126649, 17710339}, {126650, 17713411},
2589
  {126651, 17714947}, {126652, 2}, {126704, 1}, {126706, 2},
2590
  {126976, 1}, {127020, 2}, {127024, 1}, {127124, 2},
2591
  {127136, 1}, {127151, 2}, {127153, 1}, {127168, 2},
2592
  {127169, 1}, {127184, 2}, {127185, 1}, {127222, 2},
2593
  {127233, 34756611}, {127234, 34757123}, {127235, 34757635}, {127236, 34758147},
2594
  {127237, 34758659}, {127238, 34759171}, {127239, 34759683}, {127240, 34760195},
2595
  {127241, 34760707}, {127242, 34761219}, {127243, 1}, {127248, 50655491},
2596
  {127249, 50656259}, {127250, 50657027}, {127251, 50657795}, {127252, 50658563},
2597
  {127253, 50659331}, {127254, 50660099}, {127255, 50660867}, {127256, 50661635},
2598
  {127257, 50662403}, {127258, 50663171}, {127259, 50663939}, {127260, 50664707},
2599
  {127261, 50665475}, {127262, 50666243}, {127263, 50667011}, {127264, 50667779},
2600
  {127265, 50668547}, {127266, 50669315}, {127267, 50670083}, {127268, 50670851},
2601
  {127269, 50671619}, {127270, 50672387}, {127271, 50673155}, {127272, 50673923},
2602
  {127273, 50674691}, {127274, 51538947}, {127275, 16777731}, {127276, 16781571},
2603
  {127277, 33554947}, {127278, 34762499}, {127279, 1}, {127280, 16777219},
2604
  {127281, 16777475}, {127282, 16777731}, {127283, 16777987}, {127284, 16778243},
2605
  {127285, 16778499}, {127286, 16778755}, {127287, 16779011}, {127288, 16779267},
2606
  {127289, 16779523}, {127290, 16779779}, {127291, 16780035}, {127292, 16780291},
2607
  {127293, 16780547}, {127294, 16780803}, {127295, 16781059}, {127296, 16781315},
2608
  {127297, 16781571}, {127298, 16781827}, {127299, 16782083}, {127300, 16782339},
2609
  {127301, 16782595}, {127302, 16782851}, {127303, 16783107}, {127304, 16783363},
2610
  {127305, 16783619}, {127306, 34763011}, {127307, 34237187}, {127308, 34763523},
2611
  {127309, 34764035}, {127310, 51541763}, {127311, 34765315}, {127312, 1},
2612
  {127338, 34220035}, {127339, 34200067}, {127340, 34765827}, {127341, 1},
2613
  {127376, 34766339}, {127377, 1}, {127406, 2}, {127462, 1},
2614
  {127488, 34766851}, {127489, 34767363}, {127490, 17318403}, {127491, 2},
2615
  {127504, 17168387}, {127505, 17990659}, {127506, 17990915}, {127507, 17362179},
2616
  {127508, 17153795}, {127509, 17991171}, {127510, 17991427}, {127511, 17235971},
2617
  {127512, 17991683}, {127513, 17991939}, {127514, 17992195}, {127515, 17596931},
2618
  {127516, 17992451}, {127517, 17992707}, {127518, 17992963}, {127519, 17993219},
2619
  {127520, 17993475}, {127521, 17993731}, {127522, 17177603}, {127523, 17993987},
2620
  {127524, 17994243}, {127525, 17994499}, {127526, 17994755}, {127527, 17995011},
2621
  {127528, 17995267}, {127529, 17152259}, {127530, 17233923}, {127531, 17995523},
2622
  {127532, 17299203}, {127533, 17234691}, {127534, 17299459}, {127535, 17995779},
2623
  {127536, 17191939}, {127537, 17996035}, {127538, 17996291}, {127539, 17996547},
2624
  {127540, 17996803}, {127541, 17997059}, {127542, 17274883}, {127543, 17170947},
2625
  {127544, 17997315}, {127545, 17997571}, {127546, 17997827}, {127547, 17998083},
2626
  {127548, 2}, {127552, 51552771}, {127553, 51553539}, {127554, 51554307},
2627
  {127555, 51555075}, {127556, 51555843}, {127557, 51556611}, {127558, 51557379},
2628
  {127559, 51558147}, {127560, 51558915}, {127561, 2}, {127568, 18005251},
2629
  {127569, 18005507}, {127570, 2}, {127584, 1}, {127590, 2},
2630
  {127744, 1}, {128729, 2}, {128732, 1}, {128749, 2},
2631
  {128752, 1}, {128765, 2}, {128768, 1}, {128986, 2},
2632
  {128992, 1}, {129004, 2}, {129008, 1}, {129009, 2},
2633
  {129024, 1}, {129036, 2}, {129040, 1}, {129096, 2},
2634
  {129104, 1}, {129114, 2}, {129120, 1}, {129160, 2},
2635
  {129168, 1}, {129198, 2}, {129200, 1}, {129212, 2},
2636
  {129216, 1}, {129218, 2}, {129232, 1}, {129241, 2},
2637
  {129280, 1}, {129624, 2}, {129632, 1}, {129646, 2},
2638
  {129648, 1}, {129661, 2}, {129664, 1}, {129675, 2},
2639
  {129678, 1}, {129735, 2}, {129736, 1}, {129737, 2},
2640
  {129741, 1}, {129757, 2}, {129759, 1}, {129771, 2},
2641
  {129775, 1}, {129785, 2}, {129792, 1}, {129939, 2},
2642
  {129940, 1}, {130032, 17045507}, {130033, 16786947}, {130034, 16785155},
2643
  {130035, 16785411}, {130036, 16787715}, {130037, 17045763}, {130038, 17046019},
2644
  {130039, 17046275}, {130040, 17046531}, {130041, 17046787}, {130042, 1},
2645
  {130043, 2}, {131072, 1}, {173792, 2}, {173824, 1},
2646
  {178206, 2}, {178208, 1}, {183982, 2}, {183984, 1},
2647
  {191457, 2}, {191472, 1}, {192094, 2}, {194560, 18005763},
2648
  {194561, 18006019}, {194562, 18006275}, {194563, 18006531}, {194564, 18006787},
2649
  {194565, 17620739}, {194566, 18007043}, {194567, 18007299}, {194568, 18007555},
2650
  {194569, 18007811}, {194570, 17620995}, {194571, 18008067}, {194572, 18008323},
2651
  {194573, 18008579}, {194574, 17621251}, {194575, 18008835}, {194576, 18009091},
2652
  {194577, 18009347}, {194578, 18009603}, {194579, 18009859}, {194580, 18010115},
2653
  {194581, 17992963}, {194582, 18010371}, {194583, 18010627}, {194584, 18010883},
2654
  {194585, 18011139}, {194586, 18011395}, {194587, 17635331}, {194588, 18011651},
2655
  {194589, 17156355}, {194590, 18011907}, {194591, 18012163}, {194592, 18012419},
2656
  {194593, 18012675}, {194594, 17997571}, {194595, 18012931}, {194596, 18013187},
2657
  {194597, 17636611}, {194598, 17621507}, {194599, 17621763}, {194600, 17636867},
2658
  {194601, 18013443}, {194602, 18013699}, {194603, 17575171}, {194604, 18013955},
2659
  {194605, 17622019}, {194606, 18014211}, {194607, 18014467}, {194608, 18014723},
2660
  {194609, 18014979}, {194612, 18015235}, {194613, 18015491}, {194614, 18015747},
2661
  {194615, 18016003}, {194616, 18016259}, {194617, 18016515}, {194618, 18016771},
2662
  {194619, 18017027}, {194620, 18017283}, {194621, 18017539}, {194622, 18017795},
2663
  {194623, 18018051}, {194624, 18018307}, {194625, 18018563}, {194626, 18018819},
2664
  {194627, 18019075}, {194628, 18019331}, {194629, 18019587}, {194631, 17637379},
2665
  {194632, 18019843}, {194633, 18020099}, {194634, 18020355}, {194635, 18020611},
2666
  {194636, 17622531}, {194637, 18020867}, {194638, 18021123}, {194639, 18021379},
2667
  {194640, 17612291}, {194641, 18021635}, {194642, 18021891}, {194643, 18022147},
2668
  {194644, 18022403}, {194645, 18022659}, {194646, 18022915}, {194647, 18023171},
2669
  {194648, 18023427}, {194649, 18023683}, {194650, 18023939}, {194651, 18024195},
2670
  {194652, 18024451}, {194653, 17991171}, {194654, 18024707}, {194655, 18024963},
2671
  {194656, 18025219}, {194657, 18025475}, {194658, 18025731}, {194659, 18025987},
2672
  {194660, 18026243}, {194661, 18026499}, {194662, 18026755}, {194663, 18027011},
2673
  {194664, 18027267}, {194665, 18027523}, {194666, 18027779}, {194668, 18028035},
2674
  {194669, 18028291}, {194670, 18028547}, {194671, 17574147}, {194672, 18028803},
2675
  {194673, 18029059}, {194674, 18029315}, {194675, 18029571}, {194676, 18029827},
2676
  {194677, 17163011}, {194678, 18030083}, {194679, 18030339}, {194680, 17163523},
2677
  {194681, 18030595}, {194682, 18030851}, {194683, 18031107}, {194684, 18031363},
2678
  {194685, 18031619}, {194686, 18031875}, {194687, 18032131}, {194688, 18032387},
2679
  {194689, 18032643}, {194690, 18032899}, {194691, 18033155}, {194692, 18033411},
2680
  {194693, 18033667}, {194694, 18033923}, {194695, 18034179}, {194696, 18034435},
2681
  {194697, 18034691}, {194698, 18034947}, {194699, 18035203}, {194700, 18035459},
2682
  {194701, 18035715}, {194702, 17560835}, {194703, 18035971}, {194704, 17166083},
2683
  {194705, 18036227}, {194707, 18036483}, {194708, 18036739}, {194710, 18036995},
2684
  {194711, 18037251}, {194712, 18037507}, {194713, 18037763}, {194714, 18038019},
2685
  {194715, 18038275}, {194716, 18038531}, {194717, 18038787}, {194718, 18039043},
2686
  {194719, 18039299}, {194720, 18039555}, {194721, 18039811}, {194722, 18040067},
2687
  {194723, 17623811}, {194724, 18040323}, {194725, 18040579}, {194726, 18040835},
2688
  {194727, 18041091}, {194728, 17640451}, {194729, 18041091}, {194730, 18041347},
2689
  {194731, 17624323}, {194732, 18041603}, {194733, 18041859}, {194734, 18042115},
2690
  {194735, 18042371}, {194736, 17624579}, {194737, 17553923}, {194738, 17425411},
2691
  {194739, 18042627}, {194740, 18042883}, {194741, 18043139}, {194742, 18043395},
2692
  {194743, 18043651}, {194744, 18043907}, {194745, 18044163}, {194746, 18044419},
2693
  {194747, 18044675}, {194748, 18044931}, {194749, 18045187}, {194750, 18045443},
2694
  {194751, 18045699}, {194752, 18045955}, {194753, 18046211}, {194754, 18046467},
2695
  {194755, 18046723}, {194756, 18046979}, {194757, 18047235}, {194758, 18047491},
2696
  {194759, 18047747}, {194760, 17624835}, {194761, 18048003}, {194762, 18048259},
2697
  {194763, 18048515}, {194764, 18048771}, {194765, 18049027}, {194766, 18049283},
2698
  {194767, 17625347}, {194768, 18049539}, {194769, 18049795}, {194770, 18050051},
2699
  {194771, 18050307}, {194772, 18050563}, {194773, 18050819}, {194774, 18051075},
2700
  {194775, 18051331}, {194776, 17561091}, {194777, 17642499}, {194778, 18051587},
2701
  {194779, 18051843}, {194780, 18052099}, {194781, 18052355}, {194782, 18052611},
2702
  {194783, 18052867}, {194784, 18053123}, {194785, 18053379}, {194786, 17625603},
2703
  {194787, 18053635}, {194788, 18053891}, {194789, 18054147}, {194790, 18054403},
2704
  {194791, 17653251}, {194792, 18054659}, {194793, 18054915}, {194794, 18055171},
2705
  {194795, 18055427}, {194796, 18055683}, {194797, 18055939}, {194798, 18056195},
2706
  {194799, 18056451}, {194800, 18056707}, {194801, 18056963}, {194802, 18057219},
2707
  {194803, 18057475}, {194804, 18057731}, {194805, 17578499}, {194806, 18057987},
2708
  {194807, 18058243}, {194808, 18058499}, {194809, 18058755}, {194810, 18059011},
2709
  {194811, 18059267}, {194812, 18059523}, {194813, 18059779}, {194814, 18060035},
2710
  {194815, 18060291}, {194816, 18060547}, {194817, 17625859}, {194818, 17599491},
2711
  {194819, 18060803}, {194820, 18061059}, {194821, 18061315}, {194822, 18061571},
2712
  {194823, 18061827}, {194824, 18062083}, {194825, 18062339}, {194826, 18062595},
2713
  {194827, 17643267}, {194828, 18062851}, {194829, 18063107}, {194830, 18063363},
2714
  {194831, 18063619}, {194832, 18063875}, {194833, 18064131}, {194834, 18064387},
2715
  {194835, 18064643}, {194836, 17643523}, {194837, 18064899}, {194838, 18065155},
2716
  {194839, 18065411}, {194840, 18065667}, {194841, 18065923}, {194842, 18066179},
2717
  {194843, 18066435}, {194844, 18066691}, {194845, 18066947}, {194846, 18067203},
2718
  {194847, 18067459}, {194848, 18067715}, {194849, 17644035}, {194850, 18067971},
2719
  {194851, 18068227}, {194852, 18068483}, {194853, 18068739}, {194854, 18068995},
2720
  {194855, 18069251}, {194856, 18069507}, {194857, 18069763}, {194858, 18070019},
2721
  {194859, 18070275}, {194860, 18070531}, {194862, 18070787}, {194863, 18071043},
2722
  {194864, 17644547}, {194865, 18071299}, {194866, 18071555}, {194867, 18071811},
2723
  {194868, 18072067}, {194869, 18072323}, {194870, 18072579}, {194871, 18072835},
2724
  {194872, 17574915}, {194873, 18073091}, {194874, 18073347}, {194875, 18073603},
2725
  {194876, 18073859}, {194877, 18074115}, {194878, 18074371}, {194879, 18074627},
2726
  {194880, 17646083}, {194881, 18074883}, {194882, 18075139}, {194883, 18075395},
2727
  {194884, 18075651}, {194885, 18075907}, {194886, 18076163}, {194888, 17646339},
2728
  {194889, 17653763}, {194890, 18076419}, {194891, 18076675}, {194892, 18076931},
2729
  {194893, 18077187}, {194894, 18077443}, {194895, 17565443}, {194896, 17646851},
2730
  {194897, 18077699}, {194898, 18077955}, {194899, 17628419}, {194900, 18078211},
2731
  {194901, 18078467}, {194902, 17617411}, {194903, 18078723}, {194904, 18078979},
2732
  {194905, 17629187}, {194906, 18079235}, {194907, 18079491}, {194908, 18079747},
2733
  {194909, 18080003}, {194911, 18080259}, {194912, 18080515}, {194913, 18080771},
2734
  {194914, 18081027}, {194915, 18081283}, {194916, 18081539}, {194917, 18081795},
2735
  {194918, 18082051}, {194919, 18082307}, {194920, 18082563}, {194921, 18082819},
2736
  {194922, 18083075}, {194923, 18083331}, {194924, 18083587}, {194925, 18083843},
2737
  {194926, 18084099}, {194927, 18084355}, {194928, 18084611}, {194929, 18084867},
2738
  {194930, 18085123}, {194931, 18085379}, {194932, 18085635}, {194933, 18085891},
2739
  {194934, 18086147}, {194935, 18086403}, {194936, 18086659}, {194937, 18086915},
2740
  {194938, 17630723}, {194939, 18087171}, {194940, 18087427}, {194941, 18087683},
2741
  {194942, 18087939}, {194943, 18088195}, {194944, 18088451}, {194945, 18088707},
2742
  {194946, 18088963}, {194947, 18089219}, {194948, 18089475}, {194949, 18089731},
2743
  {194950, 18089987}, {194951, 18090243}, {194952, 18090499}, {194953, 18090755},
2744
  {194954, 18091011}, {194955, 18036483}, {194956, 18091267}, {194957, 18091523},
2745
  {194958, 18091779}, {194959, 18092035}, {194960, 18092291}, {194961, 18092547},
2746
  {194962, 18092803}, {194963, 18093059}, {194964, 18093315}, {194965, 18093571},
2747
  {194966, 18093827}, {194967, 18094083}, {194968, 17579267}, {194969, 18094339},
2748
  {194970, 18094595}, {194971, 18094851}, {194972, 18095107}, {194973, 18095363},
2749
  {194974, 18095619}, {194975, 17631491}, {194976, 18095875}, {194977, 18096131},
2750
  {194978, 18096387}, {194979, 18096643}, {194980, 18096899}, {194981, 18097155},
2751
  {194982, 18097411}, {194983, 18097667}, {194984, 18097923}, {194985, 18098179},
2752
  {194986, 18098435}, {194987, 18098691}, {194988, 18098947}, {194989, 18099203},
2753
  {194990, 18099459}, {194991, 18099715}, {194992, 18099971}, {194993, 18100227},
2754
  {194994, 18100483}, {194995, 18100739}, {194996, 17564163}, {194997, 18100995},
2755
  {194998, 18101251}, {194999, 18101507}, {195000, 18101763}, {195001, 18102019},
2756
  {195002, 18102275}, {195003, 17648643}, {195004, 18102531}, {195005, 18102787},
2757
  {195006, 18103043}, {195007, 18103299}, {195008, 18103555}, {195009, 18103811},
2758
  {195010, 18104067}, {195011, 18104323}, {195012, 17189123}, {195013, 18104579},
2759
  {195014, 18104835}, {195015, 18105091}, {195016, 18105347}, {195017, 18105603},
2760
  {195018, 18105859}, {195019, 18106115}, {195020, 18106371}, {195021, 18106627},
2761
  {195022, 18106883}, {195023, 18107139}, {195024, 17649923}, {195025, 17650179},
2762
  {195026, 17190915}, {195027, 18107395}, {195028, 18107651}, {195029, 18107907},
2763
  {195030, 18108163}, {195031, 18108419}, {195032, 18108675}, {195033, 18108931},
2764
  {195034, 18109187}, {195035, 18109443}, {195036, 18109699}, {195037, 18109955},
2765
  {195038, 18110211}, {195039, 17650435}, {195040, 18110467}, {195041, 18110723},
2766
  {195042, 18110979}, {195043, 18111235}, {195044, 18111491}, {195045, 18111747},
2767
  {195046, 18112003}, {195047, 18112259}, {195048, 18112515}, {195049, 18112771},
2768
  {195050, 18113027}, {195051, 18113283}, {195052, 18113539}, {195053, 18113795},
2769
  {195054, 18114051}, {195055, 18114307}, {195056, 18114563}, {195057, 18114819},
2770
  {195058, 18115075}, {195059, 18115331}, {195060, 18115587}, {195061, 18115843},
2771
  {195062, 18116099}, {195063, 18116355}, {195064, 18116611}, {195065, 18116867},
2772
  {195066, 18117123}, {195067, 18117379}, {195068, 18117635}, {195069, 18117891},
2773
  {195070, 17651971}, {195072, 18118147}, {195073, 18118403}, {195074, 18118659},
2774
  {195075, 18118915}, {195076, 18119171}, {195077, 18119427}, {195078, 18119683},
2775
  {195079, 18119939}, {195080, 18120195}, {195081, 18120451}, {195082, 17652227},
2776
  {195083, 18120707}, {195084, 18120963}, {195085, 18121219}, {195086, 18121475},
2777
  {195087, 18121731}, {195088, 18121987}, {195089, 18122243}, {195090, 18122499},
2778
  {195091, 18122755}, {195092, 18123011}, {195093, 17203203}, {195094, 18123267},
2779
  {195095, 17204227}, {195096, 18123523}, {195097, 18123779}, {195098, 18124035},
2780
  {195099, 18124291}, {195100, 17205507}, {195101, 18124547}, {195102, 2},
2781
  {196608, 1}, {201547, 2}, {201552, 1}, {210042, 2},
2782
  {917760, 0}, {918000, 2}
2783
};
2784
2785
2786
} // namespace ada::idna
2787
#endif // ADA_IDNA_TABLES_H
2788
/* end file src/mapping_tables.cpp */
2789
2790
namespace ada::idna {
2791
2792
// This can be greatly accelerated. For now we just use a simply
2793
// binary search. In practice, you should *not* do that.
2794
394k
uint32_t find_range_index(uint32_t key) {
2795
  ////////////////
2796
  // This could be implemented with std::lower_bound, but we roll our own
2797
  // because we want to allow further optimizations in the future.
2798
  ////////////////
2799
394k
  uint32_t len = std::size(table);
2800
394k
  uint32_t low = 0;
2801
394k
  uint32_t high = len - 1;
2802
5.29M
  while (low <= high) {
2803
5.06M
    uint32_t middle_index = (low + high) >> 1;  // cannot overflow
2804
5.06M
    uint32_t middle_value = table[middle_index][0];
2805
5.06M
    if (middle_value < key) {
2806
1.46M
      low = middle_index + 1;
2807
3.59M
    } else if (middle_value > key) {
2808
3.44M
      high = middle_index - 1;
2809
3.44M
    } else {
2810
157k
      return middle_index;  // perfect match
2811
157k
    }
2812
5.06M
  }
2813
236k
  return low == 0 ? 0 : low - 1;
2814
394k
}
2815
2816
5.77k
void ascii_map(char* input, size_t length) {
2817
17.3k
  auto broadcast = [](uint8_t v) -> uint64_t {
2818
17.3k
    return 0x101010101010101ull * v;
2819
17.3k
  };
2820
5.77k
  uint64_t broadcast_80 = broadcast(0x80);
2821
5.77k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
2822
5.77k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2823
5.77k
  size_t i = 0;
2824
2825
29.5k
  for (; i + 7 < length; i += 8) {
2826
23.7k
    uint64_t word{};
2827
23.7k
    memcpy(&word, input + i, sizeof(word));
2828
23.7k
    word ^=
2829
23.7k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2830
23.7k
    memcpy(input + i, &word, sizeof(word));
2831
23.7k
  }
2832
5.77k
  if (i < length) {
2833
5.32k
    uint64_t word{};
2834
5.32k
    memcpy(&word, input + i, length - i);
2835
5.32k
    word ^=
2836
5.32k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2837
5.32k
    memcpy(input + i, &word, length - i);
2838
5.32k
  }
2839
5.77k
}
2840
2841
// Map the characters according to IDNA, returning the empty string on error.
2842
12.5k
std::u32string map(std::u32string_view input) {
2843
  //  [Map](https://www.unicode.org/reports/tr46/#ProcessingStepMap).
2844
  //  For each code point in the domain_name string, look up the status
2845
  //  value in Section 5, [IDNA Mapping
2846
  //  Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table),
2847
  //  and take the following actions:
2848
  //    * disallowed: Leave the code point unchanged in the string, and
2849
  //    record that there was an error.
2850
  //    * ignored: Remove the code point from the string. This is
2851
  //    equivalent to mapping the code point to an empty string.
2852
  //    * mapped: Replace the code point in the string by the value for
2853
  //    the mapping in Section 5, [IDNA Mapping
2854
  //    Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table).
2855
  //    * valid: Leave the code point unchanged in the string.
2856
12.5k
  static std::u32string error = U"";
2857
12.5k
  std::u32string answer;
2858
12.5k
  answer.reserve(input.size());
2859
394k
  for (char32_t x : input) {
2860
394k
    size_t index = find_range_index(x);
2861
394k
    uint32_t descriptor = table[index][1];
2862
394k
    uint8_t code = uint8_t(descriptor);
2863
394k
    switch (code) {
2864
368
      case 0:
2865
368
        break;  // nothing to do, ignored
2866
253k
      case 1:
2867
253k
        answer.push_back(x);  // valid, we just copy it to output
2868
253k
        break;
2869
208
      case 2:
2870
208
        return error;  // disallowed
2871
      // case 3 :
2872
139k
      default:
2873
        // We have a mapping
2874
139k
        {
2875
139k
          size_t char_count = (descriptor >> 24);
2876
139k
          uint16_t char_index = uint16_t(descriptor >> 8);
2877
1.13M
          for (size_t idx = char_index; idx < char_index + char_count; idx++) {
2878
990k
            answer.push_back(mappings[idx]);
2879
990k
          }
2880
139k
        }
2881
394k
    }
2882
394k
  }
2883
12.3k
  return answer;
2884
12.5k
}
2885
}  // namespace ada::idna
2886
/* end file src/mapping.cpp */
2887
/* begin file src/normalization.cpp */
2888
/* begin file src/normalization_tables.cpp */
2889
// IDNA  17.0.0
2890
2891
// clang-format off
2892
#ifndef ADA_IDNA_NORMALIZATION_TABLES_H
2893
#define ADA_IDNA_NORMALIZATION_TABLES_H
2894
#include <cstdint>
2895
2896
/**
2897
 * Unicode Standard Annex #15
2898
 *
2899
 * UNICODE NORMALIZATION FORMS
2900
 * https://www.unicode.org/reports/tr15/
2901
 *
2902
 * See https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/data/data_norm.h for reference.
2903
 */
2904
2905
namespace ada::idna {
2906
2907
const uint8_t decomposition_index[4352] = {
2908
    0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  9,  10, 11, 12, 13, 14, 15, 7,  7,
2909
    7,  7,  7,  7,  7,  7,  7,  7,  16, 7,  17, 18, 19, 20, 21, 22, 23, 24, 7,
2910
    7,  7,  7,  7,  25, 7,  26, 27, 28, 29, 30, 31, 32, 33, 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,  34, 35, 7,  7,  7,
2917
    36, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2918
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2919
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  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,  37, 38, 39, 40, 41, 42, 43, 7,  7,  7,  7,  7,  7,  7,  44, 7,  7,
2922
    7,  7,  7,  7,  7,  7,  45, 46, 7,  47, 48, 49, 7,  7,  7,  50, 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,  51, 7,  52, 53, 54, 55, 56, 7,  7,  7,
2933
    7,  7,  7,  7,  7,  57, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  58,
2934
    59, 7,  60, 61, 62, 7,  7,  7,  7,  7,  7,  7,  7,  63, 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
    64, 65, 66, 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,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3123
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3124
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3125
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3126
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3127
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3128
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3129
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3130
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3131
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3132
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3133
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3134
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3135
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3136
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3137
    7};
3138
3139
const uint16_t decomposition_block[67][257] = {
3140
    {4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3141
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3142
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3143
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3144
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3145
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3146
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3147
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3148
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3149
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3150
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   5,   8,   8,   8,   8,
3151
     8,   8,   8,   9,   16,  17,  20,  20,  20,  20,  21,  28,  28,  29,  33,
3152
     37,  45,  48,  48,  49,  57,  61,  64,  65,  77,  89,  100, 100, 108, 116,
3153
     124, 132, 140, 148, 148, 156, 164, 172, 180, 188, 196, 204, 212, 220, 220,
3154
     228, 236, 244, 252, 260, 268, 268, 268, 276, 284, 292, 300, 308, 308, 308,
3155
     316, 324, 332, 340, 348, 356, 356, 364, 372, 380, 388, 396, 404, 412, 420,
3156
     428, 428, 436, 444, 452, 460, 468, 476, 476, 476, 484, 492, 500, 508, 516,
3157
     516, 524},
3158
    {524,  532,  540,  548,  556,  564,  572,  580,  588,  596,  604,  612,
3159
     620,  628,  636,  644,  652,  652,  652,  660,  668,  676,  684,  692,
3160
     700,  708,  716,  724,  732,  740,  748,  756,  764,  772,  780,  788,
3161
     796,  804,  812,  812,  812,  820,  828,  836,  844,  852,  860,  868,
3162
     876,  884,  885,  893,  900,  908,  916,  924,  932,  932,  940,  948,
3163
     956,  964,  972,  981,  989,  996,  996,  996,  1004, 1012, 1020, 1028,
3164
     1036, 1045, 1052, 1052, 1052, 1060, 1068, 1076, 1084, 1092, 1100, 1100,
3165
     1100, 1108, 1116, 1124, 1132, 1140, 1148, 1156, 1164, 1172, 1180, 1188,
3166
     1196, 1204, 1212, 1220, 1228, 1236, 1244, 1244, 1244, 1252, 1260, 1268,
3167
     1276, 1284, 1292, 1300, 1308, 1316, 1324, 1332, 1340, 1348, 1356, 1364,
3168
     1372, 1380, 1388, 1396, 1404, 1412, 1420, 1429, 1432, 1432, 1432, 1432,
3169
     1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3170
     1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3171
     1432, 1432, 1432, 1432, 1432, 1440, 1448, 1448, 1448, 1448, 1448, 1448,
3172
     1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1456, 1464, 1464, 1464,
3173
     1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464,
3174
     1464, 1464, 1464, 1464, 1465, 1477, 1489, 1501, 1509, 1517, 1525, 1533,
3175
     1541, 1548, 1556, 1564, 1572, 1580, 1588, 1596, 1604, 1612, 1624, 1636,
3176
     1648, 1660, 1672, 1684, 1696, 1708, 1708, 1720, 1732, 1744, 1756, 1764,
3177
     1772, 1772, 1772, 1780, 1788, 1796, 1804, 1812, 1820, 1832, 1844, 1852,
3178
     1860, 1869, 1877, 1885, 1892, 1900, 1908, 1908, 1908, 1916, 1924, 1936,
3179
     1948, 1956, 1964, 1972, 1980},
3180
    {1980, 1988, 1996, 2004, 2012, 2020, 2028, 2036, 2044, 2052, 2060, 2068,
3181
     2076, 2084, 2092, 2100, 2108, 2116, 2124, 2132, 2140, 2148, 2156, 2164,
3182
     2172, 2180, 2188, 2196, 2204, 2204, 2204, 2212, 2220, 2220, 2220, 2220,
3183
     2220, 2220, 2220, 2228, 2236, 2244, 2252, 2264, 2276, 2288, 2300, 2308,
3184
     2316, 2328, 2340, 2348, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3185
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3186
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3187
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3188
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3189
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3190
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3191
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3192
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3193
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3194
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2357, 2361, 2365, 2369,
3195
     2373, 2377, 2381, 2385, 2389, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3196
     2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3197
     2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3198
     2393, 2401, 2409, 2417, 2425, 2433, 2440, 2440, 2441, 2445, 2449, 2453,
3199
     2457, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3200
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3201
     2460, 2460, 2460, 2460, 2460},
3202
    {2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3203
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3204
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3205
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3206
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3207
     2460, 2460, 2460, 2460, 2460, 2464, 2468, 2468, 2472, 2480, 2480, 2480,
3208
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3209
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3210
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3211
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2484, 2484, 2484,
3212
     2484, 2484, 2485, 2492, 2492, 2492, 2492, 2496, 2496, 2496, 2496, 2496,
3213
     2497, 2506, 2512, 2520, 2524, 2532, 2540, 2548, 2548, 2556, 2556, 2564,
3214
     2572, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3215
     2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3216
     2584, 2584, 2584, 2592, 2600, 2608, 2616, 2624, 2632, 2644, 2644, 2644,
3217
     2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644,
3218
     2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2652,
3219
     2660, 2668, 2676, 2684, 2685, 2689, 2693, 2698, 2706, 2713, 2717, 2720,
3220
     2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3221
     2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3222
     2721, 2725, 2729, 2732, 2733, 2737, 2740, 2740, 2740, 2741, 2744, 2744,
3223
     2744, 2744, 2744, 2744, 2744},
3224
    {2744, 2752, 2760, 2760, 2768, 2768, 2768, 2768, 2776, 2776, 2776, 2776,
3225
     2776, 2784, 2792, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800,
3226
     2800, 2800, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3227
     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3228
     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2816, 2816,
3229
     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816,
3230
     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2824, 2832, 2832,
3231
     2840, 2840, 2840, 2840, 2848, 2848, 2848, 2848, 2848, 2856, 2864, 2872,
3232
     2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872,
3233
     2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2880,
3234
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3235
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3236
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3237
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3238
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3239
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3240
     2888, 2888, 2896, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904,
3241
     2904, 2904, 2904, 2904, 2904, 2912, 2920, 2928, 2936, 2936, 2936, 2944,
3242
     2952, 2952, 2952, 2960, 2968, 2976, 2984, 2992, 3000, 3000, 3000, 3008,
3243
     3016, 3024, 3032, 3040, 3048, 3048, 3048, 3056, 3064, 3072, 3080, 3088,
3244
     3096, 3104, 3112, 3120, 3128, 3136, 3144, 3144, 3144, 3152, 3160, 3160,
3245
     3160, 3160, 3160, 3160, 3160},
3246
    {3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3247
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3248
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3249
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3250
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3251
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3252
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3253
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3254
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3255
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3256
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3257
     3160, 3160, 3160, 3161, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3258
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3259
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3260
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3261
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3262
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3263
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3264
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3265
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3266
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3267
     3168, 3168, 3168, 3168, 3168},
3268
    {3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3269
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3270
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3176,
3271
     3184, 3192, 3200, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3272
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3273
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3274
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3275
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3276
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3277
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3209, 3217, 3225,
3278
     3233, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3279
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3280
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3281
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3282
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3283
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3284
     3240, 3248, 3248, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256,
3285
     3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3264, 3264, 3264, 3264,
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},
3290
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3291
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3292
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3293
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3294
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3295
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3296
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3297
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3298
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3299
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3300
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
3301
    {3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3302
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3303
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3304
     3264, 3264, 3264, 3264, 3264, 3264, 3272, 3272, 3272, 3272, 3272, 3272,
3305
     3272, 3272, 3280, 3280, 3280, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3306
     3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3307
     3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3308
     3288, 3288, 3288, 3288, 3288, 3296, 3304, 3312, 3320, 3328, 3336, 3344,
3309
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3310
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3311
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3312
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3313
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3314
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3315
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3316
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3317
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3318
     3360, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368,
3319
     3368, 3368, 3368, 3368, 3368, 3376, 3384, 3384, 3392, 3392, 3392, 3392,
3320
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3321
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3322
     3392, 3392, 3392, 3392, 3392},
3323
    {3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3324
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3325
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3326
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3327
     3392, 3392, 3392, 3392, 3400, 3400, 3400, 3408, 3408, 3408, 3408, 3408,
3328
     3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3329
     3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3330
     3408, 3408, 3408, 3408, 3408, 3408, 3416, 3424, 3432, 3432, 3432, 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, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3337
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3338
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3339
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3340
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3341
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3342
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3343
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3344
     3440, 3440, 3440, 3440, 3440},
3345
    {3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3346
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3347
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3348
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3349
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3350
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3351
     3440, 3448, 3448, 3448, 3456, 3464, 3464, 3464, 3464, 3464, 3464, 3464,
3352
     3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3472, 3480, 3480,
3353
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3354
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3355
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3356
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3357
     3480, 3480, 3480, 3480, 3480, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3358
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3359
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3360
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3361
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3496,
3362
     3504, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3363
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3364
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3365
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3366
     3512, 3512, 3512, 3512, 3512},
3367
    {3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3368
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3369
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3370
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3371
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3372
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3373
     3512, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3374
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3375
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3376
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3377
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3378
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3379
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3380
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3381
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3382
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3383
     3520, 3528, 3528, 3528, 3528, 3528, 3528, 3528, 3536, 3544, 3544, 3552,
3384
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3385
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3386
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3387
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3388
     3564, 3564, 3564, 3564, 3564},
3389
    {3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3390
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3391
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3392
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3393
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3394
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3395
     3564, 3564, 3564, 3572, 3580, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3396
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3397
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3398
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3399
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3400
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3401
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3402
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3403
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3404
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3405
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3406
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3407
     3588, 3588, 3588, 3596, 3596, 3604, 3616, 3624, 3624, 3624, 3624, 3624,
3408
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3409
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3410
     3624, 3624, 3624, 3624, 3624},
3411
    {3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3412
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3413
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3414
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3415
     3624, 3624, 3624, 3625, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3416
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3417
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3418
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3419
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3420
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3421
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3422
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3423
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3424
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3425
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3633,
3426
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3427
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3428
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3429
     3640, 3640, 3640, 3640, 3641, 3649, 3656, 3656, 3656, 3656, 3656, 3656,
3430
     3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3431
     3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3432
     3656, 3656, 3656, 3656, 3656},
3433
    {3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3434
     3657, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3435
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3436
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3437
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3438
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3668, 3668, 3668, 3668,
3439
     3668, 3668, 3668, 3668, 3668, 3668, 3676, 3676, 3676, 3676, 3676, 3684,
3440
     3684, 3684, 3684, 3684, 3692, 3692, 3692, 3692, 3692, 3700, 3700, 3700,
3441
     3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3708, 3708,
3442
     3708, 3708, 3708, 3708, 3708, 3708, 3708, 3708, 3716, 3716, 3724, 3733,
3443
     3744, 3753, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3772, 3772,
3444
     3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772,
3445
     3772, 3772, 3772, 3772, 3780, 3780, 3780, 3780, 3780, 3780, 3780, 3780,
3446
     3780, 3780, 3788, 3788, 3788, 3788, 3788, 3796, 3796, 3796, 3796, 3796,
3447
     3804, 3804, 3804, 3804, 3804, 3812, 3812, 3812, 3812, 3812, 3812, 3812,
3448
     3812, 3812, 3812, 3812, 3812, 3812, 3820, 3820, 3820, 3820, 3820, 3820,
3449
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3450
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3451
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3452
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3453
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3454
     3820, 3820, 3820, 3820, 3820},
3455
    {3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3456
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3457
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3458
     3820, 3820, 3820, 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
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3462
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3463
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3464
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3465
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3466
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3467
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3468
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3469
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3470
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3471
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3472
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3473
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3474
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3475
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3476
     3829, 3832, 3832, 3832, 3832},
3477
    {3832, 3832, 3832, 3832, 3832, 3832, 3832, 3840, 3840, 3848, 3848, 3856,
3478
     3856, 3864, 3864, 3872, 3872, 3872, 3872, 3880, 3880, 3880, 3880, 3880,
3479
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3480
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3481
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3482
     3888, 3888, 3896, 3896, 3896, 3904, 3912, 3912, 3920, 3920, 3920, 3920,
3483
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 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, 3920, 3920, 3920, 3920,
3488
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3489
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3490
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3491
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3492
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3493
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3494
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3495
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3496
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3497
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3498
     3920, 3920, 3920, 3920, 3920},
3499
    {3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3500
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3501
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3502
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3921, 3925, 3929, 3932,
3503
     3933, 3937, 3941, 3945, 3949, 3953, 3957, 3961, 3965, 3969, 3973, 3976,
3504
     3977, 3981, 3985, 3989, 3993, 3997, 4001, 4005, 4009, 4013, 4017, 4021,
3505
     4025, 4029, 4033, 4037, 4041, 4045, 4048, 4049, 4053, 4057, 4061, 4065,
3506
     4069, 4073, 4077, 4081, 4085, 4089, 4093, 4097, 4101, 4105, 4109, 4113,
3507
     4117, 4121, 4125, 4129, 4133, 4137, 4141, 4145, 4149, 4153, 4157, 4160,
3508
     4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160,
3509
     4161, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3510
     4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3511
     4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4165,
3512
     4169, 4173, 4177, 4181, 4185, 4189, 4193, 4197, 4201, 4205, 4209, 4213,
3513
     4217, 4221, 4225, 4229, 4233, 4237, 4241, 4245, 4249, 4253, 4257, 4261,
3514
     4265, 4269, 4273, 4277, 4281, 4285, 4289, 4293, 4297, 4301, 4305, 4309,
3515
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3516
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3517
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3518
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3519
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3520
     4312, 4312, 4312, 4312, 4312},
3521
    {4312, 4320, 4328, 4336, 4344, 4352, 4360, 4368, 4376, 4388, 4400, 4408,
3522
     4416, 4424, 4432, 4440, 4448, 4456, 4464, 4472, 4480, 4492, 4504, 4516,
3523
     4528, 4536, 4544, 4552, 4560, 4572, 4584, 4592, 4600, 4608, 4616, 4624,
3524
     4632, 4640, 4648, 4656, 4664, 4672, 4680, 4688, 4696, 4704, 4712, 4724,
3525
     4736, 4744, 4752, 4760, 4768, 4776, 4784, 4792, 4800, 4812, 4824, 4832,
3526
     4840, 4848, 4856, 4864, 4872, 4880, 4888, 4896, 4904, 4912, 4920, 4928,
3527
     4936, 4944, 4952, 4960, 4968, 4980, 4992, 5004, 5016, 5028, 5040, 5052,
3528
     5064, 5072, 5080, 5088, 5096, 5104, 5112, 5120, 5128, 5140, 5152, 5160,
3529
     5168, 5176, 5184, 5192, 5200, 5212, 5224, 5236, 5248, 5260, 5272, 5280,
3530
     5288, 5296, 5304, 5312, 5320, 5328, 5336, 5344, 5352, 5360, 5368, 5376,
3531
     5384, 5396, 5408, 5420, 5432, 5440, 5448, 5456, 5464, 5472, 5480, 5488,
3532
     5496, 5504, 5512, 5520, 5528, 5536, 5544, 5552, 5560, 5568, 5576, 5584,
3533
     5592, 5600, 5608, 5616, 5624, 5632, 5640, 5648, 5656, 5664, 5673, 5682,
3534
     5688, 5688, 5688, 5688, 5688, 5696, 5704, 5712, 5720, 5732, 5744, 5756,
3535
     5768, 5780, 5792, 5804, 5816, 5828, 5840, 5852, 5864, 5876, 5888, 5900,
3536
     5912, 5924, 5936, 5948, 5960, 5968, 5976, 5984, 5992, 6000, 6008, 6020,
3537
     6032, 6044, 6056, 6068, 6080, 6092, 6104, 6116, 6128, 6136, 6144, 6152,
3538
     6160, 6168, 6176, 6184, 6192, 6204, 6216, 6228, 6240, 6252, 6264, 6276,
3539
     6288, 6300, 6312, 6324, 6336, 6348, 6360, 6372, 6384, 6396, 6408, 6420,
3540
     6432, 6440, 6448, 6456, 6464, 6476, 6488, 6500, 6512, 6524, 6536, 6548,
3541
     6560, 6572, 6584, 6592, 6600, 6608, 6616, 6624, 6632, 6640, 6648, 6648,
3542
     6648, 6648, 6648, 6648, 6648},
3543
    {6648, 6656, 6664, 6676, 6688, 6700, 6712, 6724, 6736, 6744, 6752, 6764,
3544
     6776, 6788, 6800, 6812, 6824, 6832, 6840, 6852, 6864, 6876, 6888, 6888,
3545
     6888, 6896, 6904, 6916, 6928, 6940, 6952, 6952, 6952, 6960, 6968, 6980,
3546
     6992, 7004, 7016, 7028, 7040, 7048, 7056, 7068, 7080, 7092, 7104, 7116,
3547
     7128, 7136, 7144, 7156, 7168, 7180, 7192, 7204, 7216, 7224, 7232, 7244,
3548
     7256, 7268, 7280, 7292, 7304, 7312, 7320, 7332, 7344, 7356, 7368, 7368,
3549
     7368, 7376, 7384, 7396, 7408, 7420, 7432, 7432, 7432, 7440, 7448, 7460,
3550
     7472, 7484, 7496, 7508, 7520, 7520, 7528, 7528, 7540, 7540, 7552, 7552,
3551
     7564, 7572, 7580, 7592, 7604, 7616, 7628, 7640, 7652, 7660, 7668, 7680,
3552
     7692, 7704, 7716, 7728, 7740, 7748, 7756, 7764, 7772, 7780, 7788, 7796,
3553
     7804, 7812, 7820, 7828, 7836, 7844, 7852, 7852, 7852, 7864, 7876, 7892,
3554
     7908, 7924, 7940, 7956, 7972, 7984, 7996, 8012, 8028, 8044, 8060, 8076,
3555
     8092, 8104, 8116, 8132, 8148, 8164, 8180, 8196, 8212, 8224, 8236, 8252,
3556
     8268, 8284, 8300, 8316, 8332, 8344, 8356, 8372, 8388, 8404, 8420, 8436,
3557
     8452, 8464, 8476, 8492, 8508, 8524, 8540, 8556, 8572, 8580, 8588, 8600,
3558
     8608, 8620, 8620, 8628, 8640, 8648, 8656, 8664, 8672, 8681, 8688, 8693,
3559
     8701, 8710, 8716, 8728, 8736, 8748, 8748, 8756, 8768, 8776, 8784, 8792,
3560
     8800, 8810, 8818, 8826, 8832, 8840, 8848, 8860, 8872, 8872, 8872, 8880,
3561
     8892, 8900, 8908, 8916, 8924, 8926, 8934, 8942, 8948, 8956, 8964, 8976,
3562
     8988, 8996, 9004, 9012, 9024, 9032, 9040, 9048, 9056, 9066, 9074, 9080,
3563
     9084, 9084, 9084, 9096, 9104, 9116, 9116, 9124, 9136, 9144, 9152, 9160,
3564
     9168, 9178, 9181, 9188, 9190},
3565
    {9190, 9194, 9197, 9201, 9205, 9209, 9213, 9217, 9221, 9225, 9229, 9232,
3566
     9232, 9232, 9232, 9232, 9232, 9233, 9236, 9236, 9236, 9236, 9236, 9237,
3567
     9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244,
3568
     9245, 9249, 9257, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9269,
3569
     9272, 9272, 9272, 9273, 9281, 9292, 9293, 9301, 9312, 9312, 9312, 9312,
3570
     9313, 9320, 9321, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9329,
3571
     9337, 9345, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352,
3572
     9352, 9352, 9352, 9353, 9368, 9368, 9368, 9368, 9368, 9368, 9368, 9369,
3573
     9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372,
3574
     9372, 9372, 9372, 9372, 9373, 9377, 9380, 9380, 9381, 9385, 9389, 9393,
3575
     9397, 9401, 9405, 9409, 9413, 9417, 9421, 9425, 9429, 9433, 9437, 9441,
3576
     9445, 9449, 9453, 9457, 9461, 9465, 9469, 9473, 9477, 9481, 9485, 9488,
3577
     9489, 9493, 9497, 9501, 9505, 9509, 9513, 9517, 9521, 9525, 9529, 9533,
3578
     9537, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540,
3579
     9541, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3580
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3581
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3582
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3583
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3584
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3585
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3586
     9548, 9548, 9548, 9548, 9549},
3587
    {9549,  9561,  9573,  9577,  9584,  9585,  9597,  9609,  9612,  9613,
3588
     9621,  9625,  9629,  9633,  9637,  9641,  9645,  9649,  9653,  9657,
3589
     9660,  9661,  9665,  9672,  9672,  9673,  9677,  9681,  9685,  9689,
3590
     9692,  9692,  9693,  9701,  9713,  9720,  9721,  9724,  9724,  9728,
3591
     9729,  9732,  9732,  9736,  9745,  9749,  9752,  9753,  9757,  9761,
3592
     9764,  9765,  9769,  9773,  9777,  9781,  9785,  9789,  9792,  9793,
3593
     9805,  9809,  9813,  9817,  9821,  9824,  9824,  9824,  9824,  9825,
3594
     9829,  9833,  9837,  9841,  9844,  9844,  9844,  9844,  9844,  9844,
3595
     9845,  9857,  9869,  9885,  9897,  9909,  9921,  9933,  9945,  9957,
3596
     9969,  9981,  9993,  10005, 10017, 10029, 10037, 10041, 10049, 10061,
3597
     10069, 10073, 10081, 10093, 10109, 10117, 10121, 10129, 10141, 10145,
3598
     10149, 10153, 10157, 10161, 10169, 10181, 10189, 10193, 10201, 10213,
3599
     10229, 10237, 10241, 10249, 10261, 10265, 10269, 10273, 10276, 10276,
3600
     10276, 10276, 10276, 10276, 10276, 10276, 10276, 10277, 10288, 10288,
3601
     10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288,
3602
     10288, 10288, 10288, 10288, 10288, 10296, 10304, 10304, 10304, 10304,
3603
     10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304,
3604
     10304, 10304, 10304, 10304, 10304, 10312, 10312, 10312, 10312, 10312,
3605
     10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3606
     10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3607
     10312, 10312, 10312, 10312, 10312, 10312, 10320, 10328, 10336, 10336,
3608
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3609
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3610
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3611
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3612
     10336, 10336, 10336, 10336, 10336, 10336, 10336},
3613
    {10336, 10336, 10336, 10336, 10336, 10344, 10344, 10344, 10344, 10344,
3614
     10352, 10352, 10352, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3615
     10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3616
     10360, 10360, 10360, 10360, 10360, 10360, 10360, 10368, 10368, 10376,
3617
     10376, 10376, 10376, 10376, 10377, 10385, 10396, 10397, 10405, 10416,
3618
     10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416,
3619
     10416, 10416, 10416, 10416, 10416, 10416, 10424, 10424, 10424, 10432,
3620
     10432, 10432, 10440, 10440, 10448, 10448, 10448, 10448, 10448, 10448,
3621
     10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448,
3622
     10448, 10448, 10448, 10448, 10448, 10448, 10448, 10456, 10456, 10464,
3623
     10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464,
3624
     10472, 10480, 10488, 10496, 10504, 10504, 10504, 10512, 10520, 10520,
3625
     10520, 10528, 10536, 10536, 10536, 10536, 10536, 10536, 10536, 10544,
3626
     10552, 10552, 10552, 10560, 10568, 10568, 10568, 10576, 10584, 10584,
3627
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3628
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3629
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3630
     10584, 10584, 10584, 10592, 10600, 10608, 10616, 10616, 10616, 10616,
3631
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3632
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3633
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3634
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3635
     10616, 10616, 10616, 10616, 10616, 10624, 10632, 10640, 10648, 10648,
3636
     10648, 10648, 10648, 10648, 10648, 10656, 10664, 10672, 10680, 10680,
3637
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3638
     10680, 10680, 10680, 10680, 10680, 10680, 10680},
3639
    {10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3640
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3641
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3642
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3643
     10680, 10680, 10684, 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, 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, 10688, 10688, 10688, 10688,
3660
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3661
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3662
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3663
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3664
     10688, 10688, 10688, 10688, 10688, 10688, 10688},
3665
    {10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3666
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3667
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3668
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3669
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3670
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3671
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3672
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3673
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3674
     10688, 10688, 10688, 10688, 10688, 10688, 10689, 10693, 10697, 10701,
3675
     10705, 10709, 10713, 10717, 10721, 10725, 10733, 10741, 10749, 10757,
3676
     10765, 10773, 10781, 10789, 10797, 10805, 10813, 10825, 10837, 10849,
3677
     10861, 10873, 10885, 10897, 10909, 10921, 10937, 10953, 10969, 10985,
3678
     11001, 11017, 11033, 11049, 11065, 11081, 11097, 11105, 11113, 11121,
3679
     11129, 11137, 11145, 11153, 11161, 11169, 11181, 11193, 11205, 11217,
3680
     11229, 11241, 11253, 11265, 11277, 11289, 11301, 11313, 11325, 11337,
3681
     11349, 11361, 11373, 11385, 11397, 11409, 11421, 11433, 11445, 11457,
3682
     11469, 11481, 11493, 11505, 11517, 11529, 11541, 11553, 11565, 11577,
3683
     11589, 11601, 11613, 11617, 11621, 11625, 11629, 11633, 11637, 11641,
3684
     11645, 11649, 11653, 11657, 11661, 11665, 11669, 11673, 11677, 11681,
3685
     11685, 11689, 11693, 11697, 11701, 11705, 11709, 11713, 11717, 11721,
3686
     11725, 11729, 11733, 11737, 11741, 11745, 11749, 11753, 11757, 11761,
3687
     11765, 11769, 11773, 11777, 11781, 11785, 11789, 11793, 11797, 11801,
3688
     11805, 11809, 11813, 11817, 11821, 11824, 11824, 11824, 11824, 11824,
3689
     11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3690
     11824, 11824, 11824, 11824, 11824, 11824, 11824},
3691
    {11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3692
     11824, 11824, 11825, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3693
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3694
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3695
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3696
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3697
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3698
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3699
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3700
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3701
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3702
     11840, 11840, 11840, 11840, 11840, 11840, 11841, 11853, 11861, 11872,
3703
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3704
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3705
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3706
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3707
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3708
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3709
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3710
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3711
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3712
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3713
     11872, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3714
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3715
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3716
     11880, 11880, 11880, 11880, 11880, 11880, 11880},
3717
    {11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3718
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3719
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3720
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3721
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3722
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3723
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3724
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3725
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3726
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3727
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3728
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3729
     11880, 11880, 11880, 11880, 11881, 11885, 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, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3740
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3741
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3742
     11888, 11888, 11888, 11888, 11888, 11888, 11888},
3743
    {11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3744
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3745
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3746
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3747
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3748
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3749
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3750
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3751
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3752
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3753
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3754
     11888, 11889, 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},
3769
    {11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3770
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3771
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3772
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3773
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3774
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3775
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3776
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3777
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3778
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3779
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3780
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3781
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3782
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3783
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3784
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11893,
3785
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3786
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3787
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3788
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3789
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3790
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3791
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3792
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3793
     11896, 11896, 11896, 11897, 11900, 11900, 11900, 11900, 11900, 11900,
3794
     11900, 11900, 11900, 11900, 11900, 11900, 11901},
3795
    {11901, 11905, 11909, 11913, 11917, 11921, 11925, 11929, 11933, 11937,
3796
     11941, 11945, 11949, 11953, 11957, 11961, 11965, 11969, 11973, 11977,
3797
     11981, 11985, 11989, 11993, 11997, 12001, 12005, 12009, 12013, 12017,
3798
     12021, 12025, 12029, 12033, 12037, 12041, 12045, 12049, 12053, 12057,
3799
     12061, 12065, 12069, 12073, 12077, 12081, 12085, 12089, 12093, 12097,
3800
     12101, 12105, 12109, 12113, 12117, 12121, 12125, 12129, 12133, 12137,
3801
     12141, 12145, 12149, 12153, 12157, 12161, 12165, 12169, 12173, 12177,
3802
     12181, 12185, 12189, 12193, 12197, 12201, 12205, 12209, 12213, 12217,
3803
     12221, 12225, 12229, 12233, 12237, 12241, 12245, 12249, 12253, 12257,
3804
     12261, 12265, 12269, 12273, 12277, 12281, 12285, 12289, 12293, 12297,
3805
     12301, 12305, 12309, 12313, 12317, 12321, 12325, 12329, 12333, 12337,
3806
     12341, 12345, 12349, 12353, 12357, 12361, 12365, 12369, 12373, 12377,
3807
     12381, 12385, 12389, 12393, 12397, 12401, 12405, 12409, 12413, 12417,
3808
     12421, 12425, 12429, 12433, 12437, 12441, 12445, 12449, 12453, 12457,
3809
     12461, 12465, 12469, 12473, 12477, 12481, 12485, 12489, 12493, 12497,
3810
     12501, 12505, 12509, 12513, 12517, 12521, 12525, 12529, 12533, 12537,
3811
     12541, 12545, 12549, 12553, 12557, 12561, 12565, 12569, 12573, 12577,
3812
     12581, 12585, 12589, 12593, 12597, 12601, 12605, 12609, 12613, 12617,
3813
     12621, 12625, 12629, 12633, 12637, 12641, 12645, 12649, 12653, 12657,
3814
     12661, 12665, 12669, 12673, 12677, 12681, 12685, 12689, 12693, 12697,
3815
     12701, 12705, 12709, 12713, 12717, 12721, 12725, 12729, 12733, 12737,
3816
     12741, 12745, 12749, 12753, 12756, 12756, 12756, 12756, 12756, 12756,
3817
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3818
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3819
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3820
     12756, 12756, 12756, 12756, 12756, 12756, 12757},
3821
    {12757, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3822
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3823
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3824
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3825
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3826
     12760, 12760, 12760, 12760, 12761, 12764, 12765, 12769, 12773, 12776,
3827
     12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776,
3828
     12776, 12776, 12776, 12776, 12776, 12776, 12776, 12784, 12784, 12792,
3829
     12792, 12800, 12800, 12808, 12808, 12816, 12816, 12824, 12824, 12832,
3830
     12832, 12840, 12840, 12848, 12848, 12856, 12856, 12864, 12864, 12872,
3831
     12872, 12872, 12880, 12880, 12888, 12888, 12896, 12896, 12896, 12896,
3832
     12896, 12896, 12896, 12904, 12912, 12912, 12920, 12928, 12928, 12936,
3833
     12944, 12944, 12952, 12960, 12960, 12968, 12976, 12976, 12976, 12976,
3834
     12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976,
3835
     12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12984,
3836
     12984, 12984, 12984, 12984, 12984, 12985, 12993, 13000, 13000, 13009,
3837
     13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016,
3838
     13016, 13016, 13016, 13024, 13024, 13032, 13032, 13040, 13040, 13048,
3839
     13048, 13056, 13056, 13064, 13064, 13072, 13072, 13080, 13080, 13088,
3840
     13088, 13096, 13096, 13104, 13104, 13112, 13112, 13112, 13120, 13120,
3841
     13128, 13128, 13136, 13136, 13136, 13136, 13136, 13136, 13136, 13144,
3842
     13152, 13152, 13160, 13168, 13168, 13176, 13184, 13184, 13192, 13200,
3843
     13200, 13208, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3844
     13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3845
     13216, 13216, 13216, 13216, 13216, 13224, 13224, 13224, 13232, 13240,
3846
     13248, 13256, 13256, 13256, 13256, 13265, 13272},
3847
    {13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3848
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3849
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3850
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3851
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13273,
3852
     13277, 13281, 13285, 13289, 13293, 13297, 13301, 13305, 13309, 13313,
3853
     13317, 13321, 13325, 13329, 13333, 13337, 13341, 13345, 13349, 13353,
3854
     13357, 13361, 13365, 13369, 13373, 13377, 13381, 13385, 13389, 13393,
3855
     13397, 13401, 13405, 13409, 13413, 13417, 13421, 13425, 13429, 13433,
3856
     13437, 13441, 13445, 13449, 13453, 13457, 13461, 13465, 13469, 13473,
3857
     13477, 13481, 13485, 13489, 13493, 13497, 13501, 13505, 13509, 13513,
3858
     13517, 13521, 13525, 13529, 13533, 13537, 13541, 13545, 13549, 13553,
3859
     13557, 13561, 13565, 13569, 13573, 13577, 13581, 13585, 13589, 13593,
3860
     13597, 13601, 13605, 13609, 13613, 13617, 13621, 13625, 13629, 13633,
3861
     13637, 13641, 13645, 13648, 13648, 13648, 13649, 13653, 13657, 13661,
3862
     13665, 13669, 13673, 13677, 13681, 13685, 13689, 13693, 13697, 13701,
3863
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3864
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3865
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3866
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3867
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3868
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3869
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3870
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3871
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3872
     13704, 13704, 13704, 13704, 13704, 13704, 13705},
3873
    {13705, 13717, 13729, 13741, 13753, 13765, 13777, 13789, 13801, 13813,
3874
     13825, 13837, 13849, 13861, 13873, 13889, 13905, 13921, 13937, 13953,
3875
     13969, 13985, 14001, 14017, 14033, 14049, 14065, 14081, 14097, 14113,
3876
     14141, 14164, 14165, 14177, 14189, 14201, 14213, 14225, 14237, 14249,
3877
     14261, 14273, 14285, 14297, 14309, 14321, 14333, 14345, 14357, 14369,
3878
     14381, 14393, 14405, 14417, 14429, 14441, 14453, 14465, 14477, 14489,
3879
     14501, 14513, 14525, 14537, 14549, 14561, 14573, 14585, 14597, 14601,
3880
     14605, 14609, 14612, 14612, 14612, 14612, 14612, 14612, 14612, 14612,
3881
     14613, 14625, 14633, 14641, 14649, 14657, 14665, 14673, 14681, 14689,
3882
     14697, 14705, 14713, 14721, 14729, 14737, 14745, 14749, 14753, 14757,
3883
     14761, 14765, 14769, 14773, 14777, 14781, 14785, 14789, 14793, 14797,
3884
     14801, 14809, 14817, 14825, 14833, 14841, 14849, 14857, 14865, 14873,
3885
     14881, 14889, 14897, 14905, 14913, 14933, 14949, 14956, 14957, 14961,
3886
     14965, 14969, 14973, 14977, 14981, 14985, 14989, 14993, 14997, 15001,
3887
     15005, 15009, 15013, 15017, 15021, 15025, 15029, 15033, 15037, 15041,
3888
     15045, 15049, 15053, 15057, 15061, 15065, 15069, 15073, 15077, 15081,
3889
     15085, 15089, 15093, 15097, 15101, 15105, 15109, 15113, 15117, 15121,
3890
     15125, 15129, 15133, 15137, 15141, 15145, 15149, 15153, 15161, 15169,
3891
     15177, 15185, 15193, 15201, 15209, 15217, 15225, 15233, 15241, 15249,
3892
     15257, 15265, 15273, 15281, 15289, 15297, 15305, 15313, 15321, 15329,
3893
     15337, 15345, 15357, 15369, 15381, 15389, 15401, 15409, 15421, 15425,
3894
     15429, 15433, 15437, 15441, 15445, 15449, 15453, 15457, 15461, 15465,
3895
     15469, 15473, 15477, 15481, 15485, 15489, 15493, 15497, 15501, 15505,
3896
     15509, 15513, 15517, 15521, 15525, 15529, 15533, 15537, 15541, 15545,
3897
     15549, 15553, 15557, 15561, 15565, 15569, 15573, 15577, 15581, 15585,
3898
     15589, 15593, 15597, 15601, 15605, 15609, 15617},
3899
    {15617, 15637, 15653, 15673, 15685, 15705, 15717, 15729, 15753, 15769,
3900
     15781, 15793, 15805, 15821, 15837, 15853, 15869, 15885, 15901, 15917,
3901
     15941, 15949, 15973, 15997, 16017, 16033, 16057, 16081, 16097, 16109,
3902
     16121, 16137, 16153, 16173, 16193, 16205, 16217, 16233, 16245, 16257,
3903
     16265, 16273, 16285, 16297, 16321, 16337, 16357, 16381, 16397, 16409,
3904
     16421, 16445, 16461, 16485, 16497, 16517, 16529, 16545, 16557, 16573,
3905
     16593, 16609, 16629, 16645, 16653, 16673, 16685, 16697, 16713, 16725,
3906
     16737, 16749, 16769, 16785, 16793, 16817, 16829, 16849, 16865, 16881,
3907
     16893, 16905, 16921, 16929, 16945, 16965, 16973, 16997, 17009, 17017,
3908
     17025, 17033, 17041, 17049, 17057, 17065, 17073, 17081, 17089, 17101,
3909
     17113, 17125, 17137, 17149, 17161, 17173, 17185, 17197, 17209, 17221,
3910
     17233, 17245, 17257, 17269, 17281, 17289, 17297, 17309, 17317, 17325,
3911
     17333, 17345, 17357, 17365, 17373, 17381, 17389, 17397, 17413, 17421,
3912
     17429, 17437, 17445, 17453, 17461, 17469, 17477, 17489, 17505, 17513,
3913
     17521, 17529, 17537, 17545, 17553, 17561, 17573, 17585, 17597, 17609,
3914
     17617, 17625, 17633, 17641, 17649, 17657, 17665, 17673, 17681, 17689,
3915
     17701, 17713, 17721, 17733, 17745, 17757, 17765, 17777, 17789, 17805,
3916
     17813, 17825, 17837, 17849, 17861, 17881, 17905, 17913, 17921, 17929,
3917
     17937, 17945, 17953, 17961, 17969, 17977, 17985, 17993, 18001, 18009,
3918
     18017, 18025, 18033, 18041, 18049, 18065, 18073, 18081, 18089, 18105,
3919
     18117, 18125, 18133, 18141, 18149, 18157, 18165, 18173, 18181, 18189,
3920
     18197, 18209, 18217, 18225, 18237, 18249, 18257, 18273, 18285, 18293,
3921
     18301, 18309, 18317, 18329, 18341, 18349, 18357, 18365, 18373, 18381,
3922
     18389, 18397, 18405, 18413, 18425, 18437, 18449, 18461, 18473, 18485,
3923
     18497, 18509, 18521, 18533, 18545, 18557, 18569, 18581, 18593, 18605,
3924
     18617, 18629, 18641, 18653, 18665, 18677, 18688},
3925
    {18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3926
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3927
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3928
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3929
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3930
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3931
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3932
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3933
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3934
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3935
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3936
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3937
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3938
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3939
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3940
     18688, 18688, 18688, 18688, 18688, 18688, 18689, 18693, 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, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3948
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3949
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3950
     18696, 18696, 18696, 18696, 18696, 18696, 18696},
3951
    {18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3952
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3953
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3954
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3955
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3956
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3957
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3958
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3959
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3960
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3961
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3962
     18696, 18696, 18697, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3963
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3964
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3965
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3966
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3967
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3968
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3969
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3970
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3971
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3972
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3973
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3974
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3975
     18700, 18700, 18701, 18705, 18709, 18712, 18712, 18712, 18713, 18717,
3976
     18720, 18720, 18720, 18720, 18720, 18720, 18720},
3977
    {18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3978
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3979
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3980
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3981
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3982
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3983
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3984
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3985
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3986
     18720, 18720, 18721, 18725, 18729, 18733, 18736, 18736, 18736, 18736,
3987
     18736, 18736, 18736, 18736, 18736, 18737, 18740, 18740, 18740, 18740,
3988
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3989
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3990
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3991
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3992
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3993
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3994
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3995
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3996
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3997
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3998
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3999
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4000
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4001
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4002
     18740, 18740, 18740, 18740, 18740, 18740, 18740},
4003
    {18740, 18744, 18748, 18752, 18756, 18760, 18764, 18768, 18772, 18776,
4004
     18780, 18784, 18788, 18792, 18796, 18800, 18804, 18808, 18812, 18816,
4005
     18820, 18824, 18828, 18832, 18836, 18840, 18844, 18848, 18852, 18856,
4006
     18860, 18864, 18868, 18872, 18876, 18880, 18884, 18888, 18892, 18896,
4007
     18900, 18904, 18908, 18912, 18916, 18920, 18924, 18928, 18932, 18936,
4008
     18940, 18944, 18948, 18952, 18956, 18960, 18964, 18968, 18972, 18976,
4009
     18980, 18984, 18988, 18992, 18996, 19000, 19004, 19008, 19012, 19016,
4010
     19020, 19024, 19028, 19032, 19036, 19040, 19044, 19048, 19052, 19056,
4011
     19060, 19064, 19068, 19072, 19076, 19080, 19084, 19088, 19092, 19096,
4012
     19100, 19104, 19108, 19112, 19116, 19120, 19124, 19128, 19132, 19136,
4013
     19140, 19144, 19148, 19152, 19156, 19160, 19164, 19168, 19172, 19176,
4014
     19180, 19184, 19188, 19192, 19196, 19200, 19204, 19208, 19212, 19216,
4015
     19220, 19224, 19228, 19232, 19236, 19240, 19244, 19248, 19252, 19256,
4016
     19260, 19264, 19268, 19272, 19276, 19280, 19284, 19288, 19292, 19296,
4017
     19300, 19304, 19308, 19312, 19316, 19320, 19324, 19328, 19332, 19336,
4018
     19340, 19344, 19348, 19352, 19356, 19360, 19364, 19368, 19372, 19376,
4019
     19380, 19384, 19388, 19392, 19396, 19400, 19404, 19408, 19412, 19416,
4020
     19420, 19424, 19428, 19432, 19436, 19440, 19444, 19448, 19452, 19456,
4021
     19460, 19464, 19468, 19472, 19476, 19480, 19484, 19488, 19492, 19496,
4022
     19500, 19504, 19508, 19512, 19516, 19520, 19524, 19528, 19532, 19536,
4023
     19540, 19544, 19548, 19552, 19556, 19560, 19564, 19568, 19572, 19576,
4024
     19580, 19584, 19588, 19592, 19596, 19600, 19604, 19608, 19612, 19616,
4025
     19620, 19624, 19628, 19632, 19636, 19640, 19644, 19648, 19652, 19656,
4026
     19660, 19664, 19668, 19672, 19676, 19680, 19684, 19688, 19692, 19696,
4027
     19700, 19704, 19708, 19712, 19716, 19720, 19724, 19728, 19732, 19736,
4028
     19740, 19744, 19748, 19752, 19756, 19760, 19764},
4029
    {19764, 19768, 19772, 19776, 19780, 19784, 19788, 19792, 19796, 19800,
4030
     19804, 19808, 19812, 19816, 19820, 19820, 19820, 19824, 19824, 19828,
4031
     19828, 19828, 19832, 19836, 19840, 19844, 19848, 19852, 19856, 19860,
4032
     19864, 19868, 19868, 19872, 19872, 19876, 19876, 19876, 19880, 19884,
4033
     19884, 19884, 19884, 19888, 19892, 19896, 19900, 19904, 19908, 19912,
4034
     19916, 19920, 19924, 19928, 19932, 19936, 19940, 19944, 19948, 19952,
4035
     19956, 19960, 19964, 19968, 19972, 19976, 19980, 19984, 19988, 19992,
4036
     19996, 20000, 20004, 20008, 20012, 20016, 20020, 20024, 20028, 20032,
4037
     20036, 20040, 20044, 20048, 20052, 20056, 20060, 20064, 20068, 20072,
4038
     20076, 20080, 20084, 20088, 20092, 20096, 20100, 20104, 20108, 20112,
4039
     20116, 20120, 20124, 20128, 20132, 20136, 20140, 20144, 20148, 20152,
4040
     20156, 20156, 20156, 20160, 20164, 20168, 20172, 20176, 20180, 20184,
4041
     20188, 20192, 20196, 20200, 20204, 20208, 20212, 20216, 20220, 20224,
4042
     20228, 20232, 20236, 20240, 20244, 20248, 20252, 20256, 20260, 20264,
4043
     20268, 20272, 20276, 20280, 20284, 20288, 20292, 20296, 20300, 20304,
4044
     20308, 20312, 20316, 20320, 20324, 20328, 20332, 20336, 20340, 20344,
4045
     20348, 20352, 20356, 20360, 20364, 20368, 20372, 20376, 20380, 20384,
4046
     20388, 20392, 20396, 20400, 20404, 20408, 20412, 20416, 20420, 20424,
4047
     20428, 20432, 20436, 20440, 20444, 20448, 20452, 20456, 20460, 20464,
4048
     20468, 20472, 20476, 20480, 20484, 20488, 20492, 20496, 20500, 20504,
4049
     20508, 20512, 20516, 20520, 20524, 20528, 20532, 20536, 20540, 20544,
4050
     20548, 20552, 20556, 20560, 20564, 20568, 20572, 20576, 20580, 20580,
4051
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4052
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4053
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4054
     20580, 20580, 20580, 20580, 20580, 20580, 20581},
4055
    {20581, 20589, 20597, 20605, 20617, 20629, 20637, 20644, 20644, 20644,
4056
     20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20645,
4057
     20653, 20661, 20669, 20677, 20684, 20684, 20684, 20684, 20684, 20684,
4058
     20692, 20692, 20701, 20705, 20709, 20713, 20717, 20721, 20725, 20729,
4059
     20733, 20737, 20740, 20748, 20756, 20768, 20780, 20788, 20796, 20804,
4060
     20812, 20820, 20828, 20836, 20844, 20852, 20852, 20860, 20868, 20876,
4061
     20884, 20892, 20892, 20900, 20900, 20908, 20916, 20916, 20924, 20932,
4062
     20932, 20940, 20948, 20956, 20964, 20972, 20980, 20988, 20996, 21005,
4063
     21013, 21017, 21021, 21025, 21029, 21033, 21037, 21041, 21045, 21049,
4064
     21053, 21057, 21061, 21065, 21069, 21073, 21077, 21081, 21085, 21089,
4065
     21093, 21097, 21101, 21105, 21109, 21113, 21117, 21121, 21125, 21129,
4066
     21133, 21137, 21141, 21145, 21149, 21153, 21157, 21161, 21165, 21169,
4067
     21173, 21177, 21181, 21185, 21189, 21193, 21197, 21201, 21205, 21209,
4068
     21213, 21217, 21221, 21225, 21229, 21233, 21237, 21241, 21245, 21249,
4069
     21253, 21257, 21261, 21265, 21269, 21273, 21277, 21281, 21285, 21289,
4070
     21293, 21297, 21301, 21305, 21309, 21313, 21317, 21321, 21325, 21329,
4071
     21333, 21337, 21341, 21345, 21349, 21357, 21365, 21369, 21373, 21377,
4072
     21381, 21385, 21389, 21393, 21397, 21401, 21405, 21413, 21420, 21420,
4073
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4074
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4075
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4076
     21420, 21421, 21425, 21429, 21433, 21437, 21441, 21445, 21449, 21453,
4077
     21457, 21461, 21469, 21473, 21477, 21481, 21485, 21489, 21493, 21497,
4078
     21501, 21505, 21509, 21513, 21517, 21529, 21541, 21553, 21565, 21577,
4079
     21589, 21601, 21613, 21625, 21637, 21649, 21661, 21673, 21685, 21697,
4080
     21709, 21721, 21733, 21737, 21741, 21745, 21749},
4081
    {21749, 21761, 21773, 21785, 21797, 21809, 21817, 21825, 21833, 21841,
4082
     21849, 21857, 21865, 21873, 21881, 21889, 21897, 21905, 21913, 21921,
4083
     21929, 21937, 21945, 21953, 21961, 21969, 21977, 21985, 21993, 22001,
4084
     22009, 22017, 22025, 22033, 22041, 22049, 22057, 22065, 22073, 22081,
4085
     22089, 22097, 22105, 22113, 22121, 22129, 22137, 22145, 22153, 22161,
4086
     22169, 22177, 22185, 22193, 22201, 22209, 22217, 22225, 22233, 22241,
4087
     22249, 22257, 22265, 22273, 22281, 22289, 22297, 22305, 22313, 22321,
4088
     22329, 22337, 22345, 22353, 22361, 22369, 22377, 22385, 22393, 22401,
4089
     22409, 22417, 22425, 22433, 22441, 22449, 22457, 22465, 22473, 22481,
4090
     22489, 22497, 22505, 22513, 22521, 22533, 22545, 22557, 22569, 22581,
4091
     22593, 22605, 22617, 22629, 22641, 22653, 22665, 22673, 22681, 22689,
4092
     22697, 22705, 22713, 22721, 22729, 22737, 22745, 22753, 22761, 22769,
4093
     22777, 22785, 22793, 22801, 22809, 22817, 22825, 22833, 22841, 22849,
4094
     22857, 22865, 22873, 22881, 22889, 22897, 22905, 22913, 22921, 22929,
4095
     22937, 22945, 22953, 22961, 22969, 22977, 22985, 22993, 23001, 23009,
4096
     23017, 23025, 23037, 23049, 23061, 23073, 23085, 23093, 23101, 23109,
4097
     23117, 23125, 23133, 23141, 23149, 23157, 23165, 23173, 23181, 23189,
4098
     23197, 23205, 23213, 23221, 23229, 23237, 23245, 23253, 23261, 23269,
4099
     23277, 23285, 23293, 23301, 23309, 23317, 23325, 23333, 23341, 23349,
4100
     23357, 23365, 23373, 23381, 23389, 23397, 23405, 23413, 23421, 23429,
4101
     23437, 23445, 23453, 23461, 23469, 23477, 23485, 23493, 23501, 23509,
4102
     23517, 23525, 23533, 23541, 23549, 23557, 23565, 23573, 23581, 23589,
4103
     23597, 23605, 23613, 23621, 23633, 23645, 23653, 23661, 23669, 23677,
4104
     23685, 23693, 23701, 23709, 23717, 23725, 23733, 23741, 23749, 23757,
4105
     23765, 23773, 23781, 23793, 23805, 23817, 23825, 23833, 23841, 23849,
4106
     23857, 23865, 23873, 23881, 23889, 23897, 23905},
4107
    {23905, 23913, 23921, 23929, 23937, 23945, 23953, 23961, 23969, 23977,
4108
     23985, 23993, 24001, 24009, 24017, 24025, 24033, 24041, 24049, 24057,
4109
     24065, 24073, 24081, 24089, 24097, 24105, 24113, 24121, 24129, 24137,
4110
     24145, 24153, 24161, 24169, 24177, 24185, 24193, 24201, 24209, 24217,
4111
     24225, 24233, 24241, 24249, 24257, 24265, 24273, 24281, 24289, 24297,
4112
     24305, 24313, 24321, 24329, 24337, 24345, 24353, 24361, 24369, 24377,
4113
     24385, 24393, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4114
     24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4115
     24401, 24413, 24425, 24437, 24449, 24461, 24473, 24485, 24497, 24509,
4116
     24521, 24533, 24545, 24557, 24569, 24581, 24593, 24605, 24617, 24629,
4117
     24641, 24653, 24665, 24677, 24689, 24701, 24713, 24725, 24737, 24749,
4118
     24761, 24773, 24785, 24797, 24809, 24821, 24833, 24845, 24857, 24869,
4119
     24881, 24893, 24905, 24917, 24929, 24941, 24953, 24965, 24977, 24989,
4120
     25001, 25013, 25025, 25037, 25049, 25061, 25073, 25085, 25097, 25109,
4121
     25121, 25133, 25145, 25157, 25168, 25168, 25169, 25181, 25193, 25205,
4122
     25217, 25229, 25241, 25253, 25265, 25277, 25289, 25301, 25313, 25325,
4123
     25337, 25349, 25361, 25373, 25385, 25397, 25409, 25421, 25433, 25445,
4124
     25457, 25469, 25481, 25493, 25505, 25517, 25529, 25541, 25553, 25565,
4125
     25577, 25589, 25601, 25613, 25625, 25637, 25649, 25661, 25673, 25685,
4126
     25697, 25709, 25721, 25733, 25745, 25757, 25769, 25781, 25793, 25805,
4127
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4128
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4129
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4130
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4131
     25817, 25829, 25841, 25857, 25873, 25889, 25905, 25921, 25937, 25953,
4132
     25965, 26037, 26069, 26084, 26084, 26084, 26084},
4133
    {26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084,
4134
     26084, 26084, 26084, 26084, 26084, 26084, 26085, 26089, 26093, 26097,
4135
     26101, 26105, 26109, 26113, 26117, 26121, 26132, 26132, 26132, 26132,
4136
     26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132,
4137
     26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26133, 26141,
4138
     26145, 26149, 26153, 26157, 26161, 26165, 26169, 26173, 26177, 26181,
4139
     26185, 26189, 26193, 26197, 26201, 26205, 26209, 26213, 26217, 26220,
4140
     26220, 26221, 26225, 26229, 26237, 26245, 26253, 26261, 26265, 26269,
4141
     26273, 26277, 26281, 26284, 26285, 26289, 26293, 26297, 26301, 26305,
4142
     26309, 26313, 26317, 26321, 26325, 26329, 26333, 26337, 26341, 26345,
4143
     26349, 26353, 26357, 26360, 26361, 26365, 26369, 26373, 26376, 26376,
4144
     26376, 26376, 26377, 26385, 26393, 26400, 26401, 26408, 26409, 26417,
4145
     26425, 26433, 26441, 26449, 26457, 26465, 26473, 26481, 26489, 26493,
4146
     26501, 26509, 26517, 26525, 26533, 26541, 26549, 26557, 26565, 26573,
4147
     26581, 26589, 26593, 26597, 26601, 26605, 26609, 26613, 26617, 26621,
4148
     26625, 26629, 26633, 26637, 26641, 26645, 26649, 26653, 26657, 26661,
4149
     26665, 26669, 26673, 26677, 26681, 26685, 26689, 26693, 26697, 26701,
4150
     26705, 26709, 26713, 26717, 26721, 26725, 26729, 26733, 26737, 26741,
4151
     26745, 26749, 26753, 26757, 26761, 26765, 26769, 26773, 26777, 26781,
4152
     26785, 26789, 26793, 26797, 26801, 26805, 26809, 26813, 26817, 26821,
4153
     26825, 26829, 26833, 26837, 26841, 26845, 26849, 26853, 26857, 26861,
4154
     26865, 26869, 26873, 26877, 26881, 26885, 26889, 26893, 26897, 26901,
4155
     26905, 26909, 26913, 26917, 26921, 26925, 26929, 26933, 26937, 26941,
4156
     26945, 26949, 26953, 26957, 26961, 26965, 26969, 26973, 26977, 26981,
4157
     26985, 26989, 26993, 26997, 27001, 27005, 27017, 27029, 27041, 27053,
4158
     27065, 27077, 27085, 27092, 27092, 27092, 27092},
4159
    {27092, 27093, 27097, 27101, 27105, 27109, 27113, 27117, 27121, 27125,
4160
     27129, 27133, 27137, 27141, 27145, 27149, 27153, 27157, 27161, 27165,
4161
     27169, 27173, 27177, 27181, 27185, 27189, 27193, 27197, 27201, 27205,
4162
     27209, 27213, 27217, 27221, 27225, 27229, 27233, 27237, 27241, 27245,
4163
     27249, 27253, 27257, 27261, 27265, 27269, 27273, 27277, 27281, 27285,
4164
     27289, 27293, 27297, 27301, 27305, 27309, 27313, 27317, 27321, 27325,
4165
     27329, 27333, 27337, 27341, 27345, 27349, 27353, 27357, 27361, 27365,
4166
     27369, 27373, 27377, 27381, 27385, 27389, 27393, 27397, 27401, 27405,
4167
     27409, 27413, 27417, 27421, 27425, 27429, 27433, 27437, 27441, 27445,
4168
     27449, 27453, 27457, 27461, 27465, 27469, 27473, 27477, 27481, 27485,
4169
     27489, 27493, 27497, 27501, 27505, 27509, 27513, 27517, 27521, 27525,
4170
     27529, 27533, 27537, 27541, 27545, 27549, 27553, 27557, 27561, 27565,
4171
     27569, 27573, 27577, 27581, 27585, 27589, 27593, 27597, 27601, 27605,
4172
     27609, 27613, 27617, 27621, 27625, 27629, 27633, 27637, 27641, 27645,
4173
     27649, 27653, 27657, 27661, 27665, 27669, 27673, 27677, 27681, 27685,
4174
     27689, 27693, 27697, 27701, 27705, 27709, 27713, 27717, 27721, 27725,
4175
     27729, 27733, 27737, 27741, 27745, 27749, 27753, 27757, 27761, 27765,
4176
     27769, 27773, 27777, 27781, 27785, 27789, 27793, 27797, 27801, 27805,
4177
     27809, 27813, 27817, 27821, 27825, 27829, 27833, 27837, 27841, 27845,
4178
     27849, 27852, 27852, 27852, 27853, 27857, 27861, 27865, 27869, 27873,
4179
     27876, 27876, 27877, 27881, 27885, 27889, 27893, 27897, 27900, 27900,
4180
     27901, 27905, 27909, 27913, 27917, 27921, 27924, 27924, 27925, 27929,
4181
     27933, 27936, 27936, 27936, 27937, 27941, 27945, 27949, 27957, 27961,
4182
     27965, 27968, 27969, 27973, 27977, 27981, 27985, 27989, 27993, 27996,
4183
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4184
     27996, 27996, 27996, 27996, 27996, 27996, 27996},
4185
    {27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4186
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4187
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4188
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4189
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4190
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4191
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4192
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4193
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4194
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4195
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4196
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4197
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27997,
4198
     28001, 28005, 28009, 28013, 28016, 28017, 28021, 28025, 28029, 28033,
4199
     28037, 28041, 28045, 28049, 28053, 28057, 28061, 28065, 28069, 28073,
4200
     28077, 28081, 28085, 28089, 28093, 28097, 28101, 28105, 28109, 28113,
4201
     28117, 28121, 28125, 28129, 28133, 28137, 28141, 28145, 28149, 28153,
4202
     28157, 28161, 28165, 28169, 28173, 28177, 28181, 28184, 28185, 28189,
4203
     28193, 28197, 28201, 28205, 28209, 28213, 28217, 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},
4211
    {28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4212
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4213
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4214
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4215
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4216
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4217
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4218
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4219
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4220
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4221
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4222
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4223
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4224
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4225
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4226
     28220, 28220, 28220, 28220, 28220, 28228, 28228, 28236, 28236, 28236,
4227
     28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236,
4228
     28236, 28236, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4229
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4230
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4231
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4232
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4233
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4234
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4235
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4236
     28244, 28244, 28244, 28244, 28244, 28244, 28244},
4237
    {28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4238
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4239
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4240
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4241
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28252, 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, 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, 28260, 28260, 28260, 28260,
4256
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4257
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4258
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4259
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4260
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4261
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4262
     28260, 28260, 28260, 28260, 28260, 28260, 28260},
4263
    {28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4264
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4265
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4266
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4267
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4268
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4269
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4270
     28260, 28260, 28260, 28260, 28260, 28260, 28268, 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, 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},
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, 28276, 28276,
4293
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4294
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4295
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4296
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4297
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4298
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4299
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4300
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4301
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4302
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4303
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4304
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4305
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4306
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4307
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28284, 28292,
4308
     28292, 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},
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, 28300, 28300, 28300,
4319
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4320
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4321
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4322
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4323
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4324
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4325
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4326
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4327
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4328
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4329
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4330
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4331
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4332
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4333
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28308, 28316, 28316,
4334
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4335
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4336
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4337
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4338
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4339
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4340
     28316, 28316, 28316, 28316, 28316, 28316, 28316},
4341
    {28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4342
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4343
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4344
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4345
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4346
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 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, 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, 28324, 28324, 28324, 28324, 28324,
4362
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4363
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4364
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4365
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4366
     28324, 28324, 28324, 28324, 28324, 28324, 28324},
4367
    {28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4368
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4369
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4370
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4371
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4372
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4373
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4374
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4375
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4376
     28324, 28324, 28324, 28324, 28324, 28332, 28340, 28352, 28364, 28376,
4377
     28388, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4378
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4379
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4380
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4381
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4382
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4383
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4384
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4385
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28408, 28416,
4386
     28428, 28440, 28452, 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},
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, 28464, 28464, 28464, 28464,
4404
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4405
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4406
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4407
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4408
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4409
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4410
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4411
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4412
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4413
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4414
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4415
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4416
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4417
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4418
     28464, 28464, 28464, 28464, 28464, 28464, 28465},
4419
    {28465, 28469, 28473, 28477, 28481, 28485, 28489, 28493, 28497, 28501,
4420
     28505, 28509, 28513, 28517, 28521, 28525, 28529, 28533, 28537, 28541,
4421
     28545, 28549, 28553, 28557, 28561, 28565, 28569, 28573, 28577, 28581,
4422
     28585, 28589, 28593, 28597, 28601, 28605, 28609, 28613, 28617, 28621,
4423
     28625, 28629, 28633, 28637, 28641, 28645, 28649, 28653, 28657, 28661,
4424
     28665, 28669, 28673, 28677, 28681, 28685, 28689, 28693, 28697, 28701,
4425
     28705, 28709, 28713, 28717, 28721, 28725, 28729, 28733, 28737, 28741,
4426
     28745, 28749, 28753, 28757, 28761, 28765, 28769, 28773, 28777, 28781,
4427
     28785, 28789, 28793, 28797, 28801, 28804, 28805, 28809, 28813, 28817,
4428
     28821, 28825, 28829, 28833, 28837, 28841, 28845, 28849, 28853, 28857,
4429
     28861, 28865, 28869, 28873, 28877, 28881, 28885, 28889, 28893, 28897,
4430
     28901, 28905, 28909, 28913, 28917, 28921, 28925, 28929, 28933, 28937,
4431
     28941, 28945, 28949, 28953, 28957, 28961, 28965, 28969, 28973, 28977,
4432
     28981, 28985, 28989, 28993, 28997, 29001, 29005, 29009, 29013, 29017,
4433
     29021, 29025, 29029, 29033, 29037, 29041, 29045, 29049, 29053, 29057,
4434
     29061, 29065, 29069, 29073, 29077, 29081, 29085, 29088, 29089, 29093,
4435
     29096, 29096, 29097, 29100, 29100, 29101, 29105, 29108, 29108, 29109,
4436
     29113, 29117, 29121, 29124, 29125, 29129, 29133, 29137, 29141, 29145,
4437
     29149, 29153, 29157, 29161, 29165, 29169, 29172, 29173, 29176, 29177,
4438
     29181, 29185, 29189, 29193, 29197, 29201, 29204, 29205, 29209, 29213,
4439
     29217, 29221, 29225, 29229, 29233, 29237, 29241, 29245, 29249, 29253,
4440
     29257, 29261, 29265, 29269, 29273, 29277, 29281, 29285, 29289, 29293,
4441
     29297, 29301, 29305, 29309, 29313, 29317, 29321, 29325, 29329, 29333,
4442
     29337, 29341, 29345, 29349, 29353, 29357, 29361, 29365, 29369, 29373,
4443
     29377, 29381, 29385, 29389, 29393, 29397, 29401, 29405, 29409, 29413,
4444
     29417, 29421, 29425, 29429, 29433, 29437, 29441},
4445
    {29441, 29445, 29449, 29453, 29457, 29461, 29464, 29465, 29469, 29473,
4446
     29477, 29480, 29480, 29481, 29485, 29489, 29493, 29497, 29501, 29505,
4447
     29509, 29512, 29513, 29517, 29521, 29525, 29529, 29533, 29537, 29540,
4448
     29541, 29545, 29549, 29553, 29557, 29561, 29565, 29569, 29573, 29577,
4449
     29581, 29585, 29589, 29593, 29597, 29601, 29605, 29609, 29613, 29617,
4450
     29621, 29625, 29629, 29633, 29637, 29641, 29645, 29649, 29652, 29653,
4451
     29657, 29661, 29665, 29668, 29669, 29673, 29677, 29681, 29685, 29688,
4452
     29689, 29692, 29692, 29692, 29693, 29697, 29701, 29705, 29709, 29713,
4453
     29717, 29720, 29721, 29725, 29729, 29733, 29737, 29741, 29745, 29749,
4454
     29753, 29757, 29761, 29765, 29769, 29773, 29777, 29781, 29785, 29789,
4455
     29793, 29797, 29801, 29805, 29809, 29813, 29817, 29821, 29825, 29829,
4456
     29833, 29837, 29841, 29845, 29849, 29853, 29857, 29861, 29865, 29869,
4457
     29873, 29877, 29881, 29885, 29889, 29893, 29897, 29901, 29905, 29909,
4458
     29913, 29917, 29921, 29925, 29929, 29933, 29937, 29941, 29945, 29949,
4459
     29953, 29957, 29961, 29965, 29969, 29973, 29977, 29981, 29985, 29989,
4460
     29993, 29997, 30001, 30005, 30009, 30013, 30017, 30021, 30025, 30029,
4461
     30033, 30037, 30041, 30045, 30049, 30053, 30057, 30061, 30065, 30069,
4462
     30073, 30077, 30081, 30085, 30089, 30093, 30097, 30101, 30105, 30109,
4463
     30113, 30117, 30121, 30125, 30129, 30133, 30137, 30141, 30145, 30149,
4464
     30153, 30157, 30161, 30165, 30169, 30173, 30177, 30181, 30185, 30189,
4465
     30193, 30197, 30201, 30205, 30209, 30213, 30217, 30221, 30225, 30229,
4466
     30233, 30237, 30241, 30245, 30249, 30253, 30257, 30261, 30265, 30269,
4467
     30273, 30277, 30281, 30285, 30289, 30293, 30297, 30301, 30305, 30309,
4468
     30313, 30317, 30321, 30325, 30329, 30333, 30337, 30341, 30345, 30349,
4469
     30353, 30357, 30361, 30365, 30369, 30373, 30377, 30381, 30385, 30389,
4470
     30393, 30397, 30401, 30405, 30409, 30413, 30417},
4471
    {30417, 30421, 30425, 30429, 30433, 30437, 30441, 30445, 30449, 30453,
4472
     30457, 30461, 30465, 30469, 30473, 30477, 30481, 30485, 30489, 30493,
4473
     30497, 30501, 30505, 30509, 30513, 30517, 30521, 30525, 30529, 30533,
4474
     30537, 30541, 30545, 30549, 30553, 30557, 30561, 30565, 30569, 30573,
4475
     30577, 30581, 30585, 30589, 30593, 30597, 30601, 30605, 30609, 30613,
4476
     30617, 30621, 30625, 30629, 30633, 30637, 30641, 30645, 30649, 30653,
4477
     30657, 30661, 30665, 30669, 30673, 30677, 30681, 30685, 30689, 30693,
4478
     30697, 30701, 30705, 30709, 30713, 30717, 30721, 30725, 30729, 30733,
4479
     30737, 30741, 30745, 30749, 30753, 30757, 30761, 30765, 30769, 30773,
4480
     30777, 30781, 30785, 30789, 30793, 30797, 30801, 30805, 30809, 30813,
4481
     30817, 30821, 30825, 30829, 30833, 30837, 30841, 30845, 30849, 30853,
4482
     30857, 30861, 30865, 30869, 30873, 30877, 30881, 30885, 30889, 30893,
4483
     30897, 30901, 30905, 30909, 30913, 30917, 30921, 30925, 30929, 30933,
4484
     30937, 30941, 30945, 30949, 30953, 30957, 30961, 30965, 30969, 30973,
4485
     30977, 30981, 30985, 30989, 30993, 30997, 31001, 31005, 31009, 31013,
4486
     31017, 31021, 31025, 31029, 31033, 31037, 31041, 31045, 31049, 31053,
4487
     31057, 31061, 31065, 31069, 31073, 31077, 31080, 31080, 31081, 31085,
4488
     31089, 31093, 31097, 31101, 31105, 31109, 31113, 31117, 31121, 31125,
4489
     31129, 31133, 31137, 31141, 31145, 31149, 31153, 31157, 31161, 31165,
4490
     31169, 31173, 31177, 31181, 31185, 31189, 31193, 31197, 31201, 31205,
4491
     31209, 31213, 31217, 31221, 31225, 31229, 31233, 31237, 31241, 31245,
4492
     31249, 31253, 31257, 31261, 31265, 31269, 31273, 31277, 31281, 31285,
4493
     31289, 31293, 31297, 31301, 31305, 31309, 31313, 31317, 31321, 31325,
4494
     31329, 31333, 31337, 31341, 31345, 31349, 31353, 31357, 31361, 31365,
4495
     31369, 31373, 31377, 31381, 31385, 31389, 31393, 31397, 31401, 31405,
4496
     31409, 31413, 31417, 31421, 31425, 31429, 31433},
4497
    {31433, 31437, 31441, 31445, 31449, 31453, 31457, 31461, 31465, 31469,
4498
     31473, 31477, 31481, 31485, 31489, 31493, 31497, 31501, 31505, 31509,
4499
     31513, 31517, 31521, 31525, 31529, 31533, 31537, 31541, 31545, 31549,
4500
     31553, 31557, 31561, 31565, 31569, 31573, 31577, 31581, 31585, 31589,
4501
     31593, 31597, 31601, 31605, 31609, 31613, 31617, 31621, 31625, 31629,
4502
     31633, 31637, 31641, 31645, 31649, 31653, 31657, 31661, 31665, 31669,
4503
     31673, 31677, 31681, 31685, 31689, 31693, 31697, 31701, 31705, 31709,
4504
     31713, 31717, 31721, 31725, 31729, 31733, 31737, 31741, 31745, 31749,
4505
     31753, 31757, 31761, 31765, 31769, 31773, 31777, 31781, 31785, 31789,
4506
     31793, 31797, 31801, 31805, 31809, 31813, 31817, 31821, 31825, 31829,
4507
     31833, 31837, 31841, 31845, 31849, 31853, 31857, 31861, 31865, 31869,
4508
     31873, 31877, 31881, 31885, 31889, 31893, 31897, 31901, 31905, 31909,
4509
     31913, 31917, 31921, 31925, 31929, 31933, 31937, 31941, 31945, 31949,
4510
     31953, 31957, 31961, 31965, 31969, 31973, 31977, 31981, 31985, 31989,
4511
     31993, 31997, 32001, 32005, 32009, 32013, 32017, 32021, 32025, 32029,
4512
     32033, 32037, 32041, 32045, 32049, 32053, 32057, 32061, 32065, 32069,
4513
     32073, 32077, 32081, 32085, 32089, 32093, 32097, 32101, 32105, 32109,
4514
     32113, 32117, 32121, 32125, 32129, 32133, 32137, 32141, 32145, 32149,
4515
     32153, 32157, 32161, 32165, 32169, 32173, 32177, 32181, 32185, 32189,
4516
     32193, 32197, 32201, 32205, 32209, 32213, 32217, 32221, 32225, 32229,
4517
     32233, 32237, 32241, 32245, 32248, 32248, 32249, 32253, 32257, 32261,
4518
     32265, 32269, 32273, 32277, 32281, 32285, 32289, 32293, 32297, 32301,
4519
     32305, 32309, 32313, 32317, 32321, 32325, 32329, 32333, 32337, 32341,
4520
     32345, 32349, 32353, 32357, 32361, 32365, 32369, 32373, 32377, 32381,
4521
     32385, 32389, 32393, 32397, 32401, 32405, 32409, 32413, 32417, 32421,
4522
     32425, 32429, 32433, 32437, 32441, 32445, 32448},
4523
    {32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4524
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4525
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4526
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4527
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32449, 32453,
4528
     32457, 32461, 32465, 32469, 32473, 32477, 32481, 32485, 32489, 32493,
4529
     32497, 32501, 32505, 32509, 32513, 32517, 32521, 32525, 32529, 32533,
4530
     32537, 32541, 32545, 32549, 32553, 32557, 32561, 32565, 32569, 32573,
4531
     32577, 32581, 32585, 32589, 32593, 32597, 32601, 32605, 32609, 32613,
4532
     32617, 32621, 32625, 32629, 32633, 32637, 32641, 32645, 32649, 32653,
4533
     32657, 32661, 32665, 32669, 32673, 32677, 32681, 32685, 32689, 32693,
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},
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, 32696, 32696, 32696, 32696,
4560
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4561
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4562
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4563
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4564
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4565
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4566
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4567
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4568
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4569
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4570
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4571
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4572
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4573
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4574
     32696, 32696, 32696, 32696, 32696, 32696, 32697},
4575
    {32697, 32701, 32705, 32709, 32712, 32713, 32717, 32721, 32725, 32729,
4576
     32733, 32737, 32741, 32745, 32749, 32753, 32757, 32761, 32765, 32769,
4577
     32773, 32777, 32781, 32785, 32789, 32793, 32797, 32801, 32805, 32809,
4578
     32813, 32817, 32820, 32821, 32825, 32828, 32829, 32832, 32832, 32833,
4579
     32836, 32837, 32841, 32845, 32849, 32853, 32857, 32861, 32865, 32869,
4580
     32873, 32876, 32877, 32881, 32885, 32889, 32892, 32893, 32896, 32897,
4581
     32900, 32900, 32900, 32900, 32900, 32900, 32901, 32904, 32904, 32904,
4582
     32904, 32905, 32908, 32909, 32912, 32913, 32916, 32917, 32921, 32925,
4583
     32928, 32929, 32933, 32936, 32937, 32940, 32940, 32941, 32944, 32945,
4584
     32948, 32949, 32952, 32953, 32956, 32957, 32960, 32961, 32965, 32968,
4585
     32969, 32972, 32972, 32973, 32977, 32981, 32985, 32988, 32989, 32993,
4586
     32997, 33001, 33005, 33009, 33013, 33016, 33017, 33021, 33025, 33029,
4587
     33032, 33033, 33037, 33041, 33045, 33048, 33049, 33052, 33053, 33057,
4588
     33061, 33065, 33069, 33073, 33077, 33081, 33085, 33089, 33092, 33093,
4589
     33097, 33101, 33105, 33109, 33113, 33117, 33121, 33125, 33129, 33133,
4590
     33137, 33141, 33145, 33149, 33153, 33157, 33160, 33160, 33160, 33160,
4591
     33160, 33161, 33165, 33169, 33172, 33173, 33177, 33181, 33185, 33189,
4592
     33192, 33193, 33197, 33201, 33205, 33209, 33213, 33217, 33221, 33225,
4593
     33229, 33233, 33237, 33241, 33245, 33249, 33253, 33257, 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},
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, 33260, 33260, 33260, 33260,
4612
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4613
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4614
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4615
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4616
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4617
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4618
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4619
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4620
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4621
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4622
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4623
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4624
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4625
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4626
     33260, 33260, 33260, 33260, 33260, 33260, 33261},
4627
    {33261, 33269, 33277, 33285, 33293, 33301, 33309, 33317, 33325, 33333,
4628
     33341, 33348, 33348, 33348, 33348, 33348, 33349, 33361, 33373, 33385,
4629
     33397, 33409, 33421, 33433, 33445, 33457, 33469, 33481, 33493, 33505,
4630
     33517, 33529, 33541, 33553, 33565, 33577, 33589, 33601, 33613, 33625,
4631
     33637, 33649, 33661, 33673, 33677, 33681, 33689, 33696, 33697, 33701,
4632
     33705, 33709, 33713, 33717, 33721, 33725, 33729, 33733, 33737, 33741,
4633
     33745, 33749, 33753, 33757, 33761, 33765, 33769, 33773, 33777, 33781,
4634
     33785, 33789, 33793, 33797, 33801, 33809, 33817, 33825, 33833, 33845,
4635
     33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4636
     33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4637
     33852, 33852, 33852, 33852, 33852, 33852, 33853, 33861, 33869, 33876,
4638
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4639
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4640
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4641
     33876, 33876, 33876, 33876, 33877, 33884, 33884, 33884, 33884, 33884,
4642
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4643
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4644
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4645
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4646
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4647
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4648
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4649
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4650
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4651
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4652
     33884, 33884, 33884, 33884, 33884, 33884, 33885},
4653
    {33885, 33893, 33901, 33904, 33904, 33904, 33904, 33904, 33904, 33904,
4654
     33904, 33904, 33904, 33904, 33904, 33904, 33905, 33909, 33913, 33917,
4655
     33925, 33929, 33933, 33937, 33941, 33945, 33949, 33953, 33957, 33961,
4656
     33965, 33969, 33973, 33977, 33981, 33985, 33989, 33993, 33997, 34001,
4657
     34005, 34009, 34013, 34017, 34021, 34025, 34029, 34033, 34037, 34041,
4658
     34045, 34049, 34053, 34057, 34061, 34065, 34069, 34073, 34077, 34081,
4659
     34084, 34084, 34084, 34084, 34085, 34097, 34109, 34121, 34133, 34145,
4660
     34157, 34169, 34181, 34192, 34192, 34192, 34192, 34192, 34192, 34192,
4661
     34193, 34197, 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, 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},
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
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4689
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4690
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4691
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4692
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4693
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4694
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4695
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4696
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4697
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4698
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4699
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4700
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4701
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4702
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4703
     34201, 34205, 34209, 34213, 34217, 34221, 34225, 34229, 34233, 34237,
4704
     34240, 34240, 34240, 34240, 34240, 34240, 34240},
4705
    {34240, 34244, 34248, 34252, 34256, 34260, 34264, 34268, 34272, 34276,
4706
     34280, 34284, 34288, 34292, 34296, 34300, 34304, 34308, 34312, 34316,
4707
     34320, 34324, 34328, 34332, 34336, 34340, 34344, 34348, 34352, 34356,
4708
     34360, 34364, 34368, 34372, 34376, 34380, 34384, 34388, 34392, 34396,
4709
     34400, 34404, 34408, 34412, 34416, 34420, 34424, 34428, 34432, 34436,
4710
     34440, 34444, 34448, 34452, 34456, 34460, 34464, 34468, 34472, 34476,
4711
     34480, 34484, 34488, 34492, 34496, 34500, 34504, 34508, 34512, 34516,
4712
     34520, 34524, 34528, 34532, 34536, 34540, 34544, 34548, 34552, 34556,
4713
     34560, 34564, 34568, 34572, 34576, 34580, 34584, 34588, 34592, 34596,
4714
     34600, 34604, 34608, 34612, 34616, 34620, 34624, 34628, 34632, 34636,
4715
     34640, 34644, 34648, 34652, 34656, 34660, 34664, 34668, 34672, 34676,
4716
     34680, 34684, 34688, 34692, 34696, 34700, 34704, 34708, 34712, 34716,
4717
     34720, 34724, 34728, 34732, 34736, 34740, 34744, 34748, 34752, 34756,
4718
     34760, 34764, 34768, 34772, 34776, 34780, 34784, 34788, 34792, 34796,
4719
     34800, 34804, 34808, 34812, 34816, 34820, 34824, 34828, 34832, 34836,
4720
     34840, 34844, 34848, 34852, 34856, 34860, 34864, 34868, 34872, 34876,
4721
     34880, 34884, 34888, 34892, 34896, 34900, 34904, 34908, 34912, 34916,
4722
     34920, 34924, 34928, 34932, 34936, 34940, 34944, 34948, 34952, 34956,
4723
     34960, 34964, 34968, 34972, 34976, 34980, 34984, 34988, 34992, 34996,
4724
     35000, 35004, 35008, 35012, 35016, 35020, 35024, 35028, 35032, 35036,
4725
     35040, 35044, 35048, 35052, 35056, 35060, 35064, 35068, 35072, 35076,
4726
     35080, 35084, 35088, 35092, 35096, 35100, 35104, 35108, 35112, 35116,
4727
     35120, 35124, 35128, 35132, 35136, 35140, 35144, 35148, 35152, 35156,
4728
     35160, 35164, 35168, 35172, 35176, 35180, 35184, 35188, 35192, 35196,
4729
     35200, 35204, 35208, 35212, 35216, 35220, 35224, 35228, 35232, 35236,
4730
     35240, 35244, 35248, 35252, 35256, 35260, 35264},
4731
    {35264, 35268, 35272, 35276, 35280, 35284, 35288, 35292, 35296, 35300,
4732
     35304, 35308, 35312, 35316, 35320, 35324, 35328, 35332, 35336, 35340,
4733
     35344, 35348, 35352, 35356, 35360, 35364, 35368, 35372, 35376, 35380,
4734
     35384, 35388, 35392, 35396, 35400, 35404, 35408, 35412, 35416, 35420,
4735
     35424, 35428, 35432, 35436, 35440, 35444, 35448, 35452, 35456, 35460,
4736
     35464, 35468, 35472, 35476, 35480, 35484, 35488, 35492, 35496, 35500,
4737
     35504, 35508, 35512, 35516, 35520, 35524, 35528, 35532, 35536, 35540,
4738
     35544, 35548, 35552, 35556, 35560, 35564, 35568, 35572, 35576, 35580,
4739
     35584, 35588, 35592, 35596, 35600, 35604, 35608, 35612, 35616, 35620,
4740
     35624, 35628, 35632, 35636, 35640, 35644, 35648, 35652, 35656, 35660,
4741
     35664, 35668, 35672, 35676, 35680, 35684, 35688, 35692, 35696, 35700,
4742
     35704, 35708, 35712, 35716, 35720, 35724, 35728, 35732, 35736, 35740,
4743
     35744, 35748, 35752, 35756, 35760, 35764, 35768, 35772, 35776, 35780,
4744
     35784, 35788, 35792, 35796, 35800, 35804, 35808, 35812, 35816, 35820,
4745
     35824, 35828, 35832, 35836, 35840, 35844, 35848, 35852, 35856, 35860,
4746
     35864, 35868, 35872, 35876, 35880, 35884, 35888, 35892, 35896, 35900,
4747
     35904, 35908, 35912, 35916, 35920, 35924, 35928, 35932, 35936, 35940,
4748
     35944, 35948, 35952, 35956, 35960, 35964, 35968, 35972, 35976, 35980,
4749
     35984, 35988, 35992, 35996, 36000, 36004, 36008, 36012, 36016, 36020,
4750
     36024, 36028, 36032, 36036, 36040, 36044, 36048, 36052, 36056, 36060,
4751
     36064, 36068, 36072, 36076, 36080, 36084, 36088, 36092, 36096, 36100,
4752
     36104, 36108, 36112, 36116, 36120, 36124, 36128, 36132, 36136, 36140,
4753
     36144, 36148, 36152, 36156, 36160, 36164, 36168, 36172, 36176, 36180,
4754
     36184, 36188, 36192, 36196, 36200, 36204, 36208, 36212, 36216, 36220,
4755
     36224, 36228, 36232, 36236, 36240, 36244, 36248, 36252, 36256, 36260,
4756
     36264, 36268, 36272, 36276, 36280, 36284, 36288},
4757
    {36288, 36292, 36296, 36300, 36304, 36308, 36312, 36316, 36320, 36324,
4758
     36328, 36332, 36336, 36340, 36344, 36348, 36352, 36356, 36360, 36364,
4759
     36368, 36372, 36376, 36380, 36384, 36388, 36392, 36396, 36400, 36404,
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, 36408, 36408, 36408,
4768
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4769
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4770
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4771
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4772
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4773
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4774
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4775
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4776
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4777
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4778
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4779
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4780
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4781
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4782
     36408, 36408, 36408, 36408, 36408, 36408, 36408}};
4783
const char32_t decomposition_data[9102] = {
4784
    0,      32,     32,     776,    97,     32,     772,    50,     51,
4785
    32,     769,    956,    32,     807,    49,     111,    49,     8260,
4786
    52,     49,     8260,   50,     51,     8260,   52,     65,     768,
4787
    65,     769,    65,     770,    65,     771,    65,     776,    65,
4788
    778,    67,     807,    69,     768,    69,     769,    69,     770,
4789
    69,     776,    73,     768,    73,     769,    73,     770,    73,
4790
    776,    78,     771,    79,     768,    79,     769,    79,     770,
4791
    79,     771,    79,     776,    85,     768,    85,     769,    85,
4792
    770,    85,     776,    89,     769,    97,     768,    97,     769,
4793
    97,     770,    97,     771,    97,     776,    97,     778,    99,
4794
    807,    101,    768,    101,    769,    101,    770,    101,    776,
4795
    105,    768,    105,    769,    105,    770,    105,    776,    110,
4796
    771,    111,    768,    111,    769,    111,    770,    111,    771,
4797
    111,    776,    117,    768,    117,    769,    117,    770,    117,
4798
    776,    121,    769,    121,    776,    65,     772,    97,     772,
4799
    65,     774,    97,     774,    65,     808,    97,     808,    67,
4800
    769,    99,     769,    67,     770,    99,     770,    67,     775,
4801
    99,     775,    67,     780,    99,     780,    68,     780,    100,
4802
    780,    69,     772,    101,    772,    69,     774,    101,    774,
4803
    69,     775,    101,    775,    69,     808,    101,    808,    69,
4804
    780,    101,    780,    71,     770,    103,    770,    71,     774,
4805
    103,    774,    71,     775,    103,    775,    71,     807,    103,
4806
    807,    72,     770,    104,    770,    73,     771,    105,    771,
4807
    73,     772,    105,    772,    73,     774,    105,    774,    73,
4808
    808,    105,    808,    73,     775,    73,     74,     105,    106,
4809
    74,     770,    106,    770,    75,     807,    107,    807,    76,
4810
    769,    108,    769,    76,     807,    108,    807,    76,     780,
4811
    108,    780,    76,     183,    108,    183,    78,     769,    110,
4812
    769,    78,     807,    110,    807,    78,     780,    110,    780,
4813
    700,    110,    79,     772,    111,    772,    79,     774,    111,
4814
    774,    79,     779,    111,    779,    82,     769,    114,    769,
4815
    82,     807,    114,    807,    82,     780,    114,    780,    83,
4816
    769,    115,    769,    83,     770,    115,    770,    83,     807,
4817
    115,    807,    83,     780,    115,    780,    84,     807,    116,
4818
    807,    84,     780,    116,    780,    85,     771,    117,    771,
4819
    85,     772,    117,    772,    85,     774,    117,    774,    85,
4820
    778,    117,    778,    85,     779,    117,    779,    85,     808,
4821
    117,    808,    87,     770,    119,    770,    89,     770,    121,
4822
    770,    89,     776,    90,     769,    122,    769,    90,     775,
4823
    122,    775,    90,     780,    122,    780,    115,    79,     795,
4824
    111,    795,    85,     795,    117,    795,    68,     90,     780,
4825
    68,     122,    780,    100,    122,    780,    76,     74,     76,
4826
    106,    108,    106,    78,     74,     78,     106,    110,    106,
4827
    65,     780,    97,     780,    73,     780,    105,    780,    79,
4828
    780,    111,    780,    85,     780,    117,    780,    85,     776,
4829
    772,    117,    776,    772,    85,     776,    769,    117,    776,
4830
    769,    85,     776,    780,    117,    776,    780,    85,     776,
4831
    768,    117,    776,    768,    65,     776,    772,    97,     776,
4832
    772,    65,     775,    772,    97,     775,    772,    198,    772,
4833
    230,    772,    71,     780,    103,    780,    75,     780,    107,
4834
    780,    79,     808,    111,    808,    79,     808,    772,    111,
4835
    808,    772,    439,    780,    658,    780,    106,    780,    68,
4836
    90,     68,     122,    100,    122,    71,     769,    103,    769,
4837
    78,     768,    110,    768,    65,     778,    769,    97,     778,
4838
    769,    198,    769,    230,    769,    216,    769,    248,    769,
4839
    65,     783,    97,     783,    65,     785,    97,     785,    69,
4840
    783,    101,    783,    69,     785,    101,    785,    73,     783,
4841
    105,    783,    73,     785,    105,    785,    79,     783,    111,
4842
    783,    79,     785,    111,    785,    82,     783,    114,    783,
4843
    82,     785,    114,    785,    85,     783,    117,    783,    85,
4844
    785,    117,    785,    83,     806,    115,    806,    84,     806,
4845
    116,    806,    72,     780,    104,    780,    65,     775,    97,
4846
    775,    69,     807,    101,    807,    79,     776,    772,    111,
4847
    776,    772,    79,     771,    772,    111,    771,    772,    79,
4848
    775,    111,    775,    79,     775,    772,    111,    775,    772,
4849
    89,     772,    121,    772,    104,    614,    106,    114,    633,
4850
    635,    641,    119,    121,    32,     774,    32,     775,    32,
4851
    778,    32,     808,    32,     771,    32,     779,    611,    108,
4852
    115,    120,    661,    768,    769,    787,    776,    769,    697,
4853
    32,     837,    59,     32,     769,    168,    769,    913,    769,
4854
    183,    917,    769,    919,    769,    921,    769,    927,    769,
4855
    933,    769,    937,    769,    953,    776,    769,    921,    776,
4856
    933,    776,    945,    769,    949,    769,    951,    769,    953,
4857
    769,    965,    776,    769,    953,    776,    965,    776,    959,
4858
    769,    965,    769,    969,    769,    946,    952,    933,    978,
4859
    769,    978,    776,    966,    960,    954,    961,    962,    920,
4860
    949,    931,    1045,   768,    1045,   776,    1043,   769,    1030,
4861
    776,    1050,   769,    1048,   768,    1059,   774,    1048,   774,
4862
    1080,   774,    1077,   768,    1077,   776,    1075,   769,    1110,
4863
    776,    1082,   769,    1080,   768,    1091,   774,    1140,   783,
4864
    1141,   783,    1046,   774,    1078,   774,    1040,   774,    1072,
4865
    774,    1040,   776,    1072,   776,    1045,   774,    1077,   774,
4866
    1240,   776,    1241,   776,    1046,   776,    1078,   776,    1047,
4867
    776,    1079,   776,    1048,   772,    1080,   772,    1048,   776,
4868
    1080,   776,    1054,   776,    1086,   776,    1256,   776,    1257,
4869
    776,    1069,   776,    1101,   776,    1059,   772,    1091,   772,
4870
    1059,   776,    1091,   776,    1059,   779,    1091,   779,    1063,
4871
    776,    1095,   776,    1067,   776,    1099,   776,    1381,   1410,
4872
    1575,   1619,   1575,   1620,   1608,   1620,   1575,   1621,   1610,
4873
    1620,   1575,   1652,   1608,   1652,   1735,   1652,   1610,   1652,
4874
    1749,   1620,   1729,   1620,   1746,   1620,   2344,   2364,   2352,
4875
    2364,   2355,   2364,   2325,   2364,   2326,   2364,   2327,   2364,
4876
    2332,   2364,   2337,   2364,   2338,   2364,   2347,   2364,   2351,
4877
    2364,   2503,   2494,   2503,   2519,   2465,   2492,   2466,   2492,
4878
    2479,   2492,   2610,   2620,   2616,   2620,   2582,   2620,   2583,
4879
    2620,   2588,   2620,   2603,   2620,   2887,   2902,   2887,   2878,
4880
    2887,   2903,   2849,   2876,   2850,   2876,   2962,   3031,   3014,
4881
    3006,   3015,   3006,   3014,   3031,   3142,   3158,   3263,   3285,
4882
    3270,   3285,   3270,   3286,   3270,   3266,   3270,   3266,   3285,
4883
    3398,   3390,   3399,   3390,   3398,   3415,   3545,   3530,   3545,
4884
    3535,   3545,   3535,   3530,   3545,   3551,   3661,   3634,   3789,
4885
    3762,   3755,   3737,   3755,   3745,   3851,   3906,   4023,   3916,
4886
    4023,   3921,   4023,   3926,   4023,   3931,   4023,   3904,   4021,
4887
    3953,   3954,   3953,   3956,   4018,   3968,   4018,   3953,   3968,
4888
    4019,   3968,   4019,   3953,   3968,   3953,   3968,   3986,   4023,
4889
    3996,   4023,   4001,   4023,   4006,   4023,   4011,   4023,   3984,
4890
    4021,   4133,   4142,   4316,   6917,   6965,   6919,   6965,   6921,
4891
    6965,   6923,   6965,   6925,   6965,   6929,   6965,   6970,   6965,
4892
    6972,   6965,   6974,   6965,   6975,   6965,   6978,   6965,   65,
4893
    198,    66,     68,     69,     398,    71,     72,     73,     74,
4894
    75,     76,     77,     78,     79,     546,    80,     82,     84,
4895
    85,     87,     97,     592,    593,    7426,   98,     100,    101,
4896
    601,    603,    604,    103,    107,    109,    331,    111,    596,
4897
    7446,   7447,   112,    116,    117,    7453,   623,    118,    7461,
4898
    946,    947,    948,    966,    967,    105,    114,    117,    118,
4899
    946,    947,    961,    966,    967,    1085,   594,    99,     597,
4900
    240,    604,    102,    607,    609,    613,    616,    617,    618,
4901
    7547,   669,    621,    7557,   671,    625,    624,    626,    627,
4902
    628,    629,    632,    642,    643,    427,    649,    650,    7452,
4903
    651,    652,    122,    656,    657,    658,    952,    65,     805,
4904
    97,     805,    66,     775,    98,     775,    66,     803,    98,
4905
    803,    66,     817,    98,     817,    67,     807,    769,    99,
4906
    807,    769,    68,     775,    100,    775,    68,     803,    100,
4907
    803,    68,     817,    100,    817,    68,     807,    100,    807,
4908
    68,     813,    100,    813,    69,     772,    768,    101,    772,
4909
    768,    69,     772,    769,    101,    772,    769,    69,     813,
4910
    101,    813,    69,     816,    101,    816,    69,     807,    774,
4911
    101,    807,    774,    70,     775,    102,    775,    71,     772,
4912
    103,    772,    72,     775,    104,    775,    72,     803,    104,
4913
    803,    72,     776,    104,    776,    72,     807,    104,    807,
4914
    72,     814,    104,    814,    73,     816,    105,    816,    73,
4915
    776,    769,    105,    776,    769,    75,     769,    107,    769,
4916
    75,     803,    107,    803,    75,     817,    107,    817,    76,
4917
    803,    108,    803,    76,     803,    772,    108,    803,    772,
4918
    76,     817,    108,    817,    76,     813,    108,    813,    77,
4919
    769,    109,    769,    77,     775,    109,    775,    77,     803,
4920
    109,    803,    78,     775,    110,    775,    78,     803,    110,
4921
    803,    78,     817,    110,    817,    78,     813,    110,    813,
4922
    79,     771,    769,    111,    771,    769,    79,     771,    776,
4923
    111,    771,    776,    79,     772,    768,    111,    772,    768,
4924
    79,     772,    769,    111,    772,    769,    80,     769,    112,
4925
    769,    80,     775,    112,    775,    82,     775,    114,    775,
4926
    82,     803,    114,    803,    82,     803,    772,    114,    803,
4927
    772,    82,     817,    114,    817,    83,     775,    115,    775,
4928
    83,     803,    115,    803,    83,     769,    775,    115,    769,
4929
    775,    83,     780,    775,    115,    780,    775,    83,     803,
4930
    775,    115,    803,    775,    84,     775,    116,    775,    84,
4931
    803,    116,    803,    84,     817,    116,    817,    84,     813,
4932
    116,    813,    85,     804,    117,    804,    85,     816,    117,
4933
    816,    85,     813,    117,    813,    85,     771,    769,    117,
4934
    771,    769,    85,     772,    776,    117,    772,    776,    86,
4935
    771,    118,    771,    86,     803,    118,    803,    87,     768,
4936
    119,    768,    87,     769,    119,    769,    87,     776,    119,
4937
    776,    87,     775,    119,    775,    87,     803,    119,    803,
4938
    88,     775,    120,    775,    88,     776,    120,    776,    89,
4939
    775,    121,    775,    90,     770,    122,    770,    90,     803,
4940
    122,    803,    90,     817,    122,    817,    104,    817,    116,
4941
    776,    119,    778,    121,    778,    97,     702,    383,    775,
4942
    65,     803,    97,     803,    65,     777,    97,     777,    65,
4943
    770,    769,    97,     770,    769,    65,     770,    768,    97,
4944
    770,    768,    65,     770,    777,    97,     770,    777,    65,
4945
    770,    771,    97,     770,    771,    65,     803,    770,    97,
4946
    803,    770,    65,     774,    769,    97,     774,    769,    65,
4947
    774,    768,    97,     774,    768,    65,     774,    777,    97,
4948
    774,    777,    65,     774,    771,    97,     774,    771,    65,
4949
    803,    774,    97,     803,    774,    69,     803,    101,    803,
4950
    69,     777,    101,    777,    69,     771,    101,    771,    69,
4951
    770,    769,    101,    770,    769,    69,     770,    768,    101,
4952
    770,    768,    69,     770,    777,    101,    770,    777,    69,
4953
    770,    771,    101,    770,    771,    69,     803,    770,    101,
4954
    803,    770,    73,     777,    105,    777,    73,     803,    105,
4955
    803,    79,     803,    111,    803,    79,     777,    111,    777,
4956
    79,     770,    769,    111,    770,    769,    79,     770,    768,
4957
    111,    770,    768,    79,     770,    777,    111,    770,    777,
4958
    79,     770,    771,    111,    770,    771,    79,     803,    770,
4959
    111,    803,    770,    79,     795,    769,    111,    795,    769,
4960
    79,     795,    768,    111,    795,    768,    79,     795,    777,
4961
    111,    795,    777,    79,     795,    771,    111,    795,    771,
4962
    79,     795,    803,    111,    795,    803,    85,     803,    117,
4963
    803,    85,     777,    117,    777,    85,     795,    769,    117,
4964
    795,    769,    85,     795,    768,    117,    795,    768,    85,
4965
    795,    777,    117,    795,    777,    85,     795,    771,    117,
4966
    795,    771,    85,     795,    803,    117,    795,    803,    89,
4967
    768,    121,    768,    89,     803,    121,    803,    89,     777,
4968
    121,    777,    89,     771,    121,    771,    945,    787,    945,
4969
    788,    945,    787,    768,    945,    788,    768,    945,    787,
4970
    769,    945,    788,    769,    945,    787,    834,    945,    788,
4971
    834,    913,    787,    913,    788,    913,    787,    768,    913,
4972
    788,    768,    913,    787,    769,    913,    788,    769,    913,
4973
    787,    834,    913,    788,    834,    949,    787,    949,    788,
4974
    949,    787,    768,    949,    788,    768,    949,    787,    769,
4975
    949,    788,    769,    917,    787,    917,    788,    917,    787,
4976
    768,    917,    788,    768,    917,    787,    769,    917,    788,
4977
    769,    951,    787,    951,    788,    951,    787,    768,    951,
4978
    788,    768,    951,    787,    769,    951,    788,    769,    951,
4979
    787,    834,    951,    788,    834,    919,    787,    919,    788,
4980
    919,    787,    768,    919,    788,    768,    919,    787,    769,
4981
    919,    788,    769,    919,    787,    834,    919,    788,    834,
4982
    953,    787,    953,    788,    953,    787,    768,    953,    788,
4983
    768,    953,    787,    769,    953,    788,    769,    953,    787,
4984
    834,    953,    788,    834,    921,    787,    921,    788,    921,
4985
    787,    768,    921,    788,    768,    921,    787,    769,    921,
4986
    788,    769,    921,    787,    834,    921,    788,    834,    959,
4987
    787,    959,    788,    959,    787,    768,    959,    788,    768,
4988
    959,    787,    769,    959,    788,    769,    927,    787,    927,
4989
    788,    927,    787,    768,    927,    788,    768,    927,    787,
4990
    769,    927,    788,    769,    965,    787,    965,    788,    965,
4991
    787,    768,    965,    788,    768,    965,    787,    769,    965,
4992
    788,    769,    965,    787,    834,    965,    788,    834,    933,
4993
    788,    933,    788,    768,    933,    788,    769,    933,    788,
4994
    834,    969,    787,    969,    788,    969,    787,    768,    969,
4995
    788,    768,    969,    787,    769,    969,    788,    769,    969,
4996
    787,    834,    969,    788,    834,    937,    787,    937,    788,
4997
    937,    787,    768,    937,    788,    768,    937,    787,    769,
4998
    937,    788,    769,    937,    787,    834,    937,    788,    834,
4999
    945,    768,    945,    769,    949,    768,    949,    769,    951,
5000
    768,    951,    769,    953,    768,    953,    769,    959,    768,
5001
    959,    769,    965,    768,    965,    769,    969,    768,    969,
5002
    769,    945,    787,    837,    945,    788,    837,    945,    787,
5003
    768,    837,    945,    788,    768,    837,    945,    787,    769,
5004
    837,    945,    788,    769,    837,    945,    787,    834,    837,
5005
    945,    788,    834,    837,    913,    787,    837,    913,    788,
5006
    837,    913,    787,    768,    837,    913,    788,    768,    837,
5007
    913,    787,    769,    837,    913,    788,    769,    837,    913,
5008
    787,    834,    837,    913,    788,    834,    837,    951,    787,
5009
    837,    951,    788,    837,    951,    787,    768,    837,    951,
5010
    788,    768,    837,    951,    787,    769,    837,    951,    788,
5011
    769,    837,    951,    787,    834,    837,    951,    788,    834,
5012
    837,    919,    787,    837,    919,    788,    837,    919,    787,
5013
    768,    837,    919,    788,    768,    837,    919,    787,    769,
5014
    837,    919,    788,    769,    837,    919,    787,    834,    837,
5015
    919,    788,    834,    837,    969,    787,    837,    969,    788,
5016
    837,    969,    787,    768,    837,    969,    788,    768,    837,
5017
    969,    787,    769,    837,    969,    788,    769,    837,    969,
5018
    787,    834,    837,    969,    788,    834,    837,    937,    787,
5019
    837,    937,    788,    837,    937,    787,    768,    837,    937,
5020
    788,    768,    837,    937,    787,    769,    837,    937,    788,
5021
    769,    837,    937,    787,    834,    837,    937,    788,    834,
5022
    837,    945,    774,    945,    772,    945,    768,    837,    945,
5023
    837,    945,    769,    837,    945,    834,    945,    834,    837,
5024
    913,    774,    913,    772,    913,    768,    913,    769,    913,
5025
    837,    32,     787,    953,    32,     787,    32,     834,    168,
5026
    834,    951,    768,    837,    951,    837,    951,    769,    837,
5027
    951,    834,    951,    834,    837,    917,    768,    917,    769,
5028
    919,    768,    919,    769,    919,    837,    8127,   768,    8127,
5029
    769,    8127,   834,    953,    774,    953,    772,    953,    776,
5030
    768,    953,    776,    769,    953,    834,    953,    776,    834,
5031
    921,    774,    921,    772,    921,    768,    921,    769,    8190,
5032
    768,    8190,   769,    8190,   834,    965,    774,    965,    772,
5033
    965,    776,    768,    965,    776,    769,    961,    787,    961,
5034
    788,    965,    834,    965,    776,    834,    933,    774,    933,
5035
    772,    933,    768,    933,    769,    929,    788,    168,    768,
5036
    168,    769,    96,     969,    768,    837,    969,    837,    969,
5037
    769,    837,    969,    834,    969,    834,    837,    927,    768,
5038
    927,    769,    937,    768,    937,    769,    937,    837,    180,
5039
    32,     788,    8194,   8195,   32,     32,     32,     32,     32,
5040
    32,     32,     32,     32,     8208,   32,     819,    46,     46,
5041
    46,     46,     46,     46,     32,     8242,   8242,   8242,   8242,
5042
    8242,   8245,   8245,   8245,   8245,   8245,   33,     33,     32,
5043
    773,    63,     63,     63,     33,     33,     63,     8242,   8242,
5044
    8242,   8242,   32,     48,     105,    52,     53,     54,     55,
5045
    56,     57,     43,     8722,   61,     40,     41,     110,    48,
5046
    49,     50,     51,     52,     53,     54,     55,     56,     57,
5047
    43,     8722,   61,     40,     41,     97,     101,    111,    120,
5048
    601,    104,    107,    108,    109,    110,    112,    115,    116,
5049
    82,     115,    97,     47,     99,     97,     47,     115,    67,
5050
    176,    67,     99,     47,     111,    99,     47,     117,    400,
5051
    176,    70,     103,    72,     72,     72,     104,    295,    73,
5052
    73,     76,     108,    78,     78,     111,    80,     81,     82,
5053
    82,     82,     83,     77,     84,     69,     76,     84,     77,
5054
    90,     937,    90,     75,     65,     778,    66,     67,     101,
5055
    69,     70,     77,     111,    1488,   1489,   1490,   1491,   105,
5056
    70,     65,     88,     960,    947,    915,    928,    8721,   68,
5057
    100,    101,    105,    106,    49,     8260,   55,     49,     8260,
5058
    57,     49,     8260,   49,     48,     49,     8260,   51,     50,
5059
    8260,   51,     49,     8260,   53,     50,     8260,   53,     51,
5060
    8260,   53,     52,     8260,   53,     49,     8260,   54,     53,
5061
    8260,   54,     49,     8260,   56,     51,     8260,   56,     53,
5062
    8260,   56,     55,     8260,   56,     49,     8260,   73,     73,
5063
    73,     73,     73,     73,     73,     86,     86,     86,     73,
5064
    86,     73,     73,     86,     73,     73,     73,     73,     88,
5065
    88,     88,     73,     88,     73,     73,     76,     67,     68,
5066
    77,     105,    105,    105,    105,    105,    105,    105,    118,
5067
    118,    118,    105,    118,    105,    105,    118,    105,    105,
5068
    105,    105,    120,    120,    120,    105,    120,    105,    105,
5069
    108,    99,     100,    109,    48,     8260,   51,     8592,   824,
5070
    8594,   824,    8596,   824,    8656,   824,    8660,   824,    8658,
5071
    824,    8707,   824,    8712,   824,    8715,   824,    8739,   824,
5072
    8741,   824,    8747,   8747,   8747,   8747,   8747,   8750,   8750,
5073
    8750,   8750,   8750,   8764,   824,    8771,   824,    8773,   824,
5074
    8776,   824,    61,     824,    8801,   824,    8781,   824,    60,
5075
    824,    62,     824,    8804,   824,    8805,   824,    8818,   824,
5076
    8819,   824,    8822,   824,    8823,   824,    8826,   824,    8827,
5077
    824,    8834,   824,    8835,   824,    8838,   824,    8839,   824,
5078
    8866,   824,    8872,   824,    8873,   824,    8875,   824,    8828,
5079
    824,    8829,   824,    8849,   824,    8850,   824,    8882,   824,
5080
    8883,   824,    8884,   824,    8885,   824,    12296,  12297,  49,
5081
    50,     51,     52,     53,     54,     55,     56,     57,     49,
5082
    48,     49,     49,     49,     50,     49,     51,     49,     52,
5083
    49,     53,     49,     54,     49,     55,     49,     56,     49,
5084
    57,     50,     48,     40,     49,     41,     40,     50,     41,
5085
    40,     51,     41,     40,     52,     41,     40,     53,     41,
5086
    40,     54,     41,     40,     55,     41,     40,     56,     41,
5087
    40,     57,     41,     40,     49,     48,     41,     40,     49,
5088
    49,     41,     40,     49,     50,     41,     40,     49,     51,
5089
    41,     40,     49,     52,     41,     40,     49,     53,     41,
5090
    40,     49,     54,     41,     40,     49,     55,     41,     40,
5091
    49,     56,     41,     40,     49,     57,     41,     40,     50,
5092
    48,     41,     49,     46,     50,     46,     51,     46,     52,
5093
    46,     53,     46,     54,     46,     55,     46,     56,     46,
5094
    57,     46,     49,     48,     46,     49,     49,     46,     49,
5095
    50,     46,     49,     51,     46,     49,     52,     46,     49,
5096
    53,     46,     49,     54,     46,     49,     55,     46,     49,
5097
    56,     46,     49,     57,     46,     50,     48,     46,     40,
5098
    97,     41,     40,     98,     41,     40,     99,     41,     40,
5099
    100,    41,     40,     101,    41,     40,     102,    41,     40,
5100
    103,    41,     40,     104,    41,     40,     105,    41,     40,
5101
    106,    41,     40,     107,    41,     40,     108,    41,     40,
5102
    109,    41,     40,     110,    41,     40,     111,    41,     40,
5103
    112,    41,     40,     113,    41,     40,     114,    41,     40,
5104
    115,    41,     40,     116,    41,     40,     117,    41,     40,
5105
    118,    41,     40,     119,    41,     40,     120,    41,     40,
5106
    121,    41,     40,     122,    41,     65,     66,     67,     68,
5107
    69,     70,     71,     72,     73,     74,     75,     76,     77,
5108
    78,     79,     80,     81,     82,     83,     84,     85,     86,
5109
    87,     88,     89,     90,     97,     98,     99,     100,    101,
5110
    102,    103,    104,    105,    106,    107,    108,    109,    110,
5111
    111,    112,    113,    114,    115,    116,    117,    118,    119,
5112
    120,    121,    122,    48,     8747,   8747,   8747,   8747,   58,
5113
    58,     61,     61,     61,     61,     61,     61,     10973,  824,
5114
    106,    86,     11617,  27597,  40863,  19968,  20008,  20022,  20031,
5115
    20057,  20101,  20108,  20128,  20154,  20799,  20837,  20843,  20866,
5116
    20886,  20907,  20960,  20981,  20992,  21147,  21241,  21269,  21274,
5117
    21304,  21313,  21340,  21353,  21378,  21430,  21448,  21475,  22231,
5118
    22303,  22763,  22786,  22794,  22805,  22823,  22899,  23376,  23424,
5119
    23544,  23567,  23586,  23608,  23662,  23665,  24027,  24037,  24049,
5120
    24062,  24178,  24186,  24191,  24308,  24318,  24331,  24339,  24400,
5121
    24417,  24435,  24515,  25096,  25142,  25163,  25903,  25908,  25991,
5122
    26007,  26020,  26041,  26080,  26085,  26352,  26376,  26408,  27424,
5123
    27490,  27513,  27571,  27595,  27604,  27611,  27663,  27668,  27700,
5124
    28779,  29226,  29238,  29243,  29247,  29255,  29273,  29275,  29356,
5125
    29572,  29577,  29916,  29926,  29976,  29983,  29992,  30000,  30091,
5126
    30098,  30326,  30333,  30382,  30399,  30446,  30683,  30690,  30707,
5127
    31034,  31160,  31166,  31348,  31435,  31481,  31859,  31992,  32566,
5128
    32593,  32650,  32701,  32769,  32780,  32786,  32819,  32895,  32905,
5129
    33251,  33258,  33267,  33276,  33292,  33307,  33311,  33390,  33394,
5130
    33400,  34381,  34411,  34880,  34892,  34915,  35198,  35211,  35282,
5131
    35328,  35895,  35910,  35925,  35960,  35997,  36196,  36208,  36275,
5132
    36523,  36554,  36763,  36784,  36789,  37009,  37193,  37318,  37324,
5133
    37329,  38263,  38272,  38428,  38582,  38585,  38632,  38737,  38750,
5134
    38754,  38761,  38859,  38893,  38899,  38913,  39080,  39131,  39135,
5135
    39318,  39321,  39340,  39592,  39640,  39647,  39717,  39727,  39730,
5136
    39740,  39770,  40165,  40565,  40575,  40613,  40635,  40643,  40653,
5137
    40657,  40697,  40701,  40718,  40723,  40736,  40763,  40778,  40786,
5138
    40845,  40860,  40864,  32,     12306,  21313,  21316,  21317,  12363,
5139
    12441,  12365,  12441,  12367,  12441,  12369,  12441,  12371,  12441,
5140
    12373,  12441,  12375,  12441,  12377,  12441,  12379,  12441,  12381,
5141
    12441,  12383,  12441,  12385,  12441,  12388,  12441,  12390,  12441,
5142
    12392,  12441,  12399,  12441,  12399,  12442,  12402,  12441,  12402,
5143
    12442,  12405,  12441,  12405,  12442,  12408,  12441,  12408,  12442,
5144
    12411,  12441,  12411,  12442,  12358,  12441,  32,     12441,  32,
5145
    12442,  12445,  12441,  12424,  12426,  12459,  12441,  12461,  12441,
5146
    12463,  12441,  12465,  12441,  12467,  12441,  12469,  12441,  12471,
5147
    12441,  12473,  12441,  12475,  12441,  12477,  12441,  12479,  12441,
5148
    12481,  12441,  12484,  12441,  12486,  12441,  12488,  12441,  12495,
5149
    12441,  12495,  12442,  12498,  12441,  12498,  12442,  12501,  12441,
5150
    12501,  12442,  12504,  12441,  12504,  12442,  12507,  12441,  12507,
5151
    12442,  12454,  12441,  12527,  12441,  12528,  12441,  12529,  12441,
5152
    12530,  12441,  12541,  12441,  12467,  12488,  4352,   4353,   4522,
5153
    4354,   4524,   4525,   4355,   4356,   4357,   4528,   4529,   4530,
5154
    4531,   4532,   4533,   4378,   4358,   4359,   4360,   4385,   4361,
5155
    4362,   4363,   4364,   4365,   4366,   4367,   4368,   4369,   4370,
5156
    4449,   4450,   4451,   4452,   4453,   4454,   4455,   4456,   4457,
5157
    4458,   4459,   4460,   4461,   4462,   4463,   4464,   4465,   4466,
5158
    4467,   4468,   4469,   4448,   4372,   4373,   4551,   4552,   4556,
5159
    4558,   4563,   4567,   4569,   4380,   4573,   4575,   4381,   4382,
5160
    4384,   4386,   4387,   4391,   4393,   4395,   4396,   4397,   4398,
5161
    4399,   4402,   4406,   4416,   4423,   4428,   4593,   4594,   4439,
5162
    4440,   4441,   4484,   4485,   4488,   4497,   4498,   4500,   4510,
5163
    4513,   19968,  20108,  19977,  22235,  19978,  20013,  19979,  30002,
5164
    20057,  19993,  19969,  22825,  22320,  20154,  40,     4352,   41,
5165
    40,     4354,   41,     40,     4355,   41,     40,     4357,   41,
5166
    40,     4358,   41,     40,     4359,   41,     40,     4361,   41,
5167
    40,     4363,   41,     40,     4364,   41,     40,     4366,   41,
5168
    40,     4367,   41,     40,     4368,   41,     40,     4369,   41,
5169
    40,     4370,   41,     40,     4352,   4449,   41,     40,     4354,
5170
    4449,   41,     40,     4355,   4449,   41,     40,     4357,   4449,
5171
    41,     40,     4358,   4449,   41,     40,     4359,   4449,   41,
5172
    40,     4361,   4449,   41,     40,     4363,   4449,   41,     40,
5173
    4364,   4449,   41,     40,     4366,   4449,   41,     40,     4367,
5174
    4449,   41,     40,     4368,   4449,   41,     40,     4369,   4449,
5175
    41,     40,     4370,   4449,   41,     40,     4364,   4462,   41,
5176
    40,     4363,   4457,   4364,   4453,   4523,   41,     40,     4363,
5177
    4457,   4370,   4462,   41,     40,     19968,  41,     40,     20108,
5178
    41,     40,     19977,  41,     40,     22235,  41,     40,     20116,
5179
    41,     40,     20845,  41,     40,     19971,  41,     40,     20843,
5180
    41,     40,     20061,  41,     40,     21313,  41,     40,     26376,
5181
    41,     40,     28779,  41,     40,     27700,  41,     40,     26408,
5182
    41,     40,     37329,  41,     40,     22303,  41,     40,     26085,
5183
    41,     40,     26666,  41,     40,     26377,  41,     40,     31038,
5184
    41,     40,     21517,  41,     40,     29305,  41,     40,     36001,
5185
    41,     40,     31069,  41,     40,     21172,  41,     40,     20195,
5186
    41,     40,     21628,  41,     40,     23398,  41,     40,     30435,
5187
    41,     40,     20225,  41,     40,     36039,  41,     40,     21332,
5188
    41,     40,     31085,  41,     40,     20241,  41,     40,     33258,
5189
    41,     40,     33267,  41,     21839,  24188,  25991,  31631,  80,
5190
    84,     69,     50,     49,     50,     50,     50,     51,     50,
5191
    52,     50,     53,     50,     54,     50,     55,     50,     56,
5192
    50,     57,     51,     48,     51,     49,     51,     50,     51,
5193
    51,     51,     52,     51,     53,     4352,   4354,   4355,   4357,
5194
    4358,   4359,   4361,   4363,   4364,   4366,   4367,   4368,   4369,
5195
    4370,   4352,   4449,   4354,   4449,   4355,   4449,   4357,   4449,
5196
    4358,   4449,   4359,   4449,   4361,   4449,   4363,   4449,   4364,
5197
    4449,   4366,   4449,   4367,   4449,   4368,   4449,   4369,   4449,
5198
    4370,   4449,   4366,   4449,   4535,   4352,   4457,   4364,   4462,
5199
    4363,   4468,   4363,   4462,   19968,  20108,  19977,  22235,  20116,
5200
    20845,  19971,  20843,  20061,  21313,  26376,  28779,  27700,  26408,
5201
    37329,  22303,  26085,  26666,  26377,  31038,  21517,  29305,  36001,
5202
    31069,  21172,  31192,  30007,  22899,  36969,  20778,  21360,  27880,
5203
    38917,  20241,  20889,  27491,  19978,  20013,  19979,  24038,  21491,
5204
    21307,  23447,  23398,  30435,  20225,  36039,  21332,  22812,  51,
5205
    54,     51,     55,     51,     56,     51,     57,     52,     48,
5206
    52,     49,     52,     50,     52,     51,     52,     52,     52,
5207
    53,     52,     54,     52,     55,     52,     56,     52,     57,
5208
    53,     48,     49,     26376,  50,     26376,  51,     26376,  52,
5209
    26376,  53,     26376,  54,     26376,  55,     26376,  56,     26376,
5210
    57,     26376,  49,     48,     26376,  49,     49,     26376,  49,
5211
    50,     26376,  72,     103,    101,    114,    103,    101,    86,
5212
    76,     84,     68,     12450,  12452,  12454,  12456,  12458,  12459,
5213
    12461,  12463,  12465,  12467,  12469,  12471,  12473,  12475,  12477,
5214
    12479,  12481,  12484,  12486,  12488,  12490,  12491,  12492,  12493,
5215
    12494,  12495,  12498,  12501,  12504,  12507,  12510,  12511,  12512,
5216
    12513,  12514,  12516,  12518,  12520,  12521,  12522,  12523,  12524,
5217
    12525,  12527,  12528,  12529,  12530,  20196,  21644,  12450,  12495,
5218
    12442,  12540,  12488,  12450,  12523,  12501,  12449,  12450,  12531,
5219
    12504,  12442,  12450,  12450,  12540,  12523,  12452,  12491,  12531,
5220
    12463,  12441,  12452,  12531,  12481,  12454,  12457,  12531,  12456,
5221
    12473,  12463,  12540,  12488,  12441,  12456,  12540,  12459,  12540,
5222
    12458,  12531,  12473,  12458,  12540,  12512,  12459,  12452,  12522,
5223
    12459,  12521,  12483,  12488,  12459,  12525,  12522,  12540,  12459,
5224
    12441,  12525,  12531,  12459,  12441,  12531,  12510,  12461,  12441,
5225
    12459,  12441,  12461,  12441,  12491,  12540,  12461,  12517,  12522,
5226
    12540,  12461,  12441,  12523,  12479,  12441,  12540,  12461,  12525,
5227
    12461,  12525,  12463,  12441,  12521,  12512,  12461,  12525,  12513,
5228
    12540,  12488,  12523,  12461,  12525,  12527,  12483,  12488,  12463,
5229
    12441,  12521,  12512,  12463,  12441,  12521,  12512,  12488,  12531,
5230
    12463,  12523,  12475,  12441,  12452,  12525,  12463,  12525,  12540,
5231
    12493,  12465,  12540,  12473,  12467,  12523,  12490,  12467,  12540,
5232
    12507,  12442,  12469,  12452,  12463,  12523,  12469,  12531,  12481,
5233
    12540,  12512,  12471,  12522,  12531,  12463,  12441,  12475,  12531,
5234
    12481,  12475,  12531,  12488,  12479,  12441,  12540,  12473,  12486,
5235
    12441,  12471,  12488,  12441,  12523,  12488,  12531,  12490,  12494,
5236
    12494,  12483,  12488,  12495,  12452,  12484,  12495,  12442,  12540,
5237
    12475,  12531,  12488,  12495,  12442,  12540,  12484,  12495,  12441,
5238
    12540,  12524,  12523,  12498,  12442,  12450,  12473,  12488,  12523,
5239
    12498,  12442,  12463,  12523,  12498,  12442,  12467,  12498,  12441,
5240
    12523,  12501,  12449,  12521,  12483,  12488,  12441,  12501,  12451,
5241
    12540,  12488,  12501,  12441,  12483,  12471,  12455,  12523,  12501,
5242
    12521,  12531,  12504,  12463,  12479,  12540,  12523,  12504,  12442,
5243
    12477,  12504,  12442,  12491,  12498,  12504,  12523,  12484,  12504,
5244
    12442,  12531,  12473,  12504,  12442,  12540,  12471,  12441,  12504,
5245
    12441,  12540,  12479,  12507,  12442,  12452,  12531,  12488,  12507,
5246
    12441,  12523,  12488,  12507,  12531,  12507,  12442,  12531,  12488,
5247
    12441,  12507,  12540,  12523,  12507,  12540,  12531,  12510,  12452,
5248
    12463,  12525,  12510,  12452,  12523,  12510,  12483,  12495,  12510,
5249
    12523,  12463,  12510,  12531,  12471,  12519,  12531,  12511,  12463,
5250
    12525,  12531,  12511,  12522,  12511,  12522,  12495,  12441,  12540,
5251
    12523,  12513,  12459,  12441,  12513,  12459,  12441,  12488,  12531,
5252
    12513,  12540,  12488,  12523,  12516,  12540,  12488,  12441,  12516,
5253
    12540,  12523,  12518,  12450,  12531,  12522,  12483,  12488,  12523,
5254
    12522,  12521,  12523,  12498,  12442,  12540,  12523,  12540,  12501,
5255
    12441,  12523,  12524,  12512,  12524,  12531,  12488,  12465,  12441,
5256
    12531,  12527,  12483,  12488,  48,     28857,  49,     28857,  50,
5257
    28857,  51,     28857,  52,     28857,  53,     28857,  54,     28857,
5258
    55,     28857,  56,     28857,  57,     28857,  49,     48,     28857,
5259
    49,     49,     28857,  49,     50,     28857,  49,     51,     28857,
5260
    49,     52,     28857,  49,     53,     28857,  49,     54,     28857,
5261
    49,     55,     28857,  49,     56,     28857,  49,     57,     28857,
5262
    50,     48,     28857,  50,     49,     28857,  50,     50,     28857,
5263
    50,     51,     28857,  50,     52,     28857,  104,    80,     97,
5264
    100,    97,     65,     85,     98,     97,     114,    111,    86,
5265
    112,    99,     100,    109,    100,    109,    50,     100,    109,
5266
    51,     73,     85,     24179,  25104,  26157,  21644,  22823,  27491,
5267
    26126,  27835,  26666,  24335,  20250,  31038,  112,    65,     110,
5268
    65,     956,    65,     109,    65,     107,    65,     75,     66,
5269
    77,     66,     71,     66,     99,     97,     108,    107,    99,
5270
    97,     108,    112,    70,     110,    70,     956,    70,     956,
5271
    103,    109,    103,    107,    103,    72,     122,    107,    72,
5272
    122,    77,     72,     122,    71,     72,     122,    84,     72,
5273
    122,    956,    108,    109,    108,    100,    108,    107,    108,
5274
    102,    109,    110,    109,    956,    109,    109,    109,    99,
5275
    109,    107,    109,    109,    109,    50,     99,     109,    50,
5276
    109,    50,     107,    109,    50,     109,    109,    51,     99,
5277
    109,    51,     109,    51,     107,    109,    51,     109,    8725,
5278
    115,    109,    8725,   115,    50,     80,     97,     107,    80,
5279
    97,     77,     80,     97,     71,     80,     97,     114,    97,
5280
    100,    114,    97,     100,    8725,   115,    114,    97,     100,
5281
    8725,   115,    50,     112,    115,    110,    115,    956,    115,
5282
    109,    115,    112,    86,     110,    86,     956,    86,     109,
5283
    86,     107,    86,     77,     86,     112,    87,     110,    87,
5284
    956,    87,     109,    87,     107,    87,     77,     87,     107,
5285
    937,    77,     937,    97,     46,     109,    46,     66,     113,
5286
    99,     99,     99,     100,    67,     8725,   107,    103,    67,
5287
    111,    46,     100,    66,     71,     121,    104,    97,     72,
5288
    80,     105,    110,    75,     75,     75,     77,     107,    116,
5289
    108,    109,    108,    110,    108,    111,    103,    108,    120,
5290
    109,    98,     109,    105,    108,    109,    111,    108,    80,
5291
    72,     112,    46,     109,    46,     80,     80,     77,     80,
5292
    82,     115,    114,    83,     118,    87,     98,     86,     8725,
5293
    109,    65,     8725,   109,    49,     26085,  50,     26085,  51,
5294
    26085,  52,     26085,  53,     26085,  54,     26085,  55,     26085,
5295
    56,     26085,  57,     26085,  49,     48,     26085,  49,     49,
5296
    26085,  49,     50,     26085,  49,     51,     26085,  49,     52,
5297
    26085,  49,     53,     26085,  49,     54,     26085,  49,     55,
5298
    26085,  49,     56,     26085,  49,     57,     26085,  50,     48,
5299
    26085,  50,     49,     26085,  50,     50,     26085,  50,     51,
5300
    26085,  50,     52,     26085,  50,     53,     26085,  50,     54,
5301
    26085,  50,     55,     26085,  50,     56,     26085,  50,     57,
5302
    26085,  51,     48,     26085,  51,     49,     26085,  103,    97,
5303
    108,    1098,   1100,   42863,  67,     70,     81,     294,    339,
5304
    42791,  43831,  619,    43858,  653,    35912,  26356,  36554,  36040,
5305
    28369,  20018,  21477,  40860,  40860,  22865,  37329,  21895,  22856,
5306
    25078,  30313,  32645,  34367,  34746,  35064,  37007,  27138,  27931,
5307
    28889,  29662,  33853,  37226,  39409,  20098,  21365,  27396,  29211,
5308
    34349,  40478,  23888,  28651,  34253,  35172,  25289,  33240,  34847,
5309
    24266,  26391,  28010,  29436,  37070,  20358,  20919,  21214,  25796,
5310
    27347,  29200,  30439,  32769,  34310,  34396,  36335,  38706,  39791,
5311
    40442,  30860,  31103,  32160,  33737,  37636,  40575,  35542,  22751,
5312
    24324,  31840,  32894,  29282,  30922,  36034,  38647,  22744,  23650,
5313
    27155,  28122,  28431,  32047,  32311,  38475,  21202,  32907,  20956,
5314
    20940,  31260,  32190,  33777,  38517,  35712,  25295,  27138,  35582,
5315
    20025,  23527,  24594,  29575,  30064,  21271,  30971,  20415,  24489,
5316
    19981,  27852,  25976,  32034,  21443,  22622,  30465,  33865,  35498,
5317
    27578,  36784,  27784,  25342,  33509,  25504,  30053,  20142,  20841,
5318
    20937,  26753,  31975,  33391,  35538,  37327,  21237,  21570,  22899,
5319
    24300,  26053,  28670,  31018,  38317,  39530,  40599,  40654,  21147,
5320
    26310,  27511,  36706,  24180,  24976,  25088,  25754,  28451,  29001,
5321
    29833,  31178,  32244,  32879,  36646,  34030,  36899,  37706,  21015,
5322
    21155,  21693,  28872,  35010,  35498,  24265,  24565,  25467,  27566,
5323
    31806,  29557,  20196,  22265,  23527,  23994,  24604,  29618,  29801,
5324
    32666,  32838,  37428,  38646,  38728,  38936,  20363,  31150,  37300,
5325
    38584,  24801,  20102,  20698,  23534,  23615,  26009,  27138,  29134,
5326
    30274,  34044,  36988,  40845,  26248,  38446,  21129,  26491,  26611,
5327
    27969,  28316,  29705,  30041,  30827,  32016,  39006,  20845,  25134,
5328
    38520,  20523,  23833,  28138,  36650,  24459,  24900,  26647,  29575,
5329
    38534,  21033,  21519,  23653,  26131,  26446,  26792,  27877,  29702,
5330
    30178,  32633,  35023,  35041,  37324,  38626,  21311,  28346,  21533,
5331
    29136,  29848,  34298,  38563,  40023,  40607,  26519,  28107,  33256,
5332
    31435,  31520,  31890,  29376,  28825,  35672,  20160,  33590,  21050,
5333
    20999,  24230,  25299,  31958,  23429,  27934,  26292,  36667,  34892,
5334
    38477,  35211,  24275,  20800,  21952,  22618,  26228,  20958,  29482,
5335
    30410,  31036,  31070,  31077,  31119,  38742,  31934,  32701,  34322,
5336
    35576,  36920,  37117,  39151,  39164,  39208,  40372,  37086,  38583,
5337
    20398,  20711,  20813,  21193,  21220,  21329,  21917,  22022,  22120,
5338
    22592,  22696,  23652,  23662,  24724,  24936,  24974,  25074,  25935,
5339
    26082,  26257,  26757,  28023,  28186,  28450,  29038,  29227,  29730,
5340
    30865,  31038,  31049,  31048,  31056,  31062,  31069,  31117,  31118,
5341
    31296,  31361,  31680,  32244,  32265,  32321,  32626,  32773,  33261,
5342
    33401,  33401,  33879,  35088,  35222,  35585,  35641,  36051,  36104,
5343
    36790,  36920,  38627,  38911,  38971,  24693,  148206, 33304,  20006,
5344
    20917,  20840,  20352,  20805,  20864,  21191,  21242,  21917,  21845,
5345
    21913,  21986,  22618,  22707,  22852,  22868,  23138,  23336,  24274,
5346
    24281,  24425,  24493,  24792,  24910,  24840,  24974,  24928,  25074,
5347
    25140,  25540,  25628,  25682,  25942,  26228,  26391,  26395,  26454,
5348
    27513,  27578,  27969,  28379,  28363,  28450,  28702,  29038,  30631,
5349
    29237,  29359,  29482,  29809,  29958,  30011,  30237,  30239,  30410,
5350
    30427,  30452,  30538,  30528,  30924,  31409,  31680,  31867,  32091,
5351
    32244,  32574,  32773,  33618,  33775,  34681,  35137,  35206,  35222,
5352
    35519,  35576,  35531,  35585,  35582,  35565,  35641,  35722,  36104,
5353
    36664,  36978,  37273,  37494,  38524,  38627,  38742,  38875,  38911,
5354
    38923,  38971,  39698,  40860,  141386, 141380, 144341, 15261,  16408,
5355
    16441,  152137, 154832, 163539, 40771,  40846,  102,    102,    102,
5356
    105,    102,    108,    102,    102,    105,    102,    102,    108,
5357
    115,    116,    115,    116,    1396,   1398,   1396,   1381,   1396,
5358
    1387,   1406,   1398,   1396,   1389,   1497,   1460,   1522,   1463,
5359
    1506,   1488,   1491,   1492,   1499,   1500,   1501,   1512,   1514,
5360
    43,     1513,   1473,   1513,   1474,   1513,   1468,   1473,   1513,
5361
    1468,   1474,   1488,   1463,   1488,   1464,   1488,   1468,   1489,
5362
    1468,   1490,   1468,   1491,   1468,   1492,   1468,   1493,   1468,
5363
    1494,   1468,   1496,   1468,   1497,   1468,   1498,   1468,   1499,
5364
    1468,   1500,   1468,   1502,   1468,   1504,   1468,   1505,   1468,
5365
    1507,   1468,   1508,   1468,   1510,   1468,   1511,   1468,   1512,
5366
    1468,   1513,   1468,   1514,   1468,   1493,   1465,   1489,   1471,
5367
    1499,   1471,   1508,   1471,   1488,   1500,   1649,   1649,   1659,
5368
    1659,   1659,   1659,   1662,   1662,   1662,   1662,   1664,   1664,
5369
    1664,   1664,   1658,   1658,   1658,   1658,   1663,   1663,   1663,
5370
    1663,   1657,   1657,   1657,   1657,   1700,   1700,   1700,   1700,
5371
    1702,   1702,   1702,   1702,   1668,   1668,   1668,   1668,   1667,
5372
    1667,   1667,   1667,   1670,   1670,   1670,   1670,   1671,   1671,
5373
    1671,   1671,   1677,   1677,   1676,   1676,   1678,   1678,   1672,
5374
    1672,   1688,   1688,   1681,   1681,   1705,   1705,   1705,   1705,
5375
    1711,   1711,   1711,   1711,   1715,   1715,   1715,   1715,   1713,
5376
    1713,   1713,   1713,   1722,   1722,   1723,   1723,   1723,   1723,
5377
    1749,   1620,   1749,   1620,   1729,   1729,   1729,   1729,   1726,
5378
    1726,   1726,   1726,   1746,   1746,   1746,   1620,   1746,   1620,
5379
    1709,   1709,   1709,   1709,   1735,   1735,   1734,   1734,   1736,
5380
    1736,   1735,   1652,   1739,   1739,   1733,   1733,   1737,   1737,
5381
    1744,   1744,   1744,   1744,   1609,   1609,   1610,   1620,   1575,
5382
    1610,   1620,   1575,   1610,   1620,   1749,   1610,   1620,   1749,
5383
    1610,   1620,   1608,   1610,   1620,   1608,   1610,   1620,   1735,
5384
    1610,   1620,   1735,   1610,   1620,   1734,   1610,   1620,   1734,
5385
    1610,   1620,   1736,   1610,   1620,   1736,   1610,   1620,   1744,
5386
    1610,   1620,   1744,   1610,   1620,   1744,   1610,   1620,   1609,
5387
    1610,   1620,   1609,   1610,   1620,   1609,   1740,   1740,   1740,
5388
    1740,   1610,   1620,   1580,   1610,   1620,   1581,   1610,   1620,
5389
    1605,   1610,   1620,   1609,   1610,   1620,   1610,   1576,   1580,
5390
    1576,   1581,   1576,   1582,   1576,   1605,   1576,   1609,   1576,
5391
    1610,   1578,   1580,   1578,   1581,   1578,   1582,   1578,   1605,
5392
    1578,   1609,   1578,   1610,   1579,   1580,   1579,   1605,   1579,
5393
    1609,   1579,   1610,   1580,   1581,   1580,   1605,   1581,   1580,
5394
    1581,   1605,   1582,   1580,   1582,   1581,   1582,   1605,   1587,
5395
    1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,   1581,
5396
    1589,   1605,   1590,   1580,   1590,   1581,   1590,   1582,   1590,
5397
    1605,   1591,   1581,   1591,   1605,   1592,   1605,   1593,   1580,
5398
    1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,   1601,
5399
    1581,   1601,   1582,   1601,   1605,   1601,   1609,   1601,   1610,
5400
    1602,   1581,   1602,   1605,   1602,   1609,   1602,   1610,   1603,
5401
    1575,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5402
    1603,   1605,   1603,   1609,   1603,   1610,   1604,   1580,   1604,
5403
    1581,   1604,   1582,   1604,   1605,   1604,   1609,   1604,   1610,
5404
    1605,   1580,   1605,   1581,   1605,   1582,   1605,   1605,   1605,
5405
    1609,   1605,   1610,   1606,   1580,   1606,   1581,   1606,   1582,
5406
    1606,   1605,   1606,   1609,   1606,   1610,   1607,   1580,   1607,
5407
    1605,   1607,   1609,   1607,   1610,   1610,   1580,   1610,   1581,
5408
    1610,   1582,   1610,   1605,   1610,   1609,   1610,   1610,   1584,
5409
    1648,   1585,   1648,   1609,   1648,   32,     1612,   1617,   32,
5410
    1613,   1617,   32,     1614,   1617,   32,     1615,   1617,   32,
5411
    1616,   1617,   32,     1617,   1648,   1610,   1620,   1585,   1610,
5412
    1620,   1586,   1610,   1620,   1605,   1610,   1620,   1606,   1610,
5413
    1620,   1609,   1610,   1620,   1610,   1576,   1585,   1576,   1586,
5414
    1576,   1605,   1576,   1606,   1576,   1609,   1576,   1610,   1578,
5415
    1585,   1578,   1586,   1578,   1605,   1578,   1606,   1578,   1609,
5416
    1578,   1610,   1579,   1585,   1579,   1586,   1579,   1605,   1579,
5417
    1606,   1579,   1609,   1579,   1610,   1601,   1609,   1601,   1610,
5418
    1602,   1609,   1602,   1610,   1603,   1575,   1603,   1604,   1603,
5419
    1605,   1603,   1609,   1603,   1610,   1604,   1605,   1604,   1609,
5420
    1604,   1610,   1605,   1575,   1605,   1605,   1606,   1585,   1606,
5421
    1586,   1606,   1605,   1606,   1606,   1606,   1609,   1606,   1610,
5422
    1609,   1648,   1610,   1585,   1610,   1586,   1610,   1605,   1610,
5423
    1606,   1610,   1609,   1610,   1610,   1610,   1620,   1580,   1610,
5424
    1620,   1581,   1610,   1620,   1582,   1610,   1620,   1605,   1610,
5425
    1620,   1607,   1576,   1580,   1576,   1581,   1576,   1582,   1576,
5426
    1605,   1576,   1607,   1578,   1580,   1578,   1581,   1578,   1582,
5427
    1578,   1605,   1578,   1607,   1579,   1605,   1580,   1581,   1580,
5428
    1605,   1581,   1580,   1581,   1605,   1582,   1580,   1582,   1605,
5429
    1587,   1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,
5430
    1581,   1589,   1582,   1589,   1605,   1590,   1580,   1590,   1581,
5431
    1590,   1582,   1590,   1605,   1591,   1581,   1592,   1605,   1593,
5432
    1580,   1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,
5433
    1601,   1581,   1601,   1582,   1601,   1605,   1602,   1581,   1602,
5434
    1605,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5435
    1603,   1605,   1604,   1580,   1604,   1581,   1604,   1582,   1604,
5436
    1605,   1604,   1607,   1605,   1580,   1605,   1581,   1605,   1582,
5437
    1605,   1605,   1606,   1580,   1606,   1581,   1606,   1582,   1606,
5438
    1605,   1606,   1607,   1607,   1580,   1607,   1605,   1607,   1648,
5439
    1610,   1580,   1610,   1581,   1610,   1582,   1610,   1605,   1610,
5440
    1607,   1610,   1620,   1605,   1610,   1620,   1607,   1576,   1605,
5441
    1576,   1607,   1578,   1605,   1578,   1607,   1579,   1605,   1579,
5442
    1607,   1587,   1605,   1587,   1607,   1588,   1605,   1588,   1607,
5443
    1603,   1604,   1603,   1605,   1604,   1605,   1606,   1605,   1606,
5444
    1607,   1610,   1605,   1610,   1607,   1600,   1614,   1617,   1600,
5445
    1615,   1617,   1600,   1616,   1617,   1591,   1609,   1591,   1610,
5446
    1593,   1609,   1593,   1610,   1594,   1609,   1594,   1610,   1587,
5447
    1609,   1587,   1610,   1588,   1609,   1588,   1610,   1581,   1609,
5448
    1581,   1610,   1580,   1609,   1580,   1610,   1582,   1609,   1582,
5449
    1610,   1589,   1609,   1589,   1610,   1590,   1609,   1590,   1610,
5450
    1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1588,
5451
    1585,   1587,   1585,   1589,   1585,   1590,   1585,   1591,   1609,
5452
    1591,   1610,   1593,   1609,   1593,   1610,   1594,   1609,   1594,
5453
    1610,   1587,   1609,   1587,   1610,   1588,   1609,   1588,   1610,
5454
    1581,   1609,   1581,   1610,   1580,   1609,   1580,   1610,   1582,
5455
    1609,   1582,   1610,   1589,   1609,   1589,   1610,   1590,   1609,
5456
    1590,   1610,   1588,   1580,   1588,   1581,   1588,   1582,   1588,
5457
    1605,   1588,   1585,   1587,   1585,   1589,   1585,   1590,   1585,
5458
    1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1587,
5459
    1607,   1588,   1607,   1591,   1605,   1587,   1580,   1587,   1581,
5460
    1587,   1582,   1588,   1580,   1588,   1581,   1588,   1582,   1591,
5461
    1605,   1592,   1605,   1575,   1611,   1575,   1611,   1578,   1580,
5462
    1605,   1578,   1581,   1580,   1578,   1581,   1580,   1578,   1581,
5463
    1605,   1578,   1582,   1605,   1578,   1605,   1580,   1578,   1605,
5464
    1581,   1578,   1605,   1582,   1580,   1605,   1581,   1580,   1605,
5465
    1581,   1581,   1605,   1610,   1581,   1605,   1609,   1587,   1581,
5466
    1580,   1587,   1580,   1581,   1587,   1580,   1609,   1587,   1605,
5467
    1581,   1587,   1605,   1581,   1587,   1605,   1580,   1587,   1605,
5468
    1605,   1587,   1605,   1605,   1589,   1581,   1581,   1589,   1581,
5469
    1581,   1589,   1605,   1605,   1588,   1581,   1605,   1588,   1581,
5470
    1605,   1588,   1580,   1610,   1588,   1605,   1582,   1588,   1605,
5471
    1582,   1588,   1605,   1605,   1588,   1605,   1605,   1590,   1581,
5472
    1609,   1590,   1582,   1605,   1590,   1582,   1605,   1591,   1605,
5473
    1581,   1591,   1605,   1581,   1591,   1605,   1605,   1591,   1605,
5474
    1610,   1593,   1580,   1605,   1593,   1605,   1605,   1593,   1605,
5475
    1605,   1593,   1605,   1609,   1594,   1605,   1605,   1594,   1605,
5476
    1610,   1594,   1605,   1609,   1601,   1582,   1605,   1601,   1582,
5477
    1605,   1602,   1605,   1581,   1602,   1605,   1605,   1604,   1581,
5478
    1605,   1604,   1581,   1610,   1604,   1581,   1609,   1604,   1580,
5479
    1580,   1604,   1580,   1580,   1604,   1582,   1605,   1604,   1582,
5480
    1605,   1604,   1605,   1581,   1604,   1605,   1581,   1605,   1581,
5481
    1580,   1605,   1581,   1605,   1605,   1581,   1610,   1605,   1580,
5482
    1581,   1605,   1580,   1605,   1605,   1582,   1580,   1605,   1582,
5483
    1605,   1605,   1580,   1582,   1607,   1605,   1580,   1607,   1605,
5484
    1605,   1606,   1581,   1605,   1606,   1581,   1609,   1606,   1580,
5485
    1605,   1606,   1580,   1605,   1606,   1580,   1609,   1606,   1605,
5486
    1610,   1606,   1605,   1609,   1610,   1605,   1605,   1610,   1605,
5487
    1605,   1576,   1582,   1610,   1578,   1580,   1610,   1578,   1580,
5488
    1609,   1578,   1582,   1610,   1578,   1582,   1609,   1578,   1605,
5489
    1610,   1578,   1605,   1609,   1580,   1605,   1610,   1580,   1581,
5490
    1609,   1580,   1605,   1609,   1587,   1582,   1609,   1589,   1581,
5491
    1610,   1588,   1581,   1610,   1590,   1581,   1610,   1604,   1580,
5492
    1610,   1604,   1605,   1610,   1610,   1581,   1610,   1610,   1580,
5493
    1610,   1610,   1605,   1610,   1605,   1605,   1610,   1602,   1605,
5494
    1610,   1606,   1581,   1610,   1602,   1605,   1581,   1604,   1581,
5495
    1605,   1593,   1605,   1610,   1603,   1605,   1610,   1606,   1580,
5496
    1581,   1605,   1582,   1610,   1604,   1580,   1605,   1603,   1605,
5497
    1605,   1604,   1580,   1605,   1606,   1580,   1581,   1580,   1581,
5498
    1610,   1581,   1580,   1610,   1605,   1580,   1610,   1601,   1605,
5499
    1610,   1576,   1581,   1610,   1603,   1605,   1605,   1593,   1580,
5500
    1605,   1589,   1605,   1605,   1587,   1582,   1610,   1606,   1580,
5501
    1610,   1589,   1604,   1746,   1602,   1604,   1746,   1575,   1604,
5502
    1604,   1607,   1575,   1603,   1576,   1585,   1605,   1581,   1605,
5503
    1583,   1589,   1604,   1593,   1605,   1585,   1587,   1608,   1604,
5504
    1593,   1604,   1610,   1607,   1608,   1587,   1604,   1605,   1589,
5505
    1604,   1609,   1589,   1604,   1609,   32,     1575,   1604,   1604,
5506
    1607,   32,     1593,   1604,   1610,   1607,   32,     1608,   1587,
5507
    1604,   1605,   1580,   1604,   32,     1580,   1604,   1575,   1604,
5508
    1607,   1585,   1740,   1575,   1604,   44,     12289,  12290,  58,
5509
    59,     33,     63,     12310,  12311,  46,     46,     46,     46,
5510
    46,     8212,   8211,   95,     95,     40,     41,     123,    125,
5511
    12308,  12309,  12304,  12305,  12298,  12299,  12296,  12297,  12300,
5512
    12301,  12302,  12303,  91,     93,     32,     773,    32,     773,
5513
    32,     773,    32,     773,    95,     95,     95,     44,     12289,
5514
    46,     59,     58,     63,     33,     8212,   40,     41,     123,
5515
    125,    12308,  12309,  35,     38,     42,     43,     45,     60,
5516
    62,     61,     92,     36,     37,     64,     32,     1611,   1600,
5517
    1611,   32,     1612,   32,     1613,   32,     1614,   1600,   1614,
5518
    32,     1615,   1600,   1615,   32,     1616,   1600,   1616,   32,
5519
    1617,   1600,   1617,   32,     1618,   1600,   1618,   1569,   1575,
5520
    1619,   1575,   1619,   1575,   1620,   1575,   1620,   1608,   1620,
5521
    1608,   1620,   1575,   1621,   1575,   1621,   1610,   1620,   1610,
5522
    1620,   1610,   1620,   1610,   1620,   1575,   1575,   1576,   1576,
5523
    1576,   1576,   1577,   1577,   1578,   1578,   1578,   1578,   1579,
5524
    1579,   1579,   1579,   1580,   1580,   1580,   1580,   1581,   1581,
5525
    1581,   1581,   1582,   1582,   1582,   1582,   1583,   1583,   1584,
5526
    1584,   1585,   1585,   1586,   1586,   1587,   1587,   1587,   1587,
5527
    1588,   1588,   1588,   1588,   1589,   1589,   1589,   1589,   1590,
5528
    1590,   1590,   1590,   1591,   1591,   1591,   1591,   1592,   1592,
5529
    1592,   1592,   1593,   1593,   1593,   1593,   1594,   1594,   1594,
5530
    1594,   1601,   1601,   1601,   1601,   1602,   1602,   1602,   1602,
5531
    1603,   1603,   1603,   1603,   1604,   1604,   1604,   1604,   1605,
5532
    1605,   1605,   1605,   1606,   1606,   1606,   1606,   1607,   1607,
5533
    1607,   1607,   1608,   1608,   1609,   1609,   1610,   1610,   1610,
5534
    1610,   1604,   1575,   1619,   1604,   1575,   1619,   1604,   1575,
5535
    1620,   1604,   1575,   1620,   1604,   1575,   1621,   1604,   1575,
5536
    1621,   1604,   1575,   1604,   1575,   33,     34,     35,     36,
5537
    37,     38,     39,     40,     41,     42,     43,     44,     45,
5538
    46,     47,     48,     49,     50,     51,     52,     53,     54,
5539
    55,     56,     57,     58,     59,     60,     61,     62,     63,
5540
    64,     65,     66,     67,     68,     69,     70,     71,     72,
5541
    73,     74,     75,     76,     77,     78,     79,     80,     81,
5542
    82,     83,     84,     85,     86,     87,     88,     89,     90,
5543
    91,     92,     93,     94,     95,     96,     97,     98,     99,
5544
    100,    101,    102,    103,    104,    105,    106,    107,    108,
5545
    109,    110,    111,    112,    113,    114,    115,    116,    117,
5546
    118,    119,    120,    121,    122,    123,    124,    125,    126,
5547
    10629,  10630,  12290,  12300,  12301,  12289,  12539,  12530,  12449,
5548
    12451,  12453,  12455,  12457,  12515,  12517,  12519,  12483,  12540,
5549
    12450,  12452,  12454,  12456,  12458,  12459,  12461,  12463,  12465,
5550
    12467,  12469,  12471,  12473,  12475,  12477,  12479,  12481,  12484,
5551
    12486,  12488,  12490,  12491,  12492,  12493,  12494,  12495,  12498,
5552
    12501,  12504,  12507,  12510,  12511,  12512,  12513,  12514,  12516,
5553
    12518,  12520,  12521,  12522,  12523,  12524,  12525,  12527,  12531,
5554
    12441,  12442,  4448,   4352,   4353,   4522,   4354,   4524,   4525,
5555
    4355,   4356,   4357,   4528,   4529,   4530,   4531,   4532,   4533,
5556
    4378,   4358,   4359,   4360,   4385,   4361,   4362,   4363,   4364,
5557
    4365,   4366,   4367,   4368,   4369,   4370,   4449,   4450,   4451,
5558
    4452,   4453,   4454,   4455,   4456,   4457,   4458,   4459,   4460,
5559
    4461,   4462,   4463,   4464,   4465,   4466,   4467,   4468,   4469,
5560
    162,    163,    172,    32,     772,    166,    165,    8361,   9474,
5561
    8592,   8593,   8594,   8595,   9632,   9675,   720,    721,    230,
5562
    665,    595,    675,    43878,  677,    676,    598,    599,    7569,
5563
    600,    606,    681,    612,    610,    608,    667,    295,    668,
5564
    615,    644,    682,    683,    620,    122628, 42894,  622,    122629,
5565
    654,    122630, 248,    630,    631,    113,    634,    122632, 637,
5566
    638,    640,    680,    678,    43879,  679,    648,    11377,  655,
5567
    673,    674,    664,    448,    449,    450,    122634, 122654, 69785,
5568
    69818,  69787,  69818,  69797,  69818,  69937,  69927,  69938,  69927,
5569
    70471,  70462,  70471,  70487,  70841,  70842,  70841,  70832,  70841,
5570
    70845,  71096,  71087,  71097,  71087,  71989,  71984,  119127, 119141,
5571
    119128, 119141, 119128, 119141, 119150, 119128, 119141, 119151, 119128,
5572
    119141, 119152, 119128, 119141, 119153, 119128, 119141, 119154, 119225,
5573
    119141, 119226, 119141, 119225, 119141, 119150, 119226, 119141, 119150,
5574
    119225, 119141, 119151, 119226, 119141, 119151, 65,     66,     67,
5575
    68,     69,     70,     71,     72,     73,     74,     75,     76,
5576
    77,     78,     79,     80,     81,     82,     83,     84,     85,
5577
    86,     87,     88,     89,     90,     97,     98,     99,     100,
5578
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5579
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5580
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5581
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5582
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5583
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5584
    103,    105,    106,    107,    108,    109,    110,    111,    112,
5585
    113,    114,    115,    116,    117,    118,    119,    120,    121,
5586
    122,    65,     66,     67,     68,     69,     70,     71,     72,
5587
    73,     74,     75,     76,     77,     78,     79,     80,     81,
5588
    82,     83,     84,     85,     86,     87,     88,     89,     90,
5589
    97,     98,     99,     100,    101,    102,    103,    104,    105,
5590
    106,    107,    108,    109,    110,    111,    112,    113,    114,
5591
    115,    116,    117,    118,    119,    120,    121,    122,    65,
5592
    67,     68,     71,     74,     75,     78,     79,     80,     81,
5593
    83,     84,     85,     86,     87,     88,     89,     90,     97,
5594
    98,     99,     100,    102,    104,    105,    106,    107,    108,
5595
    109,    110,    112,    113,    114,    115,    116,    117,    118,
5596
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5597
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5598
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5599
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5600
    103,    104,    105,    106,    107,    108,    109,    110,    111,
5601
    112,    113,    114,    115,    116,    117,    118,    119,    120,
5602
    121,    122,    65,     66,     68,     69,     70,     71,     74,
5603
    75,     76,     77,     78,     79,     80,     81,     83,     84,
5604
    85,     86,     87,     88,     89,     97,     98,     99,     100,
5605
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5606
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5607
    119,    120,    121,    122,    65,     66,     68,     69,     70,
5608
    71,     73,     74,     75,     76,     77,     79,     83,     84,
5609
    85,     86,     87,     88,     89,     97,     98,     99,     100,
5610
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5611
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5612
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5613
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5614
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5615
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5616
    103,    104,    105,    106,    107,    108,    109,    110,    111,
5617
    112,    113,    114,    115,    116,    117,    118,    119,    120,
5618
    121,    122,    65,     66,     67,     68,     69,     70,     71,
5619
    72,     73,     74,     75,     76,     77,     78,     79,     80,
5620
    81,     82,     83,     84,     85,     86,     87,     88,     89,
5621
    90,     97,     98,     99,     100,    101,    102,    103,    104,
5622
    105,    106,    107,    108,    109,    110,    111,    112,    113,
5623
    114,    115,    116,    117,    118,    119,    120,    121,    122,
5624
    65,     66,     67,     68,     69,     70,     71,     72,     73,
5625
    74,     75,     76,     77,     78,     79,     80,     81,     82,
5626
    83,     84,     85,     86,     87,     88,     89,     90,     97,
5627
    98,     99,     100,    101,    102,    103,    104,    105,    106,
5628
    107,    108,    109,    110,    111,    112,    113,    114,    115,
5629
    116,    117,    118,    119,    120,    121,    122,    65,     66,
5630
    67,     68,     69,     70,     71,     72,     73,     74,     75,
5631
    76,     77,     78,     79,     80,     81,     82,     83,     84,
5632
    85,     86,     87,     88,     89,     90,     97,     98,     99,
5633
    100,    101,    102,    103,    104,    105,    106,    107,    108,
5634
    109,    110,    111,    112,    113,    114,    115,    116,    117,
5635
    118,    119,    120,    121,    122,    65,     66,     67,     68,
5636
    69,     70,     71,     72,     73,     74,     75,     76,     77,
5637
    78,     79,     80,     81,     82,     83,     84,     85,     86,
5638
    87,     88,     89,     90,     97,     98,     99,     100,    101,
5639
    102,    103,    104,    105,    106,    107,    108,    109,    110,
5640
    111,    112,    113,    114,    115,    116,    117,    118,    119,
5641
    120,    121,    122,    65,     66,     67,     68,     69,     70,
5642
    71,     72,     73,     74,     75,     76,     77,     78,     79,
5643
    80,     81,     82,     83,     84,     85,     86,     87,     88,
5644
    89,     90,     97,     98,     99,     100,    101,    102,    103,
5645
    104,    105,    106,    107,    108,    109,    110,    111,    112,
5646
    113,    114,    115,    116,    117,    118,    119,    120,    121,
5647
    122,    305,    567,    913,    914,    915,    916,    917,    918,
5648
    919,    920,    921,    922,    923,    924,    925,    926,    927,
5649
    928,    929,    920,    931,    932,    933,    934,    935,    936,
5650
    937,    8711,   945,    946,    947,    948,    949,    950,    951,
5651
    952,    953,    954,    955,    956,    957,    958,    959,    960,
5652
    961,    962,    963,    964,    965,    966,    967,    968,    969,
5653
    8706,   949,    952,    954,    966,    961,    960,    913,    914,
5654
    915,    916,    917,    918,    919,    920,    921,    922,    923,
5655
    924,    925,    926,    927,    928,    929,    920,    931,    932,
5656
    933,    934,    935,    936,    937,    8711,   945,    946,    947,
5657
    948,    949,    950,    951,    952,    953,    954,    955,    956,
5658
    957,    958,    959,    960,    961,    962,    963,    964,    965,
5659
    966,    967,    968,    969,    8706,   949,    952,    954,    966,
5660
    961,    960,    913,    914,    915,    916,    917,    918,    919,
5661
    920,    921,    922,    923,    924,    925,    926,    927,    928,
5662
    929,    920,    931,    932,    933,    934,    935,    936,    937,
5663
    8711,   945,    946,    947,    948,    949,    950,    951,    952,
5664
    953,    954,    955,    956,    957,    958,    959,    960,    961,
5665
    962,    963,    964,    965,    966,    967,    968,    969,    8706,
5666
    949,    952,    954,    966,    961,    960,    913,    914,    915,
5667
    916,    917,    918,    919,    920,    921,    922,    923,    924,
5668
    925,    926,    927,    928,    929,    920,    931,    932,    933,
5669
    934,    935,    936,    937,    8711,   945,    946,    947,    948,
5670
    949,    950,    951,    952,    953,    954,    955,    956,    957,
5671
    958,    959,    960,    961,    962,    963,    964,    965,    966,
5672
    967,    968,    969,    8706,   949,    952,    954,    966,    961,
5673
    960,    913,    914,    915,    916,    917,    918,    919,    920,
5674
    921,    922,    923,    924,    925,    926,    927,    928,    929,
5675
    920,    931,    932,    933,    934,    935,    936,    937,    8711,
5676
    945,    946,    947,    948,    949,    950,    951,    952,    953,
5677
    954,    955,    956,    957,    958,    959,    960,    961,    962,
5678
    963,    964,    965,    966,    967,    968,    969,    8706,   949,
5679
    952,    954,    966,    961,    960,    988,    989,    48,     49,
5680
    50,     51,     52,     53,     54,     55,     56,     57,     48,
5681
    49,     50,     51,     52,     53,     54,     55,     56,     57,
5682
    48,     49,     50,     51,     52,     53,     54,     55,     56,
5683
    57,     48,     49,     50,     51,     52,     53,     54,     55,
5684
    56,     57,     48,     49,     50,     51,     52,     53,     54,
5685
    55,     56,     57,     1072,   1073,   1074,   1075,   1076,   1077,
5686
    1078,   1079,   1080,   1082,   1083,   1084,   1086,   1087,   1088,
5687
    1089,   1090,   1091,   1092,   1093,   1094,   1095,   1096,   1099,
5688
    1101,   1102,   42633,  1241,   1110,   1112,   1257,   1199,   1231,
5689
    1072,   1073,   1074,   1075,   1076,   1077,   1078,   1079,   1080,
5690
    1082,   1083,   1086,   1087,   1089,   1091,   1092,   1093,   1094,
5691
    1095,   1096,   1098,   1099,   1169,   1110,   1109,   1119,   1195,
5692
    42577,  1201,   1575,   1576,   1580,   1583,   1608,   1586,   1581,
5693
    1591,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5694
    1589,   1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,
5695
    1592,   1594,   1646,   1722,   1697,   1647,   1576,   1580,   1607,
5696
    1581,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5697
    1589,   1602,   1588,   1578,   1579,   1582,   1590,   1594,   1580,
5698
    1581,   1610,   1604,   1606,   1587,   1593,   1589,   1602,   1588,
5699
    1582,   1590,   1594,   1722,   1647,   1576,   1580,   1607,   1581,
5700
    1591,   1610,   1603,   1605,   1606,   1587,   1593,   1601,   1589,
5701
    1602,   1588,   1578,   1579,   1582,   1590,   1592,   1594,   1646,
5702
    1697,   1575,   1576,   1580,   1583,   1607,   1608,   1586,   1581,
5703
    1591,   1610,   1604,   1605,   1606,   1587,   1593,   1601,   1589,
5704
    1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,   1592,
5705
    1594,   1576,   1580,   1583,   1608,   1586,   1581,   1591,   1610,
5706
    1604,   1605,   1606,   1587,   1593,   1601,   1589,   1602,   1585,
5707
    1588,   1578,   1579,   1582,   1584,   1590,   1592,   1594,   48,
5708
    46,     48,     44,     49,     44,     50,     44,     51,     44,
5709
    52,     44,     53,     44,     54,     44,     55,     44,     56,
5710
    44,     57,     44,     40,     65,     41,     40,     66,     41,
5711
    40,     67,     41,     40,     68,     41,     40,     69,     41,
5712
    40,     70,     41,     40,     71,     41,     40,     72,     41,
5713
    40,     73,     41,     40,     74,     41,     40,     75,     41,
5714
    40,     76,     41,     40,     77,     41,     40,     78,     41,
5715
    40,     79,     41,     40,     80,     41,     40,     81,     41,
5716
    40,     82,     41,     40,     83,     41,     40,     84,     41,
5717
    40,     85,     41,     40,     86,     41,     40,     87,     41,
5718
    40,     88,     41,     40,     89,     41,     40,     90,     41,
5719
    12308,  83,     12309,  67,     82,     67,     68,     87,     90,
5720
    65,     66,     67,     68,     69,     70,     71,     72,     73,
5721
    74,     75,     76,     77,     78,     79,     80,     81,     82,
5722
    83,     84,     85,     86,     87,     88,     89,     90,     72,
5723
    86,     77,     86,     83,     68,     83,     83,     80,     80,
5724
    86,     87,     67,     77,     67,     77,     68,     77,     82,
5725
    68,     74,     12411,  12363,  12467,  12467,  12469,  25163,  23383,
5726
    21452,  12486,  12441,  20108,  22810,  35299,  22825,  20132,  26144,
5727
    28961,  26009,  21069,  24460,  20877,  26032,  21021,  32066,  29983,
5728
    36009,  22768,  21561,  28436,  25237,  25429,  19968,  19977,  36938,
5729
    24038,  20013,  21491,  25351,  36208,  25171,  31105,  31354,  21512,
5730
    28288,  26377,  26376,  30003,  21106,  21942,  37197,  12308,  26412,
5731
    12309,  12308,  19977,  12309,  12308,  20108,  12309,  12308,  23433,
5732
    12309,  12308,  28857,  12309,  12308,  25171,  12309,  12308,  30423,
5733
    12309,  12308,  21213,  12309,  12308,  25943,  12309,  24471,  21487,
5734
    48,     49,     50,     51,     52,     53,     54,     55,     56,
5735
    57,     20029,  20024,  20033,  131362, 20320,  20398,  20411,  20482,
5736
    20602,  20633,  20711,  20687,  13470,  132666, 20813,  20820,  20836,
5737
    20855,  132380, 13497,  20839,  20877,  132427, 20887,  20900,  20172,
5738
    20908,  20917,  168415, 20981,  20995,  13535,  21051,  21062,  21106,
5739
    21111,  13589,  21191,  21193,  21220,  21242,  21253,  21254,  21271,
5740
    21321,  21329,  21338,  21363,  21373,  21375,  21375,  21375,  133676,
5741
    28784,  21450,  21471,  133987, 21483,  21489,  21510,  21662,  21560,
5742
    21576,  21608,  21666,  21750,  21776,  21843,  21859,  21892,  21892,
5743
    21913,  21931,  21939,  21954,  22294,  22022,  22295,  22097,  22132,
5744
    20999,  22766,  22478,  22516,  22541,  22411,  22578,  22577,  22700,
5745
    136420, 22770,  22775,  22790,  22810,  22818,  22882,  136872, 136938,
5746
    23020,  23067,  23079,  23000,  23142,  14062,  14076,  23304,  23358,
5747
    23358,  137672, 23491,  23512,  23527,  23539,  138008, 23551,  23558,
5748
    24403,  23586,  14209,  23648,  23662,  23744,  23693,  138724, 23875,
5749
    138726, 23918,  23915,  23932,  24033,  24034,  14383,  24061,  24104,
5750
    24125,  24169,  14434,  139651, 14460,  24240,  24243,  24246,  24266,
5751
    172946, 24318,  140081, 140081, 33281,  24354,  24354,  14535,  144056,
5752
    156122, 24418,  24427,  14563,  24474,  24525,  24535,  24569,  24705,
5753
    14650,  14620,  24724,  141012, 24775,  24904,  24908,  24910,  24908,
5754
    24954,  24974,  25010,  24996,  25007,  25054,  25074,  25078,  25104,
5755
    25115,  25181,  25265,  25300,  25424,  142092, 25405,  25340,  25448,
5756
    25475,  25572,  142321, 25634,  25541,  25513,  14894,  25705,  25726,
5757
    25757,  25719,  14956,  25935,  25964,  143370, 26083,  26360,  26185,
5758
    15129,  26257,  15112,  15076,  20882,  20885,  26368,  26268,  32941,
5759
    17369,  26391,  26395,  26401,  26462,  26451,  144323, 15177,  26618,
5760
    26501,  26706,  26757,  144493, 26766,  26655,  26900,  15261,  26946,
5761
    27043,  27114,  27304,  145059, 27355,  15384,  27425,  145575, 27476,
5762
    15438,  27506,  27551,  27578,  27579,  146061, 138507, 146170, 27726,
5763
    146620, 27839,  27853,  27751,  27926,  27966,  28023,  27969,  28009,
5764
    28024,  28037,  146718, 27956,  28207,  28270,  15667,  28363,  28359,
5765
    147153, 28153,  28526,  147294, 147342, 28614,  28729,  28702,  28699,
5766
    15766,  28746,  28797,  28791,  28845,  132389, 28997,  148067, 29084,
5767
    148395, 29224,  29237,  29264,  149000, 29312,  29333,  149301, 149524,
5768
    29562,  29579,  16044,  29605,  16056,  16056,  29767,  29788,  29809,
5769
    29829,  29898,  16155,  29988,  150582, 30014,  150674, 30064,  139679,
5770
    30224,  151457, 151480, 151620, 16380,  16392,  30452,  151795, 151794,
5771
    151833, 151859, 30494,  30495,  30495,  30538,  16441,  30603,  16454,
5772
    16534,  152605, 30798,  30860,  30924,  16611,  153126, 31062,  153242,
5773
    153285, 31119,  31211,  16687,  31296,  31306,  31311,  153980, 154279,
5774
    154279, 31470,  16898,  154539, 31686,  31689,  16935,  154752, 31954,
5775
    17056,  31976,  31971,  32000,  155526, 32099,  17153,  32199,  32258,
5776
    32325,  17204,  156200, 156231, 17241,  156377, 32634,  156478, 32661,
5777
    32762,  32773,  156890, 156963, 32864,  157096, 32880,  144223, 17365,
5778
    32946,  33027,  17419,  33086,  23221,  157607, 157621, 144275, 144284,
5779
    33281,  33284,  36766,  17515,  33425,  33419,  33437,  21171,  33457,
5780
    33459,  33469,  33510,  158524, 33509,  33565,  33635,  33709,  33571,
5781
    33725,  33767,  33879,  33619,  33738,  33740,  33756,  158774, 159083,
5782
    158933, 17707,  34033,  34035,  34070,  160714, 34148,  159532, 17757,
5783
    17761,  159665, 159954, 17771,  34384,  34396,  34407,  34409,  34473,
5784
    34440,  34574,  34530,  34681,  34600,  34667,  34694,  17879,  34785,
5785
    34817,  17913,  34912,  34915,  161383, 35031,  35038,  17973,  35066,
5786
    13499,  161966, 162150, 18110,  18119,  35488,  35565,  35722,  35925,
5787
    162984, 36011,  36033,  36123,  36215,  163631, 133124, 36299,  36284,
5788
    36336,  133342, 36564,  36664,  165330, 165357, 37012,  37105,  37137,
5789
    165678, 37147,  37432,  37591,  37592,  37500,  37881,  37909,  166906,
5790
    38283,  18837,  38327,  167287, 18918,  38595,  23986,  38691,  168261,
5791
    168474, 19054,  19062,  38880,  168970, 19122,  169110, 38923,  38923,
5792
    38953,  169398, 39138,  19251,  39209,  39335,  39362,  39422,  19406,
5793
    170800, 39698,  40000,  40189,  19662,  19693,  40295,  172238, 19704,
5794
    172293, 172558, 172689, 40635,  19798,  40697,  40702,  40709,  40719,
5795
    40726,  40763,  173568};
5796
5797
const uint8_t canonical_combining_class_index[4352] = {
5798
    0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 0,  0,
5799
    15, 0,  0,  0,  16, 17, 18, 19, 20, 21, 22, 0,  0,  23, 0,  0,  0,  0,  0,
5800
    0,  0,  0,  0,  0,  0,  24, 25, 0,  0,  26, 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,  0,  0,  0,  0,  0,  0,  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,  0,  0,  0,  0,  0,  0,  0,  27, 0,  28, 29, 30,
5807
    31, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5808
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  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,  32, 0,  0,  33, 0,  0,  34, 35, 36, 0,  0,  0,  0,  0,  0,
5812
    37, 0,  0,  38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,  52,
5813
    53, 0,  54, 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,  55, 56, 0,  0,  0,  57, 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,  58, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5822
    0,  0,  0,  0,  0,  0,  0,  0,  0,  59, 60, 0,  0,  0,  0,  0,  0,  0,  0,
5823
    0,  0,  0,  0,  0,  61, 56, 62, 0,  63, 0,  0,  0,  64, 65, 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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6013
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6014
    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,
6016
    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,
6018
    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,
6020
    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,
6022
    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,
6024
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6025
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6026
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6027
    0};
6028
const uint8_t canonical_combining_class_block[67][256] = {
6029
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6030
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6031
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6032
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6033
     0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 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, 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, 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, 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, 0},
6040
    {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6041
     230, 230, 230, 230, 230, 230, 232, 220, 220, 220, 220, 232, 216, 220, 220,
6042
     220, 220, 220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220,
6043
     220, 220, 220, 220, 220, 220, 220, 1,   1,   1,   1,   1,   220, 220, 220,
6044
     220, 230, 230, 230, 230, 230, 230, 230, 230, 240, 230, 220, 220, 220, 230,
6045
     230, 230, 220, 220, 0,   230, 230, 230, 220, 220, 220, 220, 230, 232, 220,
6046
     220, 230, 233, 234, 234, 233, 234, 234, 233, 230, 230, 230, 230, 230, 230,
6047
     230, 230, 230, 230, 230, 230, 230, 0,   0,   0,   0,   0,   0,   0,   0,
6048
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6049
     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,
6051
     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,
6053
     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,   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},
6058
    {0,   0,   0,   0,   0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0,
6060
     0,   0,   0,   0,   0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0,
6062
     0,   0,   0,   0,   0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 230,
6064
     230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6065
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6066
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6067
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6068
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 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},
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,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6073
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6074
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   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
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6079
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 230, 230, 230, 230,
6080
     220, 230, 230, 230, 222, 220, 230, 230, 230, 230, 230, 230, 220, 220, 220,
6081
     220, 220, 220, 230, 230, 220, 230, 230, 222, 228, 230, 10,  11,  12,  13,
6082
     14,  15,  16,  17,  18,  19,  19,  20,  21,  22,  0,   23,  0,   24,  25,
6083
     0,   230, 220, 0,   18,  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},
6088
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6089
     0,   230, 230, 230, 230, 230, 230, 230, 230, 30,  31,  32,  0,   0,   0,
6090
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6091
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6092
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6093
     27,  28,  29,  30,  31,  32,  33,  34,  230, 230, 220, 220, 230, 230, 230,
6094
     230, 230, 220, 230, 230, 220, 0,   0,   0,   0,   0,   0,   0,   0,   0,
6095
     0,   0,   0,   0,   0,   0,   0,   35,  0,   0,   0,   0,   0,   0,   0,
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,   230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230,
6103
     230, 230, 220, 230, 0,   0,   230, 230, 0,   220, 230, 230, 220, 0,   0,
6104
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6105
     0},
6106
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6107
     0,   0,   36,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6108
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6109
     0,   0,   0,   230, 220, 230, 230, 220, 230, 230, 220, 220, 220, 230, 220,
6110
     220, 230, 220, 230, 230, 230, 220, 230, 220, 230, 220, 230, 220, 230, 230,
6111
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6112
     0,   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,   0,
6115
     0,   0,   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,   0,   0,   0,   0,   0,   0,   0,   0,   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,   230, 230, 230, 230, 230,
6122
     230, 230, 220, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 0,
6123
     0},
6124
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6125
     0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 0,   230, 230, 230,
6126
     230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 0,   230, 230, 230, 230,
6127
     230, 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,
6129
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   220,
6130
     220, 220, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6131
     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,
6133
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6134
     0,   0,   230, 220, 220, 220, 230, 230, 230, 230, 0,   0,   0,   0,   0,
6135
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6136
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6137
     0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 230, 220, 220, 220,
6138
     220, 220, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6139
     230, 0,   220, 230, 230, 220, 230, 230, 220, 230, 230, 230, 220, 220, 220,
6140
     27,  28,  29,  230, 230, 230, 220, 230, 230, 220, 220, 230, 230, 230, 230,
6141
     230},
6142
    {0, 0, 0, 0, 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,
6144
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   7,   0,   0,   0, 0, 0,
6145
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0, 0, 230, 220, 230, 230, 0, 0, 0,
6146
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6147
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,
6149
     0, 0, 0, 0, 0, 0, 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, 7,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6151
     0, 0, 0, 0, 0, 0, 0, 9, 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, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6153
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 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, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6157
     0, 0, 0, 0, 0, 9, 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, 0, 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, 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, 7, 0, 0, 0,
6162
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6163
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6164
     0, 0, 0, 0, 0, 0, 0, 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, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6168
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6169
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6174
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6175
     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, 7, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6179
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 84, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6180
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 7, 0, 0, 0,
6184
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,  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, 0, 0, 0, 0, 0, 0,
6186
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0},
6187
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0,
6189
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6190
     0, 0, 0, 0, 0, 9, 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, 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, 0, 0, 0, 0, 0, 0,
6193
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6194
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6195
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 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, 0, 0, 0, 0, 0, 0,
6197
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6198
    {0,   0,   0,   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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6200
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6201
     0,   0,   103, 103, 9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6202
     107, 107, 107, 107, 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, 0, 0, 0,
6204
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6205
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6206
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6207
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6208
     0,   0,   0,   0,   118, 118, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6209
     0,   0,   122, 122, 122, 122, 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, 0, 0, 0,
6211
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6212
     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,   220, 220, 0,   0,   0, 0,
6215
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6216
     0,   0, 0,   0,   0,   0,   0, 0, 220, 0,   220, 0,   216, 0, 0,
6217
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6218
     0,   0, 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,
6220
     0,   0, 0,   0,   0,   0,   0, 0, 129, 130, 0,   132, 0,   0, 0,
6221
     0,   0, 130, 130, 130, 130, 0, 0, 130, 0,   230, 230, 9,   0, 230,
6222
     230, 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,
6224
     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,
6226
     0,   0, 0,   220, 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,
6228
     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,
6230
     0},
6231
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,   0, 0,
6233
     0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 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,   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,   0, 0,
6236
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 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,   0, 0,
6238
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0,   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, 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,
6243
     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,
6245
     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, 230, 230, 230, 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, 0, 0, 0, 0,
6248
     0, 0, 0, 0, 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, 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,
6251
     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,
6253
     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, 9, 9, 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, 9, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6257
     0, 0, 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, 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, 0, 0,
6262
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6263
     0, 0, 0, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6264
     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, 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, 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, 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, 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, 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, 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, 0, 0,
6272
     0, 228, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6274
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6275
     0, 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,   0,   0, 0, 0, 0, 0, 0,
6277
     0, 0, 0, 0, 0, 0, 0, 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, 222, 230, 220, 0, 0, 0, 0, 0, 0,
6279
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6280
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6281
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6282
     0, 0, 0, 0, 0, 0, 0, 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,   0,   0, 0, 0, 0, 0, 0,
6284
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6285
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6286
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6287
     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,   230, 220, 0,   0,   0,   0,   0,
6290
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6291
     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,
6293
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6294
     0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6295
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230,
6296
     230, 230, 230, 230, 230, 0,   0,   220, 0,   0,   0,   0,   0,   0,   0,
6297
     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,
6299
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230,
6300
     230, 220, 220, 220, 220, 220, 220, 230, 230, 220, 0,   220, 220, 230, 230,
6301
     220, 220, 230, 230, 230, 230, 230, 220, 230, 230, 230, 230, 0,   0,   0,
6302
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6303
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6304
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6305
     0},
6306
    {0,   0,   0, 0, 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,   0,   0,   0,   0,
6308
     0,   0,   0, 0, 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, 9, 0,   0,   0,   0,   0,   0,   0,
6310
     0,   0,   0, 0, 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, 230, 220, 230, 230, 230, 230, 230,
6312
     230, 230, 0, 0, 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,   0,   0,   0,   0,
6314
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   9,
6315
     9,   0,   0, 0, 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,   0,   0,   0,   0,
6317
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6318
     0,   0,   7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   9,   9,   0,   0,   0,
6319
     0,   0,   0, 0, 0, 0, 0, 0, 0},
6320
    {0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6321
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6322
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6323
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   7,   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,   230, 230,
6334
     230, 0, 1, 220, 220, 220, 220, 220, 230, 230, 220, 220, 220, 220, 230,
6335
     0,   1, 1, 1,   1,   1,   1,   1,   0,   0,   0,   0,   220, 0,   0,
6336
     0,   0, 0, 0,   230, 0,   0,   0,   230, 230, 0,   0,   0,   0,   0,
6337
     0},
6338
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6339
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6340
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6341
     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,
6343
     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,
6345
     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,
6347
     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,
6349
     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,   230, 230, 220,
6351
     230, 230, 230, 230, 230, 230, 230, 220, 230, 230, 234, 214, 220, 202, 230,
6352
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6353
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6354
     230, 230, 230, 230, 230, 230, 232, 228, 228, 220, 218, 230, 233, 220, 230,
6355
     220},
6356
    {0,   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,
6358
     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,
6360
     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,
6362
     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,
6364
     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,
6366
     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,
6368
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6369
     230, 230, 1, 1, 230, 230, 230, 230, 1,   1,   1, 230, 230, 0,   0,   0,
6370
     0,   230, 0, 0, 0,   1,   1,   230, 220, 230, 1, 1,   220, 220, 220, 220,
6371
     230, 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, 0, 0, 0, 0, 0,   0,   0,
6373
     0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0,   0,   0,
6375
     0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0,   0,   0,
6377
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6378
     0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0,   0,   0,
6380
     0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0,   0,   0,
6382
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230,
6383
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6384
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6385
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6386
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6387
     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,
6389
     0,   0,   0,   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,
6391
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6392
     0,   0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,
6393
     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,   0,   0,
6395
     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,
6397
     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,   230,
6399
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6400
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6401
     230},
6402
    {0, 0, 0,   0,   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, 0, 0, 0, 0,
6404
     0, 0, 218, 228, 232, 222, 224, 224, 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, 0, 0, 0, 0,
6406
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6407
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6408
     0, 0, 0,   0,   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, 8, 8, 0, 0, 0, 0, 0,
6410
     0, 0, 0,   0,   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, 0, 0, 0, 0,
6412
     0, 0, 0,   0,   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, 0, 0, 0, 0,
6414
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0},
6415
    {0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6416
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6417
     0,   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,   0,   0,
6419
     0,   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,   0,
6421
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6422
     0,   0,   0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,
6423
     0,   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,   230, 230,
6425
     0,   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,   0,
6427
     0,   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,   0,
6429
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6430
     230, 230, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0},
6431
    {0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6432
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6433
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   9,
6434
     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,
6436
     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,
6438
     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,
6440
     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,
6442
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6443
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6444
     0,   9,   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,   230,
6446
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6447
     230, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6448
     0},
6449
    {0,   0,   0, 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, 0, 0, 220,
6451
     220, 220, 0, 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, 9, 0, 0, 0, 0,
6453
     0,   0,   0, 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, 0, 0, 0,
6455
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6456
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6457
     0,   0,   0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6458
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6459
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6460
     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,
6462
     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,
6464
     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,
6466
     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,
6468
     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,
6470
     0,   0,   0, 0,   0, 230, 0, 230, 230, 220, 0, 0, 230, 230, 0, 0, 0, 0, 0,
6471
     230, 230, 0, 230, 0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6472
     0,   0,   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, 9,
6474
     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, 0, 0, 0, 0, 0, 0, 0, 0,
6482
     0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6484
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0,
6485
     0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6487
     0, 0, 0, 0, 0, 0, 26, 0, 0, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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,   0,   230, 230, 230, 230, 230, 230, 230, 220, 220, 220, 220, 220, 220,
6500
     220, 230, 230, 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,
6502
     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,
6504
     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,
6506
     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,
6508
     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,
6510
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6511
     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,
6513
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6514
     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, 0, 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, 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, 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, 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, 0, 0,
6525
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 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, 0, 0,
6527
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 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, 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, 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, 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, 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, 0, 0,
6533
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6535
     0, 0, 0, 0, 0, 0, 0, 0, 220, 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},
6537
    {0, 0, 0, 0, 0, 0, 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, 0, 0,
6539
     0, 0, 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, 0, 0,
6541
     0, 0, 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, 230, 230, 230, 230, 230, 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, 0, 0,
6544
     0, 0, 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,   0,   0,   0,   0,   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, 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},
6549
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 220, 0, 230, 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,
6551
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   230, 1, 220, 0,
6552
     0, 0, 0, 9, 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,
6554
     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,
6556
     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,
6558
     0, 0, 0, 0, 0, 0, 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,
6560
     0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 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},
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, 230, 230, 230, 230, 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,   0,   0, 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, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6571
     0, 0, 0, 0, 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,   0, 0, 0, 0,
6573
     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, 0, 0,   0,   0, 0, 0,
6575
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   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,   0,   0, 0, 0,
6577
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6578
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   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,   0,   0, 0, 0,
6580
     0, 0, 0, 0, 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, 230, 230, 0, 0, 0,
6582
     0, 0, 0, 0, 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,   0,   0, 0, 0,
6584
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6585
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220},
6586
    {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,
6588
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6589
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 220, 220,
6590
     230, 230, 230, 220, 230, 220, 220, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6591
     0,   0,   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,
6593
     0,   0,   0,   0,   230, 220, 230, 220, 0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6594
     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,
6596
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6597
     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,
6599
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6600
     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, 0, 0,
6602
     0, 0, 0, 0, 0, 0, 0, 0, 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, 9, 0,
6604
     0, 0, 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, 0, 0,
6606
     0, 0, 0, 0, 0, 0, 0, 9, 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, 0, 0,
6608
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6612
    {230, 230, 230, 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,
6614
     0,   0,   0,   0, 0, 0, 0, 9, 9, 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,
6616
     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, 7, 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, 0, 0, 0, 0, 0,
6619
     0,   0,   0,   0, 0, 0, 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, 9, 0, 0, 0, 0, 0,
6621
     0,   0,   0,   0, 7, 0, 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, 0, 0, 0, 0, 0, 0,
6623
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6624
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6625
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6626
     0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6627
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 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, 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, 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, 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, 0, 7, 9, 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,
6637
     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,   7,   7,   0, 0, 0,
6639
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   9, 0, 0,
6640
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6641
     0,   0,   0,   0,   0,   0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0,
6642
     230, 230, 230, 230, 230, 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,
6644
     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,
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,
6648
     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,
6650
     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, 9, 0, 0, 0, 7,   0,
6654
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0,
6655
     0, 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, 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, 9, 7, 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, 0, 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},
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, 0, 0, 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, 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, 9,
6670
     7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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},
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, 9, 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, 0, 0, 0, 0, 0, 0, 0, 0,
6680
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 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, 0, 0, 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},
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, 9, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6694
     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, 9, 7, 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, 0, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6705
     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, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 7, 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, 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, 9, 0, 0, 0, 0, 0, 0, 0, 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},
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, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
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, 9, 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, 0, 0, 0, 0, 0, 0,
6727
     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, 0, 0, 0, 0, 0, 0, 0, 0, 9, 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, 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, 0, 0, 0, 0, 0, 0, 0,
6738
     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, 7, 0, 9, 9, 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, 9, 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},
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, 9, 9, 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
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0,
6759
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6760
     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, 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, 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, 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, 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, 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, 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, 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, 0, 0, 0, 0,
6769
     0, 0, 0, 0, 0, 0, 0, 0, 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
     1, 1, 1, 1, 1, 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,
6773
     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, 230, 230, 230, 230, 230, 230, 230, 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,
6776
     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,
6778
     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,
6780
     0, 0, 0, 0, 0, 0, 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,
6782
     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,
6784
     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, 0, 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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0,
6795
     6, 6, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0,
6798
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6799
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6800
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6801
     0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6803
     0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 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,
6809
     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,
6811
     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,
6813
     0,   0,   0,   0, 0, 216, 216, 1,   1,   1,   0,   0,   0,   226, 216, 216,
6814
     216, 216, 216, 0, 0, 0,   0,   0,   0,   0,   0,   220, 220, 220, 220, 220,
6815
     220, 220, 220, 0, 0, 230, 230, 230, 230, 230, 220, 220, 0,   0,   0,   0,
6816
     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,   230, 230, 230, 230, 0,   0,
6818
     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,   0,   0,
6820
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6821
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6822
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0},
6823
    {0,   0,   0,   0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0,
6825
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6826
     230, 230, 230, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0,
6828
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6829
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6830
     0,   0,   0,   0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0,
6832
     0,   0,   0,   0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0,
6834
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6835
    {230, 230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 230, 230, 230, 230,
6836
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230, 230,
6837
     230, 230, 230, 230, 0,   230, 230, 0,   230, 230, 230, 230, 230, 0,   0,
6838
     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,
6840
     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,
6842
     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,
6844
     0,   0,   0,   0,   0,   0,   0,   0,   230, 0,   0,   0,   0,   0,   0,
6845
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6846
     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,
6848
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6849
     0,   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,
6851
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6852
     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, 0,   0,   0,   0,   230, 0,
6861
     0, 0, 0, 0, 0, 0, 0, 0, 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,   0,   0,
6863
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0,   0,
6864
     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,   0, 0,
6866
     0, 0, 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,   0, 0,
6868
     0, 0, 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,   0, 0,
6870
     0, 0, 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,   0, 0,
6872
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   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,   0, 0,
6874
     0, 0, 0, 0, 0, 0, 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, 232, 232, 220, 230, 0, 0,
6876
     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, 0,   0,   0,   0,   0,   0,   0,   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, 220, 220, 220, 220, 220, 220, 220, 0, 0, 0, 0, 0,
6888
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6889
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0},
6890
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6891
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6892
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6893
     0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 7, 0, 0, 0, 0, 0,
6894
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6895
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6896
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6897
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6898
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6899
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6900
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6901
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6902
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0}};
6903
6904
const uint8_t composition_index[4352] = {
6905
    0, 1, 2, 3, 4,  5,  6, 5, 5,  7,  5, 8,  9,  10, 5, 5, 11, 5,  5, 5, 5, 5,
6906
    5, 5, 5, 5, 5,  12, 5, 5, 13, 14, 5, 15, 16, 5,  5, 5, 5,  5,  5, 5, 5, 5,
6907
    5, 5, 5, 5, 17, 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, 18, 19, 5, 20, 21, 22, 5, 5, 5,  23, 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,  5, 5, 5, 5,
7088
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7089
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7090
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7091
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7092
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7093
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7094
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7095
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7096
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7097
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7098
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7099
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7100
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7101
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7102
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5};
7103
const uint16_t composition_block[67][257] = {
7104
    {1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7105
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7106
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7107
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7108
     1,   3,   5,   7,   7,   7,   39,  45,  55,  67,  101, 103, 117, 131, 161,
7109
     163, 173, 185, 191, 209, 241, 245, 245, 261, 275, 289, 327, 331, 343, 347,
7110
     365, 377, 377, 377, 377, 377, 377, 377, 409, 415, 425, 437, 471, 473, 487,
7111
     503, 531, 535, 545, 557, 563, 581, 613, 617, 617, 633, 647, 663, 701, 705,
7112
     719, 723, 743, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7113
     755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7114
     755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7115
     755, 755, 755, 755, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7116
     761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7117
     769, 769, 771, 773, 777, 779, 779, 779, 787, 787, 787, 787, 787, 789, 789,
7118
     789, 789, 789, 797, 803, 805, 805, 807, 807, 807, 807, 815, 815, 815, 815,
7119
     815, 815, 823, 823, 825, 827, 831, 833, 833, 833, 841, 841, 841, 841, 841,
7120
     843, 843, 843, 843, 843, 851, 857, 859, 859, 861, 861, 861, 861, 869, 869,
7121
     869, 869},
7122
    {869, 869, 869, 877, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885,
7123
     885, 885, 885, 885, 889, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7124
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7125
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7126
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7127
     893, 893, 897, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901,
7128
     901, 903, 905, 905, 905, 905, 905, 907, 909, 909, 909, 909, 909, 909, 909,
7129
     911, 913, 915, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917,
7130
     917, 917, 917, 917, 917, 917, 917, 917, 919, 919, 919, 919, 919, 919, 919,
7131
     919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919,
7132
     919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 929, 939, 939, 939,
7133
     939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 949, 959, 959, 959,
7134
     959, 959, 959, 959, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7135
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7136
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7137
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 963, 965, 965, 965, 965,
7138
     965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7139
     965, 965},
7140
    {965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7141
     965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7142
     965, 965, 965, 965, 965, 965, 965, 965, 965, 967, 969, 971, 973, 973, 973,
7143
     973, 973, 975, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7144
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7145
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7146
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7147
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7148
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7149
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 979, 979, 979,
7150
     979, 979, 979, 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, 979, 979, 979,
7152
     979, 979, 979, 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, 979, 979, 979,
7154
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7155
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7156
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7157
     979, 979},
7158
    {979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7159
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7160
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7161
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7162
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7163
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7164
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7165
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7166
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7167
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7168
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7169
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7170
     979,  979,  993,  993,  993,  993,  1001, 1001, 1011, 1011, 1025, 1025,
7171
     1025, 1025, 1025, 1025, 1033, 1033, 1035, 1035, 1035, 1035, 1047, 1047,
7172
     1047, 1047, 1057, 1057, 1057, 1059, 1059, 1061, 1061, 1061, 1077, 1077,
7173
     1077, 1077, 1085, 1085, 1097, 1097, 1113, 1113, 1113, 1113, 1113, 1113,
7174
     1121, 1121, 1125, 1125, 1125, 1125, 1141, 1141, 1141, 1141, 1153, 1159,
7175
     1165, 1165, 1165, 1167, 1167, 1167, 1167, 1171, 1171, 1171, 1171, 1171,
7176
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7177
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7178
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7179
     1171, 1171, 1171, 1171, 1171},
7180
    {1171, 1171, 1171, 1171, 1171, 1171, 1171, 1173, 1173, 1173, 1173, 1173,
7181
     1173, 1173, 1173, 1173, 1173, 1177, 1177, 1177, 1179, 1179, 1185, 1189,
7182
     1191, 1199, 1199, 1201, 1201, 1201, 1201, 1203, 1203, 1203, 1203, 1203,
7183
     1211, 1211, 1211, 1211, 1213, 1213, 1213, 1213, 1215, 1215, 1217, 1217,
7184
     1217, 1221, 1221, 1221, 1223, 1223, 1229, 1233, 1235, 1243, 1243, 1245,
7185
     1245, 1245, 1245, 1247, 1247, 1247, 1247, 1247, 1255, 1255, 1255, 1255,
7186
     1257, 1257, 1257, 1257, 1259, 1259, 1261, 1261, 1261, 1261, 1261, 1261,
7187
     1261, 1261, 1261, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7188
     1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7189
     1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1265, 1267, 1267,
7190
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7191
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7192
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7193
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7194
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7195
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7196
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7197
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7198
     1267, 1269, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271,
7199
     1271, 1271, 1271, 1271, 1271, 1273, 1275, 1275, 1275, 1275, 1275, 1275,
7200
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7201
     1275, 1275, 1275, 1275, 1275},
7202
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7203
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7204
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7205
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7206
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7207
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7208
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7209
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7210
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7211
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7212
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
7213
    {1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7214
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7215
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7216
     1275, 1275, 1275, 1275, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7217
     1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7218
     1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7219
     1281, 1283, 1283, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7220
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7221
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7222
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7223
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7224
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7225
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7226
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7227
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7228
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7229
     1285, 1285, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
7230
     1287, 1287, 1287, 1287, 1287, 1287, 1287, 1289, 1289, 1289, 1291, 1291,
7231
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7232
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7233
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7234
     1291, 1291, 1291, 1291, 1291},
7235
    {1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7236
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7237
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7238
     1291, 1291, 1291, 1291, 1291, 1293, 1293, 1293, 1293, 1293, 1293, 1293,
7239
     1293, 1295, 1295, 1295, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7240
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7241
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7242
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7243
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7244
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7245
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7246
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7247
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7248
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7249
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7250
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7251
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1301, 1301, 1301, 1301,
7252
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7253
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7254
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7255
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7256
     1301, 1301, 1301, 1301, 1301},
7257
    {1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7258
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7259
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7260
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7261
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7262
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7263
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7264
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7265
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7266
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7267
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7268
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7269
     1307, 1307, 1307, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7270
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7271
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7272
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7273
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1313, 1315, 1315, 1315, 1315,
7274
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7275
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7276
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7277
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7278
     1315, 1315, 1315, 1315, 1315},
7279
    {1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7280
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7281
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7282
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7283
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7284
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1317,
7285
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7286
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7287
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7288
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7289
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7290
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7291
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7292
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7293
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7294
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7295
     1319, 1319, 1319, 1319, 1319, 1319, 1319, 1325, 1325, 1325, 1325, 1327,
7296
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7297
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7298
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7299
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7300
     1327, 1327, 1327, 1327, 1327},
7301
    {1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7302
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7303
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7304
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7305
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7306
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1331,
7307
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7308
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7309
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7310
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7311
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7312
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7313
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7314
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7315
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7316
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7317
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7318
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7319
     1333, 1333, 1339, 1339, 1339, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7320
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7321
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7322
     1341, 1341, 1341, 1341, 1341},
7323
    {1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7324
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7325
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7326
     1341, 1341, 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, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7330
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7331
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7332
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7333
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7334
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7335
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7336
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7337
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7338
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7339
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7340
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7341
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7342
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7343
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7344
     1343, 1343, 1343, 1343, 1343},
7345
    {1343, 1343, 1343, 1343, 1343, 1343, 1345, 1345, 1347, 1347, 1349, 1349,
7346
     1351, 1351, 1353, 1353, 1353, 1353, 1355, 1355, 1355, 1355, 1355, 1355,
7347
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7348
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7349
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1357,
7350
     1357, 1359, 1359, 1361, 1363, 1363, 1363, 1365, 1365, 1365, 1365, 1365,
7351
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 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, 1365, 1365, 1365, 1365, 1365,
7357
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7358
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7359
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7360
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7361
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7362
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7363
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7364
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7365
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7366
     1365, 1365, 1365, 1365, 1365},
7367
    {1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7368
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7369
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7370
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7371
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1367, 1369, 1369, 1369, 1369,
7372
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7373
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7374
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1371, 1373, 1373, 1373, 1373,
7375
     1373, 1373, 1373, 1375, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7376
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7377
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7378
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7379
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7380
     1377, 1377, 1377, 1377, 1377, 1381, 1385, 1385, 1385, 1385, 1385, 1385,
7381
     1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385,
7382
     1385, 1385, 1385, 1385, 1385, 1387, 1389, 1389, 1389, 1389, 1389, 1389,
7383
     1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389,
7384
     1389, 1391, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7385
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7386
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7387
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7388
     1393, 1393, 1393, 1393, 1393},
7389
    {1393, 1401, 1409, 1411, 1413, 1415, 1417, 1419, 1421, 1429, 1437, 1439,
7390
     1441, 1443, 1445, 1447, 1449, 1453, 1457, 1457, 1457, 1457, 1457, 1457,
7391
     1457, 1461, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1473, 1481, 1483,
7392
     1485, 1487, 1489, 1491, 1493, 1501, 1509, 1511, 1513, 1515, 1517, 1519,
7393
     1521, 1527, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1539, 1545, 1545,
7394
     1545, 1545, 1545, 1545, 1545, 1549, 1553, 1553, 1553, 1553, 1553, 1553,
7395
     1553, 1557, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1567, 1573, 1573,
7396
     1573, 1573, 1573, 1573, 1573, 1573, 1579, 1579, 1579, 1579, 1579, 1579,
7397
     1579, 1587, 1595, 1597, 1599, 1601, 1603, 1605, 1607, 1615, 1623, 1625,
7398
     1627, 1629, 1631, 1633, 1635, 1637, 1637, 1637, 1637, 1639, 1639, 1639,
7399
     1639, 1639, 1639, 1639, 1639, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7400
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7401
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7402
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7403
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7404
     1641, 1641, 1641, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643,
7405
     1649, 1649, 1649, 1649, 1649, 1649, 1649, 1651, 1651, 1651, 1651, 1651,
7406
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7407
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7408
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7409
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1653, 1653, 1653, 1653, 1653,
7410
     1653, 1653, 1653, 1659, 1659},
7411
    {1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7412
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7413
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7414
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7415
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7416
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7417
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7418
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7419
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7420
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7421
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7422
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7423
     1659, 1661, 1661, 1663, 1663, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7424
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7425
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7426
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7427
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7428
     1665, 1665, 1665, 1665, 1665, 1667, 1667, 1669, 1669, 1671, 1671, 1671,
7429
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7430
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7431
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7432
     1671, 1671, 1671, 1671, 1671},
7433
    {1671, 1671, 1671, 1671, 1673, 1673, 1673, 1673, 1673, 1675, 1675, 1675,
7434
     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7435
     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7436
     1679, 1679, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7437
     1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7438
     1681, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1685, 1685, 1687, 1687,
7439
     1687, 1689, 1689, 1689, 1689, 1689, 1691, 1691, 1691, 1691, 1691, 1691,
7440
     1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691,
7441
     1691, 1691, 1693, 1693, 1693, 1695, 1697, 1697, 1697, 1697, 1697, 1697,
7442
     1697, 1697, 1697, 1697, 1697, 1697, 1697, 1699, 1701, 1701, 1701, 1703,
7443
     1705, 1705, 1705, 1707, 1709, 1711, 1713, 1713, 1713, 1713, 1713, 1715,
7444
     1717, 1717, 1717, 1719, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
7445
     1721, 1721, 1723, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725,
7446
     1725, 1725, 1725, 1725, 1725, 1725, 1725, 1727, 1727, 1727, 1727, 1727,
7447
     1727, 1729, 1731, 1731, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1735,
7448
     1737, 1739, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7449
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7450
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7451
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7452
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7453
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7454
     1741, 1741, 1741, 1741, 1741},
7455
    {1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7456
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7457
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7458
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7459
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7460
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1743,
7461
     1743, 1743, 1743, 1743, 1745, 1745, 1747, 1747, 1749, 1749, 1751, 1751,
7462
     1753, 1753, 1755, 1755, 1757, 1757, 1759, 1759, 1761, 1761, 1763, 1763,
7463
     1765, 1765, 1767, 1767, 1767, 1769, 1769, 1771, 1771, 1773, 1773, 1773,
7464
     1773, 1773, 1773, 1773, 1777, 1777, 1777, 1781, 1781, 1781, 1785, 1785,
7465
     1785, 1789, 1789, 1789, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7466
     1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7467
     1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7468
     1793, 1793, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1797,
7469
     1797, 1797, 1797, 1797, 1799, 1799, 1801, 1801, 1803, 1803, 1805, 1805,
7470
     1807, 1807, 1809, 1809, 1811, 1811, 1813, 1813, 1815, 1815, 1817, 1817,
7471
     1819, 1819, 1821, 1821, 1821, 1823, 1823, 1825, 1825, 1827, 1827, 1827,
7472
     1827, 1827, 1827, 1827, 1831, 1831, 1831, 1835, 1835, 1835, 1839, 1839,
7473
     1839, 1843, 1843, 1843, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7474
     1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7475
     1849, 1851, 1853, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855,
7476
     1855, 1855, 1857, 1857, 1857},
7477
    {1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7478
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7479
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7480
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7481
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7482
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7483
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7484
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7485
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7486
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7487
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7488
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7489
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1859, 1859,
7490
     1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1863, 1863,
7491
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7492
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7493
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7494
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7495
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7496
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7497
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7498
     1863, 1863, 1863, 1863, 1863},
7499
    {1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7500
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7501
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7502
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7503
     1863, 1863, 1865, 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, 1867, 1867, 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
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7513
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7514
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7515
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7516
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7517
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7518
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7519
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7520
     1867, 1867, 1867, 1867, 1867},
7521
    {1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7522
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7523
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7524
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7525
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7526
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7527
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 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},
7543
    {1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7544
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7545
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7546
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7547
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7548
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7549
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7550
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7551
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7552
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7553
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7554
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7555
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7556
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7557
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7558
     1871, 1871, 1871, 1871, 1871, 1871, 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},
7565
    {1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7566
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7567
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7568
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7569
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7570
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7571
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7572
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7573
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7574
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7575
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7576
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7577
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7578
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7579
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7580
     1877, 1877, 1877, 1877, 1877, 1879, 1881, 1881, 1881, 1881, 1881, 1881,
7581
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7582
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7583
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7584
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7585
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7586
     1881, 1881, 1881, 1881, 1881},
7587
    {1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7588
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7589
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7590
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7591
     1881, 1881, 1881, 1881, 1881, 1881, 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, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7594
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7595
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7596
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7597
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7598
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7599
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7600
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7601
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7602
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7603
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7604
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7605
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7606
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7607
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7608
     1883, 1883, 1883, 1883, 1883}};
7609
const char32_t composition_data[1883] = {
7610
    0,     824,   8814,  824,   8800,  824,   8815,  768,   192,   769,   193,
7611
    770,   194,   771,   195,   772,   256,   774,   258,   775,   550,   776,
7612
    196,   777,   7842,  778,   197,   780,   461,   783,   512,   785,   514,
7613
    803,   7840,  805,   7680,  808,   260,   775,   7682,  803,   7684,  817,
7614
    7686,  769,   262,   770,   264,   775,   266,   780,   268,   807,   199,
7615
    775,   7690,  780,   270,   803,   7692,  807,   7696,  813,   7698,  817,
7616
    7694,  768,   200,   769,   201,   770,   202,   771,   7868,  772,   274,
7617
    774,   276,   775,   278,   776,   203,   777,   7866,  780,   282,   783,
7618
    516,   785,   518,   803,   7864,  807,   552,   808,   280,   813,   7704,
7619
    816,   7706,  775,   7710,  769,   500,   770,   284,   772,   7712,  774,
7620
    286,   775,   288,   780,   486,   807,   290,   770,   292,   775,   7714,
7621
    776,   7718,  780,   542,   803,   7716,  807,   7720,  814,   7722,  768,
7622
    204,   769,   205,   770,   206,   771,   296,   772,   298,   774,   300,
7623
    775,   304,   776,   207,   777,   7880,  780,   463,   783,   520,   785,
7624
    522,   803,   7882,  808,   302,   816,   7724,  770,   308,   769,   7728,
7625
    780,   488,   803,   7730,  807,   310,   817,   7732,  769,   313,   780,
7626
    317,   803,   7734,  807,   315,   813,   7740,  817,   7738,  769,   7742,
7627
    775,   7744,  803,   7746,  768,   504,   769,   323,   771,   209,   775,
7628
    7748,  780,   327,   803,   7750,  807,   325,   813,   7754,  817,   7752,
7629
    768,   210,   769,   211,   770,   212,   771,   213,   772,   332,   774,
7630
    334,   775,   558,   776,   214,   777,   7886,  779,   336,   780,   465,
7631
    783,   524,   785,   526,   795,   416,   803,   7884,  808,   490,   769,
7632
    7764,  775,   7766,  769,   340,   775,   7768,  780,   344,   783,   528,
7633
    785,   530,   803,   7770,  807,   342,   817,   7774,  769,   346,   770,
7634
    348,   775,   7776,  780,   352,   803,   7778,  806,   536,   807,   350,
7635
    775,   7786,  780,   356,   803,   7788,  806,   538,   807,   354,   813,
7636
    7792,  817,   7790,  768,   217,   769,   218,   770,   219,   771,   360,
7637
    772,   362,   774,   364,   776,   220,   777,   7910,  778,   366,   779,
7638
    368,   780,   467,   783,   532,   785,   534,   795,   431,   803,   7908,
7639
    804,   7794,  808,   370,   813,   7798,  816,   7796,  771,   7804,  803,
7640
    7806,  768,   7808,  769,   7810,  770,   372,   775,   7814,  776,   7812,
7641
    803,   7816,  775,   7818,  776,   7820,  768,   7922,  769,   221,   770,
7642
    374,   771,   7928,  772,   562,   775,   7822,  776,   376,   777,   7926,
7643
    803,   7924,  769,   377,   770,   7824,  775,   379,   780,   381,   803,
7644
    7826,  817,   7828,  768,   224,   769,   225,   770,   226,   771,   227,
7645
    772,   257,   774,   259,   775,   551,   776,   228,   777,   7843,  778,
7646
    229,   780,   462,   783,   513,   785,   515,   803,   7841,  805,   7681,
7647
    808,   261,   775,   7683,  803,   7685,  817,   7687,  769,   263,   770,
7648
    265,   775,   267,   780,   269,   807,   231,   775,   7691,  780,   271,
7649
    803,   7693,  807,   7697,  813,   7699,  817,   7695,  768,   232,   769,
7650
    233,   770,   234,   771,   7869,  772,   275,   774,   277,   775,   279,
7651
    776,   235,   777,   7867,  780,   283,   783,   517,   785,   519,   803,
7652
    7865,  807,   553,   808,   281,   813,   7705,  816,   7707,  775,   7711,
7653
    769,   501,   770,   285,   772,   7713,  774,   287,   775,   289,   780,
7654
    487,   807,   291,   770,   293,   775,   7715,  776,   7719,  780,   543,
7655
    803,   7717,  807,   7721,  814,   7723,  817,   7830,  768,   236,   769,
7656
    237,   770,   238,   771,   297,   772,   299,   774,   301,   776,   239,
7657
    777,   7881,  780,   464,   783,   521,   785,   523,   803,   7883,  808,
7658
    303,   816,   7725,  770,   309,   780,   496,   769,   7729,  780,   489,
7659
    803,   7731,  807,   311,   817,   7733,  769,   314,   780,   318,   803,
7660
    7735,  807,   316,   813,   7741,  817,   7739,  769,   7743,  775,   7745,
7661
    803,   7747,  768,   505,   769,   324,   771,   241,   775,   7749,  780,
7662
    328,   803,   7751,  807,   326,   813,   7755,  817,   7753,  768,   242,
7663
    769,   243,   770,   244,   771,   245,   772,   333,   774,   335,   775,
7664
    559,   776,   246,   777,   7887,  779,   337,   780,   466,   783,   525,
7665
    785,   527,   795,   417,   803,   7885,  808,   491,   769,   7765,  775,
7666
    7767,  769,   341,   775,   7769,  780,   345,   783,   529,   785,   531,
7667
    803,   7771,  807,   343,   817,   7775,  769,   347,   770,   349,   775,
7668
    7777,  780,   353,   803,   7779,  806,   537,   807,   351,   775,   7787,
7669
    776,   7831,  780,   357,   803,   7789,  806,   539,   807,   355,   813,
7670
    7793,  817,   7791,  768,   249,   769,   250,   770,   251,   771,   361,
7671
    772,   363,   774,   365,   776,   252,   777,   7911,  778,   367,   779,
7672
    369,   780,   468,   783,   533,   785,   535,   795,   432,   803,   7909,
7673
    804,   7795,  808,   371,   813,   7799,  816,   7797,  771,   7805,  803,
7674
    7807,  768,   7809,  769,   7811,  770,   373,   775,   7815,  776,   7813,
7675
    778,   7832,  803,   7817,  775,   7819,  776,   7821,  768,   7923,  769,
7676
    253,   770,   375,   771,   7929,  772,   563,   775,   7823,  776,   255,
7677
    777,   7927,  778,   7833,  803,   7925,  769,   378,   770,   7825,  775,
7678
    380,   780,   382,   803,   7827,  817,   7829,  768,   8173,  769,   901,
7679
    834,   8129,  768,   7846,  769,   7844,  771,   7850,  777,   7848,  772,
7680
    478,   769,   506,   769,   508,   772,   482,   769,   7688,  768,   7872,
7681
    769,   7870,  771,   7876,  777,   7874,  769,   7726,  768,   7890,  769,
7682
    7888,  771,   7894,  777,   7892,  769,   7756,  772,   556,   776,   7758,
7683
    772,   554,   769,   510,   768,   475,   769,   471,   772,   469,   780,
7684
    473,   768,   7847,  769,   7845,  771,   7851,  777,   7849,  772,   479,
7685
    769,   507,   769,   509,   772,   483,   769,   7689,  768,   7873,  769,
7686
    7871,  771,   7877,  777,   7875,  769,   7727,  768,   7891,  769,   7889,
7687
    771,   7895,  777,   7893,  769,   7757,  772,   557,   776,   7759,  772,
7688
    555,   769,   511,   768,   476,   769,   472,   772,   470,   780,   474,
7689
    768,   7856,  769,   7854,  771,   7860,  777,   7858,  768,   7857,  769,
7690
    7855,  771,   7861,  777,   7859,  768,   7700,  769,   7702,  768,   7701,
7691
    769,   7703,  768,   7760,  769,   7762,  768,   7761,  769,   7763,  775,
7692
    7780,  775,   7781,  775,   7782,  775,   7783,  769,   7800,  769,   7801,
7693
    776,   7802,  776,   7803,  775,   7835,  768,   7900,  769,   7898,  771,
7694
    7904,  777,   7902,  803,   7906,  768,   7901,  769,   7899,  771,   7905,
7695
    777,   7903,  803,   7907,  768,   7914,  769,   7912,  771,   7918,  777,
7696
    7916,  803,   7920,  768,   7915,  769,   7913,  771,   7919,  777,   7917,
7697
    803,   7921,  780,   494,   772,   492,   772,   493,   772,   480,   772,
7698
    481,   774,   7708,  774,   7709,  772,   560,   772,   561,   780,   495,
7699
    768,   8122,  769,   902,   772,   8121,  774,   8120,  787,   7944,  788,
7700
    7945,  837,   8124,  768,   8136,  769,   904,   787,   7960,  788,   7961,
7701
    768,   8138,  769,   905,   787,   7976,  788,   7977,  837,   8140,  768,
7702
    8154,  769,   906,   772,   8153,  774,   8152,  776,   938,   787,   7992,
7703
    788,   7993,  768,   8184,  769,   908,   787,   8008,  788,   8009,  788,
7704
    8172,  768,   8170,  769,   910,   772,   8169,  774,   8168,  776,   939,
7705
    788,   8025,  768,   8186,  769,   911,   787,   8040,  788,   8041,  837,
7706
    8188,  837,   8116,  837,   8132,  768,   8048,  769,   940,   772,   8113,
7707
    774,   8112,  787,   7936,  788,   7937,  834,   8118,  837,   8115,  768,
7708
    8050,  769,   941,   787,   7952,  788,   7953,  768,   8052,  769,   942,
7709
    787,   7968,  788,   7969,  834,   8134,  837,   8131,  768,   8054,  769,
7710
    943,   772,   8145,  774,   8144,  776,   970,   787,   7984,  788,   7985,
7711
    834,   8150,  768,   8056,  769,   972,   787,   8000,  788,   8001,  787,
7712
    8164,  788,   8165,  768,   8058,  769,   973,   772,   8161,  774,   8160,
7713
    776,   971,   787,   8016,  788,   8017,  834,   8166,  768,   8060,  769,
7714
    974,   787,   8032,  788,   8033,  834,   8182,  837,   8179,  768,   8146,
7715
    769,   912,   834,   8151,  768,   8162,  769,   944,   834,   8167,  837,
7716
    8180,  769,   979,   776,   980,   776,   1031,  774,   1232,  776,   1234,
7717
    769,   1027,  768,   1024,  774,   1238,  776,   1025,  774,   1217,  776,
7718
    1244,  776,   1246,  768,   1037,  772,   1250,  774,   1049,  776,   1252,
7719
    769,   1036,  776,   1254,  772,   1262,  774,   1038,  776,   1264,  779,
7720
    1266,  776,   1268,  776,   1272,  776,   1260,  774,   1233,  776,   1235,
7721
    769,   1107,  768,   1104,  774,   1239,  776,   1105,  774,   1218,  776,
7722
    1245,  776,   1247,  768,   1117,  772,   1251,  774,   1081,  776,   1253,
7723
    769,   1116,  776,   1255,  772,   1263,  774,   1118,  776,   1265,  779,
7724
    1267,  776,   1269,  776,   1273,  776,   1261,  776,   1111,  783,   1142,
7725
    783,   1143,  776,   1242,  776,   1243,  776,   1258,  776,   1259,  1619,
7726
    1570,  1620,  1571,  1621,  1573,  1620,  1572,  1620,  1574,  1620,  1730,
7727
    1620,  1747,  1620,  1728,  2364,  2345,  2364,  2353,  2364,  2356,  2494,
7728
    2507,  2519,  2508,  2878,  2891,  2902,  2888,  2903,  2892,  3031,  2964,
7729
    3006,  3018,  3031,  3020,  3006,  3019,  3158,  3144,  3285,  3264,  3266,
7730
    3274,  3285,  3271,  3286,  3272,  3285,  3275,  3390,  3402,  3415,  3404,
7731
    3390,  3403,  3530,  3546,  3535,  3548,  3551,  3550,  3530,  3549,  4142,
7732
    4134,  6965,  6918,  6965,  6920,  6965,  6922,  6965,  6924,  6965,  6926,
7733
    6965,  6930,  6965,  6971,  6965,  6973,  6965,  6976,  6965,  6977,  6965,
7734
    6979,  772,   7736,  772,   7737,  772,   7772,  772,   7773,  775,   7784,
7735
    775,   7785,  770,   7852,  774,   7862,  770,   7853,  774,   7863,  770,
7736
    7878,  770,   7879,  770,   7896,  770,   7897,  768,   7938,  769,   7940,
7737
    834,   7942,  837,   8064,  768,   7939,  769,   7941,  834,   7943,  837,
7738
    8065,  837,   8066,  837,   8067,  837,   8068,  837,   8069,  837,   8070,
7739
    837,   8071,  768,   7946,  769,   7948,  834,   7950,  837,   8072,  768,
7740
    7947,  769,   7949,  834,   7951,  837,   8073,  837,   8074,  837,   8075,
7741
    837,   8076,  837,   8077,  837,   8078,  837,   8079,  768,   7954,  769,
7742
    7956,  768,   7955,  769,   7957,  768,   7962,  769,   7964,  768,   7963,
7743
    769,   7965,  768,   7970,  769,   7972,  834,   7974,  837,   8080,  768,
7744
    7971,  769,   7973,  834,   7975,  837,   8081,  837,   8082,  837,   8083,
7745
    837,   8084,  837,   8085,  837,   8086,  837,   8087,  768,   7978,  769,
7746
    7980,  834,   7982,  837,   8088,  768,   7979,  769,   7981,  834,   7983,
7747
    837,   8089,  837,   8090,  837,   8091,  837,   8092,  837,   8093,  837,
7748
    8094,  837,   8095,  768,   7986,  769,   7988,  834,   7990,  768,   7987,
7749
    769,   7989,  834,   7991,  768,   7994,  769,   7996,  834,   7998,  768,
7750
    7995,  769,   7997,  834,   7999,  768,   8002,  769,   8004,  768,   8003,
7751
    769,   8005,  768,   8010,  769,   8012,  768,   8011,  769,   8013,  768,
7752
    8018,  769,   8020,  834,   8022,  768,   8019,  769,   8021,  834,   8023,
7753
    768,   8027,  769,   8029,  834,   8031,  768,   8034,  769,   8036,  834,
7754
    8038,  837,   8096,  768,   8035,  769,   8037,  834,   8039,  837,   8097,
7755
    837,   8098,  837,   8099,  837,   8100,  837,   8101,  837,   8102,  837,
7756
    8103,  768,   8042,  769,   8044,  834,   8046,  837,   8104,  768,   8043,
7757
    769,   8045,  834,   8047,  837,   8105,  837,   8106,  837,   8107,  837,
7758
    8108,  837,   8109,  837,   8110,  837,   8111,  837,   8114,  837,   8130,
7759
    837,   8178,  837,   8119,  768,   8141,  769,   8142,  834,   8143,  837,
7760
    8135,  837,   8183,  768,   8157,  769,   8158,  834,   8159,  824,   8602,
7761
    824,   8603,  824,   8622,  824,   8653,  824,   8655,  824,   8654,  824,
7762
    8708,  824,   8713,  824,   8716,  824,   8740,  824,   8742,  824,   8769,
7763
    824,   8772,  824,   8775,  824,   8777,  824,   8813,  824,   8802,  824,
7764
    8816,  824,   8817,  824,   8820,  824,   8821,  824,   8824,  824,   8825,
7765
    824,   8832,  824,   8833,  824,   8928,  824,   8929,  824,   8836,  824,
7766
    8837,  824,   8840,  824,   8841,  824,   8930,  824,   8931,  824,   8876,
7767
    824,   8877,  824,   8878,  824,   8879,  824,   8938,  824,   8939,  824,
7768
    8940,  824,   8941,  12441, 12436, 12441, 12364, 12441, 12366, 12441, 12368,
7769
    12441, 12370, 12441, 12372, 12441, 12374, 12441, 12376, 12441, 12378, 12441,
7770
    12380, 12441, 12382, 12441, 12384, 12441, 12386, 12441, 12389, 12441, 12391,
7771
    12441, 12393, 12441, 12400, 12442, 12401, 12441, 12403, 12442, 12404, 12441,
7772
    12406, 12442, 12407, 12441, 12409, 12442, 12410, 12441, 12412, 12442, 12413,
7773
    12441, 12446, 12441, 12532, 12441, 12460, 12441, 12462, 12441, 12464, 12441,
7774
    12466, 12441, 12468, 12441, 12470, 12441, 12472, 12441, 12474, 12441, 12476,
7775
    12441, 12478, 12441, 12480, 12441, 12482, 12441, 12485, 12441, 12487, 12441,
7776
    12489, 12441, 12496, 12442, 12497, 12441, 12499, 12442, 12500, 12441, 12502,
7777
    12442, 12503, 12441, 12505, 12442, 12506, 12441, 12508, 12442, 12509, 12441,
7778
    12535, 12441, 12536, 12441, 12537, 12441, 12538, 12441, 12542, 69818, 69786,
7779
    69818, 69788, 69818, 69803, 69927, 69934, 69927, 69935, 70462, 70475, 70487,
7780
    70476, 70832, 70844, 70842, 70843, 70845, 70846, 71087, 71098, 71087, 71099,
7781
    71984, 71992};
7782
7783
}  // namespace ada::idna
7784
#endif  // ADA_IDNA_NORMALIZATION_TABLES_H
7785
/* end file src/normalization_tables.cpp */
7786
7787
namespace ada::idna {
7788
7789
// See
7790
// https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/impl_norm.h#L467
7791
constexpr char32_t hangul_sbase = 0xAC00;
7792
constexpr char32_t hangul_tbase = 0x11A7;
7793
constexpr char32_t hangul_vbase = 0x1161;
7794
constexpr char32_t hangul_lbase = 0x1100;
7795
constexpr char32_t hangul_lcount = 19;
7796
constexpr char32_t hangul_vcount = 21;
7797
constexpr char32_t hangul_tcount = 28;
7798
constexpr char32_t hangul_ncount = hangul_vcount * hangul_tcount;
7799
constexpr char32_t hangul_scount =
7800
    hangul_lcount * hangul_vcount * hangul_tcount;
7801
7802
std::pair<bool, size_t> compute_decomposition_length(
7803
12.2k
    const std::u32string_view input) noexcept {
7804
12.2k
  bool decomposition_needed{false};
7805
12.2k
  size_t additional_elements{0};
7806
972k
  for (char32_t current_character : input) {
7807
972k
    size_t decomposition_length{0};
7808
7809
972k
    if (current_character >= hangul_sbase &&
7810
9.77k
        current_character < hangul_sbase + hangul_scount) {
7811
6.53k
      decomposition_length = 2;
7812
6.53k
      if ((current_character - hangul_sbase) % hangul_tcount) {
7813
5.30k
        decomposition_length = 3;
7814
5.30k
      }
7815
965k
    } else if (current_character < 0x110000) {
7816
965k
      const uint8_t di = decomposition_index[current_character >> 8];
7817
965k
      const uint16_t* const decomposition =
7818
965k
          decomposition_block[di] + (current_character % 256);
7819
965k
      decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
7820
965k
      if ((decomposition_length > 0) && (decomposition[0] & 1)) {
7821
0
        decomposition_length = 0;
7822
0
      }
7823
965k
    }
7824
972k
    if (decomposition_length != 0) {
7825
35.9k
      decomposition_needed = true;
7826
35.9k
      additional_elements += decomposition_length - 1;
7827
35.9k
    }
7828
972k
  }
7829
12.2k
  return {decomposition_needed, additional_elements};
7830
12.2k
}
7831
7832
4.65k
void decompose(std::u32string& input, size_t additional_elements) {
7833
4.65k
  input.resize(input.size() + additional_elements);
7834
4.65k
  for (size_t descending_idx = input.size(),
7835
4.65k
              input_count = descending_idx - additional_elements;
7836
315k
       input_count--;) {
7837
311k
    if (input[input_count] >= hangul_sbase &&
7838
7.97k
        input[input_count] < hangul_sbase + hangul_scount) {
7839
      // Hangul decomposition.
7840
6.53k
      char32_t s_index = input[input_count] - hangul_sbase;
7841
6.53k
      if (s_index % hangul_tcount != 0) {
7842
5.30k
        input[--descending_idx] = hangul_tbase + s_index % hangul_tcount;
7843
5.30k
      }
7844
6.53k
      input[--descending_idx] =
7845
6.53k
          hangul_vbase + (s_index % hangul_ncount) / hangul_tcount;
7846
6.53k
      input[--descending_idx] = hangul_lbase + s_index / hangul_ncount;
7847
304k
    } else if (input[input_count] < 0x110000) {
7848
      // Check decomposition_data.
7849
304k
      const uint16_t* decomposition =
7850
304k
          decomposition_block[decomposition_index[input[input_count] >> 8]] +
7851
304k
          (input[input_count] % 256);
7852
304k
      uint16_t decomposition_length =
7853
304k
          (decomposition[1] >> 2) - (decomposition[0] >> 2);
7854
304k
      if (decomposition_length > 0 && (decomposition[0] & 1)) {
7855
0
        decomposition_length = 0;
7856
0
      }
7857
304k
      if (decomposition_length > 0) {
7858
        // Non-recursive decomposition.
7859
113k
        while (decomposition_length-- > 0) {
7860
83.8k
          input[--descending_idx] = decomposition_data[(decomposition[0] >> 2) +
7861
83.8k
                                                       decomposition_length];
7862
83.8k
        }
7863
275k
      } else {
7864
        // No decomposition.
7865
275k
        input[--descending_idx] = input[input_count];
7866
275k
      }
7867
304k
    } else {
7868
      // Non-Unicode character.
7869
0
      input[--descending_idx] = input[input_count];
7870
0
    }
7871
311k
  }
7872
4.65k
}
7873
7874
2.12M
uint8_t get_ccc(char32_t c) noexcept {
7875
2.12M
  return c < 0x110000 ? canonical_combining_class_block
7876
2.12M
                            [canonical_combining_class_index[c >> 8]][c % 256]
7877
2.12M
                      : 0;
7878
2.12M
}
7879
7880
12.2k
void sort_marks(std::u32string& input) {
7881
1.03M
  for (size_t idx = 1; idx < input.size(); idx++) {
7882
1.02M
    uint8_t ccc = get_ccc(input[idx]);
7883
1.02M
    if (ccc == 0) {
7884
961k
      continue;
7885
961k
    }  // Skip non-combining characters.
7886
64.5k
    auto current_character = input[idx];
7887
64.5k
    size_t back_idx = idx;
7888
87.1k
    while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) {
7889
22.6k
      input[back_idx] = input[back_idx - 1];
7890
22.6k
      back_idx--;
7891
22.6k
    }
7892
64.5k
    input[back_idx] = current_character;
7893
64.5k
  }
7894
12.2k
}
7895
7896
12.2k
void decompose_nfc(std::u32string& input) {
7897
  /**
7898
   * Decompose the domain_name string to Unicode Normalization Form C.
7899
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepDecompose
7900
   */
7901
12.2k
  auto [decomposition_needed, additional_elements] =
7902
12.2k
      compute_decomposition_length(input);
7903
12.2k
  if (decomposition_needed) {
7904
4.65k
    decompose(input, additional_elements);
7905
4.65k
  }
7906
12.2k
  sort_marks(input);
7907
12.2k
}
7908
7909
12.2k
void compose(std::u32string& input) {
7910
  /**
7911
   * Compose the domain_name string to Unicode Normalization Form C.
7912
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepCompose
7913
   */
7914
12.2k
  size_t input_count{0};
7915
12.2k
  size_t composition_count{0};
7916
974k
  for (; input_count < input.size(); input_count++, composition_count++) {
7917
962k
    input[composition_count] = input[input_count];
7918
962k
    if (input[input_count] >= hangul_lbase &&
7919
295k
        input[input_count] < hangul_lbase + hangul_lcount) {
7920
8.16k
      if (input_count + 1 < input.size() &&
7921
7.79k
          input[input_count + 1] >= hangul_vbase &&
7922
6.92k
          input[input_count + 1] < hangul_vbase + hangul_vcount) {
7923
6.54k
        input[composition_count] =
7924
6.54k
            hangul_sbase +
7925
6.54k
            ((input[input_count] - hangul_lbase) * hangul_vcount +
7926
6.54k
             input[input_count + 1] - hangul_vbase) *
7927
6.54k
                hangul_tcount;
7928
6.54k
        input_count++;
7929
6.54k
        if (input_count + 1 < input.size() &&
7930
6.21k
            input[input_count + 1] > hangul_tbase &&
7931
5.55k
            input[input_count + 1] < hangul_tbase + hangul_tcount) {
7932
5.30k
          input[composition_count] += input[++input_count] - hangul_tbase;
7933
5.30k
        }
7934
6.54k
      }
7935
953k
    } else if (input[input_count] >= hangul_sbase &&
7936
2.46k
               input[input_count] < hangul_sbase + hangul_scount) {
7937
0
      if ((input[input_count] - hangul_sbase) % hangul_tcount &&
7938
0
          input_count + 1 < input.size() &&
7939
0
          input[input_count + 1] > hangul_tbase &&
7940
0
          input[input_count + 1] < hangul_tbase + hangul_tcount) {
7941
0
        input[composition_count] += input[++input_count] - hangul_tbase;
7942
0
      }
7943
953k
    } else if (input[input_count] < 0x110000) {
7944
953k
      const uint16_t* composition =
7945
953k
          &composition_block[composition_index[input[input_count] >> 8]]
7946
953k
                            [input[input_count] % 256];
7947
953k
      size_t initial_composition_count = composition_count;
7948
1.01M
      for (int32_t previous_ccc = -1; input_count + 1 < input.size();
7949
1.00M
           input_count++) {
7950
1.00M
        uint8_t ccc = get_ccc(input[input_count + 1]);
7951
7952
1.00M
        if (composition[1] != composition[0] && previous_ccc < ccc) {
7953
          // Try finding a composition.
7954
204k
          int left = composition[0];
7955
204k
          int right = composition[1];
7956
505k
          while (left + 2 < right) {
7957
            // mean without overflow
7958
300k
            int middle = left + (((right - left) >> 1) & ~1);
7959
300k
            if (composition_data[middle] <= input[input_count + 1]) {
7960
73.7k
              left = middle;
7961
73.7k
            }
7962
300k
            if (composition_data[middle] >= input[input_count + 1]) {
7963
260k
              right = middle;
7964
260k
            }
7965
300k
          }
7966
204k
          if (composition_data[left] == input[input_count + 1]) {
7967
53.6k
            input[initial_composition_count] = composition_data[left + 1];
7968
53.6k
            composition =
7969
53.6k
                &composition_block
7970
53.6k
                    [composition_index[composition_data[left + 1] >> 8]]
7971
53.6k
                    [composition_data[left + 1] % 256];
7972
53.6k
            continue;
7973
53.6k
          }
7974
204k
        }
7975
7976
953k
        if (ccc == 0) {
7977
942k
          break;
7978
942k
        }  // Not a combining character.
7979
10.9k
        previous_ccc = ccc;
7980
10.9k
        input[++composition_count] = input[input_count + 1];
7981
10.9k
      }
7982
953k
    }
7983
962k
  }
7984
7985
12.2k
  if (composition_count < input_count) {
7986
4.67k
    input.resize(composition_count);
7987
4.67k
  }
7988
12.2k
}
7989
7990
12.2k
void normalize(std::u32string& input) {
7991
  /**
7992
   * Normalize the domain_name string to Unicode Normalization Form C.
7993
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepNormalize
7994
   */
7995
12.2k
  decompose_nfc(input);
7996
12.2k
  compose(input);
7997
12.2k
}
7998
7999
}  // namespace ada::idna
8000
/* end file src/normalization.cpp */
8001
/* begin file src/punycode.cpp */
8002
8003
#include <cstdint>
8004
8005
namespace ada::idna {
8006
8007
constexpr int32_t base = 36;
8008
constexpr int32_t tmin = 1;
8009
constexpr int32_t tmax = 26;
8010
constexpr int32_t skew = 38;
8011
constexpr int32_t damp = 700;
8012
constexpr int32_t initial_bias = 72;
8013
constexpr uint32_t initial_n = 128;
8014
8015
100k
static constexpr int32_t char_to_digit_value(char value) {
8016
100k
  if (value >= 'a' && value <= 'z') return value - 'a';
8017
6.60k
  if (value >= '0' && value <= '9') return value - '0' + 26;
8018
87
  return -1;
8019
6.60k
}
8020
8021
1.14M
static constexpr char digit_to_char(int32_t digit) {
8022
1.14M
  return digit < 26 ? char(digit + 97) : char(digit + 22);
8023
1.14M
}
8024
8025
594k
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
8026
594k
  if (firsttime) {
8027
78.8k
    d = d / damp;
8028
516k
  } else {
8029
516k
    d = d / 2;
8030
516k
  }
8031
594k
  d += d / n;
8032
594k
  int32_t k = 0;
8033
800k
  while (d > ((base - tmin) * tmax) / 2) {
8034
205k
    d /= base - tmin;
8035
205k
    k += base;
8036
205k
  }
8037
594k
  return k + (((base - tmin + 1) * d) / (d + skew));
8038
594k
}
8039
8040
7.44k
bool punycode_to_utf32(std::string_view input, std::u32string &out) {
8041
  // See https://github.com/whatwg/url/issues/803
8042
7.44k
  if (input.starts_with("xn--")) {
8043
3
    return false;
8044
3
  }
8045
7.44k
  int32_t written_out{0};
8046
7.44k
  out.reserve(out.size() + input.size());
8047
7.44k
  uint32_t n = initial_n;
8048
7.44k
  int32_t i = 0;
8049
7.44k
  int32_t bias = initial_bias;
8050
  // grab ascii content
8051
7.44k
  size_t end_of_ascii = input.find_last_of('-');
8052
7.44k
  if (end_of_ascii != std::string_view::npos) {
8053
42.8k
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8054
42.8k
      if (c >= 0x80) {
8055
0
        return false;
8056
0
      }
8057
42.8k
      out.push_back(c);
8058
42.8k
      written_out++;
8059
42.8k
    }
8060
784
    input.remove_prefix(end_of_ascii + 1);
8061
784
  }
8062
89.1k
  while (!input.empty()) {
8063
81.9k
    int32_t oldi = i;
8064
81.9k
    int32_t w = 1;
8065
100k
    for (int32_t k = base;; k += base) {
8066
100k
      if (input.empty()) {
8067
86
        return false;
8068
86
      }
8069
100k
      uint8_t code_point = input.front();
8070
100k
      input.remove_prefix(1);
8071
100k
      int32_t digit = char_to_digit_value(code_point);
8072
100k
      if (digit < 0) {
8073
87
        return false;
8074
87
      }
8075
100k
      if (digit > (0x7fffffff - i) / w) {
8076
14
        return false;
8077
14
      }
8078
100k
      i = i + digit * w;
8079
100k
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8080
100k
      if (digit < t) {
8081
81.7k
        break;
8082
81.7k
      }
8083
18.3k
      if (w > 0x7fffffff / (base - t)) {
8084
0
        return false;
8085
0
      }
8086
18.3k
      w = w * (base - t);
8087
18.3k
    }
8088
81.7k
    bias = adapt(i - oldi, written_out + 1, oldi == 0);
8089
81.7k
    if (i / (written_out + 1) > int32_t(0x7fffffff - n)) {
8090
59
      return false;
8091
59
    }
8092
81.7k
    n = n + i / (written_out + 1);
8093
81.7k
    i = i % (written_out + 1);
8094
81.7k
    if (n < 0x80) {
8095
0
      return false;
8096
0
    }
8097
81.7k
    out.insert(out.begin() + i, n);
8098
81.7k
    written_out++;
8099
81.7k
    ++i;
8100
81.7k
  }
8101
7.19k
  return true;
8102
7.44k
}
8103
8104
0
bool verify_punycode(std::string_view input) {
8105
0
  if (input.starts_with("xn--")) {
8106
0
    return false;
8107
0
  }
8108
0
  size_t written_out{0};
8109
0
  uint32_t n = initial_n;
8110
0
  int32_t i = 0;
8111
0
  int32_t bias = initial_bias;
8112
  // grab ascii content
8113
0
  size_t end_of_ascii = input.find_last_of('-');
8114
0
  if (end_of_ascii != std::string_view::npos) {
8115
0
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8116
0
      if (c >= 0x80) {
8117
0
        return false;
8118
0
      }
8119
0
      written_out++;
8120
0
    }
8121
0
    input.remove_prefix(end_of_ascii + 1);
8122
0
  }
8123
0
  while (!input.empty()) {
8124
0
    int32_t oldi = i;
8125
0
    int32_t w = 1;
8126
0
    for (int32_t k = base;; k += base) {
8127
0
      if (input.empty()) {
8128
0
        return false;
8129
0
      }
8130
0
      uint8_t code_point = input.front();
8131
0
      input.remove_prefix(1);
8132
0
      int32_t digit = char_to_digit_value(code_point);
8133
0
      if (digit < 0) {
8134
0
        return false;
8135
0
      }
8136
0
      if (digit > (0x7fffffff - i) / w) {
8137
0
        return false;
8138
0
      }
8139
0
      i = i + digit * w;
8140
0
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8141
0
      if (digit < t) {
8142
0
        break;
8143
0
      }
8144
0
      if (w > 0x7fffffff / (base - t)) {
8145
0
        return false;
8146
0
      }
8147
0
      w = w * (base - t);
8148
0
    }
8149
0
    bias = adapt(i - oldi, int32_t(written_out + 1), oldi == 0);
8150
0
    if (i / (written_out + 1) > 0x7fffffff - n) {
8151
0
      return false;
8152
0
    }
8153
0
    n = n + i / int32_t(written_out + 1);
8154
0
    i = i % int32_t(written_out + 1);
8155
0
    if (n < 0x80) {
8156
0
      return false;
8157
0
    }
8158
0
    written_out++;
8159
0
    ++i;
8160
0
  }
8161
8162
0
  return true;
8163
0
}
8164
8165
71.5k
bool utf32_to_punycode(std::u32string_view input, std::string &out) {
8166
71.5k
  out.reserve(input.size() + out.size());
8167
71.5k
  uint32_t n = initial_n;
8168
71.5k
  int32_t d = 0;
8169
71.5k
  int32_t bias = initial_bias;
8170
71.5k
  size_t h = 0;
8171
  // first push the ascii content
8172
608k
  for (uint32_t c : input) {
8173
608k
    if (c < 0x80) {
8174
95.7k
      ++h;
8175
95.7k
      out.push_back(char(c));
8176
95.7k
    }
8177
608k
    if (c > 0x10ffff || (c >= 0xd800 && c < 0xe000)) {
8178
0
      return false;
8179
0
    }
8180
608k
  }
8181
71.5k
  size_t b = h;
8182
71.5k
  if (b > 0) {
8183
6.59k
    out.push_back('-');
8184
6.59k
  }
8185
344k
  while (h < input.size()) {
8186
272k
    uint32_t m = 0x10FFFF;
8187
5.57M
    for (auto code_point : input) {
8188
5.57M
      if (code_point >= n && code_point < m) m = code_point;
8189
5.57M
    }
8190
8191
272k
    if ((m - n) > (0x7fffffff - d) / (h + 1)) {
8192
0
      return false;
8193
0
    }
8194
272k
    d = d + int32_t((m - n) * (h + 1));
8195
272k
    n = m;
8196
5.57M
    for (auto c : input) {
8197
5.57M
      if (c < n) {
8198
3.43M
        if (d == 0x7fffffff) {
8199
0
          return false;
8200
0
        }
8201
3.43M
        ++d;
8202
3.43M
      }
8203
5.57M
      if (c == n) {
8204
513k
        int32_t q = d;
8205
1.14M
        for (int32_t k = base;; k += base) {
8206
1.14M
          int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8207
8208
1.14M
          if (q < t) {
8209
513k
            break;
8210
513k
          }
8211
632k
          out.push_back(digit_to_char(t + ((q - t) % (base - t))));
8212
632k
          q = (q - t) / (base - t);
8213
632k
        }
8214
513k
        out.push_back(digit_to_char(q));
8215
513k
        bias = adapt(d, int32_t(h + 1), h == b);
8216
513k
        d = 0;
8217
513k
        ++h;
8218
513k
      }
8219
5.57M
    }
8220
272k
    ++d;
8221
272k
    ++n;
8222
272k
  }
8223
71.5k
  return true;
8224
71.5k
}
8225
8226
}  // namespace ada::idna
8227
/* end file src/punycode.cpp */
8228
/* begin file src/validity.cpp */
8229
#include <algorithm>
8230
#include <string_view>
8231
8232
namespace ada::idna {
8233
8234
enum direction : uint8_t {
8235
  NONE,
8236
  BN,
8237
  CS,
8238
  ES,
8239
  ON,
8240
  EN,
8241
  L,
8242
  R,
8243
  NSM,
8244
  AL,
8245
  AN,
8246
  ET,
8247
  WS,
8248
  RLO,
8249
  LRO,
8250
  PDF,
8251
  RLE,
8252
  RLI,
8253
  FSI,
8254
  PDI,
8255
  LRI,
8256
  B,
8257
  S,
8258
  LRE
8259
};
8260
8261
struct directions {
8262
  uint32_t start_code;
8263
  uint32_t final_code;
8264
  direction direct;
8265
};
8266
8267
static directions dir_table[] = {
8268
    {0x0, 0x8, direction::BN},          {0x9, 0x9, direction::S},
8269
    {0xa, 0xa, direction::B},           {0xb, 0xb, direction::S},
8270
    {0xc, 0xc, direction::WS},          {0xd, 0xd, direction::B},
8271
    {0xe, 0x1b, direction::BN},         {0x1c, 0x1e, direction::B},
8272
    {0x1f, 0x1f, direction::S},         {0x20, 0x20, direction::WS},
8273
    {0x21, 0x22, direction::ON},        {0x23, 0x25, direction::ET},
8274
    {0x26, 0x2a, direction::ON},        {0x2b, 0x2b, direction::ES},
8275
    {0x2c, 0x2c, direction::CS},        {0x2d, 0x2d, direction::ES},
8276
    {0x2e, 0x2f, direction::CS},        {0x30, 0x39, direction::EN},
8277
    {0x3a, 0x3a, direction::CS},        {0x3b, 0x40, direction::ON},
8278
    {0x41, 0x5a, direction::L},         {0x5b, 0x60, direction::ON},
8279
    {0x61, 0x7a, direction::L},         {0x7b, 0x7e, direction::ON},
8280
    {0x7f, 0x84, direction::BN},        {0x85, 0x85, direction::B},
8281
    {0x86, 0x9f, direction::BN},        {0xa0, 0xa0, direction::CS},
8282
    {0xa1, 0xa1, direction::ON},        {0xa2, 0xa5, direction::ET},
8283
    {0xa6, 0xa9, direction::ON},        {0xaa, 0xaa, direction::L},
8284
    {0xab, 0xac, direction::ON},        {0xad, 0xad, direction::BN},
8285
    {0xae, 0xaf, direction::ON},        {0xb0, 0xb1, direction::ET},
8286
    {0xb2, 0xb3, direction::EN},        {0xb4, 0xb4, direction::ON},
8287
    {0xb5, 0xb5, direction::L},         {0xb6, 0xb8, direction::ON},
8288
    {0xb9, 0xb9, direction::EN},        {0xba, 0xba, direction::L},
8289
    {0xbb, 0xbf, direction::ON},        {0xc0, 0xd6, direction::L},
8290
    {0xd7, 0xd7, direction::ON},        {0xd8, 0xf6, direction::L},
8291
    {0xf7, 0xf7, direction::ON},        {0xf8, 0x2b8, direction::L},
8292
    {0x2b9, 0x2ba, direction::ON},      {0x2bb, 0x2c1, direction::L},
8293
    {0x2c2, 0x2cf, direction::ON},      {0x2d0, 0x2d1, direction::L},
8294
    {0x2d2, 0x2df, direction::ON},      {0x2e0, 0x2e4, direction::L},
8295
    {0x2e5, 0x2ed, direction::ON},      {0x2ee, 0x2ee, direction::L},
8296
    {0x2ef, 0x2ff, direction::ON},      {0x300, 0x36f, direction::NSM},
8297
    {0x370, 0x373, direction::L},       {0x374, 0x375, direction::ON},
8298
    {0x376, 0x377, direction::L},       {0x37a, 0x37d, direction::L},
8299
    {0x37e, 0x37e, direction::ON},      {0x37f, 0x37f, direction::L},
8300
    {0x384, 0x385, direction::ON},      {0x386, 0x386, direction::L},
8301
    {0x387, 0x387, direction::ON},      {0x388, 0x38a, direction::L},
8302
    {0x38c, 0x38c, direction::L},       {0x38e, 0x3a1, direction::L},
8303
    {0x3a3, 0x3f5, direction::L},       {0x3f6, 0x3f6, direction::ON},
8304
    {0x3f7, 0x482, direction::L},       {0x483, 0x489, direction::NSM},
8305
    {0x48a, 0x52f, direction::L},       {0x531, 0x556, direction::L},
8306
    {0x559, 0x589, direction::L},       {0x58a, 0x58a, direction::ON},
8307
    {0x58d, 0x58e, direction::ON},      {0x58f, 0x58f, direction::ET},
8308
    {0x591, 0x5bd, direction::NSM},     {0x5be, 0x5be, direction::R},
8309
    {0x5bf, 0x5bf, direction::NSM},     {0x5c0, 0x5c0, direction::R},
8310
    {0x5c1, 0x5c2, direction::NSM},     {0x5c3, 0x5c3, direction::R},
8311
    {0x5c4, 0x5c5, direction::NSM},     {0x5c6, 0x5c6, direction::R},
8312
    {0x5c7, 0x5c7, direction::NSM},     {0x5d0, 0x5ea, direction::R},
8313
    {0x5ef, 0x5f4, direction::R},       {0x600, 0x605, direction::AN},
8314
    {0x606, 0x607, direction::ON},      {0x608, 0x608, direction::AL},
8315
    {0x609, 0x60a, direction::ET},      {0x60b, 0x60b, direction::AL},
8316
    {0x60c, 0x60c, direction::CS},      {0x60d, 0x60d, direction::AL},
8317
    {0x60e, 0x60f, direction::ON},      {0x610, 0x61a, direction::NSM},
8318
    {0x61b, 0x61c, direction::AL},      {0x61e, 0x64a, direction::AL},
8319
    {0x64b, 0x65f, direction::NSM},     {0x660, 0x669, direction::AN},
8320
    {0x66a, 0x66a, direction::ET},      {0x66b, 0x66c, direction::AN},
8321
    {0x66d, 0x66f, direction::AL},      {0x670, 0x670, direction::NSM},
8322
    {0x671, 0x6d5, direction::AL},      {0x6d6, 0x6dc, direction::NSM},
8323
    {0x6dd, 0x6dd, direction::AN},      {0x6de, 0x6de, direction::ON},
8324
    {0x6df, 0x6e4, direction::NSM},     {0x6e5, 0x6e6, direction::AL},
8325
    {0x6e7, 0x6e8, direction::NSM},     {0x6e9, 0x6e9, direction::ON},
8326
    {0x6ea, 0x6ed, direction::NSM},     {0x6ee, 0x6ef, direction::AL},
8327
    {0x6f0, 0x6f9, direction::EN},      {0x6fa, 0x70d, direction::AL},
8328
    {0x70f, 0x710, direction::AL},      {0x711, 0x711, direction::NSM},
8329
    {0x712, 0x72f, direction::AL},      {0x730, 0x74a, direction::NSM},
8330
    {0x74d, 0x7a5, direction::AL},      {0x7a6, 0x7b0, direction::NSM},
8331
    {0x7b1, 0x7b1, direction::AL},      {0x7c0, 0x7ea, direction::R},
8332
    {0x7eb, 0x7f3, direction::NSM},     {0x7f4, 0x7f5, direction::R},
8333
    {0x7f6, 0x7f9, direction::ON},      {0x7fa, 0x7fa, direction::R},
8334
    {0x7fd, 0x7fd, direction::NSM},     {0x7fe, 0x815, direction::R},
8335
    {0x816, 0x819, direction::NSM},     {0x81a, 0x81a, direction::R},
8336
    {0x81b, 0x823, direction::NSM},     {0x824, 0x824, direction::R},
8337
    {0x825, 0x827, direction::NSM},     {0x828, 0x828, direction::R},
8338
    {0x829, 0x82d, direction::NSM},     {0x830, 0x83e, direction::R},
8339
    {0x840, 0x858, direction::R},       {0x859, 0x85b, direction::NSM},
8340
    {0x85e, 0x85e, direction::R},       {0x860, 0x86a, direction::AL},
8341
    {0x8a0, 0x8b4, direction::AL},      {0x8b6, 0x8c7, direction::AL},
8342
    {0x8d3, 0x8e1, direction::NSM},     {0x8e2, 0x8e2, direction::AN},
8343
    {0x8e3, 0x902, direction::NSM},     {0x903, 0x939, direction::L},
8344
    {0x93a, 0x93a, direction::NSM},     {0x93b, 0x93b, direction::L},
8345
    {0x93c, 0x93c, direction::NSM},     {0x93d, 0x940, direction::L},
8346
    {0x941, 0x948, direction::NSM},     {0x949, 0x94c, direction::L},
8347
    {0x94d, 0x94d, direction::NSM},     {0x94e, 0x950, direction::L},
8348
    {0x951, 0x957, direction::NSM},     {0x958, 0x961, direction::L},
8349
    {0x962, 0x963, direction::NSM},     {0x964, 0x980, direction::L},
8350
    {0x981, 0x981, direction::NSM},     {0x982, 0x983, direction::L},
8351
    {0x985, 0x98c, direction::L},       {0x98f, 0x990, direction::L},
8352
    {0x993, 0x9a8, direction::L},       {0x9aa, 0x9b0, direction::L},
8353
    {0x9b2, 0x9b2, direction::L},       {0x9b6, 0x9b9, direction::L},
8354
    {0x9bc, 0x9bc, direction::NSM},     {0x9bd, 0x9c0, direction::L},
8355
    {0x9c1, 0x9c4, direction::NSM},     {0x9c7, 0x9c8, direction::L},
8356
    {0x9cb, 0x9cc, direction::L},       {0x9cd, 0x9cd, direction::NSM},
8357
    {0x9ce, 0x9ce, direction::L},       {0x9d7, 0x9d7, direction::L},
8358
    {0x9dc, 0x9dd, direction::L},       {0x9df, 0x9e1, direction::L},
8359
    {0x9e2, 0x9e3, direction::NSM},     {0x9e6, 0x9f1, direction::L},
8360
    {0x9f2, 0x9f3, direction::ET},      {0x9f4, 0x9fa, direction::L},
8361
    {0x9fb, 0x9fb, direction::ET},      {0x9fc, 0x9fd, direction::L},
8362
    {0x9fe, 0x9fe, direction::NSM},     {0xa01, 0xa02, direction::NSM},
8363
    {0xa03, 0xa03, direction::L},       {0xa05, 0xa0a, direction::L},
8364
    {0xa0f, 0xa10, direction::L},       {0xa13, 0xa28, direction::L},
8365
    {0xa2a, 0xa30, direction::L},       {0xa32, 0xa33, direction::L},
8366
    {0xa35, 0xa36, direction::L},       {0xa38, 0xa39, direction::L},
8367
    {0xa3c, 0xa3c, direction::NSM},     {0xa3e, 0xa40, direction::L},
8368
    {0xa41, 0xa42, direction::NSM},     {0xa47, 0xa48, direction::NSM},
8369
    {0xa4b, 0xa4d, direction::NSM},     {0xa51, 0xa51, direction::NSM},
8370
    {0xa59, 0xa5c, direction::L},       {0xa5e, 0xa5e, direction::L},
8371
    {0xa66, 0xa6f, direction::L},       {0xa70, 0xa71, direction::NSM},
8372
    {0xa72, 0xa74, direction::L},       {0xa75, 0xa75, direction::NSM},
8373
    {0xa76, 0xa76, direction::L},       {0xa81, 0xa82, direction::NSM},
8374
    {0xa83, 0xa83, direction::L},       {0xa85, 0xa8d, direction::L},
8375
    {0xa8f, 0xa91, direction::L},       {0xa93, 0xaa8, direction::L},
8376
    {0xaaa, 0xab0, direction::L},       {0xab2, 0xab3, direction::L},
8377
    {0xab5, 0xab9, direction::L},       {0xabc, 0xabc, direction::NSM},
8378
    {0xabd, 0xac0, direction::L},       {0xac1, 0xac5, direction::NSM},
8379
    {0xac7, 0xac8, direction::NSM},     {0xac9, 0xac9, direction::L},
8380
    {0xacb, 0xacc, direction::L},       {0xacd, 0xacd, direction::NSM},
8381
    {0xad0, 0xad0, direction::L},       {0xae0, 0xae1, direction::L},
8382
    {0xae2, 0xae3, direction::NSM},     {0xae6, 0xaf0, direction::L},
8383
    {0xaf1, 0xaf1, direction::ET},      {0xaf9, 0xaf9, direction::L},
8384
    {0xafa, 0xaff, direction::NSM},     {0xb01, 0xb01, direction::NSM},
8385
    {0xb02, 0xb03, direction::L},       {0xb05, 0xb0c, direction::L},
8386
    {0xb0f, 0xb10, direction::L},       {0xb13, 0xb28, direction::L},
8387
    {0xb2a, 0xb30, direction::L},       {0xb32, 0xb33, direction::L},
8388
    {0xb35, 0xb39, direction::L},       {0xb3c, 0xb3c, direction::NSM},
8389
    {0xb3d, 0xb3e, direction::L},       {0xb3f, 0xb3f, direction::NSM},
8390
    {0xb40, 0xb40, direction::L},       {0xb41, 0xb44, direction::NSM},
8391
    {0xb47, 0xb48, direction::L},       {0xb4b, 0xb4c, direction::L},
8392
    {0xb4d, 0xb4d, direction::NSM},     {0xb55, 0xb56, direction::NSM},
8393
    {0xb57, 0xb57, direction::L},       {0xb5c, 0xb5d, direction::L},
8394
    {0xb5f, 0xb61, direction::L},       {0xb62, 0xb63, direction::NSM},
8395
    {0xb66, 0xb77, direction::L},       {0xb82, 0xb82, direction::NSM},
8396
    {0xb83, 0xb83, direction::L},       {0xb85, 0xb8a, direction::L},
8397
    {0xb8e, 0xb90, direction::L},       {0xb92, 0xb95, direction::L},
8398
    {0xb99, 0xb9a, direction::L},       {0xb9c, 0xb9c, direction::L},
8399
    {0xb9e, 0xb9f, direction::L},       {0xba3, 0xba4, direction::L},
8400
    {0xba8, 0xbaa, direction::L},       {0xbae, 0xbb9, direction::L},
8401
    {0xbbe, 0xbbf, direction::L},       {0xbc0, 0xbc0, direction::NSM},
8402
    {0xbc1, 0xbc2, direction::L},       {0xbc6, 0xbc8, direction::L},
8403
    {0xbca, 0xbcc, direction::L},       {0xbcd, 0xbcd, direction::NSM},
8404
    {0xbd0, 0xbd0, direction::L},       {0xbd7, 0xbd7, direction::L},
8405
    {0xbe6, 0xbf2, direction::L},       {0xbf3, 0xbf8, direction::ON},
8406
    {0xbf9, 0xbf9, direction::ET},      {0xbfa, 0xbfa, direction::ON},
8407
    {0xc00, 0xc00, direction::NSM},     {0xc01, 0xc03, direction::L},
8408
    {0xc04, 0xc04, direction::NSM},     {0xc05, 0xc0c, direction::L},
8409
    {0xc0e, 0xc10, direction::L},       {0xc12, 0xc28, direction::L},
8410
    {0xc2a, 0xc39, direction::L},       {0xc3d, 0xc3d, direction::L},
8411
    {0xc3e, 0xc40, direction::NSM},     {0xc41, 0xc44, direction::L},
8412
    {0xc46, 0xc48, direction::NSM},     {0xc4a, 0xc4d, direction::NSM},
8413
    {0xc55, 0xc56, direction::NSM},     {0xc58, 0xc5a, direction::L},
8414
    {0xc60, 0xc61, direction::L},       {0xc62, 0xc63, direction::NSM},
8415
    {0xc66, 0xc6f, direction::L},       {0xc77, 0xc77, direction::L},
8416
    {0xc78, 0xc7e, direction::ON},      {0xc7f, 0xc80, direction::L},
8417
    {0xc81, 0xc81, direction::NSM},     {0xc82, 0xc8c, direction::L},
8418
    {0xc8e, 0xc90, direction::L},       {0xc92, 0xca8, direction::L},
8419
    {0xcaa, 0xcb3, direction::L},       {0xcb5, 0xcb9, direction::L},
8420
    {0xcbc, 0xcbc, direction::NSM},     {0xcbd, 0xcc4, direction::L},
8421
    {0xcc6, 0xcc8, direction::L},       {0xcca, 0xccb, direction::L},
8422
    {0xccc, 0xccd, direction::NSM},     {0xcd5, 0xcd6, direction::L},
8423
    {0xcde, 0xcde, direction::L},       {0xce0, 0xce1, direction::L},
8424
    {0xce2, 0xce3, direction::NSM},     {0xce6, 0xcef, direction::L},
8425
    {0xcf1, 0xcf2, direction::L},       {0xd00, 0xd01, direction::NSM},
8426
    {0xd02, 0xd0c, direction::L},       {0xd0e, 0xd10, direction::L},
8427
    {0xd12, 0xd3a, direction::L},       {0xd3b, 0xd3c, direction::NSM},
8428
    {0xd3d, 0xd40, direction::L},       {0xd41, 0xd44, direction::NSM},
8429
    {0xd46, 0xd48, direction::L},       {0xd4a, 0xd4c, direction::L},
8430
    {0xd4d, 0xd4d, direction::NSM},     {0xd4e, 0xd4f, direction::L},
8431
    {0xd54, 0xd61, direction::L},       {0xd62, 0xd63, direction::NSM},
8432
    {0xd66, 0xd7f, direction::L},       {0xd81, 0xd81, direction::NSM},
8433
    {0xd82, 0xd83, direction::L},       {0xd85, 0xd96, direction::L},
8434
    {0xd9a, 0xdb1, direction::L},       {0xdb3, 0xdbb, direction::L},
8435
    {0xdbd, 0xdbd, direction::L},       {0xdc0, 0xdc6, direction::L},
8436
    {0xdca, 0xdca, direction::NSM},     {0xdcf, 0xdd1, direction::L},
8437
    {0xdd2, 0xdd4, direction::NSM},     {0xdd6, 0xdd6, direction::NSM},
8438
    {0xdd8, 0xddf, direction::L},       {0xde6, 0xdef, direction::L},
8439
    {0xdf2, 0xdf4, direction::L},       {0xe01, 0xe30, direction::L},
8440
    {0xe31, 0xe31, direction::NSM},     {0xe32, 0xe33, direction::L},
8441
    {0xe34, 0xe3a, direction::NSM},     {0xe3f, 0xe3f, direction::ET},
8442
    {0xe40, 0xe46, direction::L},       {0xe47, 0xe4e, direction::NSM},
8443
    {0xe4f, 0xe5b, direction::L},       {0xe81, 0xe82, direction::L},
8444
    {0xe84, 0xe84, direction::L},       {0xe86, 0xe8a, direction::L},
8445
    {0xe8c, 0xea3, direction::L},       {0xea5, 0xea5, direction::L},
8446
    {0xea7, 0xeb0, direction::L},       {0xeb1, 0xeb1, direction::NSM},
8447
    {0xeb2, 0xeb3, direction::L},       {0xeb4, 0xebc, direction::NSM},
8448
    {0xebd, 0xebd, direction::L},       {0xec0, 0xec4, direction::L},
8449
    {0xec6, 0xec6, direction::L},       {0xec8, 0xecd, direction::NSM},
8450
    {0xed0, 0xed9, direction::L},       {0xedc, 0xedf, direction::L},
8451
    {0xf00, 0xf17, direction::L},       {0xf18, 0xf19, direction::NSM},
8452
    {0xf1a, 0xf34, direction::L},       {0xf35, 0xf35, direction::NSM},
8453
    {0xf36, 0xf36, direction::L},       {0xf37, 0xf37, direction::NSM},
8454
    {0xf38, 0xf38, direction::L},       {0xf39, 0xf39, direction::NSM},
8455
    {0xf3a, 0xf3d, direction::ON},      {0xf3e, 0xf47, direction::L},
8456
    {0xf49, 0xf6c, direction::L},       {0xf71, 0xf7e, direction::NSM},
8457
    {0xf7f, 0xf7f, direction::L},       {0xf80, 0xf84, direction::NSM},
8458
    {0xf85, 0xf85, direction::L},       {0xf86, 0xf87, direction::NSM},
8459
    {0xf88, 0xf8c, direction::L},       {0xf8d, 0xf97, direction::NSM},
8460
    {0xf99, 0xfbc, direction::NSM},     {0xfbe, 0xfc5, direction::L},
8461
    {0xfc6, 0xfc6, direction::NSM},     {0xfc7, 0xfcc, direction::L},
8462
    {0xfce, 0xfda, direction::L},       {0x1000, 0x102c, direction::L},
8463
    {0x102d, 0x1030, direction::NSM},   {0x1031, 0x1031, direction::L},
8464
    {0x1032, 0x1037, direction::NSM},   {0x1038, 0x1038, direction::L},
8465
    {0x1039, 0x103a, direction::NSM},   {0x103b, 0x103c, direction::L},
8466
    {0x103d, 0x103e, direction::NSM},   {0x103f, 0x1057, direction::L},
8467
    {0x1058, 0x1059, direction::NSM},   {0x105a, 0x105d, direction::L},
8468
    {0x105e, 0x1060, direction::NSM},   {0x1061, 0x1070, direction::L},
8469
    {0x1071, 0x1074, direction::NSM},   {0x1075, 0x1081, direction::L},
8470
    {0x1082, 0x1082, direction::NSM},   {0x1083, 0x1084, direction::L},
8471
    {0x1085, 0x1086, direction::NSM},   {0x1087, 0x108c, direction::L},
8472
    {0x108d, 0x108d, direction::NSM},   {0x108e, 0x109c, direction::L},
8473
    {0x109d, 0x109d, direction::NSM},   {0x109e, 0x10c5, direction::L},
8474
    {0x10c7, 0x10c7, direction::L},     {0x10cd, 0x10cd, direction::L},
8475
    {0x10d0, 0x1248, direction::L},     {0x124a, 0x124d, direction::L},
8476
    {0x1250, 0x1256, direction::L},     {0x1258, 0x1258, direction::L},
8477
    {0x125a, 0x125d, direction::L},     {0x1260, 0x1288, direction::L},
8478
    {0x128a, 0x128d, direction::L},     {0x1290, 0x12b0, direction::L},
8479
    {0x12b2, 0x12b5, direction::L},     {0x12b8, 0x12be, direction::L},
8480
    {0x12c0, 0x12c0, direction::L},     {0x12c2, 0x12c5, direction::L},
8481
    {0x12c8, 0x12d6, direction::L},     {0x12d8, 0x1310, direction::L},
8482
    {0x1312, 0x1315, direction::L},     {0x1318, 0x135a, direction::L},
8483
    {0x135d, 0x135f, direction::NSM},   {0x1360, 0x137c, direction::L},
8484
    {0x1380, 0x138f, direction::L},     {0x1390, 0x1399, direction::ON},
8485
    {0x13a0, 0x13f5, direction::L},     {0x13f8, 0x13fd, direction::L},
8486
    {0x1400, 0x1400, direction::ON},    {0x1401, 0x167f, direction::L},
8487
    {0x1680, 0x1680, direction::WS},    {0x1681, 0x169a, direction::L},
8488
    {0x169b, 0x169c, direction::ON},    {0x16a0, 0x16f8, direction::L},
8489
    {0x1700, 0x170c, direction::L},     {0x170e, 0x1711, direction::L},
8490
    {0x1712, 0x1714, direction::NSM},   {0x1720, 0x1731, direction::L},
8491
    {0x1732, 0x1734, direction::NSM},   {0x1735, 0x1736, direction::L},
8492
    {0x1740, 0x1751, direction::L},     {0x1752, 0x1753, direction::NSM},
8493
    {0x1760, 0x176c, direction::L},     {0x176e, 0x1770, direction::L},
8494
    {0x1772, 0x1773, direction::NSM},   {0x1780, 0x17b3, direction::L},
8495
    {0x17b4, 0x17b5, direction::NSM},   {0x17b6, 0x17b6, direction::L},
8496
    {0x17b7, 0x17bd, direction::NSM},   {0x17be, 0x17c5, direction::L},
8497
    {0x17c6, 0x17c6, direction::NSM},   {0x17c7, 0x17c8, direction::L},
8498
    {0x17c9, 0x17d3, direction::NSM},   {0x17d4, 0x17da, direction::L},
8499
    {0x17db, 0x17db, direction::ET},    {0x17dc, 0x17dc, direction::L},
8500
    {0x17dd, 0x17dd, direction::NSM},   {0x17e0, 0x17e9, direction::L},
8501
    {0x17f0, 0x17f9, direction::ON},    {0x1800, 0x180a, direction::ON},
8502
    {0x180b, 0x180d, direction::NSM},   {0x180e, 0x180e, direction::BN},
8503
    {0x1810, 0x1819, direction::L},     {0x1820, 0x1878, direction::L},
8504
    {0x1880, 0x1884, direction::L},     {0x1885, 0x1886, direction::NSM},
8505
    {0x1887, 0x18a8, direction::L},     {0x18a9, 0x18a9, direction::NSM},
8506
    {0x18aa, 0x18aa, direction::L},     {0x18b0, 0x18f5, direction::L},
8507
    {0x1900, 0x191e, direction::L},     {0x1920, 0x1922, direction::NSM},
8508
    {0x1923, 0x1926, direction::L},     {0x1927, 0x1928, direction::NSM},
8509
    {0x1929, 0x192b, direction::L},     {0x1930, 0x1931, direction::L},
8510
    {0x1932, 0x1932, direction::NSM},   {0x1933, 0x1938, direction::L},
8511
    {0x1939, 0x193b, direction::NSM},   {0x1940, 0x1940, direction::ON},
8512
    {0x1944, 0x1945, direction::ON},    {0x1946, 0x196d, direction::L},
8513
    {0x1970, 0x1974, direction::L},     {0x1980, 0x19ab, direction::L},
8514
    {0x19b0, 0x19c9, direction::L},     {0x19d0, 0x19da, direction::L},
8515
    {0x19de, 0x19ff, direction::ON},    {0x1a00, 0x1a16, direction::L},
8516
    {0x1a17, 0x1a18, direction::NSM},   {0x1a19, 0x1a1a, direction::L},
8517
    {0x1a1b, 0x1a1b, direction::NSM},   {0x1a1e, 0x1a55, direction::L},
8518
    {0x1a56, 0x1a56, direction::NSM},   {0x1a57, 0x1a57, direction::L},
8519
    {0x1a58, 0x1a5e, direction::NSM},   {0x1a60, 0x1a60, direction::NSM},
8520
    {0x1a61, 0x1a61, direction::L},     {0x1a62, 0x1a62, direction::NSM},
8521
    {0x1a63, 0x1a64, direction::L},     {0x1a65, 0x1a6c, direction::NSM},
8522
    {0x1a6d, 0x1a72, direction::L},     {0x1a73, 0x1a7c, direction::NSM},
8523
    {0x1a7f, 0x1a7f, direction::NSM},   {0x1a80, 0x1a89, direction::L},
8524
    {0x1a90, 0x1a99, direction::L},     {0x1aa0, 0x1aad, direction::L},
8525
    {0x1ab0, 0x1ac0, direction::NSM},   {0x1b00, 0x1b03, direction::NSM},
8526
    {0x1b04, 0x1b33, direction::L},     {0x1b34, 0x1b34, direction::NSM},
8527
    {0x1b35, 0x1b35, direction::L},     {0x1b36, 0x1b3a, direction::NSM},
8528
    {0x1b3b, 0x1b3b, direction::L},     {0x1b3c, 0x1b3c, direction::NSM},
8529
    {0x1b3d, 0x1b41, direction::L},     {0x1b42, 0x1b42, direction::NSM},
8530
    {0x1b43, 0x1b4b, direction::L},     {0x1b50, 0x1b6a, direction::L},
8531
    {0x1b6b, 0x1b73, direction::NSM},   {0x1b74, 0x1b7c, direction::L},
8532
    {0x1b80, 0x1b81, direction::NSM},   {0x1b82, 0x1ba1, direction::L},
8533
    {0x1ba2, 0x1ba5, direction::NSM},   {0x1ba6, 0x1ba7, direction::L},
8534
    {0x1ba8, 0x1ba9, direction::NSM},   {0x1baa, 0x1baa, direction::L},
8535
    {0x1bab, 0x1bad, direction::NSM},   {0x1bae, 0x1be5, direction::L},
8536
    {0x1be6, 0x1be6, direction::NSM},   {0x1be7, 0x1be7, direction::L},
8537
    {0x1be8, 0x1be9, direction::NSM},   {0x1bea, 0x1bec, direction::L},
8538
    {0x1bed, 0x1bed, direction::NSM},   {0x1bee, 0x1bee, direction::L},
8539
    {0x1bef, 0x1bf1, direction::NSM},   {0x1bf2, 0x1bf3, direction::L},
8540
    {0x1bfc, 0x1c2b, direction::L},     {0x1c2c, 0x1c33, direction::NSM},
8541
    {0x1c34, 0x1c35, direction::L},     {0x1c36, 0x1c37, direction::NSM},
8542
    {0x1c3b, 0x1c49, direction::L},     {0x1c4d, 0x1c88, direction::L},
8543
    {0x1c90, 0x1cba, direction::L},     {0x1cbd, 0x1cc7, direction::L},
8544
    {0x1cd0, 0x1cd2, direction::NSM},   {0x1cd3, 0x1cd3, direction::L},
8545
    {0x1cd4, 0x1ce0, direction::NSM},   {0x1ce1, 0x1ce1, direction::L},
8546
    {0x1ce2, 0x1ce8, direction::NSM},   {0x1ce9, 0x1cec, direction::L},
8547
    {0x1ced, 0x1ced, direction::NSM},   {0x1cee, 0x1cf3, direction::L},
8548
    {0x1cf4, 0x1cf4, direction::NSM},   {0x1cf5, 0x1cf7, direction::L},
8549
    {0x1cf8, 0x1cf9, direction::NSM},   {0x1cfa, 0x1cfa, direction::L},
8550
    {0x1d00, 0x1dbf, direction::L},     {0x1dc0, 0x1df9, direction::NSM},
8551
    {0x1dfb, 0x1dff, direction::NSM},   {0x1e00, 0x1f15, direction::L},
8552
    {0x1f18, 0x1f1d, direction::L},     {0x1f20, 0x1f45, direction::L},
8553
    {0x1f48, 0x1f4d, direction::L},     {0x1f50, 0x1f57, direction::L},
8554
    {0x1f59, 0x1f59, direction::L},     {0x1f5b, 0x1f5b, direction::L},
8555
    {0x1f5d, 0x1f5d, direction::L},     {0x1f5f, 0x1f7d, direction::L},
8556
    {0x1f80, 0x1fb4, direction::L},     {0x1fb6, 0x1fbc, direction::L},
8557
    {0x1fbd, 0x1fbd, direction::ON},    {0x1fbe, 0x1fbe, direction::L},
8558
    {0x1fbf, 0x1fc1, direction::ON},    {0x1fc2, 0x1fc4, direction::L},
8559
    {0x1fc6, 0x1fcc, direction::L},     {0x1fcd, 0x1fcf, direction::ON},
8560
    {0x1fd0, 0x1fd3, direction::L},     {0x1fd6, 0x1fdb, direction::L},
8561
    {0x1fdd, 0x1fdf, direction::ON},    {0x1fe0, 0x1fec, direction::L},
8562
    {0x1fed, 0x1fef, direction::ON},    {0x1ff2, 0x1ff4, direction::L},
8563
    {0x1ff6, 0x1ffc, direction::L},     {0x1ffd, 0x1ffe, direction::ON},
8564
    {0x2000, 0x200a, direction::WS},    {0x200b, 0x200d, direction::BN},
8565
    {0x200e, 0x200e, direction::L},     {0x200f, 0x200f, direction::R},
8566
    {0x2010, 0x2027, direction::ON},    {0x2028, 0x2028, direction::WS},
8567
    {0x2029, 0x2029, direction::B},     {0x202a, 0x202a, direction::LRE},
8568
    {0x202b, 0x202b, direction::RLE},   {0x202c, 0x202c, direction::PDF},
8569
    {0x202d, 0x202d, direction::LRO},   {0x202e, 0x202e, direction::RLO},
8570
    {0x202f, 0x202f, direction::CS},    {0x2030, 0x2034, direction::ET},
8571
    {0x2035, 0x2043, direction::ON},    {0x2044, 0x2044, direction::CS},
8572
    {0x2045, 0x205e, direction::ON},    {0x205f, 0x205f, direction::WS},
8573
    {0x2060, 0x2064, direction::BN},    {0x2066, 0x2066, direction::LRI},
8574
    {0x2067, 0x2067, direction::RLI},   {0x2068, 0x2068, direction::FSI},
8575
    {0x2069, 0x2069, direction::PDI},   {0x206a, 0x206f, direction::BN},
8576
    {0x2070, 0x2070, direction::EN},    {0x2071, 0x2071, direction::L},
8577
    {0x2074, 0x2079, direction::EN},    {0x207a, 0x207b, direction::ES},
8578
    {0x207c, 0x207e, direction::ON},    {0x207f, 0x207f, direction::L},
8579
    {0x2080, 0x2089, direction::EN},    {0x208a, 0x208b, direction::ES},
8580
    {0x208c, 0x208e, direction::ON},    {0x2090, 0x209c, direction::L},
8581
    {0x20a0, 0x20bf, direction::ET},    {0x20d0, 0x20f0, direction::NSM},
8582
    {0x2100, 0x2101, direction::ON},    {0x2102, 0x2102, direction::L},
8583
    {0x2103, 0x2106, direction::ON},    {0x2107, 0x2107, direction::L},
8584
    {0x2108, 0x2109, direction::ON},    {0x210a, 0x2113, direction::L},
8585
    {0x2114, 0x2114, direction::ON},    {0x2115, 0x2115, direction::L},
8586
    {0x2116, 0x2118, direction::ON},    {0x2119, 0x211d, direction::L},
8587
    {0x211e, 0x2123, direction::ON},    {0x2124, 0x2124, direction::L},
8588
    {0x2125, 0x2125, direction::ON},    {0x2126, 0x2126, direction::L},
8589
    {0x2127, 0x2127, direction::ON},    {0x2128, 0x2128, direction::L},
8590
    {0x2129, 0x2129, direction::ON},    {0x212a, 0x212d, direction::L},
8591
    {0x212e, 0x212e, direction::ET},    {0x212f, 0x2139, direction::L},
8592
    {0x213a, 0x213b, direction::ON},    {0x213c, 0x213f, direction::L},
8593
    {0x2140, 0x2144, direction::ON},    {0x2145, 0x2149, direction::L},
8594
    {0x214a, 0x214d, direction::ON},    {0x214e, 0x214f, direction::L},
8595
    {0x2150, 0x215f, direction::ON},    {0x2160, 0x2188, direction::L},
8596
    {0x2189, 0x218b, direction::ON},    {0x2190, 0x2211, direction::ON},
8597
    {0x2212, 0x2212, direction::ES},    {0x2213, 0x2213, direction::ET},
8598
    {0x2214, 0x2335, direction::ON},    {0x2336, 0x237a, direction::L},
8599
    {0x237b, 0x2394, direction::ON},    {0x2395, 0x2395, direction::L},
8600
    {0x2396, 0x2426, direction::ON},    {0x2440, 0x244a, direction::ON},
8601
    {0x2460, 0x2487, direction::ON},    {0x2488, 0x249b, direction::EN},
8602
    {0x249c, 0x24e9, direction::L},     {0x24ea, 0x26ab, direction::ON},
8603
    {0x26ac, 0x26ac, direction::L},     {0x26ad, 0x27ff, direction::ON},
8604
    {0x2800, 0x28ff, direction::L},     {0x2900, 0x2b73, direction::ON},
8605
    {0x2b76, 0x2b95, direction::ON},    {0x2b97, 0x2bff, direction::ON},
8606
    {0x2c00, 0x2c2e, direction::L},     {0x2c30, 0x2c5e, direction::L},
8607
    {0x2c60, 0x2ce4, direction::L},     {0x2ce5, 0x2cea, direction::ON},
8608
    {0x2ceb, 0x2cee, direction::L},     {0x2cef, 0x2cf1, direction::NSM},
8609
    {0x2cf2, 0x2cf3, direction::L},     {0x2cf9, 0x2cff, direction::ON},
8610
    {0x2d00, 0x2d25, direction::L},     {0x2d27, 0x2d27, direction::L},
8611
    {0x2d2d, 0x2d2d, direction::L},     {0x2d30, 0x2d67, direction::L},
8612
    {0x2d6f, 0x2d70, direction::L},     {0x2d7f, 0x2d7f, direction::NSM},
8613
    {0x2d80, 0x2d96, direction::L},     {0x2da0, 0x2da6, direction::L},
8614
    {0x2da8, 0x2dae, direction::L},     {0x2db0, 0x2db6, direction::L},
8615
    {0x2db8, 0x2dbe, direction::L},     {0x2dc0, 0x2dc6, direction::L},
8616
    {0x2dc8, 0x2dce, direction::L},     {0x2dd0, 0x2dd6, direction::L},
8617
    {0x2dd8, 0x2dde, direction::L},     {0x2de0, 0x2dff, direction::NSM},
8618
    {0x2e00, 0x2e52, direction::ON},    {0x2e80, 0x2e99, direction::ON},
8619
    {0x2e9b, 0x2ef3, direction::ON},    {0x2f00, 0x2fd5, direction::ON},
8620
    {0x2ff0, 0x2ffb, direction::ON},    {0x3000, 0x3000, direction::WS},
8621
    {0x3001, 0x3004, direction::ON},    {0x3005, 0x3007, direction::L},
8622
    {0x3008, 0x3020, direction::ON},    {0x3021, 0x3029, direction::L},
8623
    {0x302a, 0x302d, direction::NSM},   {0x302e, 0x302f, direction::L},
8624
    {0x3030, 0x3030, direction::ON},    {0x3031, 0x3035, direction::L},
8625
    {0x3036, 0x3037, direction::ON},    {0x3038, 0x303c, direction::L},
8626
    {0x303d, 0x303f, direction::ON},    {0x3041, 0x3096, direction::L},
8627
    {0x3099, 0x309a, direction::NSM},   {0x309b, 0x309c, direction::ON},
8628
    {0x309d, 0x309f, direction::L},     {0x30a0, 0x30a0, direction::ON},
8629
    {0x30a1, 0x30fa, direction::L},     {0x30fb, 0x30fb, direction::ON},
8630
    {0x30fc, 0x30ff, direction::L},     {0x3105, 0x312f, direction::L},
8631
    {0x3131, 0x318e, direction::L},     {0x3190, 0x31bf, direction::L},
8632
    {0x31c0, 0x31e3, direction::ON},    {0x31f0, 0x321c, direction::L},
8633
    {0x321d, 0x321e, direction::ON},    {0x3220, 0x324f, direction::L},
8634
    {0x3250, 0x325f, direction::ON},    {0x3260, 0x327b, direction::L},
8635
    {0x327c, 0x327e, direction::ON},    {0x327f, 0x32b0, direction::L},
8636
    {0x32b1, 0x32bf, direction::ON},    {0x32c0, 0x32cb, direction::L},
8637
    {0x32cc, 0x32cf, direction::ON},    {0x32d0, 0x3376, direction::L},
8638
    {0x3377, 0x337a, direction::ON},    {0x337b, 0x33dd, direction::L},
8639
    {0x33de, 0x33df, direction::ON},    {0x33e0, 0x33fe, direction::L},
8640
    {0x33ff, 0x33ff, direction::ON},    {0x3400, 0x4dbf, direction::L},
8641
    {0x4dc0, 0x4dff, direction::ON},    {0x4e00, 0x9ffc, direction::L},
8642
    {0xa000, 0xa48c, direction::L},     {0xa490, 0xa4c6, direction::ON},
8643
    {0xa4d0, 0xa60c, direction::L},     {0xa60d, 0xa60f, direction::ON},
8644
    {0xa610, 0xa62b, direction::L},     {0xa640, 0xa66e, direction::L},
8645
    {0xa66f, 0xa672, direction::NSM},   {0xa673, 0xa673, direction::ON},
8646
    {0xa674, 0xa67d, direction::NSM},   {0xa67e, 0xa67f, direction::ON},
8647
    {0xa680, 0xa69d, direction::L},     {0xa69e, 0xa69f, direction::NSM},
8648
    {0xa6a0, 0xa6ef, direction::L},     {0xa6f0, 0xa6f1, direction::NSM},
8649
    {0xa6f2, 0xa6f7, direction::L},     {0xa700, 0xa721, direction::ON},
8650
    {0xa722, 0xa787, direction::L},     {0xa788, 0xa788, direction::ON},
8651
    {0xa789, 0xa7bf, direction::L},     {0xa7c2, 0xa7ca, direction::L},
8652
    {0xa7f5, 0xa801, direction::L},     {0xa802, 0xa802, direction::NSM},
8653
    {0xa803, 0xa805, direction::L},     {0xa806, 0xa806, direction::NSM},
8654
    {0xa807, 0xa80a, direction::L},     {0xa80b, 0xa80b, direction::NSM},
8655
    {0xa80c, 0xa824, direction::L},     {0xa825, 0xa826, direction::NSM},
8656
    {0xa827, 0xa827, direction::L},     {0xa828, 0xa82b, direction::ON},
8657
    {0xa82c, 0xa82c, direction::NSM},   {0xa830, 0xa837, direction::L},
8658
    {0xa838, 0xa839, direction::ET},    {0xa840, 0xa873, direction::L},
8659
    {0xa874, 0xa877, direction::ON},    {0xa880, 0xa8c3, direction::L},
8660
    {0xa8c4, 0xa8c5, direction::NSM},   {0xa8ce, 0xa8d9, direction::L},
8661
    {0xa8e0, 0xa8f1, direction::NSM},   {0xa8f2, 0xa8fe, direction::L},
8662
    {0xa8ff, 0xa8ff, direction::NSM},   {0xa900, 0xa925, direction::L},
8663
    {0xa926, 0xa92d, direction::NSM},   {0xa92e, 0xa946, direction::L},
8664
    {0xa947, 0xa951, direction::NSM},   {0xa952, 0xa953, direction::L},
8665
    {0xa95f, 0xa97c, direction::L},     {0xa980, 0xa982, direction::NSM},
8666
    {0xa983, 0xa9b2, direction::L},     {0xa9b3, 0xa9b3, direction::NSM},
8667
    {0xa9b4, 0xa9b5, direction::L},     {0xa9b6, 0xa9b9, direction::NSM},
8668
    {0xa9ba, 0xa9bb, direction::L},     {0xa9bc, 0xa9bd, direction::NSM},
8669
    {0xa9be, 0xa9cd, direction::L},     {0xa9cf, 0xa9d9, direction::L},
8670
    {0xa9de, 0xa9e4, direction::L},     {0xa9e5, 0xa9e5, direction::NSM},
8671
    {0xa9e6, 0xa9fe, direction::L},     {0xaa00, 0xaa28, direction::L},
8672
    {0xaa29, 0xaa2e, direction::NSM},   {0xaa2f, 0xaa30, direction::L},
8673
    {0xaa31, 0xaa32, direction::NSM},   {0xaa33, 0xaa34, direction::L},
8674
    {0xaa35, 0xaa36, direction::NSM},   {0xaa40, 0xaa42, direction::L},
8675
    {0xaa43, 0xaa43, direction::NSM},   {0xaa44, 0xaa4b, direction::L},
8676
    {0xaa4c, 0xaa4c, direction::NSM},   {0xaa4d, 0xaa4d, direction::L},
8677
    {0xaa50, 0xaa59, direction::L},     {0xaa5c, 0xaa7b, direction::L},
8678
    {0xaa7c, 0xaa7c, direction::NSM},   {0xaa7d, 0xaaaf, direction::L},
8679
    {0xaab0, 0xaab0, direction::NSM},   {0xaab1, 0xaab1, direction::L},
8680
    {0xaab2, 0xaab4, direction::NSM},   {0xaab5, 0xaab6, direction::L},
8681
    {0xaab7, 0xaab8, direction::NSM},   {0xaab9, 0xaabd, direction::L},
8682
    {0xaabe, 0xaabf, direction::NSM},   {0xaac0, 0xaac0, direction::L},
8683
    {0xaac1, 0xaac1, direction::NSM},   {0xaac2, 0xaac2, direction::L},
8684
    {0xaadb, 0xaaeb, direction::L},     {0xaaec, 0xaaed, direction::NSM},
8685
    {0xaaee, 0xaaf5, direction::L},     {0xaaf6, 0xaaf6, direction::NSM},
8686
    {0xab01, 0xab06, direction::L},     {0xab09, 0xab0e, direction::L},
8687
    {0xab11, 0xab16, direction::L},     {0xab20, 0xab26, direction::L},
8688
    {0xab28, 0xab2e, direction::L},     {0xab30, 0xab69, direction::L},
8689
    {0xab6a, 0xab6b, direction::ON},    {0xab70, 0xabe4, direction::L},
8690
    {0xabe5, 0xabe5, direction::NSM},   {0xabe6, 0xabe7, direction::L},
8691
    {0xabe8, 0xabe8, direction::NSM},   {0xabe9, 0xabec, direction::L},
8692
    {0xabed, 0xabed, direction::NSM},   {0xabf0, 0xabf9, direction::L},
8693
    {0xac00, 0xd7a3, direction::L},     {0xd7b0, 0xd7c6, direction::L},
8694
    {0xd7cb, 0xd7fb, direction::L},     {0xd800, 0xfa6d, direction::L},
8695
    {0xfa70, 0xfad9, direction::L},     {0xfb00, 0xfb06, direction::L},
8696
    {0xfb13, 0xfb17, direction::L},     {0xfb1d, 0xfb1d, direction::R},
8697
    {0xfb1e, 0xfb1e, direction::NSM},   {0xfb1f, 0xfb28, direction::R},
8698
    {0xfb29, 0xfb29, direction::ES},    {0xfb2a, 0xfb36, direction::R},
8699
    {0xfb38, 0xfb3c, direction::R},     {0xfb3e, 0xfb3e, direction::R},
8700
    {0xfb40, 0xfb41, direction::R},     {0xfb43, 0xfb44, direction::R},
8701
    {0xfb46, 0xfb4f, direction::R},     {0xfb50, 0xfbc1, direction::AL},
8702
    {0xfbd3, 0xfd3d, direction::AL},    {0xfd3e, 0xfd3f, direction::ON},
8703
    {0xfd50, 0xfd8f, direction::AL},    {0xfd92, 0xfdc7, direction::AL},
8704
    {0xfdf0, 0xfdfc, direction::AL},    {0xfdfd, 0xfdfd, direction::ON},
8705
    {0xfe00, 0xfe0f, direction::NSM},   {0xfe10, 0xfe19, direction::ON},
8706
    {0xfe20, 0xfe2f, direction::NSM},   {0xfe30, 0xfe4f, direction::ON},
8707
    {0xfe50, 0xfe50, direction::CS},    {0xfe51, 0xfe51, direction::ON},
8708
    {0xfe52, 0xfe52, direction::CS},    {0xfe54, 0xfe54, direction::ON},
8709
    {0xfe55, 0xfe55, direction::CS},    {0xfe56, 0xfe5e, direction::ON},
8710
    {0xfe5f, 0xfe5f, direction::ET},    {0xfe60, 0xfe61, direction::ON},
8711
    {0xfe62, 0xfe63, direction::ES},    {0xfe64, 0xfe66, direction::ON},
8712
    {0xfe68, 0xfe68, direction::ON},    {0xfe69, 0xfe6a, direction::ET},
8713
    {0xfe6b, 0xfe6b, direction::ON},    {0xfe70, 0xfe74, direction::AL},
8714
    {0xfe76, 0xfefc, direction::AL},    {0xfeff, 0xfeff, direction::BN},
8715
    {0xff01, 0xff02, direction::ON},    {0xff03, 0xff05, direction::ET},
8716
    {0xff06, 0xff0a, direction::ON},    {0xff0b, 0xff0b, direction::ES},
8717
    {0xff0c, 0xff0c, direction::CS},    {0xff0d, 0xff0d, direction::ES},
8718
    {0xff0e, 0xff0f, direction::CS},    {0xff10, 0xff19, direction::EN},
8719
    {0xff1a, 0xff1a, direction::CS},    {0xff1b, 0xff20, direction::ON},
8720
    {0xff21, 0xff3a, direction::L},     {0xff3b, 0xff40, direction::ON},
8721
    {0xff41, 0xff5a, direction::L},     {0xff5b, 0xff65, direction::ON},
8722
    {0xff66, 0xffbe, direction::L},     {0xffc2, 0xffc7, direction::L},
8723
    {0xffca, 0xffcf, direction::L},     {0xffd2, 0xffd7, direction::L},
8724
    {0xffda, 0xffdc, direction::L},     {0xffe0, 0xffe1, direction::ET},
8725
    {0xffe2, 0xffe4, direction::ON},    {0xffe5, 0xffe6, direction::ET},
8726
    {0xffe8, 0xffee, direction::ON},    {0xfff9, 0xfffd, direction::ON},
8727
    {0x10000, 0x1000b, direction::L},   {0x1000d, 0x10026, direction::L},
8728
    {0x10028, 0x1003a, direction::L},   {0x1003c, 0x1003d, direction::L},
8729
    {0x1003f, 0x1004d, direction::L},   {0x10050, 0x1005d, direction::L},
8730
    {0x10080, 0x100fa, direction::L},   {0x10100, 0x10100, direction::L},
8731
    {0x10101, 0x10101, direction::ON},  {0x10102, 0x10102, direction::L},
8732
    {0x10107, 0x10133, direction::L},   {0x10137, 0x1013f, direction::L},
8733
    {0x10140, 0x1018c, direction::ON},  {0x1018d, 0x1018e, direction::L},
8734
    {0x10190, 0x1019c, direction::ON},  {0x101a0, 0x101a0, direction::ON},
8735
    {0x101d0, 0x101fc, direction::L},   {0x101fd, 0x101fd, direction::NSM},
8736
    {0x10280, 0x1029c, direction::L},   {0x102a0, 0x102d0, direction::L},
8737
    {0x102e0, 0x102e0, direction::NSM}, {0x102e1, 0x102fb, direction::EN},
8738
    {0x10300, 0x10323, direction::L},   {0x1032d, 0x1034a, direction::L},
8739
    {0x10350, 0x10375, direction::L},   {0x10376, 0x1037a, direction::NSM},
8740
    {0x10380, 0x1039d, direction::L},   {0x1039f, 0x103c3, direction::L},
8741
    {0x103c8, 0x103d5, direction::L},   {0x10400, 0x1049d, direction::L},
8742
    {0x104a0, 0x104a9, direction::L},   {0x104b0, 0x104d3, direction::L},
8743
    {0x104d8, 0x104fb, direction::L},   {0x10500, 0x10527, direction::L},
8744
    {0x10530, 0x10563, direction::L},   {0x1056f, 0x1056f, direction::L},
8745
    {0x10600, 0x10736, direction::L},   {0x10740, 0x10755, direction::L},
8746
    {0x10760, 0x10767, direction::L},   {0x10800, 0x10805, direction::R},
8747
    {0x10808, 0x10808, direction::R},   {0x1080a, 0x10835, direction::R},
8748
    {0x10837, 0x10838, direction::R},   {0x1083c, 0x1083c, direction::R},
8749
    {0x1083f, 0x10855, direction::R},   {0x10857, 0x1089e, direction::R},
8750
    {0x108a7, 0x108af, direction::R},   {0x108e0, 0x108f2, direction::R},
8751
    {0x108f4, 0x108f5, direction::R},   {0x108fb, 0x1091b, direction::R},
8752
    {0x1091f, 0x1091f, direction::ON},  {0x10920, 0x10939, direction::R},
8753
    {0x1093f, 0x1093f, direction::R},   {0x10980, 0x109b7, direction::R},
8754
    {0x109bc, 0x109cf, direction::R},   {0x109d2, 0x10a00, direction::R},
8755
    {0x10a01, 0x10a03, direction::NSM}, {0x10a05, 0x10a06, direction::NSM},
8756
    {0x10a0c, 0x10a0f, direction::NSM}, {0x10a10, 0x10a13, direction::R},
8757
    {0x10a15, 0x10a17, direction::R},   {0x10a19, 0x10a35, direction::R},
8758
    {0x10a38, 0x10a3a, direction::NSM}, {0x10a3f, 0x10a3f, direction::NSM},
8759
    {0x10a40, 0x10a48, direction::R},   {0x10a50, 0x10a58, direction::R},
8760
    {0x10a60, 0x10a9f, direction::R},   {0x10ac0, 0x10ae4, direction::R},
8761
    {0x10ae5, 0x10ae6, direction::NSM}, {0x10aeb, 0x10af6, direction::R},
8762
    {0x10b00, 0x10b35, direction::R},   {0x10b39, 0x10b3f, direction::ON},
8763
    {0x10b40, 0x10b55, direction::R},   {0x10b58, 0x10b72, direction::R},
8764
    {0x10b78, 0x10b91, direction::R},   {0x10b99, 0x10b9c, direction::R},
8765
    {0x10ba9, 0x10baf, direction::R},   {0x10c00, 0x10c48, direction::R},
8766
    {0x10c80, 0x10cb2, direction::R},   {0x10cc0, 0x10cf2, direction::R},
8767
    {0x10cfa, 0x10cff, direction::R},   {0x10d00, 0x10d23, direction::AL},
8768
    {0x10d24, 0x10d27, direction::NSM}, {0x10d30, 0x10d39, direction::AN},
8769
    {0x10e60, 0x10e7e, direction::AN},  {0x10e80, 0x10ea9, direction::R},
8770
    {0x10eab, 0x10eac, direction::NSM}, {0x10ead, 0x10ead, direction::R},
8771
    {0x10eb0, 0x10eb1, direction::R},   {0x10f00, 0x10f27, direction::R},
8772
    {0x10f30, 0x10f45, direction::AL},  {0x10f46, 0x10f50, direction::NSM},
8773
    {0x10f51, 0x10f59, direction::AL},  {0x10fb0, 0x10fcb, direction::R},
8774
    {0x10fe0, 0x10ff6, direction::R},   {0x11000, 0x11000, direction::L},
8775
    {0x11001, 0x11001, direction::NSM}, {0x11002, 0x11037, direction::L},
8776
    {0x11038, 0x11046, direction::NSM}, {0x11047, 0x1104d, direction::L},
8777
    {0x11052, 0x11065, direction::ON},  {0x11066, 0x1106f, direction::L},
8778
    {0x1107f, 0x11081, direction::NSM}, {0x11082, 0x110b2, direction::L},
8779
    {0x110b3, 0x110b6, direction::NSM}, {0x110b7, 0x110b8, direction::L},
8780
    {0x110b9, 0x110ba, direction::NSM}, {0x110bb, 0x110c1, direction::L},
8781
    {0x110cd, 0x110cd, direction::L},   {0x110d0, 0x110e8, direction::L},
8782
    {0x110f0, 0x110f9, direction::L},   {0x11100, 0x11102, direction::NSM},
8783
    {0x11103, 0x11126, direction::L},   {0x11127, 0x1112b, direction::NSM},
8784
    {0x1112c, 0x1112c, direction::L},   {0x1112d, 0x11134, direction::NSM},
8785
    {0x11136, 0x11147, direction::L},   {0x11150, 0x11172, direction::L},
8786
    {0x11173, 0x11173, direction::NSM}, {0x11174, 0x11176, direction::L},
8787
    {0x11180, 0x11181, direction::NSM}, {0x11182, 0x111b5, direction::L},
8788
    {0x111b6, 0x111be, direction::NSM}, {0x111bf, 0x111c8, direction::L},
8789
    {0x111c9, 0x111cc, direction::NSM}, {0x111cd, 0x111ce, direction::L},
8790
    {0x111cf, 0x111cf, direction::NSM}, {0x111d0, 0x111df, direction::L},
8791
    {0x111e1, 0x111f4, direction::L},   {0x11200, 0x11211, direction::L},
8792
    {0x11213, 0x1122e, direction::L},   {0x1122f, 0x11231, direction::NSM},
8793
    {0x11232, 0x11233, direction::L},   {0x11234, 0x11234, direction::NSM},
8794
    {0x11235, 0x11235, direction::L},   {0x11236, 0x11237, direction::NSM},
8795
    {0x11238, 0x1123d, direction::L},   {0x1123e, 0x1123e, direction::NSM},
8796
    {0x11280, 0x11286, direction::L},   {0x11288, 0x11288, direction::L},
8797
    {0x1128a, 0x1128d, direction::L},   {0x1128f, 0x1129d, direction::L},
8798
    {0x1129f, 0x112a9, direction::L},   {0x112b0, 0x112de, direction::L},
8799
    {0x112df, 0x112df, direction::NSM}, {0x112e0, 0x112e2, direction::L},
8800
    {0x112e3, 0x112ea, direction::NSM}, {0x112f0, 0x112f9, direction::L},
8801
    {0x11300, 0x11301, direction::NSM}, {0x11302, 0x11303, direction::L},
8802
    {0x11305, 0x1130c, direction::L},   {0x1130f, 0x11310, direction::L},
8803
    {0x11313, 0x11328, direction::L},   {0x1132a, 0x11330, direction::L},
8804
    {0x11332, 0x11333, direction::L},   {0x11335, 0x11339, direction::L},
8805
    {0x1133b, 0x1133c, direction::NSM}, {0x1133d, 0x1133f, direction::L},
8806
    {0x11340, 0x11340, direction::NSM}, {0x11341, 0x11344, direction::L},
8807
    {0x11347, 0x11348, direction::L},   {0x1134b, 0x1134d, direction::L},
8808
    {0x11350, 0x11350, direction::L},   {0x11357, 0x11357, direction::L},
8809
    {0x1135d, 0x11363, direction::L},   {0x11366, 0x1136c, direction::NSM},
8810
    {0x11370, 0x11374, direction::NSM}, {0x11400, 0x11437, direction::L},
8811
    {0x11438, 0x1143f, direction::NSM}, {0x11440, 0x11441, direction::L},
8812
    {0x11442, 0x11444, direction::NSM}, {0x11445, 0x11445, direction::L},
8813
    {0x11446, 0x11446, direction::NSM}, {0x11447, 0x1145b, direction::L},
8814
    {0x1145d, 0x1145d, direction::L},   {0x1145e, 0x1145e, direction::NSM},
8815
    {0x1145f, 0x11461, direction::L},   {0x11480, 0x114b2, direction::L},
8816
    {0x114b3, 0x114b8, direction::NSM}, {0x114b9, 0x114b9, direction::L},
8817
    {0x114ba, 0x114ba, direction::NSM}, {0x114bb, 0x114be, direction::L},
8818
    {0x114bf, 0x114c0, direction::NSM}, {0x114c1, 0x114c1, direction::L},
8819
    {0x114c2, 0x114c3, direction::NSM}, {0x114c4, 0x114c7, direction::L},
8820
    {0x114d0, 0x114d9, direction::L},   {0x11580, 0x115b1, direction::L},
8821
    {0x115b2, 0x115b5, direction::NSM}, {0x115b8, 0x115bb, direction::L},
8822
    {0x115bc, 0x115bd, direction::NSM}, {0x115be, 0x115be, direction::L},
8823
    {0x115bf, 0x115c0, direction::NSM}, {0x115c1, 0x115db, direction::L},
8824
    {0x115dc, 0x115dd, direction::NSM}, {0x11600, 0x11632, direction::L},
8825
    {0x11633, 0x1163a, direction::NSM}, {0x1163b, 0x1163c, direction::L},
8826
    {0x1163d, 0x1163d, direction::NSM}, {0x1163e, 0x1163e, direction::L},
8827
    {0x1163f, 0x11640, direction::NSM}, {0x11641, 0x11644, direction::L},
8828
    {0x11650, 0x11659, direction::L},   {0x11660, 0x1166c, direction::ON},
8829
    {0x11680, 0x116aa, direction::L},   {0x116ab, 0x116ab, direction::NSM},
8830
    {0x116ac, 0x116ac, direction::L},   {0x116ad, 0x116ad, direction::NSM},
8831
    {0x116ae, 0x116af, direction::L},   {0x116b0, 0x116b5, direction::NSM},
8832
    {0x116b6, 0x116b6, direction::L},   {0x116b7, 0x116b7, direction::NSM},
8833
    {0x116b8, 0x116b8, direction::L},   {0x116c0, 0x116c9, direction::L},
8834
    {0x11700, 0x1171a, direction::L},   {0x1171d, 0x1171f, direction::NSM},
8835
    {0x11720, 0x11721, direction::L},   {0x11722, 0x11725, direction::NSM},
8836
    {0x11726, 0x11726, direction::L},   {0x11727, 0x1172b, direction::NSM},
8837
    {0x11730, 0x1173f, direction::L},   {0x11800, 0x1182e, direction::L},
8838
    {0x1182f, 0x11837, direction::NSM}, {0x11838, 0x11838, direction::L},
8839
    {0x11839, 0x1183a, direction::NSM}, {0x1183b, 0x1183b, direction::L},
8840
    {0x118a0, 0x118f2, direction::L},   {0x118ff, 0x11906, direction::L},
8841
    {0x11909, 0x11909, direction::L},   {0x1190c, 0x11913, direction::L},
8842
    {0x11915, 0x11916, direction::L},   {0x11918, 0x11935, direction::L},
8843
    {0x11937, 0x11938, direction::L},   {0x1193b, 0x1193c, direction::NSM},
8844
    {0x1193d, 0x1193d, direction::L},   {0x1193e, 0x1193e, direction::NSM},
8845
    {0x1193f, 0x11942, direction::L},   {0x11943, 0x11943, direction::NSM},
8846
    {0x11944, 0x11946, direction::L},   {0x11950, 0x11959, direction::L},
8847
    {0x119a0, 0x119a7, direction::L},   {0x119aa, 0x119d3, direction::L},
8848
    {0x119d4, 0x119d7, direction::NSM}, {0x119da, 0x119db, direction::NSM},
8849
    {0x119dc, 0x119df, direction::L},   {0x119e0, 0x119e0, direction::NSM},
8850
    {0x119e1, 0x119e4, direction::L},   {0x11a00, 0x11a00, direction::L},
8851
    {0x11a01, 0x11a06, direction::NSM}, {0x11a07, 0x11a08, direction::L},
8852
    {0x11a09, 0x11a0a, direction::NSM}, {0x11a0b, 0x11a32, direction::L},
8853
    {0x11a33, 0x11a38, direction::NSM}, {0x11a39, 0x11a3a, direction::L},
8854
    {0x11a3b, 0x11a3e, direction::NSM}, {0x11a3f, 0x11a46, direction::L},
8855
    {0x11a47, 0x11a47, direction::NSM}, {0x11a50, 0x11a50, direction::L},
8856
    {0x11a51, 0x11a56, direction::NSM}, {0x11a57, 0x11a58, direction::L},
8857
    {0x11a59, 0x11a5b, direction::NSM}, {0x11a5c, 0x11a89, direction::L},
8858
    {0x11a8a, 0x11a96, direction::NSM}, {0x11a97, 0x11a97, direction::L},
8859
    {0x11a98, 0x11a99, direction::NSM}, {0x11a9a, 0x11aa2, direction::L},
8860
    {0x11ac0, 0x11af8, direction::L},   {0x11c00, 0x11c08, direction::L},
8861
    {0x11c0a, 0x11c2f, direction::L},   {0x11c30, 0x11c36, direction::NSM},
8862
    {0x11c38, 0x11c3d, direction::NSM}, {0x11c3e, 0x11c45, direction::L},
8863
    {0x11c50, 0x11c6c, direction::L},   {0x11c70, 0x11c8f, direction::L},
8864
    {0x11c92, 0x11ca7, direction::NSM}, {0x11ca9, 0x11ca9, direction::L},
8865
    {0x11caa, 0x11cb0, direction::NSM}, {0x11cb1, 0x11cb1, direction::L},
8866
    {0x11cb2, 0x11cb3, direction::NSM}, {0x11cb4, 0x11cb4, direction::L},
8867
    {0x11cb5, 0x11cb6, direction::NSM}, {0x11d00, 0x11d06, direction::L},
8868
    {0x11d08, 0x11d09, direction::L},   {0x11d0b, 0x11d30, direction::L},
8869
    {0x11d31, 0x11d36, direction::NSM}, {0x11d3a, 0x11d3a, direction::NSM},
8870
    {0x11d3c, 0x11d3d, direction::NSM}, {0x11d3f, 0x11d45, direction::NSM},
8871
    {0x11d46, 0x11d46, direction::L},   {0x11d47, 0x11d47, direction::NSM},
8872
    {0x11d50, 0x11d59, direction::L},   {0x11d60, 0x11d65, direction::L},
8873
    {0x11d67, 0x11d68, direction::L},   {0x11d6a, 0x11d8e, direction::L},
8874
    {0x11d90, 0x11d91, direction::NSM}, {0x11d93, 0x11d94, direction::L},
8875
    {0x11d95, 0x11d95, direction::NSM}, {0x11d96, 0x11d96, direction::L},
8876
    {0x11d97, 0x11d97, direction::NSM}, {0x11d98, 0x11d98, direction::L},
8877
    {0x11da0, 0x11da9, direction::L},   {0x11ee0, 0x11ef2, direction::L},
8878
    {0x11ef3, 0x11ef4, direction::NSM}, {0x11ef5, 0x11ef8, direction::L},
8879
    {0x11fb0, 0x11fb0, direction::L},   {0x11fc0, 0x11fd4, direction::L},
8880
    {0x11fd5, 0x11fdc, direction::ON},  {0x11fdd, 0x11fe0, direction::ET},
8881
    {0x11fe1, 0x11ff1, direction::ON},  {0x11fff, 0x12399, direction::L},
8882
    {0x12400, 0x1246e, direction::L},   {0x12470, 0x12474, direction::L},
8883
    {0x12480, 0x12543, direction::L},   {0x13000, 0x1342e, direction::L},
8884
    {0x13430, 0x13438, direction::L},   {0x14400, 0x14646, direction::L},
8885
    {0x16800, 0x16a38, direction::L},   {0x16a40, 0x16a5e, direction::L},
8886
    {0x16a60, 0x16a69, direction::L},   {0x16a6e, 0x16a6f, direction::L},
8887
    {0x16ad0, 0x16aed, direction::L},   {0x16af0, 0x16af4, direction::NSM},
8888
    {0x16af5, 0x16af5, direction::L},   {0x16b00, 0x16b2f, direction::L},
8889
    {0x16b30, 0x16b36, direction::NSM}, {0x16b37, 0x16b45, direction::L},
8890
    {0x16b50, 0x16b59, direction::L},   {0x16b5b, 0x16b61, direction::L},
8891
    {0x16b63, 0x16b77, direction::L},   {0x16b7d, 0x16b8f, direction::L},
8892
    {0x16e40, 0x16e9a, direction::L},   {0x16f00, 0x16f4a, direction::L},
8893
    {0x16f4f, 0x16f4f, direction::NSM}, {0x16f50, 0x16f87, direction::L},
8894
    {0x16f8f, 0x16f92, direction::NSM}, {0x16f93, 0x16f9f, direction::L},
8895
    {0x16fe0, 0x16fe1, direction::L},   {0x16fe2, 0x16fe2, direction::ON},
8896
    {0x16fe3, 0x16fe3, direction::L},   {0x16fe4, 0x16fe4, direction::NSM},
8897
    {0x16ff0, 0x16ff1, direction::L},   {0x17000, 0x187f7, direction::L},
8898
    {0x18800, 0x18cd5, direction::L},   {0x18d00, 0x18d08, direction::L},
8899
    {0x1b000, 0x1b11e, direction::L},   {0x1b150, 0x1b152, direction::L},
8900
    {0x1b164, 0x1b167, direction::L},   {0x1b170, 0x1b2fb, direction::L},
8901
    {0x1bc00, 0x1bc6a, direction::L},   {0x1bc70, 0x1bc7c, direction::L},
8902
    {0x1bc80, 0x1bc88, direction::L},   {0x1bc90, 0x1bc99, direction::L},
8903
    {0x1bc9c, 0x1bc9c, direction::L},   {0x1bc9d, 0x1bc9e, direction::NSM},
8904
    {0x1bc9f, 0x1bc9f, direction::L},   {0x1bca0, 0x1bca3, direction::BN},
8905
    {0x1d000, 0x1d0f5, direction::L},   {0x1d100, 0x1d126, direction::L},
8906
    {0x1d129, 0x1d166, direction::L},   {0x1d167, 0x1d169, direction::NSM},
8907
    {0x1d16a, 0x1d172, direction::L},   {0x1d173, 0x1d17a, direction::BN},
8908
    {0x1d17b, 0x1d182, direction::NSM}, {0x1d183, 0x1d184, direction::L},
8909
    {0x1d185, 0x1d18b, direction::NSM}, {0x1d18c, 0x1d1a9, direction::L},
8910
    {0x1d1aa, 0x1d1ad, direction::NSM}, {0x1d1ae, 0x1d1e8, direction::L},
8911
    {0x1d200, 0x1d241, direction::ON},  {0x1d242, 0x1d244, direction::NSM},
8912
    {0x1d245, 0x1d245, direction::ON},  {0x1d2e0, 0x1d2f3, direction::L},
8913
    {0x1d300, 0x1d356, direction::ON},  {0x1d360, 0x1d378, direction::L},
8914
    {0x1d400, 0x1d454, direction::L},   {0x1d456, 0x1d49c, direction::L},
8915
    {0x1d49e, 0x1d49f, direction::L},   {0x1d4a2, 0x1d4a2, direction::L},
8916
    {0x1d4a5, 0x1d4a6, direction::L},   {0x1d4a9, 0x1d4ac, direction::L},
8917
    {0x1d4ae, 0x1d4b9, direction::L},   {0x1d4bb, 0x1d4bb, direction::L},
8918
    {0x1d4bd, 0x1d4c3, direction::L},   {0x1d4c5, 0x1d505, direction::L},
8919
    {0x1d507, 0x1d50a, direction::L},   {0x1d50d, 0x1d514, direction::L},
8920
    {0x1d516, 0x1d51c, direction::L},   {0x1d51e, 0x1d539, direction::L},
8921
    {0x1d53b, 0x1d53e, direction::L},   {0x1d540, 0x1d544, direction::L},
8922
    {0x1d546, 0x1d546, direction::L},   {0x1d54a, 0x1d550, direction::L},
8923
    {0x1d552, 0x1d6a5, direction::L},   {0x1d6a8, 0x1d6da, direction::L},
8924
    {0x1d6db, 0x1d6db, direction::ON},  {0x1d6dc, 0x1d714, direction::L},
8925
    {0x1d715, 0x1d715, direction::ON},  {0x1d716, 0x1d74e, direction::L},
8926
    {0x1d74f, 0x1d74f, direction::ON},  {0x1d750, 0x1d788, direction::L},
8927
    {0x1d789, 0x1d789, direction::ON},  {0x1d78a, 0x1d7c2, direction::L},
8928
    {0x1d7c3, 0x1d7c3, direction::ON},  {0x1d7c4, 0x1d7cb, direction::L},
8929
    {0x1d7ce, 0x1d7ff, direction::EN},  {0x1d800, 0x1d9ff, direction::L},
8930
    {0x1da00, 0x1da36, direction::NSM}, {0x1da37, 0x1da3a, direction::L},
8931
    {0x1da3b, 0x1da6c, direction::NSM}, {0x1da6d, 0x1da74, direction::L},
8932
    {0x1da75, 0x1da75, direction::NSM}, {0x1da76, 0x1da83, direction::L},
8933
    {0x1da84, 0x1da84, direction::NSM}, {0x1da85, 0x1da8b, direction::L},
8934
    {0x1da9b, 0x1da9f, direction::NSM}, {0x1daa1, 0x1daaf, direction::NSM},
8935
    {0x1e000, 0x1e006, direction::NSM}, {0x1e008, 0x1e018, direction::NSM},
8936
    {0x1e01b, 0x1e021, direction::NSM}, {0x1e023, 0x1e024, direction::NSM},
8937
    {0x1e026, 0x1e02a, direction::NSM}, {0x1e100, 0x1e12c, direction::L},
8938
    {0x1e130, 0x1e136, direction::NSM}, {0x1e137, 0x1e13d, direction::L},
8939
    {0x1e140, 0x1e149, direction::L},   {0x1e14e, 0x1e14f, direction::L},
8940
    {0x1e2c0, 0x1e2eb, direction::L},   {0x1e2ec, 0x1e2ef, direction::NSM},
8941
    {0x1e2f0, 0x1e2f9, direction::L},   {0x1e2ff, 0x1e2ff, direction::ET},
8942
    {0x1e800, 0x1e8c4, direction::R},   {0x1e8c7, 0x1e8cf, direction::R},
8943
    {0x1e8d0, 0x1e8d6, direction::NSM}, {0x1e900, 0x1e943, direction::R},
8944
    {0x1e944, 0x1e94a, direction::NSM}, {0x1e94b, 0x1e94b, direction::R},
8945
    {0x1e950, 0x1e959, direction::R},   {0x1e95e, 0x1e95f, direction::R},
8946
    {0x1ec71, 0x1ecb4, direction::AL},  {0x1ed01, 0x1ed3d, direction::AL},
8947
    {0x1ee00, 0x1ee03, direction::AL},  {0x1ee05, 0x1ee1f, direction::AL},
8948
    {0x1ee21, 0x1ee22, direction::AL},  {0x1ee24, 0x1ee24, direction::AL},
8949
    {0x1ee27, 0x1ee27, direction::AL},  {0x1ee29, 0x1ee32, direction::AL},
8950
    {0x1ee34, 0x1ee37, direction::AL},  {0x1ee39, 0x1ee39, direction::AL},
8951
    {0x1ee3b, 0x1ee3b, direction::AL},  {0x1ee42, 0x1ee42, direction::AL},
8952
    {0x1ee47, 0x1ee47, direction::AL},  {0x1ee49, 0x1ee49, direction::AL},
8953
    {0x1ee4b, 0x1ee4b, direction::AL},  {0x1ee4d, 0x1ee4f, direction::AL},
8954
    {0x1ee51, 0x1ee52, direction::AL},  {0x1ee54, 0x1ee54, direction::AL},
8955
    {0x1ee57, 0x1ee57, direction::AL},  {0x1ee59, 0x1ee59, direction::AL},
8956
    {0x1ee5b, 0x1ee5b, direction::AL},  {0x1ee5d, 0x1ee5d, direction::AL},
8957
    {0x1ee5f, 0x1ee5f, direction::AL},  {0x1ee61, 0x1ee62, direction::AL},
8958
    {0x1ee64, 0x1ee64, direction::AL},  {0x1ee67, 0x1ee6a, direction::AL},
8959
    {0x1ee6c, 0x1ee72, direction::AL},  {0x1ee74, 0x1ee77, direction::AL},
8960
    {0x1ee79, 0x1ee7c, direction::AL},  {0x1ee7e, 0x1ee7e, direction::AL},
8961
    {0x1ee80, 0x1ee89, direction::AL},  {0x1ee8b, 0x1ee9b, direction::AL},
8962
    {0x1eea1, 0x1eea3, direction::AL},  {0x1eea5, 0x1eea9, direction::AL},
8963
    {0x1eeab, 0x1eebb, direction::AL},  {0x1eef0, 0x1eef1, direction::ON},
8964
    {0x1f000, 0x1f02b, direction::ON},  {0x1f030, 0x1f093, direction::ON},
8965
    {0x1f0a0, 0x1f0ae, direction::ON},  {0x1f0b1, 0x1f0bf, direction::ON},
8966
    {0x1f0c1, 0x1f0cf, direction::ON},  {0x1f0d1, 0x1f0f5, direction::ON},
8967
    {0x1f100, 0x1f10a, direction::EN},  {0x1f10b, 0x1f10f, direction::ON},
8968
    {0x1f110, 0x1f12e, direction::L},   {0x1f12f, 0x1f12f, direction::ON},
8969
    {0x1f130, 0x1f169, direction::L},   {0x1f16a, 0x1f16f, direction::ON},
8970
    {0x1f170, 0x1f1ac, direction::L},   {0x1f1ad, 0x1f1ad, direction::ON},
8971
    {0x1f1e6, 0x1f202, direction::L},   {0x1f210, 0x1f23b, direction::L},
8972
    {0x1f240, 0x1f248, direction::L},   {0x1f250, 0x1f251, direction::L},
8973
    {0x1f260, 0x1f265, direction::ON},  {0x1f300, 0x1f6d7, direction::ON},
8974
    {0x1f6e0, 0x1f6ec, direction::ON},  {0x1f6f0, 0x1f6fc, direction::ON},
8975
    {0x1f700, 0x1f773, direction::ON},  {0x1f780, 0x1f7d8, direction::ON},
8976
    {0x1f7e0, 0x1f7eb, direction::ON},  {0x1f800, 0x1f80b, direction::ON},
8977
    {0x1f810, 0x1f847, direction::ON},  {0x1f850, 0x1f859, direction::ON},
8978
    {0x1f860, 0x1f887, direction::ON},  {0x1f890, 0x1f8ad, direction::ON},
8979
    {0x1f8b0, 0x1f8b1, direction::ON},  {0x1f900, 0x1f978, direction::ON},
8980
    {0x1f97a, 0x1f9cb, direction::ON},  {0x1f9cd, 0x1fa53, direction::ON},
8981
    {0x1fa60, 0x1fa6d, direction::ON},  {0x1fa70, 0x1fa74, direction::ON},
8982
    {0x1fa78, 0x1fa7a, direction::ON},  {0x1fa80, 0x1fa86, direction::ON},
8983
    {0x1fa90, 0x1faa8, direction::ON},  {0x1fab0, 0x1fab6, direction::ON},
8984
    {0x1fac0, 0x1fac2, direction::ON},  {0x1fad0, 0x1fad6, direction::ON},
8985
    {0x1fb00, 0x1fb92, direction::ON},  {0x1fb94, 0x1fbca, direction::ON},
8986
    {0x1fbf0, 0x1fbf9, direction::EN},  {0x20000, 0x2a6dd, direction::L},
8987
    {0x2a700, 0x2b734, direction::L},   {0x2b740, 0x2b81d, direction::L},
8988
    {0x2b820, 0x2cea1, direction::L},   {0x2ceb0, 0x2ebe0, direction::L},
8989
    {0x2f800, 0x2fa1d, direction::L},   {0x30000, 0x3134a, direction::L},
8990
    {0xe0001, 0xe0001, direction::BN},  {0xe0020, 0xe007f, direction::BN},
8991
    {0xe0100, 0xe01ef, direction::NSM}, {0xf0000, 0xffffd, direction::L},
8992
    {0x100000, 0x10fffd, direction::L}};
8993
8994
// CheckJoiners and CheckBidi are true for URL specification.
8995
8996
568k
inline static direction find_direction(uint32_t code_point) noexcept {
8997
568k
  auto it = std::lower_bound(
8998
568k
      std::begin(dir_table), std::end(dir_table), code_point,
8999
5.82M
      [](const directions& d, uint32_t c) { return d.final_code < c; });
9000
9001
  // next check is almost surely in vain, but we use it for safety.
9002
568k
  if (it == std::end(dir_table)) {
9003
0
    return direction::NONE;
9004
0
  }
9005
  // We have that d.final_code >= c.
9006
568k
  if (code_point >= it->start_code) {
9007
566k
    return it->direct;
9008
566k
  }
9009
1.70k
  return direction::NONE;
9010
568k
}
9011
9012
inline static size_t find_last_not_of_nsm(
9013
75.9k
    const std::u32string_view label) noexcept {
9014
77.2k
  for (int i = static_cast<int>(label.size() - 1); i >= 0; i--)
9015
77.2k
    if (find_direction(label[i]) != direction::NSM) return i;
9016
9017
0
  return std::u32string_view::npos;
9018
75.9k
}
9019
9020
// An RTL label is a label that contains at least one character of type R, AL,
9021
// or AN. https://www.rfc-editor.org/rfc/rfc5893#section-2
9022
75.9k
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
9023
75.9k
  const size_t mask =
9024
75.9k
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
9025
9026
75.9k
  size_t directions = 0;
9027
540k
  for (size_t i = 0; i < label.size(); i++) {
9028
464k
    directions |= 1u << find_direction(label[i]);
9029
464k
  }
9030
75.9k
  return (directions & mask) != 0;
9031
75.9k
}
9032
9033
78.7k
bool is_label_valid(const std::u32string_view label) {
9034
78.7k
  if (label.empty()) {
9035
0
    return true;
9036
0
  }
9037
9038
  ///////////////
9039
  // We have a normalization step which ensures that we are in NFC.
9040
  // If we receive punycode, we normalize and check that the normalized
9041
  // version matches the original.
9042
  // --------------------------------------
9043
  // The label must be in Unicode Normalization Form NFC.
9044
9045
  // Current URL standard indicatest that CheckHyphens is set to false.
9046
  // ---------------------------------------
9047
  // If CheckHyphens, the label must not contain a U+002D HYPHEN-MINUS character
9048
  // in both the third and fourth positions. If CheckHyphens, the label must
9049
  // neither begin nor end with a U+002D HYPHEN-MINUS character.
9050
9051
  // This is not necessary because we segment the
9052
  // labels by '.'.
9053
  // ---------------------------------------
9054
  // The label must not contain a U+002E ( . ) FULL STOP.
9055
  // if (label.find('.') != std::string_view::npos) return false;
9056
9057
  // The label must not begin with a combining mark, that is:
9058
  // General_Category=Mark.
9059
78.7k
  constexpr static uint32_t combining[] = {
9060
78.7k
      0x300,   0x301,   0x302,   0x303,   0x304,   0x305,   0x306,   0x307,
9061
78.7k
      0x308,   0x309,   0x30a,   0x30b,   0x30c,   0x30d,   0x30e,   0x30f,
9062
78.7k
      0x310,   0x311,   0x312,   0x313,   0x314,   0x315,   0x316,   0x317,
9063
78.7k
      0x318,   0x319,   0x31a,   0x31b,   0x31c,   0x31d,   0x31e,   0x31f,
9064
78.7k
      0x320,   0x321,   0x322,   0x323,   0x324,   0x325,   0x326,   0x327,
9065
78.7k
      0x328,   0x329,   0x32a,   0x32b,   0x32c,   0x32d,   0x32e,   0x32f,
9066
78.7k
      0x330,   0x331,   0x332,   0x333,   0x334,   0x335,   0x336,   0x337,
9067
78.7k
      0x338,   0x339,   0x33a,   0x33b,   0x33c,   0x33d,   0x33e,   0x33f,
9068
78.7k
      0x340,   0x341,   0x342,   0x343,   0x344,   0x345,   0x346,   0x347,
9069
78.7k
      0x348,   0x349,   0x34a,   0x34b,   0x34c,   0x34d,   0x34e,   0x34f,
9070
78.7k
      0x350,   0x351,   0x352,   0x353,   0x354,   0x355,   0x356,   0x357,
9071
78.7k
      0x358,   0x359,   0x35a,   0x35b,   0x35c,   0x35d,   0x35e,   0x35f,
9072
78.7k
      0x360,   0x361,   0x362,   0x363,   0x364,   0x365,   0x366,   0x367,
9073
78.7k
      0x368,   0x369,   0x36a,   0x36b,   0x36c,   0x36d,   0x36e,   0x36f,
9074
78.7k
      0x483,   0x484,   0x485,   0x486,   0x487,   0x488,   0x489,   0x591,
9075
78.7k
      0x592,   0x593,   0x594,   0x595,   0x596,   0x597,   0x598,   0x599,
9076
78.7k
      0x59a,   0x59b,   0x59c,   0x59d,   0x59e,   0x59f,   0x5a0,   0x5a1,
9077
78.7k
      0x5a2,   0x5a3,   0x5a4,   0x5a5,   0x5a6,   0x5a7,   0x5a8,   0x5a9,
9078
78.7k
      0x5aa,   0x5ab,   0x5ac,   0x5ad,   0x5ae,   0x5af,   0x5b0,   0x5b1,
9079
78.7k
      0x5b2,   0x5b3,   0x5b4,   0x5b5,   0x5b6,   0x5b7,   0x5b8,   0x5b9,
9080
78.7k
      0x5ba,   0x5bb,   0x5bc,   0x5bd,   0x5bf,   0x5c1,   0x5c2,   0x5c4,
9081
78.7k
      0x5c5,   0x5c7,   0x610,   0x611,   0x612,   0x613,   0x614,   0x615,
9082
78.7k
      0x616,   0x617,   0x618,   0x619,   0x61a,   0x64b,   0x64c,   0x64d,
9083
78.7k
      0x64e,   0x64f,   0x650,   0x651,   0x652,   0x653,   0x654,   0x655,
9084
78.7k
      0x656,   0x657,   0x658,   0x659,   0x65a,   0x65b,   0x65c,   0x65d,
9085
78.7k
      0x65e,   0x65f,   0x670,   0x6d6,   0x6d7,   0x6d8,   0x6d9,   0x6da,
9086
78.7k
      0x6db,   0x6dc,   0x6df,   0x6e0,   0x6e1,   0x6e2,   0x6e3,   0x6e4,
9087
78.7k
      0x6e7,   0x6e8,   0x6ea,   0x6eb,   0x6ec,   0x6ed,   0x711,   0x730,
9088
78.7k
      0x731,   0x732,   0x733,   0x734,   0x735,   0x736,   0x737,   0x738,
9089
78.7k
      0x739,   0x73a,   0x73b,   0x73c,   0x73d,   0x73e,   0x73f,   0x740,
9090
78.7k
      0x741,   0x742,   0x743,   0x744,   0x745,   0x746,   0x747,   0x748,
9091
78.7k
      0x749,   0x74a,   0x7a6,   0x7a7,   0x7a8,   0x7a9,   0x7aa,   0x7ab,
9092
78.7k
      0x7ac,   0x7ad,   0x7ae,   0x7af,   0x7b0,   0x7eb,   0x7ec,   0x7ed,
9093
78.7k
      0x7ee,   0x7ef,   0x7f0,   0x7f1,   0x7f2,   0x7f3,   0x7fd,   0x816,
9094
78.7k
      0x817,   0x818,   0x819,   0x81b,   0x81c,   0x81d,   0x81e,   0x81f,
9095
78.7k
      0x820,   0x821,   0x822,   0x823,   0x825,   0x826,   0x827,   0x829,
9096
78.7k
      0x82a,   0x82b,   0x82c,   0x82d,   0x859,   0x85a,   0x85b,   0x8d3,
9097
78.7k
      0x8d4,   0x8d5,   0x8d6,   0x8d7,   0x8d8,   0x8d9,   0x8da,   0x8db,
9098
78.7k
      0x8dc,   0x8dd,   0x8de,   0x8df,   0x8e0,   0x8e1,   0x8e3,   0x8e4,
9099
78.7k
      0x8e5,   0x8e6,   0x8e7,   0x8e8,   0x8e9,   0x8ea,   0x8eb,   0x8ec,
9100
78.7k
      0x8ed,   0x8ee,   0x8ef,   0x8f0,   0x8f1,   0x8f2,   0x8f3,   0x8f4,
9101
78.7k
      0x8f5,   0x8f6,   0x8f7,   0x8f8,   0x8f9,   0x8fa,   0x8fb,   0x8fc,
9102
78.7k
      0x8fd,   0x8fe,   0x8ff,   0x900,   0x901,   0x902,   0x903,   0x93a,
9103
78.7k
      0x93b,   0x93c,   0x93e,   0x93f,   0x940,   0x941,   0x942,   0x943,
9104
78.7k
      0x944,   0x945,   0x946,   0x947,   0x948,   0x949,   0x94a,   0x94b,
9105
78.7k
      0x94c,   0x94d,   0x94e,   0x94f,   0x951,   0x952,   0x953,   0x954,
9106
78.7k
      0x955,   0x956,   0x957,   0x962,   0x963,   0x981,   0x982,   0x983,
9107
78.7k
      0x9bc,   0x9be,   0x9bf,   0x9c0,   0x9c1,   0x9c2,   0x9c3,   0x9c4,
9108
78.7k
      0x9c7,   0x9c8,   0x9cb,   0x9cc,   0x9cd,   0x9d7,   0x9e2,   0x9e3,
9109
78.7k
      0x9fe,   0xa01,   0xa02,   0xa03,   0xa3c,   0xa3e,   0xa3f,   0xa40,
9110
78.7k
      0xa41,   0xa42,   0xa47,   0xa48,   0xa4b,   0xa4c,   0xa4d,   0xa51,
9111
78.7k
      0xa70,   0xa71,   0xa75,   0xa81,   0xa82,   0xa83,   0xabc,   0xabe,
9112
78.7k
      0xabf,   0xac0,   0xac1,   0xac2,   0xac3,   0xac4,   0xac5,   0xac7,
9113
78.7k
      0xac8,   0xac9,   0xacb,   0xacc,   0xacd,   0xae2,   0xae3,   0xafa,
9114
78.7k
      0xafb,   0xafc,   0xafd,   0xafe,   0xaff,   0xb01,   0xb02,   0xb03,
9115
78.7k
      0xb3c,   0xb3e,   0xb3f,   0xb40,   0xb41,   0xb42,   0xb43,   0xb44,
9116
78.7k
      0xb47,   0xb48,   0xb4b,   0xb4c,   0xb4d,   0xb55,   0xb56,   0xb57,
9117
78.7k
      0xb62,   0xb63,   0xb82,   0xbbe,   0xbbf,   0xbc0,   0xbc1,   0xbc2,
9118
78.7k
      0xbc6,   0xbc7,   0xbc8,   0xbca,   0xbcb,   0xbcc,   0xbcd,   0xbd7,
9119
78.7k
      0xc00,   0xc01,   0xc02,   0xc03,   0xc04,   0xc3e,   0xc3f,   0xc40,
9120
78.7k
      0xc41,   0xc42,   0xc43,   0xc44,   0xc46,   0xc47,   0xc48,   0xc4a,
9121
78.7k
      0xc4b,   0xc4c,   0xc4d,   0xc55,   0xc56,   0xc62,   0xc63,   0xc81,
9122
78.7k
      0xc82,   0xc83,   0xcbc,   0xcbe,   0xcbf,   0xcc0,   0xcc1,   0xcc2,
9123
78.7k
      0xcc3,   0xcc4,   0xcc6,   0xcc7,   0xcc8,   0xcca,   0xccb,   0xccc,
9124
78.7k
      0xccd,   0xcd5,   0xcd6,   0xce2,   0xce3,   0xd00,   0xd01,   0xd02,
9125
78.7k
      0xd03,   0xd3b,   0xd3c,   0xd3e,   0xd3f,   0xd40,   0xd41,   0xd42,
9126
78.7k
      0xd43,   0xd44,   0xd46,   0xd47,   0xd48,   0xd4a,   0xd4b,   0xd4c,
9127
78.7k
      0xd4d,   0xd57,   0xd62,   0xd63,   0xd81,   0xd82,   0xd83,   0xdca,
9128
78.7k
      0xdcf,   0xdd0,   0xdd1,   0xdd2,   0xdd3,   0xdd4,   0xdd6,   0xdd8,
9129
78.7k
      0xdd9,   0xdda,   0xddb,   0xddc,   0xddd,   0xdde,   0xddf,   0xdf2,
9130
78.7k
      0xdf3,   0xe31,   0xe34,   0xe35,   0xe36,   0xe37,   0xe38,   0xe39,
9131
78.7k
      0xe3a,   0xe47,   0xe48,   0xe49,   0xe4a,   0xe4b,   0xe4c,   0xe4d,
9132
78.7k
      0xe4e,   0xeb1,   0xeb4,   0xeb5,   0xeb6,   0xeb7,   0xeb8,   0xeb9,
9133
78.7k
      0xeba,   0xebb,   0xebc,   0xec8,   0xec9,   0xeca,   0xecb,   0xecc,
9134
78.7k
      0xecd,   0xf18,   0xf19,   0xf35,   0xf37,   0xf39,   0xf3e,   0xf3f,
9135
78.7k
      0xf71,   0xf72,   0xf73,   0xf74,   0xf75,   0xf76,   0xf77,   0xf78,
9136
78.7k
      0xf79,   0xf7a,   0xf7b,   0xf7c,   0xf7d,   0xf7e,   0xf7f,   0xf80,
9137
78.7k
      0xf81,   0xf82,   0xf83,   0xf84,   0xf86,   0xf87,   0xf8d,   0xf8e,
9138
78.7k
      0xf8f,   0xf90,   0xf91,   0xf92,   0xf93,   0xf94,   0xf95,   0xf96,
9139
78.7k
      0xf97,   0xf99,   0xf9a,   0xf9b,   0xf9c,   0xf9d,   0xf9e,   0xf9f,
9140
78.7k
      0xfa0,   0xfa1,   0xfa2,   0xfa3,   0xfa4,   0xfa5,   0xfa6,   0xfa7,
9141
78.7k
      0xfa8,   0xfa9,   0xfaa,   0xfab,   0xfac,   0xfad,   0xfae,   0xfaf,
9142
78.7k
      0xfb0,   0xfb1,   0xfb2,   0xfb3,   0xfb4,   0xfb5,   0xfb6,   0xfb7,
9143
78.7k
      0xfb8,   0xfb9,   0xfba,   0xfbb,   0xfbc,   0xfc6,   0x102b,  0x102c,
9144
78.7k
      0x102d,  0x102e,  0x102f,  0x1030,  0x1031,  0x1032,  0x1033,  0x1034,
9145
78.7k
      0x1035,  0x1036,  0x1037,  0x1038,  0x1039,  0x103a,  0x103b,  0x103c,
9146
78.7k
      0x103d,  0x103e,  0x1056,  0x1057,  0x1058,  0x1059,  0x105e,  0x105f,
9147
78.7k
      0x1060,  0x1062,  0x1063,  0x1064,  0x1067,  0x1068,  0x1069,  0x106a,
9148
78.7k
      0x106b,  0x106c,  0x106d,  0x1071,  0x1072,  0x1073,  0x1074,  0x1082,
9149
78.7k
      0x1083,  0x1084,  0x1085,  0x1086,  0x1087,  0x1088,  0x1089,  0x108a,
9150
78.7k
      0x108b,  0x108c,  0x108d,  0x108f,  0x109a,  0x109b,  0x109c,  0x109d,
9151
78.7k
      0x135d,  0x135e,  0x135f,  0x1712,  0x1713,  0x1714,  0x1732,  0x1733,
9152
78.7k
      0x1734,  0x1752,  0x1753,  0x1772,  0x1773,  0x17b4,  0x17b5,  0x17b6,
9153
78.7k
      0x17b7,  0x17b8,  0x17b9,  0x17ba,  0x17bb,  0x17bc,  0x17bd,  0x17be,
9154
78.7k
      0x17bf,  0x17c0,  0x17c1,  0x17c2,  0x17c3,  0x17c4,  0x17c5,  0x17c6,
9155
78.7k
      0x17c7,  0x17c8,  0x17c9,  0x17ca,  0x17cb,  0x17cc,  0x17cd,  0x17ce,
9156
78.7k
      0x17cf,  0x17d0,  0x17d1,  0x17d2,  0x17d3,  0x17dd,  0x180b,  0x180c,
9157
78.7k
      0x180d,  0x1885,  0x1886,  0x18a9,  0x1920,  0x1921,  0x1922,  0x1923,
9158
78.7k
      0x1924,  0x1925,  0x1926,  0x1927,  0x1928,  0x1929,  0x192a,  0x192b,
9159
78.7k
      0x1930,  0x1931,  0x1932,  0x1933,  0x1934,  0x1935,  0x1936,  0x1937,
9160
78.7k
      0x1938,  0x1939,  0x193a,  0x193b,  0x1a17,  0x1a18,  0x1a19,  0x1a1a,
9161
78.7k
      0x1a1b,  0x1a55,  0x1a56,  0x1a57,  0x1a58,  0x1a59,  0x1a5a,  0x1a5b,
9162
78.7k
      0x1a5c,  0x1a5d,  0x1a5e,  0x1a60,  0x1a61,  0x1a62,  0x1a63,  0x1a64,
9163
78.7k
      0x1a65,  0x1a66,  0x1a67,  0x1a68,  0x1a69,  0x1a6a,  0x1a6b,  0x1a6c,
9164
78.7k
      0x1a6d,  0x1a6e,  0x1a6f,  0x1a70,  0x1a71,  0x1a72,  0x1a73,  0x1a74,
9165
78.7k
      0x1a75,  0x1a76,  0x1a77,  0x1a78,  0x1a79,  0x1a7a,  0x1a7b,  0x1a7c,
9166
78.7k
      0x1a7f,  0x1ab0,  0x1ab1,  0x1ab2,  0x1ab3,  0x1ab4,  0x1ab5,  0x1ab6,
9167
78.7k
      0x1ab7,  0x1ab8,  0x1ab9,  0x1aba,  0x1abb,  0x1abc,  0x1abd,  0x1abe,
9168
78.7k
      0x1abf,  0x1ac0,  0x1b00,  0x1b01,  0x1b02,  0x1b03,  0x1b04,  0x1b34,
9169
78.7k
      0x1b35,  0x1b36,  0x1b37,  0x1b38,  0x1b39,  0x1b3a,  0x1b3b,  0x1b3c,
9170
78.7k
      0x1b3d,  0x1b3e,  0x1b3f,  0x1b40,  0x1b41,  0x1b42,  0x1b43,  0x1b44,
9171
78.7k
      0x1b6b,  0x1b6c,  0x1b6d,  0x1b6e,  0x1b6f,  0x1b70,  0x1b71,  0x1b72,
9172
78.7k
      0x1b73,  0x1b80,  0x1b81,  0x1b82,  0x1ba1,  0x1ba2,  0x1ba3,  0x1ba4,
9173
78.7k
      0x1ba5,  0x1ba6,  0x1ba7,  0x1ba8,  0x1ba9,  0x1baa,  0x1bab,  0x1bac,
9174
78.7k
      0x1bad,  0x1be6,  0x1be7,  0x1be8,  0x1be9,  0x1bea,  0x1beb,  0x1bec,
9175
78.7k
      0x1bed,  0x1bee,  0x1bef,  0x1bf0,  0x1bf1,  0x1bf2,  0x1bf3,  0x1c24,
9176
78.7k
      0x1c25,  0x1c26,  0x1c27,  0x1c28,  0x1c29,  0x1c2a,  0x1c2b,  0x1c2c,
9177
78.7k
      0x1c2d,  0x1c2e,  0x1c2f,  0x1c30,  0x1c31,  0x1c32,  0x1c33,  0x1c34,
9178
78.7k
      0x1c35,  0x1c36,  0x1c37,  0x1cd0,  0x1cd1,  0x1cd2,  0x1cd4,  0x1cd5,
9179
78.7k
      0x1cd6,  0x1cd7,  0x1cd8,  0x1cd9,  0x1cda,  0x1cdb,  0x1cdc,  0x1cdd,
9180
78.7k
      0x1cde,  0x1cdf,  0x1ce0,  0x1ce1,  0x1ce2,  0x1ce3,  0x1ce4,  0x1ce5,
9181
78.7k
      0x1ce6,  0x1ce7,  0x1ce8,  0x1ced,  0x1cf4,  0x1cf7,  0x1cf8,  0x1cf9,
9182
78.7k
      0x1dc0,  0x1dc1,  0x1dc2,  0x1dc3,  0x1dc4,  0x1dc5,  0x1dc6,  0x1dc7,
9183
78.7k
      0x1dc8,  0x1dc9,  0x1dca,  0x1dcb,  0x1dcc,  0x1dcd,  0x1dce,  0x1dcf,
9184
78.7k
      0x1dd0,  0x1dd1,  0x1dd2,  0x1dd3,  0x1dd4,  0x1dd5,  0x1dd6,  0x1dd7,
9185
78.7k
      0x1dd8,  0x1dd9,  0x1dda,  0x1ddb,  0x1ddc,  0x1ddd,  0x1dde,  0x1ddf,
9186
78.7k
      0x1de0,  0x1de1,  0x1de2,  0x1de3,  0x1de4,  0x1de5,  0x1de6,  0x1de7,
9187
78.7k
      0x1de8,  0x1de9,  0x1dea,  0x1deb,  0x1dec,  0x1ded,  0x1dee,  0x1def,
9188
78.7k
      0x1df0,  0x1df1,  0x1df2,  0x1df3,  0x1df4,  0x1df5,  0x1df6,  0x1df7,
9189
78.7k
      0x1df8,  0x1df9,  0x1dfb,  0x1dfc,  0x1dfd,  0x1dfe,  0x1dff,  0x20d0,
9190
78.7k
      0x20d1,  0x20d2,  0x20d3,  0x20d4,  0x20d5,  0x20d6,  0x20d7,  0x20d8,
9191
78.7k
      0x20d9,  0x20da,  0x20db,  0x20dc,  0x20dd,  0x20de,  0x20df,  0x20e0,
9192
78.7k
      0x20e1,  0x20e2,  0x20e3,  0x20e4,  0x20e5,  0x20e6,  0x20e7,  0x20e8,
9193
78.7k
      0x20e9,  0x20ea,  0x20eb,  0x20ec,  0x20ed,  0x20ee,  0x20ef,  0x20f0,
9194
78.7k
      0x2cef,  0x2cf0,  0x2cf1,  0x2d7f,  0x2de0,  0x2de1,  0x2de2,  0x2de3,
9195
78.7k
      0x2de4,  0x2de5,  0x2de6,  0x2de7,  0x2de8,  0x2de9,  0x2dea,  0x2deb,
9196
78.7k
      0x2dec,  0x2ded,  0x2dee,  0x2def,  0x2df0,  0x2df1,  0x2df2,  0x2df3,
9197
78.7k
      0x2df4,  0x2df5,  0x2df6,  0x2df7,  0x2df8,  0x2df9,  0x2dfa,  0x2dfb,
9198
78.7k
      0x2dfc,  0x2dfd,  0x2dfe,  0x2dff,  0x302a,  0x302b,  0x302c,  0x302d,
9199
78.7k
      0x302e,  0x302f,  0x3099,  0x309a,  0xa66f,  0xa670,  0xa671,  0xa672,
9200
78.7k
      0xa674,  0xa675,  0xa676,  0xa677,  0xa678,  0xa679,  0xa67a,  0xa67b,
9201
78.7k
      0xa67c,  0xa67d,  0xa69e,  0xa69f,  0xa6f0,  0xa6f1,  0xa802,  0xa806,
9202
78.7k
      0xa80b,  0xa823,  0xa824,  0xa825,  0xa826,  0xa827,  0xa82c,  0xa880,
9203
78.7k
      0xa881,  0xa8b4,  0xa8b5,  0xa8b6,  0xa8b7,  0xa8b8,  0xa8b9,  0xa8ba,
9204
78.7k
      0xa8bb,  0xa8bc,  0xa8bd,  0xa8be,  0xa8bf,  0xa8c0,  0xa8c1,  0xa8c2,
9205
78.7k
      0xa8c3,  0xa8c4,  0xa8c5,  0xa8e0,  0xa8e1,  0xa8e2,  0xa8e3,  0xa8e4,
9206
78.7k
      0xa8e5,  0xa8e6,  0xa8e7,  0xa8e8,  0xa8e9,  0xa8ea,  0xa8eb,  0xa8ec,
9207
78.7k
      0xa8ed,  0xa8ee,  0xa8ef,  0xa8f0,  0xa8f1,  0xa8ff,  0xa926,  0xa927,
9208
78.7k
      0xa928,  0xa929,  0xa92a,  0xa92b,  0xa92c,  0xa92d,  0xa947,  0xa948,
9209
78.7k
      0xa949,  0xa94a,  0xa94b,  0xa94c,  0xa94d,  0xa94e,  0xa94f,  0xa950,
9210
78.7k
      0xa951,  0xa952,  0xa953,  0xa980,  0xa981,  0xa982,  0xa983,  0xa9b3,
9211
78.7k
      0xa9b4,  0xa9b5,  0xa9b6,  0xa9b7,  0xa9b8,  0xa9b9,  0xa9ba,  0xa9bb,
9212
78.7k
      0xa9bc,  0xa9bd,  0xa9be,  0xa9bf,  0xa9c0,  0xa9e5,  0xaa29,  0xaa2a,
9213
78.7k
      0xaa2b,  0xaa2c,  0xaa2d,  0xaa2e,  0xaa2f,  0xaa30,  0xaa31,  0xaa32,
9214
78.7k
      0xaa33,  0xaa34,  0xaa35,  0xaa36,  0xaa43,  0xaa4c,  0xaa4d,  0xaa7b,
9215
78.7k
      0xaa7c,  0xaa7d,  0xaab0,  0xaab2,  0xaab3,  0xaab4,  0xaab7,  0xaab8,
9216
78.7k
      0xaabe,  0xaabf,  0xaac1,  0xaaeb,  0xaaec,  0xaaed,  0xaaee,  0xaaef,
9217
78.7k
      0xaaf5,  0xaaf6,  0xabe3,  0xabe4,  0xabe5,  0xabe6,  0xabe7,  0xabe8,
9218
78.7k
      0xabe9,  0xabea,  0xabec,  0xabed,  0xfb1e,  0xfe00,  0xfe01,  0xfe02,
9219
78.7k
      0xfe03,  0xfe04,  0xfe05,  0xfe06,  0xfe07,  0xfe08,  0xfe09,  0xfe0a,
9220
78.7k
      0xfe0b,  0xfe0c,  0xfe0d,  0xfe0e,  0xfe0f,  0xfe20,  0xfe21,  0xfe22,
9221
78.7k
      0xfe23,  0xfe24,  0xfe25,  0xfe26,  0xfe27,  0xfe28,  0xfe29,  0xfe2a,
9222
78.7k
      0xfe2b,  0xfe2c,  0xfe2d,  0xfe2e,  0xfe2f,  0x101fd, 0x102e0, 0x10376,
9223
78.7k
      0x10377, 0x10378, 0x10379, 0x1037a, 0x10a01, 0x10a02, 0x10a03, 0x10a05,
9224
78.7k
      0x10a06, 0x10a0c, 0x10a0d, 0x10a0e, 0x10a0f, 0x10a38, 0x10a39, 0x10a3a,
9225
78.7k
      0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d25, 0x10d26, 0x10d27, 0x10eab,
9226
78.7k
      0x10eac, 0x10f46, 0x10f47, 0x10f48, 0x10f49, 0x10f4a, 0x10f4b, 0x10f4c,
9227
78.7k
      0x10f4d, 0x10f4e, 0x10f4f, 0x10f50, 0x11000, 0x11001, 0x11002, 0x11038,
9228
78.7k
      0x11039, 0x1103a, 0x1103b, 0x1103c, 0x1103d, 0x1103e, 0x1103f, 0x11040,
9229
78.7k
      0x11041, 0x11042, 0x11043, 0x11044, 0x11045, 0x11046, 0x1107f, 0x11080,
9230
78.7k
      0x11081, 0x11082, 0x110b0, 0x110b1, 0x110b2, 0x110b3, 0x110b4, 0x110b5,
9231
78.7k
      0x110b6, 0x110b7, 0x110b8, 0x110b9, 0x110ba, 0x11100, 0x11101, 0x11102,
9232
78.7k
      0x11127, 0x11128, 0x11129, 0x1112a, 0x1112b, 0x1112c, 0x1112d, 0x1112e,
9233
78.7k
      0x1112f, 0x11130, 0x11131, 0x11132, 0x11133, 0x11134, 0x11145, 0x11146,
9234
78.7k
      0x11173, 0x11180, 0x11181, 0x11182, 0x111b3, 0x111b4, 0x111b5, 0x111b6,
9235
78.7k
      0x111b7, 0x111b8, 0x111b9, 0x111ba, 0x111bb, 0x111bc, 0x111bd, 0x111be,
9236
78.7k
      0x111bf, 0x111c0, 0x111c9, 0x111ca, 0x111cb, 0x111cc, 0x111ce, 0x111cf,
9237
78.7k
      0x1122c, 0x1122d, 0x1122e, 0x1122f, 0x11230, 0x11231, 0x11232, 0x11233,
9238
78.7k
      0x11234, 0x11235, 0x11236, 0x11237, 0x1123e, 0x112df, 0x112e0, 0x112e1,
9239
78.7k
      0x112e2, 0x112e3, 0x112e4, 0x112e5, 0x112e6, 0x112e7, 0x112e8, 0x112e9,
9240
78.7k
      0x112ea, 0x11300, 0x11301, 0x11302, 0x11303, 0x1133b, 0x1133c, 0x1133e,
9241
78.7k
      0x1133f, 0x11340, 0x11341, 0x11342, 0x11343, 0x11344, 0x11347, 0x11348,
9242
78.7k
      0x1134b, 0x1134c, 0x1134d, 0x11357, 0x11362, 0x11363, 0x11366, 0x11367,
9243
78.7k
      0x11368, 0x11369, 0x1136a, 0x1136b, 0x1136c, 0x11370, 0x11371, 0x11372,
9244
78.7k
      0x11373, 0x11374, 0x11435, 0x11436, 0x11437, 0x11438, 0x11439, 0x1143a,
9245
78.7k
      0x1143b, 0x1143c, 0x1143d, 0x1143e, 0x1143f, 0x11440, 0x11441, 0x11442,
9246
78.7k
      0x11443, 0x11444, 0x11445, 0x11446, 0x1145e, 0x114b0, 0x114b1, 0x114b2,
9247
78.7k
      0x114b3, 0x114b4, 0x114b5, 0x114b6, 0x114b7, 0x114b8, 0x114b9, 0x114ba,
9248
78.7k
      0x114bb, 0x114bc, 0x114bd, 0x114be, 0x114bf, 0x114c0, 0x114c1, 0x114c2,
9249
78.7k
      0x114c3, 0x115af, 0x115b0, 0x115b1, 0x115b2, 0x115b3, 0x115b4, 0x115b5,
9250
78.7k
      0x115b8, 0x115b9, 0x115ba, 0x115bb, 0x115bc, 0x115bd, 0x115be, 0x115bf,
9251
78.7k
      0x115c0, 0x115dc, 0x115dd, 0x11630, 0x11631, 0x11632, 0x11633, 0x11634,
9252
78.7k
      0x11635, 0x11636, 0x11637, 0x11638, 0x11639, 0x1163a, 0x1163b, 0x1163c,
9253
78.7k
      0x1163d, 0x1163e, 0x1163f, 0x11640, 0x116ab, 0x116ac, 0x116ad, 0x116ae,
9254
78.7k
      0x116af, 0x116b0, 0x116b1, 0x116b2, 0x116b3, 0x116b4, 0x116b5, 0x116b6,
9255
78.7k
      0x116b7, 0x1171d, 0x1171e, 0x1171f, 0x11720, 0x11721, 0x11722, 0x11723,
9256
78.7k
      0x11724, 0x11725, 0x11726, 0x11727, 0x11728, 0x11729, 0x1172a, 0x1172b,
9257
78.7k
      0x1182c, 0x1182d, 0x1182e, 0x1182f, 0x11830, 0x11831, 0x11832, 0x11833,
9258
78.7k
      0x11834, 0x11835, 0x11836, 0x11837, 0x11838, 0x11839, 0x1183a, 0x11930,
9259
78.7k
      0x11931, 0x11932, 0x11933, 0x11934, 0x11935, 0x11937, 0x11938, 0x1193b,
9260
78.7k
      0x1193c, 0x1193d, 0x1193e, 0x11940, 0x11942, 0x11943, 0x119d1, 0x119d2,
9261
78.7k
      0x119d3, 0x119d4, 0x119d5, 0x119d6, 0x119d7, 0x119da, 0x119db, 0x119dc,
9262
78.7k
      0x119dd, 0x119de, 0x119df, 0x119e0, 0x119e4, 0x11a01, 0x11a02, 0x11a03,
9263
78.7k
      0x11a04, 0x11a05, 0x11a06, 0x11a07, 0x11a08, 0x11a09, 0x11a0a, 0x11a33,
9264
78.7k
      0x11a34, 0x11a35, 0x11a36, 0x11a37, 0x11a38, 0x11a39, 0x11a3b, 0x11a3c,
9265
78.7k
      0x11a3d, 0x11a3e, 0x11a47, 0x11a51, 0x11a52, 0x11a53, 0x11a54, 0x11a55,
9266
78.7k
      0x11a56, 0x11a57, 0x11a58, 0x11a59, 0x11a5a, 0x11a5b, 0x11a8a, 0x11a8b,
9267
78.7k
      0x11a8c, 0x11a8d, 0x11a8e, 0x11a8f, 0x11a90, 0x11a91, 0x11a92, 0x11a93,
9268
78.7k
      0x11a94, 0x11a95, 0x11a96, 0x11a97, 0x11a98, 0x11a99, 0x11c2f, 0x11c30,
9269
78.7k
      0x11c31, 0x11c32, 0x11c33, 0x11c34, 0x11c35, 0x11c36, 0x11c38, 0x11c39,
9270
78.7k
      0x11c3a, 0x11c3b, 0x11c3c, 0x11c3d, 0x11c3e, 0x11c3f, 0x11c92, 0x11c93,
9271
78.7k
      0x11c94, 0x11c95, 0x11c96, 0x11c97, 0x11c98, 0x11c99, 0x11c9a, 0x11c9b,
9272
78.7k
      0x11c9c, 0x11c9d, 0x11c9e, 0x11c9f, 0x11ca0, 0x11ca1, 0x11ca2, 0x11ca3,
9273
78.7k
      0x11ca4, 0x11ca5, 0x11ca6, 0x11ca7, 0x11ca9, 0x11caa, 0x11cab, 0x11cac,
9274
78.7k
      0x11cad, 0x11cae, 0x11caf, 0x11cb0, 0x11cb1, 0x11cb2, 0x11cb3, 0x11cb4,
9275
78.7k
      0x11cb5, 0x11cb6, 0x11d31, 0x11d32, 0x11d33, 0x11d34, 0x11d35, 0x11d36,
9276
78.7k
      0x11d3a, 0x11d3c, 0x11d3d, 0x11d3f, 0x11d40, 0x11d41, 0x11d42, 0x11d43,
9277
78.7k
      0x11d44, 0x11d45, 0x11d47, 0x11d8a, 0x11d8b, 0x11d8c, 0x11d8d, 0x11d8e,
9278
78.7k
      0x11d90, 0x11d91, 0x11d93, 0x11d94, 0x11d95, 0x11d96, 0x11d97, 0x11ef3,
9279
78.7k
      0x11ef4, 0x11ef5, 0x11ef6, 0x16af0, 0x16af1, 0x16af2, 0x16af3, 0x16af4,
9280
78.7k
      0x16b30, 0x16b31, 0x16b32, 0x16b33, 0x16b34, 0x16b35, 0x16b36, 0x16f4f,
9281
78.7k
      0x16f51, 0x16f52, 0x16f53, 0x16f54, 0x16f55, 0x16f56, 0x16f57, 0x16f58,
9282
78.7k
      0x16f59, 0x16f5a, 0x16f5b, 0x16f5c, 0x16f5d, 0x16f5e, 0x16f5f, 0x16f60,
9283
78.7k
      0x16f61, 0x16f62, 0x16f63, 0x16f64, 0x16f65, 0x16f66, 0x16f67, 0x16f68,
9284
78.7k
      0x16f69, 0x16f6a, 0x16f6b, 0x16f6c, 0x16f6d, 0x16f6e, 0x16f6f, 0x16f70,
9285
78.7k
      0x16f71, 0x16f72, 0x16f73, 0x16f74, 0x16f75, 0x16f76, 0x16f77, 0x16f78,
9286
78.7k
      0x16f79, 0x16f7a, 0x16f7b, 0x16f7c, 0x16f7d, 0x16f7e, 0x16f7f, 0x16f80,
9287
78.7k
      0x16f81, 0x16f82, 0x16f83, 0x16f84, 0x16f85, 0x16f86, 0x16f87, 0x16f8f,
9288
78.7k
      0x16f90, 0x16f91, 0x16f92, 0x16fe4, 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e,
9289
78.7k
      0x1d165, 0x1d166, 0x1d167, 0x1d168, 0x1d169, 0x1d16d, 0x1d16e, 0x1d16f,
9290
78.7k
      0x1d170, 0x1d171, 0x1d172, 0x1d17b, 0x1d17c, 0x1d17d, 0x1d17e, 0x1d17f,
9291
78.7k
      0x1d180, 0x1d181, 0x1d182, 0x1d185, 0x1d186, 0x1d187, 0x1d188, 0x1d189,
9292
78.7k
      0x1d18a, 0x1d18b, 0x1d1aa, 0x1d1ab, 0x1d1ac, 0x1d1ad, 0x1d242, 0x1d243,
9293
78.7k
      0x1d244, 0x1da00, 0x1da01, 0x1da02, 0x1da03, 0x1da04, 0x1da05, 0x1da06,
9294
78.7k
      0x1da07, 0x1da08, 0x1da09, 0x1da0a, 0x1da0b, 0x1da0c, 0x1da0d, 0x1da0e,
9295
78.7k
      0x1da0f, 0x1da10, 0x1da11, 0x1da12, 0x1da13, 0x1da14, 0x1da15, 0x1da16,
9296
78.7k
      0x1da17, 0x1da18, 0x1da19, 0x1da1a, 0x1da1b, 0x1da1c, 0x1da1d, 0x1da1e,
9297
78.7k
      0x1da1f, 0x1da20, 0x1da21, 0x1da22, 0x1da23, 0x1da24, 0x1da25, 0x1da26,
9298
78.7k
      0x1da27, 0x1da28, 0x1da29, 0x1da2a, 0x1da2b, 0x1da2c, 0x1da2d, 0x1da2e,
9299
78.7k
      0x1da2f, 0x1da30, 0x1da31, 0x1da32, 0x1da33, 0x1da34, 0x1da35, 0x1da36,
9300
78.7k
      0x1da3b, 0x1da3c, 0x1da3d, 0x1da3e, 0x1da3f, 0x1da40, 0x1da41, 0x1da42,
9301
78.7k
      0x1da43, 0x1da44, 0x1da45, 0x1da46, 0x1da47, 0x1da48, 0x1da49, 0x1da4a,
9302
78.7k
      0x1da4b, 0x1da4c, 0x1da4d, 0x1da4e, 0x1da4f, 0x1da50, 0x1da51, 0x1da52,
9303
78.7k
      0x1da53, 0x1da54, 0x1da55, 0x1da56, 0x1da57, 0x1da58, 0x1da59, 0x1da5a,
9304
78.7k
      0x1da5b, 0x1da5c, 0x1da5d, 0x1da5e, 0x1da5f, 0x1da60, 0x1da61, 0x1da62,
9305
78.7k
      0x1da63, 0x1da64, 0x1da65, 0x1da66, 0x1da67, 0x1da68, 0x1da69, 0x1da6a,
9306
78.7k
      0x1da6b, 0x1da6c, 0x1da75, 0x1da84, 0x1da9b, 0x1da9c, 0x1da9d, 0x1da9e,
9307
78.7k
      0x1da9f, 0x1daa1, 0x1daa2, 0x1daa3, 0x1daa4, 0x1daa5, 0x1daa6, 0x1daa7,
9308
78.7k
      0x1daa8, 0x1daa9, 0x1daaa, 0x1daab, 0x1daac, 0x1daad, 0x1daae, 0x1daaf,
9309
78.7k
      0x1e000, 0x1e001, 0x1e002, 0x1e003, 0x1e004, 0x1e005, 0x1e006, 0x1e008,
9310
78.7k
      0x1e009, 0x1e00a, 0x1e00b, 0x1e00c, 0x1e00d, 0x1e00e, 0x1e00f, 0x1e010,
9311
78.7k
      0x1e011, 0x1e012, 0x1e013, 0x1e014, 0x1e015, 0x1e016, 0x1e017, 0x1e018,
9312
78.7k
      0x1e01b, 0x1e01c, 0x1e01d, 0x1e01e, 0x1e01f, 0x1e020, 0x1e021, 0x1e023,
9313
78.7k
      0x1e024, 0x1e026, 0x1e027, 0x1e028, 0x1e029, 0x1e02a, 0x1e130, 0x1e131,
9314
78.7k
      0x1e132, 0x1e133, 0x1e134, 0x1e135, 0x1e136, 0x1e2ec, 0x1e2ed, 0x1e2ee,
9315
78.7k
      0x1e2ef, 0x1e8d0, 0x1e8d1, 0x1e8d2, 0x1e8d3, 0x1e8d4, 0x1e8d5, 0x1e8d6,
9316
78.7k
      0x1e944, 0x1e945, 0x1e946, 0x1e947, 0x1e948, 0x1e949, 0x1e94a, 0xe0100,
9317
78.7k
      0xe0101, 0xe0102, 0xe0103, 0xe0104, 0xe0105, 0xe0106, 0xe0107, 0xe0108,
9318
78.7k
      0xe0109, 0xe010a, 0xe010b, 0xe010c, 0xe010d, 0xe010e, 0xe010f, 0xe0110,
9319
78.7k
      0xe0111, 0xe0112, 0xe0113, 0xe0114, 0xe0115, 0xe0116, 0xe0117, 0xe0118,
9320
78.7k
      0xe0119, 0xe011a, 0xe011b, 0xe011c, 0xe011d, 0xe011e, 0xe011f, 0xe0120,
9321
78.7k
      0xe0121, 0xe0122, 0xe0123, 0xe0124, 0xe0125, 0xe0126, 0xe0127, 0xe0128,
9322
78.7k
      0xe0129, 0xe012a, 0xe012b, 0xe012c, 0xe012d, 0xe012e, 0xe012f, 0xe0130,
9323
78.7k
      0xe0131, 0xe0132, 0xe0133, 0xe0134, 0xe0135, 0xe0136, 0xe0137, 0xe0138,
9324
78.7k
      0xe0139, 0xe013a, 0xe013b, 0xe013c, 0xe013d, 0xe013e, 0xe013f, 0xe0140,
9325
78.7k
      0xe0141, 0xe0142, 0xe0143, 0xe0144, 0xe0145, 0xe0146, 0xe0147, 0xe0148,
9326
78.7k
      0xe0149, 0xe014a, 0xe014b, 0xe014c, 0xe014d, 0xe014e, 0xe014f, 0xe0150,
9327
78.7k
      0xe0151, 0xe0152, 0xe0153, 0xe0154, 0xe0155, 0xe0156, 0xe0157, 0xe0158,
9328
78.7k
      0xe0159, 0xe015a, 0xe015b, 0xe015c, 0xe015d, 0xe015e, 0xe015f, 0xe0160,
9329
78.7k
      0xe0161, 0xe0162, 0xe0163, 0xe0164, 0xe0165, 0xe0166, 0xe0167, 0xe0168,
9330
78.7k
      0xe0169, 0xe016a, 0xe016b, 0xe016c, 0xe016d, 0xe016e, 0xe016f, 0xe0170,
9331
78.7k
      0xe0171, 0xe0172, 0xe0173, 0xe0174, 0xe0175, 0xe0176, 0xe0177, 0xe0178,
9332
78.7k
      0xe0179, 0xe017a, 0xe017b, 0xe017c, 0xe017d, 0xe017e, 0xe017f, 0xe0180,
9333
78.7k
      0xe0181, 0xe0182, 0xe0183, 0xe0184, 0xe0185, 0xe0186, 0xe0187, 0xe0188,
9334
78.7k
      0xe0189, 0xe018a, 0xe018b, 0xe018c, 0xe018d, 0xe018e, 0xe018f, 0xe0190,
9335
78.7k
      0xe0191, 0xe0192, 0xe0193, 0xe0194, 0xe0195, 0xe0196, 0xe0197, 0xe0198,
9336
78.7k
      0xe0199, 0xe019a, 0xe019b, 0xe019c, 0xe019d, 0xe019e, 0xe019f, 0xe01a0,
9337
78.7k
      0xe01a1, 0xe01a2, 0xe01a3, 0xe01a4, 0xe01a5, 0xe01a6, 0xe01a7, 0xe01a8,
9338
78.7k
      0xe01a9, 0xe01aa, 0xe01ab, 0xe01ac, 0xe01ad, 0xe01ae, 0xe01af, 0xe01b0,
9339
78.7k
      0xe01b1, 0xe01b2, 0xe01b3, 0xe01b4, 0xe01b5, 0xe01b6, 0xe01b7, 0xe01b8,
9340
78.7k
      0xe01b9, 0xe01ba, 0xe01bb, 0xe01bc, 0xe01bd, 0xe01be, 0xe01bf, 0xe01c0,
9341
78.7k
      0xe01c1, 0xe01c2, 0xe01c3, 0xe01c4, 0xe01c5, 0xe01c6, 0xe01c7, 0xe01c8,
9342
78.7k
      0xe01c9, 0xe01ca, 0xe01cb, 0xe01cc, 0xe01cd, 0xe01ce, 0xe01cf, 0xe01d0,
9343
78.7k
      0xe01d1, 0xe01d2, 0xe01d3, 0xe01d4, 0xe01d5, 0xe01d6, 0xe01d7, 0xe01d8,
9344
78.7k
      0xe01d9, 0xe01da, 0xe01db, 0xe01dc, 0xe01dd, 0xe01de, 0xe01df, 0xe01e0,
9345
78.7k
      0xe01e1, 0xe01e2, 0xe01e3, 0xe01e4, 0xe01e5, 0xe01e6, 0xe01e7, 0xe01e8,
9346
78.7k
      0xe01e9, 0xe01ea, 0xe01eb, 0xe01ec, 0xe01ed, 0xe01ee, 0xe01ef};
9347
78.7k
  if (std::binary_search(std::begin(combining), std::end(combining),
9348
78.7k
                         label.front())) {
9349
75
    return false;
9350
75
  }
9351
  // We verify this next step as part of the mapping:
9352
  // ---------------------------------------------
9353
  // Each code point in the label must only have certain status values
9354
  // according to Section 5, IDNA Mapping Table:
9355
  // - For Transitional Processing, each value must be valid.
9356
  // - For Nontransitional Processing, each value must be either valid or
9357
  // deviation.
9358
9359
  // If CheckJoiners, the label must satisfy the ContextJ rules from Appendix
9360
  // A, in The Unicode Code Points and Internationalized Domain Names for
9361
  // Applications (IDNA) [IDNA2008].
9362
78.7k
  constexpr static uint32_t virama[] = {
9363
78.7k
      0x094D,  0x09CD,  0x0A4D,  0x0ACD,  0x0B4D,  0x0BCD,  0x0C4D,  0x0CCD,
9364
78.7k
      0x0D3B,  0x0D3C,  0x0D4D,  0x0DCA,  0x0E3A,  0x0EBA,  0x0F84,  0x1039,
9365
78.7k
      0x103A,  0x1714,  0x1734,  0x17D2,  0x1A60,  0x1B44,  0x1BAA,  0x1BAB,
9366
78.7k
      0x1BF2,  0x1BF3,  0x2D7F,  0xA806,  0xA82C,  0xA8C4,  0xA953,  0xA9C0,
9367
78.7k
      0xAAF6,  0xABED,  0x10A3F, 0x11046, 0x1107F, 0x110B9, 0x11133, 0x11134,
9368
78.7k
      0x111C0, 0x11235, 0x112EA, 0x1134D, 0x11442, 0x114C2, 0x115BF, 0x1163F,
9369
78.7k
      0x116B6, 0x1172B, 0x11839, 0x1193D, 0x1193E, 0x119E0, 0x11A34, 0x11A47,
9370
78.7k
      0x11A99, 0x11C3F, 0x11D44, 0x11D45, 0x11D97};
9371
78.7k
  constexpr static uint32_t R[] = {
9372
78.7k
      0x622, 0x623, 0x624, 0x625, 0x627, 0x629, 0x62f, 0x630, 0x631,
9373
78.7k
      0x632, 0x648, 0x671, 0x672, 0x673, 0x675, 0x676, 0x677, 0x688,
9374
78.7k
      0x689, 0x68a, 0x68b, 0x68c, 0x68d, 0x68e, 0x68f, 0x690, 0x691,
9375
78.7k
      0x692, 0x693, 0x694, 0x695, 0x696, 0x697, 0x698, 0x699, 0x6c0,
9376
78.7k
      0x6c3, 0x6c4, 0x6c5, 0x6c6, 0x6c7, 0x6c8, 0x6c9, 0x6ca, 0x6cb,
9377
78.7k
      0x6cd, 0x6cf, 0x6d2, 0x6d3, 0x6d5, 0x6ee, 0x6ef, 0x710, 0x715,
9378
78.7k
      0x716, 0x717, 0x718, 0x719, 0x71e, 0x728, 0x72a, 0x72c, 0x72f,
9379
78.7k
      0x74d, 0x759, 0x75a, 0x75b, 0x854, 0x8aa, 0x8ab, 0x8ac};
9380
78.7k
  constexpr static uint32_t L[] = {0xa872};
9381
78.7k
  constexpr static uint32_t D[] = {
9382
78.7k
      0x620,  0x626,  0x628,  0x62a,  0x62b,  0x62c,  0x62d,  0x62e,  0x633,
9383
78.7k
      0x634,  0x635,  0x636,  0x637,  0x638,  0x639,  0x63a,  0x63b,  0x63c,
9384
78.7k
      0x63d,  0x63e,  0x63f,  0x641,  0x642,  0x643,  0x644,  0x645,  0x646,
9385
78.7k
      0x647,  0x649,  0x64a,  0x66e,  0x66f,  0x678,  0x679,  0x67a,  0x67b,
9386
78.7k
      0x67c,  0x67d,  0x67e,  0x67f,  0x680,  0x681,  0x682,  0x683,  0x684,
9387
78.7k
      0x685,  0x686,  0x687,  0x69a,  0x69b,  0x69c,  0x69d,  0x69e,  0x69f,
9388
78.7k
      0x6a0,  0x6a1,  0x6a2,  0x6a3,  0x6a4,  0x6a5,  0x6a6,  0x6a7,  0x6a8,
9389
78.7k
      0x6a9,  0x6aa,  0x6ab,  0x6ac,  0x6ad,  0x6ae,  0x6af,  0x6b0,  0x6b1,
9390
78.7k
      0x6b2,  0x6b3,  0x6b4,  0x6b5,  0x6b6,  0x6b7,  0x6b8,  0x6b9,  0x6ba,
9391
78.7k
      0x6bb,  0x6bc,  0x6bd,  0x6be,  0x6bf,  0x6c1,  0x6c2,  0x6cc,  0x6ce,
9392
78.7k
      0x6d0,  0x6d1,  0x6fa,  0x6fb,  0x6fc,  0x6ff,  0x712,  0x713,  0x714,
9393
78.7k
      0x71a,  0x71b,  0x71c,  0x71d,  0x71f,  0x720,  0x721,  0x722,  0x723,
9394
78.7k
      0x724,  0x725,  0x726,  0x727,  0x729,  0x72b,  0x72d,  0x72e,  0x74e,
9395
78.7k
      0x74f,  0x750,  0x751,  0x752,  0x753,  0x754,  0x755,  0x756,  0x757,
9396
78.7k
      0x758,  0x75c,  0x75d,  0x75e,  0x75f,  0x760,  0x761,  0x762,  0x763,
9397
78.7k
      0x764,  0x765,  0x766,  0x850,  0x851,  0x852,  0x853,  0x855,  0x8a0,
9398
78.7k
      0x8a2,  0x8a3,  0x8a4,  0x8a5,  0x8a6,  0x8a7,  0x8a8,  0x8a9,  0x1807,
9399
78.7k
      0x1820, 0x1821, 0x1822, 0x1823, 0x1824, 0x1825, 0x1826, 0x1827, 0x1828,
9400
78.7k
      0x1829, 0x182a, 0x182b, 0x182c, 0x182d, 0x182e, 0x182f, 0x1830, 0x1831,
9401
78.7k
      0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837, 0x1838, 0x1839, 0x183a,
9402
78.7k
      0x183b, 0x183c, 0x183d, 0x183e, 0x183f, 0x1840, 0x1841, 0x1842, 0x1843,
9403
78.7k
      0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x184a, 0x184b, 0x184c,
9404
78.7k
      0x184d, 0x184e, 0x184f, 0x1850, 0x1851, 0x1852, 0x1853, 0x1854, 0x1855,
9405
78.7k
      0x1856, 0x1857, 0x1858, 0x1859, 0x185a, 0x185b, 0x185c, 0x185d, 0x185e,
9406
78.7k
      0x185f, 0x1860, 0x1861, 0x1862, 0x1863, 0x1864, 0x1865, 0x1866, 0x1867,
9407
78.7k
      0x1868, 0x1869, 0x186a, 0x186b, 0x186c, 0x186d, 0x186e, 0x186f, 0x1870,
9408
78.7k
      0x1871, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, 0x1877, 0x1887, 0x1888,
9409
78.7k
      0x1889, 0x188a, 0x188b, 0x188c, 0x188d, 0x188e, 0x188f, 0x1890, 0x1891,
9410
78.7k
      0x1892, 0x1893, 0x1894, 0x1895, 0x1896, 0x1897, 0x1898, 0x1899, 0x189a,
9411
78.7k
      0x189b, 0x189c, 0x189d, 0x189e, 0x189f, 0x18a0, 0x18a1, 0x18a2, 0x18a3,
9412
78.7k
      0x18a4, 0x18a5, 0x18a6, 0x18a7, 0x18a8, 0x18aa, 0xa840, 0xa841, 0xa842,
9413
78.7k
      0xa843, 0xa844, 0xa845, 0xa846, 0xa847, 0xa848, 0xa849, 0xa84a, 0xa84b,
9414
78.7k
      0xa84c, 0xa84d, 0xa84e, 0xa84f, 0xa850, 0xa851, 0xa852, 0xa853, 0xa854,
9415
78.7k
      0xa855, 0xa856, 0xa857, 0xa858, 0xa859, 0xa85a, 0xa85b, 0xa85c, 0xa85d,
9416
78.7k
      0xa85e, 0xa85f, 0xa860, 0xa861, 0xa862, 0xa863, 0xa864, 0xa865, 0xa866,
9417
78.7k
      0xa867, 0xa868, 0xa869, 0xa86a, 0xa86b, 0xa86c, 0xa86d, 0xa86e, 0xa86f,
9418
78.7k
      0xa870, 0xa871};
9419
9420
589k
  for (size_t i = 0; i < label.size(); i++) {
9421
513k
    uint32_t c = label[i];
9422
513k
    if (c == 0x200c) {
9423
2.03k
      if (i > 0) {
9424
2.03k
        if (std::binary_search(std::begin(virama), std::end(virama),
9425
2.03k
                               label[i - 1])) {
9426
266
          return true;
9427
266
        }
9428
2.03k
      }
9429
1.76k
      if ((i == 0) || (i + 1 >= label.size())) {
9430
63
        return false;
9431
63
      }
9432
      // we go backward looking for L or D
9433
4.24k
      auto is_l_or_d = [](uint32_t code) {
9434
4.24k
        return std::binary_search(std::begin(L), std::end(L), code) ||
9435
3.89k
               std::binary_search(std::begin(D), std::end(D), code);
9436
4.24k
      };
9437
23.3k
      auto is_r_or_d = [](uint32_t code) {
9438
23.3k
        return std::binary_search(std::begin(R), std::end(R), code) ||
9439
22.6k
               std::binary_search(std::begin(D), std::end(D), code);
9440
23.3k
      };
9441
1.70k
      std::u32string_view before = label.substr(0, i);
9442
1.70k
      std::u32string_view after = label.substr(i + 1);
9443
1.70k
      return (std::find_if(before.begin(), before.end(), is_l_or_d) !=
9444
1.70k
              before.end()) &&
9445
1.62k
             (std::find_if(after.begin(), after.end(), is_r_or_d) !=
9446
1.62k
              after.end());
9447
511k
    } else if (c == 0x200d) {
9448
701
      if (i > 0) {
9449
696
        if (std::binary_search(std::begin(virama), std::end(virama),
9450
696
                               label[i - 1])) {
9451
628
          return true;
9452
628
        }
9453
696
      }
9454
73
      return false;
9455
701
    }
9456
513k
  }
9457
9458
  // If CheckBidi, and if the domain name is a  Bidi domain name, then the label
9459
  // must satisfy all six of the numbered conditions in [IDNA2008] RFC 5893,
9460
  // Section 2.
9461
9462
  // The following rule, consisting of six conditions, applies to labels
9463
  // in Bidi domain names.  The requirements that this rule satisfies are
9464
  // described in Section 3.  All of the conditions must be satisfied for
9465
  // the rule to be satisfied.
9466
  //
9467
  //  1.  The first character must be a character with Bidi property L, R,
9468
  //     or AL.  If it has the R or AL property, it is an RTL label; if it
9469
  //     has the L property, it is an LTR label.
9470
  //
9471
  //  2.  In an RTL label, only characters with the Bidi properties R, AL,
9472
  //      AN, EN, ES, CS, ET, ON, BN, or NSM are allowed.
9473
  //
9474
  //   3.  In an RTL label, the end of the label must be a character with
9475
  //       Bidi property R, AL, EN, or AN, followed by zero or more
9476
  //       characters with Bidi property NSM.
9477
  //
9478
  //   4.  In an RTL label, if an EN is present, no AN may be present, and
9479
  //       vice versa.
9480
  //
9481
  //  5.  In an LTR label, only characters with the Bidi properties L, EN,
9482
  //       ES, CS, ET, ON, BN, or NSM are allowed.
9483
  //
9484
  //   6.  In an LTR label, the end of the label must be a character with
9485
  //       Bidi property L or EN, followed by zero or more characters with
9486
  //       Bidi property NSM.
9487
9488
75.9k
  size_t last_non_nsm_char = find_last_not_of_nsm(label);
9489
75.9k
  if (last_non_nsm_char == std::u32string_view::npos) {
9490
0
    return false;
9491
0
  }
9492
9493
  // A "Bidi domain name" is a domain name that contains at least one RTL label.
9494
  // The following rule, consisting of six conditions, applies to labels in Bidi
9495
  // domain names.
9496
75.9k
  if (is_rtl_label(label)) {
9497
    // The first character must be a character with Bidi property L, R,
9498
    // or AL. If it has the R or AL property, it is an RTL label; if it
9499
    // has the L property, it is an LTR label.
9500
9501
3.44k
    if (find_direction(label[0]) == direction::L) {
9502
      // Eval as LTR
9503
9504
      // In an LTR label, only characters with the Bidi properties L, EN,
9505
      // ES, CS, ET, ON, BN, or NSM are allowed.
9506
13.8k
      for (size_t i = 0; i < last_non_nsm_char; i++) {
9507
13.3k
        const direction d = find_direction(label[i]);
9508
13.3k
        if (!(d == direction::L || d == direction::EN || d == direction::ES ||
9509
4.73k
              d == direction::CS || d == direction::ET || d == direction::ON ||
9510
2.38k
              d == direction::BN || d == direction::NSM)) {
9511
107
          return false;
9512
107
        }
9513
9514
13.2k
        if ((i == last_non_nsm_char) &&
9515
0
            !(d == direction::L || d == direction::EN)) {
9516
0
          return false;
9517
0
        }
9518
13.2k
      }
9519
9520
549
      return true;
9521
9522
2.78k
    } else {
9523
      // Eval as RTL
9524
9525
2.78k
      bool has_an = false;
9526
2.78k
      bool has_en = false;
9527
12.2k
      for (size_t i = 0; i <= last_non_nsm_char; i++) {
9528
9.58k
        const direction d = find_direction(label[i]);
9529
9530
        // In an RTL label, if an EN is present, no AN may be present, and vice
9531
        // versa.
9532
9.58k
        if ((d == direction::EN && ((has_en = true) && has_an)) ||
9533
9.58k
            (d == direction::AN && ((has_an = true) && has_en))) {
9534
6
          return false;
9535
6
        }
9536
9537
9.58k
        if (!(d == direction::R || d == direction::AL || d == direction::AN ||
9538
2.97k
              d == direction::EN || d == direction::ES || d == direction::CS ||
9539
1.78k
              d == direction::ET || d == direction::ON || d == direction::BN ||
9540
454
              d == direction::NSM)) {
9541
125
          return false;
9542
125
        }
9543
9544
9.45k
        if (i == last_non_nsm_char &&
9545
2.65k
            !(d == direction::R || d == direction::AL || d == direction::AN ||
9546
250
              d == direction::EN)) {
9547
20
          return false;
9548
20
        }
9549
9.45k
      }
9550
9551
2.63k
      return true;
9552
2.78k
    }
9553
3.44k
  }
9554
9555
72.5k
  return true;
9556
75.9k
}
9557
9558
}  // namespace ada::idna
9559
/* end file src/validity.cpp */
9560
/* begin file src/to_ascii.cpp */
9561
9562
#include <algorithm>
9563
#include <cstdint>
9564
#include <ranges>
9565
9566
9567
#ifdef ADA_USE_SIMDUTF
9568
#include "simdutf.h"
9569
#endif
9570
9571
namespace ada::idna {
9572
9573
80.8k
bool constexpr is_ascii(std::u32string_view view) {
9574
149k
  for (uint32_t c : view) {
9575
149k
    if (c >= 0x80) {
9576
79.2k
      return false;
9577
79.2k
    }
9578
149k
  }
9579
1.52k
  return true;
9580
80.8k
}
9581
9582
12.0k
bool constexpr is_ascii(std::string_view view) {
9583
267k
  for (uint8_t c : view) {
9584
267k
    if (c >= 0x80) {
9585
6.31k
      return false;
9586
6.31k
    }
9587
267k
  }
9588
5.77k
  return true;
9589
12.0k
}
9590
9591
constexpr static uint8_t is_forbidden_domain_code_point_table[] = {
9592
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9593
    1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
9594
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
9595
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
9596
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9597
    0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9598
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9599
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9600
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9601
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9602
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
9603
9604
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
9605
9606
0
inline bool is_forbidden_domain_code_point(const char c) noexcept {
9607
0
  return is_forbidden_domain_code_point_table[uint8_t(c)];
9608
0
}
9609
9610
0
bool contains_forbidden_domain_code_point(std::string_view view) {
9611
0
  return std::ranges::any_of(view, is_forbidden_domain_code_point);
9612
0
}
9613
9614
// We return "" on error.
9615
5.77k
static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9616
5.77k
  static const std::string error = "";
9617
  // copy and map
9618
  // we could be more efficient by avoiding the copy when unnecessary.
9619
5.77k
  std::string mapped_string = std::string(ut8_string);
9620
5.77k
  ascii_map(mapped_string.data(), mapped_string.size());
9621
5.77k
  std::string out;
9622
5.77k
  size_t label_start = 0;
9623
9624
25.4k
  while (label_start != mapped_string.size()) {
9625
20.1k
    size_t loc_dot = mapped_string.find('.', label_start);
9626
20.1k
    bool is_last_label = (loc_dot == std::string_view::npos);
9627
20.1k
    size_t label_size = is_last_label ? mapped_string.size() - label_start
9628
20.1k
                                      : loc_dot - label_start;
9629
20.1k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9630
20.1k
    std::string_view label_view(mapped_string.data() + label_start, label_size);
9631
20.1k
    label_start += label_size_with_dot;
9632
20.1k
    if (label_size == 0) {
9633
      // empty label? Nothing to do.
9634
12.0k
    } else if (label_view.starts_with("xn--")) {
9635
      // The xn-- part is the expensive game.
9636
5.26k
      out.append(label_view);
9637
5.26k
      std::string_view puny_segment_ascii(
9638
5.26k
          out.data() + out.size() - label_view.size() + 4,
9639
5.26k
          label_view.size() - 4);
9640
5.26k
      std::u32string tmp_buffer;
9641
5.26k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9642
5.26k
      if (!is_ok) {
9643
195
        return error;
9644
195
      }
9645
      // If the input is just ASCII, it should not have been encoded
9646
      // as punycode.
9647
      // https://github.com/whatwg/url/issues/760
9648
5.06k
      if (is_ascii(tmp_buffer)) {
9649
51
        return error;
9650
51
      }
9651
5.01k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9652
5.01k
      if (tmp_buffer != post_map) {
9653
217
        return error;
9654
217
      }
9655
4.79k
      std::u32string pre_normal = post_map;
9656
4.79k
      normalize(post_map);
9657
4.79k
      if (post_map != pre_normal) {
9658
70
        return error;
9659
70
      }
9660
4.72k
      if (post_map.empty()) {
9661
0
        return error;
9662
0
      }
9663
4.72k
      if (!is_label_valid(post_map)) {
9664
14
        return error;
9665
14
      }
9666
6.83k
    } else {
9667
6.83k
      out.append(label_view);
9668
6.83k
    }
9669
19.6k
    if (!is_last_label) {
9670
14.6k
      out.push_back('.');
9671
14.6k
    }
9672
19.6k
  }
9673
5.22k
  return out;
9674
5.77k
}
9675
9676
// We return "" on error.
9677
12.0k
std::string to_ascii(std::string_view ut8_string) {
9678
12.0k
  if (is_ascii(ut8_string)) {
9679
5.77k
    return from_ascii_to_ascii(ut8_string);
9680
5.77k
  }
9681
6.31k
  static const std::string error = "";
9682
  // We convert to UTF-32
9683
9684
#ifdef ADA_USE_SIMDUTF
9685
  size_t utf32_length =
9686
      simdutf::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9687
  std::u32string utf32(utf32_length, '\0');
9688
  size_t actual_utf32_length = simdutf::convert_utf8_to_utf32(
9689
      ut8_string.data(), ut8_string.size(), utf32.data());
9690
#else
9691
6.31k
  size_t utf32_length =
9692
6.31k
      ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9693
6.31k
  std::u32string utf32(utf32_length, '\0');
9694
6.31k
  size_t actual_utf32_length = ada::idna::utf8_to_utf32(
9695
6.31k
      ut8_string.data(), ut8_string.size(), utf32.data());
9696
6.31k
#endif
9697
6.31k
  if (actual_utf32_length == 0) {
9698
804
    return error;
9699
804
  }
9700
  // mapping
9701
5.50k
  utf32 = ada::idna::map(utf32);
9702
5.50k
  normalize(utf32);
9703
5.50k
  std::string out;
9704
5.50k
  size_t label_start = 0;
9705
9706
84.1k
  while (label_start != utf32.size()) {
9707
79.6k
    size_t loc_dot = utf32.find('.', label_start);
9708
79.6k
    bool is_last_label = (loc_dot == std::string_view::npos);
9709
79.6k
    size_t label_size =
9710
79.6k
        is_last_label ? utf32.size() - label_start : loc_dot - label_start;
9711
79.6k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9712
79.6k
    std::u32string_view label_view(utf32.data() + label_start, label_size);
9713
79.6k
    label_start += label_size_with_dot;
9714
79.6k
    if (label_size == 0) {
9715
      // empty label? Nothing to do.
9716
75.8k
    } else if (label_view.starts_with(U"xn--")) {
9717
      // we do not need to check, e.g., Xn-- because mapping goes to lower case
9718
73.4k
      for (char32_t c : label_view) {
9719
73.4k
        if (c >= 0x80) {
9720
25
          return error;
9721
25
        }
9722
73.3k
        out += (unsigned char)(c);
9723
73.3k
      }
9724
2.18k
      std::string_view puny_segment_ascii(
9725
2.18k
          out.data() + out.size() - label_view.size() + 4,
9726
2.18k
          label_view.size() - 4);
9727
2.18k
      std::u32string tmp_buffer;
9728
2.18k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9729
2.18k
      if (!is_ok) {
9730
54
        return error;
9731
54
      }
9732
      // If the input is just ASCII, it should not have been encoded
9733
      // as punycode.
9734
      // https://github.com/whatwg/url/issues/760
9735
2.13k
      if (is_ascii(tmp_buffer)) {
9736
59
        return error;
9737
59
      }
9738
2.07k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9739
2.07k
      if (tmp_buffer != post_map) {
9740
149
        return error;
9741
149
      }
9742
1.92k
      std::u32string pre_normal = post_map;
9743
1.92k
      normalize(post_map);
9744
1.92k
      if (post_map != pre_normal) {
9745
52
        return error;
9746
52
      }
9747
1.87k
      if (post_map.empty()) {
9748
0
        return error;
9749
0
      }
9750
1.87k
      if (!is_label_valid(post_map)) {
9751
10
        return error;
9752
10
      }
9753
73.6k
    } else {
9754
      // The fast path here is an ascii label.
9755
73.6k
      if (is_ascii(label_view)) {
9756
        // no validation needed.
9757
27.6k
        for (char32_t c : label_view) {
9758
27.6k
          out += (unsigned char)(c);
9759
27.6k
        }
9760
72.1k
      } else {
9761
        // slow path.
9762
        // first check validity.
9763
72.1k
        if (!is_label_valid(label_view)) {
9764
627
          return error;
9765
627
        }
9766
        // It is valid! So now we must encode it as punycode...
9767
71.5k
        out.append("xn--");
9768
71.5k
        bool is_ok = ada::idna::utf32_to_punycode(label_view, out);
9769
71.5k
        if (!is_ok) {
9770
0
          return error;
9771
0
        }
9772
71.5k
      }
9773
73.6k
    }
9774
78.6k
    if (!is_last_label) {
9775
74.4k
      out.push_back('.');
9776
74.4k
    }
9777
78.6k
  }
9778
4.53k
  return out;
9779
5.50k
}
9780
}  // namespace ada::idna
9781
/* end file src/to_ascii.cpp */
9782
/* begin file src/to_unicode.cpp */
9783
9784
#include <algorithm>
9785
#include <string>
9786
9787
9788
#ifdef ADA_USE_SIMDUTF
9789
#include "simdutf.h"
9790
#endif
9791
9792
namespace ada::idna {
9793
0
std::string to_unicode(std::string_view input) {
9794
0
  std::string output;
9795
0
  output.reserve(input.size());
9796
9797
0
  size_t label_start = 0;
9798
0
  while (label_start < input.size()) {
9799
0
    size_t loc_dot = input.find('.', label_start);
9800
0
    bool is_last_label = (loc_dot == std::string_view::npos);
9801
0
    size_t label_size =
9802
0
        is_last_label ? input.size() - label_start : loc_dot - label_start;
9803
0
    auto label_view = std::string_view(input.data() + label_start, label_size);
9804
9805
0
    if (label_view.starts_with("xn--") && ada::idna::is_ascii(label_view)) {
9806
0
      label_view.remove_prefix(4);
9807
0
      if (ada::idna::verify_punycode(label_view)) {
9808
0
        std::u32string tmp_buffer;
9809
0
        if (ada::idna::punycode_to_utf32(label_view, tmp_buffer)) {
9810
#ifdef ADA_USE_SIMDUTF
9811
          auto utf8_size = simdutf::utf8_length_from_utf32(tmp_buffer.data(),
9812
                                                           tmp_buffer.size());
9813
          std::string final_utf8(utf8_size, '\0');
9814
          simdutf::convert_utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9815
                                         final_utf8.data());
9816
#else
9817
0
          auto utf8_size = ada::idna::utf8_length_from_utf32(tmp_buffer.data(),
9818
0
                                                             tmp_buffer.size());
9819
0
          std::string final_utf8(utf8_size, '\0');
9820
0
          ada::idna::utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9821
0
                                   final_utf8.data());
9822
0
#endif
9823
0
          output.append(final_utf8);
9824
0
        } else {
9825
          // ToUnicode never fails.  If any step fails, then the original input
9826
          // sequence is returned immediately in that step.
9827
0
          output.append(
9828
0
              std::string_view(input.data() + label_start, label_size));
9829
0
        }
9830
0
      } else {
9831
0
        output.append(std::string_view(input.data() + label_start, label_size));
9832
0
      }
9833
0
    } else {
9834
0
      output.append(label_view);
9835
0
    }
9836
9837
0
    if (!is_last_label) {
9838
0
      output.push_back('.');
9839
0
    }
9840
9841
0
    label_start += label_size + 1;
9842
0
  }
9843
9844
0
  return output;
9845
0
}
9846
}  // namespace ada::idna
9847
/* end file src/to_unicode.cpp */
9848
/* begin file src/identifier.cpp */
9849
9850
#include <algorithm>
9851
#include <array>
9852
#include <string>
9853
9854
/* begin file src/id_tables.cpp */
9855
// IDNA  17.0.0
9856
9857
// clang-format off
9858
#ifndef ADA_IDNA_IDENTIFIER_TABLES_H
9859
#define ADA_IDNA_IDENTIFIER_TABLES_H
9860
#include <cstdint>
9861
9862
namespace ada::idna {
9863
9864
const uint32_t id_continue[1418][2] =
9865
{
9866
  {48, 57}, {65, 90}, {95, 95}, {97, 122},
9867
  {170, 170}, {181, 181}, {183, 183}, {186, 186},
9868
  {192, 214}, {216, 246}, {248, 442}, {443, 443},
9869
  {444, 447}, {448, 451}, {452, 659}, {660, 661},
9870
  {662, 687}, {688, 705}, {710, 721}, {736, 740},
9871
  {748, 748}, {750, 750}, {768, 879}, {880, 883},
9872
  {884, 884}, {886, 887}, {890, 890}, {891, 893},
9873
  {895, 895}, {902, 902}, {903, 903}, {904, 906},
9874
  {908, 908}, {910, 929}, {931, 1013}, {1015, 1153},
9875
  {1155, 1159}, {1162, 1327}, {1329, 1366}, {1369, 1369},
9876
  {1376, 1416}, {1425, 1469}, {1471, 1471}, {1473, 1474},
9877
  {1476, 1477}, {1479, 1479}, {1488, 1514}, {1519, 1522},
9878
  {1552, 1562}, {1568, 1599}, {1600, 1600}, {1601, 1610},
9879
  {1611, 1631}, {1632, 1641}, {1646, 1647}, {1648, 1648},
9880
  {1649, 1747}, {1749, 1749}, {1750, 1756}, {1759, 1764},
9881
  {1765, 1766}, {1767, 1768}, {1770, 1773}, {1774, 1775},
9882
  {1776, 1785}, {1786, 1788}, {1791, 1791}, {1808, 1808},
9883
  {1809, 1809}, {1810, 1839}, {1840, 1866}, {1869, 1957},
9884
  {1958, 1968}, {1969, 1969}, {1984, 1993}, {1994, 2026},
9885
  {2027, 2035}, {2036, 2037}, {2042, 2042}, {2045, 2045},
9886
  {2048, 2069}, {2070, 2073}, {2074, 2074}, {2075, 2083},
9887
  {2084, 2084}, {2085, 2087}, {2088, 2088}, {2089, 2093},
9888
  {2112, 2136}, {2137, 2139}, {2144, 2154}, {2160, 2183},
9889
  {2185, 2191}, {2199, 2207}, {2208, 2248}, {2249, 2249},
9890
  {2250, 2273}, {2275, 2306}, {2307, 2307}, {2308, 2361},
9891
  {2362, 2362}, {2363, 2363}, {2364, 2364}, {2365, 2365},
9892
  {2366, 2368}, {2369, 2376}, {2377, 2380}, {2381, 2381},
9893
  {2382, 2383}, {2384, 2384}, {2385, 2391}, {2392, 2401},
9894
  {2402, 2403}, {2406, 2415}, {2417, 2417}, {2418, 2432},
9895
  {2433, 2433}, {2434, 2435}, {2437, 2444}, {2447, 2448},
9896
  {2451, 2472}, {2474, 2480}, {2482, 2482}, {2486, 2489},
9897
  {2492, 2492}, {2493, 2493}, {2494, 2496}, {2497, 2500},
9898
  {2503, 2504}, {2507, 2508}, {2509, 2509}, {2510, 2510},
9899
  {2519, 2519}, {2524, 2525}, {2527, 2529}, {2530, 2531},
9900
  {2534, 2543}, {2544, 2545}, {2556, 2556}, {2558, 2558},
9901
  {2561, 2562}, {2563, 2563}, {2565, 2570}, {2575, 2576},
9902
  {2579, 2600}, {2602, 2608}, {2610, 2611}, {2613, 2614},
9903
  {2616, 2617}, {2620, 2620}, {2622, 2624}, {2625, 2626},
9904
  {2631, 2632}, {2635, 2637}, {2641, 2641}, {2649, 2652},
9905
  {2654, 2654}, {2662, 2671}, {2672, 2673}, {2674, 2676},
9906
  {2677, 2677}, {2689, 2690}, {2691, 2691}, {2693, 2701},
9907
  {2703, 2705}, {2707, 2728}, {2730, 2736}, {2738, 2739},
9908
  {2741, 2745}, {2748, 2748}, {2749, 2749}, {2750, 2752},
9909
  {2753, 2757}, {2759, 2760}, {2761, 2761}, {2763, 2764},
9910
  {2765, 2765}, {2768, 2768}, {2784, 2785}, {2786, 2787},
9911
  {2790, 2799}, {2809, 2809}, {2810, 2815}, {2817, 2817},
9912
  {2818, 2819}, {2821, 2828}, {2831, 2832}, {2835, 2856},
9913
  {2858, 2864}, {2866, 2867}, {2869, 2873}, {2876, 2876},
9914
  {2877, 2877}, {2878, 2878}, {2879, 2879}, {2880, 2880},
9915
  {2881, 2884}, {2887, 2888}, {2891, 2892}, {2893, 2893},
9916
  {2901, 2902}, {2903, 2903}, {2908, 2909}, {2911, 2913},
9917
  {2914, 2915}, {2918, 2927}, {2929, 2929}, {2946, 2946},
9918
  {2947, 2947}, {2949, 2954}, {2958, 2960}, {2962, 2965},
9919
  {2969, 2970}, {2972, 2972}, {2974, 2975}, {2979, 2980},
9920
  {2984, 2986}, {2990, 3001}, {3006, 3007}, {3008, 3008},
9921
  {3009, 3010}, {3014, 3016}, {3018, 3020}, {3021, 3021},
9922
  {3024, 3024}, {3031, 3031}, {3046, 3055}, {3072, 3072},
9923
  {3073, 3075}, {3076, 3076}, {3077, 3084}, {3086, 3088},
9924
  {3090, 3112}, {3114, 3129}, {3132, 3132}, {3133, 3133},
9925
  {3134, 3136}, {3137, 3140}, {3142, 3144}, {3146, 3149},
9926
  {3157, 3158}, {3160, 3162}, {3164, 3165}, {3168, 3169},
9927
  {3170, 3171}, {3174, 3183}, {3200, 3200}, {3201, 3201},
9928
  {3202, 3203}, {3205, 3212}, {3214, 3216}, {3218, 3240},
9929
  {3242, 3251}, {3253, 3257}, {3260, 3260}, {3261, 3261},
9930
  {3262, 3262}, {3263, 3263}, {3264, 3268}, {3270, 3270},
9931
  {3271, 3272}, {3274, 3275}, {3276, 3277}, {3285, 3286},
9932
  {3292, 3294}, {3296, 3297}, {3298, 3299}, {3302, 3311},
9933
  {3313, 3314}, {3315, 3315}, {3328, 3329}, {3330, 3331},
9934
  {3332, 3340}, {3342, 3344}, {3346, 3386}, {3387, 3388},
9935
  {3389, 3389}, {3390, 3392}, {3393, 3396}, {3398, 3400},
9936
  {3402, 3404}, {3405, 3405}, {3406, 3406}, {3412, 3414},
9937
  {3415, 3415}, {3423, 3425}, {3426, 3427}, {3430, 3439},
9938
  {3450, 3455}, {3457, 3457}, {3458, 3459}, {3461, 3478},
9939
  {3482, 3505}, {3507, 3515}, {3517, 3517}, {3520, 3526},
9940
  {3530, 3530}, {3535, 3537}, {3538, 3540}, {3542, 3542},
9941
  {3544, 3551}, {3558, 3567}, {3570, 3571}, {3585, 3632},
9942
  {3633, 3633}, {3634, 3635}, {3636, 3642}, {3648, 3653},
9943
  {3654, 3654}, {3655, 3662}, {3664, 3673}, {3713, 3714},
9944
  {3716, 3716}, {3718, 3722}, {3724, 3747}, {3749, 3749},
9945
  {3751, 3760}, {3761, 3761}, {3762, 3763}, {3764, 3772},
9946
  {3773, 3773}, {3776, 3780}, {3782, 3782}, {3784, 3790},
9947
  {3792, 3801}, {3804, 3807}, {3840, 3840}, {3864, 3865},
9948
  {3872, 3881}, {3893, 3893}, {3895, 3895}, {3897, 3897},
9949
  {3902, 3903}, {3904, 3911}, {3913, 3948}, {3953, 3966},
9950
  {3967, 3967}, {3968, 3972}, {3974, 3975}, {3976, 3980},
9951
  {3981, 3991}, {3993, 4028}, {4038, 4038}, {4096, 4138},
9952
  {4139, 4140}, {4141, 4144}, {4145, 4145}, {4146, 4151},
9953
  {4152, 4152}, {4153, 4154}, {4155, 4156}, {4157, 4158},
9954
  {4159, 4159}, {4160, 4169}, {4176, 4181}, {4182, 4183},
9955
  {4184, 4185}, {4186, 4189}, {4190, 4192}, {4193, 4193},
9956
  {4194, 4196}, {4197, 4198}, {4199, 4205}, {4206, 4208},
9957
  {4209, 4212}, {4213, 4225}, {4226, 4226}, {4227, 4228},
9958
  {4229, 4230}, {4231, 4236}, {4237, 4237}, {4238, 4238},
9959
  {4239, 4239}, {4240, 4249}, {4250, 4252}, {4253, 4253},
9960
  {4256, 4293}, {4295, 4295}, {4301, 4301}, {4304, 4346},
9961
  {4348, 4348}, {4349, 4351}, {4352, 4680}, {4682, 4685},
9962
  {4688, 4694}, {4696, 4696}, {4698, 4701}, {4704, 4744},
9963
  {4746, 4749}, {4752, 4784}, {4786, 4789}, {4792, 4798},
9964
  {4800, 4800}, {4802, 4805}, {4808, 4822}, {4824, 4880},
9965
  {4882, 4885}, {4888, 4954}, {4957, 4959}, {4969, 4977},
9966
  {4992, 5007}, {5024, 5109}, {5112, 5117}, {5121, 5740},
9967
  {5743, 5759}, {5761, 5786}, {5792, 5866}, {5870, 5872},
9968
  {5873, 5880}, {5888, 5905}, {5906, 5908}, {5909, 5909},
9969
  {5919, 5937}, {5938, 5939}, {5940, 5940}, {5952, 5969},
9970
  {5970, 5971}, {5984, 5996}, {5998, 6000}, {6002, 6003},
9971
  {6016, 6067}, {6068, 6069}, {6070, 6070}, {6071, 6077},
9972
  {6078, 6085}, {6086, 6086}, {6087, 6088}, {6089, 6099},
9973
  {6103, 6103}, {6108, 6108}, {6109, 6109}, {6112, 6121},
9974
  {6155, 6157}, {6159, 6159}, {6160, 6169}, {6176, 6210},
9975
  {6211, 6211}, {6212, 6264}, {6272, 6276}, {6277, 6278},
9976
  {6279, 6312}, {6313, 6313}, {6314, 6314}, {6320, 6389},
9977
  {6400, 6430}, {6432, 6434}, {6435, 6438}, {6439, 6440},
9978
  {6441, 6443}, {6448, 6449}, {6450, 6450}, {6451, 6456},
9979
  {6457, 6459}, {6470, 6479}, {6480, 6509}, {6512, 6516},
9980
  {6528, 6571}, {6576, 6601}, {6608, 6617}, {6618, 6618},
9981
  {6656, 6678}, {6679, 6680}, {6681, 6682}, {6683, 6683},
9982
  {6688, 6740}, {6741, 6741}, {6742, 6742}, {6743, 6743},
9983
  {6744, 6750}, {6752, 6752}, {6753, 6753}, {6754, 6754},
9984
  {6755, 6756}, {6757, 6764}, {6765, 6770}, {6771, 6780},
9985
  {6783, 6783}, {6784, 6793}, {6800, 6809}, {6823, 6823},
9986
  {6832, 6845}, {6847, 6877}, {6880, 6891}, {6912, 6915},
9987
  {6916, 6916}, {6917, 6963}, {6964, 6964}, {6965, 6965},
9988
  {6966, 6970}, {6971, 6971}, {6972, 6972}, {6973, 6977},
9989
  {6978, 6978}, {6979, 6980}, {6981, 6988}, {6992, 7001},
9990
  {7019, 7027}, {7040, 7041}, {7042, 7042}, {7043, 7072},
9991
  {7073, 7073}, {7074, 7077}, {7078, 7079}, {7080, 7081},
9992
  {7082, 7082}, {7083, 7085}, {7086, 7087}, {7088, 7097},
9993
  {7098, 7141}, {7142, 7142}, {7143, 7143}, {7144, 7145},
9994
  {7146, 7148}, {7149, 7149}, {7150, 7150}, {7151, 7153},
9995
  {7154, 7155}, {7168, 7203}, {7204, 7211}, {7212, 7219},
9996
  {7220, 7221}, {7222, 7223}, {7232, 7241}, {7245, 7247},
9997
  {7248, 7257}, {7258, 7287}, {7288, 7293}, {7296, 7306},
9998
  {7312, 7354}, {7357, 7359}, {7376, 7378}, {7380, 7392},
9999
  {7393, 7393}, {7394, 7400}, {7401, 7404}, {7405, 7405},
10000
  {7406, 7411}, {7412, 7412}, {7413, 7414}, {7415, 7415},
10001
  {7416, 7417}, {7418, 7418}, {7424, 7467}, {7468, 7530},
10002
  {7531, 7543}, {7544, 7544}, {7545, 7578}, {7579, 7615},
10003
  {7616, 7679}, {7680, 7957}, {7960, 7965}, {7968, 8005},
10004
  {8008, 8013}, {8016, 8023}, {8025, 8025}, {8027, 8027},
10005
  {8029, 8029}, {8031, 8061}, {8064, 8116}, {8118, 8124},
10006
  {8126, 8126}, {8130, 8132}, {8134, 8140}, {8144, 8147},
10007
  {8150, 8155}, {8160, 8172}, {8178, 8180}, {8182, 8188},
10008
  {8204, 8205}, {8255, 8256}, {8276, 8276}, {8305, 8305},
10009
  {8319, 8319}, {8336, 8348}, {8400, 8412}, {8417, 8417},
10010
  {8421, 8432}, {8450, 8450}, {8455, 8455}, {8458, 8467},
10011
  {8469, 8469}, {8472, 8472}, {8473, 8477}, {8484, 8484},
10012
  {8486, 8486}, {8488, 8488}, {8490, 8493}, {8494, 8494},
10013
  {8495, 8500}, {8501, 8504}, {8505, 8505}, {8508, 8511},
10014
  {8517, 8521}, {8526, 8526}, {8544, 8578}, {8579, 8580},
10015
  {8581, 8584}, {11264, 11387}, {11388, 11389}, {11390, 11492},
10016
  {11499, 11502}, {11503, 11505}, {11506, 11507}, {11520, 11557},
10017
  {11559, 11559}, {11565, 11565}, {11568, 11623}, {11631, 11631},
10018
  {11647, 11647}, {11648, 11670}, {11680, 11686}, {11688, 11694},
10019
  {11696, 11702}, {11704, 11710}, {11712, 11718}, {11720, 11726},
10020
  {11728, 11734}, {11736, 11742}, {11744, 11775}, {12293, 12293},
10021
  {12294, 12294}, {12295, 12295}, {12321, 12329}, {12330, 12333},
10022
  {12334, 12335}, {12337, 12341}, {12344, 12346}, {12347, 12347},
10023
  {12348, 12348}, {12353, 12438}, {12441, 12442}, {12443, 12444},
10024
  {12445, 12446}, {12447, 12447}, {12449, 12538}, {12539, 12539},
10025
  {12540, 12542}, {12543, 12543}, {12549, 12591}, {12593, 12686},
10026
  {12704, 12735}, {12784, 12799}, {13312, 19903}, {19968, 40980},
10027
  {40981, 40981}, {40982, 42124}, {42192, 42231}, {42232, 42237},
10028
  {42240, 42507}, {42508, 42508}, {42512, 42527}, {42528, 42537},
10029
  {42538, 42539}, {42560, 42605}, {42606, 42606}, {42607, 42607},
10030
  {42612, 42621}, {42623, 42623}, {42624, 42651}, {42652, 42653},
10031
  {42654, 42655}, {42656, 42725}, {42726, 42735}, {42736, 42737},
10032
  {42775, 42783}, {42786, 42863}, {42864, 42864}, {42865, 42887},
10033
  {42888, 42888}, {42891, 42894}, {42895, 42895}, {42896, 42972},
10034
  {42993, 42996}, {42997, 42998}, {42999, 42999}, {43000, 43001},
10035
  {43002, 43002}, {43003, 43009}, {43010, 43010}, {43011, 43013},
10036
  {43014, 43014}, {43015, 43018}, {43019, 43019}, {43020, 43042},
10037
  {43043, 43044}, {43045, 43046}, {43047, 43047}, {43052, 43052},
10038
  {43072, 43123}, {43136, 43137}, {43138, 43187}, {43188, 43203},
10039
  {43204, 43205}, {43216, 43225}, {43232, 43249}, {43250, 43255},
10040
  {43259, 43259}, {43261, 43262}, {43263, 43263}, {43264, 43273},
10041
  {43274, 43301}, {43302, 43309}, {43312, 43334}, {43335, 43345},
10042
  {43346, 43347}, {43360, 43388}, {43392, 43394}, {43395, 43395},
10043
  {43396, 43442}, {43443, 43443}, {43444, 43445}, {43446, 43449},
10044
  {43450, 43451}, {43452, 43453}, {43454, 43456}, {43471, 43471},
10045
  {43472, 43481}, {43488, 43492}, {43493, 43493}, {43494, 43494},
10046
  {43495, 43503}, {43504, 43513}, {43514, 43518}, {43520, 43560},
10047
  {43561, 43566}, {43567, 43568}, {43569, 43570}, {43571, 43572},
10048
  {43573, 43574}, {43584, 43586}, {43587, 43587}, {43588, 43595},
10049
  {43596, 43596}, {43597, 43597}, {43600, 43609}, {43616, 43631},
10050
  {43632, 43632}, {43633, 43638}, {43642, 43642}, {43643, 43643},
10051
  {43644, 43644}, {43645, 43645}, {43646, 43695}, {43696, 43696},
10052
  {43697, 43697}, {43698, 43700}, {43701, 43702}, {43703, 43704},
10053
  {43705, 43709}, {43710, 43711}, {43712, 43712}, {43713, 43713},
10054
  {43714, 43714}, {43739, 43740}, {43741, 43741}, {43744, 43754},
10055
  {43755, 43755}, {43756, 43757}, {43758, 43759}, {43762, 43762},
10056
  {43763, 43764}, {43765, 43765}, {43766, 43766}, {43777, 43782},
10057
  {43785, 43790}, {43793, 43798}, {43808, 43814}, {43816, 43822},
10058
  {43824, 43866}, {43868, 43871}, {43872, 43880}, {43881, 43881},
10059
  {43888, 43967}, {43968, 44002}, {44003, 44004}, {44005, 44005},
10060
  {44006, 44007}, {44008, 44008}, {44009, 44010}, {44012, 44012},
10061
  {44013, 44013}, {44016, 44025}, {44032, 55203}, {55216, 55238},
10062
  {55243, 55291}, {63744, 64109}, {64112, 64217}, {64256, 64262},
10063
  {64275, 64279}, {64285, 64285}, {64286, 64286}, {64287, 64296},
10064
  {64298, 64310}, {64312, 64316}, {64318, 64318}, {64320, 64321},
10065
  {64323, 64324}, {64326, 64433}, {64467, 64829}, {64848, 64911},
10066
  {64914, 64967}, {65008, 65019}, {65024, 65039}, {65056, 65071},
10067
  {65075, 65076}, {65101, 65103}, {65136, 65140}, {65142, 65276},
10068
  {65296, 65305}, {65313, 65338}, {65343, 65343}, {65345, 65370},
10069
  {65381, 65381}, {65382, 65391}, {65392, 65392}, {65393, 65437},
10070
  {65438, 65439}, {65440, 65470}, {65474, 65479}, {65482, 65487},
10071
  {65490, 65495}, {65498, 65500}, {65536, 65547}, {65549, 65574},
10072
  {65576, 65594}, {65596, 65597}, {65599, 65613}, {65616, 65629},
10073
  {65664, 65786}, {65856, 65908}, {66045, 66045}, {66176, 66204},
10074
  {66208, 66256}, {66272, 66272}, {66304, 66335}, {66349, 66368},
10075
  {66369, 66369}, {66370, 66377}, {66378, 66378}, {66384, 66421},
10076
  {66422, 66426}, {66432, 66461}, {66464, 66499}, {66504, 66511},
10077
  {66513, 66517}, {66560, 66639}, {66640, 66717}, {66720, 66729},
10078
  {66736, 66771}, {66776, 66811}, {66816, 66855}, {66864, 66915},
10079
  {66928, 66938}, {66940, 66954}, {66956, 66962}, {66964, 66965},
10080
  {66967, 66977}, {66979, 66993}, {66995, 67001}, {67003, 67004},
10081
  {67008, 67059}, {67072, 67382}, {67392, 67413}, {67424, 67431},
10082
  {67456, 67461}, {67463, 67504}, {67506, 67514}, {67584, 67589},
10083
  {67592, 67592}, {67594, 67637}, {67639, 67640}, {67644, 67644},
10084
  {67647, 67669}, {67680, 67702}, {67712, 67742}, {67808, 67826},
10085
  {67828, 67829}, {67840, 67861}, {67872, 67897}, {67904, 67929},
10086
  {67968, 68023}, {68030, 68031}, {68096, 68096}, {68097, 68099},
10087
  {68101, 68102}, {68108, 68111}, {68112, 68115}, {68117, 68119},
10088
  {68121, 68149}, {68152, 68154}, {68159, 68159}, {68192, 68220},
10089
  {68224, 68252}, {68288, 68295}, {68297, 68324}, {68325, 68326},
10090
  {68352, 68405}, {68416, 68437}, {68448, 68466}, {68480, 68497},
10091
  {68608, 68680}, {68736, 68786}, {68800, 68850}, {68864, 68899},
10092
  {68900, 68903}, {68912, 68921}, {68928, 68937}, {68938, 68941},
10093
  {68942, 68942}, {68943, 68943}, {68944, 68965}, {68969, 68973},
10094
  {68975, 68975}, {68976, 68997}, {69248, 69289}, {69291, 69292},
10095
  {69296, 69297}, {69314, 69316}, {69317, 69317}, {69318, 69319},
10096
  {69370, 69375}, {69376, 69404}, {69415, 69415}, {69424, 69445},
10097
  {69446, 69456}, {69488, 69505}, {69506, 69509}, {69552, 69572},
10098
  {69600, 69622}, {69632, 69632}, {69633, 69633}, {69634, 69634},
10099
  {69635, 69687}, {69688, 69702}, {69734, 69743}, {69744, 69744},
10100
  {69745, 69746}, {69747, 69748}, {69749, 69749}, {69759, 69761},
10101
  {69762, 69762}, {69763, 69807}, {69808, 69810}, {69811, 69814},
10102
  {69815, 69816}, {69817, 69818}, {69826, 69826}, {69840, 69864},
10103
  {69872, 69881}, {69888, 69890}, {69891, 69926}, {69927, 69931},
10104
  {69932, 69932}, {69933, 69940}, {69942, 69951}, {69956, 69956},
10105
  {69957, 69958}, {69959, 69959}, {69968, 70002}, {70003, 70003},
10106
  {70006, 70006}, {70016, 70017}, {70018, 70018}, {70019, 70066},
10107
  {70067, 70069}, {70070, 70078}, {70079, 70080}, {70081, 70084},
10108
  {70089, 70092}, {70094, 70094}, {70095, 70095}, {70096, 70105},
10109
  {70106, 70106}, {70108, 70108}, {70144, 70161}, {70163, 70187},
10110
  {70188, 70190}, {70191, 70193}, {70194, 70195}, {70196, 70196},
10111
  {70197, 70197}, {70198, 70199}, {70206, 70206}, {70207, 70208},
10112
  {70209, 70209}, {70272, 70278}, {70280, 70280}, {70282, 70285},
10113
  {70287, 70301}, {70303, 70312}, {70320, 70366}, {70367, 70367},
10114
  {70368, 70370}, {70371, 70378}, {70384, 70393}, {70400, 70401},
10115
  {70402, 70403}, {70405, 70412}, {70415, 70416}, {70419, 70440},
10116
  {70442, 70448}, {70450, 70451}, {70453, 70457}, {70459, 70460},
10117
  {70461, 70461}, {70462, 70463}, {70464, 70464}, {70465, 70468},
10118
  {70471, 70472}, {70475, 70477}, {70480, 70480}, {70487, 70487},
10119
  {70493, 70497}, {70498, 70499}, {70502, 70508}, {70512, 70516},
10120
  {70528, 70537}, {70539, 70539}, {70542, 70542}, {70544, 70581},
10121
  {70583, 70583}, {70584, 70586}, {70587, 70592}, {70594, 70594},
10122
  {70597, 70597}, {70599, 70602}, {70604, 70605}, {70606, 70606},
10123
  {70607, 70607}, {70608, 70608}, {70609, 70609}, {70610, 70610},
10124
  {70611, 70611}, {70625, 70626}, {70656, 70708}, {70709, 70711},
10125
  {70712, 70719}, {70720, 70721}, {70722, 70724}, {70725, 70725},
10126
  {70726, 70726}, {70727, 70730}, {70736, 70745}, {70750, 70750},
10127
  {70751, 70753}, {70784, 70831}, {70832, 70834}, {70835, 70840},
10128
  {70841, 70841}, {70842, 70842}, {70843, 70846}, {70847, 70848},
10129
  {70849, 70849}, {70850, 70851}, {70852, 70853}, {70855, 70855},
10130
  {70864, 70873}, {71040, 71086}, {71087, 71089}, {71090, 71093},
10131
  {71096, 71099}, {71100, 71101}, {71102, 71102}, {71103, 71104},
10132
  {71128, 71131}, {71132, 71133}, {71168, 71215}, {71216, 71218},
10133
  {71219, 71226}, {71227, 71228}, {71229, 71229}, {71230, 71230},
10134
  {71231, 71232}, {71236, 71236}, {71248, 71257}, {71296, 71338},
10135
  {71339, 71339}, {71340, 71340}, {71341, 71341}, {71342, 71343},
10136
  {71344, 71349}, {71350, 71350}, {71351, 71351}, {71352, 71352},
10137
  {71360, 71369}, {71376, 71395}, {71424, 71450}, {71453, 71453},
10138
  {71454, 71454}, {71455, 71455}, {71456, 71457}, {71458, 71461},
10139
  {71462, 71462}, {71463, 71467}, {71472, 71481}, {71488, 71494},
10140
  {71680, 71723}, {71724, 71726}, {71727, 71735}, {71736, 71736},
10141
  {71737, 71738}, {71840, 71903}, {71904, 71913}, {71935, 71942},
10142
  {71945, 71945}, {71948, 71955}, {71957, 71958}, {71960, 71983},
10143
  {71984, 71989}, {71991, 71992}, {71995, 71996}, {71997, 71997},
10144
  {71998, 71998}, {71999, 71999}, {72000, 72000}, {72001, 72001},
10145
  {72002, 72002}, {72003, 72003}, {72016, 72025}, {72096, 72103},
10146
  {72106, 72144}, {72145, 72147}, {72148, 72151}, {72154, 72155},
10147
  {72156, 72159}, {72160, 72160}, {72161, 72161}, {72163, 72163},
10148
  {72164, 72164}, {72192, 72192}, {72193, 72202}, {72203, 72242},
10149
  {72243, 72248}, {72249, 72249}, {72250, 72250}, {72251, 72254},
10150
  {72263, 72263}, {72272, 72272}, {72273, 72278}, {72279, 72280},
10151
  {72281, 72283}, {72284, 72329}, {72330, 72342}, {72343, 72343},
10152
  {72344, 72345}, {72349, 72349}, {72368, 72440}, {72544, 72544},
10153
  {72545, 72545}, {72546, 72548}, {72549, 72549}, {72550, 72550},
10154
  {72551, 72551}, {72640, 72672}, {72688, 72697}, {72704, 72712},
10155
  {72714, 72750}, {72751, 72751}, {72752, 72758}, {72760, 72765},
10156
  {72766, 72766}, {72767, 72767}, {72768, 72768}, {72784, 72793},
10157
  {72818, 72847}, {72850, 72871}, {72873, 72873}, {72874, 72880},
10158
  {72881, 72881}, {72882, 72883}, {72884, 72884}, {72885, 72886},
10159
  {72960, 72966}, {72968, 72969}, {72971, 73008}, {73009, 73014},
10160
  {73018, 73018}, {73020, 73021}, {73023, 73029}, {73030, 73030},
10161
  {73031, 73031}, {73040, 73049}, {73056, 73061}, {73063, 73064},
10162
  {73066, 73097}, {73098, 73102}, {73104, 73105}, {73107, 73108},
10163
  {73109, 73109}, {73110, 73110}, {73111, 73111}, {73112, 73112},
10164
  {73120, 73129}, {73136, 73176}, {73177, 73177}, {73178, 73179},
10165
  {73184, 73193}, {73440, 73458}, {73459, 73460}, {73461, 73462},
10166
  {73472, 73473}, {73474, 73474}, {73475, 73475}, {73476, 73488},
10167
  {73490, 73523}, {73524, 73525}, {73526, 73530}, {73534, 73535},
10168
  {73536, 73536}, {73537, 73537}, {73538, 73538}, {73552, 73561},
10169
  {73562, 73562}, {73648, 73648}, {73728, 74649}, {74752, 74862},
10170
  {74880, 75075}, {77712, 77808}, {77824, 78895}, {78912, 78912},
10171
  {78913, 78918}, {78919, 78933}, {78944, 82938}, {82944, 83526},
10172
  {90368, 90397}, {90398, 90409}, {90410, 90412}, {90413, 90415},
10173
  {90416, 90425}, {92160, 92728}, {92736, 92766}, {92768, 92777},
10174
  {92784, 92862}, {92864, 92873}, {92880, 92909}, {92912, 92916},
10175
  {92928, 92975}, {92976, 92982}, {92992, 92995}, {93008, 93017},
10176
  {93027, 93047}, {93053, 93071}, {93504, 93506}, {93507, 93546},
10177
  {93547, 93548}, {93552, 93561}, {93760, 93823}, {93856, 93880},
10178
  {93883, 93907}, {93952, 94026}, {94031, 94031}, {94032, 94032},
10179
  {94033, 94087}, {94095, 94098}, {94099, 94111}, {94176, 94177},
10180
  {94179, 94179}, {94180, 94180}, {94192, 94193}, {94194, 94195},
10181
  {94196, 94198}, {94208, 101589}, {101631, 101662}, {101760, 101874},
10182
  {110576, 110579}, {110581, 110587}, {110589, 110590}, {110592, 110882},
10183
  {110898, 110898}, {110928, 110930}, {110933, 110933}, {110948, 110951},
10184
  {110960, 111355}, {113664, 113770}, {113776, 113788}, {113792, 113800},
10185
  {113808, 113817}, {113821, 113822}, {118000, 118009}, {118528, 118573},
10186
  {118576, 118598}, {119141, 119142}, {119143, 119145}, {119149, 119154},
10187
  {119163, 119170}, {119173, 119179}, {119210, 119213}, {119362, 119364},
10188
  {119808, 119892}, {119894, 119964}, {119966, 119967}, {119970, 119970},
10189
  {119973, 119974}, {119977, 119980}, {119982, 119993}, {119995, 119995},
10190
  {119997, 120003}, {120005, 120069}, {120071, 120074}, {120077, 120084},
10191
  {120086, 120092}, {120094, 120121}, {120123, 120126}, {120128, 120132},
10192
  {120134, 120134}, {120138, 120144}, {120146, 120485}, {120488, 120512},
10193
  {120514, 120538}, {120540, 120570}, {120572, 120596}, {120598, 120628},
10194
  {120630, 120654}, {120656, 120686}, {120688, 120712}, {120714, 120744},
10195
  {120746, 120770}, {120772, 120779}, {120782, 120831}, {121344, 121398},
10196
  {121403, 121452}, {121461, 121461}, {121476, 121476}, {121499, 121503},
10197
  {121505, 121519}, {122624, 122633}, {122634, 122634}, {122635, 122654},
10198
  {122661, 122666}, {122880, 122886}, {122888, 122904}, {122907, 122913},
10199
  {122915, 122916}, {122918, 122922}, {122928, 122989}, {123023, 123023},
10200
  {123136, 123180}, {123184, 123190}, {123191, 123197}, {123200, 123209},
10201
  {123214, 123214}, {123536, 123565}, {123566, 123566}, {123584, 123627},
10202
  {123628, 123631}, {123632, 123641}, {124112, 124138}, {124139, 124139},
10203
  {124140, 124143}, {124144, 124153}, {124368, 124397}, {124398, 124399},
10204
  {124400, 124400}, {124401, 124410}, {124608, 124638}, {124640, 124642},
10205
  {124643, 124643}, {124644, 124645}, {124646, 124646}, {124647, 124653},
10206
  {124654, 124655}, {124656, 124660}, {124661, 124661}, {124670, 124670},
10207
  {124671, 124671}, {124896, 124902}, {124904, 124907}, {124909, 124910},
10208
  {124912, 124926}, {124928, 125124}, {125136, 125142}, {125184, 125251},
10209
  {125252, 125258}, {125259, 125259}, {125264, 125273}, {126464, 126467},
10210
  {126469, 126495}, {126497, 126498}, {126500, 126500}, {126503, 126503},
10211
  {126505, 126514}, {126516, 126519}, {126521, 126521}, {126523, 126523},
10212
  {126530, 126530}, {126535, 126535}, {126537, 126537}, {126539, 126539},
10213
  {126541, 126543}, {126545, 126546}, {126548, 126548}, {126551, 126551},
10214
  {126553, 126553}, {126555, 126555}, {126557, 126557}, {126559, 126559},
10215
  {126561, 126562}, {126564, 126564}, {126567, 126570}, {126572, 126578},
10216
  {126580, 126583}, {126585, 126588}, {126590, 126590}, {126592, 126601},
10217
  {126603, 126619}, {126625, 126627}, {126629, 126633}, {126635, 126651},
10218
  {130032, 130041}, {131072, 173791}, {173824, 178205}, {178208, 183981},
10219
  {183984, 191456}, {191472, 192093}, {194560, 195101}, {196608, 201546},
10220
  {201552, 210041}, {917760, 917999}
10221
};
10222
const uint32_t id_start[776][2] =
10223
{
10224
  {65, 90}, {97, 122}, {170, 170}, {181, 181},
10225
  {186, 186}, {192, 214}, {216, 246}, {248, 442},
10226
  {443, 443}, {444, 447}, {448, 451}, {452, 659},
10227
  {660, 661}, {662, 687}, {688, 705}, {710, 721},
10228
  {736, 740}, {748, 748}, {750, 750}, {880, 883},
10229
  {884, 884}, {886, 887}, {890, 890}, {891, 893},
10230
  {895, 895}, {902, 902}, {904, 906}, {908, 908},
10231
  {910, 929}, {931, 1013}, {1015, 1153}, {1162, 1327},
10232
  {1329, 1366}, {1369, 1369}, {1376, 1416}, {1488, 1514},
10233
  {1519, 1522}, {1568, 1599}, {1600, 1600}, {1601, 1610},
10234
  {1646, 1647}, {1649, 1747}, {1749, 1749}, {1765, 1766},
10235
  {1774, 1775}, {1786, 1788}, {1791, 1791}, {1808, 1808},
10236
  {1810, 1839}, {1869, 1957}, {1969, 1969}, {1994, 2026},
10237
  {2036, 2037}, {2042, 2042}, {2048, 2069}, {2074, 2074},
10238
  {2084, 2084}, {2088, 2088}, {2112, 2136}, {2144, 2154},
10239
  {2160, 2183}, {2185, 2191}, {2208, 2248}, {2249, 2249},
10240
  {2308, 2361}, {2365, 2365}, {2384, 2384}, {2392, 2401},
10241
  {2417, 2417}, {2418, 2432}, {2437, 2444}, {2447, 2448},
10242
  {2451, 2472}, {2474, 2480}, {2482, 2482}, {2486, 2489},
10243
  {2493, 2493}, {2510, 2510}, {2524, 2525}, {2527, 2529},
10244
  {2544, 2545}, {2556, 2556}, {2565, 2570}, {2575, 2576},
10245
  {2579, 2600}, {2602, 2608}, {2610, 2611}, {2613, 2614},
10246
  {2616, 2617}, {2649, 2652}, {2654, 2654}, {2674, 2676},
10247
  {2693, 2701}, {2703, 2705}, {2707, 2728}, {2730, 2736},
10248
  {2738, 2739}, {2741, 2745}, {2749, 2749}, {2768, 2768},
10249
  {2784, 2785}, {2809, 2809}, {2821, 2828}, {2831, 2832},
10250
  {2835, 2856}, {2858, 2864}, {2866, 2867}, {2869, 2873},
10251
  {2877, 2877}, {2908, 2909}, {2911, 2913}, {2929, 2929},
10252
  {2947, 2947}, {2949, 2954}, {2958, 2960}, {2962, 2965},
10253
  {2969, 2970}, {2972, 2972}, {2974, 2975}, {2979, 2980},
10254
  {2984, 2986}, {2990, 3001}, {3024, 3024}, {3077, 3084},
10255
  {3086, 3088}, {3090, 3112}, {3114, 3129}, {3133, 3133},
10256
  {3160, 3162}, {3164, 3165}, {3168, 3169}, {3200, 3200},
10257
  {3205, 3212}, {3214, 3216}, {3218, 3240}, {3242, 3251},
10258
  {3253, 3257}, {3261, 3261}, {3292, 3294}, {3296, 3297},
10259
  {3313, 3314}, {3332, 3340}, {3342, 3344}, {3346, 3386},
10260
  {3389, 3389}, {3406, 3406}, {3412, 3414}, {3423, 3425},
10261
  {3450, 3455}, {3461, 3478}, {3482, 3505}, {3507, 3515},
10262
  {3517, 3517}, {3520, 3526}, {3585, 3632}, {3634, 3635},
10263
  {3648, 3653}, {3654, 3654}, {3713, 3714}, {3716, 3716},
10264
  {3718, 3722}, {3724, 3747}, {3749, 3749}, {3751, 3760},
10265
  {3762, 3763}, {3773, 3773}, {3776, 3780}, {3782, 3782},
10266
  {3804, 3807}, {3840, 3840}, {3904, 3911}, {3913, 3948},
10267
  {3976, 3980}, {4096, 4138}, {4159, 4159}, {4176, 4181},
10268
  {4186, 4189}, {4193, 4193}, {4197, 4198}, {4206, 4208},
10269
  {4213, 4225}, {4238, 4238}, {4256, 4293}, {4295, 4295},
10270
  {4301, 4301}, {4304, 4346}, {4348, 4348}, {4349, 4351},
10271
  {4352, 4680}, {4682, 4685}, {4688, 4694}, {4696, 4696},
10272
  {4698, 4701}, {4704, 4744}, {4746, 4749}, {4752, 4784},
10273
  {4786, 4789}, {4792, 4798}, {4800, 4800}, {4802, 4805},
10274
  {4808, 4822}, {4824, 4880}, {4882, 4885}, {4888, 4954},
10275
  {4992, 5007}, {5024, 5109}, {5112, 5117}, {5121, 5740},
10276
  {5743, 5759}, {5761, 5786}, {5792, 5866}, {5870, 5872},
10277
  {5873, 5880}, {5888, 5905}, {5919, 5937}, {5952, 5969},
10278
  {5984, 5996}, {5998, 6000}, {6016, 6067}, {6103, 6103},
10279
  {6108, 6108}, {6176, 6210}, {6211, 6211}, {6212, 6264},
10280
  {6272, 6276}, {6277, 6278}, {6279, 6312}, {6314, 6314},
10281
  {6320, 6389}, {6400, 6430}, {6480, 6509}, {6512, 6516},
10282
  {6528, 6571}, {6576, 6601}, {6656, 6678}, {6688, 6740},
10283
  {6823, 6823}, {6917, 6963}, {6981, 6988}, {7043, 7072},
10284
  {7086, 7087}, {7098, 7141}, {7168, 7203}, {7245, 7247},
10285
  {7258, 7287}, {7288, 7293}, {7296, 7306}, {7312, 7354},
10286
  {7357, 7359}, {7401, 7404}, {7406, 7411}, {7413, 7414},
10287
  {7418, 7418}, {7424, 7467}, {7468, 7530}, {7531, 7543},
10288
  {7544, 7544}, {7545, 7578}, {7579, 7615}, {7680, 7957},
10289
  {7960, 7965}, {7968, 8005}, {8008, 8013}, {8016, 8023},
10290
  {8025, 8025}, {8027, 8027}, {8029, 8029}, {8031, 8061},
10291
  {8064, 8116}, {8118, 8124}, {8126, 8126}, {8130, 8132},
10292
  {8134, 8140}, {8144, 8147}, {8150, 8155}, {8160, 8172},
10293
  {8178, 8180}, {8182, 8188}, {8305, 8305}, {8319, 8319},
10294
  {8336, 8348}, {8450, 8450}, {8455, 8455}, {8458, 8467},
10295
  {8469, 8469}, {8472, 8472}, {8473, 8477}, {8484, 8484},
10296
  {8486, 8486}, {8488, 8488}, {8490, 8493}, {8494, 8494},
10297
  {8495, 8500}, {8501, 8504}, {8505, 8505}, {8508, 8511},
10298
  {8517, 8521}, {8526, 8526}, {8544, 8578}, {8579, 8580},
10299
  {8581, 8584}, {11264, 11387}, {11388, 11389}, {11390, 11492},
10300
  {11499, 11502}, {11506, 11507}, {11520, 11557}, {11559, 11559},
10301
  {11565, 11565}, {11568, 11623}, {11631, 11631}, {11648, 11670},
10302
  {11680, 11686}, {11688, 11694}, {11696, 11702}, {11704, 11710},
10303
  {11712, 11718}, {11720, 11726}, {11728, 11734}, {11736, 11742},
10304
  {12293, 12293}, {12294, 12294}, {12295, 12295}, {12321, 12329},
10305
  {12337, 12341}, {12344, 12346}, {12347, 12347}, {12348, 12348},
10306
  {12353, 12438}, {12443, 12444}, {12445, 12446}, {12447, 12447},
10307
  {12449, 12538}, {12540, 12542}, {12543, 12543}, {12549, 12591},
10308
  {12593, 12686}, {12704, 12735}, {12784, 12799}, {13312, 19903},
10309
  {19968, 40980}, {40981, 40981}, {40982, 42124}, {42192, 42231},
10310
  {42232, 42237}, {42240, 42507}, {42508, 42508}, {42512, 42527},
10311
  {42538, 42539}, {42560, 42605}, {42606, 42606}, {42623, 42623},
10312
  {42624, 42651}, {42652, 42653}, {42656, 42725}, {42726, 42735},
10313
  {42775, 42783}, {42786, 42863}, {42864, 42864}, {42865, 42887},
10314
  {42888, 42888}, {42891, 42894}, {42895, 42895}, {42896, 42972},
10315
  {42993, 42996}, {42997, 42998}, {42999, 42999}, {43000, 43001},
10316
  {43002, 43002}, {43003, 43009}, {43011, 43013}, {43015, 43018},
10317
  {43020, 43042}, {43072, 43123}, {43138, 43187}, {43250, 43255},
10318
  {43259, 43259}, {43261, 43262}, {43274, 43301}, {43312, 43334},
10319
  {43360, 43388}, {43396, 43442}, {43471, 43471}, {43488, 43492},
10320
  {43494, 43494}, {43495, 43503}, {43514, 43518}, {43520, 43560},
10321
  {43584, 43586}, {43588, 43595}, {43616, 43631}, {43632, 43632},
10322
  {43633, 43638}, {43642, 43642}, {43646, 43695}, {43697, 43697},
10323
  {43701, 43702}, {43705, 43709}, {43712, 43712}, {43714, 43714},
10324
  {43739, 43740}, {43741, 43741}, {43744, 43754}, {43762, 43762},
10325
  {43763, 43764}, {43777, 43782}, {43785, 43790}, {43793, 43798},
10326
  {43808, 43814}, {43816, 43822}, {43824, 43866}, {43868, 43871},
10327
  {43872, 43880}, {43881, 43881}, {43888, 43967}, {43968, 44002},
10328
  {44032, 55203}, {55216, 55238}, {55243, 55291}, {63744, 64109},
10329
  {64112, 64217}, {64256, 64262}, {64275, 64279}, {64285, 64285},
10330
  {64287, 64296}, {64298, 64310}, {64312, 64316}, {64318, 64318},
10331
  {64320, 64321}, {64323, 64324}, {64326, 64433}, {64467, 64829},
10332
  {64848, 64911}, {64914, 64967}, {65008, 65019}, {65136, 65140},
10333
  {65142, 65276}, {65313, 65338}, {65345, 65370}, {65382, 65391},
10334
  {65392, 65392}, {65393, 65437}, {65438, 65439}, {65440, 65470},
10335
  {65474, 65479}, {65482, 65487}, {65490, 65495}, {65498, 65500},
10336
  {65536, 65547}, {65549, 65574}, {65576, 65594}, {65596, 65597},
10337
  {65599, 65613}, {65616, 65629}, {65664, 65786}, {65856, 65908},
10338
  {66176, 66204}, {66208, 66256}, {66304, 66335}, {66349, 66368},
10339
  {66369, 66369}, {66370, 66377}, {66378, 66378}, {66384, 66421},
10340
  {66432, 66461}, {66464, 66499}, {66504, 66511}, {66513, 66517},
10341
  {66560, 66639}, {66640, 66717}, {66736, 66771}, {66776, 66811},
10342
  {66816, 66855}, {66864, 66915}, {66928, 66938}, {66940, 66954},
10343
  {66956, 66962}, {66964, 66965}, {66967, 66977}, {66979, 66993},
10344
  {66995, 67001}, {67003, 67004}, {67008, 67059}, {67072, 67382},
10345
  {67392, 67413}, {67424, 67431}, {67456, 67461}, {67463, 67504},
10346
  {67506, 67514}, {67584, 67589}, {67592, 67592}, {67594, 67637},
10347
  {67639, 67640}, {67644, 67644}, {67647, 67669}, {67680, 67702},
10348
  {67712, 67742}, {67808, 67826}, {67828, 67829}, {67840, 67861},
10349
  {67872, 67897}, {67904, 67929}, {67968, 68023}, {68030, 68031},
10350
  {68096, 68096}, {68112, 68115}, {68117, 68119}, {68121, 68149},
10351
  {68192, 68220}, {68224, 68252}, {68288, 68295}, {68297, 68324},
10352
  {68352, 68405}, {68416, 68437}, {68448, 68466}, {68480, 68497},
10353
  {68608, 68680}, {68736, 68786}, {68800, 68850}, {68864, 68899},
10354
  {68938, 68941}, {68942, 68942}, {68943, 68943}, {68944, 68965},
10355
  {68975, 68975}, {68976, 68997}, {69248, 69289}, {69296, 69297},
10356
  {69314, 69316}, {69317, 69317}, {69318, 69319}, {69376, 69404},
10357
  {69415, 69415}, {69424, 69445}, {69488, 69505}, {69552, 69572},
10358
  {69600, 69622}, {69635, 69687}, {69745, 69746}, {69749, 69749},
10359
  {69763, 69807}, {69840, 69864}, {69891, 69926}, {69956, 69956},
10360
  {69959, 69959}, {69968, 70002}, {70006, 70006}, {70019, 70066},
10361
  {70081, 70084}, {70106, 70106}, {70108, 70108}, {70144, 70161},
10362
  {70163, 70187}, {70207, 70208}, {70272, 70278}, {70280, 70280},
10363
  {70282, 70285}, {70287, 70301}, {70303, 70312}, {70320, 70366},
10364
  {70405, 70412}, {70415, 70416}, {70419, 70440}, {70442, 70448},
10365
  {70450, 70451}, {70453, 70457}, {70461, 70461}, {70480, 70480},
10366
  {70493, 70497}, {70528, 70537}, {70539, 70539}, {70542, 70542},
10367
  {70544, 70581}, {70583, 70583}, {70609, 70609}, {70611, 70611},
10368
  {70656, 70708}, {70727, 70730}, {70751, 70753}, {70784, 70831},
10369
  {70852, 70853}, {70855, 70855}, {71040, 71086}, {71128, 71131},
10370
  {71168, 71215}, {71236, 71236}, {71296, 71338}, {71352, 71352},
10371
  {71424, 71450}, {71488, 71494}, {71680, 71723}, {71840, 71903},
10372
  {71935, 71942}, {71945, 71945}, {71948, 71955}, {71957, 71958},
10373
  {71960, 71983}, {71999, 71999}, {72001, 72001}, {72096, 72103},
10374
  {72106, 72144}, {72161, 72161}, {72163, 72163}, {72192, 72192},
10375
  {72203, 72242}, {72250, 72250}, {72272, 72272}, {72284, 72329},
10376
  {72349, 72349}, {72368, 72440}, {72640, 72672}, {72704, 72712},
10377
  {72714, 72750}, {72768, 72768}, {72818, 72847}, {72960, 72966},
10378
  {72968, 72969}, {72971, 73008}, {73030, 73030}, {73056, 73061},
10379
  {73063, 73064}, {73066, 73097}, {73112, 73112}, {73136, 73176},
10380
  {73177, 73177}, {73178, 73179}, {73440, 73458}, {73474, 73474},
10381
  {73476, 73488}, {73490, 73523}, {73648, 73648}, {73728, 74649},
10382
  {74752, 74862}, {74880, 75075}, {77712, 77808}, {77824, 78895},
10383
  {78913, 78918}, {78944, 82938}, {82944, 83526}, {90368, 90397},
10384
  {92160, 92728}, {92736, 92766}, {92784, 92862}, {92880, 92909},
10385
  {92928, 92975}, {92992, 92995}, {93027, 93047}, {93053, 93071},
10386
  {93504, 93506}, {93507, 93546}, {93547, 93548}, {93760, 93823},
10387
  {93856, 93880}, {93883, 93907}, {93952, 94026}, {94032, 94032},
10388
  {94099, 94111}, {94176, 94177}, {94179, 94179}, {94194, 94195},
10389
  {94196, 94198}, {94208, 101589}, {101631, 101662}, {101760, 101874},
10390
  {110576, 110579}, {110581, 110587}, {110589, 110590}, {110592, 110882},
10391
  {110898, 110898}, {110928, 110930}, {110933, 110933}, {110948, 110951},
10392
  {110960, 111355}, {113664, 113770}, {113776, 113788}, {113792, 113800},
10393
  {113808, 113817}, {119808, 119892}, {119894, 119964}, {119966, 119967},
10394
  {119970, 119970}, {119973, 119974}, {119977, 119980}, {119982, 119993},
10395
  {119995, 119995}, {119997, 120003}, {120005, 120069}, {120071, 120074},
10396
  {120077, 120084}, {120086, 120092}, {120094, 120121}, {120123, 120126},
10397
  {120128, 120132}, {120134, 120134}, {120138, 120144}, {120146, 120485},
10398
  {120488, 120512}, {120514, 120538}, {120540, 120570}, {120572, 120596},
10399
  {120598, 120628}, {120630, 120654}, {120656, 120686}, {120688, 120712},
10400
  {120714, 120744}, {120746, 120770}, {120772, 120779}, {122624, 122633},
10401
  {122634, 122634}, {122635, 122654}, {122661, 122666}, {122928, 122989},
10402
  {123136, 123180}, {123191, 123197}, {123214, 123214}, {123536, 123565},
10403
  {123584, 123627}, {124112, 124138}, {124139, 124139}, {124368, 124397},
10404
  {124400, 124400}, {124608, 124638}, {124640, 124642}, {124644, 124645},
10405
  {124647, 124653}, {124656, 124660}, {124670, 124670}, {124671, 124671},
10406
  {124896, 124902}, {124904, 124907}, {124909, 124910}, {124912, 124926},
10407
  {124928, 125124}, {125184, 125251}, {125259, 125259}, {126464, 126467},
10408
  {126469, 126495}, {126497, 126498}, {126500, 126500}, {126503, 126503},
10409
  {126505, 126514}, {126516, 126519}, {126521, 126521}, {126523, 126523},
10410
  {126530, 126530}, {126535, 126535}, {126537, 126537}, {126539, 126539},
10411
  {126541, 126543}, {126545, 126546}, {126548, 126548}, {126551, 126551},
10412
  {126553, 126553}, {126555, 126555}, {126557, 126557}, {126559, 126559},
10413
  {126561, 126562}, {126564, 126564}, {126567, 126570}, {126572, 126578},
10414
  {126580, 126583}, {126585, 126588}, {126590, 126590}, {126592, 126601},
10415
  {126603, 126619}, {126625, 126627}, {126629, 126633}, {126635, 126651},
10416
  {131072, 173791}, {173824, 178205}, {178208, 183981}, {183984, 191456},
10417
  {191472, 192093}, {194560, 195101}, {196608, 201546}, {201552, 210041}
10418
};
10419
10420
10421
} // namespace ada::idna
10422
#endif // ADA_IDNA_IDENTIFIER_TABLES_H
10423
/* end file src/id_tables.cpp */
10424
10425
namespace ada::idna {
10426
0
constexpr bool is_ascii_letter(char32_t c) noexcept {
10427
0
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
10428
0
}
10429
10430
0
constexpr bool is_ascii_letter_or_digit(char32_t c) noexcept {
10431
0
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
10432
0
         (c >= '0' && c <= '9');
10433
0
}
10434
10435
0
bool valid_name_code_point(char32_t code_point, bool first) {
10436
  // https://tc39.es/ecma262/#prod-IdentifierStart
10437
  // Fast paths:
10438
0
  if (first &&
10439
0
      (code_point == '$' || code_point == '_' || is_ascii_letter(code_point))) {
10440
0
    return true;
10441
0
  }
10442
0
  if (!first && (code_point == '$' || is_ascii_letter_or_digit(code_point))) {
10443
0
    return true;
10444
0
  }
10445
  // Slow path...
10446
0
  if (code_point == 0xffffffff) {
10447
0
    return false;  // minimal error handling
10448
0
  }
10449
0
  if (first) {
10450
0
    auto iter = std::lower_bound(
10451
0
        std::begin(ada::idna::id_start), std::end(ada::idna::id_start),
10452
0
        code_point,
10453
0
        [](const uint32_t* range, uint32_t cp) { return range[1] < cp; });
10454
0
    return iter != std::end(id_start) && code_point >= (*iter)[0];
10455
0
  } else {
10456
0
    auto iter = std::lower_bound(
10457
0
        std::begin(id_continue), std::end(id_continue), code_point,
10458
0
        [](const uint32_t* range, uint32_t cp) { return range[1] < cp; });
10459
0
    return iter != std::end(id_start) && code_point >= (*iter)[0];
10460
0
  }
10461
0
}
10462
}  // namespace ada::idna
10463
/* end file src/identifier.cpp */
10464
/* end file src/idna.cpp */
10465
// NOLINTEND
10466
/* end file src/ada_idna.cpp */
10467
ADA_POP_DISABLE_WARNINGS
10468
10469
#include <algorithm>
10470
#if ADA_SSSE3
10471
#include <tmmintrin.h>
10472
#elif ADA_NEON
10473
#include <arm_neon.h>
10474
#elif ADA_SSE2
10475
#include <emmintrin.h>
10476
#elif ADA_LSX
10477
#include <lsxintrin.h>
10478
#elif ADA_RVV
10479
#include <riscv_vector.h>
10480
#endif
10481
10482
#include <ranges>
10483
10484
namespace ada::unicode {
10485
10486
129k
constexpr bool is_tabs_or_newline(char c) noexcept {
10487
129k
  return c == '\r' || c == '\n' || c == '\t';
10488
129k
}
10489
10490
54.6k
constexpr uint64_t broadcast(uint8_t v) noexcept {
10491
54.6k
  return 0x101010101010101ull * v;
10492
54.6k
}
10493
10494
18.2k
constexpr bool to_lower_ascii(char* input, size_t length) noexcept {
10495
18.2k
  uint64_t broadcast_80 = broadcast(0x80);
10496
18.2k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
10497
18.2k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
10498
18.2k
  uint64_t non_ascii = 0;
10499
18.2k
  size_t i = 0;
10500
10501
28.0k
  for (; i + 7 < length; i += 8) {
10502
9.82k
    uint64_t word{};
10503
9.82k
    memcpy(&word, input + i, sizeof(word));
10504
9.82k
    non_ascii |= (word & broadcast_80);
10505
9.82k
    word ^=
10506
9.82k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10507
9.82k
    memcpy(input + i, &word, sizeof(word));
10508
9.82k
  }
10509
18.2k
  if (i < length) {
10510
18.0k
    uint64_t word{};
10511
18.0k
    memcpy(&word, input + i, length - i);
10512
18.0k
    non_ascii |= (word & broadcast_80);
10513
18.0k
    word ^=
10514
18.0k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10515
18.0k
    memcpy(input + i, &word, length - i);
10516
18.0k
  }
10517
18.2k
  return non_ascii == 0;
10518
18.2k
}
10519
#if ADA_SSSE3
10520
ada_really_inline bool has_tabs_or_newline(
10521
    std::string_view user_input) noexcept {
10522
  // first check for short strings in which case we do it naively.
10523
  if (user_input.size() < 16) {  // slow path
10524
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10525
  }
10526
  // fast path for long strings (expected to be common)
10527
  // Using SSSE3's _mm_shuffle_epi8 for table lookup (same approach as NEON)
10528
  size_t i = 0;
10529
  // Lookup table where positions 9, 10, 13 contain their own values
10530
  // Everything else is set to 1 so it won't match
10531
  const __m128i rnt =
10532
      _mm_setr_epi8(1, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 0, 0, 13, 0, 0);
10533
  __m128i running = _mm_setzero_si128();
10534
  for (; i + 15 < user_input.size(); i += 16) {
10535
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
10536
    // Shuffle the lookup table using input bytes as indices
10537
    __m128i shuffled = _mm_shuffle_epi8(rnt, word);
10538
    // Compare: if shuffled value matches input, we found \t, \n, or \r
10539
    __m128i matches = _mm_cmpeq_epi8(shuffled, word);
10540
    running = _mm_or_si128(running, matches);
10541
  }
10542
  if (i < user_input.size()) {
10543
    __m128i word = _mm_loadu_si128(
10544
        (const __m128i*)(user_input.data() + user_input.length() - 16));
10545
    __m128i shuffled = _mm_shuffle_epi8(rnt, word);
10546
    __m128i matches = _mm_cmpeq_epi8(shuffled, word);
10547
    running = _mm_or_si128(running, matches);
10548
  }
10549
  return _mm_movemask_epi8(running) != 0;
10550
}
10551
#elif ADA_NEON
10552
ada_really_inline bool has_tabs_or_newline(
10553
    std::string_view user_input) noexcept {
10554
  // first check for short strings in which case we do it naively.
10555
  if (user_input.size() < 16) {  // slow path
10556
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10557
  }
10558
  // fast path for long strings (expected to be common)
10559
  size_t i = 0;
10560
  /**
10561
   * The fastest way to check for `\t` (==9), '\n'(== 10) and `\r` (==13) relies
10562
   * on table lookup instruction. We notice that these are all unique numbers
10563
   * between 0..15. Let's prepare a special register, where we put '\t' in the
10564
   * 9th position, '\n' - 10th and '\r' - 13th. Then we shuffle this register by
10565
   * input register. If the input had `\t` in position X then this shuffled
10566
   * register will also have '\t' in that position. Comparing input with this
10567
   * shuffled register will mark us all interesting characters in the input.
10568
   *
10569
   * credit for algorithmic idea: @aqrit, credit for description:
10570
   * @DenisYaroshevskiy
10571
   */
10572
  static uint8_t rnt_array[16] = {1, 0, 0,  0, 0, 0,  0, 0,
10573
                                  0, 9, 10, 0, 0, 13, 0, 0};
10574
  const uint8x16_t rnt = vld1q_u8(rnt_array);
10575
  // m['0xd', '0xa', '0x9']
10576
  uint8x16_t running{0};
10577
  for (; i + 15 < user_input.size(); i += 16) {
10578
    uint8x16_t word = vld1q_u8((const uint8_t*)user_input.data() + i);
10579
10580
    running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word));
10581
  }
10582
  if (i < user_input.size()) {
10583
    uint8x16_t word =
10584
        vld1q_u8((const uint8_t*)user_input.data() + user_input.length() - 16);
10585
    running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word));
10586
  }
10587
  return vmaxvq_u32(vreinterpretq_u32_u8(running)) != 0;
10588
}
10589
#elif ADA_SSE2
10590
ada_really_inline bool has_tabs_or_newline(
10591
29.9k
    std::string_view user_input) noexcept {
10592
  // first check for short strings in which case we do it naively.
10593
29.9k
  if (user_input.size() < 16) {  // slow path
10594
15.3k
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10595
15.3k
  }
10596
  // fast path for long strings (expected to be common)
10597
14.5k
  size_t i = 0;
10598
14.5k
  const __m128i mask1 = _mm_set1_epi8('\r');
10599
14.5k
  const __m128i mask2 = _mm_set1_epi8('\n');
10600
14.5k
  const __m128i mask3 = _mm_set1_epi8('\t');
10601
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10602
14.5k
  __m128i running{0};
10603
177k
  for (; i + 15 < user_input.size(); i += 16) {
10604
162k
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
10605
162k
    running = _mm_or_si128(
10606
162k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10607
162k
                                           _mm_cmpeq_epi8(word, mask2))),
10608
162k
        _mm_cmpeq_epi8(word, mask3));
10609
162k
  }
10610
14.5k
  if (i < user_input.size()) {
10611
12.7k
    __m128i word = _mm_loadu_si128(
10612
12.7k
        (const __m128i*)(user_input.data() + user_input.length() - 16));
10613
12.7k
    running = _mm_or_si128(
10614
12.7k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10615
12.7k
                                           _mm_cmpeq_epi8(word, mask2))),
10616
12.7k
        _mm_cmpeq_epi8(word, mask3));
10617
12.7k
  }
10618
14.5k
  return _mm_movemask_epi8(running) != 0;
10619
29.9k
}
10620
#elif ADA_LSX
10621
ada_really_inline bool has_tabs_or_newline(
10622
    std::string_view user_input) noexcept {
10623
  // first check for short strings in which case we do it naively.
10624
  if (user_input.size() < 16) {  // slow path
10625
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10626
  }
10627
  // fast path for long strings (expected to be common)
10628
  size_t i = 0;
10629
  const __m128i mask1 = __lsx_vrepli_b('\r');
10630
  const __m128i mask2 = __lsx_vrepli_b('\n');
10631
  const __m128i mask3 = __lsx_vrepli_b('\t');
10632
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10633
  __m128i running{0};
10634
  for (; i + 15 < user_input.size(); i += 16) {
10635
    __m128i word = __lsx_vld((const __m128i*)(user_input.data() + i), 0);
10636
    running = __lsx_vor_v(
10637
        __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1),
10638
                                         __lsx_vseq_b(word, mask2))),
10639
        __lsx_vseq_b(word, mask3));
10640
  }
10641
  if (i < user_input.size()) {
10642
    __m128i word = __lsx_vld(
10643
        (const __m128i*)(user_input.data() + user_input.length() - 16), 0);
10644
    running = __lsx_vor_v(
10645
        __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1),
10646
                                         __lsx_vseq_b(word, mask2))),
10647
        __lsx_vseq_b(word, mask3));
10648
  }
10649
  if (__lsx_bz_v(running)) return false;
10650
  return true;
10651
}
10652
#elif ADA_RVV
10653
ada_really_inline bool has_tabs_or_newline(
10654
    std::string_view user_input) noexcept {
10655
  uint8_t* src = (uint8_t*)user_input.data();
10656
  for (size_t vl, n = user_input.size(); n > 0; n -= vl, src += vl) {
10657
    vl = __riscv_vsetvl_e8m1(n);
10658
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
10659
    vbool8_t m1 = __riscv_vmseq(v, '\r', vl);
10660
    vbool8_t m2 = __riscv_vmseq(v, '\n', vl);
10661
    vbool8_t m3 = __riscv_vmseq(v, '\t', vl);
10662
    vbool8_t m = __riscv_vmor(__riscv_vmor(m1, m2, vl), m3, vl);
10663
    long idx = __riscv_vfirst(m, vl);
10664
    if (idx >= 0) return true;
10665
  }
10666
  return false;
10667
}
10668
#else
10669
ada_really_inline bool has_tabs_or_newline(
10670
    std::string_view user_input) noexcept {
10671
  auto has_zero_byte = [](uint64_t v) {
10672
    return ((v - 0x0101010101010101) & ~(v) & 0x8080808080808080);
10673
  };
10674
  size_t i = 0;
10675
  uint64_t mask1 = broadcast('\r');
10676
  uint64_t mask2 = broadcast('\n');
10677
  uint64_t mask3 = broadcast('\t');
10678
  uint64_t running{0};
10679
  for (; i + 7 < user_input.size(); i += 8) {
10680
    uint64_t word{};
10681
    memcpy(&word, user_input.data() + i, sizeof(word));
10682
    uint64_t xor1 = word ^ mask1;
10683
    uint64_t xor2 = word ^ mask2;
10684
    uint64_t xor3 = word ^ mask3;
10685
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
10686
  }
10687
  if (i < user_input.size()) {
10688
    uint64_t word{};
10689
    memcpy(&word, user_input.data() + i, user_input.size() - i);
10690
    uint64_t xor1 = word ^ mask1;
10691
    uint64_t xor2 = word ^ mask2;
10692
    uint64_t xor3 = word ^ mask3;
10693
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
10694
  }
10695
  return running;
10696
}
10697
#endif
10698
10699
// A forbidden host code point is U+0000 NULL, U+0009 TAB, U+000A LF, U+000D CR,
10700
// U+0020 SPACE, U+0023 (#), U+002F (/), U+003A (:), U+003C (<), U+003E (>),
10701
// U+003F (?), U+0040 (@), U+005B ([), U+005C (\), U+005D (]), U+005E (^), or
10702
// U+007C (|).
10703
constexpr static std::array<uint8_t, 256> is_forbidden_host_code_point_table =
10704
    []() consteval {
10705
      std::array<uint8_t, 256> result{};
10706
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10707
                        '>', '?', '@', '[', '\\', ']', '^', '|'}) {
10708
        result[c] = true;
10709
      }
10710
      return result;
10711
    }();
10712
10713
ada_really_inline constexpr bool is_forbidden_host_code_point(
10714
151k
    const char c) noexcept {
10715
151k
  return is_forbidden_host_code_point_table[uint8_t(c)];
10716
151k
}
10717
10718
constexpr static std::array<uint8_t, 256> is_forbidden_domain_code_point_table =
10719
    []() consteval {
10720
      std::array<uint8_t, 256> result{};
10721
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10722
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
10723
        result[c] = true;
10724
      }
10725
      for (uint8_t c = 0; c <= 32; c++) {
10726
        result[c] = true;
10727
      }
10728
      for (size_t c = 127; c < 255; c++) {
10729
        result[c] = true;
10730
      }
10731
      return result;
10732
    }();
10733
10734
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
10735
10736
ada_really_inline constexpr bool is_forbidden_domain_code_point(
10737
1.39M
    const char c) noexcept {
10738
1.39M
  return is_forbidden_domain_code_point_table[uint8_t(c)];
10739
1.39M
}
10740
10741
ada_really_inline constexpr bool contains_forbidden_domain_code_point(
10742
9.70k
    const char* input, size_t length) noexcept {
10743
9.70k
  size_t i = 0;
10744
9.70k
  uint8_t accumulator{};
10745
455k
  for (; i + 4 <= length; i += 4) {
10746
445k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10747
445k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 1])];
10748
445k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 2])];
10749
445k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 3])];
10750
445k
  }
10751
24.6k
  for (; i < length; i++) {
10752
14.9k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10753
14.9k
  }
10754
9.70k
  return accumulator;
10755
9.70k
}
10756
10757
constexpr static std::array<uint8_t, 256>
10758
    is_forbidden_domain_code_point_table_or_upper = []() consteval {
10759
      std::array<uint8_t, 256> result{};
10760
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10761
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
10762
        result[c] = 1;
10763
      }
10764
      for (uint8_t c = 'A'; c <= 'Z'; c++) {
10765
        result[c] = 2;
10766
      }
10767
      for (uint8_t c = 0; c <= 32; c++) {
10768
        result[c] = 1;
10769
      }
10770
      for (size_t c = 127; c < 255; c++) {
10771
        result[c] = 1;
10772
      }
10773
      return result;
10774
    }();
10775
10776
ada_really_inline constexpr uint8_t
10777
contains_forbidden_domain_code_point_or_upper(const char* input,
10778
19.0k
                                              size_t length) noexcept {
10779
19.0k
  size_t i = 0;
10780
19.0k
  uint8_t accumulator{};
10781
244k
  for (; i + 4 <= length; i += 4) {
10782
225k
    accumulator |=
10783
225k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10784
225k
    accumulator |=
10785
225k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 1])];
10786
225k
    accumulator |=
10787
225k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 2])];
10788
225k
    accumulator |=
10789
225k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 3])];
10790
225k
  }
10791
48.3k
  for (; i < length; i++) {
10792
29.3k
    accumulator |=
10793
29.3k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10794
29.3k
  }
10795
19.0k
  return accumulator;
10796
19.0k
}
10797
10798
// std::isalnum(c) || c == '+' || c == '-' || c == '.') is true for
10799
constexpr static std::array<bool, 256> is_alnum_plus_table = []() consteval {
10800
  std::array<bool, 256> result{};
10801
  for (size_t c = 0; c < 256; c++) {
10802
    result[c] = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
10803
                (c >= 'A' && c <= 'Z') || c == '+' || c == '-' || c == '.';
10804
  }
10805
  return result;
10806
}();
10807
10808
158k
ada_really_inline constexpr bool is_alnum_plus(const char c) noexcept {
10809
158k
  return is_alnum_plus_table[uint8_t(c)];
10810
  // A table is almost surely much faster than the
10811
  // following under most compilers: return
10812
  // return (std::isalnum(c) || c == '+' || c == '-' || c == '.');
10813
158k
}
10814
10815
51.5k
ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept {
10816
51.5k
  return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
10817
3.31k
         (c >= 'a' && c <= 'f');
10818
51.5k
}
10819
10820
12.7k
ada_really_inline constexpr bool is_ascii_digit(const char c) noexcept {
10821
  // An ASCII digit is a code point in the range U+0030 (0) to U+0039 (9),
10822
  // inclusive.
10823
12.7k
  return (c >= '0' && c <= '9');
10824
12.7k
}
10825
10826
0
ada_really_inline constexpr bool is_ascii(const char32_t c) noexcept {
10827
  // If code point is between U+0000 and U+007F inclusive, then return true.
10828
0
  return c <= 0x7F;
10829
0
}
10830
10831
99.9k
ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept {
10832
99.9k
  return (unsigned char)c <= ' ';
10833
99.9k
}
10834
10835
ada_really_inline constexpr bool is_ascii_tab_or_newline(
10836
3.65M
    const char c) noexcept {
10837
3.65M
  return c == '\t' || c == '\n' || c == '\r';
10838
3.65M
}
10839
10840
constexpr std::string_view table_is_double_dot_path_segment[] = {
10841
    "..", "%2e.", ".%2e", "%2e%2e"};
10842
10843
ada_really_inline constexpr bool is_double_dot_path_segment(
10844
23.8k
    std::string_view input) noexcept {
10845
  // This will catch most cases:
10846
  // The length must be 2,4 or 6.
10847
  // We divide by two and require
10848
  // that the result be between 1 and 3 inclusively.
10849
23.8k
  uint64_t half_length = uint64_t(input.size()) / 2;
10850
23.8k
  if (half_length - 1 > 2) {
10851
13.4k
    return false;
10852
13.4k
  }
10853
  // We have a string of length 2, 4 or 6.
10854
  // We now check the first character:
10855
10.3k
  if ((input[0] != '.') && (input[0] != '%')) {
10856
2.59k
    return false;
10857
2.59k
  }
10858
  // We are unlikely the get beyond this point.
10859
7.75k
  int hash_value = (input.size() + (unsigned)(input[0])) & 3;
10860
7.75k
  const std::string_view target = table_is_double_dot_path_segment[hash_value];
10861
7.75k
  if (target.size() != input.size()) {
10862
2.01k
    return false;
10863
2.01k
  }
10864
  // We almost never get here.
10865
  // Optimizing the rest is relatively unimportant.
10866
5.73k
  auto prefix_equal_unsafe = [](std::string_view a, std::string_view b) {
10867
5.73k
    uint16_t A, B;
10868
5.73k
    memcpy(&A, a.data(), sizeof(A));
10869
5.73k
    memcpy(&B, b.data(), sizeof(B));
10870
5.73k
    return A == B;
10871
5.73k
  };
10872
5.73k
  if (!prefix_equal_unsafe(input, target)) {
10873
495
    return false;
10874
495
  }
10875
6.34k
  for (size_t i = 2; i < input.size(); i++) {
10876
1.90k
    char c = input[i];
10877
1.90k
    if ((uint8_t((c | 0x20) - 0x61) <= 25 ? (c | 0x20) : c) != target[i]) {
10878
805
      return false;
10879
805
    }
10880
1.90k
  }
10881
4.43k
  return true;
10882
  // The above code might be a bit better than the code below. Compilers
10883
  // are not stupid and may use the fact that these strings have length 2,4 and
10884
  // 6 and other tricks.
10885
  // return input == ".." ||
10886
  //  input == ".%2e" || input == ".%2E" ||
10887
  //  input == "%2e." || input == "%2E." ||
10888
  //  input == "%2e%2e" || input == "%2E%2E" || input == "%2E%2e" || input ==
10889
  //  "%2e%2E";
10890
5.24k
}
10891
10892
ada_really_inline constexpr bool is_single_dot_path_segment(
10893
38.5k
    std::string_view input) noexcept {
10894
38.5k
  return input == "." || input == "%2e" || input == "%2E";
10895
38.5k
}
10896
10897
19.8k
ada_really_inline constexpr bool is_lowercase_hex(const char c) noexcept {
10898
19.8k
  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
10899
19.8k
}
10900
10901
constexpr static char hex_to_binary_table[] = {
10902
    0,  1,  2,  3,  4, 5, 6, 7, 8, 9, 0, 0,  0,  0,  0,  0,  0, 10, 11,
10903
    12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0,  0,
10904
    0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
10905
48.7k
unsigned constexpr convert_hex_to_binary(const char c) noexcept {
10906
48.7k
  return hex_to_binary_table[c - '0'];
10907
48.7k
}
10908
10909
864
std::string percent_decode(const std::string_view input, size_t first_percent) {
10910
  // next line is for safety only, we expect users to avoid calling
10911
  // percent_decode when first_percent is outside the range.
10912
864
  if (first_percent == std::string_view::npos) {
10913
0
    return std::string(input);
10914
0
  }
10915
864
  std::string dest;
10916
864
  dest.reserve(input.length());
10917
864
  dest.append(input.substr(0, first_percent));
10918
864
  const char* pointer = input.data() + first_percent;
10919
864
  const char* end = input.data() + input.size();
10920
  // Optimization opportunity: if the following code gets
10921
  // called often, it can be optimized quite a bit.
10922
64.0k
  while (pointer < end) {
10923
63.1k
    const char ch = pointer[0];
10924
63.1k
    size_t remaining = end - pointer - 1;
10925
63.1k
    if (ch != '%' || remaining < 2 ||
10926
25.3k
        (  // ch == '%' && // It is unnecessary to check that ch == '%'.
10927
25.3k
            (!is_ascii_hex_digit(pointer[1]) ||
10928
39.4k
             !is_ascii_hex_digit(pointer[2])))) {
10929
39.4k
      dest += ch;
10930
39.4k
      pointer++;
10931
39.4k
    } else {
10932
23.6k
      unsigned a = convert_hex_to_binary(pointer[1]);
10933
23.6k
      unsigned b = convert_hex_to_binary(pointer[2]);
10934
23.6k
      char c = static_cast<char>(a * 16 + b);
10935
23.6k
      dest += c;
10936
23.6k
      pointer += 3;
10937
23.6k
    }
10938
63.1k
  }
10939
864
  return dest;
10940
864
}
10941
10942
std::string percent_encode(const std::string_view input,
10943
16.2k
                           const uint8_t character_set[]) {
10944
65.0k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10945
65.0k
    return character_sets::bit_at(character_set, c);
10946
65.0k
  });
10947
  // Optimization: Don't iterate if percent encode is not required
10948
16.2k
  if (pointer == input.end()) {
10949
11.3k
    return std::string(input);
10950
11.3k
  }
10951
10952
4.85k
  std::string result;
10953
4.85k
  result.reserve(input.length());  // in the worst case, percent encoding might
10954
                                   // produce 3 characters.
10955
4.85k
  result.append(input.substr(0, std::distance(input.begin(), pointer)));
10956
10957
401k
  for (; pointer != input.end(); pointer++) {
10958
396k
    if (character_sets::bit_at(character_set, *pointer)) {
10959
351k
      result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10960
351k
    } else {
10961
44.6k
      result += *pointer;
10962
44.6k
    }
10963
396k
  }
10964
10965
4.85k
  return result;
10966
16.2k
}
10967
10968
template <bool append>
10969
bool percent_encode(const std::string_view input, const uint8_t character_set[],
10970
30.7k
                    std::string& out) {
10971
30.7k
  ada_log("percent_encode ", input, " to output string while ",
10972
30.7k
          append ? "appending" : "overwriting");
10973
379k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10974
379k
    return character_sets::bit_at(character_set, c);
10975
379k
  });
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
Line
Count
Source
10973
59.3k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10974
59.3k
    return character_sets::bit_at(character_set, c);
10975
59.3k
  });
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
10973
320k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10974
320k
    return character_sets::bit_at(character_set, c);
10975
320k
  });
10976
30.7k
  ada_log("percent_encode done checking, moved to ",
10977
30.7k
          std::distance(input.begin(), pointer));
10978
10979
  // Optimization: Don't iterate if percent encode is not required
10980
30.7k
  if (pointer == input.end()) {
10981
14.8k
    ada_log("percent_encode encoding not needed.");
10982
14.8k
    return false;
10983
14.8k
  }
10984
15.9k
  if constexpr (!append) {
10985
8.02k
    out.clear();
10986
8.02k
  }
10987
15.9k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10988
15.9k
          " bytes");
10989
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10990
15.9k
  out.append(input.data(), std::distance(input.begin(), pointer));
10991
15.9k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10992
15.9k
          " bytes");
10993
1.55M
  for (; pointer != input.end(); pointer++) {
10994
1.53M
    if (character_sets::bit_at(character_set, *pointer)) {
10995
1.27M
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10996
1.27M
    } else {
10997
262k
      out += *pointer;
10998
262k
    }
10999
1.53M
  }
11000
15.9k
  return true;
11001
30.7k
}
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> >&)
Line
Count
Source
10970
16.3k
                    std::string& out) {
10971
16.3k
  ada_log("percent_encode ", input, " to output string while ",
10972
16.3k
          append ? "appending" : "overwriting");
10973
16.3k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10974
16.3k
    return character_sets::bit_at(character_set, c);
10975
16.3k
  });
10976
16.3k
  ada_log("percent_encode done checking, moved to ",
10977
16.3k
          std::distance(input.begin(), pointer));
10978
10979
  // Optimization: Don't iterate if percent encode is not required
10980
16.3k
  if (pointer == input.end()) {
10981
8.33k
    ada_log("percent_encode encoding not needed.");
10982
8.33k
    return false;
10983
8.33k
  }
10984
8.02k
  if constexpr (!append) {
10985
8.02k
    out.clear();
10986
8.02k
  }
10987
8.02k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10988
8.02k
          " bytes");
10989
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10990
8.02k
  out.append(input.data(), std::distance(input.begin(), pointer));
10991
8.02k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10992
8.02k
          " bytes");
10993
621k
  for (; pointer != input.end(); pointer++) {
10994
612k
    if (character_sets::bit_at(character_set, *pointer)) {
10995
510k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10996
510k
    } else {
10997
102k
      out += *pointer;
10998
102k
    }
10999
612k
  }
11000
8.02k
  return true;
11001
16.3k
}
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
10970
14.4k
                    std::string& out) {
10971
14.4k
  ada_log("percent_encode ", input, " to output string while ",
10972
14.4k
          append ? "appending" : "overwriting");
10973
14.4k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10974
14.4k
    return character_sets::bit_at(character_set, c);
10975
14.4k
  });
10976
14.4k
  ada_log("percent_encode done checking, moved to ",
10977
14.4k
          std::distance(input.begin(), pointer));
10978
10979
  // Optimization: Don't iterate if percent encode is not required
10980
14.4k
  if (pointer == input.end()) {
10981
6.51k
    ada_log("percent_encode encoding not needed.");
10982
6.51k
    return false;
10983
6.51k
  }
10984
  if constexpr (!append) {
10985
    out.clear();
10986
  }
10987
7.89k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10988
7.89k
          " bytes");
10989
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10990
7.89k
  out.append(input.data(), std::distance(input.begin(), pointer));
10991
7.89k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10992
7.89k
          " bytes");
10993
931k
  for (; pointer != input.end(); pointer++) {
10994
923k
    if (character_sets::bit_at(character_set, *pointer)) {
10995
763k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10996
763k
    } else {
10997
159k
      out += *pointer;
10998
159k
    }
10999
923k
  }
11000
7.89k
  return true;
11001
14.4k
}
11002
11003
bool to_ascii(std::optional<std::string>& out, const std::string_view plain,
11004
12.0k
              size_t first_percent) {
11005
12.0k
  std::string percent_decoded_buffer;
11006
12.0k
  std::string_view input = plain;
11007
12.0k
  if (first_percent != std::string_view::npos) {
11008
864
    percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
11009
864
    input = percent_decoded_buffer;
11010
864
  }
11011
  // input is a non-empty UTF-8 string, must be percent decoded
11012
12.0k
  std::string idna_ascii = ada::idna::to_ascii(input);
11013
12.0k
  if (idna_ascii.empty() || contains_forbidden_domain_code_point(
11014
9.70k
                                idna_ascii.data(), idna_ascii.size())) {
11015
4.52k
    return false;
11016
4.52k
  }
11017
7.55k
  out = std::move(idna_ascii);
11018
7.55k
  return true;
11019
12.0k
}
11020
11021
std::string percent_encode(const std::string_view input,
11022
9.26k
                           const uint8_t character_set[], size_t index) {
11023
9.26k
  std::string out;
11024
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
11025
9.26k
  out.append(input.data(), index);
11026
9.26k
  auto pointer = input.begin() + index;
11027
811k
  for (; pointer != input.end(); pointer++) {
11028
802k
    if (character_sets::bit_at(character_set, *pointer)) {
11029
564k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
11030
564k
    } else {
11031
238k
      out += *pointer;
11032
238k
    }
11033
802k
  }
11034
9.26k
  return out;
11035
9.26k
}
11036
11037
}  // namespace ada::unicode
11038
/* end file src/unicode.cpp */
11039
/* begin file src/serializers.cpp */
11040
#include <array>
11041
#include <charconv>
11042
#include <string>
11043
11044
namespace ada::serializers {
11045
11046
void find_longest_sequence_of_ipv6_pieces(
11047
    const std::array<uint16_t, 8>& address, size_t& compress,
11048
219
    size_t& compress_length) noexcept {
11049
802
  for (size_t i = 0; i < 8; i++) {
11050
665
    if (address[i] == 0) {
11051
273
      size_t next = i + 1;
11052
1.23k
      while (next != 8 && address[next] == 0) ++next;
11053
273
      const size_t count = next - i;
11054
273
      if (compress_length < count) {
11055
230
        compress_length = count;
11056
230
        compress = i;
11057
230
        if (next == 8) break;
11058
148
        i = next;
11059
148
      }
11060
273
    }
11061
665
  }
11062
219
}
11063
11064
219
std::string ipv6(const std::array<uint16_t, 8>& address) {
11065
219
  size_t compress_length = 0;  // The length of a long sequence of zeros.
11066
219
  size_t compress = 0;         // The start of a long sequence of zeros.
11067
219
  find_longest_sequence_of_ipv6_pieces(address, compress, compress_length);
11068
11069
219
  if (compress_length <= 1) {
11070
    // Optimization opportunity: Find a faster way then snprintf for imploding
11071
    // and return here.
11072
21
    compress = compress_length = 8;
11073
21
  }
11074
11075
219
  std::string output(4 * 8 + 7 + 2, '\0');
11076
219
  size_t piece_index = 0;
11077
219
  char* point = output.data();
11078
219
  char* point_end = output.data() + output.size();
11079
219
  *point++ = '[';
11080
703
  while (true) {
11081
703
    if (piece_index == compress) {
11082
198
      *point++ = ':';
11083
      // If we skip a value initially, we need to write '::', otherwise
11084
      // a single ':' will do since it follows a previous ':'.
11085
198
      if (piece_index == 0) {
11086
74
        *point++ = ':';
11087
74
      }
11088
198
      piece_index += compress_length;
11089
198
      if (piece_index == 8) {
11090
82
        break;
11091
82
      }
11092
198
    }
11093
621
    point = std::to_chars(point, point_end, address[piece_index], 16).ptr;
11094
621
    piece_index++;
11095
621
    if (piece_index == 8) {
11096
137
      break;
11097
137
    }
11098
484
    *point++ = ':';
11099
484
  }
11100
219
  *point++ = ']';
11101
219
  output.resize(point - output.data());
11102
219
  return output;
11103
219
}
11104
11105
2.68k
std::string ipv4(const uint64_t address) {
11106
2.68k
  std::string output(15, '\0');
11107
2.68k
  char* point = output.data();
11108
2.68k
  char* point_end = output.data() + output.size();
11109
2.68k
  point = std::to_chars(point, point_end, uint8_t(address >> 24)).ptr;
11110
10.7k
  for (int i = 2; i >= 0; i--) {
11111
8.04k
    *point++ = '.';
11112
8.04k
    point = std::to_chars(point, point_end, uint8_t(address >> (i * 8))).ptr;
11113
8.04k
  }
11114
2.68k
  output.resize(point - output.data());
11115
2.68k
  return output;
11116
2.68k
}
11117
11118
}  // namespace ada::serializers
11119
/* end file src/serializers.cpp */
11120
/* begin file src/implementation.cpp */
11121
11122
#include <string_view>
11123
11124
11125
namespace ada {
11126
11127
template <class result_type>
11128
ada_warn_unused tl::expected<result_type, errors> parse(
11129
16.0k
    std::string_view input, const result_type* base_url) {
11130
16.0k
  result_type u =
11131
16.0k
      ada::parser::parse_url_impl<result_type, true>(input, base_url);
11132
16.0k
  if (!u.is_valid) {
11133
2.56k
    return tl::unexpected(errors::type_error);
11134
2.56k
  }
11135
13.4k
  return u;
11136
16.0k
}
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*)
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*)
Line
Count
Source
11129
16.0k
    std::string_view input, const result_type* base_url) {
11130
16.0k
  result_type u =
11131
16.0k
      ada::parser::parse_url_impl<result_type, true>(input, base_url);
11132
16.0k
  if (!u.is_valid) {
11133
2.56k
    return tl::unexpected(errors::type_error);
11134
2.56k
  }
11135
13.4k
  return u;
11136
16.0k
}
11137
11138
template ada::result<url> parse<url>(std::string_view input,
11139
                                     const url* base_url = nullptr);
11140
template ada::result<url_aggregator> parse<url_aggregator>(
11141
    std::string_view input, const url_aggregator* base_url = nullptr);
11142
11143
0
std::string href_from_file(std::string_view input) {
11144
  // This is going to be much faster than constructing a URL.
11145
0
  std::string tmp_buffer;
11146
0
  std::string_view internal_input;
11147
0
  if (unicode::has_tabs_or_newline(input)) {
11148
0
    tmp_buffer = input;
11149
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
11150
0
    internal_input = tmp_buffer;
11151
0
  } else {
11152
0
    internal_input = input;
11153
0
  }
11154
0
  std::string path;
11155
0
  if (internal_input.empty()) {
11156
0
    path = "/";
11157
0
  } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
11158
0
    helpers::parse_prepared_path(internal_input.substr(1),
11159
0
                                 ada::scheme::type::FILE, path);
11160
0
  } else {
11161
0
    helpers::parse_prepared_path(internal_input, ada::scheme::type::FILE, path);
11162
0
  }
11163
0
  return "file://" + path;
11164
0
}
11165
11166
8.59k
bool can_parse(std::string_view input, const std::string_view* base_input) {
11167
8.59k
  ada::url_aggregator base_aggregator;
11168
8.59k
  ada::url_aggregator* base_pointer = nullptr;
11169
11170
8.59k
  if (base_input != nullptr) {
11171
0
    base_aggregator = ada::parser::parse_url_impl<ada::url_aggregator, false>(
11172
0
        *base_input, nullptr);
11173
0
    if (!base_aggregator.is_valid) {
11174
0
      return false;
11175
0
    }
11176
0
    base_pointer = &base_aggregator;
11177
0
  }
11178
11179
8.59k
  ada::url_aggregator result =
11180
8.59k
      ada::parser::parse_url_impl<ada::url_aggregator, false>(input,
11181
8.59k
                                                              base_pointer);
11182
8.59k
  return result.is_valid;
11183
8.59k
}
11184
11185
0
ada_warn_unused std::string_view to_string(ada::encoding_type type) {
11186
0
  switch (type) {
11187
0
    case ada::encoding_type::UTF8:
11188
0
      return "UTF-8";
11189
0
    case ada::encoding_type::UTF_16LE:
11190
0
      return "UTF-16LE";
11191
0
    case ada::encoding_type::UTF_16BE:
11192
0
      return "UTF-16BE";
11193
0
    default:
11194
0
      unreachable();
11195
0
  }
11196
0
}
11197
11198
}  // namespace ada
11199
/* end file src/implementation.cpp */
11200
/* begin file src/helpers.cpp */
11201
#include <cstdint>
11202
#include <cstring>
11203
#include <sstream>
11204
11205
11206
#if ADA_SSSE3
11207
#include <tmmintrin.h>
11208
#endif
11209
11210
namespace ada::helpers {
11211
11212
template <typename out_iter>
11213
0
void encode_json(std::string_view view, out_iter out) {
11214
  // trivial implementation. could be faster.
11215
0
  const char* hexvalues =
11216
0
      "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
11217
0
  for (uint8_t c : view) {
11218
0
    if (c == '\\') {
11219
0
      *out++ = '\\';
11220
0
      *out++ = '\\';
11221
0
    } else if (c == '"') {
11222
0
      *out++ = '\\';
11223
0
      *out++ = '"';
11224
0
    } else if (c <= 0x1f) {
11225
0
      *out++ = '\\';
11226
0
      *out++ = 'u';
11227
0
      *out++ = '0';
11228
0
      *out++ = '0';
11229
0
      *out++ = hexvalues[2 * c];
11230
0
      *out++ = hexvalues[2 * c + 1];
11231
0
    } else {
11232
0
      *out++ = c;
11233
0
    }
11234
0
  }
11235
0
}
11236
11237
0
ada_unused std::string get_state(ada::state s) {
11238
0
  switch (s) {
11239
0
    case ada::state::AUTHORITY:
11240
0
      return "Authority";
11241
0
    case ada::state::SCHEME_START:
11242
0
      return "Scheme Start";
11243
0
    case ada::state::SCHEME:
11244
0
      return "Scheme";
11245
0
    case ada::state::HOST:
11246
0
      return "Host";
11247
0
    case ada::state::NO_SCHEME:
11248
0
      return "No Scheme";
11249
0
    case ada::state::FRAGMENT:
11250
0
      return "Fragment";
11251
0
    case ada::state::RELATIVE_SCHEME:
11252
0
      return "Relative Scheme";
11253
0
    case ada::state::RELATIVE_SLASH:
11254
0
      return "Relative Slash";
11255
0
    case ada::state::FILE:
11256
0
      return "File";
11257
0
    case ada::state::FILE_HOST:
11258
0
      return "File Host";
11259
0
    case ada::state::FILE_SLASH:
11260
0
      return "File Slash";
11261
0
    case ada::state::PATH_OR_AUTHORITY:
11262
0
      return "Path or Authority";
11263
0
    case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES:
11264
0
      return "Special Authority Ignore Slashes";
11265
0
    case ada::state::SPECIAL_AUTHORITY_SLASHES:
11266
0
      return "Special Authority Slashes";
11267
0
    case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY:
11268
0
      return "Special Relative or Authority";
11269
0
    case ada::state::QUERY:
11270
0
      return "Query";
11271
0
    case ada::state::PATH:
11272
0
      return "Path";
11273
0
    case ada::state::PATH_START:
11274
0
      return "Path Start";
11275
0
    case ada::state::OPAQUE_PATH:
11276
0
      return "Opaque Path";
11277
0
    case ada::state::PORT:
11278
0
      return "Port";
11279
0
    default:
11280
0
      return "unknown state";
11281
0
  }
11282
0
}
11283
11284
ada_really_inline std::optional<std::string_view> prune_hash(
11285
24.6k
    std::string_view& input) noexcept {
11286
  // compiles down to 20--30 instructions including a class to memchr (C
11287
  // function). this function should be quite fast.
11288
24.6k
  size_t location_of_first = input.find('#');
11289
24.6k
  if (location_of_first == std::string_view::npos) {
11290
23.5k
    return std::nullopt;
11291
23.5k
  }
11292
1.08k
  std::string_view hash = input;
11293
1.08k
  hash.remove_prefix(location_of_first + 1);
11294
1.08k
  input.remove_suffix(input.size() - location_of_first);
11295
1.08k
  return hash;
11296
24.6k
}
11297
11298
4.43k
ada_really_inline bool shorten_path(std::string& path, ada::scheme::type type) {
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
4.43k
  if (type == ada::scheme::type::FILE &&
11303
3.00k
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11304
2.02k
    if (checkers::is_normalized_windows_drive_letter(
11305
2.02k
            helpers::substring(path, 1))) {
11306
594
      return false;
11307
594
    }
11308
2.02k
  }
11309
11310
  // Remove path's last item, if any.
11311
3.84k
  size_t last_delimiter = path.rfind('/');
11312
3.84k
  if (last_delimiter != std::string::npos) {
11313
2.57k
    path.erase(last_delimiter);
11314
2.57k
    return true;
11315
2.57k
  }
11316
11317
1.27k
  return false;
11318
3.84k
}
11319
11320
ada_really_inline bool shorten_path(std::string_view& path,
11321
0
                                    ada::scheme::type type) {
11322
  // Let path be url's path.
11323
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
11324
  // Windows drive letter, then return.
11325
0
  if (type == ada::scheme::type::FILE &&
11326
0
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11327
0
    if (checkers::is_normalized_windows_drive_letter(
11328
0
            helpers::substring(path, 1))) {
11329
0
      return false;
11330
0
    }
11331
0
  }
11332
11333
  // Remove path's last item, if any.
11334
0
  if (!path.empty()) {
11335
0
    size_t slash_loc = path.rfind('/');
11336
0
    if (slash_loc != std::string_view::npos) {
11337
0
      path.remove_suffix(path.size() - slash_loc);
11338
0
      return true;
11339
0
    }
11340
0
  }
11341
11342
0
  return false;
11343
0
}
11344
11345
39.7k
ada_really_inline void remove_ascii_tab_or_newline(std::string& input) {
11346
  // if this ever becomes a performance issue, we could use an approach similar
11347
  // to has_tabs_or_newline
11348
39.7k
  std::erase_if(input, ada::unicode::is_ascii_tab_or_newline);
11349
39.7k
}
11350
11351
ada_really_inline constexpr std::string_view substring(std::string_view input,
11352
8.57k
                                                       size_t pos) {
11353
8.57k
  ADA_ASSERT_TRUE(pos <= input.size());
11354
  // The following is safer but unneeded if we have the above line:
11355
  // return pos > input.size() ? std::string_view() : input.substr(pos);
11356
8.57k
  return input.substr(pos);
11357
8.57k
}
11358
11359
0
ada_really_inline void resize(std::string_view& input, size_t pos) noexcept {
11360
0
  ADA_ASSERT_TRUE(pos <= input.size());
11361
0
  input.remove_suffix(input.size() - pos);
11362
0
}
11363
11364
// computes the number of trailing zeroes
11365
// this is a private inline function only defined in this source file.
11366
9.02k
ada_really_inline int trailing_zeroes(uint32_t input_num) noexcept {
11367
#ifdef ADA_REGULAR_VISUAL_STUDIO
11368
  unsigned long ret;
11369
  // Search the mask data from least significant bit (LSB)
11370
  // to the most significant bit (MSB) for a set bit (1).
11371
  _BitScanForward(&ret, input_num);
11372
  return (int)ret;
11373
#else   // ADA_REGULAR_VISUAL_STUDIO
11374
9.02k
  return __builtin_ctzl(input_num);
11375
9.02k
#endif  // ADA_REGULAR_VISUAL_STUDIO
11376
9.02k
}
11377
11378
// starting at index location, this finds the next location of a character
11379
// :, /, \\, ? or [. If none is found, view.size() is returned.
11380
// For use within get_host_delimiter_location.
11381
#if ADA_SSSE3
11382
ada_really_inline size_t find_next_host_delimiter_special(
11383
    std::string_view view, size_t location) noexcept {
11384
  // first check for short strings in which case we do it naively.
11385
  if (view.size() - location < 16) {  // slow path
11386
    for (size_t i = location; i < view.size(); i++) {
11387
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11388
          view[i] == '?' || view[i] == '[') {
11389
        return i;
11390
      }
11391
    }
11392
    return size_t(view.size());
11393
  }
11394
  // fast path for long strings (expected to be common)
11395
  // Using SSSE3's _mm_shuffle_epi8 for table lookup (same approach as NEON)
11396
  size_t i = location;
11397
  const __m128i low_mask =
11398
      _mm_setr_epi8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11399
                    0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
11400
  const __m128i high_mask =
11401
      _mm_setr_epi8(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
11402
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11403
  const __m128i fmask = _mm_set1_epi8(0xf);
11404
  const __m128i zero = _mm_setzero_si128();
11405
  for (; i + 15 < view.size(); i += 16) {
11406
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11407
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
11408
    __m128i highpart = _mm_shuffle_epi8(
11409
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
11410
    __m128i classify = _mm_and_si128(lowpart, highpart);
11411
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
11412
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
11413
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
11414
    // avoid false positives.
11415
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
11416
    if (mask != 0) {
11417
      return i + trailing_zeroes(static_cast<uint32_t>(mask));
11418
    }
11419
  }
11420
  if (i < view.size()) {
11421
    __m128i word =
11422
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11423
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
11424
    __m128i highpart = _mm_shuffle_epi8(
11425
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
11426
    __m128i classify = _mm_and_si128(lowpart, highpart);
11427
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
11428
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
11429
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
11430
    // avoid false positives.
11431
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
11432
    if (mask != 0) {
11433
      return view.length() - 16 + trailing_zeroes(static_cast<uint32_t>(mask));
11434
    }
11435
  }
11436
  return size_t(view.size());
11437
}
11438
#elif ADA_NEON
11439
// The ada_make_uint8x16_t macro is necessary because Visual Studio does not
11440
// support direct initialization of uint8x16_t. See
11441
// https://developercommunity.visualstudio.com/t/error-C2078:-too-many-initializers-whe/402911?q=backend+neon
11442
#ifndef ada_make_uint8x16_t
11443
#define ada_make_uint8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
11444
                            x13, x14, x15, x16)                                \
11445
  ([=]() {                                                                     \
11446
    static uint8_t array[16] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8,          \
11447
                                x9, x10, x11, x12, x13, x14, x15, x16};        \
11448
    return vld1q_u8(array);                                                    \
11449
  }())
11450
#endif
11451
11452
ada_really_inline size_t find_next_host_delimiter_special(
11453
    std::string_view view, size_t location) noexcept {
11454
  // first check for short strings in which case we do it naively.
11455
  if (view.size() - location < 16) {  // slow path
11456
    for (size_t i = location; i < view.size(); i++) {
11457
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11458
          view[i] == '?' || view[i] == '[') {
11459
        return i;
11460
      }
11461
    }
11462
    return size_t(view.size());
11463
  }
11464
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
11465
    uint8x16_t bit_mask =
11466
        ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
11467
                            0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
11468
    uint8x16_t minput = vandq_u8(input, bit_mask);
11469
    uint8x16_t tmp = vpaddq_u8(minput, minput);
11470
    tmp = vpaddq_u8(tmp, tmp);
11471
    tmp = vpaddq_u8(tmp, tmp);
11472
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
11473
  };
11474
11475
  // fast path for long strings (expected to be common)
11476
  size_t i = location;
11477
  uint8x16_t low_mask =
11478
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11479
                          0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
11480
  uint8x16_t high_mask =
11481
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
11482
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11483
  uint8x16_t fmask = vmovq_n_u8(0xf);
11484
  uint8x16_t zero{0};
11485
  for (; i + 15 < view.size(); i += 16) {
11486
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
11487
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11488
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11489
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11490
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11491
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11492
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11493
      return i + trailing_zeroes(is_non_zero);
11494
    }
11495
  }
11496
11497
  if (i < view.size()) {
11498
    uint8x16_t word =
11499
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
11500
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11501
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11502
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11503
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11504
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11505
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11506
      return view.length() - 16 + trailing_zeroes(is_non_zero);
11507
    }
11508
  }
11509
  return size_t(view.size());
11510
}
11511
#elif ADA_SSE2
11512
ada_really_inline size_t find_next_host_delimiter_special(
11513
21.3k
    std::string_view view, size_t location) noexcept {
11514
  // first check for short strings in which case we do it naively.
11515
21.3k
  if (view.size() - location < 16) {  // slow path
11516
62.9k
    for (size_t i = location; i < view.size(); i++) {
11517
55.9k
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11518
50.5k
          view[i] == '?' || view[i] == '[') {
11519
6.00k
        return i;
11520
6.00k
      }
11521
55.9k
    }
11522
7.09k
    return size_t(view.size());
11523
13.0k
  }
11524
  // fast path for long strings (expected to be common)
11525
8.23k
  size_t i = location;
11526
8.23k
  const __m128i mask1 = _mm_set1_epi8(':');
11527
8.23k
  const __m128i mask2 = _mm_set1_epi8('/');
11528
8.23k
  const __m128i mask3 = _mm_set1_epi8('\\');
11529
8.23k
  const __m128i mask4 = _mm_set1_epi8('?');
11530
8.23k
  const __m128i mask5 = _mm_set1_epi8('[');
11531
11532
42.8k
  for (; i + 15 < view.size(); i += 16) {
11533
39.7k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11534
39.7k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11535
39.7k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11536
39.7k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11537
39.7k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11538
39.7k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11539
39.7k
    __m128i m = _mm_or_si128(
11540
39.7k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11541
39.7k
    int mask = _mm_movemask_epi8(m);
11542
39.7k
    if (mask != 0) {
11543
5.09k
      return i + trailing_zeroes(mask);
11544
5.09k
    }
11545
39.7k
  }
11546
3.13k
  if (i < view.size()) {
11547
2.83k
    __m128i word =
11548
2.83k
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11549
2.83k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11550
2.83k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11551
2.83k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11552
2.83k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11553
2.83k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11554
2.83k
    __m128i m = _mm_or_si128(
11555
2.83k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11556
2.83k
    int mask = _mm_movemask_epi8(m);
11557
2.83k
    if (mask != 0) {
11558
513
      return view.length() - 16 + trailing_zeroes(mask);
11559
513
    }
11560
2.83k
  }
11561
2.62k
  return size_t(view.length());
11562
3.13k
}
11563
#elif ADA_LSX
11564
ada_really_inline size_t find_next_host_delimiter_special(
11565
    std::string_view view, size_t location) noexcept {
11566
  // first check for short strings in which case we do it naively.
11567
  if (view.size() - location < 16) {  // slow path
11568
    for (size_t i = location; i < view.size(); i++) {
11569
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11570
          view[i] == '?' || view[i] == '[') {
11571
        return i;
11572
      }
11573
    }
11574
    return size_t(view.size());
11575
  }
11576
  // fast path for long strings (expected to be common)
11577
  size_t i = location;
11578
  const __m128i mask1 = __lsx_vrepli_b(':');
11579
  const __m128i mask2 = __lsx_vrepli_b('/');
11580
  const __m128i mask3 = __lsx_vrepli_b('\\');
11581
  const __m128i mask4 = __lsx_vrepli_b('?');
11582
  const __m128i mask5 = __lsx_vrepli_b('[');
11583
11584
  for (; i + 15 < view.size(); i += 16) {
11585
    __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0);
11586
    __m128i m1 = __lsx_vseq_b(word, mask1);
11587
    __m128i m2 = __lsx_vseq_b(word, mask2);
11588
    __m128i m3 = __lsx_vseq_b(word, mask3);
11589
    __m128i m4 = __lsx_vseq_b(word, mask4);
11590
    __m128i m5 = __lsx_vseq_b(word, mask5);
11591
    __m128i m =
11592
        __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5);
11593
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11594
    if (mask != 0) {
11595
      return i + trailing_zeroes(mask);
11596
    }
11597
  }
11598
  if (i < view.size()) {
11599
    __m128i word =
11600
        __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0);
11601
    __m128i m1 = __lsx_vseq_b(word, mask1);
11602
    __m128i m2 = __lsx_vseq_b(word, mask2);
11603
    __m128i m3 = __lsx_vseq_b(word, mask3);
11604
    __m128i m4 = __lsx_vseq_b(word, mask4);
11605
    __m128i m5 = __lsx_vseq_b(word, mask5);
11606
    __m128i m =
11607
        __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5);
11608
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11609
    if (mask != 0) {
11610
      return view.length() - 16 + trailing_zeroes(mask);
11611
    }
11612
  }
11613
  return size_t(view.length());
11614
}
11615
#elif ADA_RVV
11616
ada_really_inline size_t find_next_host_delimiter_special(
11617
    std::string_view view, size_t location) noexcept {
11618
  // The LUT approach was a bit slower on the SpacemiT X60, but I could see it
11619
  // being faster on future hardware.
11620
#if 0
11621
  // LUT generated using: s=":/\\?["; list(zip([((ord(c)>>2)&0xF)for c in s],s))
11622
  static const uint8_t tbl[16] = {
11623
    0xF, 0, 0, 0, 0, 0, '[', '\\', 0, 0, 0, '/', 0, 0, ':', '?'
11624
  };
11625
  vuint8m1_t vtbl = __riscv_vle8_v_u8m1(tbl, 16);
11626
#endif
11627
  uint8_t* src = (uint8_t*)view.data() + location;
11628
  for (size_t vl, n = view.size() - location; n > 0;
11629
       n -= vl, src += vl, location += vl) {
11630
    vl = __riscv_vsetvl_e8m1(n);
11631
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
11632
#if 0
11633
    vuint8m1_t vidx = __riscv_vand(__riscv_vsrl(v, 2, vl), 0xF, vl);
11634
    vuint8m1_t vlut = __riscv_vrgather(vtbl, vidx, vl);
11635
    vbool8_t m = __riscv_vmseq(v, vlut, vl);
11636
#else
11637
    vbool8_t m1 = __riscv_vmseq(v, ':', vl);
11638
    vbool8_t m2 = __riscv_vmseq(v, '/', vl);
11639
    vbool8_t m3 = __riscv_vmseq(v, '?', vl);
11640
    vbool8_t m4 = __riscv_vmseq(v, '[', vl);
11641
    vbool8_t m5 = __riscv_vmseq(v, '\\', vl);
11642
    vbool8_t m = __riscv_vmor(
11643
        __riscv_vmor(__riscv_vmor(m1, m2, vl), __riscv_vmor(m3, m4, vl), vl),
11644
        m5, vl);
11645
#endif
11646
    long idx = __riscv_vfirst(m, vl);
11647
    if (idx >= 0) return location + idx;
11648
  }
11649
  return size_t(view.size());
11650
}
11651
#else
11652
// : / [ \\ ?
11653
static constexpr std::array<uint8_t, 256> special_host_delimiters =
11654
    []() consteval {
11655
      std::array<uint8_t, 256> result{};
11656
      for (int i : {':', '/', '[', '\\', '?'}) {
11657
        result[i] = 1;
11658
      }
11659
      return result;
11660
    }();
11661
// credit: @the-moisrex recommended a table-based approach
11662
ada_really_inline size_t find_next_host_delimiter_special(
11663
    std::string_view view, size_t location) noexcept {
11664
  auto const str = view.substr(location);
11665
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
11666
    if (special_host_delimiters[(uint8_t)*pos]) {
11667
      return pos - str.begin() + location;
11668
    }
11669
  }
11670
  return size_t(view.size());
11671
}
11672
#endif
11673
11674
// starting at index location, this finds the next location of a character
11675
// :, /, ? or [. If none is found, view.size() is returned.
11676
// For use within get_host_delimiter_location.
11677
#if ADA_SSSE3
11678
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11679
                                                  size_t location) noexcept {
11680
  // first check for short strings in which case we do it naively.
11681
  if (view.size() - location < 16) {  // slow path
11682
    for (size_t i = location; i < view.size(); i++) {
11683
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11684
          view[i] == '[') {
11685
        return i;
11686
      }
11687
    }
11688
    return size_t(view.size());
11689
  }
11690
  // fast path for long strings (expected to be common)
11691
  size_t i = location;
11692
  // Lookup tables for bit classification:
11693
  // ':' (0x3A): low[0xA]=0x01, high[0x3]=0x01 -> match
11694
  // '/' (0x2F): low[0xF]=0x02, high[0x2]=0x02 -> match
11695
  // '?' (0x3F): low[0xF]=0x01, high[0x3]=0x01 -> match
11696
  // '[' (0x5B): low[0xB]=0x04, high[0x5]=0x04 -> match
11697
  const __m128i low_mask =
11698
      _mm_setr_epi8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11699
                    0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
11700
  const __m128i high_mask =
11701
      _mm_setr_epi8(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
11702
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11703
  const __m128i fmask = _mm_set1_epi8(0xf);
11704
  const __m128i zero = _mm_setzero_si128();
11705
11706
  for (; i + 15 < view.size(); i += 16) {
11707
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11708
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
11709
    __m128i highpart = _mm_shuffle_epi8(
11710
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
11711
    __m128i classify = _mm_and_si128(lowpart, highpart);
11712
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
11713
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
11714
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
11715
    // avoid false positives.
11716
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
11717
    if (mask != 0) {
11718
      return i + trailing_zeroes(static_cast<uint32_t>(mask));
11719
    }
11720
  }
11721
11722
  if (i < view.size()) {
11723
    __m128i word =
11724
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11725
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
11726
    __m128i highpart = _mm_shuffle_epi8(
11727
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
11728
    __m128i classify = _mm_and_si128(lowpart, highpart);
11729
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
11730
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
11731
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
11732
    // avoid false positives.
11733
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
11734
    if (mask != 0) {
11735
      return view.length() - 16 + trailing_zeroes(static_cast<uint32_t>(mask));
11736
    }
11737
  }
11738
  return size_t(view.size());
11739
}
11740
#elif ADA_NEON
11741
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11742
                                                  size_t location) noexcept {
11743
  // first check for short strings in which case we do it naively.
11744
  if (view.size() - location < 16) {  // slow path
11745
    for (size_t i = location; i < view.size(); i++) {
11746
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11747
          view[i] == '[') {
11748
        return i;
11749
      }
11750
    }
11751
    return size_t(view.size());
11752
  }
11753
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
11754
    uint8x16_t bit_mask =
11755
        ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
11756
                            0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
11757
    uint8x16_t minput = vandq_u8(input, bit_mask);
11758
    uint8x16_t tmp = vpaddq_u8(minput, minput);
11759
    tmp = vpaddq_u8(tmp, tmp);
11760
    tmp = vpaddq_u8(tmp, tmp);
11761
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
11762
  };
11763
11764
  // fast path for long strings (expected to be common)
11765
  size_t i = location;
11766
  uint8x16_t low_mask =
11767
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11768
                          0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
11769
  uint8x16_t high_mask =
11770
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
11771
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11772
  uint8x16_t fmask = vmovq_n_u8(0xf);
11773
  uint8x16_t zero{0};
11774
  for (; i + 15 < view.size(); i += 16) {
11775
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
11776
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11777
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11778
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11779
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11780
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11781
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11782
      return i + trailing_zeroes(is_non_zero);
11783
    }
11784
  }
11785
11786
  if (i < view.size()) {
11787
    uint8x16_t word =
11788
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
11789
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11790
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11791
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11792
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11793
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11794
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11795
      return view.length() - 16 + trailing_zeroes(is_non_zero);
11796
    }
11797
  }
11798
  return size_t(view.size());
11799
}
11800
#elif ADA_SSE2
11801
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11802
5.79k
                                                  size_t location) noexcept {
11803
  // first check for short strings in which case we do it naively.
11804
5.79k
  if (view.size() - location < 16) {  // slow path
11805
5.38k
    for (size_t i = location; i < view.size(); i++) {
11806
5.00k
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11807
3.61k
          view[i] == '[') {
11808
1.67k
        return i;
11809
1.67k
      }
11810
5.00k
    }
11811
384
    return size_t(view.size());
11812
2.06k
  }
11813
  // fast path for long strings (expected to be common)
11814
3.73k
  size_t i = location;
11815
3.73k
  const __m128i mask1 = _mm_set1_epi8(':');
11816
3.73k
  const __m128i mask2 = _mm_set1_epi8('/');
11817
3.73k
  const __m128i mask4 = _mm_set1_epi8('?');
11818
3.73k
  const __m128i mask5 = _mm_set1_epi8('[');
11819
11820
14.8k
  for (; i + 15 < view.size(); i += 16) {
11821
14.2k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11822
14.2k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11823
14.2k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11824
14.2k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11825
14.2k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11826
14.2k
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
11827
14.2k
    int mask = _mm_movemask_epi8(m);
11828
14.2k
    if (mask != 0) {
11829
3.16k
      return i + trailing_zeroes(mask);
11830
3.16k
    }
11831
14.2k
  }
11832
568
  if (i < view.size()) {
11833
486
    __m128i word =
11834
486
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11835
486
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11836
486
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11837
486
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11838
486
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11839
486
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
11840
486
    int mask = _mm_movemask_epi8(m);
11841
486
    if (mask != 0) {
11842
251
      return view.length() - 16 + trailing_zeroes(mask);
11843
251
    }
11844
486
  }
11845
317
  return size_t(view.length());
11846
568
}
11847
#elif ADA_LSX
11848
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11849
                                                  size_t location) noexcept {
11850
  // first check for short strings in which case we do it naively.
11851
  if (view.size() - location < 16) {  // slow path
11852
    for (size_t i = location; i < view.size(); i++) {
11853
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11854
          view[i] == '[') {
11855
        return i;
11856
      }
11857
    }
11858
    return size_t(view.size());
11859
  }
11860
  // fast path for long strings (expected to be common)
11861
  size_t i = location;
11862
  const __m128i mask1 = __lsx_vrepli_b(':');
11863
  const __m128i mask2 = __lsx_vrepli_b('/');
11864
  const __m128i mask4 = __lsx_vrepli_b('?');
11865
  const __m128i mask5 = __lsx_vrepli_b('[');
11866
11867
  for (; i + 15 < view.size(); i += 16) {
11868
    __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0);
11869
    __m128i m1 = __lsx_vseq_b(word, mask1);
11870
    __m128i m2 = __lsx_vseq_b(word, mask2);
11871
    __m128i m4 = __lsx_vseq_b(word, mask4);
11872
    __m128i m5 = __lsx_vseq_b(word, mask5);
11873
    __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5));
11874
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11875
    if (mask != 0) {
11876
      return i + trailing_zeroes(mask);
11877
    }
11878
  }
11879
  if (i < view.size()) {
11880
    __m128i word =
11881
        __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0);
11882
    __m128i m1 = __lsx_vseq_b(word, mask1);
11883
    __m128i m2 = __lsx_vseq_b(word, mask2);
11884
    __m128i m4 = __lsx_vseq_b(word, mask4);
11885
    __m128i m5 = __lsx_vseq_b(word, mask5);
11886
    __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5));
11887
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11888
    if (mask != 0) {
11889
      return view.length() - 16 + trailing_zeroes(mask);
11890
    }
11891
  }
11892
  return size_t(view.length());
11893
}
11894
#elif ADA_RVV
11895
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11896
                                                  size_t location) noexcept {
11897
  uint8_t* src = (uint8_t*)view.data() + location;
11898
  for (size_t vl, n = view.size() - location; n > 0;
11899
       n -= vl, src += vl, location += vl) {
11900
    vl = __riscv_vsetvl_e8m1(n);
11901
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
11902
    vbool8_t m1 = __riscv_vmseq(v, ':', vl);
11903
    vbool8_t m2 = __riscv_vmseq(v, '/', vl);
11904
    vbool8_t m3 = __riscv_vmseq(v, '?', vl);
11905
    vbool8_t m4 = __riscv_vmseq(v, '[', vl);
11906
    vbool8_t m =
11907
        __riscv_vmor(__riscv_vmor(m1, m2, vl), __riscv_vmor(m3, m4, vl), vl);
11908
    long idx = __riscv_vfirst(m, vl);
11909
    if (idx >= 0) return location + idx;
11910
  }
11911
  return size_t(view.size());
11912
}
11913
#else
11914
// : / [ ?
11915
static constexpr std::array<uint8_t, 256> host_delimiters = []() consteval {
11916
  std::array<uint8_t, 256> result{};
11917
  for (int i : {':', '/', '?', '['}) {
11918
    result[i] = 1;
11919
  }
11920
  return result;
11921
}();
11922
// credit: @the-moisrex recommended a table-based approach
11923
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11924
                                                  size_t location) noexcept {
11925
  auto const str = view.substr(location);
11926
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
11927
    if (host_delimiters[(uint8_t)*pos]) {
11928
      return pos - str.begin() + location;
11929
    }
11930
  }
11931
  return size_t(view.size());
11932
}
11933
#endif
11934
11935
ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
11936
23.2k
    const bool is_special, std::string_view& view) noexcept {
11937
  /**
11938
   * The spec at https://url.spec.whatwg.org/#hostname-state expects us to
11939
   * compute a variable called insideBrackets but this variable is only used
11940
   * once, to check whether a ':' character was found outside brackets. Exact
11941
   * text: "Otherwise, if c is U+003A (:) and insideBrackets is false, then:".
11942
   * It is conceptually simpler and arguably more efficient to just return a
11943
   * Boolean indicating whether ':' was found outside brackets.
11944
   */
11945
23.2k
  const size_t view_size = view.size();
11946
23.2k
  size_t location = 0;
11947
23.2k
  bool found_colon = false;
11948
  /**
11949
   * Performance analysis:
11950
   *
11951
   * We are basically seeking the end of the hostname which can be indicated
11952
   * by the end of the view, or by one of the characters ':', '/', '?', '\\'
11953
   * (where '\\' is only applicable for special URLs). However, these must
11954
   * appear outside a bracket range. E.g., if you have [something?]fd: then the
11955
   * '?' does not count.
11956
   *
11957
   * So we can skip ahead to the next delimiter, as long as we include '[' in
11958
   * the set of delimiters, and that we handle it first.
11959
   *
11960
   * So the trick is to have a fast function that locates the next delimiter.
11961
   * Unless we find '[', then it only needs to be called once! Ideally, such a
11962
   * function would be provided by the C++ standard library, but it seems that
11963
   * find_first_of is not very fast, so we are forced to roll our own.
11964
   *
11965
   * We do not break into two loops for speed, but for clarity.
11966
   */
11967
23.2k
  if (is_special) {
11968
    // We move to the next delimiter.
11969
19.4k
    location = find_next_host_delimiter_special(view, location);
11970
    // Unless we find '[' then we are going only going to have to call
11971
    // find_next_host_delimiter_special once.
11972
21.3k
    for (; location < view_size;
11973
19.4k
         location = find_next_host_delimiter_special(view, location)) {
11974
11.6k
      if (view[location] == '[') {
11975
1.91k
        location = view.find(']', location);
11976
1.91k
        if (location == std::string_view::npos) {
11977
          // performance: view.find might get translated to a memchr, which
11978
          // has no notion of std::string_view::npos, so the code does not
11979
          // reflect the assembly.
11980
71
          location = view_size;
11981
71
          break;
11982
71
        }
11983
9.69k
      } else {
11984
9.69k
        found_colon = view[location] == ':';
11985
9.69k
        break;
11986
9.69k
      }
11987
11.6k
    }
11988
19.4k
  } else {
11989
    // We move to the next delimiter.
11990
3.71k
    location = find_next_host_delimiter(view, location);
11991
    // Unless we find '[' then we are going only going to have to call
11992
    // find_next_host_delimiter_special once.
11993
5.79k
    for (; location < view_size;
11994
5.09k
         location = find_next_host_delimiter(view, location)) {
11995
5.09k
      if (view[location] == '[') {
11996
2.14k
        location = view.find(']', location);
11997
2.14k
        if (location == std::string_view::npos) {
11998
          // performance: view.find might get translated to a memchr, which
11999
          // has no notion of std::string_view::npos, so the code does not
12000
          // reflect the assembly.
12001
68
          location = view_size;
12002
68
          break;
12003
68
        }
12004
2.94k
      } else {
12005
2.94k
        found_colon = view[location] == ':';
12006
2.94k
        break;
12007
2.94k
      }
12008
5.09k
    }
12009
3.71k
  }
12010
  // performance: remove_suffix may translate into a single instruction.
12011
23.2k
  view.remove_suffix(view_size - location);
12012
23.2k
  return {location, found_colon};
12013
23.2k
}
12014
12015
24.6k
void trim_c0_whitespace(std::string_view& input) noexcept {
12016
66.2k
  while (!input.empty() &&
12017
66.1k
         ada::unicode::is_c0_control_or_space(input.front())) {
12018
41.6k
    input.remove_prefix(1);
12019
41.6k
  }
12020
33.8k
  while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
12021
9.25k
    input.remove_suffix(1);
12022
9.25k
  }
12023
24.6k
}
12024
12025
ada_really_inline void parse_prepared_path(std::string_view input,
12026
                                           ada::scheme::type type,
12027
0
                                           std::string& path) {
12028
0
  ada_log("parse_prepared_path ", input);
12029
0
  uint8_t accumulator = checkers::path_signature(input);
12030
  // Let us first detect a trivial case.
12031
  // If it is special, we check that we have no dot, no %,  no \ and no
12032
  // character needing percent encoding. Otherwise, we check that we have no %,
12033
  // no dot, and no character needing percent encoding.
12034
0
  constexpr uint8_t need_encoding = 1;
12035
0
  constexpr uint8_t backslash_char = 2;
12036
0
  constexpr uint8_t dot_char = 4;
12037
0
  constexpr uint8_t percent_char = 8;
12038
0
  bool special = type != ada::scheme::NOT_SPECIAL;
12039
0
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
12040
0
                                      checkers::is_windows_drive_letter(input));
12041
0
  bool trivial_path =
12042
0
      (special ? (accumulator == 0)
12043
0
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
12044
0
                  0)) &&
12045
0
      (!may_need_slow_file_handling);
12046
0
  if (accumulator == dot_char && !may_need_slow_file_handling) {
12047
    // '4' means that we have at least one dot, but nothing that requires
12048
    // percent encoding or decoding. The only part that is not trivial is
12049
    // that we may have single dots and double dots path segments.
12050
    // If we have such segments, then we either have a path that begins
12051
    // with '.' (easy to check), or we have the sequence './'.
12052
    // Note: input cannot be empty, it must at least contain one character ('.')
12053
    // Note: we know that '\' is not present.
12054
0
    if (input[0] != '.') {
12055
0
      size_t slashdot = 0;
12056
0
      bool dot_is_file = true;
12057
0
      for (;;) {
12058
0
        slashdot = input.find("/.", slashdot);
12059
0
        if (slashdot == std::string_view::npos) {  // common case
12060
0
          break;
12061
0
        } else {  // uncommon
12062
          // only three cases matter: /./, /.. or a final /
12063
0
          slashdot += 2;
12064
0
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
12065
0
                           input[slashdot] == '/');
12066
0
        }
12067
0
      }
12068
0
      trivial_path = dot_is_file;
12069
0
    }
12070
0
  }
12071
0
  if (trivial_path) {
12072
0
    ada_log("parse_path trivial");
12073
0
    path += '/';
12074
0
    path += input;
12075
0
    return;
12076
0
  }
12077
  // We are going to need to look a bit at the path, but let us see if we can
12078
  // ignore percent encoding *and* backslashes *and* percent characters.
12079
  // Except for the trivial case, this is likely to capture 99% of paths out
12080
  // there.
12081
0
  bool fast_path =
12082
0
      (special &&
12083
0
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
12084
0
      (type != ada::scheme::type::FILE);
12085
0
  if (fast_path) {
12086
0
    ada_log("parse_prepared_path fast");
12087
    // Here we don't need to worry about \ or percent encoding.
12088
    // We also do not have a file protocol. We might have dots, however,
12089
    // but dots must as appear as '.', and they cannot be encoded because
12090
    // the symbol '%' is not present.
12091
0
    size_t previous_location = 0;  // We start at 0.
12092
0
    do {
12093
0
      size_t new_location = input.find('/', previous_location);
12094
      // std::string_view path_view = input;
12095
      //  We process the last segment separately:
12096
0
      if (new_location == std::string_view::npos) {
12097
0
        std::string_view path_view = input.substr(previous_location);
12098
0
        if (path_view == "..") {  // The path ends with ..
12099
          // e.g., if you receive ".." with an empty path, you go to "/".
12100
0
          if (path.empty()) {
12101
0
            path = '/';
12102
0
            return;
12103
0
          }
12104
          // Fast case where we have nothing to do:
12105
0
          if (path.back() == '/') {
12106
0
            return;
12107
0
          }
12108
          // If you have the path "/joe/myfriend",
12109
          // then you delete 'myfriend'.
12110
0
          path.resize(path.rfind('/') + 1);
12111
0
          return;
12112
0
        }
12113
0
        path += '/';
12114
0
        if (path_view != ".") {
12115
0
          path.append(path_view);
12116
0
        }
12117
0
        return;
12118
0
      } else {
12119
        // This is a non-final segment.
12120
0
        std::string_view path_view =
12121
0
            input.substr(previous_location, new_location - previous_location);
12122
0
        previous_location = new_location + 1;
12123
0
        if (path_view == "..") {
12124
0
          size_t last_delimiter = path.rfind('/');
12125
0
          if (last_delimiter != std::string::npos) {
12126
0
            path.erase(last_delimiter);
12127
0
          }
12128
0
        } else if (path_view != ".") {
12129
0
          path += '/';
12130
0
          path.append(path_view);
12131
0
        }
12132
0
      }
12133
0
    } while (true);
12134
0
  } else {
12135
0
    ada_log("parse_path slow");
12136
    // we have reached the general case
12137
0
    bool needs_percent_encoding = (accumulator & 1);
12138
0
    std::string path_buffer_tmp;
12139
0
    do {
12140
0
      size_t location = (special && (accumulator & 2))
12141
0
                            ? input.find_first_of("/\\")
12142
0
                            : input.find('/');
12143
0
      std::string_view path_view = input;
12144
0
      if (location != std::string_view::npos) {
12145
0
        path_view.remove_suffix(path_view.size() - location);
12146
0
        input.remove_prefix(location + 1);
12147
0
      }
12148
      // path_buffer is either path_view or it might point at a percent encoded
12149
      // temporary file.
12150
0
      std::string_view path_buffer =
12151
0
          (needs_percent_encoding &&
12152
0
           ada::unicode::percent_encode<false>(
12153
0
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
12154
0
              ? path_buffer_tmp
12155
0
              : path_view;
12156
0
      if (unicode::is_double_dot_path_segment(path_buffer)) {
12157
0
        helpers::shorten_path(path, type);
12158
0
        if (location == std::string_view::npos) {
12159
0
          path += '/';
12160
0
        }
12161
0
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
12162
0
                 (location == std::string_view::npos)) {
12163
0
        path += '/';
12164
0
      }
12165
      // Otherwise, if path_buffer is not a single-dot path segment, then:
12166
0
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
12167
        // If url's scheme is "file", url's path is empty, and path_buffer is a
12168
        // Windows drive letter, then replace the second code point in
12169
        // path_buffer with U+003A (:).
12170
0
        if (type == ada::scheme::type::FILE && path.empty() &&
12171
0
            checkers::is_windows_drive_letter(path_buffer)) {
12172
0
          path += '/';
12173
0
          path += path_buffer[0];
12174
0
          path += ':';
12175
0
          path_buffer.remove_prefix(2);
12176
0
          path.append(path_buffer);
12177
0
        } else {
12178
          // Append path_buffer to url's path.
12179
0
          path += '/';
12180
0
          path.append(path_buffer);
12181
0
        }
12182
0
      }
12183
0
      if (location == std::string_view::npos) {
12184
0
        return;
12185
0
      }
12186
0
    } while (true);
12187
0
  }
12188
0
}
12189
12190
0
bool overlaps(std::string_view input1, const std::string& input2) noexcept {
12191
0
  ada_log("helpers::overlaps check if string_view '", input1, "' [",
12192
0
          input1.size(), " bytes] is part of string '", input2, "' [",
12193
0
          input2.size(), " bytes]");
12194
0
  return !input1.empty() && !input2.empty() && input1.data() >= input2.data() &&
12195
0
         input1.data() < input2.data() + input2.size();
12196
0
}
12197
12198
template <class url_type>
12199
0
ada_really_inline void strip_trailing_spaces_from_opaque_path(url_type& url) {
12200
0
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
12201
0
  if (!url.has_opaque_path) return;
12202
0
  if (url.has_hash()) return;
12203
0
  if (url.has_search()) return;
12204
12205
0
  auto path = std::string(url.get_pathname());
12206
0
  while (!path.empty() && path.back() == ' ') {
12207
0
    path.resize(path.size() - 1);
12208
0
  }
12209
0
  url.update_base_pathname(path);
12210
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&)
12211
12212
// @ / \\ ?
12213
static constexpr std::array<uint8_t, 256> authority_delimiter_special =
12214
    []() 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
18.3k
find_authority_delimiter_special(std::string_view view) noexcept {
12224
  // performance note: we might be able to gain further performance
12225
  // with SIMD intrinsics.
12226
174k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12227
173k
    if (authority_delimiter_special[(uint8_t)*pos]) {
12228
17.4k
      return pos - view.begin();
12229
17.4k
    }
12230
173k
  }
12231
875
  return size_t(view.size());
12232
18.3k
}
12233
12234
// @ / ?
12235
static constexpr std::array<uint8_t, 256> authority_delimiter = []() consteval {
12236
  std::array<uint8_t, 256> result{};
12237
  for (uint8_t i : {'@', '/', '?'}) {
12238
    result[i] = 1;
12239
  }
12240
  return result;
12241
}();
12242
// credit: @the-moisrex recommended a table-based approach
12243
ada_really_inline size_t
12244
1.45k
find_authority_delimiter(std::string_view view) noexcept {
12245
  // performance note: we might be able to gain further performance
12246
  // with SIMD instrinsics.
12247
30.5k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12248
30.4k
    if (authority_delimiter[(uint8_t)*pos]) {
12249
1.34k
      return pos - view.begin();
12250
1.34k
    }
12251
30.4k
  }
12252
112
  return size_t(view.size());
12253
1.45k
}
12254
12255
}  // namespace ada::helpers
12256
12257
namespace ada {
12258
0
ada_warn_unused std::string to_string(ada::state state) {
12259
0
  return ada::helpers::get_state(state);
12260
0
}
12261
#undef ada_make_uint8x16_t
12262
}  // namespace ada
12263
/* end file src/helpers.cpp */
12264
/* begin file src/url.cpp */
12265
12266
#include <numeric>
12267
#include <algorithm>
12268
#include <iterator>
12269
#include <ranges>
12270
#include <string>
12271
#include <string_view>
12272
12273
namespace ada {
12274
12275
0
bool url::parse_opaque_host(std::string_view input) {
12276
0
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
12277
0
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
12278
0
    return is_valid = false;
12279
0
  }
12280
12281
  // Return the result of running UTF-8 percent-encode on input using the C0
12282
  // control percent-encode set.
12283
0
  host = ada::unicode::percent_encode(
12284
0
      input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
12285
0
  return true;
12286
0
}
12287
12288
0
bool url::parse_ipv4(std::string_view input) {
12289
0
  ada_log("parse_ipv4 ", input, " [", input.size(), " bytes]");
12290
0
  if (input.back() == '.') {
12291
0
    input.remove_suffix(1);
12292
0
  }
12293
0
  size_t digit_count{0};
12294
0
  int pure_decimal_count = 0;  // entries that are decimal
12295
0
  std::string_view original_input =
12296
0
      input;  // we might use this if pure_decimal_count == 4.
12297
0
  uint64_t ipv4{0};
12298
  // we could unroll for better performance?
12299
0
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
12300
0
    uint32_t
12301
0
        segment_result{};  // If any number exceeds 32 bits, we have an error.
12302
0
    bool is_hex = checkers::has_hex_prefix(input);
12303
0
    if (is_hex && ((input.length() == 2) ||
12304
0
                   ((input.length() > 2) && (input[2] == '.')))) {
12305
      // special case
12306
0
      segment_result = 0;
12307
0
      input.remove_prefix(2);
12308
0
    } else {
12309
0
      std::from_chars_result r{};
12310
0
      if (is_hex) {
12311
0
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
12312
0
                            segment_result, 16);
12313
0
      } else if ((input.length() >= 2) && input[0] == '0' &&
12314
0
                 checkers::is_digit(input[1])) {
12315
0
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
12316
0
                            segment_result, 8);
12317
0
      } else {
12318
0
        pure_decimal_count++;
12319
0
        r = std::from_chars(input.data(), input.data() + input.size(),
12320
0
                            segment_result, 10);
12321
0
      }
12322
0
      if (r.ec != std::errc()) {
12323
0
        return is_valid = false;
12324
0
      }
12325
0
      input.remove_prefix(r.ptr - input.data());
12326
0
    }
12327
0
    if (input.empty()) {
12328
      // We have the last value.
12329
      // At this stage, ipv4 contains digit_count*8 bits.
12330
      // So we have 32-digit_count*8 bits left.
12331
0
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
12332
0
        return is_valid = false;
12333
0
      }
12334
0
      ipv4 <<= (32 - digit_count * 8);
12335
0
      ipv4 |= segment_result;
12336
0
      goto final;
12337
0
    } else {
12338
      // There is more, so that the value must no be larger than 255
12339
      // and we must have a '.'.
12340
0
      if ((segment_result > 255) || (input[0] != '.')) {
12341
0
        return is_valid = false;
12342
0
      }
12343
0
      ipv4 <<= 8;
12344
0
      ipv4 |= segment_result;
12345
0
      input.remove_prefix(1);  // remove '.'
12346
0
    }
12347
0
  }
12348
0
  if ((digit_count != 4) || (!input.empty())) {
12349
0
    return is_valid = false;
12350
0
  }
12351
0
final:
12352
  // We could also check r.ptr to see where the parsing ended.
12353
0
  if (pure_decimal_count == 4) {
12354
0
    host = original_input;  // The original input was already all decimal and we
12355
                            // validated it.
12356
0
  } else {
12357
0
    host = ada::serializers::ipv4(ipv4);  // We have to reserialize the address.
12358
0
  }
12359
0
  host_type = IPV4;
12360
0
  return true;
12361
0
}
12362
12363
0
bool url::parse_ipv6(std::string_view input) {
12364
0
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
12365
12366
0
  if (input.empty()) {
12367
0
    return is_valid = false;
12368
0
  }
12369
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
12370
0
  std::array<uint16_t, 8> address{};
12371
12372
  // Let pieceIndex be 0.
12373
0
  int piece_index = 0;
12374
12375
  // Let compress be null.
12376
0
  std::optional<int> compress{};
12377
12378
  // Let pointer be a pointer for input.
12379
0
  std::string_view::iterator pointer = input.begin();
12380
12381
  // If c is U+003A (:), then:
12382
0
  if (input[0] == ':') {
12383
    // If remaining does not start with U+003A (:), validation error, return
12384
    // failure.
12385
0
    if (input.size() == 1 || input[1] != ':') {
12386
0
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
12387
0
      return is_valid = false;
12388
0
    }
12389
12390
    // Increase pointer by 2.
12391
0
    pointer += 2;
12392
12393
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
12394
0
    compress = ++piece_index;
12395
0
  }
12396
12397
  // While c is not the EOF code point:
12398
0
  while (pointer != input.end()) {
12399
    // If pieceIndex is 8, validation error, return failure.
12400
0
    if (piece_index == 8) {
12401
0
      ada_log("parse_ipv6 piece_index == 8");
12402
0
      return is_valid = false;
12403
0
    }
12404
12405
    // If c is U+003A (:), then:
12406
0
    if (*pointer == ':') {
12407
      // If compress is non-null, validation error, return failure.
12408
0
      if (compress.has_value()) {
12409
0
        ada_log("parse_ipv6 compress is non-null");
12410
0
        return is_valid = false;
12411
0
      }
12412
12413
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
12414
      // then continue.
12415
0
      pointer++;
12416
0
      compress = ++piece_index;
12417
0
      continue;
12418
0
    }
12419
12420
    // Let value and length be 0.
12421
0
    uint16_t value = 0, length = 0;
12422
12423
    // While length is less than 4 and c is an ASCII hex digit,
12424
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
12425
    // increase pointer and length by 1.
12426
0
    while (length < 4 && pointer != input.end() &&
12427
0
           unicode::is_ascii_hex_digit(*pointer)) {
12428
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12429
0
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
12430
0
      pointer++;
12431
0
      length++;
12432
0
    }
12433
12434
    // If c is U+002E (.), then:
12435
0
    if (pointer != input.end() && *pointer == '.') {
12436
      // If length is 0, validation error, return failure.
12437
0
      if (length == 0) {
12438
0
        ada_log("parse_ipv6 length is 0");
12439
0
        return is_valid = false;
12440
0
      }
12441
12442
      // Decrease pointer by length.
12443
0
      pointer -= length;
12444
12445
      // If pieceIndex is greater than 6, validation error, return failure.
12446
0
      if (piece_index > 6) {
12447
0
        ada_log("parse_ipv6 piece_index > 6");
12448
0
        return is_valid = false;
12449
0
      }
12450
12451
      // Let numbersSeen be 0.
12452
0
      int numbers_seen = 0;
12453
12454
      // While c is not the EOF code point:
12455
0
      while (pointer != input.end()) {
12456
        // Let ipv4Piece be null.
12457
0
        std::optional<uint16_t> ipv4_piece{};
12458
12459
        // If numbersSeen is greater than 0, then:
12460
0
        if (numbers_seen > 0) {
12461
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
12462
          // pointer by 1.
12463
0
          if (*pointer == '.' && numbers_seen < 4) {
12464
0
            pointer++;
12465
0
          }
12466
          // Otherwise, validation error, return failure.
12467
0
          else {
12468
0
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
12469
0
            return is_valid = false;
12470
0
          }
12471
0
        }
12472
12473
        // If c is not an ASCII digit, validation error, return failure.
12474
0
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
12475
0
          ada_log(
12476
0
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
12477
0
              "failure");
12478
0
          return is_valid = false;
12479
0
        }
12480
12481
        // While c is an ASCII digit:
12482
0
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
12483
          // Let number be c interpreted as decimal number.
12484
0
          int number = *pointer - '0';
12485
12486
          // If ipv4Piece is null, then set ipv4Piece to number.
12487
0
          if (!ipv4_piece.has_value()) {
12488
0
            ipv4_piece = number;
12489
0
          }
12490
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
12491
0
          else if (ipv4_piece == 0) {
12492
0
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
12493
0
            return is_valid = false;
12494
0
          }
12495
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
12496
0
          else {
12497
0
            ipv4_piece = *ipv4_piece * 10 + number;
12498
0
          }
12499
12500
          // If ipv4Piece is greater than 255, validation error, return failure.
12501
0
          if (ipv4_piece > 255) {
12502
0
            ada_log("parse_ipv6 ipv4_piece > 255");
12503
0
            return is_valid = false;
12504
0
          }
12505
12506
          // Increase pointer by 1.
12507
0
          pointer++;
12508
0
        }
12509
12510
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
12511
        // ipv4Piece.
12512
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12513
0
        address[piece_index] =
12514
0
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
12515
12516
        // Increase numbersSeen by 1.
12517
0
        numbers_seen++;
12518
12519
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
12520
0
        if (numbers_seen == 2 || numbers_seen == 4) {
12521
0
          piece_index++;
12522
0
        }
12523
0
      }
12524
12525
      // If numbersSeen is not 4, validation error, return failure.
12526
0
      if (numbers_seen != 4) {
12527
0
        return is_valid = false;
12528
0
      }
12529
12530
      // Break.
12531
0
      break;
12532
0
    }
12533
    // Otherwise, if c is U+003A (:):
12534
0
    else if ((pointer != input.end()) && (*pointer == ':')) {
12535
      // Increase pointer by 1.
12536
0
      pointer++;
12537
12538
      // If c is the EOF code point, validation error, return failure.
12539
0
      if (pointer == input.end()) {
12540
0
        ada_log(
12541
0
            "parse_ipv6 If c is the EOF code point, validation error, return "
12542
0
            "failure");
12543
0
        return is_valid = false;
12544
0
      }
12545
0
    }
12546
    // Otherwise, if c is not the EOF code point, validation error, return
12547
    // failure.
12548
0
    else if (pointer != input.end()) {
12549
0
      ada_log(
12550
0
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
12551
0
          "error, return failure");
12552
0
      return is_valid = false;
12553
0
    }
12554
12555
    // Set address[pieceIndex] to value.
12556
0
    address[piece_index] = value;
12557
12558
    // Increase pieceIndex by 1.
12559
0
    piece_index++;
12560
0
  }
12561
12562
  // If compress is non-null, then:
12563
0
  if (compress.has_value()) {
12564
    // Let swaps be pieceIndex - compress.
12565
0
    int swaps = piece_index - *compress;
12566
12567
    // Set pieceIndex to 7.
12568
0
    piece_index = 7;
12569
12570
    // While pieceIndex is not 0 and swaps is greater than 0,
12571
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
12572
    // decrease both pieceIndex and swaps by 1.
12573
0
    while (piece_index != 0 && swaps > 0) {
12574
0
      std::swap(address[piece_index], address[*compress + swaps - 1]);
12575
0
      piece_index--;
12576
0
      swaps--;
12577
0
    }
12578
0
  }
12579
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
12580
  // return failure.
12581
0
  else if (piece_index != 8) {
12582
0
    ada_log(
12583
0
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
12584
0
        "error, return failure");
12585
0
    return is_valid = false;
12586
0
  }
12587
0
  host = ada::serializers::ipv6(address);
12588
0
  ada_log("parse_ipv6 ", *host);
12589
0
  host_type = IPV6;
12590
0
  return true;
12591
0
}
12592
12593
template <bool has_state_override>
12594
0
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12595
0
  auto parsed_type = ada::scheme::get_scheme_type(input);
12596
0
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
12597
  /**
12598
   * In the common case, we will immediately recognize a special scheme (e.g.,
12599
   *http, https), in which case, we can go really fast.
12600
   **/
12601
0
  if (is_input_special) {  // fast path!!!
12602
0
    if constexpr (has_state_override) {
12603
      // If url's scheme is not a special scheme and buffer is a special scheme,
12604
      // then return.
12605
0
      if (is_special() != is_input_special) {
12606
0
        return false;
12607
0
      }
12608
12609
      // If url includes credentials or has a non-null port, and buffer is
12610
      // "file", then return.
12611
0
      if ((has_credentials() || port.has_value()) &&
12612
0
          parsed_type == ada::scheme::type::FILE) {
12613
0
        return false;
12614
0
      }
12615
12616
      // If url's scheme is "file" and its host is an empty host, then return.
12617
      // An empty host is the empty string.
12618
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
12619
0
          host.value().empty()) {
12620
0
        return false;
12621
0
      }
12622
0
    }
12623
12624
0
    type = parsed_type;
12625
12626
0
    if constexpr (has_state_override) {
12627
      // This is uncommon.
12628
0
      uint16_t urls_scheme_port = get_special_port();
12629
12630
0
      if (urls_scheme_port) {
12631
        // If url's port is url's scheme's default port, then set url's port to
12632
        // null.
12633
0
        if (port.has_value() && *port == urls_scheme_port) {
12634
0
          port = std::nullopt;
12635
0
        }
12636
0
      }
12637
0
    }
12638
0
  } else {  // slow path
12639
0
    std::string _buffer(input);
12640
    // Next function is only valid if the input is ASCII and returns false
12641
    // otherwise, but it seems that we always have ascii content so we do not
12642
    // need to check the return value.
12643
    // bool is_ascii =
12644
0
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
12645
12646
0
    if constexpr (has_state_override) {
12647
      // If url's scheme is a special scheme and buffer is not a special scheme,
12648
      // then return. If url's scheme is not a special scheme and buffer is a
12649
      // special scheme, then return.
12650
0
      if (is_special() != ada::scheme::is_special(_buffer)) {
12651
0
        return true;
12652
0
      }
12653
12654
      // If url includes credentials or has a non-null port, and buffer is
12655
      // "file", then return.
12656
0
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
12657
0
        return true;
12658
0
      }
12659
12660
      // If url's scheme is "file" and its host is an empty host, then return.
12661
      // An empty host is the empty string.
12662
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
12663
0
          host.value().empty()) {
12664
0
        return true;
12665
0
      }
12666
0
    }
12667
12668
0
    set_scheme(std::move(_buffer));
12669
12670
0
    if constexpr (has_state_override) {
12671
      // This is uncommon.
12672
0
      uint16_t urls_scheme_port = get_special_port();
12673
12674
0
      if (urls_scheme_port) {
12675
        // If url's port is url's scheme's default port, then set url's port to
12676
        // null.
12677
0
        if (port.has_value() && *port == urls_scheme_port) {
12678
0
          port = std::nullopt;
12679
0
        }
12680
0
      }
12681
0
    }
12682
0
  }
12683
12684
0
  return true;
12685
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> >)
12686
12687
0
ada_really_inline bool url::parse_host(std::string_view input) {
12688
0
  ada_log("parse_host ", input, " [", input.size(), " bytes]");
12689
0
  if (input.empty()) {
12690
0
    return is_valid = false;
12691
0
  }  // technically unnecessary.
12692
  // If input starts with U+005B ([), then:
12693
0
  if (input[0] == '[') {
12694
    // If input does not end with U+005D (]), validation error, return failure.
12695
0
    if (input.back() != ']') {
12696
0
      return is_valid = false;
12697
0
    }
12698
0
    ada_log("parse_host ipv6");
12699
12700
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
12701
    // trailing U+005D (]) removed.
12702
0
    input.remove_prefix(1);
12703
0
    input.remove_suffix(1);
12704
0
    return parse_ipv6(input);
12705
0
  }
12706
12707
  // If isNotSpecial is true, then return the result of opaque-host parsing
12708
  // input.
12709
0
  if (!is_special()) {
12710
0
    return parse_opaque_host(input);
12711
0
  }
12712
12713
  // Fast path: try to parse as pure decimal IPv4(a.b.c.d) first.
12714
0
  const uint64_t fast_result = checkers::try_parse_ipv4_fast(input);
12715
0
  if (fast_result < checkers::ipv4_fast_fail) {
12716
    // Fast path succeeded - input is pure decimal IPv4
12717
0
    if (!input.empty() && input.back() == '.') {
12718
0
      host = input.substr(0, input.size() - 1);
12719
0
    } else {
12720
0
      host = input;
12721
0
    }
12722
0
    host_type = IPV4;
12723
0
    ada_log("parse_host fast path decimal ipv4");
12724
0
    return true;
12725
0
  }
12726
  // Let domain be the result of running UTF-8 decode without BOM on the
12727
  // percent-decoding of input. Let asciiDomain be the result of running domain
12728
  // to ASCII with domain and false. The most common case is an ASCII input, in
12729
  // which case we do not need to call the expensive 'to_ascii' if a few
12730
  // conditions are met: no '%' and no 'xn-' subsequence.
12731
0
  std::string buffer = std::string(input);
12732
  // This next function checks that the result is ascii, but we are going to
12733
  // to check anyhow with is_forbidden.
12734
  // bool is_ascii =
12735
0
  unicode::to_lower_ascii(buffer.data(), buffer.size());
12736
0
  bool is_forbidden = unicode::contains_forbidden_domain_code_point(
12737
0
      buffer.data(), buffer.size());
12738
0
  if (is_forbidden == 0 && buffer.find("xn-") == std::string_view::npos) {
12739
    // fast path
12740
0
    host = std::move(buffer);
12741
12742
    // Check for other IPv4 formats (hex, octal, etc.)
12743
0
    if (checkers::is_ipv4(host.value())) {
12744
0
      ada_log("parse_host fast path ipv4");
12745
0
      return parse_ipv4(host.value());
12746
0
    }
12747
0
    ada_log("parse_host fast path ", *host);
12748
0
    return true;
12749
0
  }
12750
0
  ada_log("parse_host calling to_ascii");
12751
0
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
12752
0
  if (!is_valid) {
12753
0
    ada_log("parse_host to_ascii returns false");
12754
0
    return is_valid = false;
12755
0
  }
12756
0
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
12757
0
          " bytes]");
12758
12759
0
  if (std::any_of(host.value().begin(), host.value().end(),
12760
0
                  ada::unicode::is_forbidden_domain_code_point)) {
12761
0
    host = std::nullopt;
12762
0
    return is_valid = false;
12763
0
  }
12764
12765
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
12766
  // asciiDomain.
12767
0
  if (checkers::is_ipv4(host.value())) {
12768
0
    ada_log("parse_host got ipv4 ", *host);
12769
0
    return parse_ipv4(host.value());
12770
0
  }
12771
12772
0
  return true;
12773
0
}
12774
12775
0
ada_really_inline void url::parse_path(std::string_view input) {
12776
0
  ada_log("parse_path ", input);
12777
0
  std::string tmp_buffer;
12778
0
  std::string_view internal_input;
12779
0
  if (unicode::has_tabs_or_newline(input)) {
12780
0
    tmp_buffer = input;
12781
    // Optimization opportunity: Instead of copying and then pruning, we could
12782
    // just directly build the string from user_input.
12783
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12784
0
    internal_input = tmp_buffer;
12785
0
  } else {
12786
0
    internal_input = input;
12787
0
  }
12788
12789
  // If url is special, then:
12790
0
  if (is_special()) {
12791
0
    if (internal_input.empty()) {
12792
0
      path = "/";
12793
0
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
12794
0
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
12795
0
    } else {
12796
0
      helpers::parse_prepared_path(internal_input, type, path);
12797
0
    }
12798
0
  } else if (!internal_input.empty()) {
12799
0
    if (internal_input[0] == '/') {
12800
0
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
12801
0
    } else {
12802
0
      helpers::parse_prepared_path(internal_input, type, path);
12803
0
    }
12804
0
  } else {
12805
0
    if (!host.has_value()) {
12806
0
      path = "/";
12807
0
    }
12808
0
  }
12809
0
}
12810
12811
0
[[nodiscard]] std::string url::to_string() const {
12812
0
  if (!is_valid) {
12813
0
    return "null";
12814
0
  }
12815
0
  std::string answer;
12816
0
  auto back = std::back_insert_iterator(answer);
12817
0
  answer.append("{\n");
12818
0
  answer.append("\t\"protocol\":\"");
12819
0
  helpers::encode_json(get_protocol(), back);
12820
0
  answer.append("\",\n");
12821
0
  if (has_credentials()) {
12822
0
    answer.append("\t\"username\":\"");
12823
0
    helpers::encode_json(username, back);
12824
0
    answer.append("\",\n");
12825
0
    answer.append("\t\"password\":\"");
12826
0
    helpers::encode_json(password, back);
12827
0
    answer.append("\",\n");
12828
0
  }
12829
0
  if (host.has_value()) {
12830
0
    answer.append("\t\"host\":\"");
12831
0
    helpers::encode_json(host.value(), back);
12832
0
    answer.append("\",\n");
12833
0
  }
12834
0
  if (port.has_value()) {
12835
0
    answer.append("\t\"port\":\"");
12836
0
    answer.append(std::to_string(port.value()));
12837
0
    answer.append("\",\n");
12838
0
  }
12839
0
  answer.append("\t\"path\":\"");
12840
0
  helpers::encode_json(path, back);
12841
0
  answer.append("\",\n");
12842
0
  answer.append("\t\"opaque path\":");
12843
0
  answer.append((has_opaque_path ? "true" : "false"));
12844
0
  if (has_search()) {
12845
0
    answer.append(",\n");
12846
0
    answer.append("\t\"query\":\"");
12847
    // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
12848
0
    helpers::encode_json(query.value(), back);
12849
0
    answer.append("\"");
12850
0
  }
12851
0
  if (hash.has_value()) {
12852
0
    answer.append(",\n");
12853
0
    answer.append("\t\"hash\":\"");
12854
0
    helpers::encode_json(hash.value(), back);
12855
0
    answer.append("\"");
12856
0
  }
12857
0
  answer.append("\n}");
12858
0
  return answer;
12859
0
}
12860
12861
0
[[nodiscard]] bool url::has_valid_domain() const noexcept {
12862
0
  if (!host.has_value()) {
12863
0
    return false;
12864
0
  }
12865
0
  return checkers::verify_dns_length(host.value());
12866
0
}
12867
12868
0
[[nodiscard]] std::string url::get_origin() const {
12869
0
  if (is_special()) {
12870
    // Return a new opaque origin.
12871
0
    if (type == scheme::FILE) {
12872
0
      return "null";
12873
0
    }
12874
0
    return ada::helpers::concat(get_protocol(), "//", get_host());
12875
0
  }
12876
12877
0
  if (non_special_scheme == "blob") {
12878
0
    if (!path.empty()) {
12879
0
      auto result = ada::parse<ada::url>(path);
12880
0
      if (result &&
12881
0
          (result->type == scheme::HTTP || result->type == scheme::HTTPS)) {
12882
        // If pathURL's scheme is not "http" and not "https", then return a
12883
        // new opaque origin.
12884
0
        return ada::helpers::concat(result->get_protocol(), "//",
12885
0
                                    result->get_host());
12886
0
      }
12887
0
    }
12888
0
  }
12889
12890
  // Return a new opaque origin.
12891
0
  return "null";
12892
0
}
12893
12894
0
[[nodiscard]] std::string url::get_protocol() const {
12895
0
  if (is_special()) {
12896
0
    return helpers::concat(ada::scheme::details::is_special_list[type], ":");
12897
0
  }
12898
  // We only move the 'scheme' if it is non-special.
12899
0
  return helpers::concat(non_special_scheme, ":");
12900
0
}
12901
12902
0
[[nodiscard]] std::string url::get_host() const {
12903
  // If url's host is null, then return the empty string.
12904
  // If url's port is null, return url's host, serialized.
12905
  // Return url's host, serialized, followed by U+003A (:) and url's port,
12906
  // serialized.
12907
0
  if (!host.has_value()) {
12908
0
    return "";
12909
0
  }
12910
0
  if (port.has_value()) {
12911
0
    return host.value() + ":" + get_port();
12912
0
  }
12913
0
  return host.value();
12914
0
}
12915
12916
0
[[nodiscard]] std::string url::get_hostname() const {
12917
0
  return host.value_or("");
12918
0
}
12919
12920
0
[[nodiscard]] std::string url::get_search() const {
12921
  // If this's URL's query is either null or the empty string, then return the
12922
  // empty string. Return U+003F (?), followed by this's URL's query.
12923
0
  return (!query.has_value() || (query.value().empty())) ? ""
12924
0
                                                         : "?" + query.value();
12925
0
}
12926
12927
0
[[nodiscard]] const std::string& url::get_username() const noexcept {
12928
0
  return username;
12929
0
}
12930
12931
0
[[nodiscard]] const std::string& url::get_password() const noexcept {
12932
0
  return password;
12933
0
}
12934
12935
0
[[nodiscard]] std::string url::get_port() const {
12936
0
  return port.has_value() ? std::to_string(port.value()) : "";
12937
0
}
12938
12939
0
[[nodiscard]] std::string url::get_hash() const {
12940
  // If this's URL's fragment is either null or the empty string, then return
12941
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
12942
0
  return (!hash.has_value() || (hash.value().empty())) ? ""
12943
0
                                                       : "#" + hash.value();
12944
0
}
12945
12946
template <bool override_hostname>
12947
0
bool url::set_host_or_hostname(const std::string_view input) {
12948
0
  if (has_opaque_path) {
12949
0
    return false;
12950
0
  }
12951
12952
0
  std::optional<std::string> previous_host = host;
12953
0
  std::optional<uint16_t> previous_port = port;
12954
12955
0
  size_t host_end_pos = input.find('#');
12956
0
  std::string _host(input.data(), host_end_pos != std::string_view::npos
12957
0
                                      ? host_end_pos
12958
0
                                      : input.size());
12959
0
  helpers::remove_ascii_tab_or_newline(_host);
12960
0
  std::string_view new_host(_host);
12961
12962
  // If url's scheme is "file", then set state to file host state, instead of
12963
  // host state.
12964
0
  if (type != ada::scheme::type::FILE) {
12965
0
    std::string_view host_view(_host.data(), _host.length());
12966
0
    auto [location, found_colon] =
12967
0
        helpers::get_host_delimiter_location(is_special(), host_view);
12968
12969
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12970
    // Note: the 'found_colon' value is true if and only if a colon was
12971
    // encountered while not inside brackets.
12972
0
    if (found_colon) {
12973
      // If buffer is the empty string, host-missing validation error, return
12974
      // failure.
12975
0
      std::string_view buffer = host_view.substr(0, location);
12976
0
      if (buffer.empty()) {
12977
0
        return false;
12978
0
      }
12979
12980
      // If state override is given and state override is hostname state, then
12981
      // return failure.
12982
0
      if constexpr (override_hostname) {
12983
0
        return false;
12984
0
      }
12985
12986
      // Let host be the result of host parsing buffer with url is not special.
12987
0
      bool succeeded = parse_host(buffer);
12988
0
      if (!succeeded) {
12989
0
        host = std::move(previous_host);
12990
0
        update_base_port(previous_port);
12991
0
        return false;
12992
0
      }
12993
12994
      // Set url's host to host, buffer to the empty string, and state to port
12995
      // state.
12996
0
      std::string_view port_buffer = new_host.substr(location + 1);
12997
0
      if (!port_buffer.empty()) {
12998
0
        set_port(port_buffer);
12999
0
      }
13000
0
      return true;
13001
0
    }
13002
    // Otherwise, if one of the following is true:
13003
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13004
    // - url is special and c is U+005C (\)
13005
0
    else {
13006
      // If url is special and host_view is the empty string, host-missing
13007
      // validation error, return failure.
13008
0
      if (host_view.empty() && is_special()) {
13009
0
        return false;
13010
0
      }
13011
13012
      // Otherwise, if state override is given, host_view is the empty string,
13013
      // and either url includes credentials or url's port is non-null, then
13014
      // return failure.
13015
0
      if (host_view.empty() && (has_credentials() || port.has_value())) {
13016
0
        return false;
13017
0
      }
13018
13019
      // Let host be the result of host parsing host_view with url is not
13020
      // special.
13021
0
      if (host_view.empty() && !is_special()) {
13022
0
        host = "";
13023
0
        return true;
13024
0
      }
13025
13026
0
      bool succeeded = parse_host(host_view);
13027
0
      if (!succeeded) {
13028
0
        host = std::move(previous_host);
13029
0
        update_base_port(previous_port);
13030
0
        return false;
13031
0
      }
13032
0
      return true;
13033
0
    }
13034
0
  }
13035
13036
0
  size_t location = new_host.find_first_of("/\\?");
13037
0
  if (location != std::string_view::npos) {
13038
0
    new_host.remove_suffix(new_host.length() - location);
13039
0
  }
13040
13041
0
  if (new_host.empty()) {
13042
    // Set url's host to the empty string.
13043
0
    host = "";
13044
0
  } else {
13045
    // Let host be the result of host parsing buffer with url is not special.
13046
0
    if (!parse_host(new_host)) {
13047
0
      host = std::move(previous_host);
13048
0
      update_base_port(previous_port);
13049
0
      return false;
13050
0
    }
13051
13052
    // If host is "localhost", then set host to the empty string.
13053
0
    if (host == "localhost") {
13054
0
      host = "";
13055
0
    }
13056
0
  }
13057
0
  return true;
13058
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> >)
13059
13060
0
bool url::set_host(const std::string_view input) {
13061
0
  return set_host_or_hostname<false>(input);
13062
0
}
13063
13064
0
bool url::set_hostname(const std::string_view input) {
13065
0
  return set_host_or_hostname<true>(input);
13066
0
}
13067
13068
0
bool url::set_username(const std::string_view input) {
13069
0
  if (cannot_have_credentials_or_port()) {
13070
0
    return false;
13071
0
  }
13072
0
  username = ada::unicode::percent_encode(
13073
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
13074
0
  return true;
13075
0
}
13076
13077
0
bool url::set_password(const std::string_view input) {
13078
0
  if (cannot_have_credentials_or_port()) {
13079
0
    return false;
13080
0
  }
13081
0
  password = ada::unicode::percent_encode(
13082
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
13083
0
  return true;
13084
0
}
13085
13086
0
bool url::set_port(const std::string_view input) {
13087
0
  if (cannot_have_credentials_or_port()) {
13088
0
    return false;
13089
0
  }
13090
13091
0
  if (input.empty()) {
13092
0
    port = std::nullopt;
13093
0
    return true;
13094
0
  }
13095
13096
0
  std::string trimmed(input);
13097
0
  helpers::remove_ascii_tab_or_newline(trimmed);
13098
13099
0
  if (trimmed.empty()) {
13100
0
    return true;
13101
0
  }
13102
13103
  // Input should not start with a non-digit character.
13104
0
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
13105
0
    return false;
13106
0
  }
13107
13108
  // Find the first non-digit character to determine the length of digits
13109
0
  auto first_non_digit =
13110
0
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
13111
0
  std::string_view digits_to_parse =
13112
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
13113
13114
  // Revert changes if parse_port fails.
13115
0
  std::optional<uint16_t> previous_port = port;
13116
0
  parse_port(digits_to_parse);
13117
0
  if (is_valid) {
13118
0
    return true;
13119
0
  }
13120
0
  port = std::move(previous_port);
13121
0
  is_valid = true;
13122
0
  return false;
13123
0
}
13124
13125
0
void url::set_hash(const std::string_view input) {
13126
0
  if (input.empty()) {
13127
0
    hash = std::nullopt;
13128
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13129
0
    return;
13130
0
  }
13131
13132
0
  std::string new_value;
13133
0
  new_value = input[0] == '#' ? input.substr(1) : input;
13134
0
  helpers::remove_ascii_tab_or_newline(new_value);
13135
0
  hash = unicode::percent_encode(new_value,
13136
0
                                 ada::character_sets::FRAGMENT_PERCENT_ENCODE);
13137
0
}
13138
13139
0
void url::set_search(const std::string_view input) {
13140
0
  if (input.empty()) {
13141
0
    query = std::nullopt;
13142
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13143
0
    return;
13144
0
  }
13145
13146
0
  std::string new_value;
13147
0
  new_value = input[0] == '?' ? input.substr(1) : input;
13148
0
  helpers::remove_ascii_tab_or_newline(new_value);
13149
13150
0
  auto query_percent_encode_set =
13151
0
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13152
0
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
13153
13154
0
  query = ada::unicode::percent_encode(new_value, query_percent_encode_set);
13155
0
}
13156
13157
0
bool url::set_pathname(const std::string_view input) {
13158
0
  if (has_opaque_path) {
13159
0
    return false;
13160
0
  }
13161
0
  path.clear();
13162
0
  parse_path(input);
13163
0
  return true;
13164
0
}
13165
13166
0
bool url::set_protocol(const std::string_view input) {
13167
0
  std::string view(input);
13168
0
  helpers::remove_ascii_tab_or_newline(view);
13169
0
  if (view.empty()) {
13170
0
    return true;
13171
0
  }
13172
13173
  // Schemes should start with alpha values.
13174
0
  if (!checkers::is_alpha(view[0])) {
13175
0
    return false;
13176
0
  }
13177
13178
0
  view.append(":");
13179
13180
0
  std::string::iterator pointer =
13181
0
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
13182
13183
0
  if (pointer != view.end() && *pointer == ':') {
13184
0
    return parse_scheme<true>(
13185
0
        std::string_view(view.data(), pointer - view.begin()));
13186
0
  }
13187
0
  return false;
13188
0
}
13189
13190
0
bool url::set_href(const std::string_view input) {
13191
0
  ada::result<ada::url> out = ada::parse<ada::url>(input);
13192
13193
0
  if (out) {
13194
0
    *this = *out;
13195
0
  }
13196
13197
0
  return out.has_value();
13198
0
}
13199
13200
}  // namespace ada
13201
/* end file src/url.cpp */
13202
/* begin file src/parser.cpp */
13203
13204
#include <limits>
13205
#include <ranges>
13206
13207
13208
namespace ada::parser {
13209
13210
template <class result_type, bool store_values>
13211
result_type parse_url_impl(std::string_view user_input,
13212
24.6k
                           const result_type* base_url) {
13213
  // We can specialize the implementation per type.
13214
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
13215
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
13216
  // something else } is free (at runtime). This means that ada::url_aggregator
13217
  // and ada::url **do not have to support the exact same API**.
13218
24.6k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13219
24.6k
  constexpr bool result_type_is_ada_url_aggregator =
13220
24.6k
      std::is_same_v<url_aggregator, result_type>;
13221
24.6k
  static_assert(result_type_is_ada_url ||
13222
24.6k
                result_type_is_ada_url_aggregator);  // We don't support
13223
                                                     // anything else for now.
13224
13225
24.6k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13226
24.6k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13227
24.6k
          ")");
13228
13229
24.6k
  state state = state::SCHEME_START;
13230
24.6k
  result_type url{};
13231
13232
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
13233
  // surely the result of a bug or are otherwise a security concern.
13234
24.6k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) [[unlikely]] {
13235
0
    url.is_valid = false;
13236
0
  }
13237
  // Going forward, user_input.size() is in [0,
13238
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
13239
  // base, or the optional_url was invalid, we must return.
13240
24.6k
  if (base_url != nullptr) {
13241
0
    url.is_valid &= base_url->is_valid;
13242
0
  }
13243
24.6k
  if (!url.is_valid) {
13244
0
    return url;
13245
0
  }
13246
24.6k
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
13247
    // Most of the time, we just need user_input.size().
13248
    // In some instances, we may need a bit more.
13249
    ///////////////////////////
13250
    // This is *very* important. This line should *not* be removed
13251
    // hastily. There are principled reasons why reserve is important
13252
    // for performance. If you have a benchmark with small inputs,
13253
    // it may not matter, but in other instances, it could.
13254
    ////
13255
    // This rounds up to the next power of two.
13256
    // We know that user_input.size() is in [0,
13257
    // std::numeric_limits<uint32_t>::max).
13258
16.0k
    uint32_t reserve_capacity =
13259
16.0k
        (0xFFFFFFFF >>
13260
16.0k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13261
16.0k
        1;
13262
16.0k
    url.reserve(reserve_capacity);
13263
16.0k
  }
13264
24.6k
  std::string tmp_buffer;
13265
24.6k
  std::string_view url_data;
13266
24.6k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13267
998
    tmp_buffer = user_input;
13268
    // Optimization opportunity: Instead of copying and then pruning, we could
13269
    // just directly build the string from user_input.
13270
998
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13271
998
    url_data = tmp_buffer;
13272
23.6k
  } else [[likely]] {
13273
23.6k
    url_data = user_input;
13274
23.6k
  }
13275
13276
  // Leading and trailing control characters are uncommon and easy to deal with
13277
  // (no performance concern).
13278
24.6k
  helpers::trim_c0_whitespace(url_data);
13279
13280
  // Optimization opportunity. Most websites do not have fragment.
13281
24.6k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13282
  // We add it last so that an implementation like ada::url_aggregator
13283
  // can append it last to its internal buffer, thus improving performance.
13284
13285
  // Here url_data no longer has its fragment.
13286
  // We are going to access the data from url_data (it is immutable).
13287
  // At any given time, we are pointing at byte 'input_position' in url_data.
13288
  // The input_position variable should range from 0 to input_size.
13289
  // It is illegal to access url_data at input_size.
13290
24.6k
  size_t input_position = 0;
13291
24.6k
  const size_t input_size = url_data.size();
13292
  // Keep running the following state machine by switching on state.
13293
  // If after a run pointer points to the EOF code point, go to the next step.
13294
  // Otherwise, increase pointer by 1 and continue with the state machine.
13295
  // We never decrement input_position.
13296
135k
  while (input_position <= input_size) {
13297
126k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13298
126k
            " in state ", ada::to_string(state));
13299
126k
    switch (state) {
13300
24.6k
      case state::SCHEME_START: {
13301
24.6k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13302
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13303
        // state to scheme state.
13304
24.6k
        if ((input_position != input_size) &&
13305
24.5k
            checkers::is_alpha(url_data[input_position])) {
13306
24.4k
          state = state::SCHEME;
13307
24.4k
          input_position++;
13308
24.4k
        } else {
13309
          // Otherwise, if state override is not given, set state to no scheme
13310
          // state and decrease pointer by 1.
13311
205
          state = state::NO_SCHEME;
13312
205
        }
13313
24.6k
        break;
13314
0
      }
13315
24.4k
      case state::SCHEME: {
13316
24.4k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13317
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13318
        // append c, lowercased, to buffer.
13319
117k
        while ((input_position != input_size) &&
13320
117k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13321
93.5k
          input_position++;
13322
93.5k
        }
13323
        // Otherwise, if c is U+003A (:), then:
13324
24.4k
        if ((input_position != input_size) &&
13325
24.3k
            (url_data[input_position] == ':')) {
13326
24.3k
          ada_log("SCHEME the scheme should be ",
13327
24.3k
                  url_data.substr(0, input_position));
13328
24.3k
          if constexpr (result_type_is_ada_url) {
13329
0
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13330
0
              return url;
13331
0
            }
13332
24.3k
          } else {
13333
            // we pass the colon along instead of painfully adding it back.
13334
24.3k
            if (!url.parse_scheme_with_colon(
13335
24.3k
                    url_data.substr(0, input_position + 1))) {
13336
0
              return url;
13337
0
            }
13338
24.3k
          }
13339
24.3k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13340
13341
          // If url's scheme is "file", then:
13342
24.3k
          if (url.type == scheme::type::FILE) {
13343
            // Set state to file state.
13344
3.42k
            state = state::FILE;
13345
3.42k
          }
13346
          // Otherwise, if url is special, base is non-null, and base's scheme
13347
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13348
          // != nullptr is false.
13349
20.8k
          else if (url.is_special() && base_url != nullptr &&
13350
0
                   base_url->type == url.type) {
13351
            // Set state to special relative or authority state.
13352
0
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13353
0
          }
13354
          // Otherwise, if url is special, set state to special authority
13355
          // slashes state.
13356
20.8k
          else if (url.is_special()) {
13357
13.3k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13358
13.3k
          }
13359
          // Otherwise, if remaining starts with an U+002F (/), set state to
13360
          // path or authority state and increase pointer by 1.
13361
7.54k
          else if (input_position + 1 < input_size &&
13362
6.86k
                   url_data[input_position + 1] == '/') {
13363
3.78k
            state = state::PATH_OR_AUTHORITY;
13364
3.78k
            input_position++;
13365
3.78k
          }
13366
          // Otherwise, set url's path to the empty string and set state to
13367
          // opaque path state.
13368
3.76k
          else {
13369
3.76k
            state = state::OPAQUE_PATH;
13370
3.76k
          }
13371
24.3k
        }
13372
        // Otherwise, if state override is not given, set buffer to the empty
13373
        // string, state to no scheme state, and start over (from the first code
13374
        // point in input).
13375
88
        else {
13376
88
          state = state::NO_SCHEME;
13377
88
          input_position = 0;
13378
88
          break;
13379
88
        }
13380
24.3k
        input_position++;
13381
24.3k
        break;
13382
24.4k
      }
13383
293
      case state::NO_SCHEME: {
13384
293
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13385
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13386
        // validation error, return failure.
13387
293
        if (base_url == nullptr ||
13388
293
            (base_url->has_opaque_path && !fragment.has_value())) {
13389
293
          ada_log("NO_SCHEME validation error");
13390
293
          url.is_valid = false;
13391
293
          return url;
13392
293
        }
13393
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13394
        // set url's scheme to base's scheme, url's path to base's path, url's
13395
        // query to base's query, and set state to fragment state.
13396
0
        else if (base_url->has_opaque_path && fragment.has_value() &&
13397
0
                 input_position == input_size) {
13398
0
          ada_log("NO_SCHEME opaque base with fragment");
13399
0
          url.copy_scheme(*base_url);
13400
0
          url.has_opaque_path = base_url->has_opaque_path;
13401
13402
0
          if constexpr (result_type_is_ada_url) {
13403
0
            url.path = base_url->path;
13404
0
            url.query = base_url->query;
13405
0
          } else {
13406
0
            url.update_base_pathname(base_url->get_pathname());
13407
0
            url.update_base_search(base_url->get_search());
13408
0
          }
13409
0
          url.update_unencoded_base_hash(*fragment);
13410
0
          return url;
13411
0
        }
13412
        // Otherwise, if base's scheme is not "file", set state to relative
13413
        // state and decrease pointer by 1.
13414
0
        else if (base_url->type != scheme::type::FILE) {
13415
0
          ada_log("NO_SCHEME non-file relative path");
13416
0
          state = state::RELATIVE_SCHEME;
13417
0
        }
13418
        // Otherwise, set state to file state and decrease pointer by 1.
13419
0
        else {
13420
0
          ada_log("NO_SCHEME file base type");
13421
0
          state = state::FILE;
13422
0
        }
13423
0
        break;
13424
293
      }
13425
14.8k
      case state::AUTHORITY: {
13426
14.8k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13427
        // most URLs have no @. Having no @ tells us that we don't have to worry
13428
        // about AUTHORITY. Of course, we could have @ and still not have to
13429
        // worry about AUTHORITY.
13430
        // TODO: Instead of just collecting a bool, collect the location of the
13431
        // '@' and do something useful with it.
13432
        // TODO: We could do various processing early on, using a single pass
13433
        // over the string to collect information about it, e.g., telling us
13434
        // whether there is a @ and if so, where (or how many).
13435
13436
        // Check if url data contains an @.
13437
14.8k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13438
13.4k
          state = state::HOST;
13439
13.4k
          break;
13440
13.4k
        }
13441
1.34k
        bool at_sign_seen{false};
13442
1.34k
        bool password_token_seen{false};
13443
        /**
13444
         * We expect something of the sort...
13445
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13446
         * --------^
13447
         */
13448
19.7k
        do {
13449
19.7k
          std::string_view view = url_data.substr(input_position);
13450
          // The delimiters are @, /, ? \\.
13451
19.7k
          size_t location =
13452
19.7k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13453
19.7k
                               : helpers::find_authority_delimiter(view);
13454
19.7k
          std::string_view authority_view = view.substr(0, location);
13455
19.7k
          size_t end_of_authority = input_position + authority_view.size();
13456
          // If c is U+0040 (@), then:
13457
19.7k
          if ((end_of_authority != input_size) &&
13458
18.7k
              (url_data[end_of_authority] == '@')) {
13459
            // If atSignSeen is true, then prepend "%40" to buffer.
13460
18.4k
            if (at_sign_seen) {
13461
17.2k
              if (password_token_seen) {
13462
9.66k
                if constexpr (result_type_is_ada_url) {
13463
0
                  url.password += "%40";
13464
9.66k
                } else {
13465
9.66k
                  url.append_base_password("%40");
13466
9.66k
                }
13467
9.66k
              } else {
13468
7.54k
                if constexpr (result_type_is_ada_url) {
13469
0
                  url.username += "%40";
13470
7.54k
                } else {
13471
7.54k
                  url.append_base_username("%40");
13472
7.54k
                }
13473
7.54k
              }
13474
17.2k
            }
13475
13476
18.4k
            at_sign_seen = true;
13477
13478
18.4k
            if (!password_token_seen) {
13479
8.78k
              size_t password_token_location = authority_view.find(':');
13480
8.78k
              password_token_seen =
13481
8.78k
                  password_token_location != std::string_view::npos;
13482
13483
8.78k
              if constexpr (store_values) {
13484
5.45k
                if (!password_token_seen) {
13485
5.09k
                  if constexpr (result_type_is_ada_url) {
13486
0
                    url.username += unicode::percent_encode(
13487
0
                        authority_view,
13488
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13489
5.09k
                  } else {
13490
5.09k
                    url.append_base_username(unicode::percent_encode(
13491
5.09k
                        authority_view,
13492
5.09k
                        character_sets::USERINFO_PERCENT_ENCODE));
13493
5.09k
                  }
13494
5.09k
                } else {
13495
360
                  if constexpr (result_type_is_ada_url) {
13496
0
                    url.username += unicode::percent_encode(
13497
0
                        authority_view.substr(0, password_token_location),
13498
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13499
0
                    url.password += unicode::percent_encode(
13500
0
                        authority_view.substr(password_token_location + 1),
13501
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13502
360
                  } else {
13503
360
                    url.append_base_username(unicode::percent_encode(
13504
360
                        authority_view.substr(0, password_token_location),
13505
360
                        character_sets::USERINFO_PERCENT_ENCODE));
13506
360
                    url.append_base_password(unicode::percent_encode(
13507
360
                        authority_view.substr(password_token_location + 1),
13508
360
                        character_sets::USERINFO_PERCENT_ENCODE));
13509
360
                  }
13510
360
                }
13511
5.45k
              }
13512
8.78k
            } else if constexpr (store_values) {
13513
6.28k
              if constexpr (result_type_is_ada_url) {
13514
0
                url.password += unicode::percent_encode(
13515
0
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13516
6.28k
              } else {
13517
6.28k
                url.append_base_password(unicode::percent_encode(
13518
6.28k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13519
6.28k
              }
13520
6.28k
            }
13521
18.4k
          }
13522
          // Otherwise, if one of the following is true:
13523
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13524
          // - url is special and c is U+005C (\)
13525
1.34k
          else if (end_of_authority == input_size ||
13526
353
                   url_data[end_of_authority] == '/' ||
13527
157
                   url_data[end_of_authority] == '?' ||
13528
1.34k
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13529
            // If atSignSeen is true and authority_view is the empty string,
13530
            // validation error, return failure.
13531
1.34k
            if (at_sign_seen && authority_view.empty()) {
13532
237
              url.is_valid = false;
13533
237
              return url;
13534
237
            }
13535
1.10k
            state = state::HOST;
13536
1.10k
            break;
13537
1.34k
          }
13538
18.4k
          if (end_of_authority == input_size) {
13539
0
            if constexpr (store_values) {
13540
0
              if (fragment.has_value()) {
13541
0
                url.update_unencoded_base_hash(*fragment);
13542
0
              }
13543
0
            }
13544
0
            return url;
13545
0
          }
13546
18.4k
          input_position = end_of_authority + 1;
13547
18.4k
        } while (true);
13548
13549
1.10k
        break;
13550
1.34k
      }
13551
1.10k
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
13552
0
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
13553
0
                helpers::substring(url_data, input_position));
13554
13555
        // If c is U+002F (/) and remaining starts with U+002F (/),
13556
        // then set state to special authority ignore slashes state and increase
13557
        // pointer by 1.
13558
0
        if (url_data.substr(input_position, 2) == "//") {
13559
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13560
0
          input_position += 2;
13561
0
        } else {
13562
          // Otherwise, validation error, set state to relative state and
13563
          // decrease pointer by 1.
13564
0
          state = state::RELATIVE_SCHEME;
13565
0
        }
13566
13567
0
        break;
13568
1.34k
      }
13569
3.78k
      case state::PATH_OR_AUTHORITY: {
13570
3.78k
        ada_log("PATH_OR_AUTHORITY ",
13571
3.78k
                helpers::substring(url_data, input_position));
13572
13573
        // If c is U+002F (/), then set state to authority state.
13574
3.78k
        if ((input_position != input_size) &&
13575
3.30k
            (url_data[input_position] == '/')) {
13576
1.46k
          state = state::AUTHORITY;
13577
1.46k
          input_position++;
13578
2.31k
        } else {
13579
          // Otherwise, set state to path state, and decrease pointer by 1.
13580
2.31k
          state = state::PATH;
13581
2.31k
        }
13582
13583
3.78k
        break;
13584
1.34k
      }
13585
0
      case state::RELATIVE_SCHEME: {
13586
0
        ada_log("RELATIVE_SCHEME ",
13587
0
                helpers::substring(url_data, input_position));
13588
13589
        // Set url's scheme to base's scheme.
13590
0
        url.copy_scheme(*base_url);
13591
13592
        // If c is U+002F (/), then set state to relative slash state.
13593
0
        if ((input_position != input_size) &&
13594
            // NOLINTNEXTLINE(bugprone-branch-clone)
13595
0
            (url_data[input_position] == '/')) {
13596
0
          ada_log(
13597
0
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
13598
0
              "slash state");
13599
0
          state = state::RELATIVE_SLASH;
13600
0
        } else if (url.is_special() && (input_position != input_size) &&
13601
0
                   (url_data[input_position] == '\\')) {
13602
          // Otherwise, if url is special and c is U+005C (\), validation error,
13603
          // set state to relative slash state.
13604
0
          ada_log(
13605
0
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
13606
0
              "error, set state to relative slash state");
13607
0
          state = state::RELATIVE_SLASH;
13608
0
        } else {
13609
0
          ada_log("RELATIVE_SCHEME otherwise");
13610
          // Set url's username to base's username, url's password to base's
13611
          // password, url's host to base's host, url's port to base's port,
13612
          // url's path to a clone of base's path, and url's query to base's
13613
          // query.
13614
0
          if constexpr (result_type_is_ada_url) {
13615
0
            url.username = base_url->username;
13616
0
            url.password = base_url->password;
13617
0
            url.host = base_url->host;
13618
0
            url.port = base_url->port;
13619
            // cloning the base path includes cloning the has_opaque_path flag
13620
0
            url.has_opaque_path = base_url->has_opaque_path;
13621
0
            url.path = base_url->path;
13622
0
            url.query = base_url->query;
13623
0
          } else {
13624
0
            url.update_base_authority(base_url->get_href(),
13625
0
                                      base_url->get_components());
13626
0
            url.update_host_to_base_host(base_url->get_hostname());
13627
0
            url.update_base_port(base_url->retrieve_base_port());
13628
            // cloning the base path includes cloning the has_opaque_path flag
13629
0
            url.has_opaque_path = base_url->has_opaque_path;
13630
0
            url.update_base_pathname(base_url->get_pathname());
13631
0
            url.update_base_search(base_url->get_search());
13632
0
          }
13633
13634
0
          url.has_opaque_path = base_url->has_opaque_path;
13635
13636
          // If c is U+003F (?), then set url's query to the empty string, and
13637
          // state to query state.
13638
0
          if ((input_position != input_size) &&
13639
0
              (url_data[input_position] == '?')) {
13640
0
            state = state::QUERY;
13641
0
          }
13642
          // Otherwise, if c is not the EOF code point:
13643
0
          else if (input_position != input_size) {
13644
            // Set url's query to null.
13645
0
            url.clear_search();
13646
0
            if constexpr (result_type_is_ada_url) {
13647
              // Shorten url's path.
13648
0
              helpers::shorten_path(url.path, url.type);
13649
0
            } else {
13650
0
              std::string_view path = url.get_pathname();
13651
0
              if (helpers::shorten_path(path, url.type)) {
13652
0
                url.update_base_pathname(std::move(std::string(path)));
13653
0
              }
13654
0
            }
13655
            // Set state to path state and decrease pointer by 1.
13656
0
            state = state::PATH;
13657
0
            break;
13658
0
          }
13659
0
        }
13660
0
        input_position++;
13661
0
        break;
13662
0
      }
13663
0
      case state::RELATIVE_SLASH: {
13664
0
        ada_log("RELATIVE_SLASH ",
13665
0
                helpers::substring(url_data, input_position));
13666
13667
        // If url is special and c is U+002F (/) or U+005C (\), then:
13668
0
        if (url.is_special() && (input_position != input_size) &&
13669
0
            (url_data[input_position] == '/' ||
13670
0
             url_data[input_position] == '\\')) {
13671
          // Set state to special authority ignore slashes state.
13672
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13673
0
        }
13674
        // Otherwise, if c is U+002F (/), then set state to authority state.
13675
0
        else if ((input_position != input_size) &&
13676
0
                 (url_data[input_position] == '/')) {
13677
0
          state = state::AUTHORITY;
13678
0
        }
13679
        // Otherwise, set
13680
        // - url's username to base's username,
13681
        // - url's password to base's password,
13682
        // - url's host to base's host,
13683
        // - url's port to base's port,
13684
        // - state to path state, and then, decrease pointer by 1.
13685
0
        else {
13686
0
          if constexpr (result_type_is_ada_url) {
13687
0
            url.username = base_url->username;
13688
0
            url.password = base_url->password;
13689
0
            url.host = base_url->host;
13690
0
            url.port = base_url->port;
13691
0
          } else {
13692
0
            url.update_base_authority(base_url->get_href(),
13693
0
                                      base_url->get_components());
13694
0
            url.update_host_to_base_host(base_url->get_hostname());
13695
0
            url.update_base_port(base_url->retrieve_base_port());
13696
0
          }
13697
0
          state = state::PATH;
13698
0
          break;
13699
0
        }
13700
13701
0
        input_position++;
13702
0
        break;
13703
0
      }
13704
13.3k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13705
13.3k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13706
13.3k
                helpers::substring(url_data, input_position));
13707
13708
        // If c is U+002F (/) and remaining starts with U+002F (/),
13709
        // then set state to special authority ignore slashes state and increase
13710
        // pointer by 1.
13711
13.3k
        if (url_data.substr(input_position, 2) == "//") {
13712
49
          input_position += 2;
13713
49
        }
13714
13715
13.3k
        [[fallthrough]];
13716
13.3k
      }
13717
13.3k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13718
13.3k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13719
13.3k
                helpers::substring(url_data, input_position));
13720
13721
        // If c is neither U+002F (/) nor U+005C (\), then set state to
13722
        // authority state and decrease pointer by 1.
13723
15.5k
        while ((input_position != input_size) &&
13724
15.4k
               ((url_data[input_position] == '/') ||
13725
14.4k
                (url_data[input_position] == '\\'))) {
13726
2.17k
          input_position++;
13727
2.17k
        }
13728
13.3k
        state = state::AUTHORITY;
13729
13730
13.3k
        break;
13731
13.3k
      }
13732
1.40k
      case state::QUERY: {
13733
1.40k
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13734
1.40k
        if constexpr (store_values) {
13735
          // Let queryPercentEncodeSet be the special-query percent-encode set
13736
          // if url is special; otherwise the query percent-encode set.
13737
936
          const uint8_t* query_percent_encode_set =
13738
936
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13739
936
                               : character_sets::QUERY_PERCENT_ENCODE;
13740
13741
          // Percent-encode after encoding, with encoding, buffer, and
13742
          // queryPercentEncodeSet, and append the result to url's query.
13743
936
          url.update_base_search(url_data.substr(input_position),
13744
936
                                 query_percent_encode_set);
13745
936
          ada_log("QUERY update_base_search completed ");
13746
936
          if (fragment.has_value()) {
13747
180
            url.update_unencoded_base_hash(*fragment);
13748
180
          }
13749
936
        }
13750
1.40k
        return url;
13751
13.3k
      }
13752
14.5k
      case state::HOST: {
13753
14.5k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13754
13755
14.5k
        std::string_view host_view = url_data.substr(input_position);
13756
14.5k
        auto [location, found_colon] =
13757
14.5k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13758
14.5k
        input_position = (location != std::string_view::npos)
13759
14.5k
                             ? input_position + location
13760
14.5k
                             : input_size;
13761
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13762
        // Note: the 'found_colon' value is true if and only if a colon was
13763
        // encountered while not inside brackets.
13764
14.5k
        if (found_colon) {
13765
          // If buffer is the empty string, validation error, return failure.
13766
          // Let host be the result of host parsing buffer with url is not
13767
          // special.
13768
2.12k
          ada_log("HOST parsing ", host_view);
13769
2.12k
          if (!url.parse_host(host_view)) {
13770
318
            return url;
13771
318
          }
13772
1.80k
          ada_log("HOST parsing results in ", url.get_hostname());
13773
          // Set url's host to host, buffer to the empty string, and state to
13774
          // port state.
13775
1.80k
          state = state::PORT;
13776
1.80k
          input_position++;
13777
1.80k
        }
13778
        // Otherwise, if one of the following is true:
13779
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13780
        // - url is special and c is U+005C (\)
13781
        // The get_host_delimiter_location function either brings us to
13782
        // the colon outside of the bracket, or to one of those characters.
13783
12.4k
        else {
13784
          // If url is special and host_view is the empty string, validation
13785
          // error, return failure.
13786
12.4k
          if (host_view.empty() && url.is_special()) {
13787
48
            url.is_valid = false;
13788
48
            return url;
13789
48
          }
13790
12.4k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
13791
          // Let host be the result of host parsing host_view with url is not
13792
          // special.
13793
12.4k
          if (host_view.empty()) {
13794
143
            url.update_base_hostname("");
13795
12.2k
          } else if (!url.parse_host(host_view)) {
13796
3.06k
            return url;
13797
3.06k
          }
13798
9.34k
          ada_log("HOST parsing results in ", url.get_hostname(),
13799
9.34k
                  " href=", url.get_href());
13800
13801
          // Set url's host to host, and state to path start state.
13802
9.34k
          state = state::PATH_START;
13803
9.34k
        }
13804
13805
11.1k
        break;
13806
14.5k
      }
13807
11.1k
      case state::OPAQUE_PATH: {
13808
3.76k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13809
3.76k
        std::string_view view = url_data.substr(input_position);
13810
        // If c is U+003F (?), then set url's query to the empty string and
13811
        // state to query state.
13812
3.76k
        size_t location = view.find('?');
13813
3.76k
        if (location != std::string_view::npos) {
13814
225
          view.remove_suffix(view.size() - location);
13815
225
          state = state::QUERY;
13816
225
          input_position += location + 1;
13817
3.53k
        } else {
13818
3.53k
          input_position = input_size + 1;
13819
3.53k
        }
13820
3.76k
        url.has_opaque_path = true;
13821
13822
        // This is a really unlikely scenario in real world. We should not seek
13823
        // to optimize it.
13824
3.76k
        if (view.ends_with(' ')) {
13825
180
          std::string modified_view =
13826
180
              std::string(view.substr(0, view.size() - 1)) + "%20";
13827
180
          url.update_base_pathname(unicode::percent_encode(
13828
180
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13829
3.58k
        } else {
13830
3.58k
          url.update_base_pathname(unicode::percent_encode(
13831
3.58k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13832
3.58k
        }
13833
3.76k
        break;
13834
14.5k
      }
13835
1.80k
      case state::PORT: {
13836
1.80k
        ada_log("PORT ", helpers::substring(url_data, input_position));
13837
1.80k
        std::string_view port_view = url_data.substr(input_position);
13838
1.80k
        input_position += url.parse_port(port_view, true);
13839
1.80k
        if (!url.is_valid) {
13840
278
          return url;
13841
278
        }
13842
1.52k
        state = state::PATH_START;
13843
1.52k
        [[fallthrough]];
13844
1.52k
      }
13845
11.9k
      case state::PATH_START: {
13846
11.9k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13847
13848
        // If url is special, then:
13849
11.9k
        if (url.is_special()) {
13850
          // Set state to path state.
13851
10.7k
          state = state::PATH;
13852
13853
          // Optimization: Avoiding going into PATH state improves the
13854
          // performance of urls ending with /.
13855
10.7k
          if (input_position == input_size) {
13856
8.88k
            if constexpr (store_values) {
13857
5.99k
              url.update_base_pathname("/");
13858
5.99k
              if (fragment.has_value()) {
13859
124
                url.update_unencoded_base_hash(*fragment);
13860
124
              }
13861
5.99k
            }
13862
8.88k
            return url;
13863
8.88k
          }
13864
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
13865
          // by 1. We know that (input_position == input_size) is impossible
13866
          // here, because of the previous if-check.
13867
1.90k
          if ((url_data[input_position] != '/') &&
13868
501
              (url_data[input_position] != '\\')) {
13869
330
            break;
13870
330
          }
13871
1.90k
        }
13872
        // Otherwise, if state override is not given and c is U+003F (?),
13873
        // set url's query to the empty string and state to query state.
13874
1.16k
        else if ((input_position != input_size) &&
13875
479
                 (url_data[input_position] == '?')) {
13876
183
          state = state::QUERY;
13877
183
        }
13878
        // Otherwise, if c is not the EOF code point:
13879
980
        else if (input_position != input_size) {
13880
          // Set state to path state.
13881
296
          state = state::PATH;
13882
13883
          // If c is not U+002F (/), then decrease pointer by 1.
13884
296
          if (url_data[input_position] != '/') {
13885
0
            break;
13886
0
          }
13887
296
        }
13888
13889
2.73k
        input_position++;
13890
2.73k
        break;
13891
11.9k
      }
13892
6.49k
      case state::PATH: {
13893
6.49k
        ada_log("PATH ", helpers::substring(url_data, input_position));
13894
6.49k
        std::string_view view = url_data.substr(input_position);
13895
13896
        // Most time, we do not need percent encoding.
13897
        // Furthermore, we can immediately locate the '?'.
13898
6.49k
        size_t locofquestionmark = view.find('?');
13899
6.49k
        if (locofquestionmark != std::string_view::npos) {
13900
996
          state = state::QUERY;
13901
996
          view.remove_suffix(view.size() - locofquestionmark);
13902
996
          input_position += locofquestionmark + 1;
13903
5.49k
        } else {
13904
5.49k
          input_position = input_size + 1;
13905
5.49k
        }
13906
6.49k
        if constexpr (store_values) {
13907
4.35k
          if constexpr (result_type_is_ada_url) {
13908
0
            helpers::parse_prepared_path(view, url.type, url.path);
13909
4.35k
          } else {
13910
4.35k
            url.consume_prepared_path(view);
13911
4.35k
            ADA_ASSERT_TRUE(url.validate());
13912
4.35k
          }
13913
4.35k
        }
13914
6.49k
        break;
13915
11.9k
      }
13916
1.60k
      case state::FILE_SLASH: {
13917
1.60k
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13918
13919
        // If c is U+002F (/) or U+005C (\), then:
13920
1.60k
        if ((input_position != input_size) &&
13921
1.59k
            (url_data[input_position] == '/' ||
13922
1.45k
             url_data[input_position] == '\\')) {
13923
1.45k
          ada_log("FILE_SLASH c is U+002F or U+005C");
13924
          // Set state to file host state.
13925
1.45k
          state = state::FILE_HOST;
13926
1.45k
          input_position++;
13927
1.45k
        } else {
13928
148
          ada_log("FILE_SLASH otherwise");
13929
          // If base is non-null and base's scheme is "file", then:
13930
          // Note: it is unsafe to do base_url->scheme unless you know that
13931
          // base_url_has_value() is true.
13932
148
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13933
            // Set url's host to base's host.
13934
0
            if constexpr (result_type_is_ada_url) {
13935
0
              url.host = base_url->host;
13936
0
            } else {
13937
0
              url.update_host_to_base_host(base_url->get_host());
13938
0
            }
13939
            // If the code point substring from pointer to the end of input does
13940
            // not start with a Windows drive letter and base's path[0] is a
13941
            // normalized Windows drive letter, then append base's path[0] to
13942
            // url's path.
13943
0
            if (!base_url->get_pathname().empty()) {
13944
0
              if (!checkers::is_windows_drive_letter(
13945
0
                      url_data.substr(input_position))) {
13946
0
                std::string_view first_base_url_path =
13947
0
                    base_url->get_pathname().substr(1);
13948
0
                size_t loc = first_base_url_path.find('/');
13949
0
                if (loc != std::string_view::npos) {
13950
0
                  helpers::resize(first_base_url_path, loc);
13951
0
                }
13952
0
                if (checkers::is_normalized_windows_drive_letter(
13953
0
                        first_base_url_path)) {
13954
0
                  if constexpr (result_type_is_ada_url) {
13955
0
                    url.path += '/';
13956
0
                    url.path += first_base_url_path;
13957
0
                  } else {
13958
0
                    url.append_base_pathname(
13959
0
                        helpers::concat("/", first_base_url_path));
13960
0
                  }
13961
0
                }
13962
0
              }
13963
0
            }
13964
0
          }
13965
13966
          // Set state to path state, and decrease pointer by 1.
13967
148
          state = state::PATH;
13968
148
        }
13969
13970
1.60k
        break;
13971
11.9k
      }
13972
1.45k
      case state::FILE_HOST: {
13973
1.45k
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13974
1.45k
        std::string_view view = url_data.substr(input_position);
13975
13976
1.45k
        size_t location = view.find_first_of("/\\?");
13977
1.45k
        std::string_view file_host_buffer(
13978
1.45k
            view.data(),
13979
1.45k
            (location != std::string_view::npos) ? location : view.size());
13980
13981
1.45k
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13982
7
          state = state::PATH;
13983
1.44k
        } else if (file_host_buffer.empty()) {
13984
          // Set url's host to the empty string.
13985
23
          if constexpr (result_type_is_ada_url) {
13986
0
            url.host = "";
13987
23
          } else {
13988
23
            url.update_base_hostname("");
13989
23
          }
13990
          // Set state to path start state.
13991
23
          state = state::PATH_START;
13992
1.42k
        } else {
13993
1.42k
          size_t consumed_bytes = file_host_buffer.size();
13994
1.42k
          input_position += consumed_bytes;
13995
          // Let host be the result of host parsing buffer with url is not
13996
          // special.
13997
1.42k
          if (!url.parse_host(file_host_buffer)) {
13998
362
            return url;
13999
362
          }
14000
14001
1.06k
          if constexpr (result_type_is_ada_url) {
14002
            // If host is "localhost", then set host to the empty string.
14003
0
            if (url.host.has_value() && url.host.value() == "localhost") {
14004
0
              url.host = "";
14005
0
            }
14006
1.06k
          } else {
14007
1.06k
            if (url.get_hostname() == "localhost") {
14008
10
              url.update_base_hostname("");
14009
10
            }
14010
1.06k
          }
14011
14012
          // Set buffer to the empty string and state to path start state.
14013
1.06k
          state = state::PATH_START;
14014
1.06k
        }
14015
14016
1.09k
        break;
14017
1.45k
      }
14018
3.42k
      case state::FILE: {
14019
3.42k
        ada_log("FILE ", helpers::substring(url_data, input_position));
14020
3.42k
        std::string_view file_view = url_data.substr(input_position);
14021
14022
3.42k
        url.set_protocol_as_file();
14023
3.42k
        if constexpr (result_type_is_ada_url) {
14024
          // Set url's host to the empty string.
14025
0
          url.host = "";
14026
3.42k
        } else {
14027
3.42k
          url.update_base_hostname("");
14028
3.42k
        }
14029
        // If c is U+002F (/) or U+005C (\), then:
14030
3.42k
        if (input_position != input_size &&
14031
3.37k
            (url_data[input_position] == '/' ||
14032
1.86k
             url_data[input_position] == '\\')) {
14033
1.60k
          ada_log("FILE c is U+002F or U+005C");
14034
          // Set state to file slash state.
14035
1.60k
          state = state::FILE_SLASH;
14036
1.60k
        }
14037
        // Otherwise, if base is non-null and base's scheme is "file":
14038
1.82k
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
14039
          // Set url's host to base's host, url's path to a clone of base's
14040
          // path, and url's query to base's query.
14041
0
          ada_log("FILE base non-null");
14042
0
          if constexpr (result_type_is_ada_url) {
14043
0
            url.host = base_url->host;
14044
0
            url.path = base_url->path;
14045
0
            url.query = base_url->query;
14046
0
          } else {
14047
0
            url.update_host_to_base_host(base_url->get_hostname());
14048
0
            url.update_base_pathname(base_url->get_pathname());
14049
0
            url.update_base_search(base_url->get_search());
14050
0
          }
14051
0
          url.has_opaque_path = base_url->has_opaque_path;
14052
14053
          // If c is U+003F (?), then set url's query to the empty string and
14054
          // state to query state.
14055
0
          if (input_position != input_size && url_data[input_position] == '?') {
14056
0
            state = state::QUERY;
14057
0
          }
14058
          // Otherwise, if c is not the EOF code point:
14059
0
          else if (input_position != input_size) {
14060
            // Set url's query to null.
14061
0
            url.clear_search();
14062
            // If the code point substring from pointer to the end of input does
14063
            // not start with a Windows drive letter, then shorten url's path.
14064
0
            if (!checkers::is_windows_drive_letter(file_view)) {
14065
0
              if constexpr (result_type_is_ada_url) {
14066
0
                helpers::shorten_path(url.path, url.type);
14067
0
              } else {
14068
0
                std::string_view path = url.get_pathname();
14069
0
                if (helpers::shorten_path(path, url.type)) {
14070
0
                  url.update_base_pathname(std::move(std::string(path)));
14071
0
                }
14072
0
              }
14073
0
            }
14074
            // Otherwise:
14075
0
            else {
14076
              // Set url's path to an empty list.
14077
0
              url.clear_pathname();
14078
0
              url.has_opaque_path = true;
14079
0
            }
14080
14081
            // Set state to path state and decrease pointer by 1.
14082
0
            state = state::PATH;
14083
0
            break;
14084
0
          }
14085
0
        }
14086
        // Otherwise, set state to path state, and decrease pointer by 1.
14087
1.82k
        else {
14088
1.82k
          ada_log("FILE go to path");
14089
1.82k
          state = state::PATH;
14090
1.82k
          break;
14091
1.82k
        }
14092
14093
1.60k
        input_position++;
14094
1.60k
        break;
14095
3.42k
      }
14096
0
      default:
14097
0
        unreachable();
14098
126k
    }
14099
126k
  }
14100
9.71k
  if constexpr (store_values) {
14101
6.52k
    if (fragment.has_value()) {
14102
416
      url.update_unencoded_base_hash(*fragment);
14103
416
    }
14104
6.52k
  }
14105
9.71k
  return url;
14106
24.6k
}
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*)
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*)
Line
Count
Source
13212
16.0k
                           const result_type* base_url) {
13213
  // We can specialize the implementation per type.
13214
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
13215
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
13216
  // something else } is free (at runtime). This means that ada::url_aggregator
13217
  // and ada::url **do not have to support the exact same API**.
13218
16.0k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13219
16.0k
  constexpr bool result_type_is_ada_url_aggregator =
13220
16.0k
      std::is_same_v<url_aggregator, result_type>;
13221
16.0k
  static_assert(result_type_is_ada_url ||
13222
16.0k
                result_type_is_ada_url_aggregator);  // We don't support
13223
                                                     // anything else for now.
13224
13225
16.0k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13226
16.0k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13227
16.0k
          ")");
13228
13229
16.0k
  state state = state::SCHEME_START;
13230
16.0k
  result_type url{};
13231
13232
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
13233
  // surely the result of a bug or are otherwise a security concern.
13234
16.0k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) [[unlikely]] {
13235
0
    url.is_valid = false;
13236
0
  }
13237
  // Going forward, user_input.size() is in [0,
13238
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
13239
  // base, or the optional_url was invalid, we must return.
13240
16.0k
  if (base_url != nullptr) {
13241
0
    url.is_valid &= base_url->is_valid;
13242
0
  }
13243
16.0k
  if (!url.is_valid) {
13244
0
    return url;
13245
0
  }
13246
16.0k
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
13247
    // Most of the time, we just need user_input.size().
13248
    // In some instances, we may need a bit more.
13249
    ///////////////////////////
13250
    // This is *very* important. This line should *not* be removed
13251
    // hastily. There are principled reasons why reserve is important
13252
    // for performance. If you have a benchmark with small inputs,
13253
    // it may not matter, but in other instances, it could.
13254
    ////
13255
    // This rounds up to the next power of two.
13256
    // We know that user_input.size() is in [0,
13257
    // std::numeric_limits<uint32_t>::max).
13258
16.0k
    uint32_t reserve_capacity =
13259
16.0k
        (0xFFFFFFFF >>
13260
16.0k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13261
16.0k
        1;
13262
16.0k
    url.reserve(reserve_capacity);
13263
16.0k
  }
13264
16.0k
  std::string tmp_buffer;
13265
16.0k
  std::string_view url_data;
13266
16.0k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13267
649
    tmp_buffer = user_input;
13268
    // Optimization opportunity: Instead of copying and then pruning, we could
13269
    // just directly build the string from user_input.
13270
649
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13271
649
    url_data = tmp_buffer;
13272
15.3k
  } else [[likely]] {
13273
15.3k
    url_data = user_input;
13274
15.3k
  }
13275
13276
  // Leading and trailing control characters are uncommon and easy to deal with
13277
  // (no performance concern).
13278
16.0k
  helpers::trim_c0_whitespace(url_data);
13279
13280
  // Optimization opportunity. Most websites do not have fragment.
13281
16.0k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13282
  // We add it last so that an implementation like ada::url_aggregator
13283
  // can append it last to its internal buffer, thus improving performance.
13284
13285
  // Here url_data no longer has its fragment.
13286
  // We are going to access the data from url_data (it is immutable).
13287
  // At any given time, we are pointing at byte 'input_position' in url_data.
13288
  // The input_position variable should range from 0 to input_size.
13289
  // It is illegal to access url_data at input_size.
13290
16.0k
  size_t input_position = 0;
13291
16.0k
  const size_t input_size = url_data.size();
13292
  // Keep running the following state machine by switching on state.
13293
  // If after a run pointer points to the EOF code point, go to the next step.
13294
  // Otherwise, increase pointer by 1 and continue with the state machine.
13295
  // We never decrement input_position.
13296
88.7k
  while (input_position <= input_size) {
13297
82.2k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13298
82.2k
            " in state ", ada::to_string(state));
13299
82.2k
    switch (state) {
13300
16.0k
      case state::SCHEME_START: {
13301
16.0k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13302
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13303
        // state to scheme state.
13304
16.0k
        if ((input_position != input_size) &&
13305
15.9k
            checkers::is_alpha(url_data[input_position])) {
13306
15.8k
          state = state::SCHEME;
13307
15.8k
          input_position++;
13308
15.8k
        } else {
13309
          // Otherwise, if state override is not given, set state to no scheme
13310
          // state and decrease pointer by 1.
13311
127
          state = state::NO_SCHEME;
13312
127
        }
13313
16.0k
        break;
13314
0
      }
13315
15.8k
      case state::SCHEME: {
13316
15.8k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13317
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13318
        // append c, lowercased, to buffer.
13319
77.7k
        while ((input_position != input_size) &&
13320
77.7k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13321
61.8k
          input_position++;
13322
61.8k
        }
13323
        // Otherwise, if c is U+003A (:), then:
13324
15.8k
        if ((input_position != input_size) &&
13325
15.8k
            (url_data[input_position] == ':')) {
13326
15.8k
          ada_log("SCHEME the scheme should be ",
13327
15.8k
                  url_data.substr(0, input_position));
13328
          if constexpr (result_type_is_ada_url) {
13329
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13330
              return url;
13331
            }
13332
15.8k
          } else {
13333
            // we pass the colon along instead of painfully adding it back.
13334
15.8k
            if (!url.parse_scheme_with_colon(
13335
15.8k
                    url_data.substr(0, input_position + 1))) {
13336
0
              return url;
13337
0
            }
13338
15.8k
          }
13339
15.8k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13340
13341
          // If url's scheme is "file", then:
13342
15.8k
          if (url.type == scheme::type::FILE) {
13343
            // Set state to file state.
13344
2.25k
            state = state::FILE;
13345
2.25k
          }
13346
          // Otherwise, if url is special, base is non-null, and base's scheme
13347
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13348
          // != nullptr is false.
13349
13.5k
          else if (url.is_special() && base_url != nullptr &&
13350
0
                   base_url->type == url.type) {
13351
            // Set state to special relative or authority state.
13352
0
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13353
0
          }
13354
          // Otherwise, if url is special, set state to special authority
13355
          // slashes state.
13356
13.5k
          else if (url.is_special()) {
13357
8.55k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13358
8.55k
          }
13359
          // Otherwise, if remaining starts with an U+002F (/), set state to
13360
          // path or authority state and increase pointer by 1.
13361
5.04k
          else if (input_position + 1 < input_size &&
13362
4.58k
                   url_data[input_position + 1] == '/') {
13363
2.51k
            state = state::PATH_OR_AUTHORITY;
13364
2.51k
            input_position++;
13365
2.51k
          }
13366
          // Otherwise, set url's path to the empty string and set state to
13367
          // opaque path state.
13368
2.52k
          else {
13369
2.52k
            state = state::OPAQUE_PATH;
13370
2.52k
          }
13371
15.8k
        }
13372
        // Otherwise, if state override is not given, set buffer to the empty
13373
        // string, state to no scheme state, and start over (from the first code
13374
        // point in input).
13375
47
        else {
13376
47
          state = state::NO_SCHEME;
13377
47
          input_position = 0;
13378
47
          break;
13379
47
        }
13380
15.8k
        input_position++;
13381
15.8k
        break;
13382
15.8k
      }
13383
174
      case state::NO_SCHEME: {
13384
174
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13385
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13386
        // validation error, return failure.
13387
174
        if (base_url == nullptr ||
13388
174
            (base_url->has_opaque_path && !fragment.has_value())) {
13389
174
          ada_log("NO_SCHEME validation error");
13390
174
          url.is_valid = false;
13391
174
          return url;
13392
174
        }
13393
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13394
        // set url's scheme to base's scheme, url's path to base's path, url's
13395
        // query to base's query, and set state to fragment state.
13396
0
        else if (base_url->has_opaque_path && fragment.has_value() &&
13397
0
                 input_position == input_size) {
13398
0
          ada_log("NO_SCHEME opaque base with fragment");
13399
0
          url.copy_scheme(*base_url);
13400
0
          url.has_opaque_path = base_url->has_opaque_path;
13401
13402
          if constexpr (result_type_is_ada_url) {
13403
            url.path = base_url->path;
13404
            url.query = base_url->query;
13405
0
          } else {
13406
0
            url.update_base_pathname(base_url->get_pathname());
13407
0
            url.update_base_search(base_url->get_search());
13408
0
          }
13409
0
          url.update_unencoded_base_hash(*fragment);
13410
0
          return url;
13411
0
        }
13412
        // Otherwise, if base's scheme is not "file", set state to relative
13413
        // state and decrease pointer by 1.
13414
0
        else if (base_url->type != scheme::type::FILE) {
13415
0
          ada_log("NO_SCHEME non-file relative path");
13416
0
          state = state::RELATIVE_SCHEME;
13417
0
        }
13418
        // Otherwise, set state to file state and decrease pointer by 1.
13419
0
        else {
13420
0
          ada_log("NO_SCHEME file base type");
13421
0
          state = state::FILE;
13422
0
        }
13423
0
        break;
13424
174
      }
13425
9.51k
      case state::AUTHORITY: {
13426
9.51k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13427
        // most URLs have no @. Having no @ tells us that we don't have to worry
13428
        // about AUTHORITY. Of course, we could have @ and still not have to
13429
        // worry about AUTHORITY.
13430
        // TODO: Instead of just collecting a bool, collect the location of the
13431
        // '@' and do something useful with it.
13432
        // TODO: We could do various processing early on, using a single pass
13433
        // over the string to collect information about it, e.g., telling us
13434
        // whether there is a @ and if so, where (or how many).
13435
13436
        // Check if url data contains an @.
13437
9.51k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13438
8.63k
          state = state::HOST;
13439
8.63k
          break;
13440
8.63k
        }
13441
877
        bool at_sign_seen{false};
13442
877
        bool password_token_seen{false};
13443
        /**
13444
         * We expect something of the sort...
13445
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13446
         * --------^
13447
         */
13448
12.6k
        do {
13449
12.6k
          std::string_view view = url_data.substr(input_position);
13450
          // The delimiters are @, /, ? \\.
13451
12.6k
          size_t location =
13452
12.6k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13453
12.6k
                               : helpers::find_authority_delimiter(view);
13454
12.6k
          std::string_view authority_view = view.substr(0, location);
13455
12.6k
          size_t end_of_authority = input_position + authority_view.size();
13456
          // If c is U+0040 (@), then:
13457
12.6k
          if ((end_of_authority != input_size) &&
13458
11.9k
              (url_data[end_of_authority] == '@')) {
13459
            // If atSignSeen is true, then prepend "%40" to buffer.
13460
11.7k
            if (at_sign_seen) {
13461
10.9k
              if (password_token_seen) {
13462
                if constexpr (result_type_is_ada_url) {
13463
                  url.password += "%40";
13464
6.28k
                } else {
13465
6.28k
                  url.append_base_password("%40");
13466
6.28k
                }
13467
6.28k
              } else {
13468
                if constexpr (result_type_is_ada_url) {
13469
                  url.username += "%40";
13470
4.64k
                } else {
13471
4.64k
                  url.append_base_username("%40");
13472
4.64k
                }
13473
4.64k
              }
13474
10.9k
            }
13475
13476
11.7k
            at_sign_seen = true;
13477
13478
11.7k
            if (!password_token_seen) {
13479
5.45k
              size_t password_token_location = authority_view.find(':');
13480
5.45k
              password_token_seen =
13481
5.45k
                  password_token_location != std::string_view::npos;
13482
13483
5.45k
              if constexpr (store_values) {
13484
5.45k
                if (!password_token_seen) {
13485
                  if constexpr (result_type_is_ada_url) {
13486
                    url.username += unicode::percent_encode(
13487
                        authority_view,
13488
                        character_sets::USERINFO_PERCENT_ENCODE);
13489
5.09k
                  } else {
13490
5.09k
                    url.append_base_username(unicode::percent_encode(
13491
5.09k
                        authority_view,
13492
5.09k
                        character_sets::USERINFO_PERCENT_ENCODE));
13493
5.09k
                  }
13494
5.09k
                } else {
13495
                  if constexpr (result_type_is_ada_url) {
13496
                    url.username += unicode::percent_encode(
13497
                        authority_view.substr(0, password_token_location),
13498
                        character_sets::USERINFO_PERCENT_ENCODE);
13499
                    url.password += unicode::percent_encode(
13500
                        authority_view.substr(password_token_location + 1),
13501
                        character_sets::USERINFO_PERCENT_ENCODE);
13502
360
                  } else {
13503
360
                    url.append_base_username(unicode::percent_encode(
13504
360
                        authority_view.substr(0, password_token_location),
13505
360
                        character_sets::USERINFO_PERCENT_ENCODE));
13506
360
                    url.append_base_password(unicode::percent_encode(
13507
360
                        authority_view.substr(password_token_location + 1),
13508
360
                        character_sets::USERINFO_PERCENT_ENCODE));
13509
360
                  }
13510
360
                }
13511
5.45k
              }
13512
6.28k
            } else if constexpr (store_values) {
13513
              if constexpr (result_type_is_ada_url) {
13514
                url.password += unicode::percent_encode(
13515
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13516
6.28k
              } else {
13517
6.28k
                url.append_base_password(unicode::percent_encode(
13518
6.28k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13519
6.28k
              }
13520
6.28k
            }
13521
11.7k
          }
13522
          // Otherwise, if one of the following is true:
13523
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13524
          // - url is special and c is U+005C (\)
13525
877
          else if (end_of_authority == input_size ||
13526
234
                   url_data[end_of_authority] == '/' ||
13527
104
                   url_data[end_of_authority] == '?' ||
13528
877
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13529
            // If atSignSeen is true and authority_view is the empty string,
13530
            // validation error, return failure.
13531
877
            if (at_sign_seen && authority_view.empty()) {
13532
139
              url.is_valid = false;
13533
139
              return url;
13534
139
            }
13535
738
            state = state::HOST;
13536
738
            break;
13537
877
          }
13538
11.7k
          if (end_of_authority == input_size) {
13539
0
            if constexpr (store_values) {
13540
0
              if (fragment.has_value()) {
13541
0
                url.update_unencoded_base_hash(*fragment);
13542
0
              }
13543
0
            }
13544
0
            return url;
13545
0
          }
13546
11.7k
          input_position = end_of_authority + 1;
13547
11.7k
        } while (true);
13548
13549
738
        break;
13550
877
      }
13551
738
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
13552
0
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
13553
0
                helpers::substring(url_data, input_position));
13554
13555
        // If c is U+002F (/) and remaining starts with U+002F (/),
13556
        // then set state to special authority ignore slashes state and increase
13557
        // pointer by 1.
13558
0
        if (url_data.substr(input_position, 2) == "//") {
13559
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13560
0
          input_position += 2;
13561
0
        } else {
13562
          // Otherwise, validation error, set state to relative state and
13563
          // decrease pointer by 1.
13564
0
          state = state::RELATIVE_SCHEME;
13565
0
        }
13566
13567
0
        break;
13568
877
      }
13569
2.51k
      case state::PATH_OR_AUTHORITY: {
13570
2.51k
        ada_log("PATH_OR_AUTHORITY ",
13571
2.51k
                helpers::substring(url_data, input_position));
13572
13573
        // If c is U+002F (/), then set state to authority state.
13574
2.51k
        if ((input_position != input_size) &&
13575
2.19k
            (url_data[input_position] == '/')) {
13576
965
          state = state::AUTHORITY;
13577
965
          input_position++;
13578
1.55k
        } else {
13579
          // Otherwise, set state to path state, and decrease pointer by 1.
13580
1.55k
          state = state::PATH;
13581
1.55k
        }
13582
13583
2.51k
        break;
13584
877
      }
13585
0
      case state::RELATIVE_SCHEME: {
13586
0
        ada_log("RELATIVE_SCHEME ",
13587
0
                helpers::substring(url_data, input_position));
13588
13589
        // Set url's scheme to base's scheme.
13590
0
        url.copy_scheme(*base_url);
13591
13592
        // If c is U+002F (/), then set state to relative slash state.
13593
0
        if ((input_position != input_size) &&
13594
            // NOLINTNEXTLINE(bugprone-branch-clone)
13595
0
            (url_data[input_position] == '/')) {
13596
0
          ada_log(
13597
0
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
13598
0
              "slash state");
13599
0
          state = state::RELATIVE_SLASH;
13600
0
        } else if (url.is_special() && (input_position != input_size) &&
13601
0
                   (url_data[input_position] == '\\')) {
13602
          // Otherwise, if url is special and c is U+005C (\), validation error,
13603
          // set state to relative slash state.
13604
0
          ada_log(
13605
0
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
13606
0
              "error, set state to relative slash state");
13607
0
          state = state::RELATIVE_SLASH;
13608
0
        } else {
13609
0
          ada_log("RELATIVE_SCHEME otherwise");
13610
          // Set url's username to base's username, url's password to base's
13611
          // password, url's host to base's host, url's port to base's port,
13612
          // url's path to a clone of base's path, and url's query to base's
13613
          // query.
13614
          if constexpr (result_type_is_ada_url) {
13615
            url.username = base_url->username;
13616
            url.password = base_url->password;
13617
            url.host = base_url->host;
13618
            url.port = base_url->port;
13619
            // cloning the base path includes cloning the has_opaque_path flag
13620
            url.has_opaque_path = base_url->has_opaque_path;
13621
            url.path = base_url->path;
13622
            url.query = base_url->query;
13623
0
          } else {
13624
0
            url.update_base_authority(base_url->get_href(),
13625
0
                                      base_url->get_components());
13626
0
            url.update_host_to_base_host(base_url->get_hostname());
13627
0
            url.update_base_port(base_url->retrieve_base_port());
13628
            // cloning the base path includes cloning the has_opaque_path flag
13629
0
            url.has_opaque_path = base_url->has_opaque_path;
13630
0
            url.update_base_pathname(base_url->get_pathname());
13631
0
            url.update_base_search(base_url->get_search());
13632
0
          }
13633
13634
0
          url.has_opaque_path = base_url->has_opaque_path;
13635
13636
          // If c is U+003F (?), then set url's query to the empty string, and
13637
          // state to query state.
13638
0
          if ((input_position != input_size) &&
13639
0
              (url_data[input_position] == '?')) {
13640
0
            state = state::QUERY;
13641
0
          }
13642
          // Otherwise, if c is not the EOF code point:
13643
0
          else if (input_position != input_size) {
13644
            // Set url's query to null.
13645
0
            url.clear_search();
13646
            if constexpr (result_type_is_ada_url) {
13647
              // Shorten url's path.
13648
              helpers::shorten_path(url.path, url.type);
13649
0
            } else {
13650
0
              std::string_view path = url.get_pathname();
13651
0
              if (helpers::shorten_path(path, url.type)) {
13652
0
                url.update_base_pathname(std::move(std::string(path)));
13653
0
              }
13654
0
            }
13655
            // Set state to path state and decrease pointer by 1.
13656
0
            state = state::PATH;
13657
0
            break;
13658
0
          }
13659
0
        }
13660
0
        input_position++;
13661
0
        break;
13662
0
      }
13663
0
      case state::RELATIVE_SLASH: {
13664
0
        ada_log("RELATIVE_SLASH ",
13665
0
                helpers::substring(url_data, input_position));
13666
13667
        // If url is special and c is U+002F (/) or U+005C (\), then:
13668
0
        if (url.is_special() && (input_position != input_size) &&
13669
0
            (url_data[input_position] == '/' ||
13670
0
             url_data[input_position] == '\\')) {
13671
          // Set state to special authority ignore slashes state.
13672
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13673
0
        }
13674
        // Otherwise, if c is U+002F (/), then set state to authority state.
13675
0
        else if ((input_position != input_size) &&
13676
0
                 (url_data[input_position] == '/')) {
13677
0
          state = state::AUTHORITY;
13678
0
        }
13679
        // Otherwise, set
13680
        // - url's username to base's username,
13681
        // - url's password to base's password,
13682
        // - url's host to base's host,
13683
        // - url's port to base's port,
13684
        // - state to path state, and then, decrease pointer by 1.
13685
0
        else {
13686
          if constexpr (result_type_is_ada_url) {
13687
            url.username = base_url->username;
13688
            url.password = base_url->password;
13689
            url.host = base_url->host;
13690
            url.port = base_url->port;
13691
0
          } else {
13692
0
            url.update_base_authority(base_url->get_href(),
13693
0
                                      base_url->get_components());
13694
0
            url.update_host_to_base_host(base_url->get_hostname());
13695
0
            url.update_base_port(base_url->retrieve_base_port());
13696
0
          }
13697
0
          state = state::PATH;
13698
0
          break;
13699
0
        }
13700
13701
0
        input_position++;
13702
0
        break;
13703
0
      }
13704
8.55k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13705
8.55k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13706
8.55k
                helpers::substring(url_data, input_position));
13707
13708
        // If c is U+002F (/) and remaining starts with U+002F (/),
13709
        // then set state to special authority ignore slashes state and increase
13710
        // pointer by 1.
13711
8.55k
        if (url_data.substr(input_position, 2) == "//") {
13712
33
          input_position += 2;
13713
33
        }
13714
13715
8.55k
        [[fallthrough]];
13716
8.55k
      }
13717
8.55k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13718
8.55k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13719
8.55k
                helpers::substring(url_data, input_position));
13720
13721
        // If c is neither U+002F (/) nor U+005C (\), then set state to
13722
        // authority state and decrease pointer by 1.
13723
9.87k
        while ((input_position != input_size) &&
13724
9.84k
               ((url_data[input_position] == '/') ||
13725
9.19k
                (url_data[input_position] == '\\'))) {
13726
1.32k
          input_position++;
13727
1.32k
        }
13728
8.55k
        state = state::AUTHORITY;
13729
13730
8.55k
        break;
13731
8.55k
      }
13732
936
      case state::QUERY: {
13733
936
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13734
936
        if constexpr (store_values) {
13735
          // Let queryPercentEncodeSet be the special-query percent-encode set
13736
          // if url is special; otherwise the query percent-encode set.
13737
936
          const uint8_t* query_percent_encode_set =
13738
936
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13739
936
                               : character_sets::QUERY_PERCENT_ENCODE;
13740
13741
          // Percent-encode after encoding, with encoding, buffer, and
13742
          // queryPercentEncodeSet, and append the result to url's query.
13743
936
          url.update_base_search(url_data.substr(input_position),
13744
936
                                 query_percent_encode_set);
13745
936
          ada_log("QUERY update_base_search completed ");
13746
936
          if (fragment.has_value()) {
13747
180
            url.update_unencoded_base_hash(*fragment);
13748
180
          }
13749
936
        }
13750
936
        return url;
13751
8.55k
      }
13752
9.37k
      case state::HOST: {
13753
9.37k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13754
13755
9.37k
        std::string_view host_view = url_data.substr(input_position);
13756
9.37k
        auto [location, found_colon] =
13757
9.37k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13758
9.37k
        input_position = (location != std::string_view::npos)
13759
9.37k
                             ? input_position + location
13760
9.37k
                             : input_size;
13761
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13762
        // Note: the 'found_colon' value is true if and only if a colon was
13763
        // encountered while not inside brackets.
13764
9.37k
        if (found_colon) {
13765
          // If buffer is the empty string, validation error, return failure.
13766
          // Let host be the result of host parsing buffer with url is not
13767
          // special.
13768
1.34k
          ada_log("HOST parsing ", host_view);
13769
1.34k
          if (!url.parse_host(host_view)) {
13770
175
            return url;
13771
175
          }
13772
1.16k
          ada_log("HOST parsing results in ", url.get_hostname());
13773
          // Set url's host to host, buffer to the empty string, and state to
13774
          // port state.
13775
1.16k
          state = state::PORT;
13776
1.16k
          input_position++;
13777
1.16k
        }
13778
        // Otherwise, if one of the following is true:
13779
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13780
        // - url is special and c is U+005C (\)
13781
        // The get_host_delimiter_location function either brings us to
13782
        // the colon outside of the bracket, or to one of those characters.
13783
8.03k
        else {
13784
          // If url is special and host_view is the empty string, validation
13785
          // error, return failure.
13786
8.03k
          if (host_view.empty() && url.is_special()) {
13787
25
            url.is_valid = false;
13788
25
            return url;
13789
25
          }
13790
8.01k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
13791
          // Let host be the result of host parsing host_view with url is not
13792
          // special.
13793
8.01k
          if (host_view.empty()) {
13794
96
            url.update_base_hostname("");
13795
7.91k
          } else if (!url.parse_host(host_view)) {
13796
1.71k
            return url;
13797
1.71k
          }
13798
6.29k
          ada_log("HOST parsing results in ", url.get_hostname(),
13799
6.29k
                  " href=", url.get_href());
13800
13801
          // Set url's host to host, and state to path start state.
13802
6.29k
          state = state::PATH_START;
13803
6.29k
        }
13804
13805
7.46k
        break;
13806
9.37k
      }
13807
7.46k
      case state::OPAQUE_PATH: {
13808
2.52k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13809
2.52k
        std::string_view view = url_data.substr(input_position);
13810
        // If c is U+003F (?), then set url's query to the empty string and
13811
        // state to query state.
13812
2.52k
        size_t location = view.find('?');
13813
2.52k
        if (location != std::string_view::npos) {
13814
150
          view.remove_suffix(view.size() - location);
13815
150
          state = state::QUERY;
13816
150
          input_position += location + 1;
13817
2.37k
        } else {
13818
2.37k
          input_position = input_size + 1;
13819
2.37k
        }
13820
2.52k
        url.has_opaque_path = true;
13821
13822
        // This is a really unlikely scenario in real world. We should not seek
13823
        // to optimize it.
13824
2.52k
        if (view.ends_with(' ')) {
13825
120
          std::string modified_view =
13826
120
              std::string(view.substr(0, view.size() - 1)) + "%20";
13827
120
          url.update_base_pathname(unicode::percent_encode(
13828
120
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13829
2.40k
        } else {
13830
2.40k
          url.update_base_pathname(unicode::percent_encode(
13831
2.40k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13832
2.40k
        }
13833
2.52k
        break;
13834
9.37k
      }
13835
1.16k
      case state::PORT: {
13836
1.16k
        ada_log("PORT ", helpers::substring(url_data, input_position));
13837
1.16k
        std::string_view port_view = url_data.substr(input_position);
13838
1.16k
        input_position += url.parse_port(port_view, true);
13839
1.16k
        if (!url.is_valid) {
13840
146
          return url;
13841
146
        }
13842
1.02k
        state = state::PATH_START;
13843
1.02k
        [[fallthrough]];
13844
1.02k
      }
13845
8.05k
      case state::PATH_START: {
13846
8.05k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13847
13848
        // If url is special, then:
13849
8.05k
        if (url.is_special()) {
13850
          // Set state to path state.
13851
7.26k
          state = state::PATH;
13852
13853
          // Optimization: Avoiding going into PATH state improves the
13854
          // performance of urls ending with /.
13855
7.26k
          if (input_position == input_size) {
13856
5.99k
            if constexpr (store_values) {
13857
5.99k
              url.update_base_pathname("/");
13858
5.99k
              if (fragment.has_value()) {
13859
124
                url.update_unencoded_base_hash(*fragment);
13860
124
              }
13861
5.99k
            }
13862
5.99k
            return url;
13863
5.99k
          }
13864
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
13865
          // by 1. We know that (input_position == input_size) is impossible
13866
          // here, because of the previous if-check.
13867
1.27k
          if ((url_data[input_position] != '/') &&
13868
335
              (url_data[input_position] != '\\')) {
13869
220
            break;
13870
220
          }
13871
1.27k
        }
13872
        // Otherwise, if state override is not given and c is U+003F (?),
13873
        // set url's query to the empty string and state to query state.
13874
786
        else if ((input_position != input_size) &&
13875
321
                 (url_data[input_position] == '?')) {
13876
122
          state = state::QUERY;
13877
122
        }
13878
        // Otherwise, if c is not the EOF code point:
13879
664
        else if (input_position != input_size) {
13880
          // Set state to path state.
13881
199
          state = state::PATH;
13882
13883
          // If c is not U+002F (/), then decrease pointer by 1.
13884
199
          if (url_data[input_position] != '/') {
13885
0
            break;
13886
0
          }
13887
199
        }
13888
13889
1.84k
        input_position++;
13890
1.84k
        break;
13891
8.05k
      }
13892
4.35k
      case state::PATH: {
13893
4.35k
        ada_log("PATH ", helpers::substring(url_data, input_position));
13894
4.35k
        std::string_view view = url_data.substr(input_position);
13895
13896
        // Most time, we do not need percent encoding.
13897
        // Furthermore, we can immediately locate the '?'.
13898
4.35k
        size_t locofquestionmark = view.find('?');
13899
4.35k
        if (locofquestionmark != std::string_view::npos) {
13900
664
          state = state::QUERY;
13901
664
          view.remove_suffix(view.size() - locofquestionmark);
13902
664
          input_position += locofquestionmark + 1;
13903
3.68k
        } else {
13904
3.68k
          input_position = input_size + 1;
13905
3.68k
        }
13906
4.35k
        if constexpr (store_values) {
13907
          if constexpr (result_type_is_ada_url) {
13908
            helpers::parse_prepared_path(view, url.type, url.path);
13909
4.35k
          } else {
13910
4.35k
            url.consume_prepared_path(view);
13911
4.35k
            ADA_ASSERT_TRUE(url.validate());
13912
4.35k
          }
13913
4.35k
        }
13914
4.35k
        break;
13915
8.05k
      }
13916
1.03k
      case state::FILE_SLASH: {
13917
1.03k
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13918
13919
        // If c is U+002F (/) or U+005C (\), then:
13920
1.03k
        if ((input_position != input_size) &&
13921
1.02k
            (url_data[input_position] == '/' ||
13922
931
             url_data[input_position] == '\\')) {
13923
931
          ada_log("FILE_SLASH c is U+002F or U+005C");
13924
          // Set state to file host state.
13925
931
          state = state::FILE_HOST;
13926
931
          input_position++;
13927
931
        } else {
13928
101
          ada_log("FILE_SLASH otherwise");
13929
          // If base is non-null and base's scheme is "file", then:
13930
          // Note: it is unsafe to do base_url->scheme unless you know that
13931
          // base_url_has_value() is true.
13932
101
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13933
            // Set url's host to base's host.
13934
            if constexpr (result_type_is_ada_url) {
13935
              url.host = base_url->host;
13936
0
            } else {
13937
0
              url.update_host_to_base_host(base_url->get_host());
13938
0
            }
13939
            // If the code point substring from pointer to the end of input does
13940
            // not start with a Windows drive letter and base's path[0] is a
13941
            // normalized Windows drive letter, then append base's path[0] to
13942
            // url's path.
13943
0
            if (!base_url->get_pathname().empty()) {
13944
0
              if (!checkers::is_windows_drive_letter(
13945
0
                      url_data.substr(input_position))) {
13946
0
                std::string_view first_base_url_path =
13947
0
                    base_url->get_pathname().substr(1);
13948
0
                size_t loc = first_base_url_path.find('/');
13949
0
                if (loc != std::string_view::npos) {
13950
0
                  helpers::resize(first_base_url_path, loc);
13951
0
                }
13952
0
                if (checkers::is_normalized_windows_drive_letter(
13953
0
                        first_base_url_path)) {
13954
                  if constexpr (result_type_is_ada_url) {
13955
                    url.path += '/';
13956
                    url.path += first_base_url_path;
13957
0
                  } else {
13958
0
                    url.append_base_pathname(
13959
0
                        helpers::concat("/", first_base_url_path));
13960
0
                  }
13961
0
                }
13962
0
              }
13963
0
            }
13964
0
          }
13965
13966
          // Set state to path state, and decrease pointer by 1.
13967
101
          state = state::PATH;
13968
101
        }
13969
13970
1.03k
        break;
13971
8.05k
      }
13972
931
      case state::FILE_HOST: {
13973
931
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13974
931
        std::string_view view = url_data.substr(input_position);
13975
13976
931
        size_t location = view.find_first_of("/\\?");
13977
931
        std::string_view file_host_buffer(
13978
931
            view.data(),
13979
931
            (location != std::string_view::npos) ? location : view.size());
13980
13981
931
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13982
5
          state = state::PATH;
13983
926
        } else if (file_host_buffer.empty()) {
13984
          // Set url's host to the empty string.
13985
          if constexpr (result_type_is_ada_url) {
13986
            url.host = "";
13987
16
          } else {
13988
16
            url.update_base_hostname("");
13989
16
          }
13990
          // Set state to path start state.
13991
16
          state = state::PATH_START;
13992
910
        } else {
13993
910
          size_t consumed_bytes = file_host_buffer.size();
13994
910
          input_position += consumed_bytes;
13995
          // Let host be the result of host parsing buffer with url is not
13996
          // special.
13997
910
          if (!url.parse_host(file_host_buffer)) {
13998
195
            return url;
13999
195
          }
14000
14001
          if constexpr (result_type_is_ada_url) {
14002
            // If host is "localhost", then set host to the empty string.
14003
            if (url.host.has_value() && url.host.value() == "localhost") {
14004
              url.host = "";
14005
            }
14006
715
          } else {
14007
715
            if (url.get_hostname() == "localhost") {
14008
7
              url.update_base_hostname("");
14009
7
            }
14010
715
          }
14011
14012
          // Set buffer to the empty string and state to path start state.
14013
715
          state = state::PATH_START;
14014
715
        }
14015
14016
736
        break;
14017
931
      }
14018
2.25k
      case state::FILE: {
14019
2.25k
        ada_log("FILE ", helpers::substring(url_data, input_position));
14020
2.25k
        std::string_view file_view = url_data.substr(input_position);
14021
14022
2.25k
        url.set_protocol_as_file();
14023
        if constexpr (result_type_is_ada_url) {
14024
          // Set url's host to the empty string.
14025
          url.host = "";
14026
2.25k
        } else {
14027
2.25k
          url.update_base_hostname("");
14028
2.25k
        }
14029
        // If c is U+002F (/) or U+005C (\), then:
14030
2.25k
        if (input_position != input_size &&
14031
2.21k
            (url_data[input_position] == '/' ||
14032
1.25k
             url_data[input_position] == '\\')) {
14033
1.03k
          ada_log("FILE c is U+002F or U+005C");
14034
          // Set state to file slash state.
14035
1.03k
          state = state::FILE_SLASH;
14036
1.03k
        }
14037
        // Otherwise, if base is non-null and base's scheme is "file":
14038
1.22k
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
14039
          // Set url's host to base's host, url's path to a clone of base's
14040
          // path, and url's query to base's query.
14041
0
          ada_log("FILE base non-null");
14042
          if constexpr (result_type_is_ada_url) {
14043
            url.host = base_url->host;
14044
            url.path = base_url->path;
14045
            url.query = base_url->query;
14046
0
          } else {
14047
0
            url.update_host_to_base_host(base_url->get_hostname());
14048
0
            url.update_base_pathname(base_url->get_pathname());
14049
0
            url.update_base_search(base_url->get_search());
14050
0
          }
14051
0
          url.has_opaque_path = base_url->has_opaque_path;
14052
14053
          // If c is U+003F (?), then set url's query to the empty string and
14054
          // state to query state.
14055
0
          if (input_position != input_size && url_data[input_position] == '?') {
14056
0
            state = state::QUERY;
14057
0
          }
14058
          // Otherwise, if c is not the EOF code point:
14059
0
          else if (input_position != input_size) {
14060
            // Set url's query to null.
14061
0
            url.clear_search();
14062
            // If the code point substring from pointer to the end of input does
14063
            // not start with a Windows drive letter, then shorten url's path.
14064
0
            if (!checkers::is_windows_drive_letter(file_view)) {
14065
              if constexpr (result_type_is_ada_url) {
14066
                helpers::shorten_path(url.path, url.type);
14067
0
              } else {
14068
0
                std::string_view path = url.get_pathname();
14069
0
                if (helpers::shorten_path(path, url.type)) {
14070
0
                  url.update_base_pathname(std::move(std::string(path)));
14071
0
                }
14072
0
              }
14073
0
            }
14074
            // Otherwise:
14075
0
            else {
14076
              // Set url's path to an empty list.
14077
0
              url.clear_pathname();
14078
0
              url.has_opaque_path = true;
14079
0
            }
14080
14081
            // Set state to path state and decrease pointer by 1.
14082
0
            state = state::PATH;
14083
0
            break;
14084
0
          }
14085
0
        }
14086
        // Otherwise, set state to path state, and decrease pointer by 1.
14087
1.22k
        else {
14088
1.22k
          ada_log("FILE go to path");
14089
1.22k
          state = state::PATH;
14090
1.22k
          break;
14091
1.22k
        }
14092
14093
1.03k
        input_position++;
14094
1.03k
        break;
14095
2.25k
      }
14096
0
      default:
14097
0
        unreachable();
14098
82.2k
    }
14099
82.2k
  }
14100
6.52k
  if constexpr (store_values) {
14101
6.52k
    if (fragment.has_value()) {
14102
416
      url.update_unencoded_base_hash(*fragment);
14103
416
    }
14104
6.52k
  }
14105
6.52k
  return url;
14106
16.0k
}
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
13212
8.59k
                           const result_type* base_url) {
13213
  // We can specialize the implementation per type.
13214
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
13215
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
13216
  // something else } is free (at runtime). This means that ada::url_aggregator
13217
  // and ada::url **do not have to support the exact same API**.
13218
8.59k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13219
8.59k
  constexpr bool result_type_is_ada_url_aggregator =
13220
8.59k
      std::is_same_v<url_aggregator, result_type>;
13221
8.59k
  static_assert(result_type_is_ada_url ||
13222
8.59k
                result_type_is_ada_url_aggregator);  // We don't support
13223
                                                     // anything else for now.
13224
13225
8.59k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13226
8.59k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13227
8.59k
          ")");
13228
13229
8.59k
  state state = state::SCHEME_START;
13230
8.59k
  result_type url{};
13231
13232
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
13233
  // surely the result of a bug or are otherwise a security concern.
13234
8.59k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) [[unlikely]] {
13235
0
    url.is_valid = false;
13236
0
  }
13237
  // Going forward, user_input.size() is in [0,
13238
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
13239
  // base, or the optional_url was invalid, we must return.
13240
8.59k
  if (base_url != nullptr) {
13241
0
    url.is_valid &= base_url->is_valid;
13242
0
  }
13243
8.59k
  if (!url.is_valid) {
13244
0
    return url;
13245
0
  }
13246
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
13247
    // Most of the time, we just need user_input.size().
13248
    // In some instances, we may need a bit more.
13249
    ///////////////////////////
13250
    // This is *very* important. This line should *not* be removed
13251
    // hastily. There are principled reasons why reserve is important
13252
    // for performance. If you have a benchmark with small inputs,
13253
    // it may not matter, but in other instances, it could.
13254
    ////
13255
    // This rounds up to the next power of two.
13256
    // We know that user_input.size() is in [0,
13257
    // std::numeric_limits<uint32_t>::max).
13258
    uint32_t reserve_capacity =
13259
        (0xFFFFFFFF >>
13260
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13261
        1;
13262
    url.reserve(reserve_capacity);
13263
  }
13264
8.59k
  std::string tmp_buffer;
13265
8.59k
  std::string_view url_data;
13266
8.59k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13267
349
    tmp_buffer = user_input;
13268
    // Optimization opportunity: Instead of copying and then pruning, we could
13269
    // just directly build the string from user_input.
13270
349
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13271
349
    url_data = tmp_buffer;
13272
8.24k
  } else [[likely]] {
13273
8.24k
    url_data = user_input;
13274
8.24k
  }
13275
13276
  // Leading and trailing control characters are uncommon and easy to deal with
13277
  // (no performance concern).
13278
8.59k
  helpers::trim_c0_whitespace(url_data);
13279
13280
  // Optimization opportunity. Most websites do not have fragment.
13281
8.59k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13282
  // We add it last so that an implementation like ada::url_aggregator
13283
  // can append it last to its internal buffer, thus improving performance.
13284
13285
  // Here url_data no longer has its fragment.
13286
  // We are going to access the data from url_data (it is immutable).
13287
  // At any given time, we are pointing at byte 'input_position' in url_data.
13288
  // The input_position variable should range from 0 to input_size.
13289
  // It is illegal to access url_data at input_size.
13290
8.59k
  size_t input_position = 0;
13291
8.59k
  const size_t input_size = url_data.size();
13292
  // Keep running the following state machine by switching on state.
13293
  // If after a run pointer points to the EOF code point, go to the next step.
13294
  // Otherwise, increase pointer by 1 and continue with the state machine.
13295
  // We never decrement input_position.
13296
47.1k
  while (input_position <= input_size) {
13297
43.9k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13298
43.9k
            " in state ", ada::to_string(state));
13299
43.9k
    switch (state) {
13300
8.59k
      case state::SCHEME_START: {
13301
8.59k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13302
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13303
        // state to scheme state.
13304
8.59k
        if ((input_position != input_size) &&
13305
8.55k
            checkers::is_alpha(url_data[input_position])) {
13306
8.51k
          state = state::SCHEME;
13307
8.51k
          input_position++;
13308
8.51k
        } else {
13309
          // Otherwise, if state override is not given, set state to no scheme
13310
          // state and decrease pointer by 1.
13311
78
          state = state::NO_SCHEME;
13312
78
        }
13313
8.59k
        break;
13314
0
      }
13315
8.51k
      case state::SCHEME: {
13316
8.51k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13317
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13318
        // append c, lowercased, to buffer.
13319
40.1k
        while ((input_position != input_size) &&
13320
40.1k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13321
31.6k
          input_position++;
13322
31.6k
        }
13323
        // Otherwise, if c is U+003A (:), then:
13324
8.51k
        if ((input_position != input_size) &&
13325
8.48k
            (url_data[input_position] == ':')) {
13326
8.47k
          ada_log("SCHEME the scheme should be ",
13327
8.47k
                  url_data.substr(0, input_position));
13328
          if constexpr (result_type_is_ada_url) {
13329
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13330
              return url;
13331
            }
13332
8.47k
          } else {
13333
            // we pass the colon along instead of painfully adding it back.
13334
8.47k
            if (!url.parse_scheme_with_colon(
13335
8.47k
                    url_data.substr(0, input_position + 1))) {
13336
0
              return url;
13337
0
            }
13338
8.47k
          }
13339
8.47k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13340
13341
          // If url's scheme is "file", then:
13342
8.47k
          if (url.type == scheme::type::FILE) {
13343
            // Set state to file state.
13344
1.16k
            state = state::FILE;
13345
1.16k
          }
13346
          // Otherwise, if url is special, base is non-null, and base's scheme
13347
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13348
          // != nullptr is false.
13349
7.30k
          else if (url.is_special() && base_url != nullptr &&
13350
0
                   base_url->type == url.type) {
13351
            // Set state to special relative or authority state.
13352
0
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13353
0
          }
13354
          // Otherwise, if url is special, set state to special authority
13355
          // slashes state.
13356
7.30k
          else if (url.is_special()) {
13357
4.79k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13358
4.79k
          }
13359
          // Otherwise, if remaining starts with an U+002F (/), set state to
13360
          // path or authority state and increase pointer by 1.
13361
2.50k
          else if (input_position + 1 < input_size &&
13362
2.28k
                   url_data[input_position + 1] == '/') {
13363
1.26k
            state = state::PATH_OR_AUTHORITY;
13364
1.26k
            input_position++;
13365
1.26k
          }
13366
          // Otherwise, set url's path to the empty string and set state to
13367
          // opaque path state.
13368
1.24k
          else {
13369
1.24k
            state = state::OPAQUE_PATH;
13370
1.24k
          }
13371
8.47k
        }
13372
        // Otherwise, if state override is not given, set buffer to the empty
13373
        // string, state to no scheme state, and start over (from the first code
13374
        // point in input).
13375
41
        else {
13376
41
          state = state::NO_SCHEME;
13377
41
          input_position = 0;
13378
41
          break;
13379
41
        }
13380
8.47k
        input_position++;
13381
8.47k
        break;
13382
8.51k
      }
13383
119
      case state::NO_SCHEME: {
13384
119
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13385
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13386
        // validation error, return failure.
13387
119
        if (base_url == nullptr ||
13388
119
            (base_url->has_opaque_path && !fragment.has_value())) {
13389
119
          ada_log("NO_SCHEME validation error");
13390
119
          url.is_valid = false;
13391
119
          return url;
13392
119
        }
13393
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13394
        // set url's scheme to base's scheme, url's path to base's path, url's
13395
        // query to base's query, and set state to fragment state.
13396
0
        else if (base_url->has_opaque_path && fragment.has_value() &&
13397
0
                 input_position == input_size) {
13398
0
          ada_log("NO_SCHEME opaque base with fragment");
13399
0
          url.copy_scheme(*base_url);
13400
0
          url.has_opaque_path = base_url->has_opaque_path;
13401
13402
          if constexpr (result_type_is_ada_url) {
13403
            url.path = base_url->path;
13404
            url.query = base_url->query;
13405
0
          } else {
13406
0
            url.update_base_pathname(base_url->get_pathname());
13407
0
            url.update_base_search(base_url->get_search());
13408
0
          }
13409
0
          url.update_unencoded_base_hash(*fragment);
13410
0
          return url;
13411
0
        }
13412
        // Otherwise, if base's scheme is not "file", set state to relative
13413
        // state and decrease pointer by 1.
13414
0
        else if (base_url->type != scheme::type::FILE) {
13415
0
          ada_log("NO_SCHEME non-file relative path");
13416
0
          state = state::RELATIVE_SCHEME;
13417
0
        }
13418
        // Otherwise, set state to file state and decrease pointer by 1.
13419
0
        else {
13420
0
          ada_log("NO_SCHEME file base type");
13421
0
          state = state::FILE;
13422
0
        }
13423
0
        break;
13424
119
      }
13425
5.30k
      case state::AUTHORITY: {
13426
5.30k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13427
        // most URLs have no @. Having no @ tells us that we don't have to worry
13428
        // about AUTHORITY. Of course, we could have @ and still not have to
13429
        // worry about AUTHORITY.
13430
        // TODO: Instead of just collecting a bool, collect the location of the
13431
        // '@' and do something useful with it.
13432
        // TODO: We could do various processing early on, using a single pass
13433
        // over the string to collect information about it, e.g., telling us
13434
        // whether there is a @ and if so, where (or how many).
13435
13436
        // Check if url data contains an @.
13437
5.30k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13438
4.84k
          state = state::HOST;
13439
4.84k
          break;
13440
4.84k
        }
13441
463
        bool at_sign_seen{false};
13442
463
        bool password_token_seen{false};
13443
        /**
13444
         * We expect something of the sort...
13445
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13446
         * --------^
13447
         */
13448
7.16k
        do {
13449
7.16k
          std::string_view view = url_data.substr(input_position);
13450
          // The delimiters are @, /, ? \\.
13451
7.16k
          size_t location =
13452
7.16k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13453
7.16k
                               : helpers::find_authority_delimiter(view);
13454
7.16k
          std::string_view authority_view = view.substr(0, location);
13455
7.16k
          size_t end_of_authority = input_position + authority_view.size();
13456
          // If c is U+0040 (@), then:
13457
7.16k
          if ((end_of_authority != input_size) &&
13458
6.82k
              (url_data[end_of_authority] == '@')) {
13459
            // If atSignSeen is true, then prepend "%40" to buffer.
13460
6.70k
            if (at_sign_seen) {
13461
6.27k
              if (password_token_seen) {
13462
                if constexpr (result_type_is_ada_url) {
13463
                  url.password += "%40";
13464
3.37k
                } else {
13465
3.37k
                  url.append_base_password("%40");
13466
3.37k
                }
13467
3.37k
              } else {
13468
                if constexpr (result_type_is_ada_url) {
13469
                  url.username += "%40";
13470
2.90k
                } else {
13471
2.90k
                  url.append_base_username("%40");
13472
2.90k
                }
13473
2.90k
              }
13474
6.27k
            }
13475
13476
6.70k
            at_sign_seen = true;
13477
13478
6.70k
            if (!password_token_seen) {
13479
3.32k
              size_t password_token_location = authority_view.find(':');
13480
3.32k
              password_token_seen =
13481
3.32k
                  password_token_location != std::string_view::npos;
13482
13483
              if constexpr (store_values) {
13484
                if (!password_token_seen) {
13485
                  if constexpr (result_type_is_ada_url) {
13486
                    url.username += unicode::percent_encode(
13487
                        authority_view,
13488
                        character_sets::USERINFO_PERCENT_ENCODE);
13489
                  } else {
13490
                    url.append_base_username(unicode::percent_encode(
13491
                        authority_view,
13492
                        character_sets::USERINFO_PERCENT_ENCODE));
13493
                  }
13494
                } else {
13495
                  if constexpr (result_type_is_ada_url) {
13496
                    url.username += unicode::percent_encode(
13497
                        authority_view.substr(0, password_token_location),
13498
                        character_sets::USERINFO_PERCENT_ENCODE);
13499
                    url.password += unicode::percent_encode(
13500
                        authority_view.substr(password_token_location + 1),
13501
                        character_sets::USERINFO_PERCENT_ENCODE);
13502
                  } else {
13503
                    url.append_base_username(unicode::percent_encode(
13504
                        authority_view.substr(0, password_token_location),
13505
                        character_sets::USERINFO_PERCENT_ENCODE));
13506
                    url.append_base_password(unicode::percent_encode(
13507
                        authority_view.substr(password_token_location + 1),
13508
                        character_sets::USERINFO_PERCENT_ENCODE));
13509
                  }
13510
                }
13511
              }
13512
3.37k
            } else if constexpr (store_values) {
13513
3.37k
              if constexpr (result_type_is_ada_url) {
13514
3.37k
                url.password += unicode::percent_encode(
13515
3.37k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13516
3.37k
              } else {
13517
3.37k
                url.append_base_password(unicode::percent_encode(
13518
3.37k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13519
3.37k
              }
13520
3.37k
            }
13521
6.70k
          }
13522
          // Otherwise, if one of the following is true:
13523
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13524
          // - url is special and c is U+005C (\)
13525
463
          else if (end_of_authority == input_size ||
13526
119
                   url_data[end_of_authority] == '/' ||
13527
53
                   url_data[end_of_authority] == '?' ||
13528
463
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13529
            // If atSignSeen is true and authority_view is the empty string,
13530
            // validation error, return failure.
13531
463
            if (at_sign_seen && authority_view.empty()) {
13532
98
              url.is_valid = false;
13533
98
              return url;
13534
98
            }
13535
365
            state = state::HOST;
13536
365
            break;
13537
463
          }
13538
6.70k
          if (end_of_authority == input_size) {
13539
            if constexpr (store_values) {
13540
              if (fragment.has_value()) {
13541
                url.update_unencoded_base_hash(*fragment);
13542
              }
13543
            }
13544
0
            return url;
13545
0
          }
13546
6.70k
          input_position = end_of_authority + 1;
13547
6.70k
        } while (true);
13548
13549
365
        break;
13550
463
      }
13551
365
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
13552
0
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
13553
0
                helpers::substring(url_data, input_position));
13554
13555
        // If c is U+002F (/) and remaining starts with U+002F (/),
13556
        // then set state to special authority ignore slashes state and increase
13557
        // pointer by 1.
13558
0
        if (url_data.substr(input_position, 2) == "//") {
13559
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13560
0
          input_position += 2;
13561
0
        } else {
13562
          // Otherwise, validation error, set state to relative state and
13563
          // decrease pointer by 1.
13564
0
          state = state::RELATIVE_SCHEME;
13565
0
        }
13566
13567
0
        break;
13568
463
      }
13569
1.26k
      case state::PATH_OR_AUTHORITY: {
13570
1.26k
        ada_log("PATH_OR_AUTHORITY ",
13571
1.26k
                helpers::substring(url_data, input_position));
13572
13573
        // If c is U+002F (/), then set state to authority state.
13574
1.26k
        if ((input_position != input_size) &&
13575
1.10k
            (url_data[input_position] == '/')) {
13576
504
          state = state::AUTHORITY;
13577
504
          input_position++;
13578
764
        } else {
13579
          // Otherwise, set state to path state, and decrease pointer by 1.
13580
764
          state = state::PATH;
13581
764
        }
13582
13583
1.26k
        break;
13584
463
      }
13585
0
      case state::RELATIVE_SCHEME: {
13586
0
        ada_log("RELATIVE_SCHEME ",
13587
0
                helpers::substring(url_data, input_position));
13588
13589
        // Set url's scheme to base's scheme.
13590
0
        url.copy_scheme(*base_url);
13591
13592
        // If c is U+002F (/), then set state to relative slash state.
13593
0
        if ((input_position != input_size) &&
13594
            // NOLINTNEXTLINE(bugprone-branch-clone)
13595
0
            (url_data[input_position] == '/')) {
13596
0
          ada_log(
13597
0
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
13598
0
              "slash state");
13599
0
          state = state::RELATIVE_SLASH;
13600
0
        } else if (url.is_special() && (input_position != input_size) &&
13601
0
                   (url_data[input_position] == '\\')) {
13602
          // Otherwise, if url is special and c is U+005C (\), validation error,
13603
          // set state to relative slash state.
13604
0
          ada_log(
13605
0
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
13606
0
              "error, set state to relative slash state");
13607
0
          state = state::RELATIVE_SLASH;
13608
0
        } else {
13609
0
          ada_log("RELATIVE_SCHEME otherwise");
13610
          // Set url's username to base's username, url's password to base's
13611
          // password, url's host to base's host, url's port to base's port,
13612
          // url's path to a clone of base's path, and url's query to base's
13613
          // query.
13614
          if constexpr (result_type_is_ada_url) {
13615
            url.username = base_url->username;
13616
            url.password = base_url->password;
13617
            url.host = base_url->host;
13618
            url.port = base_url->port;
13619
            // cloning the base path includes cloning the has_opaque_path flag
13620
            url.has_opaque_path = base_url->has_opaque_path;
13621
            url.path = base_url->path;
13622
            url.query = base_url->query;
13623
0
          } else {
13624
0
            url.update_base_authority(base_url->get_href(),
13625
0
                                      base_url->get_components());
13626
0
            url.update_host_to_base_host(base_url->get_hostname());
13627
0
            url.update_base_port(base_url->retrieve_base_port());
13628
            // cloning the base path includes cloning the has_opaque_path flag
13629
0
            url.has_opaque_path = base_url->has_opaque_path;
13630
0
            url.update_base_pathname(base_url->get_pathname());
13631
0
            url.update_base_search(base_url->get_search());
13632
0
          }
13633
13634
0
          url.has_opaque_path = base_url->has_opaque_path;
13635
13636
          // If c is U+003F (?), then set url's query to the empty string, and
13637
          // state to query state.
13638
0
          if ((input_position != input_size) &&
13639
0
              (url_data[input_position] == '?')) {
13640
0
            state = state::QUERY;
13641
0
          }
13642
          // Otherwise, if c is not the EOF code point:
13643
0
          else if (input_position != input_size) {
13644
            // Set url's query to null.
13645
0
            url.clear_search();
13646
            if constexpr (result_type_is_ada_url) {
13647
              // Shorten url's path.
13648
              helpers::shorten_path(url.path, url.type);
13649
0
            } else {
13650
0
              std::string_view path = url.get_pathname();
13651
0
              if (helpers::shorten_path(path, url.type)) {
13652
0
                url.update_base_pathname(std::move(std::string(path)));
13653
0
              }
13654
0
            }
13655
            // Set state to path state and decrease pointer by 1.
13656
0
            state = state::PATH;
13657
0
            break;
13658
0
          }
13659
0
        }
13660
0
        input_position++;
13661
0
        break;
13662
0
      }
13663
0
      case state::RELATIVE_SLASH: {
13664
0
        ada_log("RELATIVE_SLASH ",
13665
0
                helpers::substring(url_data, input_position));
13666
13667
        // If url is special and c is U+002F (/) or U+005C (\), then:
13668
0
        if (url.is_special() && (input_position != input_size) &&
13669
0
            (url_data[input_position] == '/' ||
13670
0
             url_data[input_position] == '\\')) {
13671
          // Set state to special authority ignore slashes state.
13672
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13673
0
        }
13674
        // Otherwise, if c is U+002F (/), then set state to authority state.
13675
0
        else if ((input_position != input_size) &&
13676
0
                 (url_data[input_position] == '/')) {
13677
0
          state = state::AUTHORITY;
13678
0
        }
13679
        // Otherwise, set
13680
        // - url's username to base's username,
13681
        // - url's password to base's password,
13682
        // - url's host to base's host,
13683
        // - url's port to base's port,
13684
        // - state to path state, and then, decrease pointer by 1.
13685
0
        else {
13686
          if constexpr (result_type_is_ada_url) {
13687
            url.username = base_url->username;
13688
            url.password = base_url->password;
13689
            url.host = base_url->host;
13690
            url.port = base_url->port;
13691
0
          } else {
13692
0
            url.update_base_authority(base_url->get_href(),
13693
0
                                      base_url->get_components());
13694
0
            url.update_host_to_base_host(base_url->get_hostname());
13695
0
            url.update_base_port(base_url->retrieve_base_port());
13696
0
          }
13697
0
          state = state::PATH;
13698
0
          break;
13699
0
        }
13700
13701
0
        input_position++;
13702
0
        break;
13703
0
      }
13704
4.79k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13705
4.79k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13706
4.79k
                helpers::substring(url_data, input_position));
13707
13708
        // If c is U+002F (/) and remaining starts with U+002F (/),
13709
        // then set state to special authority ignore slashes state and increase
13710
        // pointer by 1.
13711
4.79k
        if (url_data.substr(input_position, 2) == "//") {
13712
16
          input_position += 2;
13713
16
        }
13714
13715
4.79k
        [[fallthrough]];
13716
4.79k
      }
13717
4.79k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13718
4.79k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13719
4.79k
                helpers::substring(url_data, input_position));
13720
13721
        // If c is neither U+002F (/) nor U+005C (\), then set state to
13722
        // authority state and decrease pointer by 1.
13723
5.65k
        while ((input_position != input_size) &&
13724
5.63k
               ((url_data[input_position] == '/') ||
13725
5.20k
                (url_data[input_position] == '\\'))) {
13726
854
          input_position++;
13727
854
        }
13728
4.79k
        state = state::AUTHORITY;
13729
13730
4.79k
        break;
13731
4.79k
      }
13732
468
      case state::QUERY: {
13733
468
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13734
        if constexpr (store_values) {
13735
          // Let queryPercentEncodeSet be the special-query percent-encode set
13736
          // if url is special; otherwise the query percent-encode set.
13737
          const uint8_t* query_percent_encode_set =
13738
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13739
                               : character_sets::QUERY_PERCENT_ENCODE;
13740
13741
          // Percent-encode after encoding, with encoding, buffer, and
13742
          // queryPercentEncodeSet, and append the result to url's query.
13743
          url.update_base_search(url_data.substr(input_position),
13744
                                 query_percent_encode_set);
13745
          ada_log("QUERY update_base_search completed ");
13746
          if (fragment.has_value()) {
13747
            url.update_unencoded_base_hash(*fragment);
13748
          }
13749
        }
13750
468
        return url;
13751
4.79k
      }
13752
5.20k
      case state::HOST: {
13753
5.20k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13754
13755
5.20k
        std::string_view host_view = url_data.substr(input_position);
13756
5.20k
        auto [location, found_colon] =
13757
5.20k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13758
5.20k
        input_position = (location != std::string_view::npos)
13759
5.20k
                             ? input_position + location
13760
5.20k
                             : input_size;
13761
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13762
        // Note: the 'found_colon' value is true if and only if a colon was
13763
        // encountered while not inside brackets.
13764
5.20k
        if (found_colon) {
13765
          // If buffer is the empty string, validation error, return failure.
13766
          // Let host be the result of host parsing buffer with url is not
13767
          // special.
13768
781
          ada_log("HOST parsing ", host_view);
13769
781
          if (!url.parse_host(host_view)) {
13770
143
            return url;
13771
143
          }
13772
638
          ada_log("HOST parsing results in ", url.get_hostname());
13773
          // Set url's host to host, buffer to the empty string, and state to
13774
          // port state.
13775
638
          state = state::PORT;
13776
638
          input_position++;
13777
638
        }
13778
        // Otherwise, if one of the following is true:
13779
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13780
        // - url is special and c is U+005C (\)
13781
        // The get_host_delimiter_location function either brings us to
13782
        // the colon outside of the bracket, or to one of those characters.
13783
4.42k
        else {
13784
          // If url is special and host_view is the empty string, validation
13785
          // error, return failure.
13786
4.42k
          if (host_view.empty() && url.is_special()) {
13787
23
            url.is_valid = false;
13788
23
            return url;
13789
23
          }
13790
4.40k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
13791
          // Let host be the result of host parsing host_view with url is not
13792
          // special.
13793
4.40k
          if (host_view.empty()) {
13794
47
            url.update_base_hostname("");
13795
4.35k
          } else if (!url.parse_host(host_view)) {
13796
1.35k
            return url;
13797
1.35k
          }
13798
3.04k
          ada_log("HOST parsing results in ", url.get_hostname(),
13799
3.04k
                  " href=", url.get_href());
13800
13801
          // Set url's host to host, and state to path start state.
13802
3.04k
          state = state::PATH_START;
13803
3.04k
        }
13804
13805
3.68k
        break;
13806
5.20k
      }
13807
3.68k
      case state::OPAQUE_PATH: {
13808
1.24k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13809
1.24k
        std::string_view view = url_data.substr(input_position);
13810
        // If c is U+003F (?), then set url's query to the empty string and
13811
        // state to query state.
13812
1.24k
        size_t location = view.find('?');
13813
1.24k
        if (location != std::string_view::npos) {
13814
75
          view.remove_suffix(view.size() - location);
13815
75
          state = state::QUERY;
13816
75
          input_position += location + 1;
13817
1.16k
        } else {
13818
1.16k
          input_position = input_size + 1;
13819
1.16k
        }
13820
1.24k
        url.has_opaque_path = true;
13821
13822
        // This is a really unlikely scenario in real world. We should not seek
13823
        // to optimize it.
13824
1.24k
        if (view.ends_with(' ')) {
13825
60
          std::string modified_view =
13826
60
              std::string(view.substr(0, view.size() - 1)) + "%20";
13827
60
          url.update_base_pathname(unicode::percent_encode(
13828
60
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13829
1.18k
        } else {
13830
1.18k
          url.update_base_pathname(unicode::percent_encode(
13831
1.18k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13832
1.18k
        }
13833
1.24k
        break;
13834
5.20k
      }
13835
638
      case state::PORT: {
13836
638
        ada_log("PORT ", helpers::substring(url_data, input_position));
13837
638
        std::string_view port_view = url_data.substr(input_position);
13838
638
        input_position += url.parse_port(port_view, true);
13839
638
        if (!url.is_valid) {
13840
132
          return url;
13841
132
        }
13842
506
        state = state::PATH_START;
13843
506
        [[fallthrough]];
13844
506
      }
13845
3.90k
      case state::PATH_START: {
13846
3.90k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13847
13848
        // If url is special, then:
13849
3.90k
        if (url.is_special()) {
13850
          // Set state to path state.
13851
3.52k
          state = state::PATH;
13852
13853
          // Optimization: Avoiding going into PATH state improves the
13854
          // performance of urls ending with /.
13855
3.52k
          if (input_position == input_size) {
13856
            if constexpr (store_values) {
13857
              url.update_base_pathname("/");
13858
              if (fragment.has_value()) {
13859
                url.update_unencoded_base_hash(*fragment);
13860
              }
13861
            }
13862
2.89k
            return url;
13863
2.89k
          }
13864
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
13865
          // by 1. We know that (input_position == input_size) is impossible
13866
          // here, because of the previous if-check.
13867
627
          if ((url_data[input_position] != '/') &&
13868
166
              (url_data[input_position] != '\\')) {
13869
110
            break;
13870
110
          }
13871
627
        }
13872
        // Otherwise, if state override is not given and c is U+003F (?),
13873
        // set url's query to the empty string and state to query state.
13874
377
        else if ((input_position != input_size) &&
13875
158
                 (url_data[input_position] == '?')) {
13876
61
          state = state::QUERY;
13877
61
        }
13878
        // Otherwise, if c is not the EOF code point:
13879
316
        else if (input_position != input_size) {
13880
          // Set state to path state.
13881
97
          state = state::PATH;
13882
13883
          // If c is not U+002F (/), then decrease pointer by 1.
13884
97
          if (url_data[input_position] != '/') {
13885
0
            break;
13886
0
          }
13887
97
        }
13888
13889
894
        input_position++;
13890
894
        break;
13891
3.90k
      }
13892
2.13k
      case state::PATH: {
13893
2.13k
        ada_log("PATH ", helpers::substring(url_data, input_position));
13894
2.13k
        std::string_view view = url_data.substr(input_position);
13895
13896
        // Most time, we do not need percent encoding.
13897
        // Furthermore, we can immediately locate the '?'.
13898
2.13k
        size_t locofquestionmark = view.find('?');
13899
2.13k
        if (locofquestionmark != std::string_view::npos) {
13900
332
          state = state::QUERY;
13901
332
          view.remove_suffix(view.size() - locofquestionmark);
13902
332
          input_position += locofquestionmark + 1;
13903
1.80k
        } else {
13904
1.80k
          input_position = input_size + 1;
13905
1.80k
        }
13906
        if constexpr (store_values) {
13907
          if constexpr (result_type_is_ada_url) {
13908
            helpers::parse_prepared_path(view, url.type, url.path);
13909
          } else {
13910
            url.consume_prepared_path(view);
13911
            ADA_ASSERT_TRUE(url.validate());
13912
          }
13913
        }
13914
2.13k
        break;
13915
3.90k
      }
13916
569
      case state::FILE_SLASH: {
13917
569
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13918
13919
        // If c is U+002F (/) or U+005C (\), then:
13920
569
        if ((input_position != input_size) &&
13921
566
            (url_data[input_position] == '/' ||
13922
522
             url_data[input_position] == '\\')) {
13923
522
          ada_log("FILE_SLASH c is U+002F or U+005C");
13924
          // Set state to file host state.
13925
522
          state = state::FILE_HOST;
13926
522
          input_position++;
13927
522
        } else {
13928
47
          ada_log("FILE_SLASH otherwise");
13929
          // If base is non-null and base's scheme is "file", then:
13930
          // Note: it is unsafe to do base_url->scheme unless you know that
13931
          // base_url_has_value() is true.
13932
47
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13933
            // Set url's host to base's host.
13934
            if constexpr (result_type_is_ada_url) {
13935
              url.host = base_url->host;
13936
0
            } else {
13937
0
              url.update_host_to_base_host(base_url->get_host());
13938
0
            }
13939
            // If the code point substring from pointer to the end of input does
13940
            // not start with a Windows drive letter and base's path[0] is a
13941
            // normalized Windows drive letter, then append base's path[0] to
13942
            // url's path.
13943
0
            if (!base_url->get_pathname().empty()) {
13944
0
              if (!checkers::is_windows_drive_letter(
13945
0
                      url_data.substr(input_position))) {
13946
0
                std::string_view first_base_url_path =
13947
0
                    base_url->get_pathname().substr(1);
13948
0
                size_t loc = first_base_url_path.find('/');
13949
0
                if (loc != std::string_view::npos) {
13950
0
                  helpers::resize(first_base_url_path, loc);
13951
0
                }
13952
0
                if (checkers::is_normalized_windows_drive_letter(
13953
0
                        first_base_url_path)) {
13954
                  if constexpr (result_type_is_ada_url) {
13955
                    url.path += '/';
13956
                    url.path += first_base_url_path;
13957
0
                  } else {
13958
0
                    url.append_base_pathname(
13959
0
                        helpers::concat("/", first_base_url_path));
13960
0
                  }
13961
0
                }
13962
0
              }
13963
0
            }
13964
0
          }
13965
13966
          // Set state to path state, and decrease pointer by 1.
13967
47
          state = state::PATH;
13968
47
        }
13969
13970
569
        break;
13971
3.90k
      }
13972
522
      case state::FILE_HOST: {
13973
522
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13974
522
        std::string_view view = url_data.substr(input_position);
13975
13976
522
        size_t location = view.find_first_of("/\\?");
13977
522
        std::string_view file_host_buffer(
13978
522
            view.data(),
13979
522
            (location != std::string_view::npos) ? location : view.size());
13980
13981
522
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13982
2
          state = state::PATH;
13983
520
        } else if (file_host_buffer.empty()) {
13984
          // Set url's host to the empty string.
13985
          if constexpr (result_type_is_ada_url) {
13986
            url.host = "";
13987
7
          } else {
13988
7
            url.update_base_hostname("");
13989
7
          }
13990
          // Set state to path start state.
13991
7
          state = state::PATH_START;
13992
513
        } else {
13993
513
          size_t consumed_bytes = file_host_buffer.size();
13994
513
          input_position += consumed_bytes;
13995
          // Let host be the result of host parsing buffer with url is not
13996
          // special.
13997
513
          if (!url.parse_host(file_host_buffer)) {
13998
167
            return url;
13999
167
          }
14000
14001
          if constexpr (result_type_is_ada_url) {
14002
            // If host is "localhost", then set host to the empty string.
14003
            if (url.host.has_value() && url.host.value() == "localhost") {
14004
              url.host = "";
14005
            }
14006
346
          } else {
14007
346
            if (url.get_hostname() == "localhost") {
14008
3
              url.update_base_hostname("");
14009
3
            }
14010
346
          }
14011
14012
          // Set buffer to the empty string and state to path start state.
14013
346
          state = state::PATH_START;
14014
346
        }
14015
14016
355
        break;
14017
522
      }
14018
1.16k
      case state::FILE: {
14019
1.16k
        ada_log("FILE ", helpers::substring(url_data, input_position));
14020
1.16k
        std::string_view file_view = url_data.substr(input_position);
14021
14022
1.16k
        url.set_protocol_as_file();
14023
        if constexpr (result_type_is_ada_url) {
14024
          // Set url's host to the empty string.
14025
          url.host = "";
14026
1.16k
        } else {
14027
1.16k
          url.update_base_hostname("");
14028
1.16k
        }
14029
        // If c is U+002F (/) or U+005C (\), then:
14030
1.16k
        if (input_position != input_size &&
14031
1.15k
            (url_data[input_position] == '/' ||
14032
619
             url_data[input_position] == '\\')) {
14033
569
          ada_log("FILE c is U+002F or U+005C");
14034
          // Set state to file slash state.
14035
569
          state = state::FILE_SLASH;
14036
569
        }
14037
        // Otherwise, if base is non-null and base's scheme is "file":
14038
600
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
14039
          // Set url's host to base's host, url's path to a clone of base's
14040
          // path, and url's query to base's query.
14041
0
          ada_log("FILE base non-null");
14042
          if constexpr (result_type_is_ada_url) {
14043
            url.host = base_url->host;
14044
            url.path = base_url->path;
14045
            url.query = base_url->query;
14046
0
          } else {
14047
0
            url.update_host_to_base_host(base_url->get_hostname());
14048
0
            url.update_base_pathname(base_url->get_pathname());
14049
0
            url.update_base_search(base_url->get_search());
14050
0
          }
14051
0
          url.has_opaque_path = base_url->has_opaque_path;
14052
14053
          // If c is U+003F (?), then set url's query to the empty string and
14054
          // state to query state.
14055
0
          if (input_position != input_size && url_data[input_position] == '?') {
14056
0
            state = state::QUERY;
14057
0
          }
14058
          // Otherwise, if c is not the EOF code point:
14059
0
          else if (input_position != input_size) {
14060
            // Set url's query to null.
14061
0
            url.clear_search();
14062
            // If the code point substring from pointer to the end of input does
14063
            // not start with a Windows drive letter, then shorten url's path.
14064
0
            if (!checkers::is_windows_drive_letter(file_view)) {
14065
              if constexpr (result_type_is_ada_url) {
14066
                helpers::shorten_path(url.path, url.type);
14067
0
              } else {
14068
0
                std::string_view path = url.get_pathname();
14069
0
                if (helpers::shorten_path(path, url.type)) {
14070
0
                  url.update_base_pathname(std::move(std::string(path)));
14071
0
                }
14072
0
              }
14073
0
            }
14074
            // Otherwise:
14075
0
            else {
14076
              // Set url's path to an empty list.
14077
0
              url.clear_pathname();
14078
0
              url.has_opaque_path = true;
14079
0
            }
14080
14081
            // Set state to path state and decrease pointer by 1.
14082
0
            state = state::PATH;
14083
0
            break;
14084
0
          }
14085
0
        }
14086
        // Otherwise, set state to path state, and decrease pointer by 1.
14087
600
        else {
14088
600
          ada_log("FILE go to path");
14089
600
          state = state::PATH;
14090
600
          break;
14091
600
        }
14092
14093
569
        input_position++;
14094
569
        break;
14095
1.16k
      }
14096
0
      default:
14097
0
        unreachable();
14098
43.9k
    }
14099
43.9k
  }
14100
  if constexpr (store_values) {
14101
    if (fragment.has_value()) {
14102
      url.update_unencoded_base_hash(*fragment);
14103
    }
14104
  }
14105
3.18k
  return url;
14106
8.59k
}
14107
14108
template url parse_url_impl(std::string_view user_input,
14109
                            const url* base_url = nullptr);
14110
template url_aggregator parse_url_impl(
14111
    std::string_view user_input, const url_aggregator* base_url = nullptr);
14112
14113
template <class result_type>
14114
result_type parse_url(std::string_view user_input,
14115
0
                      const result_type* base_url) {
14116
0
  return parse_url_impl<result_type, true>(user_input, base_url);
14117
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*)
14118
14119
template url parse_url<url>(std::string_view user_input,
14120
                            const url* base_url = nullptr);
14121
template url_aggregator parse_url<url_aggregator>(
14122
    std::string_view user_input, const url_aggregator* base_url = nullptr);
14123
}  // namespace ada::parser
14124
/* end file src/parser.cpp */
14125
/* begin file src/url_components.cpp */
14126
14127
#include <iterator>
14128
#include <string>
14129
14130
namespace ada {
14131
14132
0
[[nodiscard]] std::string url_components::to_string() const {
14133
0
  std::string answer;
14134
0
  auto back = std::back_insert_iterator(answer);
14135
0
  answer.append("{\n");
14136
14137
0
  answer.append("\t\"protocol_end\":\"");
14138
0
  helpers::encode_json(std::to_string(protocol_end), back);
14139
0
  answer.append("\",\n");
14140
14141
0
  answer.append("\t\"username_end\":\"");
14142
0
  helpers::encode_json(std::to_string(username_end), back);
14143
0
  answer.append("\",\n");
14144
14145
0
  answer.append("\t\"host_start\":\"");
14146
0
  helpers::encode_json(std::to_string(host_start), back);
14147
0
  answer.append("\",\n");
14148
14149
0
  answer.append("\t\"host_end\":\"");
14150
0
  helpers::encode_json(std::to_string(host_end), back);
14151
0
  answer.append("\",\n");
14152
14153
0
  answer.append("\t\"port\":\"");
14154
0
  helpers::encode_json(std::to_string(port), back);
14155
0
  answer.append("\",\n");
14156
14157
0
  answer.append("\t\"pathname_start\":\"");
14158
0
  helpers::encode_json(std::to_string(pathname_start), back);
14159
0
  answer.append("\",\n");
14160
14161
0
  answer.append("\t\"search_start\":\"");
14162
0
  helpers::encode_json(std::to_string(search_start), back);
14163
0
  answer.append("\",\n");
14164
14165
0
  answer.append("\t\"hash_start\":\"");
14166
0
  helpers::encode_json(std::to_string(hash_start), back);
14167
0
  answer.append("\",\n");
14168
14169
0
  answer.append("\n}");
14170
0
  return answer;
14171
0
}
14172
14173
}  // namespace ada
14174
/* end file src/url_components.cpp */
14175
/* begin file src/url_aggregator.cpp */
14176
14177
#include <iterator>
14178
#include <ranges>
14179
#include <string>
14180
#include <string_view>
14181
14182
namespace ada {
14183
template <bool has_state_override>
14184
[[nodiscard]] ada_really_inline bool url_aggregator::parse_scheme_with_colon(
14185
30.3k
    const std::string_view input_with_colon) {
14186
30.3k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14187
30.3k
  ADA_ASSERT_TRUE(validate());
14188
30.3k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14189
30.3k
  std::string_view input{input_with_colon};
14190
30.3k
  input.remove_suffix(1);
14191
30.3k
  auto parsed_type = ada::scheme::get_scheme_type(input);
14192
30.3k
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
14193
  /**
14194
   * In the common case, we will immediately recognize a special scheme (e.g.,
14195
   *http, https), in which case, we can go really fast.
14196
   **/
14197
30.3k
  if (is_input_special) {  // fast path!!!
14198
12.1k
    if constexpr (has_state_override) {
14199
      // If url's scheme is not a special scheme and buffer is a special scheme,
14200
      // then return.
14201
2.28k
      if (is_special() != is_input_special) {
14202
0
        return false;
14203
0
      }
14204
14205
      // If url includes credentials or has a non-null port, and buffer is
14206
      // "file", then return.
14207
2.28k
      if ((has_credentials() || components.port != url_components::omitted) &&
14208
524
          parsed_type == ada::scheme::type::FILE) {
14209
0
        return false;
14210
0
      }
14211
14212
      // If url's scheme is "file" and its host is an empty host, then return.
14213
      // An empty host is the empty string.
14214
2.28k
      if (type == ada::scheme::type::FILE &&
14215
534
          components.host_start == components.host_end) {
14216
354
        return false;
14217
354
      }
14218
2.28k
    }
14219
14220
1.93k
    type = parsed_type;
14221
12.1k
    set_scheme_from_view_with_colon(input_with_colon);
14222
14223
12.1k
    if constexpr (has_state_override) {
14224
      // This is uncommon.
14225
2.28k
      uint16_t urls_scheme_port = get_special_port();
14226
14227
      // If url's port is url's scheme's default port, then set url's port to
14228
      // null.
14229
2.28k
      if (components.port == urls_scheme_port) {
14230
0
        clear_port();
14231
0
      }
14232
2.28k
    }
14233
18.2k
  } else {  // slow path
14234
18.2k
    std::string _buffer(input);
14235
    // Next function is only valid if the input is ASCII and returns false
14236
    // otherwise, but it seems that we always have ascii content so we do not
14237
    // need to check the return value.
14238
18.2k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14239
14240
18.2k
    if constexpr (has_state_override) {
14241
      // If url's scheme is a special scheme and buffer is not a special scheme,
14242
      // then return. If url's scheme is not a special scheme and buffer is a
14243
      // special scheme, then return.
14244
3.74k
      if (is_special() != ada::scheme::is_special(_buffer)) {
14245
0
        return true;
14246
0
      }
14247
14248
      // If url includes credentials or has a non-null port, and buffer is
14249
      // "file", then return.
14250
3.74k
      if ((has_credentials() || components.port != url_components::omitted) &&
14251
561
          _buffer == "file") {
14252
0
        return true;
14253
0
      }
14254
14255
      // If url's scheme is "file" and its host is an empty host, then return.
14256
      // An empty host is the empty string.
14257
3.74k
      if (type == ada::scheme::type::FILE &&
14258
429
          components.host_start == components.host_end) {
14259
271
        return true;
14260
271
      }
14261
3.74k
    }
14262
14263
3.47k
    set_scheme(_buffer);
14264
14265
18.2k
    if constexpr (has_state_override) {
14266
      // This is uncommon.
14267
3.74k
      uint16_t urls_scheme_port = get_special_port();
14268
14269
      // If url's port is url's scheme's default port, then set url's port to
14270
      // null.
14271
3.74k
      if (components.port == urls_scheme_port) {
14272
50
        clear_port();
14273
50
      }
14274
3.74k
    }
14275
18.2k
  }
14276
0
  ADA_ASSERT_TRUE(validate());
14277
30.3k
  return true;
14278
30.3k
}
bool ada::url_aggregator::parse_scheme_with_colon<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14185
24.3k
    const std::string_view input_with_colon) {
14186
24.3k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14187
24.3k
  ADA_ASSERT_TRUE(validate());
14188
24.3k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14189
24.3k
  std::string_view input{input_with_colon};
14190
24.3k
  input.remove_suffix(1);
14191
24.3k
  auto parsed_type = ada::scheme::get_scheme_type(input);
14192
24.3k
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
14193
  /**
14194
   * In the common case, we will immediately recognize a special scheme (e.g.,
14195
   *http, https), in which case, we can go really fast.
14196
   **/
14197
24.3k
  if (is_input_special) {  // fast path!!!
14198
    if constexpr (has_state_override) {
14199
      // If url's scheme is not a special scheme and buffer is a special scheme,
14200
      // then return.
14201
      if (is_special() != is_input_special) {
14202
        return false;
14203
      }
14204
14205
      // If url includes credentials or has a non-null port, and buffer is
14206
      // "file", then return.
14207
      if ((has_credentials() || components.port != url_components::omitted) &&
14208
          parsed_type == ada::scheme::type::FILE) {
14209
        return false;
14210
      }
14211
14212
      // If url's scheme is "file" and its host is an empty host, then return.
14213
      // An empty host is the empty string.
14214
      if (type == ada::scheme::type::FILE &&
14215
          components.host_start == components.host_end) {
14216
        return false;
14217
      }
14218
    }
14219
14220
9.85k
    type = parsed_type;
14221
9.85k
    set_scheme_from_view_with_colon(input_with_colon);
14222
14223
    if constexpr (has_state_override) {
14224
      // This is uncommon.
14225
      uint16_t urls_scheme_port = get_special_port();
14226
14227
      // If url's port is url's scheme's default port, then set url's port to
14228
      // null.
14229
      if (components.port == urls_scheme_port) {
14230
        clear_port();
14231
      }
14232
    }
14233
14.4k
  } else {  // slow path
14234
14.4k
    std::string _buffer(input);
14235
    // Next function is only valid if the input is ASCII and returns false
14236
    // otherwise, but it seems that we always have ascii content so we do not
14237
    // need to check the return value.
14238
14.4k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14239
14240
    if constexpr (has_state_override) {
14241
      // If url's scheme is a special scheme and buffer is not a special scheme,
14242
      // then return. If url's scheme is not a special scheme and buffer is a
14243
      // special scheme, then return.
14244
      if (is_special() != ada::scheme::is_special(_buffer)) {
14245
        return true;
14246
      }
14247
14248
      // If url includes credentials or has a non-null port, and buffer is
14249
      // "file", then return.
14250
      if ((has_credentials() || components.port != url_components::omitted) &&
14251
          _buffer == "file") {
14252
        return true;
14253
      }
14254
14255
      // If url's scheme is "file" and its host is an empty host, then return.
14256
      // An empty host is the empty string.
14257
      if (type == ada::scheme::type::FILE &&
14258
          components.host_start == components.host_end) {
14259
        return true;
14260
      }
14261
    }
14262
14263
14.4k
    set_scheme(_buffer);
14264
14265
    if constexpr (has_state_override) {
14266
      // This is uncommon.
14267
      uint16_t urls_scheme_port = get_special_port();
14268
14269
      // If url's port is url's scheme's default port, then set url's port to
14270
      // null.
14271
      if (components.port == urls_scheme_port) {
14272
        clear_port();
14273
      }
14274
    }
14275
14.4k
  }
14276
24.3k
  ADA_ASSERT_TRUE(validate());
14277
24.3k
  return true;
14278
24.3k
}
bool ada::url_aggregator::parse_scheme_with_colon<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14185
6.03k
    const std::string_view input_with_colon) {
14186
6.03k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14187
6.03k
  ADA_ASSERT_TRUE(validate());
14188
6.03k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14189
6.03k
  std::string_view input{input_with_colon};
14190
6.03k
  input.remove_suffix(1);
14191
6.03k
  auto parsed_type = ada::scheme::get_scheme_type(input);
14192
6.03k
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
14193
  /**
14194
   * In the common case, we will immediately recognize a special scheme (e.g.,
14195
   *http, https), in which case, we can go really fast.
14196
   **/
14197
6.03k
  if (is_input_special) {  // fast path!!!
14198
2.28k
    if constexpr (has_state_override) {
14199
      // If url's scheme is not a special scheme and buffer is a special scheme,
14200
      // then return.
14201
2.28k
      if (is_special() != is_input_special) {
14202
0
        return false;
14203
0
      }
14204
14205
      // If url includes credentials or has a non-null port, and buffer is
14206
      // "file", then return.
14207
2.28k
      if ((has_credentials() || components.port != url_components::omitted) &&
14208
524
          parsed_type == ada::scheme::type::FILE) {
14209
0
        return false;
14210
0
      }
14211
14212
      // If url's scheme is "file" and its host is an empty host, then return.
14213
      // An empty host is the empty string.
14214
2.28k
      if (type == ada::scheme::type::FILE &&
14215
534
          components.host_start == components.host_end) {
14216
354
        return false;
14217
354
      }
14218
2.28k
    }
14219
14220
1.93k
    type = parsed_type;
14221
2.28k
    set_scheme_from_view_with_colon(input_with_colon);
14222
14223
2.28k
    if constexpr (has_state_override) {
14224
      // This is uncommon.
14225
2.28k
      uint16_t urls_scheme_port = get_special_port();
14226
14227
      // If url's port is url's scheme's default port, then set url's port to
14228
      // null.
14229
2.28k
      if (components.port == urls_scheme_port) {
14230
0
        clear_port();
14231
0
      }
14232
2.28k
    }
14233
3.74k
  } else {  // slow path
14234
3.74k
    std::string _buffer(input);
14235
    // Next function is only valid if the input is ASCII and returns false
14236
    // otherwise, but it seems that we always have ascii content so we do not
14237
    // need to check the return value.
14238
3.74k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14239
14240
3.74k
    if constexpr (has_state_override) {
14241
      // If url's scheme is a special scheme and buffer is not a special scheme,
14242
      // then return. If url's scheme is not a special scheme and buffer is a
14243
      // special scheme, then return.
14244
3.74k
      if (is_special() != ada::scheme::is_special(_buffer)) {
14245
0
        return true;
14246
0
      }
14247
14248
      // If url includes credentials or has a non-null port, and buffer is
14249
      // "file", then return.
14250
3.74k
      if ((has_credentials() || components.port != url_components::omitted) &&
14251
561
          _buffer == "file") {
14252
0
        return true;
14253
0
      }
14254
14255
      // If url's scheme is "file" and its host is an empty host, then return.
14256
      // An empty host is the empty string.
14257
3.74k
      if (type == ada::scheme::type::FILE &&
14258
429
          components.host_start == components.host_end) {
14259
271
        return true;
14260
271
      }
14261
3.74k
    }
14262
14263
3.47k
    set_scheme(_buffer);
14264
14265
3.74k
    if constexpr (has_state_override) {
14266
      // This is uncommon.
14267
3.74k
      uint16_t urls_scheme_port = get_special_port();
14268
14269
      // If url's port is url's scheme's default port, then set url's port to
14270
      // null.
14271
3.74k
      if (components.port == urls_scheme_port) {
14272
50
        clear_port();
14273
50
      }
14274
3.74k
    }
14275
3.74k
  }
14276
0
  ADA_ASSERT_TRUE(validate());
14277
6.03k
  return true;
14278
6.03k
}
14279
14280
0
inline void url_aggregator::copy_scheme(const url_aggregator& u) {
14281
0
  ada_log("url_aggregator::copy_scheme ", u.buffer);
14282
0
  ADA_ASSERT_TRUE(validate());
14283
  // next line could overflow but unsigned arithmetic has well-defined
14284
  // overflows.
14285
0
  uint32_t new_difference = u.components.protocol_end - components.protocol_end;
14286
0
  type = u.type;
14287
0
  buffer.erase(0, components.protocol_end);
14288
0
  buffer.insert(0, u.get_protocol());
14289
0
  components.protocol_end = u.components.protocol_end;
14290
14291
  // No need to update the components
14292
0
  if (new_difference == 0) {
14293
0
    return;
14294
0
  }
14295
14296
  // Update the rest of the components.
14297
0
  components.username_end += new_difference;
14298
0
  components.host_start += new_difference;
14299
0
  components.host_end += new_difference;
14300
0
  components.pathname_start += new_difference;
14301
0
  if (components.search_start != url_components::omitted) {
14302
0
    components.search_start += new_difference;
14303
0
  }
14304
0
  if (components.hash_start != url_components::omitted) {
14305
0
    components.hash_start += new_difference;
14306
0
  }
14307
0
  ADA_ASSERT_TRUE(validate());
14308
0
}
14309
14310
inline void url_aggregator::set_scheme_from_view_with_colon(
14311
11.7k
    std::string_view new_scheme_with_colon) {
14312
11.7k
  ada_log("url_aggregator::set_scheme_from_view_with_colon ",
14313
11.7k
          new_scheme_with_colon);
14314
11.7k
  ADA_ASSERT_TRUE(validate());
14315
11.7k
  ADA_ASSERT_TRUE(!new_scheme_with_colon.empty() &&
14316
11.7k
                  new_scheme_with_colon.back() == ':');
14317
  // next line could overflow but unsigned arithmetic has well-defined
14318
  // overflows.
14319
11.7k
  uint32_t new_difference =
14320
11.7k
      uint32_t(new_scheme_with_colon.size()) - components.protocol_end;
14321
14322
11.7k
  if (buffer.empty()) {
14323
9.85k
    buffer.append(new_scheme_with_colon);
14324
9.85k
  } else {
14325
1.93k
    buffer.erase(0, components.protocol_end);
14326
1.93k
    buffer.insert(0, new_scheme_with_colon);
14327
1.93k
  }
14328
11.7k
  components.protocol_end += new_difference;
14329
14330
  // Update the rest of the components.
14331
11.7k
  components.username_end += new_difference;
14332
11.7k
  components.host_start += new_difference;
14333
11.7k
  components.host_end += new_difference;
14334
11.7k
  components.pathname_start += new_difference;
14335
11.7k
  if (components.search_start != url_components::omitted) {
14336
70
    components.search_start += new_difference;
14337
70
  }
14338
11.7k
  if (components.hash_start != url_components::omitted) {
14339
84
    components.hash_start += new_difference;
14340
84
  }
14341
11.7k
  ADA_ASSERT_TRUE(validate());
14342
11.7k
}
14343
14344
17.9k
inline void url_aggregator::set_scheme(std::string_view new_scheme) {
14345
17.9k
  ada_log("url_aggregator::set_scheme ", new_scheme);
14346
17.9k
  ADA_ASSERT_TRUE(validate());
14347
17.9k
  ADA_ASSERT_TRUE(new_scheme.empty() || new_scheme.back() != ':');
14348
  // next line could overflow but unsigned arithmetic has well-defined
14349
  // overflows.
14350
17.9k
  uint32_t new_difference =
14351
17.9k
      uint32_t(new_scheme.size()) - components.protocol_end + 1;
14352
14353
17.9k
  type = ada::scheme::get_scheme_type(new_scheme);
14354
17.9k
  if (buffer.empty()) {
14355
14.4k
    buffer.append(helpers::concat(new_scheme, ":"));
14356
14.4k
  } else {
14357
3.47k
    buffer.erase(0, components.protocol_end);
14358
3.47k
    buffer.insert(0, helpers::concat(new_scheme, ":"));
14359
3.47k
  }
14360
17.9k
  components.protocol_end = uint32_t(new_scheme.size() + 1);
14361
14362
  // Update the rest of the components.
14363
17.9k
  components.username_end += new_difference;
14364
17.9k
  components.host_start += new_difference;
14365
17.9k
  components.host_end += new_difference;
14366
17.9k
  components.pathname_start += new_difference;
14367
17.9k
  if (components.search_start != url_components::omitted) {
14368
299
    components.search_start += new_difference;
14369
299
  }
14370
17.9k
  if (components.hash_start != url_components::omitted) {
14371
191
    components.hash_start += new_difference;
14372
191
  }
14373
17.9k
  ADA_ASSERT_TRUE(validate());
14374
17.9k
}
14375
14376
6.55k
bool url_aggregator::set_protocol(const std::string_view input) {
14377
6.55k
  ada_log("url_aggregator::set_protocol ", input);
14378
6.55k
  ADA_ASSERT_TRUE(validate());
14379
6.55k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14380
6.55k
  std::string view(input);
14381
6.55k
  helpers::remove_ascii_tab_or_newline(view);
14382
6.55k
  if (view.empty()) {
14383
0
    return true;
14384
0
  }
14385
14386
  // Schemes should start with alpha values.
14387
6.55k
  if (!checkers::is_alpha(view[0])) {
14388
522
    return false;
14389
522
  }
14390
14391
6.03k
  view.append(":");
14392
14393
6.03k
  std::string::iterator pointer =
14394
6.03k
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
14395
14396
6.03k
  if (pointer != view.end() && *pointer == ':') {
14397
6.03k
    return parse_scheme_with_colon<true>(
14398
6.03k
        view.substr(0, pointer - view.begin() + 1));
14399
6.03k
  }
14400
0
  return false;
14401
6.03k
}
14402
14403
6.55k
bool url_aggregator::set_username(const std::string_view input) {
14404
6.55k
  ada_log("url_aggregator::set_username '", input, "' ");
14405
6.55k
  ADA_ASSERT_TRUE(validate());
14406
6.55k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14407
6.55k
  if (cannot_have_credentials_or_port()) {
14408
2.27k
    return false;
14409
2.27k
  }
14410
4.28k
  size_t idx = ada::unicode::percent_encode_index(
14411
4.28k
      input, character_sets::USERINFO_PERCENT_ENCODE);
14412
4.28k
  if (idx == input.size()) {
14413
0
    update_base_username(input);
14414
4.28k
  } else {
14415
    // We only create a temporary string if we have to!
14416
4.28k
    update_base_username(ada::unicode::percent_encode(
14417
4.28k
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14418
4.28k
  }
14419
4.28k
  ADA_ASSERT_TRUE(validate());
14420
4.28k
  return true;
14421
6.55k
}
14422
14423
6.55k
bool url_aggregator::set_password(const std::string_view input) {
14424
6.55k
  ada_log("url_aggregator::set_password '", input, "'");
14425
6.55k
  ADA_ASSERT_TRUE(validate());
14426
6.55k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14427
6.55k
  if (cannot_have_credentials_or_port()) {
14428
2.27k
    return false;
14429
2.27k
  }
14430
4.28k
  size_t idx = ada::unicode::percent_encode_index(
14431
4.28k
      input, character_sets::USERINFO_PERCENT_ENCODE);
14432
4.28k
  if (idx == input.size()) {
14433
0
    update_base_password(input);
14434
4.28k
  } else {
14435
    // We only create a temporary string if we have to!
14436
4.28k
    update_base_password(ada::unicode::percent_encode(
14437
4.28k
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14438
4.28k
  }
14439
4.28k
  ADA_ASSERT_TRUE(validate());
14440
4.28k
  return true;
14441
6.55k
}
14442
14443
10.5k
bool url_aggregator::set_port(const std::string_view input) {
14444
10.5k
  ada_log("url_aggregator::set_port ", input);
14445
10.5k
  ADA_ASSERT_TRUE(validate());
14446
10.5k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14447
10.5k
  if (cannot_have_credentials_or_port()) {
14448
2.27k
    return false;
14449
2.27k
  }
14450
14451
8.24k
  if (input.empty()) {
14452
0
    clear_port();
14453
0
    return true;
14454
0
  }
14455
14456
8.24k
  std::string trimmed(input);
14457
8.24k
  helpers::remove_ascii_tab_or_newline(trimmed);
14458
14459
8.24k
  if (trimmed.empty()) {
14460
0
    return true;
14461
0
  }
14462
14463
  // Input should not start with a non-digit character.
14464
8.24k
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
14465
7.32k
    return false;
14466
7.32k
  }
14467
14468
  // Find the first non-digit character to determine the length of digits
14469
919
  auto first_non_digit =
14470
919
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
14471
919
  std::string_view digits_to_parse =
14472
919
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
14473
14474
  // Revert changes if parse_port fails.
14475
919
  uint32_t previous_port = components.port;
14476
919
  parse_port(digits_to_parse);
14477
919
  if (is_valid) {
14478
810
    return true;
14479
810
  }
14480
109
  update_base_port(previous_port);
14481
109
  is_valid = true;
14482
109
  ADA_ASSERT_TRUE(validate());
14483
109
  return false;
14484
919
}
14485
14486
6.55k
bool url_aggregator::set_pathname(const std::string_view input) {
14487
6.55k
  ada_log("url_aggregator::set_pathname ", input);
14488
6.55k
  ADA_ASSERT_TRUE(validate());
14489
6.55k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14490
6.55k
  if (has_opaque_path) {
14491
1.24k
    return false;
14492
1.24k
  }
14493
5.31k
  clear_pathname();
14494
5.31k
  parse_path(input);
14495
5.31k
  if (get_pathname().starts_with("//") && !has_authority() && !has_dash_dot()) {
14496
0
    buffer.insert(components.pathname_start, "/.");
14497
0
    components.pathname_start += 2;
14498
0
    if (components.search_start != url_components::omitted) {
14499
0
      components.search_start += 2;
14500
0
    }
14501
0
    if (components.hash_start != url_components::omitted) {
14502
0
      components.hash_start += 2;
14503
0
    }
14504
0
  }
14505
5.31k
  ADA_ASSERT_TRUE(validate());
14506
5.31k
  return true;
14507
6.55k
}
14508
14509
5.31k
ada_really_inline void url_aggregator::parse_path(std::string_view input) {
14510
5.31k
  ada_log("url_aggregator::parse_path ", input);
14511
5.31k
  ADA_ASSERT_TRUE(validate());
14512
5.31k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14513
5.31k
  std::string tmp_buffer;
14514
5.31k
  std::string_view internal_input;
14515
5.31k
  if (unicode::has_tabs_or_newline(input)) {
14516
230
    tmp_buffer = input;
14517
    // Optimization opportunity: Instead of copying and then pruning, we could
14518
    // just directly build the string from user_input.
14519
230
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
14520
230
    internal_input = tmp_buffer;
14521
5.08k
  } else {
14522
5.08k
    internal_input = input;
14523
5.08k
  }
14524
14525
  // If url is special, then:
14526
5.31k
  if (is_special()) {
14527
4.17k
    if (internal_input.empty()) {
14528
0
      update_base_pathname("/");
14529
4.17k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
14530
0
      consume_prepared_path(internal_input.substr(1));
14531
4.17k
    } else {
14532
4.17k
      consume_prepared_path(internal_input);
14533
4.17k
    }
14534
4.17k
  } else if (!internal_input.empty()) {
14535
1.14k
    if (internal_input[0] == '/') {
14536
0
      consume_prepared_path(internal_input.substr(1));
14537
1.14k
    } else {
14538
1.14k
      consume_prepared_path(internal_input);
14539
1.14k
    }
14540
1.14k
  } else {
14541
    // Non-special URLs with an empty host can have their paths erased
14542
    // Path-only URLs cannot have their paths erased
14543
0
    if (components.host_start == components.host_end && !has_authority()) {
14544
0
      update_base_pathname("/");
14545
0
    }
14546
0
  }
14547
5.31k
  ADA_ASSERT_TRUE(validate());
14548
5.31k
}
14549
14550
6.55k
void url_aggregator::set_search(const std::string_view input) {
14551
6.55k
  ada_log("url_aggregator::set_search ", input);
14552
6.55k
  ADA_ASSERT_TRUE(validate());
14553
6.55k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14554
6.55k
  if (input.empty()) {
14555
0
    clear_search();
14556
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
14557
0
    return;
14558
0
  }
14559
14560
6.55k
  std::string new_value;
14561
6.55k
  new_value = input[0] == '?' ? input.substr(1) : input;
14562
6.55k
  helpers::remove_ascii_tab_or_newline(new_value);
14563
14564
6.55k
  auto query_percent_encode_set =
14565
6.55k
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
14566
6.55k
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
14567
14568
6.55k
  update_base_search(new_value, query_percent_encode_set);
14569
6.55k
  ADA_ASSERT_TRUE(validate());
14570
6.55k
}
14571
14572
6.55k
void url_aggregator::set_hash(const std::string_view input) {
14573
6.55k
  ada_log("url_aggregator::set_hash ", input);
14574
6.55k
  ADA_ASSERT_TRUE(validate());
14575
6.55k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14576
6.55k
  if (input.empty()) {
14577
0
    if (components.hash_start != url_components::omitted) {
14578
0
      buffer.resize(components.hash_start);
14579
0
      components.hash_start = url_components::omitted;
14580
0
    }
14581
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
14582
0
    return;
14583
0
  }
14584
14585
6.55k
  std::string new_value;
14586
6.55k
  new_value = input[0] == '#' ? input.substr(1) : input;
14587
6.55k
  helpers::remove_ascii_tab_or_newline(new_value);
14588
6.55k
  update_unencoded_base_hash(new_value);
14589
6.55k
  ADA_ASSERT_TRUE(validate());
14590
6.55k
}
14591
14592
6.55k
bool url_aggregator::set_href(const std::string_view input) {
14593
6.55k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14594
6.55k
  ada_log("url_aggregator::set_href ", input, " [", input.size(), " bytes]");
14595
6.55k
  ada::result<url_aggregator> out = ada::parse<url_aggregator>(input);
14596
6.55k
  ada_log("url_aggregator::set_href, success :", out.has_value());
14597
14598
6.55k
  if (out) {
14599
6.55k
    ada_log("url_aggregator::set_href, parsed ", out->to_string());
14600
    // TODO: Figure out why the following line puts test to never finish.
14601
6.55k
    *this = *out;
14602
6.55k
  }
14603
14604
6.55k
  return out.has_value();
14605
6.55k
}
14606
14607
22.1k
ada_really_inline bool url_aggregator::parse_host(std::string_view input) {
14608
22.1k
  ada_log("url_aggregator:parse_host \"", input, "\" [", input.size(),
14609
22.1k
          " bytes]");
14610
22.1k
  ADA_ASSERT_TRUE(validate());
14611
22.1k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14612
22.1k
  if (input.empty()) {
14613
16
    return is_valid = false;
14614
16
  }  // technically unnecessary.
14615
  // If input starts with U+005B ([), then:
14616
22.1k
  if (input[0] == '[') {
14617
    // If input does not end with U+005D (]), validation error, return failure.
14618
836
    if (input.back() != ']') {
14619
366
      return is_valid = false;
14620
366
    }
14621
470
    ada_log("parse_host ipv6");
14622
14623
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
14624
    // trailing U+005D (]) removed.
14625
470
    input.remove_prefix(1);
14626
470
    input.remove_suffix(1);
14627
470
    return parse_ipv6(input);
14628
836
  }
14629
14630
  // If isNotSpecial is true, then return the result of opaque-host parsing
14631
  // input.
14632
21.2k
  if (!is_special()) {
14633
2.22k
    return parse_opaque_host(input);
14634
2.22k
  }
14635
  // Let domain be the result of running UTF-8 decode without BOM on the
14636
  // percent-decoding of input. Let asciiDomain be the result of running domain
14637
  // to ASCII with domain and false. The most common case is an ASCII input, in
14638
  // which case we do not need to call the expensive 'to_ascii' if a few
14639
  // conditions are met: no '%' and no 'xn-' subsequence.
14640
14641
  // Often, the input does not contain any forbidden code points, and no upper
14642
  // case ASCII letter, then we can just copy it to the buffer. We want to
14643
  // optimize for such a common case.
14644
14645
  // Fast path: try to parse as pure decimal IPv4(a.b.c.d) first.
14646
19.0k
  const uint64_t fast_result = checkers::try_parse_ipv4_fast(input);
14647
19.0k
  if (fast_result < checkers::ipv4_fast_fail) {
14648
    // Fast path succeeded - input is pure decimal IPv4
14649
46
    if (!input.empty() && input.back() == '.') {
14650
24
      update_base_hostname(input.substr(0, input.size() - 1));
14651
24
    } else {
14652
22
      update_base_hostname(input);
14653
22
    }
14654
46
    host_type = IPV4;
14655
46
    ada_log("parse_host fast path decimal ipv4");
14656
46
    ADA_ASSERT_TRUE(validate());
14657
46
    return true;
14658
46
  }
14659
19.0k
  uint8_t is_forbidden_or_upper =
14660
19.0k
      unicode::contains_forbidden_domain_code_point_or_upper(input.data(),
14661
19.0k
                                                             input.size());
14662
  // Minor optimization opportunity:
14663
  // contains_forbidden_domain_code_point_or_upper could be extend to check for
14664
  // the presence of characters that cannot appear in the ipv4 address and we
14665
  // could also check whether x and n and - are present, and so we could skip
14666
  // some of the checks below. However, the gains are likely to be small, and
14667
  // the code would be more complex.
14668
19.0k
  if (is_forbidden_or_upper == 0 &&
14669
7.44k
      input.find("xn-") == std::string_view::npos) {
14670
    // fast path
14671
6.92k
    update_base_hostname(input);
14672
14673
    // Check for other IPv4 formats (hex, octal, etc.)
14674
6.92k
    if (checkers::is_ipv4(get_hostname())) {
14675
2.79k
      ada_log("parse_host fast path ipv4");
14676
2.79k
      return parse_ipv4(get_hostname(), true);
14677
2.79k
    }
14678
4.12k
    ada_log("parse_host fast path ", get_hostname());
14679
4.12k
    return true;
14680
6.92k
  }
14681
  // We have encountered at least one forbidden code point or the input contains
14682
  // 'xn-' (case insensitive), so we need to call 'to_ascii' to perform the full
14683
  // conversion.
14684
14685
12.0k
  ada_log("parse_host calling to_ascii");
14686
12.0k
  std::optional<std::string> host = std::string(get_hostname());
14687
12.0k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
14688
12.0k
  if (!is_valid) {
14689
4.52k
    ada_log("parse_host to_ascii returns false");
14690
4.52k
    return is_valid = false;
14691
4.52k
  }
14692
7.55k
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
14693
7.55k
          " bytes]");
14694
14695
7.55k
  if (std::ranges::any_of(host.value(),
14696
7.55k
                          ada::unicode::is_forbidden_domain_code_point)) {
14697
0
    return is_valid = false;
14698
0
  }
14699
14700
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
14701
  // asciiDomain.
14702
7.55k
  if (checkers::is_ipv4(host.value())) {
14703
621
    ada_log("parse_host got ipv4 ", *host);
14704
621
    return parse_ipv4(host.value(), false);
14705
621
  }
14706
14707
6.93k
  update_base_hostname(host.value());
14708
6.93k
  ADA_ASSERT_TRUE(validate());
14709
6.93k
  return true;
14710
7.55k
}
14711
14712
template <bool override_hostname>
14713
13.1k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14714
13.1k
  ada_log("url_aggregator::set_host_or_hostname ", input);
14715
13.1k
  ADA_ASSERT_TRUE(validate());
14716
13.1k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14717
13.1k
  if (has_opaque_path) {
14718
2.48k
    return false;
14719
2.48k
  }
14720
14721
10.6k
  std::string previous_host(get_hostname());
14722
10.6k
  uint32_t previous_port = components.port;
14723
14724
10.6k
  size_t host_end_pos = input.find('#');
14725
10.6k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14726
10.6k
                                      ? host_end_pos
14727
10.6k
                                      : input.size());
14728
10.6k
  helpers::remove_ascii_tab_or_newline(_host);
14729
10.6k
  std::string_view new_host(_host);
14730
14731
  // If url's scheme is "file", then set state to file host state, instead of
14732
  // host state.
14733
10.6k
  if (type != ada::scheme::type::FILE) {
14734
8.62k
    std::string_view host_view(_host.data(), _host.length());
14735
8.62k
    auto [location, found_colon] =
14736
8.62k
        helpers::get_host_delimiter_location(is_special(), host_view);
14737
14738
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14739
    // Note: the 'found_colon' value is true if and only if a colon was
14740
    // encountered while not inside brackets.
14741
8.62k
    if (found_colon) {
14742
      // If buffer is the empty string, host-missing validation error, return
14743
      // failure.
14744
8.62k
      std::string_view host_buffer = host_view.substr(0, location);
14745
8.62k
      if (host_buffer.empty()) {
14746
0
        return false;
14747
0
      }
14748
14749
      // If state override is given and state override is hostname state, then
14750
      // return failure.
14751
8.62k
      if constexpr (override_hostname) {
14752
4.31k
        return false;
14753
4.31k
      }
14754
14755
      // Let host be the result of host parsing buffer with url is not special.
14756
0
      bool succeeded = parse_host(host_buffer);
14757
8.62k
      if (!succeeded) {
14758
347
        update_base_hostname(previous_host);
14759
347
        update_base_port(previous_port);
14760
347
        return false;
14761
347
      }
14762
14763
      // Set url's host to host, buffer to the empty string, and state to port
14764
      // state.
14765
8.27k
      std::string_view port_buffer = new_host.substr(location + 1);
14766
8.27k
      if (!port_buffer.empty()) {
14767
3.96k
        set_port(port_buffer);
14768
3.96k
      }
14769
8.27k
      return true;
14770
8.62k
    }
14771
    // Otherwise, if one of the following is true:
14772
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14773
    // - url is special and c is U+005C (\)
14774
0
    else {
14775
      // If url is special and host_view is the empty string, host-missing
14776
      // validation error, return failure.
14777
0
      if (host_view.empty() && is_special()) {
14778
0
        return false;
14779
0
      }
14780
14781
      // Otherwise, if state override is given, host_view is the empty string,
14782
      // and either url includes credentials or url's port is non-null, then
14783
      // return failure.
14784
0
      if (host_view.empty() && (has_credentials() || has_port())) {
14785
0
        return false;
14786
0
      }
14787
14788
      // Let host be the result of host parsing host_view with url is not
14789
      // special.
14790
0
      if (host_view.empty() && !is_special()) {
14791
0
        if (has_hostname()) {
14792
0
          clear_hostname();  // easy!
14793
0
        } else if (has_dash_dot()) {
14794
0
          add_authority_slashes_if_needed();
14795
0
          delete_dash_dot();
14796
0
        }
14797
0
        return true;
14798
0
      }
14799
14800
0
      bool succeeded = parse_host(host_view);
14801
0
      if (!succeeded) {
14802
0
        update_base_hostname(previous_host);
14803
0
        update_base_port(previous_port);
14804
0
        return false;
14805
0
      } else if (has_dash_dot()) {
14806
        // Should remove dash_dot from pathname
14807
0
        delete_dash_dot();
14808
0
      }
14809
0
      return true;
14810
0
    }
14811
8.62k
  }
14812
14813
2.00k
  size_t location = new_host.find_first_of("/\\?");
14814
2.00k
  if (location != std::string_view::npos) {
14815
1.19k
    new_host.remove_suffix(new_host.length() - location);
14816
1.19k
  }
14817
14818
2.00k
  if (new_host.empty()) {
14819
    // Set url's host to the empty string.
14820
0
    clear_hostname();
14821
2.00k
  } else {
14822
    // Let host be the result of host parsing buffer with url is not special.
14823
2.00k
    if (!parse_host(new_host)) {
14824
2.00k
      update_base_hostname(previous_host);
14825
2.00k
      update_base_port(previous_port);
14826
2.00k
      return false;
14827
2.00k
    }
14828
14829
    // If host is "localhost", then set host to the empty string.
14830
0
    if (helpers::substring(buffer, components.host_start,
14831
0
                           components.host_end) == "localhost") {
14832
0
      clear_hostname();
14833
0
    }
14834
0
  }
14835
0
  ADA_ASSERT_TRUE(validate());
14836
0
  return true;
14837
2.00k
}
bool ada::url_aggregator::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14713
6.55k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14714
6.55k
  ada_log("url_aggregator::set_host_or_hostname ", input);
14715
6.55k
  ADA_ASSERT_TRUE(validate());
14716
6.55k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14717
6.55k
  if (has_opaque_path) {
14718
1.24k
    return false;
14719
1.24k
  }
14720
14721
5.31k
  std::string previous_host(get_hostname());
14722
5.31k
  uint32_t previous_port = components.port;
14723
14724
5.31k
  size_t host_end_pos = input.find('#');
14725
5.31k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14726
5.31k
                                      ? host_end_pos
14727
5.31k
                                      : input.size());
14728
5.31k
  helpers::remove_ascii_tab_or_newline(_host);
14729
5.31k
  std::string_view new_host(_host);
14730
14731
  // If url's scheme is "file", then set state to file host state, instead of
14732
  // host state.
14733
5.31k
  if (type != ada::scheme::type::FILE) {
14734
4.31k
    std::string_view host_view(_host.data(), _host.length());
14735
4.31k
    auto [location, found_colon] =
14736
4.31k
        helpers::get_host_delimiter_location(is_special(), host_view);
14737
14738
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14739
    // Note: the 'found_colon' value is true if and only if a colon was
14740
    // encountered while not inside brackets.
14741
4.31k
    if (found_colon) {
14742
      // If buffer is the empty string, host-missing validation error, return
14743
      // failure.
14744
4.31k
      std::string_view host_buffer = host_view.substr(0, location);
14745
4.31k
      if (host_buffer.empty()) {
14746
0
        return false;
14747
0
      }
14748
14749
      // If state override is given and state override is hostname state, then
14750
      // return failure.
14751
      if constexpr (override_hostname) {
14752
        return false;
14753
      }
14754
14755
      // Let host be the result of host parsing buffer with url is not special.
14756
4.31k
      bool succeeded = parse_host(host_buffer);
14757
4.31k
      if (!succeeded) {
14758
347
        update_base_hostname(previous_host);
14759
347
        update_base_port(previous_port);
14760
347
        return false;
14761
347
      }
14762
14763
      // Set url's host to host, buffer to the empty string, and state to port
14764
      // state.
14765
3.96k
      std::string_view port_buffer = new_host.substr(location + 1);
14766
3.96k
      if (!port_buffer.empty()) {
14767
3.96k
        set_port(port_buffer);
14768
3.96k
      }
14769
3.96k
      return true;
14770
4.31k
    }
14771
    // Otherwise, if one of the following is true:
14772
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14773
    // - url is special and c is U+005C (\)
14774
0
    else {
14775
      // If url is special and host_view is the empty string, host-missing
14776
      // validation error, return failure.
14777
0
      if (host_view.empty() && is_special()) {
14778
0
        return false;
14779
0
      }
14780
14781
      // Otherwise, if state override is given, host_view is the empty string,
14782
      // and either url includes credentials or url's port is non-null, then
14783
      // return failure.
14784
0
      if (host_view.empty() && (has_credentials() || has_port())) {
14785
0
        return false;
14786
0
      }
14787
14788
      // Let host be the result of host parsing host_view with url is not
14789
      // special.
14790
0
      if (host_view.empty() && !is_special()) {
14791
0
        if (has_hostname()) {
14792
0
          clear_hostname();  // easy!
14793
0
        } else if (has_dash_dot()) {
14794
0
          add_authority_slashes_if_needed();
14795
0
          delete_dash_dot();
14796
0
        }
14797
0
        return true;
14798
0
      }
14799
14800
0
      bool succeeded = parse_host(host_view);
14801
0
      if (!succeeded) {
14802
0
        update_base_hostname(previous_host);
14803
0
        update_base_port(previous_port);
14804
0
        return false;
14805
0
      } else if (has_dash_dot()) {
14806
        // Should remove dash_dot from pathname
14807
0
        delete_dash_dot();
14808
0
      }
14809
0
      return true;
14810
0
    }
14811
4.31k
  }
14812
14813
1.00k
  size_t location = new_host.find_first_of("/\\?");
14814
1.00k
  if (location != std::string_view::npos) {
14815
598
    new_host.remove_suffix(new_host.length() - location);
14816
598
  }
14817
14818
1.00k
  if (new_host.empty()) {
14819
    // Set url's host to the empty string.
14820
0
    clear_hostname();
14821
1.00k
  } else {
14822
    // Let host be the result of host parsing buffer with url is not special.
14823
1.00k
    if (!parse_host(new_host)) {
14824
1.00k
      update_base_hostname(previous_host);
14825
1.00k
      update_base_port(previous_port);
14826
1.00k
      return false;
14827
1.00k
    }
14828
14829
    // If host is "localhost", then set host to the empty string.
14830
0
    if (helpers::substring(buffer, components.host_start,
14831
0
                           components.host_end) == "localhost") {
14832
0
      clear_hostname();
14833
0
    }
14834
0
  }
14835
0
  ADA_ASSERT_TRUE(validate());
14836
0
  return true;
14837
1.00k
}
bool ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14713
6.55k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14714
6.55k
  ada_log("url_aggregator::set_host_or_hostname ", input);
14715
6.55k
  ADA_ASSERT_TRUE(validate());
14716
6.55k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14717
6.55k
  if (has_opaque_path) {
14718
1.24k
    return false;
14719
1.24k
  }
14720
14721
5.31k
  std::string previous_host(get_hostname());
14722
5.31k
  uint32_t previous_port = components.port;
14723
14724
5.31k
  size_t host_end_pos = input.find('#');
14725
5.31k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14726
5.31k
                                      ? host_end_pos
14727
5.31k
                                      : input.size());
14728
5.31k
  helpers::remove_ascii_tab_or_newline(_host);
14729
5.31k
  std::string_view new_host(_host);
14730
14731
  // If url's scheme is "file", then set state to file host state, instead of
14732
  // host state.
14733
5.31k
  if (type != ada::scheme::type::FILE) {
14734
4.31k
    std::string_view host_view(_host.data(), _host.length());
14735
4.31k
    auto [location, found_colon] =
14736
4.31k
        helpers::get_host_delimiter_location(is_special(), host_view);
14737
14738
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14739
    // Note: the 'found_colon' value is true if and only if a colon was
14740
    // encountered while not inside brackets.
14741
4.31k
    if (found_colon) {
14742
      // If buffer is the empty string, host-missing validation error, return
14743
      // failure.
14744
4.31k
      std::string_view host_buffer = host_view.substr(0, location);
14745
4.31k
      if (host_buffer.empty()) {
14746
0
        return false;
14747
0
      }
14748
14749
      // If state override is given and state override is hostname state, then
14750
      // return failure.
14751
4.31k
      if constexpr (override_hostname) {
14752
4.31k
        return false;
14753
4.31k
      }
14754
14755
      // Let host be the result of host parsing buffer with url is not special.
14756
0
      bool succeeded = parse_host(host_buffer);
14757
4.31k
      if (!succeeded) {
14758
0
        update_base_hostname(previous_host);
14759
0
        update_base_port(previous_port);
14760
0
        return false;
14761
0
      }
14762
14763
      // Set url's host to host, buffer to the empty string, and state to port
14764
      // state.
14765
4.31k
      std::string_view port_buffer = new_host.substr(location + 1);
14766
4.31k
      if (!port_buffer.empty()) {
14767
0
        set_port(port_buffer);
14768
0
      }
14769
4.31k
      return true;
14770
4.31k
    }
14771
    // Otherwise, if one of the following is true:
14772
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14773
    // - url is special and c is U+005C (\)
14774
0
    else {
14775
      // If url is special and host_view is the empty string, host-missing
14776
      // validation error, return failure.
14777
0
      if (host_view.empty() && is_special()) {
14778
0
        return false;
14779
0
      }
14780
14781
      // Otherwise, if state override is given, host_view is the empty string,
14782
      // and either url includes credentials or url's port is non-null, then
14783
      // return failure.
14784
0
      if (host_view.empty() && (has_credentials() || has_port())) {
14785
0
        return false;
14786
0
      }
14787
14788
      // Let host be the result of host parsing host_view with url is not
14789
      // special.
14790
0
      if (host_view.empty() && !is_special()) {
14791
0
        if (has_hostname()) {
14792
0
          clear_hostname();  // easy!
14793
0
        } else if (has_dash_dot()) {
14794
0
          add_authority_slashes_if_needed();
14795
0
          delete_dash_dot();
14796
0
        }
14797
0
        return true;
14798
0
      }
14799
14800
0
      bool succeeded = parse_host(host_view);
14801
0
      if (!succeeded) {
14802
0
        update_base_hostname(previous_host);
14803
0
        update_base_port(previous_port);
14804
0
        return false;
14805
0
      } else if (has_dash_dot()) {
14806
        // Should remove dash_dot from pathname
14807
0
        delete_dash_dot();
14808
0
      }
14809
0
      return true;
14810
0
    }
14811
4.31k
  }
14812
14813
1.00k
  size_t location = new_host.find_first_of("/\\?");
14814
1.00k
  if (location != std::string_view::npos) {
14815
598
    new_host.remove_suffix(new_host.length() - location);
14816
598
  }
14817
14818
1.00k
  if (new_host.empty()) {
14819
    // Set url's host to the empty string.
14820
0
    clear_hostname();
14821
1.00k
  } else {
14822
    // Let host be the result of host parsing buffer with url is not special.
14823
1.00k
    if (!parse_host(new_host)) {
14824
1.00k
      update_base_hostname(previous_host);
14825
1.00k
      update_base_port(previous_port);
14826
1.00k
      return false;
14827
1.00k
    }
14828
14829
    // If host is "localhost", then set host to the empty string.
14830
0
    if (helpers::substring(buffer, components.host_start,
14831
0
                           components.host_end) == "localhost") {
14832
0
      clear_hostname();
14833
0
    }
14834
0
  }
14835
0
  ADA_ASSERT_TRUE(validate());
14836
0
  return true;
14837
1.00k
}
14838
14839
6.55k
bool url_aggregator::set_host(const std::string_view input) {
14840
6.55k
  ada_log("url_aggregator::set_host '", input, "'");
14841
6.55k
  ADA_ASSERT_TRUE(validate());
14842
6.55k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14843
6.55k
  return set_host_or_hostname<false>(input);
14844
6.55k
}
14845
14846
6.55k
bool url_aggregator::set_hostname(const std::string_view input) {
14847
6.55k
  ada_log("url_aggregator::set_hostname '", input, "'");
14848
6.55k
  ADA_ASSERT_TRUE(validate());
14849
6.55k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14850
6.55k
  return set_host_or_hostname<true>(input);
14851
6.55k
}
14852
14853
6.55k
[[nodiscard]] std::string url_aggregator::get_origin() const {
14854
6.55k
  ada_log("url_aggregator::get_origin");
14855
6.55k
  if (is_special()) {
14856
    // Return a new opaque origin.
14857
4.17k
    if (type == scheme::FILE) {
14858
1.00k
      return "null";
14859
1.00k
    }
14860
14861
3.17k
    return helpers::concat(get_protocol(), "//", get_host());
14862
4.17k
  }
14863
14864
2.38k
  if (get_protocol() == "blob:") {
14865
872
    std::string_view path = get_pathname();
14866
872
    if (!path.empty()) {
14867
868
      auto out = ada::parse<ada::url_aggregator>(path);
14868
868
      if (out && (out->type == scheme::HTTP || out->type == scheme::HTTPS)) {
14869
        // If pathURL's scheme is not "http" and not "https", then return a
14870
        // new opaque origin.
14871
37
        return helpers::concat(out->get_protocol(), "//", out->get_host());
14872
37
      }
14873
868
    }
14874
872
  }
14875
14876
  // Return a new opaque origin.
14877
2.34k
  return "null";
14878
2.38k
}
14879
14880
[[nodiscard]] std::string_view url_aggregator::get_username() const
14881
6.55k
    ada_lifetime_bound {
14882
6.55k
  ada_log("url_aggregator::get_username");
14883
6.55k
  if (has_non_empty_username()) {
14884
4.28k
    return helpers::substring(buffer, components.protocol_end + 2,
14885
4.28k
                              components.username_end);
14886
4.28k
  }
14887
2.27k
  return "";
14888
6.55k
}
14889
14890
[[nodiscard]] std::string_view url_aggregator::get_password() const
14891
6.55k
    ada_lifetime_bound {
14892
6.55k
  ada_log("url_aggregator::get_password");
14893
6.55k
  if (has_non_empty_password()) {
14894
4.28k
    return helpers::substring(buffer, components.username_end + 1,
14895
4.28k
                              components.host_start);
14896
4.28k
  }
14897
2.27k
  return "";
14898
6.55k
}
14899
14900
[[nodiscard]] std::string_view url_aggregator::get_port() const
14901
6.55k
    ada_lifetime_bound {
14902
6.55k
  ada_log("url_aggregator::get_port");
14903
6.55k
  if (components.port == url_components::omitted) {
14904
5.72k
    return "";
14905
5.72k
  }
14906
828
  return helpers::substring(buffer, components.host_end + 1,
14907
828
                            components.pathname_start);
14908
6.55k
}
14909
14910
[[nodiscard]] std::string_view url_aggregator::get_hash() const
14911
6.55k
    ada_lifetime_bound {
14912
6.55k
  ada_log("url_aggregator::get_hash");
14913
  // If this's URL's fragment is either null or the empty string, then return
14914
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
14915
6.55k
  if (components.hash_start == url_components::omitted) {
14916
0
    return "";
14917
0
  }
14918
6.55k
  if (buffer.size() - components.hash_start <= 1) {
14919
0
    return "";
14920
0
  }
14921
6.55k
  return helpers::substring(buffer, components.hash_start);
14922
6.55k
}
14923
14924
[[nodiscard]] std::string_view url_aggregator::get_host() const
14925
9.76k
    ada_lifetime_bound {
14926
9.76k
  ada_log("url_aggregator::get_host");
14927
  // Technically, we should check if there is a hostname, but
14928
  // the code below works even if there isn't.
14929
  // if(!has_hostname()) { return ""; }
14930
9.76k
  size_t start = components.host_start;
14931
9.76k
  if (components.host_end > components.host_start &&
14932
7.83k
      buffer[components.host_start] == '@') {
14933
7.46k
    start++;
14934
7.46k
  }
14935
  // if we have an empty host, then the space between components.host_end and
14936
  // components.pathname_start may be occupied by /.
14937
9.76k
  if (start == components.host_end) {
14938
1.93k
    return {};
14939
1.93k
  }
14940
7.83k
  return helpers::substring(buffer, start, components.pathname_start);
14941
9.76k
}
14942
14943
[[nodiscard]] std::string_view url_aggregator::get_hostname() const
14944
40.0k
    ada_lifetime_bound {
14945
40.0k
  ada_log("url_aggregator::get_hostname");
14946
  // Technically, we should check if there is a hostname, but
14947
  // the code below works even if there isn't.
14948
  // if(!has_hostname()) { return ""; }
14949
40.0k
  size_t start = components.host_start;
14950
  // So host_start is not where the host begins.
14951
40.0k
  if (components.host_end > components.host_start &&
14952
26.1k
      buffer[components.host_start] == '@') {
14953
6.01k
    start++;
14954
6.01k
  }
14955
40.0k
  return helpers::substring(buffer, start, components.host_end);
14956
40.0k
}
14957
14958
[[nodiscard]] std::string_view url_aggregator::get_search() const
14959
6.55k
    ada_lifetime_bound {
14960
6.55k
  ada_log("url_aggregator::get_search");
14961
  // If this's URL's query is either null or the empty string, then return the
14962
  // empty string. Return U+003F (?), followed by this's URL's query.
14963
6.55k
  if (components.search_start == url_components::omitted) {
14964
0
    return "";
14965
0
  }
14966
6.55k
  auto ending_index = uint32_t(buffer.size());
14967
6.55k
  if (components.hash_start != url_components::omitted) {
14968
6.55k
    ending_index = components.hash_start;
14969
6.55k
  }
14970
6.55k
  if (ending_index - components.search_start <= 1) {
14971
0
    return "";
14972
0
  }
14973
6.55k
  return helpers::substring(buffer, components.search_start, ending_index);
14974
6.55k
}
14975
14976
[[nodiscard]] std::string_view url_aggregator::get_protocol() const
14977
12.1k
    ada_lifetime_bound {
14978
12.1k
  ada_log("url_aggregator::get_protocol");
14979
12.1k
  return helpers::substring(buffer, 0, components.protocol_end);
14980
12.1k
}
14981
14982
0
[[nodiscard]] std::string ada::url_aggregator::to_string() const {
14983
0
  ada_log("url_aggregator::to_string buffer:", buffer, " [", buffer.size(),
14984
0
          " bytes]");
14985
0
  if (!is_valid) {
14986
0
    return "null";
14987
0
  }
14988
14989
0
  std::string answer;
14990
0
  auto back = std::back_insert_iterator(answer);
14991
0
  answer.append("{\n");
14992
14993
0
  answer.append("\t\"buffer\":\"");
14994
0
  helpers::encode_json(buffer, back);
14995
0
  answer.append("\",\n");
14996
14997
0
  answer.append("\t\"protocol\":\"");
14998
0
  helpers::encode_json(get_protocol(), back);
14999
0
  answer.append("\",\n");
15000
15001
0
  if (has_credentials()) {
15002
0
    answer.append("\t\"username\":\"");
15003
0
    helpers::encode_json(get_username(), back);
15004
0
    answer.append("\",\n");
15005
0
    answer.append("\t\"password\":\"");
15006
0
    helpers::encode_json(get_password(), back);
15007
0
    answer.append("\",\n");
15008
0
  }
15009
15010
0
  answer.append("\t\"host\":\"");
15011
0
  helpers::encode_json(get_host(), back);
15012
0
  answer.append("\",\n");
15013
15014
0
  answer.append("\t\"path\":\"");
15015
0
  helpers::encode_json(get_pathname(), back);
15016
0
  answer.append("\",\n");
15017
0
  answer.append("\t\"opaque path\":");
15018
0
  answer.append((has_opaque_path ? "true" : "false"));
15019
0
  answer.append(",\n");
15020
15021
0
  if (components.search_start != url_components::omitted) {
15022
0
    answer.append("\t\"query\":\"");
15023
0
    helpers::encode_json(get_search(), back);
15024
0
    answer.append("\",\n");
15025
0
  }
15026
0
  if (components.hash_start != url_components::omitted) {
15027
0
    answer.append("\t\"fragment\":\"");
15028
0
    helpers::encode_json(get_hash(), back);
15029
0
    answer.append("\",\n");
15030
0
  }
15031
15032
0
  auto convert_offset_to_string = [](uint32_t offset) -> std::string {
15033
0
    if (offset == url_components::omitted) {
15034
0
      return "null";
15035
0
    } else {
15036
0
      return std::to_string(offset);
15037
0
    }
15038
0
  };
15039
15040
0
  answer.append("\t\"protocol_end\":");
15041
0
  answer.append(convert_offset_to_string(components.protocol_end));
15042
0
  answer.append(",\n");
15043
15044
0
  answer.append("\t\"username_end\":");
15045
0
  answer.append(convert_offset_to_string(components.username_end));
15046
0
  answer.append(",\n");
15047
15048
0
  answer.append("\t\"host_start\":");
15049
0
  answer.append(convert_offset_to_string(components.host_start));
15050
0
  answer.append(",\n");
15051
15052
0
  answer.append("\t\"host_end\":");
15053
0
  answer.append(convert_offset_to_string(components.host_end));
15054
0
  answer.append(",\n");
15055
15056
0
  answer.append("\t\"port\":");
15057
0
  answer.append(convert_offset_to_string(components.port));
15058
0
  answer.append(",\n");
15059
15060
0
  answer.append("\t\"pathname_start\":");
15061
0
  answer.append(convert_offset_to_string(components.pathname_start));
15062
0
  answer.append(",\n");
15063
15064
0
  answer.append("\t\"search_start\":");
15065
0
  answer.append(convert_offset_to_string(components.search_start));
15066
0
  answer.append(",\n");
15067
15068
0
  answer.append("\t\"hash_start\":");
15069
0
  answer.append(convert_offset_to_string(components.hash_start));
15070
0
  answer.append("\n}");
15071
15072
0
  return answer;
15073
0
}
15074
15075
0
[[nodiscard]] bool url_aggregator::has_valid_domain() const noexcept {
15076
0
  if (components.host_start == components.host_end) {
15077
0
    return false;
15078
0
  }
15079
0
  return checkers::verify_dns_length(get_hostname());
15080
0
}
15081
15082
3.42k
bool url_aggregator::parse_ipv4(std::string_view input, bool in_place) {
15083
3.42k
  ada_log("parse_ipv4 ", input, " [", input.size(),
15084
3.42k
          " bytes], overlaps with buffer: ",
15085
3.42k
          helpers::overlaps(input, buffer) ? "yes" : "no");
15086
3.42k
  ADA_ASSERT_TRUE(validate());
15087
3.42k
  const bool trailing_dot = (input.back() == '.');
15088
3.42k
  if (trailing_dot) {
15089
66
    input.remove_suffix(1);
15090
66
  }
15091
3.42k
  size_t digit_count{0};
15092
3.42k
  int pure_decimal_count = 0;  // entries that are decimal
15093
3.42k
  uint64_t ipv4{0};
15094
  // we could unroll for better performance?
15095
3.90k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
15096
3.89k
    uint32_t
15097
3.89k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
15098
3.89k
    bool is_hex = checkers::has_hex_prefix(input);
15099
3.89k
    if (is_hex && ((input.length() == 2) ||
15100
927
                   ((input.length() > 2) && (input[2] == '.')))) {
15101
      // special case
15102
57
      segment_result = 0;
15103
57
      input.remove_prefix(2);
15104
3.83k
    } else {
15105
3.83k
      std::from_chars_result r{};
15106
3.83k
      if (is_hex) {
15107
906
        ada_log("parse_ipv4 trying to parse hex number");
15108
906
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
15109
906
                            segment_result, 16);
15110
2.93k
      } else if ((input.length() >= 2) && input[0] == '0' &&
15111
687
                 checkers::is_digit(input[1])) {
15112
605
        ada_log("parse_ipv4 trying to parse octal number");
15113
605
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
15114
605
                            segment_result, 8);
15115
2.32k
      } else {
15116
2.32k
        ada_log("parse_ipv4 trying to parse decimal number");
15117
2.32k
        pure_decimal_count++;
15118
2.32k
        r = std::from_chars(input.data(), input.data() + input.size(),
15119
2.32k
                            segment_result, 10);
15120
2.32k
      }
15121
3.83k
      if (r.ec != std::errc()) {
15122
488
        ada_log("parse_ipv4 parsing failed");
15123
488
        return is_valid = false;
15124
488
      }
15125
3.35k
      ada_log("parse_ipv4 parsed ", segment_result);
15126
3.35k
      input.remove_prefix(r.ptr - input.data());
15127
3.35k
    }
15128
3.40k
    if (input.empty()) {
15129
      // We have the last value.
15130
      // At this stage, ipv4 contains digit_count*8 bits.
15131
      // So we have 32-digit_count*8 bits left.
15132
2.72k
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
15133
41
        return is_valid = false;
15134
41
      }
15135
2.68k
      ipv4 <<= (32 - digit_count * 8);
15136
2.68k
      ipv4 |= segment_result;
15137
2.68k
      goto final;
15138
2.72k
    } else {
15139
      // There is more, so that the value must no be larger than 255
15140
      // and we must have a '.'.
15141
686
      if ((segment_result > 255) || (input[0] != '.')) {
15142
203
        return is_valid = false;
15143
203
      }
15144
483
      ipv4 <<= 8;
15145
483
      ipv4 |= segment_result;
15146
483
      input.remove_prefix(1);  // remove '.'
15147
483
    }
15148
3.40k
  }
15149
7
  if ((digit_count != 4) || (!input.empty())) {
15150
7
    ada_log("parse_ipv4 found invalid (more than 4 numbers or empty) ");
15151
7
    return is_valid = false;
15152
7
  }
15153
2.68k
final:
15154
2.68k
  ada_log("url_aggregator::parse_ipv4 completed ", get_href(),
15155
2.68k
          " host: ", get_host());
15156
15157
  // We could also check r.ptr to see where the parsing ended.
15158
2.68k
  if (in_place && pure_decimal_count == 4 && !trailing_dot) {
15159
0
    ada_log(
15160
0
        "url_aggregator::parse_ipv4 completed and was already correct in the "
15161
0
        "buffer");
15162
    // The original input was already all decimal and we validated it. So we
15163
    // don't need to do anything.
15164
2.68k
  } else {
15165
2.68k
    ada_log("url_aggregator::parse_ipv4 completed and we need to update it");
15166
    // Optimization opportunity: Get rid of unnecessary string return in ipv4
15167
    // serializer.
15168
    // TODO: This is likely a bug because it goes back update_base_hostname, not
15169
    // what we want to do.
15170
2.68k
    update_base_hostname(
15171
2.68k
        ada::serializers::ipv4(ipv4));  // We have to reserialize the address.
15172
2.68k
  }
15173
2.68k
  host_type = IPV4;
15174
2.68k
  ADA_ASSERT_TRUE(validate());
15175
2.68k
  return true;
15176
7
}
15177
15178
470
bool url_aggregator::parse_ipv6(std::string_view input) {
15179
  // TODO: Implement in_place optimization: we know that input points
15180
  // in the buffer, so we can just check whether the buffer is already
15181
  // well formatted.
15182
  // TODO: Find a way to merge parse_ipv6 with url.cpp implementation.
15183
470
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
15184
470
  ADA_ASSERT_TRUE(validate());
15185
470
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15186
470
  if (input.empty()) {
15187
29
    return is_valid = false;
15188
29
  }
15189
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
15190
441
  std::array<uint16_t, 8> address{};
15191
15192
  // Let pieceIndex be 0.
15193
441
  int piece_index = 0;
15194
15195
  // Let compress be null.
15196
441
  std::optional<int> compress{};
15197
15198
  // Let pointer be a pointer for input.
15199
441
  std::string_view::iterator pointer = input.begin();
15200
15201
  // If c is U+003A (:), then:
15202
441
  if (input[0] == ':') {
15203
    // If remaining does not start with U+003A (:), validation error, return
15204
    // failure.
15205
104
    if (input.size() == 1 || input[1] != ':') {
15206
14
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
15207
14
      return is_valid = false;
15208
14
    }
15209
15210
    // Increase pointer by 2.
15211
90
    pointer += 2;
15212
15213
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
15214
90
    compress = ++piece_index;
15215
90
  }
15216
15217
  // While c is not the EOF code point:
15218
1.24k
  while (pointer != input.end()) {
15219
    // If pieceIndex is 8, validation error, return failure.
15220
1.01k
    if (piece_index == 8) {
15221
3
      ada_log("parse_ipv6 piece_index == 8");
15222
3
      return is_valid = false;
15223
3
    }
15224
15225
    // If c is U+003A (:), then:
15226
1.00k
    if (*pointer == ':') {
15227
      // If compress is non-null, validation error, return failure.
15228
143
      if (compress.has_value()) {
15229
5
        ada_log("parse_ipv6 compress is non-null");
15230
5
        return is_valid = false;
15231
5
      }
15232
15233
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
15234
      // then continue.
15235
138
      pointer++;
15236
138
      compress = ++piece_index;
15237
138
      continue;
15238
143
    }
15239
15240
    // Let value and length be 0.
15241
866
    uint16_t value = 0, length = 0;
15242
15243
    // While length is less than 4 and c is an ASCII hex digit,
15244
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
15245
    // increase pointer and length by 1.
15246
2.24k
    while (length < 4 && pointer != input.end() &&
15247
2.02k
           unicode::is_ascii_hex_digit(*pointer)) {
15248
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
15249
1.38k
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
15250
1.38k
      pointer++;
15251
1.38k
      length++;
15252
1.38k
    }
15253
15254
    // If c is U+002E (.), then:
15255
866
    if (pointer != input.end() && *pointer == '.') {
15256
      // If length is 0, validation error, return failure.
15257
89
      if (length == 0) {
15258
3
        ada_log("parse_ipv6 length is 0");
15259
3
        return is_valid = false;
15260
3
      }
15261
15262
      // Decrease pointer by length.
15263
86
      pointer -= length;
15264
15265
      // If pieceIndex is greater than 6, validation error, return failure.
15266
86
      if (piece_index > 6) {
15267
5
        ada_log("parse_ipv6 piece_index > 6");
15268
5
        return is_valid = false;
15269
5
      }
15270
15271
      // Let numbersSeen be 0.
15272
81
      int numbers_seen = 0;
15273
15274
      // While c is not the EOF code point:
15275
230
      while (pointer != input.end()) {
15276
        // Let ipv4Piece be null.
15277
202
        std::optional<uint16_t> ipv4_piece{};
15278
15279
        // If numbersSeen is greater than 0, then:
15280
202
        if (numbers_seen > 0) {
15281
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
15282
          // pointer by 1.
15283
121
          if (*pointer == '.' && numbers_seen < 4) {
15284
111
            pointer++;
15285
111
          } else {
15286
            // Otherwise, validation error, return failure.
15287
10
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
15288
10
            return is_valid = false;
15289
10
          }
15290
121
        }
15291
15292
        // If c is not an ASCII digit, validation error, return failure.
15293
192
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
15294
26
          ada_log(
15295
26
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
15296
26
              "failure");
15297
26
          return is_valid = false;
15298
26
        }
15299
15300
        // While c is an ASCII digit:
15301
432
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
15302
          // Let number be c interpreted as decimal number.
15303
283
          int number = *pointer - '0';
15304
15305
          // If ipv4Piece is null, then set ipv4Piece to number.
15306
283
          if (!ipv4_piece.has_value()) {
15307
166
            ipv4_piece = number;
15308
166
          }
15309
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
15310
117
          else if (ipv4_piece == 0) {
15311
5
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
15312
5
            return is_valid = false;
15313
5
          }
15314
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
15315
112
          else {
15316
112
            ipv4_piece = *ipv4_piece * 10 + number;
15317
112
          }
15318
15319
          // If ipv4Piece is greater than 255, validation error, return failure.
15320
278
          if (ipv4_piece > 255) {
15321
12
            ada_log("parse_ipv6 ipv4_piece > 255");
15322
12
            return is_valid = false;
15323
12
          }
15324
15325
          // Increase pointer by 1.
15326
266
          pointer++;
15327
266
        }
15328
15329
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
15330
        // ipv4Piece.
15331
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
15332
149
        address[piece_index] =
15333
149
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
15334
15335
        // Increase numbersSeen by 1.
15336
149
        numbers_seen++;
15337
15338
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
15339
149
        if (numbers_seen == 2 || numbers_seen == 4) {
15340
58
          piece_index++;
15341
58
        }
15342
149
      }
15343
15344
      // If numbersSeen is not 4, validation error, return failure.
15345
28
      if (numbers_seen != 4) {
15346
11
        return is_valid = false;
15347
11
      }
15348
15349
      // Break.
15350
17
      break;
15351
28
    }
15352
    // Otherwise, if c is U+003A (:):
15353
777
    else if ((pointer != input.end()) && (*pointer == ':')) {
15354
      // Increase pointer by 1.
15355
529
      pointer++;
15356
15357
      // If c is the EOF code point, validation error, return failure.
15358
529
      if (pointer == input.end()) {
15359
3
        ada_log(
15360
3
            "parse_ipv6 If c is the EOF code point, validation error, return "
15361
3
            "failure");
15362
3
        return is_valid = false;
15363
3
      }
15364
529
    }
15365
    // Otherwise, if c is not the EOF code point, validation error, return
15366
    // failure.
15367
248
    else if (pointer != input.end()) {
15368
94
      ada_log(
15369
94
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
15370
94
          "error, return failure");
15371
94
      return is_valid = false;
15372
94
    }
15373
15374
    // Set address[pieceIndex] to value.
15375
680
    address[piece_index] = value;
15376
15377
    // Increase pieceIndex by 1.
15378
680
    piece_index++;
15379
680
  }
15380
15381
  // If compress is non-null, then:
15382
250
  if (compress.has_value()) {
15383
    // Let swaps be pieceIndex - compress.
15384
210
    int swaps = piece_index - *compress;
15385
15386
    // Set pieceIndex to 7.
15387
210
    piece_index = 7;
15388
15389
    // While pieceIndex is not 0 and swaps is greater than 0,
15390
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
15391
    // decrease both pieceIndex and swaps by 1.
15392
507
    while (piece_index != 0 && swaps > 0) {
15393
297
      std::swap(address[piece_index], address[*compress + swaps - 1]);
15394
297
      piece_index--;
15395
297
      swaps--;
15396
297
    }
15397
210
  }
15398
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
15399
  // return failure.
15400
40
  else if (piece_index != 8) {
15401
31
    ada_log(
15402
31
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
15403
31
        "error, return failure");
15404
31
    return is_valid = false;
15405
31
  }
15406
  // TODO: Optimization opportunity: Get rid of unnecessary string creation.
15407
  // TODO: This is likely a bug because it goes back update_base_hostname, not
15408
  // what we want to do.
15409
219
  update_base_hostname(ada::serializers::ipv6(address));
15410
219
  ada_log("parse_ipv6 ", get_hostname());
15411
219
  ADA_ASSERT_TRUE(validate());
15412
219
  host_type = IPV6;
15413
219
  return true;
15414
250
}
15415
15416
2.22k
bool url_aggregator::parse_opaque_host(std::string_view input) {
15417
2.22k
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
15418
2.22k
  ADA_ASSERT_TRUE(validate());
15419
2.22k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15420
2.22k
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
15421
205
    return is_valid = false;
15422
205
  }
15423
15424
  // Return the result of running UTF-8 percent-encode on input using the C0
15425
  // control percent-encode set.
15426
2.02k
  size_t idx = ada::unicode::percent_encode_index(
15427
2.02k
      input, character_sets::C0_CONTROL_PERCENT_ENCODE);
15428
2.02k
  if (idx == input.size()) {
15429
1.31k
    update_base_hostname(input);
15430
1.31k
  } else {
15431
    // We only create a temporary string if we need to.
15432
704
    update_base_hostname(ada::unicode::percent_encode(
15433
704
        input, character_sets::C0_CONTROL_PERCENT_ENCODE, idx));
15434
704
  }
15435
2.02k
  ADA_ASSERT_TRUE(validate());
15436
2.02k
  return true;
15437
2.22k
}
15438
15439
0
[[nodiscard]] std::string url_aggregator::to_diagram() const {
15440
0
  if (!is_valid) {
15441
0
    return "invalid";
15442
0
  }
15443
0
  std::string answer;
15444
0
  answer.append(buffer);
15445
0
  answer.append(" [");
15446
0
  answer.append(std::to_string(buffer.size()));
15447
0
  answer.append(" bytes]");
15448
0
  answer.append("\n");
15449
  // first line
15450
0
  std::string line1;
15451
0
  line1.resize(buffer.size(), ' ');
15452
0
  if (components.hash_start != url_components::omitted) {
15453
0
    line1[components.hash_start] = '|';
15454
0
  }
15455
0
  if (components.search_start != url_components::omitted) {
15456
0
    line1[components.search_start] = '|';
15457
0
  }
15458
0
  if (components.pathname_start != buffer.size()) {
15459
0
    line1[components.pathname_start] = '|';
15460
0
  }
15461
0
  if (components.host_end != buffer.size()) {
15462
0
    line1[components.host_end] = '|';
15463
0
  }
15464
0
  if (components.host_start != buffer.size()) {
15465
0
    line1[components.host_start] = '|';
15466
0
  }
15467
0
  if (components.username_end != buffer.size()) {
15468
0
    line1[components.username_end] = '|';
15469
0
  }
15470
0
  if (components.protocol_end != buffer.size()) {
15471
0
    line1[components.protocol_end] = '|';
15472
0
  }
15473
0
  answer.append(line1);
15474
0
  answer.append("\n");
15475
15476
0
  std::string line2 = line1;
15477
0
  if (components.hash_start != url_components::omitted) {
15478
0
    line2[components.hash_start] = '`';
15479
0
    line1[components.hash_start] = ' ';
15480
15481
0
    for (size_t i = components.hash_start + 1; i < line2.size(); i++) {
15482
0
      line2[i] = '-';
15483
0
    }
15484
0
    line2.append(" hash_start");
15485
0
    answer.append(line2);
15486
0
    answer.append("\n");
15487
0
  }
15488
15489
0
  std::string line3 = line1;
15490
0
  if (components.search_start != url_components::omitted) {
15491
0
    line3[components.search_start] = '`';
15492
0
    line1[components.search_start] = ' ';
15493
15494
0
    for (size_t i = components.search_start + 1; i < line3.size(); i++) {
15495
0
      line3[i] = '-';
15496
0
    }
15497
0
    line3.append(" search_start ");
15498
0
    line3.append(std::to_string(components.search_start));
15499
0
    answer.append(line3);
15500
0
    answer.append("\n");
15501
0
  }
15502
15503
0
  std::string line4 = line1;
15504
0
  if (components.pathname_start != buffer.size()) {
15505
0
    line4[components.pathname_start] = '`';
15506
0
    line1[components.pathname_start] = ' ';
15507
0
    for (size_t i = components.pathname_start + 1; i < line4.size(); i++) {
15508
0
      line4[i] = '-';
15509
0
    }
15510
0
    line4.append(" pathname_start ");
15511
0
    line4.append(std::to_string(components.pathname_start));
15512
0
    answer.append(line4);
15513
0
    answer.append("\n");
15514
0
  }
15515
15516
0
  std::string line5 = line1;
15517
0
  if (components.host_end != buffer.size()) {
15518
0
    line5[components.host_end] = '`';
15519
0
    line1[components.host_end] = ' ';
15520
15521
0
    for (size_t i = components.host_end + 1; i < line5.size(); i++) {
15522
0
      line5[i] = '-';
15523
0
    }
15524
0
    line5.append(" host_end ");
15525
0
    line5.append(std::to_string(components.host_end));
15526
0
    answer.append(line5);
15527
0
    answer.append("\n");
15528
0
  }
15529
15530
0
  std::string line6 = line1;
15531
0
  if (components.host_start != buffer.size()) {
15532
0
    line6[components.host_start] = '`';
15533
0
    line1[components.host_start] = ' ';
15534
15535
0
    for (size_t i = components.host_start + 1; i < line6.size(); i++) {
15536
0
      line6[i] = '-';
15537
0
    }
15538
0
    line6.append(" host_start ");
15539
0
    line6.append(std::to_string(components.host_start));
15540
0
    answer.append(line6);
15541
0
    answer.append("\n");
15542
0
  }
15543
15544
0
  std::string line7 = line1;
15545
0
  if (components.username_end != buffer.size()) {
15546
0
    line7[components.username_end] = '`';
15547
0
    line1[components.username_end] = ' ';
15548
15549
0
    for (size_t i = components.username_end + 1; i < line7.size(); i++) {
15550
0
      line7[i] = '-';
15551
0
    }
15552
0
    line7.append(" username_end ");
15553
0
    line7.append(std::to_string(components.username_end));
15554
0
    answer.append(line7);
15555
0
    answer.append("\n");
15556
0
  }
15557
15558
0
  std::string line8 = line1;
15559
0
  if (components.protocol_end != buffer.size()) {
15560
0
    line8[components.protocol_end] = '`';
15561
0
    line1[components.protocol_end] = ' ';
15562
15563
0
    for (size_t i = components.protocol_end + 1; i < line8.size(); i++) {
15564
0
      line8[i] = '-';
15565
0
    }
15566
0
    line8.append(" protocol_end ");
15567
0
    line8.append(std::to_string(components.protocol_end));
15568
0
    answer.append(line8);
15569
0
    answer.append("\n");
15570
0
  }
15571
15572
0
  if (components.hash_start == url_components::omitted) {
15573
0
    answer.append("note: hash omitted\n");
15574
0
  }
15575
0
  if (components.search_start == url_components::omitted) {
15576
0
    answer.append("note: search omitted\n");
15577
0
  }
15578
0
  if (components.protocol_end > buffer.size()) {
15579
0
    answer.append("warning: protocol_end overflows\n");
15580
0
  }
15581
0
  if (components.username_end > buffer.size()) {
15582
0
    answer.append("warning: username_end overflows\n");
15583
0
  }
15584
0
  if (components.host_start > buffer.size()) {
15585
0
    answer.append("warning: host_start overflows\n");
15586
0
  }
15587
0
  if (components.host_end > buffer.size()) {
15588
0
    answer.append("warning: host_end overflows\n");
15589
0
  }
15590
0
  if (components.pathname_start > buffer.size()) {
15591
0
    answer.append("warning: pathname_start overflows\n");
15592
0
  }
15593
0
  return answer;
15594
0
}
15595
15596
0
void url_aggregator::delete_dash_dot() {
15597
0
  ada_log("url_aggregator::delete_dash_dot");
15598
0
  ADA_ASSERT_TRUE(validate());
15599
0
  ADA_ASSERT_TRUE(has_dash_dot());
15600
0
  buffer.erase(components.host_end, 2);
15601
0
  components.pathname_start -= 2;
15602
0
  if (components.search_start != url_components::omitted) {
15603
0
    components.search_start -= 2;
15604
0
  }
15605
0
  if (components.hash_start != url_components::omitted) {
15606
0
    components.hash_start -= 2;
15607
0
  }
15608
0
  ADA_ASSERT_TRUE(validate());
15609
0
  ADA_ASSERT_TRUE(!has_dash_dot());
15610
0
}
15611
15612
9.66k
inline void url_aggregator::consume_prepared_path(std::string_view input) {
15613
9.66k
  ada_log("url_aggregator::consume_prepared_path ", input);
15614
  /***
15615
   * This is largely duplicated code from helpers::parse_prepared_path, which is
15616
   * unfortunate. This particular function is nearly identical, except that it
15617
   * is a method on url_aggregator. The idea is that the trivial path (which is
15618
   * very common) merely appends to the buffer. This is the same trivial path as
15619
   * with helpers::parse_prepared_path, except that we have the additional check
15620
   * for is_at_path(). Otherwise, we grab a copy of the current path and we
15621
   * modify it, and then insert it back into the buffer.
15622
   */
15623
9.66k
  uint8_t accumulator = checkers::path_signature(input);
15624
  // Let us first detect a trivial case.
15625
  // If it is special, we check that we have no dot, no %,  no \ and no
15626
  // character needing percent encoding. Otherwise, we check that we have no %,
15627
  // no dot, and no character needing percent encoding.
15628
9.66k
  constexpr uint8_t need_encoding = 1;
15629
9.66k
  constexpr uint8_t backslash_char = 2;
15630
9.66k
  constexpr uint8_t dot_char = 4;
15631
9.66k
  constexpr uint8_t percent_char = 8;
15632
9.66k
  bool special = type != ada::scheme::NOT_SPECIAL;
15633
9.66k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
15634
2.37k
                                      checkers::is_windows_drive_letter(input));
15635
9.66k
  bool trivial_path =
15636
9.66k
      (special ? (accumulator == 0)
15637
9.66k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
15638
2.89k
                  0)) &&
15639
2.28k
      (!may_need_slow_file_handling);
15640
9.66k
  if (accumulator == dot_char && !may_need_slow_file_handling) {
15641
    // '4' means that we have at least one dot, but nothing that requires
15642
    // percent encoding or decoding. The only part that is not trivial is
15643
    // that we may have single dots and double dots path segments.
15644
    // If we have such segments, then we either have a path that begins
15645
    // with '.' (easy to check), or we have the sequence './'.
15646
    // Note: input cannot be empty, it must at least contain one character ('.')
15647
    // Note: we know that '\' is not present.
15648
1.80k
    if (input[0] != '.') {
15649
1.16k
      size_t slashdot = 0;
15650
1.16k
      bool dot_is_file = true;
15651
4.88k
      for (;;) {
15652
4.88k
        slashdot = input.find("/.", slashdot);
15653
4.88k
        if (slashdot == std::string_view::npos) {  // common case
15654
1.16k
          break;
15655
3.71k
        } else {  // uncommon
15656
          // only three cases matter: /./, /.. or a final /
15657
3.71k
          slashdot += 2;
15658
3.71k
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
15659
866
                           input[slashdot] == '/');
15660
3.71k
        }
15661
4.88k
      }
15662
1.16k
      trivial_path = dot_is_file;
15663
1.16k
    }
15664
1.80k
  }
15665
9.66k
  if (trivial_path && is_at_path()) {
15666
2.70k
    ada_log("parse_path trivial");
15667
2.70k
    buffer += '/';
15668
2.70k
    buffer += input;
15669
2.70k
    return;
15670
2.70k
  }
15671
6.96k
  std::string path = std::string(get_pathname());
15672
  // We are going to need to look a bit at the path, but let us see if we can
15673
  // ignore percent encoding *and* backslashes *and* percent characters.
15674
  // Except for the trivial case, this is likely to capture 99% of paths out
15675
  // there.
15676
6.96k
  bool fast_path =
15677
6.96k
      (special &&
15678
4.79k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
15679
1.05k
      (type != ada::scheme::type::FILE);
15680
6.96k
  if (fast_path) {
15681
865
    ada_log("parse_prepared_path fast");
15682
    // Here we don't need to worry about \ or percent encoding.
15683
    // We also do not have a file protocol. We might have dots, however,
15684
    // but dots must as appear as '.', and they cannot be encoded because
15685
    // the symbol '%' is not present.
15686
865
    size_t previous_location = 0;  // We start at 0.
15687
11.4k
    do {
15688
11.4k
      size_t new_location = input.find('/', previous_location);
15689
      // std::string_view path_view = input;
15690
      //  We process the last segment separately:
15691
11.4k
      if (new_location == std::string_view::npos) {
15692
865
        std::string_view path_view = input.substr(previous_location);
15693
865
        if (path_view == "..") {  // The path ends with ..
15694
          // e.g., if you receive ".." with an empty path, you go to "/".
15695
109
          if (path.empty()) {
15696
43
            path = '/';
15697
43
            update_base_pathname(path);
15698
43
            return;
15699
43
          }
15700
          // Fast case where we have nothing to do:
15701
66
          if (path.back() == '/') {
15702
22
            update_base_pathname(path);
15703
22
            return;
15704
22
          }
15705
          // If you have the path "/joe/myfriend",
15706
          // then you delete 'myfriend'.
15707
44
          path.resize(path.rfind('/') + 1);
15708
44
          update_base_pathname(path);
15709
44
          return;
15710
66
        }
15711
756
        path += '/';
15712
756
        if (path_view != ".") {
15713
575
          path.append(path_view);
15714
575
        }
15715
756
        update_base_pathname(path);
15716
756
        return;
15717
10.6k
      } else {
15718
        // This is a non-final segment.
15719
10.6k
        std::string_view path_view =
15720
10.6k
            input.substr(previous_location, new_location - previous_location);
15721
10.6k
        previous_location = new_location + 1;
15722
10.6k
        if (path_view == "..") {
15723
1.45k
          size_t last_delimiter = path.rfind('/');
15724
1.45k
          if (last_delimiter != std::string::npos) {
15725
929
            path.erase(last_delimiter);
15726
929
          }
15727
9.15k
        } else if (path_view != ".") {
15728
8.60k
          path += '/';
15729
8.60k
          path.append(path_view);
15730
8.60k
        }
15731
10.6k
      }
15732
11.4k
    } while (true);
15733
6.09k
  } else {
15734
6.09k
    ada_log("parse_path slow");
15735
    // we have reached the general case
15736
6.09k
    bool needs_percent_encoding = (accumulator & 1);
15737
6.09k
    std::string path_buffer_tmp;
15738
23.8k
    do {
15739
23.8k
      size_t location = (special && (accumulator & 2))
15740
23.8k
                            ? input.find_first_of("/\\")
15741
23.8k
                            : input.find('/');
15742
23.8k
      std::string_view path_view = input;
15743
23.8k
      if (location != std::string_view::npos) {
15744
17.7k
        path_view.remove_suffix(path_view.size() - location);
15745
17.7k
        input.remove_prefix(location + 1);
15746
17.7k
      }
15747
      // path_buffer is either path_view or it might point at a percent encoded
15748
      // temporary string.
15749
23.8k
      std::string_view path_buffer =
15750
23.8k
          (needs_percent_encoding &&
15751
16.3k
           ada::unicode::percent_encode<false>(
15752
16.3k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
15753
23.8k
              ? path_buffer_tmp
15754
23.8k
              : path_view;
15755
23.8k
      if (unicode::is_double_dot_path_segment(path_buffer)) {
15756
4.43k
        helpers::shorten_path(path, type);
15757
4.43k
        if (location == std::string_view::npos) {
15758
450
          path += '/';
15759
450
        }
15760
19.3k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
15761
1.14k
                 (location == std::string_view::npos)) {
15762
178
        path += '/';
15763
178
      }
15764
      // Otherwise, if path_buffer is not a single-dot path segment, then:
15765
19.1k
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
15766
        // If url's scheme is "file", url's path is empty, and path_buffer is a
15767
        // Windows drive letter, then replace the second code point in
15768
        // path_buffer with U+003A (:).
15769
18.2k
        if (type == ada::scheme::type::FILE && path.empty() &&
15770
3.24k
            checkers::is_windows_drive_letter(path_buffer)) {
15771
116
          path += '/';
15772
116
          path += path_buffer[0];
15773
116
          path += ':';
15774
116
          path_buffer.remove_prefix(2);
15775
116
          path.append(path_buffer);
15776
18.1k
        } else {
15777
          // Append path_buffer to url's path.
15778
18.1k
          path += '/';
15779
18.1k
          path.append(path_buffer);
15780
18.1k
        }
15781
18.2k
      }
15782
23.8k
      if (location == std::string_view::npos) {
15783
6.09k
        update_base_pathname(path);
15784
6.09k
        return;
15785
6.09k
      }
15786
23.8k
    } while (true);
15787
6.09k
  }
15788
6.96k
}
15789
}  // namespace ada
15790
/* end file src/url_aggregator.cpp */
15791
15792
#if ADA_INCLUDE_URL_PATTERN
15793
/* begin file src/url_pattern.cpp */
15794
#if ADA_INCLUDE_URL_PATTERN
15795
15796
15797
#include <algorithm>
15798
#include <optional>
15799
#include <string>
15800
15801
namespace ada {
15802
15803
tl::expected<url_pattern_init, errors> url_pattern_init::process(
15804
    const url_pattern_init& init, url_pattern_init::process_type type,
15805
    std::optional<std::string_view> protocol,
15806
    std::optional<std::string_view> username,
15807
    std::optional<std::string_view> password,
15808
    std::optional<std::string_view> hostname,
15809
    std::optional<std::string_view> port,
15810
    std::optional<std::string_view> pathname,
15811
    std::optional<std::string_view> search,
15812
0
    std::optional<std::string_view> hash) {
15813
  // Let result be the result of creating a new URLPatternInit.
15814
0
  auto result = url_pattern_init{};
15815
15816
  // If protocol is not null, set result["protocol"] to protocol.
15817
0
  if (protocol.has_value()) result.protocol = *protocol;
15818
15819
  // If username is not null, set result["username"] to username.
15820
0
  if (username.has_value()) result.username = *username;
15821
15822
  // If password is not null, set result["password"] to password.
15823
0
  if (password.has_value()) result.password = *password;
15824
15825
  // If hostname is not null, set result["hostname"] to hostname.
15826
0
  if (hostname.has_value()) result.hostname = *hostname;
15827
15828
  // If port is not null, set result["port"] to port.
15829
0
  if (port.has_value()) result.port = *port;
15830
15831
  // If pathname is not null, set result["pathname"] to pathname.
15832
0
  if (pathname.has_value()) result.pathname = *pathname;
15833
15834
  // If search is not null, set result["search"] to search.
15835
0
  if (search.has_value()) result.search = *search;
15836
15837
  // If hash is not null, set result["hash"] to hash.
15838
0
  if (hash.has_value()) result.hash = *hash;
15839
15840
  // Let baseURL be null.
15841
0
  std::optional<url_aggregator> base_url{};
15842
15843
  // If init["baseURL"] exists:
15844
0
  if (init.base_url.has_value()) {
15845
    // Set baseURL to the result of parsing init["baseURL"].
15846
0
    auto parsing_result = ada::parse<url_aggregator>(*init.base_url);
15847
    // If baseURL is failure, then throw a TypeError.
15848
0
    if (!parsing_result) {
15849
0
      return tl::unexpected(errors::type_error);
15850
0
    }
15851
0
    base_url = std::move(*parsing_result);
15852
15853
    // If init["protocol"] does not exist, then set result["protocol"] to the
15854
    // result of processing a base URL string given baseURL's scheme and type.
15855
0
    if (!init.protocol.has_value()) {
15856
0
      ADA_ASSERT_TRUE(base_url.has_value());
15857
0
      std::string_view base_url_protocol = base_url->get_protocol();
15858
0
      if (base_url_protocol.ends_with(":")) base_url_protocol.remove_suffix(1);
15859
0
      result.protocol =
15860
0
          url_pattern_helpers::process_base_url_string(base_url_protocol, type);
15861
0
    }
15862
15863
    // If type is not "pattern" and init contains none of "protocol",
15864
    // "hostname", "port" and "username", then set result["username"] to the
15865
    // result of processing a base URL string given baseURL's username and type.
15866
0
    if (type != process_type::pattern && !init.protocol && !init.hostname &&
15867
0
        !init.port && !init.username) {
15868
0
      result.username = url_pattern_helpers::process_base_url_string(
15869
0
          base_url->get_username(), type);
15870
0
    }
15871
15872
    // TODO: Optimization opportunity: Merge this with the previous check.
15873
    // If type is not "pattern" and init contains none of "protocol",
15874
    // "hostname", "port", "username" and "password", then set
15875
    // result["password"] to the result of processing a base URL string given
15876
    // baseURL's password and type.
15877
0
    if (type != process_type::pattern && !init.protocol && !init.hostname &&
15878
0
        !init.port && !init.username && !init.password) {
15879
0
      result.password = url_pattern_helpers::process_base_url_string(
15880
0
          base_url->get_password(), type);
15881
0
    }
15882
15883
    // If init contains neither "protocol" nor "hostname", then:
15884
0
    if (!init.protocol && !init.hostname) {
15885
      // Let baseHost be baseURL's host.
15886
      // If baseHost is null, then set baseHost to the empty string.
15887
0
      auto base_host = base_url->get_hostname();
15888
      // Set result["hostname"] to the result of processing a base URL string
15889
      // given baseHost and type.
15890
0
      result.hostname =
15891
0
          url_pattern_helpers::process_base_url_string(base_host, type);
15892
0
    }
15893
15894
    // If init contains none of "protocol", "hostname", and "port", then:
15895
0
    if (!init.protocol && !init.hostname && !init.port) {
15896
      // If baseURL's port is null, then set result["port"] to the empty string.
15897
      // Otherwise, set result["port"] to baseURL's port, serialized.
15898
0
      result.port = base_url->get_port();
15899
0
    }
15900
15901
    // If init contains none of "protocol", "hostname", "port", and "pathname",
15902
    // then set result["pathname"] to the result of processing a base URL string
15903
    // given the result of URL path serializing baseURL and type.
15904
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname) {
15905
0
      result.pathname = url_pattern_helpers::process_base_url_string(
15906
0
          base_url->get_pathname(), type);
15907
0
    }
15908
15909
    // If init contains none of "protocol", "hostname", "port", "pathname", and
15910
    // "search", then:
15911
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname &&
15912
0
        !init.search) {
15913
      // Let baseQuery be baseURL's query.
15914
      // Set result["search"] to the result of processing a base URL string
15915
      // given baseQuery and type.
15916
0
      result.search = url_pattern_helpers::process_base_url_string(
15917
0
          base_url->get_search(), type);
15918
0
    }
15919
15920
    // If init contains none of "protocol", "hostname", "port", "pathname",
15921
    // "search", and "hash", then:
15922
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname &&
15923
0
        !init.search && !init.hash) {
15924
      // Let baseFragment be baseURL's fragment.
15925
      // Set result["hash"] to the result of processing a base URL string given
15926
      // baseFragment and type.
15927
0
      result.hash = url_pattern_helpers::process_base_url_string(
15928
0
          base_url->get_hash(), type);
15929
0
    }
15930
0
  }
15931
15932
  // If init["protocol"] exists, then set result["protocol"] to the result of
15933
  // process protocol for init given init["protocol"] and type.
15934
0
  if (init.protocol) {
15935
0
    auto process_result = process_protocol(*init.protocol, type);
15936
0
    if (!process_result) {
15937
0
      return tl::unexpected(process_result.error());
15938
0
    }
15939
0
    result.protocol = std::move(*process_result);
15940
0
  }
15941
15942
  // If init["username"] exists, then set result["username"] to the result of
15943
  // process username for init given init["username"] and type.
15944
0
  if (init.username.has_value()) {
15945
0
    auto process_result = process_username(*init.username, type);
15946
0
    if (!process_result) {
15947
0
      return tl::unexpected(process_result.error());
15948
0
    }
15949
0
    result.username = std::move(*process_result);
15950
0
  }
15951
15952
  // If init["password"] exists, then set result["password"] to the result of
15953
  // process password for init given init["password"] and type.
15954
0
  if (init.password.has_value()) {
15955
0
    auto process_result = process_password(*init.password, type);
15956
0
    if (!process_result) {
15957
0
      return tl::unexpected(process_result.error());
15958
0
    }
15959
0
    result.password = std::move(*process_result);
15960
0
  }
15961
15962
  // If init["hostname"] exists, then set result["hostname"] to the result of
15963
  // process hostname for init given init["hostname"] and type.
15964
0
  if (init.hostname.has_value()) {
15965
0
    auto process_result = process_hostname(*init.hostname, type);
15966
0
    if (!process_result) {
15967
0
      return tl::unexpected(process_result.error());
15968
0
    }
15969
0
    result.hostname = std::move(*process_result);
15970
0
  }
15971
15972
  // If init["port"] exists, then set result["port"] to the result of process
15973
  // port for init given init["port"], result["protocol"], and type.
15974
0
  if (init.port) {
15975
0
    auto process_result =
15976
0
        process_port(*init.port, result.protocol.value_or("fake"), type);
15977
0
    if (!process_result) {
15978
0
      return tl::unexpected(process_result.error());
15979
0
    }
15980
0
    result.port = std::move(*process_result);
15981
0
  }
15982
15983
  // If init["pathname"] exists:
15984
0
  if (init.pathname.has_value()) {
15985
    // Set result["pathname"] to init["pathname"].
15986
0
    result.pathname = init.pathname;
15987
15988
    // If the following are all true:
15989
    // - baseURL is not null;
15990
    // - baseURL has an opaque path; and
15991
    // - the result of running is an absolute pathname given result["pathname"]
15992
    // and type is false,
15993
0
    if (base_url && !base_url->has_opaque_path &&
15994
0
        !url_pattern_helpers::is_absolute_pathname(*result.pathname, type)) {
15995
      // Let baseURLPath be the result of running process a base URL string
15996
      // given the result of URL path serializing baseURL and type.
15997
      // TODO: Optimization opportunity: Avoid returning a string if no slash
15998
      // exist.
15999
0
      std::string base_url_path = url_pattern_helpers::process_base_url_string(
16000
0
          base_url->get_pathname(), type);
16001
16002
      // Let slash index be the index of the last U+002F (/) code point found in
16003
      // baseURLPath, interpreted as a sequence of code points, or null if there
16004
      // are no instances of the code point.
16005
0
      auto slash_index = base_url_path.find_last_of('/');
16006
16007
      // If slash index is not null:
16008
0
      if (slash_index != std::string::npos) {
16009
        // Let new pathname be the code point substring from 0 to slash index +
16010
        // 1 within baseURLPath.
16011
0
        base_url_path.resize(slash_index + 1);
16012
        // Append result["pathname"] to the end of new pathname.
16013
0
        ADA_ASSERT_TRUE(result.pathname.has_value());
16014
0
        base_url_path.append(std::move(*result.pathname));
16015
        // Set result["pathname"] to new pathname.
16016
0
        result.pathname = std::move(base_url_path);
16017
0
      }
16018
0
    }
16019
16020
    // Set result["pathname"] to the result of process pathname for init given
16021
    // result["pathname"], result["protocol"], and type.
16022
0
    auto pathname_processing_result =
16023
0
        process_pathname(*result.pathname, result.protocol.value_or(""), type);
16024
0
    if (!pathname_processing_result) {
16025
0
      return tl::unexpected(pathname_processing_result.error());
16026
0
    }
16027
0
    result.pathname = std::move(*pathname_processing_result);
16028
0
  }
16029
16030
  // If init["search"] exists then set result["search"] to the result of process
16031
  // search for init given init["search"] and type.
16032
0
  if (init.search) {
16033
0
    auto process_result = process_search(*init.search, type);
16034
0
    if (!process_result) {
16035
0
      return tl::unexpected(process_result.error());
16036
0
    }
16037
0
    result.search = std::move(*process_result);
16038
0
  }
16039
16040
  // If init["hash"] exists then set result["hash"] to the result of process
16041
  // hash for init given init["hash"] and type.
16042
0
  if (init.hash) {
16043
0
    auto process_result = process_hash(*init.hash, type);
16044
0
    if (!process_result) {
16045
0
      return tl::unexpected(process_result.error());
16046
0
    }
16047
0
    result.hash = std::move(*process_result);
16048
0
  }
16049
  // Return result.
16050
0
  return result;
16051
0
}
16052
16053
tl::expected<std::string, errors> url_pattern_init::process_protocol(
16054
0
    std::string_view value, process_type type) {
16055
0
  ada_log("process_protocol=", value, " [", type, "]");
16056
  // Let strippedValue be the given value with a single trailing U+003A (:)
16057
  // removed, if any.
16058
0
  if (value.ends_with(":")) {
16059
0
    value.remove_suffix(1);
16060
0
  }
16061
  // If type is "pattern" then return strippedValue.
16062
0
  if (type == process_type::pattern) {
16063
0
    return std::string(value);
16064
0
  }
16065
  // Return the result of running canonicalize a protocol given strippedValue.
16066
0
  return url_pattern_helpers::canonicalize_protocol(value);
16067
0
}
16068
16069
tl::expected<std::string, errors> url_pattern_init::process_username(
16070
0
    std::string_view value, process_type type) {
16071
  // If type is "pattern" then return value.
16072
0
  if (type == process_type::pattern) {
16073
0
    return std::string(value);
16074
0
  }
16075
  // Return the result of running canonicalize a username given value.
16076
0
  return url_pattern_helpers::canonicalize_username(value);
16077
0
}
16078
16079
tl::expected<std::string, errors> url_pattern_init::process_password(
16080
0
    std::string_view value, process_type type) {
16081
  // If type is "pattern" then return value.
16082
0
  if (type == process_type::pattern) {
16083
0
    return std::string(value);
16084
0
  }
16085
  // Return the result of running canonicalize a password given value.
16086
0
  return url_pattern_helpers::canonicalize_password(value);
16087
0
}
16088
16089
tl::expected<std::string, errors> url_pattern_init::process_hostname(
16090
0
    std::string_view value, process_type type) {
16091
0
  ada_log("process_hostname value=", value, " type=", type);
16092
  // If type is "pattern" then return value.
16093
0
  if (type == process_type::pattern) {
16094
0
    return std::string(value);
16095
0
  }
16096
  // Return the result of running canonicalize a hostname given value.
16097
0
  return url_pattern_helpers::canonicalize_hostname(value);
16098
0
}
16099
16100
tl::expected<std::string, errors> url_pattern_init::process_port(
16101
0
    std::string_view port, std::string_view protocol, process_type type) {
16102
  // If type is "pattern" then return portValue.
16103
0
  if (type == process_type::pattern) {
16104
0
    return std::string(port);
16105
0
  }
16106
  // Return the result of running canonicalize a port given portValue and
16107
  // protocolValue.
16108
0
  return url_pattern_helpers::canonicalize_port_with_protocol(port, protocol);
16109
0
}
16110
16111
tl::expected<std::string, errors> url_pattern_init::process_pathname(
16112
0
    std::string_view value, std::string_view protocol, process_type type) {
16113
  // If type is "pattern" then return pathnameValue.
16114
0
  if (type == process_type::pattern) {
16115
0
    return std::string(value);
16116
0
  }
16117
16118
  // If protocolValue is a special scheme or the empty string, then return the
16119
  // result of running canonicalize a pathname given pathnameValue.
16120
0
  if (protocol.empty() || scheme::is_special(protocol)) {
16121
0
    return url_pattern_helpers::canonicalize_pathname(value);
16122
0
  }
16123
16124
  // Return the result of running canonicalize an opaque pathname given
16125
  // pathnameValue.
16126
0
  return url_pattern_helpers::canonicalize_opaque_pathname(value);
16127
0
}
16128
16129
tl::expected<std::string, errors> url_pattern_init::process_search(
16130
0
    std::string_view value, process_type type) {
16131
  // Let strippedValue be the given value with a single leading U+003F (?)
16132
  // removed, if any.
16133
0
  if (value.starts_with("?")) {
16134
0
    value.remove_prefix(1);
16135
0
  }
16136
  // We cannot assert that the value is no longer starting with a single
16137
  // question mark because technically it can start. The question is whether or
16138
  // not we should remove the first question mark. Ref:
16139
  // https://github.com/ada-url/ada/pull/992 The spec is not clear on this.
16140
16141
  // If type is "pattern" then return strippedValue.
16142
0
  if (type == process_type::pattern) {
16143
0
    return std::string(value);
16144
0
  }
16145
  // Return the result of running canonicalize a search given strippedValue.
16146
0
  return url_pattern_helpers::canonicalize_search(value);
16147
0
}
16148
16149
tl::expected<std::string, errors> url_pattern_init::process_hash(
16150
0
    std::string_view value, process_type type) {
16151
  // Let strippedValue be the given value with a single leading U+0023 (#)
16152
  // removed, if any.
16153
0
  if (value.starts_with("#")) {
16154
0
    value.remove_prefix(1);
16155
0
  }
16156
0
  ADA_ASSERT_TRUE(!value.starts_with("#"));
16157
  // If type is "pattern" then return strippedValue.
16158
0
  if (type == process_type::pattern) {
16159
0
    return std::string(value);
16160
0
  }
16161
  // Return the result of running canonicalize a hash given strippedValue.
16162
0
  return url_pattern_helpers::canonicalize_hash(value);
16163
0
}
16164
16165
}  // namespace ada
16166
16167
#endif  // ADA_INCLUDE_URL_PATTERN
16168
/* end file src/url_pattern.cpp */
16169
/* begin file src/url_pattern_helpers.cpp */
16170
#if ADA_INCLUDE_URL_PATTERN
16171
16172
#include <algorithm>
16173
#include <array>
16174
#include <charconv>
16175
#include <optional>
16176
#include <ranges>
16177
#include <string>
16178
16179
16180
namespace ada::url_pattern_helpers {
16181
16182
std::tuple<std::string, std::vector<std::string>>
16183
generate_regular_expression_and_name_list(
16184
    const std::vector<url_pattern_part>& part_list,
16185
0
    url_pattern_compile_component_options options) {
16186
  // Let result be "^"
16187
0
  std::string result = "^";
16188
  // Reserve capacity to reduce reallocations
16189
0
  result.reserve(part_list.size() * 16);
16190
16191
  // Let name list be a new list
16192
0
  std::vector<std::string> name_list{};
16193
0
  name_list.reserve(part_list.size());
16194
16195
  // Pre-generate segment wildcard regexp if needed (avoids repeated generation)
16196
0
  std::string segment_wildcard_regexp;
16197
16198
  // For each part of part list:
16199
0
  for (const url_pattern_part& part : part_list) {
16200
    // If part's type is "fixed-text":
16201
0
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
16202
      // If part's modifier is "none"
16203
0
      if (part.modifier == url_pattern_part_modifier::none) {
16204
0
        result.append(escape_regexp_string(part.value));
16205
0
      } else {
16206
        // (?:<fixed text>)<modifier>
16207
0
        result.append("(?:");
16208
0
        result.append(escape_regexp_string(part.value));
16209
0
        result.push_back(')');
16210
0
        result.append(convert_modifier_to_string(part.modifier));
16211
0
      }
16212
0
      continue;
16213
0
    }
16214
16215
    // Assert: part's name is not the empty string
16216
0
    ADA_ASSERT_TRUE(!part.name.empty());
16217
0
    name_list.push_back(part.name);
16218
16219
    // Use string_view to avoid copies where possible
16220
0
    std::string_view regexp_value = part.value;
16221
16222
0
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD) {
16223
      // Lazy generate segment wildcard regexp
16224
0
      if (segment_wildcard_regexp.empty()) {
16225
0
        segment_wildcard_regexp = generate_segment_wildcard_regexp(options);
16226
0
      }
16227
0
      regexp_value = segment_wildcard_regexp;
16228
0
    } else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
16229
0
      regexp_value = ".*";
16230
0
    }
16231
16232
    // If part's prefix is the empty string and part's suffix is the empty
16233
    // string
16234
0
    if (part.prefix.empty() && part.suffix.empty()) {
16235
      // If part's modifier is "none" or "optional"
16236
0
      if (part.modifier == url_pattern_part_modifier::none ||
16237
0
          part.modifier == url_pattern_part_modifier::optional) {
16238
        // (<regexp value>)<modifier>
16239
0
        result.push_back('(');
16240
0
        result.append(regexp_value);
16241
0
        result.push_back(')');
16242
0
        result.append(convert_modifier_to_string(part.modifier));
16243
0
      } else {
16244
        // ((?:<regexp value>)<modifier>)
16245
0
        result.append("((?:");
16246
0
        result.append(regexp_value);
16247
0
        result.push_back(')');
16248
0
        result.append(convert_modifier_to_string(part.modifier));
16249
0
        result.push_back(')');
16250
0
      }
16251
0
      continue;
16252
0
    }
16253
16254
    // If part's modifier is "none" or "optional"
16255
0
    if (part.modifier == url_pattern_part_modifier::none ||
16256
0
        part.modifier == url_pattern_part_modifier::optional) {
16257
      // (?:<prefix>(<regexp value>)<suffix>)<modifier>
16258
0
      result.append("(?:");
16259
0
      result.append(escape_regexp_string(part.prefix));
16260
0
      result.push_back('(');
16261
0
      result.append(regexp_value);
16262
0
      result.push_back(')');
16263
0
      result.append(escape_regexp_string(part.suffix));
16264
0
      result.push_back(')');
16265
0
      result.append(convert_modifier_to_string(part.modifier));
16266
0
      continue;
16267
0
    }
16268
16269
    // Assert: part's modifier is "zero-or-more" or "one-or-more"
16270
0
    ADA_ASSERT_TRUE(part.modifier == url_pattern_part_modifier::zero_or_more ||
16271
0
                    part.modifier == url_pattern_part_modifier::one_or_more);
16272
16273
    // Assert: part's prefix is not the empty string or part's suffix is not the
16274
    // empty string
16275
0
    ADA_ASSERT_TRUE(!part.prefix.empty() || !part.suffix.empty());
16276
16277
    // (?:<prefix>((?:<regexp value>)(?:<suffix><prefix>(?:<regexp
16278
    // value>))*)<suffix>)?
16279
    // Append "(?:" to the end of result.
16280
0
    result.append("(?:");
16281
    // Append the result of running escape a regexp string given part's prefix
16282
    // to the end of result.
16283
0
    result.append(escape_regexp_string(part.prefix));
16284
    // Append "((?:" to the end of result.
16285
0
    result.append("((?:");
16286
    // Append regexp value to the end of result.
16287
0
    result.append(regexp_value);
16288
    // Append ")(?:" to the end of result.
16289
0
    result.append(")(?:");
16290
    // Append the result of running escape a regexp string given part's suffix
16291
    // to the end of result.
16292
0
    result.append(escape_regexp_string(part.suffix));
16293
    // Append the result of running escape a regexp string given part's prefix
16294
    // to the end of result.
16295
0
    result.append(escape_regexp_string(part.prefix));
16296
    // Append "(?:" to the end of result.
16297
0
    result.append("(?:");
16298
    // Append regexp value to the end of result.
16299
0
    result.append(regexp_value);
16300
    // Append "))*)" to the end of result.
16301
0
    result.append("))*)");
16302
    // Append the result of running escape a regexp string given part's suffix
16303
    // to the end of result.
16304
0
    result.append(escape_regexp_string(part.suffix));
16305
    // Append ")" to the end of result.
16306
0
    result.append(")");
16307
16308
    // If part's modifier is "zero-or-more" then append "?" to the end of result
16309
0
    if (part.modifier == url_pattern_part_modifier::zero_or_more) {
16310
0
      result += "?";
16311
0
    }
16312
0
  }
16313
16314
  // Append "$" to the end of result
16315
0
  result += "$";
16316
16317
  // Return (result, name list)
16318
0
  return {std::move(result), std::move(name_list)};
16319
0
}
16320
16321
0
bool is_ipv6_address(std::string_view input) noexcept {
16322
  // If input's code point length is less than 2, then return false.
16323
0
  if (input.size() < 2) return false;
16324
16325
  // Let input code points be input interpreted as a list of code points.
16326
  // If input code points[0] is U+005B ([), then return true.
16327
0
  if (input.front() == '[') return true;
16328
  // If input code points[0] is U+007B ({) and input code points[1] is U+005B
16329
  // ([), then return true.
16330
0
  if (input.starts_with("{[")) return true;
16331
  // If input code points[0] is U+005C (\) and input code points[1] is U+005B
16332
  // ([), then return true.
16333
0
  return input.starts_with("\\[");
16334
0
}
16335
16336
std::string_view convert_modifier_to_string(
16337
0
    url_pattern_part_modifier modifier) {
16338
0
  switch (modifier) {
16339
      // If modifier is "zero-or-more", then return "*".
16340
0
    case url_pattern_part_modifier::zero_or_more:
16341
0
      return "*";
16342
    // If modifier is "optional", then return "?".
16343
0
    case url_pattern_part_modifier::optional:
16344
0
      return "?";
16345
    // If modifier is "one-or-more", then return "+".
16346
0
    case url_pattern_part_modifier::one_or_more:
16347
0
      return "+";
16348
    // Return the empty string.
16349
0
    default:
16350
0
      return "";
16351
0
  }
16352
0
}
16353
16354
std::string generate_segment_wildcard_regexp(
16355
0
    url_pattern_compile_component_options options) {
16356
  // Let result be "[^".
16357
0
  std::string result = "[^";
16358
  // Append the result of running escape a regexp string given options's
16359
  // delimiter code point to the end of result.
16360
0
  result.append(escape_regexp_string(options.get_delimiter()));
16361
  // Append "]+?" to the end of result.
16362
0
  result.append("]+?");
16363
  // Return result.
16364
0
  ada_log("generate_segment_wildcard_regexp result: ", result);
16365
0
  return result;
16366
0
}
16367
16368
namespace {
16369
// Unified lookup table for URL pattern character classification
16370
// Bit flags for different character types
16371
constexpr uint8_t CHAR_SCHEME = 1;  // valid in scheme (a-z, A-Z, 0-9, +, -, .)
16372
constexpr uint8_t CHAR_UPPER = 2;   // uppercase letter (needs lowercasing)
16373
constexpr uint8_t CHAR_SIMPLE_HOSTNAME = 4;  // simple hostname (a-z, 0-9, -, .)
16374
constexpr uint8_t CHAR_SIMPLE_PATHNAME =
16375
    8;  // simple pathname (a-z, A-Z, 0-9, /, -, _, ~)
16376
16377
constexpr std::array<uint8_t, 256> char_class_table = []() consteval {
16378
  std::array<uint8_t, 256> table{};
16379
  for (int c = 'a'; c <= 'z'; c++)
16380
    table[c] = CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME | CHAR_SIMPLE_PATHNAME;
16381
  for (int c = 'A'; c <= 'Z'; c++)
16382
    table[c] = CHAR_SCHEME | CHAR_UPPER | CHAR_SIMPLE_PATHNAME;
16383
  for (int c = '0'; c <= '9'; c++)
16384
    table[c] = CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME | CHAR_SIMPLE_PATHNAME;
16385
  table['+'] = CHAR_SCHEME;
16386
  table['-'] = CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME | CHAR_SIMPLE_PATHNAME;
16387
  table['.'] =
16388
      CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME;  // not pathname (needs normalization)
16389
  table['/'] = CHAR_SIMPLE_PATHNAME;
16390
  table['_'] = CHAR_SIMPLE_PATHNAME;
16391
  table['~'] = CHAR_SIMPLE_PATHNAME;
16392
  return table;
16393
}();
16394
}  // namespace
16395
16396
tl::expected<std::string, errors> canonicalize_protocol(
16397
0
    std::string_view input) {
16398
0
  ada_log("canonicalize_protocol called with input=", input);
16399
0
  if (input.empty()) [[unlikely]] {
16400
0
    return "";
16401
0
  }
16402
16403
0
  if (input.ends_with(":")) {
16404
0
    input.remove_suffix(1);
16405
0
  }
16406
16407
  // Fast path: special schemes are already canonical
16408
0
  if (scheme::is_special(input)) {
16409
0
    return std::string(input);
16410
0
  }
16411
16412
  // Fast path: validate scheme chars and check for uppercase
16413
  // First char must be alpha (not +, -, ., or digit)
16414
0
  uint8_t first_flags = char_class_table[static_cast<uint8_t>(input[0])];
16415
0
  if (!(first_flags & CHAR_SCHEME) || input[0] == '+' || input[0] == '-' ||
16416
0
      input[0] == '.' || unicode::is_ascii_digit(input[0])) {
16417
0
    return tl::unexpected(errors::type_error);
16418
0
  }
16419
16420
0
  uint8_t needs_lowercase = first_flags & CHAR_UPPER;
16421
0
  for (size_t i = 1; i < input.size(); i++) {
16422
0
    uint8_t flags = char_class_table[static_cast<uint8_t>(input[i])];
16423
0
    if (!(flags & CHAR_SCHEME)) {
16424
0
      return tl::unexpected(errors::type_error);
16425
0
    }
16426
0
    needs_lowercase |= flags & CHAR_UPPER;
16427
0
  }
16428
16429
0
  if (needs_lowercase == 0) {
16430
0
    return std::string(input);
16431
0
  }
16432
16433
0
  std::string result(input);
16434
0
  unicode::to_lower_ascii(result.data(), result.size());
16435
0
  return result;
16436
0
}
16437
16438
tl::expected<std::string, errors> canonicalize_username(
16439
0
    std::string_view input) {
16440
  // If value is the empty string, return value.
16441
0
  if (input.empty()) [[unlikely]] {
16442
0
    return "";
16443
0
  }
16444
  // Percent-encode the input using the userinfo percent-encode set.
16445
0
  size_t idx = ada::unicode::percent_encode_index(
16446
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
16447
0
  if (idx == input.size()) {
16448
    // No encoding needed, return input as-is
16449
0
    return std::string(input);
16450
0
  }
16451
  // Percent-encode from the first character that needs encoding
16452
0
  return ada::unicode::percent_encode(
16453
0
      input, character_sets::USERINFO_PERCENT_ENCODE, idx);
16454
0
}
16455
16456
tl::expected<std::string, errors> canonicalize_password(
16457
0
    std::string_view input) {
16458
  // If value is the empty string, return value.
16459
0
  if (input.empty()) [[unlikely]] {
16460
0
    return "";
16461
0
  }
16462
  // Percent-encode the input using the userinfo percent-encode set.
16463
0
  size_t idx = ada::unicode::percent_encode_index(
16464
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
16465
0
  if (idx == input.size()) {
16466
    // No encoding needed, return input as-is
16467
0
    return std::string(input);
16468
0
  }
16469
  // Percent-encode from the first character that needs encoding
16470
0
  return ada::unicode::percent_encode(
16471
0
      input, character_sets::USERINFO_PERCENT_ENCODE, idx);
16472
0
}
16473
16474
tl::expected<std::string, errors> canonicalize_hostname(
16475
0
    std::string_view input) {
16476
0
  ada_log("canonicalize_hostname input=", input);
16477
0
  if (input.empty()) [[unlikely]] {
16478
0
    return "";
16479
0
  }
16480
16481
  // Fast path: simple hostnames (lowercase ASCII, digits, -, .) need no IDNA
16482
0
  bool needs_processing = false;
16483
0
  for (char c : input) {
16484
0
    needs_processing |=
16485
0
        !(char_class_table[static_cast<uint8_t>(c)] & CHAR_SIMPLE_HOSTNAME);
16486
0
  }
16487
0
  if (!needs_processing) {
16488
0
    return std::string(input);
16489
0
  }
16490
16491
  // Let dummyURL be a new URL record.
16492
  // Let parseResult be the result of running the basic URL parser given value
16493
  // with dummyURL as url and hostname state as state override.
16494
16495
  // IMPORTANT: The protocol needs to be a special protocol, otherwise the
16496
  // hostname will not be converted using IDNA.
16497
0
  auto url = ada::parse<url_aggregator>("https://dummy.test", nullptr);
16498
0
  ADA_ASSERT_TRUE(url);
16499
  // if (!isValidHostnameInput(hostname)) return kj::none;
16500
0
  if (!url->set_hostname(input)) {
16501
    // If parseResult is failure, then throw a TypeError.
16502
0
    return tl::unexpected(errors::type_error);
16503
0
  }
16504
  // Return dummyURL's host, serialized, or empty string if it is null.
16505
0
  return std::string(url->get_hostname());
16506
0
}
16507
16508
tl::expected<std::string, errors> canonicalize_ipv6_hostname(
16509
0
    std::string_view input) {
16510
0
  ada_log("canonicalize_ipv6_hostname input=", input);
16511
  // TODO: Optimization opportunity: Use lookup table to speed up checking
16512
0
  if (std::ranges::any_of(input, [](char c) {
16513
0
        return c != '[' && c != ']' && c != ':' &&
16514
0
               !unicode::is_ascii_hex_digit(c);
16515
0
      })) {
16516
0
    return tl::unexpected(errors::type_error);
16517
0
  }
16518
  // Append the result of running ASCII lowercase given code point to the end of
16519
  // result.
16520
0
  auto hostname = std::string(input);
16521
0
  unicode::to_lower_ascii(hostname.data(), hostname.size());
16522
0
  return hostname;
16523
0
}
16524
16525
tl::expected<std::string, errors> canonicalize_port(
16526
0
    std::string_view port_value) {
16527
  // If portValue is the empty string, return portValue.
16528
0
  if (port_value.empty()) [[unlikely]] {
16529
0
    return "";
16530
0
  }
16531
16532
  // Remove ASCII tab or newline characters
16533
0
  std::string trimmed(port_value);
16534
0
  helpers::remove_ascii_tab_or_newline(trimmed);
16535
16536
0
  if (trimmed.empty()) {
16537
0
    return "";
16538
0
  }
16539
16540
  // Input should start with a digit character
16541
0
  if (!unicode::is_ascii_digit(trimmed.front())) {
16542
0
    return tl::unexpected(errors::type_error);
16543
0
  }
16544
16545
  // Find the first non-digit character
16546
0
  auto first_non_digit =
16547
0
      std::ranges::find_if_not(trimmed, unicode::is_ascii_digit);
16548
0
  std::string_view digits_to_parse =
16549
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
16550
16551
  // Here we have that a range of ASCII digit characters identified
16552
  // by digits_to_parse. It is none empty.
16553
  // We want to determine whether it is a valid port number (0-65535).
16554
  // Clearly, if the length is greater than 5, it is invalid.
16555
  // If the length is 5, we need to compare lexicographically to "65535".
16556
  // Otherwise it is valid.
16557
0
  if (digits_to_parse.size() == 5) {
16558
0
    if (digits_to_parse > "65535") {
16559
0
      return tl::unexpected(errors::type_error);
16560
0
    }
16561
0
  } else if (digits_to_parse.size() > 5) {
16562
0
    return tl::unexpected(errors::type_error);
16563
0
  }
16564
0
  if (digits_to_parse[0] == '0' && digits_to_parse.size() > 1) {
16565
    // Leading zeros are not allowed for multi-digit ports
16566
0
    return tl::unexpected(errors::type_error);
16567
0
  }
16568
  // It is valid! Most times, we do not need to parse it into an integer.
16569
0
  return std::string(digits_to_parse);
16570
0
}
16571
16572
tl::expected<std::string, errors> canonicalize_port_with_protocol(
16573
0
    std::string_view port_value, std::string_view protocol) {
16574
  // If portValue is the empty string, return portValue.
16575
0
  if (port_value.empty()) [[unlikely]] {
16576
0
    return "";
16577
0
  }
16578
16579
  // Handle empty or trailing colon in protocol
16580
0
  if (protocol.empty()) {
16581
0
    protocol = "fake";
16582
0
  } else if (protocol.ends_with(":")) {
16583
0
    protocol.remove_suffix(1);
16584
0
  }
16585
16586
  // Remove ASCII tab or newline characters
16587
0
  std::string trimmed(port_value);
16588
0
  helpers::remove_ascii_tab_or_newline(trimmed);
16589
16590
0
  if (trimmed.empty()) {
16591
0
    return "";
16592
0
  }
16593
16594
  // Input should start with a digit character
16595
0
  if (!unicode::is_ascii_digit(trimmed.front())) {
16596
0
    return tl::unexpected(errors::type_error);
16597
0
  }
16598
16599
  // Find the first non-digit character
16600
0
  auto first_non_digit =
16601
0
      std::ranges::find_if_not(trimmed, unicode::is_ascii_digit);
16602
0
  std::string_view digits_to_parse =
16603
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
16604
16605
  // Parse the port number
16606
0
  uint16_t parsed_port{};
16607
0
  auto result = std::from_chars(digits_to_parse.data(),
16608
0
                                digits_to_parse.data() + digits_to_parse.size(),
16609
0
                                parsed_port);
16610
16611
0
  if (result.ec == std::errc::result_out_of_range) {
16612
0
    return tl::unexpected(errors::type_error);
16613
0
  }
16614
16615
0
  if (result.ec == std::errc()) {
16616
    // Check if this is the default port for the scheme
16617
0
    uint16_t default_port = scheme::get_special_port(protocol);
16618
16619
    // If it's the default port for a special scheme, return empty string
16620
0
    if (default_port != 0 && default_port == parsed_port) {
16621
0
      return "";
16622
0
    }
16623
16624
    // Successfully parsed, return as string
16625
0
    return std::to_string(parsed_port);
16626
0
  }
16627
16628
0
  return tl::unexpected(errors::type_error);
16629
0
}
16630
16631
tl::expected<std::string, errors> canonicalize_pathname(
16632
0
    std::string_view input) {
16633
0
  if (input.empty()) [[unlikely]] {
16634
0
    return "";
16635
0
  }
16636
16637
  // Fast path: simple pathnames (no . which needs normalization) can be
16638
  // returned as-is
16639
0
  bool needs_processing = false;
16640
0
  for (char c : input) {
16641
0
    needs_processing |=
16642
0
        !(char_class_table[static_cast<uint8_t>(c)] & CHAR_SIMPLE_PATHNAME);
16643
0
  }
16644
0
  if (!needs_processing) {
16645
0
    return std::string(input);
16646
0
  }
16647
16648
  // Let leading slash be true if the first code point in value is U+002F (/)
16649
  // and otherwise false.
16650
0
  const bool leading_slash = input.starts_with("/");
16651
  // Let modified value be "/-" if leading slash is false and otherwise the
16652
  // empty string.
16653
0
  const auto modified_value = leading_slash ? "" : "/-";
16654
0
  const auto full_url =
16655
0
      std::string("fake://fake-url") + modified_value + std::string(input);
16656
0
  if (auto url = ada::parse<url_aggregator>(full_url, nullptr)) {
16657
0
    const auto pathname = url->get_pathname();
16658
    // If leading slash is false, then set result to the code point substring
16659
    // from 2 to the end of the string within result.
16660
0
    return leading_slash ? std::string(pathname)
16661
0
                         : std::string(pathname.substr(2));
16662
0
  }
16663
  // If parseResult is failure, then throw a TypeError.
16664
0
  return tl::unexpected(errors::type_error);
16665
0
}
16666
16667
tl::expected<std::string, errors> canonicalize_opaque_pathname(
16668
0
    std::string_view input) {
16669
  // If value is the empty string, return value.
16670
0
  if (input.empty()) [[unlikely]] {
16671
0
    return "";
16672
0
  }
16673
  // Let dummyURL be a new URL record.
16674
  // Set dummyURL's path to the empty string.
16675
  // Let parseResult be the result of running URL parsing given value with
16676
  // dummyURL as url and opaque path state as state override.
16677
0
  if (auto url =
16678
0
          ada::parse<url_aggregator>("fake:" + std::string(input), nullptr)) {
16679
    // Return the result of URL path serializing dummyURL.
16680
0
    return std::string(url->get_pathname());
16681
0
  }
16682
  // If parseResult is failure, then throw a TypeError.
16683
0
  return tl::unexpected(errors::type_error);
16684
0
}
16685
16686
0
tl::expected<std::string, errors> canonicalize_search(std::string_view input) {
16687
  // If value is the empty string, return value.
16688
0
  if (input.empty()) [[unlikely]] {
16689
0
    return "";
16690
0
  }
16691
  // Remove leading '?' if present
16692
0
  std::string new_value;
16693
0
  new_value = input[0] == '?' ? input.substr(1) : input;
16694
  // Remove ASCII tab or newline characters
16695
0
  helpers::remove_ascii_tab_or_newline(new_value);
16696
16697
0
  if (new_value.empty()) {
16698
0
    return "";
16699
0
  }
16700
16701
  // Percent-encode using QUERY_PERCENT_ENCODE (for non-special URLs)
16702
  // Note: "fake://dummy.test" is not a special URL, so we use
16703
  // QUERY_PERCENT_ENCODE
16704
0
  size_t idx = ada::unicode::percent_encode_index(
16705
0
      new_value, character_sets::QUERY_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::QUERY_PERCENT_ENCODE, idx);
16713
0
}
16714
16715
0
tl::expected<std::string, errors> canonicalize_hash(std::string_view input) {
16716
  // If value is the empty string, return value.
16717
0
  if (input.empty()) [[unlikely]] {
16718
0
    return "";
16719
0
  }
16720
  // Remove leading '#' if present
16721
0
  std::string new_value;
16722
0
  new_value = input[0] == '#' ? input.substr(1) : input;
16723
  // Remove ASCII tab or newline characters
16724
0
  helpers::remove_ascii_tab_or_newline(new_value);
16725
16726
0
  if (new_value.empty()) {
16727
0
    return "";
16728
0
  }
16729
16730
  // Percent-encode using FRAGMENT_PERCENT_ENCODE
16731
0
  size_t idx = ada::unicode::percent_encode_index(
16732
0
      new_value, character_sets::FRAGMENT_PERCENT_ENCODE);
16733
0
  if (idx == new_value.size()) {
16734
    // No encoding needed
16735
0
    return new_value;
16736
0
  }
16737
  // Percent-encode from the first character that needs encoding
16738
0
  return ada::unicode::percent_encode(
16739
0
      new_value, character_sets::FRAGMENT_PERCENT_ENCODE, idx);
16740
0
}
16741
16742
tl::expected<std::vector<token>, errors> tokenize(std::string_view input,
16743
0
                                                  token_policy policy) {
16744
0
  ada_log("tokenize input: ", input);
16745
  // Let tokenizer be a new tokenizer.
16746
  // Set tokenizer's input to input.
16747
  // Set tokenizer's policy to policy.
16748
0
  auto tokenizer = Tokenizer(input, policy);
16749
  // While tokenizer's index is less than tokenizer's input's code point length:
16750
0
  while (tokenizer.index < tokenizer.input.size()) {
16751
    // Run seek and get the next code point given tokenizer and tokenizer's
16752
    // index.
16753
0
    tokenizer.seek_and_get_next_code_point(tokenizer.index);
16754
16755
    // If tokenizer's code point is U+002A (*):
16756
0
    if (tokenizer.code_point == '*') {
16757
      // Run add a token with default position and length given tokenizer and
16758
      // "asterisk".
16759
0
      tokenizer.add_token_with_defaults(token_type::ASTERISK);
16760
0
      ada_log("add ASTERISK token");
16761
      // Continue.
16762
0
      continue;
16763
0
    }
16764
16765
    // If tokenizer's code point is U+002B (+) or U+003F (?):
16766
0
    if (tokenizer.code_point == '+' || tokenizer.code_point == '?') {
16767
      // Run add a token with default position and length given tokenizer and
16768
      // "other-modifier".
16769
0
      tokenizer.add_token_with_defaults(token_type::OTHER_MODIFIER);
16770
      // Continue.
16771
0
      continue;
16772
0
    }
16773
16774
    // If tokenizer's code point is U+005C (\):
16775
0
    if (tokenizer.code_point == '\\') {
16776
      // If tokenizer's index is equal to tokenizer's input's code point length
16777
      // - 1:
16778
0
      if (tokenizer.index == tokenizer.input.size() - 1) {
16779
        // Run process a tokenizing error given tokenizer, tokenizer's next
16780
        // index, and tokenizer's index.
16781
0
        if (auto error = tokenizer.process_tokenizing_error(
16782
0
                tokenizer.next_index, tokenizer.index)) {
16783
0
          ada_log("process_tokenizing_error failed");
16784
0
          return tl::unexpected(*error);
16785
0
        }
16786
0
        continue;
16787
0
      }
16788
16789
      // Let escaped index be tokenizer's next index.
16790
0
      auto escaped_index = tokenizer.next_index;
16791
      // Run get the next code point given tokenizer.
16792
0
      tokenizer.get_next_code_point();
16793
      // Run add a token with default length given tokenizer, "escaped-char",
16794
      // tokenizer's next index, and escaped index.
16795
0
      tokenizer.add_token_with_default_length(
16796
0
          token_type::ESCAPED_CHAR, tokenizer.next_index, escaped_index);
16797
0
      ada_log("add ESCAPED_CHAR token on next_index ", tokenizer.next_index,
16798
0
              " with escaped index ", escaped_index);
16799
      // Continue.
16800
0
      continue;
16801
0
    }
16802
16803
    // If tokenizer's code point is U+007B ({):
16804
0
    if (tokenizer.code_point == '{') {
16805
      // Run add a token with default position and length given tokenizer and
16806
      // "open".
16807
0
      tokenizer.add_token_with_defaults(token_type::OPEN);
16808
0
      ada_log("add OPEN token");
16809
0
      continue;
16810
0
    }
16811
16812
    // If tokenizer's code point is U+007D (}):
16813
0
    if (tokenizer.code_point == '}') {
16814
      // Run add a token with default position and length given tokenizer and
16815
      // "close".
16816
0
      tokenizer.add_token_with_defaults(token_type::CLOSE);
16817
0
      ada_log("add CLOSE token");
16818
0
      continue;
16819
0
    }
16820
16821
    // If tokenizer's code point is U+003A (:):
16822
0
    if (tokenizer.code_point == ':') {
16823
      // Let name position be tokenizer's next index.
16824
0
      auto name_position = tokenizer.next_index;
16825
      // Let name start be name position.
16826
0
      auto name_start = name_position;
16827
      // While name position is less than tokenizer's input's code point length:
16828
0
      while (name_position < tokenizer.input.size()) {
16829
        // Run seek and get the next code point given tokenizer and name
16830
        // position.
16831
0
        tokenizer.seek_and_get_next_code_point(name_position);
16832
        // Let first code point be true if name position equals name start and
16833
        // false otherwise.
16834
0
        bool first_code_point = name_position == name_start;
16835
        // Let valid code point be the result of running is a valid name code
16836
        // point given tokenizer's code point and first code point.
16837
0
        auto valid_code_point =
16838
0
            idna::valid_name_code_point(tokenizer.code_point, first_code_point);
16839
0
        ada_log("tokenizer.code_point=", uint32_t(tokenizer.code_point),
16840
0
                " first_code_point=", first_code_point,
16841
0
                " valid_code_point=", valid_code_point);
16842
        // If valid code point is false break.
16843
0
        if (!valid_code_point) break;
16844
        // Set name position to tokenizer's next index.
16845
0
        name_position = tokenizer.next_index;
16846
0
      }
16847
16848
      // If name position is less than or equal to name start:
16849
0
      if (name_position <= name_start) {
16850
        // Run process a tokenizing error given tokenizer, name start, and
16851
        // tokenizer's index.
16852
0
        if (auto error = tokenizer.process_tokenizing_error(name_start,
16853
0
                                                            tokenizer.index)) {
16854
0
          ada_log("process_tokenizing_error failed");
16855
0
          return tl::unexpected(*error);
16856
0
        }
16857
        // Continue
16858
0
        continue;
16859
0
      }
16860
16861
      // Run add a token with default length given tokenizer, "name", name
16862
      // position, and name start.
16863
0
      tokenizer.add_token_with_default_length(token_type::NAME, name_position,
16864
0
                                              name_start);
16865
0
      continue;
16866
0
    }
16867
16868
    // If tokenizer's code point is U+0028 (():
16869
0
    if (tokenizer.code_point == '(') {
16870
      // Let depth be 1.
16871
0
      size_t depth = 1;
16872
      // Let regexp position be tokenizer's next index.
16873
0
      auto regexp_position = tokenizer.next_index;
16874
      // Let regexp start be regexp position.
16875
0
      auto regexp_start = regexp_position;
16876
      // Let error be false.
16877
0
      bool error = false;
16878
16879
      // While regexp position is less than tokenizer's input's code point
16880
      // length:
16881
0
      while (regexp_position < tokenizer.input.size()) {
16882
        // Run seek and get the next code point given tokenizer and regexp
16883
        // position.
16884
0
        tokenizer.seek_and_get_next_code_point(regexp_position);
16885
16886
        // TODO: Optimization opportunity: The next 2 if statements can be
16887
        // merged. If the result of running is ASCII given tokenizer's code
16888
        // point is false:
16889
0
        if (!unicode::is_ascii(tokenizer.code_point)) {
16890
          // Run process a tokenizing error given tokenizer, regexp start, and
16891
          // tokenizer's index.
16892
0
          if (auto process_error = tokenizer.process_tokenizing_error(
16893
0
                  regexp_start, tokenizer.index)) {
16894
0
            return tl::unexpected(*process_error);
16895
0
          }
16896
          // Set error to true.
16897
0
          error = true;
16898
0
          break;
16899
0
        }
16900
16901
        // If regexp position equals regexp start and tokenizer's code point is
16902
        // U+003F (?):
16903
0
        if (regexp_position == regexp_start && tokenizer.code_point == '?') {
16904
          // Run process a tokenizing error given tokenizer, regexp start, and
16905
          // tokenizer's index.
16906
0
          if (auto process_error = tokenizer.process_tokenizing_error(
16907
0
                  regexp_start, tokenizer.index)) {
16908
0
            return tl::unexpected(*process_error);
16909
0
          }
16910
          // Set error to true;
16911
0
          error = true;
16912
0
          break;
16913
0
        }
16914
16915
        // If tokenizer's code point is U+005C (\):
16916
0
        if (tokenizer.code_point == '\\') {
16917
          // If regexp position equals tokenizer's input's code point length - 1
16918
0
          if (regexp_position == tokenizer.input.size() - 1) {
16919
            // Run process a tokenizing error given tokenizer, regexp start, and
16920
            // tokenizer's index.
16921
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16922
0
                    regexp_start, tokenizer.index)) {
16923
0
              return tl::unexpected(*process_error);
16924
0
            }
16925
            // Set error to true.
16926
0
            error = true;
16927
0
            break;
16928
0
          }
16929
          // Run get the next code point given tokenizer.
16930
0
          tokenizer.get_next_code_point();
16931
          // If the result of running is ASCII given tokenizer's code point is
16932
          // false:
16933
0
          if (!unicode::is_ascii(tokenizer.code_point)) {
16934
            // Run process a tokenizing error given tokenizer, regexp start, and
16935
            // tokenizer's index.
16936
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16937
0
                    regexp_start, tokenizer.index);
16938
0
                process_error.has_value()) {
16939
0
              return tl::unexpected(*process_error);
16940
0
            }
16941
            // Set error to true.
16942
0
            error = true;
16943
0
            break;
16944
0
          }
16945
          // Set regexp position to tokenizer's next index.
16946
0
          regexp_position = tokenizer.next_index;
16947
0
          continue;
16948
0
        }
16949
16950
        // If tokenizer's code point is U+0029 ()):
16951
0
        if (tokenizer.code_point == ')') {
16952
          // Decrement depth by 1.
16953
0
          depth--;
16954
          // If depth is 0:
16955
0
          if (depth == 0) {
16956
            // Set regexp position to tokenizer's next index.
16957
0
            regexp_position = tokenizer.next_index;
16958
            // Break.
16959
0
            break;
16960
0
          }
16961
0
        } else if (tokenizer.code_point == '(') {
16962
          // Otherwise if tokenizer's code point is U+0028 (():
16963
          // Increment depth by 1.
16964
0
          depth++;
16965
          // If regexp position equals tokenizer's input's code point length -
16966
          // 1:
16967
0
          if (regexp_position == tokenizer.input.size() - 1) {
16968
            // Run process a tokenizing error given tokenizer, regexp start, and
16969
            // tokenizer's index.
16970
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16971
0
                    regexp_start, tokenizer.index)) {
16972
0
              return tl::unexpected(*process_error);
16973
0
            }
16974
            // Set error to true.
16975
0
            error = true;
16976
0
            break;
16977
0
          }
16978
          // Let temporary position be tokenizer's next index.
16979
0
          auto temporary_position = tokenizer.next_index;
16980
          // Run get the next code point given tokenizer.
16981
0
          tokenizer.get_next_code_point();
16982
          // If tokenizer's code point is not U+003F (?):
16983
0
          if (tokenizer.code_point != '?') {
16984
            // Run process a tokenizing error given tokenizer, regexp start, and
16985
            // tokenizer's index.
16986
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16987
0
                    regexp_start, tokenizer.index)) {
16988
0
              return tl::unexpected(*process_error);
16989
0
            }
16990
            // Set error to true.
16991
0
            error = true;
16992
0
            break;
16993
0
          }
16994
          // Set tokenizer's next index to temporary position.
16995
0
          tokenizer.next_index = temporary_position;
16996
0
        }
16997
        // Set regexp position to tokenizer's next index.
16998
0
        regexp_position = tokenizer.next_index;
16999
0
      }
17000
17001
      // If error is true continue.
17002
0
      if (error) continue;
17003
      // If depth is not zero:
17004
0
      if (depth != 0) {
17005
        // Run process a tokenizing error given tokenizer, regexp start, and
17006
        // tokenizer's index.
17007
0
        if (auto process_error = tokenizer.process_tokenizing_error(
17008
0
                regexp_start, tokenizer.index)) {
17009
0
          return tl::unexpected(*process_error);
17010
0
        }
17011
0
        continue;
17012
0
      }
17013
      // Let regexp length be regexp position - regexp start - 1.
17014
0
      auto regexp_length = regexp_position - regexp_start - 1;
17015
      // If regexp length is zero:
17016
0
      if (regexp_length == 0) {
17017
        // Run process a tokenizing error given tokenizer, regexp start, and
17018
        // tokenizer's index.
17019
0
        if (auto process_error = tokenizer.process_tokenizing_error(
17020
0
                regexp_start, tokenizer.index)) {
17021
0
          ada_log("process_tokenizing_error failed");
17022
0
          return tl::unexpected(*process_error);
17023
0
        }
17024
0
        continue;
17025
0
      }
17026
      // Run add a token given tokenizer, "regexp", regexp position, regexp
17027
      // start, and regexp length.
17028
0
      tokenizer.add_token(token_type::REGEXP, regexp_position, regexp_start,
17029
0
                          regexp_length);
17030
0
      continue;
17031
0
    }
17032
    // Run add a token with default position and length given tokenizer and
17033
    // "char".
17034
0
    tokenizer.add_token_with_defaults(token_type::CHAR);
17035
0
  }
17036
  // Run add a token with default length given tokenizer, "end", tokenizer's
17037
  // index, and tokenizer's index.
17038
0
  tokenizer.add_token_with_default_length(token_type::END, tokenizer.index,
17039
0
                                          tokenizer.index);
17040
17041
0
  ada_log("tokenizer.token_list size is: ", tokenizer.token_list.size());
17042
  // Return tokenizer's token list.
17043
0
  return tokenizer.token_list;
17044
0
}
17045
17046
namespace {
17047
constexpr std::array<uint8_t, 256> escape_pattern_table = []() consteval {
17048
  std::array<uint8_t, 256> out{};
17049
  for (auto& c : {'+', '*', '?', ':', '{', '}', '(', ')', '\\'}) {
17050
    out[c] = 1;
17051
  }
17052
  return out;
17053
}();
17054
17055
0
constexpr bool should_escape_pattern_char(char c) {
17056
0
  return escape_pattern_table[static_cast<uint8_t>(c)];
17057
0
}
17058
}  // namespace
17059
17060
0
std::string escape_pattern_string(std::string_view input) {
17061
0
  ada_log("escape_pattern_string called with input=", input);
17062
0
  if (input.empty()) [[unlikely]] {
17063
0
    return "";
17064
0
  }
17065
  // Assert: input is an ASCII string.
17066
0
  ADA_ASSERT_TRUE(ada::idna::is_ascii(input));
17067
  // Let result be the empty string.
17068
0
  std::string result{};
17069
  // Reserve extra space for potential escapes
17070
0
  result.reserve(input.size() * 2);
17071
17072
  // While index is less than input's length:
17073
0
  for (const char c : input) {
17074
0
    if (should_escape_pattern_char(c)) {
17075
      // Append U+005C (\) to the end of result.
17076
0
      result.push_back('\\');
17077
0
    }
17078
    // Append c to the end of result.
17079
0
    result.push_back(c);
17080
0
  }
17081
  // Return result.
17082
0
  return result;
17083
0
}
17084
17085
namespace {
17086
constexpr std::array<uint8_t, 256> escape_regexp_table = []() consteval {
17087
  std::array<uint8_t, 256> out{};
17088
  for (auto& c : {'.', '+', '*', '?', '^', '$', '{', '}', '(', ')', '[', ']',
17089
                  '|', '/', '\\'}) {
17090
    out[c] = 1;
17091
  }
17092
  return out;
17093
}();
17094
17095
0
constexpr bool should_escape_regexp_char(char c) {
17096
0
  return escape_regexp_table[(uint8_t)c];
17097
0
}
17098
}  // namespace
17099
17100
0
std::string escape_regexp_string(std::string_view input) {
17101
  // Assert: input is an ASCII string.
17102
0
  ADA_ASSERT_TRUE(idna::is_ascii(input));
17103
  // Let result be the empty string.
17104
0
  std::string result{};
17105
  // Reserve extra space for potential escapes (worst case: all chars escaped)
17106
0
  result.reserve(input.size() * 2);
17107
0
  for (const char c : input) {
17108
0
    if (should_escape_regexp_char(c)) {
17109
      // Avoid temporary string allocation - directly append characters
17110
0
      result.push_back('\\');
17111
0
      result.push_back(c);
17112
0
    } else {
17113
0
      result.push_back(c);
17114
0
    }
17115
0
  }
17116
0
  return result;
17117
0
}
17118
17119
std::string process_base_url_string(std::string_view input,
17120
0
                                    url_pattern_init::process_type type) {
17121
  // If type is not "pattern" return input.
17122
0
  if (type != url_pattern_init::process_type::pattern) {
17123
0
    return std::string(input);
17124
0
  }
17125
  // Return the result of escaping a pattern string given input.
17126
0
  return escape_pattern_string(input);
17127
0
}
17128
17129
constexpr bool is_absolute_pathname(
17130
0
    std::string_view input, url_pattern_init::process_type type) noexcept {
17131
  // If input is the empty string, then return false.
17132
0
  if (input.empty()) [[unlikely]] {
17133
0
    return false;
17134
0
  }
17135
  // If input[0] is U+002F (/), then return true.
17136
0
  if (input.starts_with("/")) return true;
17137
  // If type is "url", then return false.
17138
0
  if (type == url_pattern_init::process_type::url) return false;
17139
  // If input's code point length is less than 2, then return false.
17140
0
  if (input.size() < 2) return false;
17141
  // If input[0] is U+005C (\) and input[1] is U+002F (/), then return true.
17142
  // If input[0] is U+007B ({) and input[1] is U+002F (/), then return true.
17143
  // Return false.
17144
0
  return input[1] == '/' && (input[0] == '\\' || input[0] == '{');
17145
0
}
17146
17147
std::string generate_pattern_string(
17148
    std::vector<url_pattern_part>& part_list,
17149
0
    url_pattern_compile_component_options& options) {
17150
  // Let result be the empty string.
17151
0
  std::string result{};
17152
  // Let index list be the result of getting the indices for part list.
17153
  // For each index of index list:
17154
0
  for (size_t index = 0; index < part_list.size(); index++) {
17155
    // Let part be part list[index].
17156
    // Use reference to avoid copy
17157
0
    const auto& part = part_list[index];
17158
    // Let previous part be part list[index - 1] if index is greater than 0,
17159
    // otherwise let it be null.
17160
    // Use pointer to avoid copy
17161
0
    const url_pattern_part* previous_part =
17162
0
        index == 0 ? nullptr : &part_list[index - 1];
17163
    // Let next part be part list[index + 1] if index is less than index list's
17164
    // size - 1, otherwise let it be null.
17165
0
    const url_pattern_part* next_part =
17166
0
        index < part_list.size() - 1 ? &part_list[index + 1] : nullptr;
17167
    // If part's type is "fixed-text" then:
17168
0
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
17169
      // If part's modifier is "none" then:
17170
0
      if (part.modifier == url_pattern_part_modifier::none) {
17171
        // Append the result of running escape a pattern string given part's
17172
        // value to the end of result.
17173
0
        result.append(escape_pattern_string(part.value));
17174
0
        continue;
17175
0
      }
17176
      // Append "{" to the end of result.
17177
0
      result += "{";
17178
      // Append the result of running escape a pattern string given part's value
17179
      // to the end of result.
17180
0
      result.append(escape_pattern_string(part.value));
17181
      // Append "}" to the end of result.
17182
0
      result += "}";
17183
      // Append the result of running convert a modifier to a string given
17184
      // part's modifier to the end of result.
17185
0
      result.append(convert_modifier_to_string(part.modifier));
17186
0
      continue;
17187
0
    }
17188
    // Let custom name be true if part's name[0] is not an ASCII digit;
17189
    // otherwise false.
17190
0
    bool custom_name = !unicode::is_ascii_digit(part.name[0]);
17191
    // Let needs grouping be true if at least one of the following are true,
17192
    // otherwise let it be false:
17193
    // - part's suffix is not the empty string.
17194
    // - part's prefix is not the empty string and is not options's prefix code
17195
    // point.
17196
0
    bool needs_grouping =
17197
0
        !part.suffix.empty() ||
17198
0
        (!part.prefix.empty() && part.prefix[0] != options.get_prefix()[0]);
17199
17200
    // If all of the following are true:
17201
    // - needs grouping is false; and
17202
    // - custom name is true; and
17203
    // - part's type is "segment-wildcard"; and
17204
    // - part's modifier is "none"; and
17205
    // - next part is not null; and
17206
    // - next part's prefix is the empty string; and
17207
    // - next part's suffix is the empty string
17208
0
    if (!needs_grouping && custom_name &&
17209
0
        part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
17210
0
        part.modifier == url_pattern_part_modifier::none && next_part &&
17211
0
        next_part->prefix.empty() && next_part->suffix.empty()) {
17212
      // If next part's type is "fixed-text":
17213
0
      if (next_part->type == url_pattern_part_type::FIXED_TEXT) {
17214
        // Set needs grouping to true if the result of running is a valid name
17215
        // code point given next part's value's first code point and the boolean
17216
        // false is true.
17217
0
        if (idna::valid_name_code_point(next_part->value[0], false)) {
17218
0
          needs_grouping = true;
17219
0
        }
17220
0
      } else {
17221
        // Set needs grouping to true if next part's name[0] is an ASCII digit.
17222
0
        needs_grouping = !next_part->name.empty() &&
17223
0
                         unicode::is_ascii_digit(next_part->name[0]);
17224
0
      }
17225
0
    }
17226
17227
    // If all of the following are true:
17228
    // - needs grouping is false; and
17229
    // - part's prefix is the empty string; and
17230
    // - previous part is not null; and
17231
    // - previous part's type is "fixed-text"; and
17232
    // - previous part's value's last code point is options's prefix code point.
17233
    // then set needs grouping to true.
17234
0
    if (!needs_grouping && part.prefix.empty() && previous_part &&
17235
0
        previous_part->type == url_pattern_part_type::FIXED_TEXT &&
17236
0
        !options.get_prefix().empty() &&
17237
0
        previous_part->value.at(previous_part->value.size() - 1) ==
17238
0
            options.get_prefix()[0]) {
17239
0
      needs_grouping = true;
17240
0
    }
17241
17242
    // Assert: part's name is not the empty string or null.
17243
0
    ADA_ASSERT_TRUE(!part.name.empty());
17244
17245
    // If needs grouping is true, then append "{" to the end of result.
17246
0
    if (needs_grouping) {
17247
0
      result.append("{");
17248
0
    }
17249
17250
    // Append the result of running escape a pattern string given part's prefix
17251
    // to the end of result.
17252
0
    result.append(escape_pattern_string(part.prefix));
17253
17254
    // If custom name is true:
17255
0
    if (custom_name) {
17256
      // Append ":" to the end of result.
17257
0
      result.append(":");
17258
      // Append part's name to the end of result.
17259
0
      result.append(part.name);
17260
0
    }
17261
17262
    // If part's type is "regexp" then:
17263
0
    if (part.type == url_pattern_part_type::REGEXP) {
17264
      // Append "(" to the end of result.
17265
0
      result.append("(");
17266
      // Append part's value to the end of result.
17267
0
      result.append(part.value);
17268
      // Append ")" to the end of result.
17269
0
      result.append(")");
17270
0
    } else if (part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
17271
0
               !custom_name) {
17272
      // Otherwise if part's type is "segment-wildcard" and custom name is
17273
      // false: Append "(" to the end of result.
17274
0
      result.append("(");
17275
      // Append the result of running generate a segment wildcard regexp given
17276
      // options to the end of result.
17277
0
      result.append(generate_segment_wildcard_regexp(options));
17278
      // Append ")" to the end of result.
17279
0
      result.append(")");
17280
0
    } else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
17281
      // Otherwise if part's type is "full-wildcard":
17282
      // If custom name is false and one of the following is true:
17283
      // - previous part is null; or
17284
      // - previous part's type is "fixed-text"; or
17285
      // - previous part's modifier is not "none"; or
17286
      // - needs grouping is true; or
17287
      // - part's prefix is not the empty string
17288
      // - then append "*" to the end of result.
17289
0
      if (!custom_name &&
17290
0
          (!previous_part ||
17291
0
           previous_part->type == url_pattern_part_type::FIXED_TEXT ||
17292
0
           previous_part->modifier != url_pattern_part_modifier::none ||
17293
0
           needs_grouping || !part.prefix.empty())) {
17294
0
        result.append("*");
17295
0
      } else {
17296
        // Append "(" to the end of result.
17297
        // Append full wildcard regexp value to the end of result.
17298
        // Append ")" to the end of result.
17299
0
        result.append("(.*)");
17300
0
      }
17301
0
    }
17302
17303
    // If all of the following are true:
17304
    // - part's type is "segment-wildcard"; and
17305
    // - custom name is true; and
17306
    // - part's suffix is not the empty string; and
17307
    // - The result of running is a valid name code point given part's suffix's
17308
    // first code point and the boolean false is true then append U+005C (\) to
17309
    // the end of result.
17310
0
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD && custom_name &&
17311
0
        !part.suffix.empty() &&
17312
0
        idna::valid_name_code_point(part.suffix[0], false)) {
17313
0
      result.append("\\");
17314
0
    }
17315
17316
    // Append the result of running escape a pattern string given part's suffix
17317
    // to the end of result.
17318
0
    result.append(escape_pattern_string(part.suffix));
17319
    // If needs grouping is true, then append "}" to the end of result.
17320
0
    if (needs_grouping) result.append("}");
17321
    // Append the result of running convert a modifier to a string given part's
17322
    // modifier to the end of result.
17323
0
    result.append(convert_modifier_to_string(part.modifier));
17324
0
  }
17325
  // Return result.
17326
0
  return result;
17327
0
}
17328
}  // namespace ada::url_pattern_helpers
17329
17330
#endif  // ADA_INCLUDE_URL_PATTERN
17331
/* end file src/url_pattern_helpers.cpp */
17332
/* begin file src/url_pattern_regex.cpp */
17333
#if ADA_INCLUDE_URL_PATTERN
17334
17335
17336
namespace ada::url_pattern_regex {
17337
17338
#ifdef ADA_USE_UNSAFE_STD_REGEX_PROVIDER
17339
std::optional<std::regex> std_regex_provider::create_instance(
17340
    std::string_view pattern, bool ignore_case) {
17341
  // Let flags be an empty string.
17342
  // If options's ignore case is true then set flags to "vi".
17343
  // Otherwise set flags to "v"
17344
  auto flags = ignore_case
17345
                   ? std::regex::icase | std::regex_constants::ECMAScript
17346
                   : std::regex_constants::ECMAScript;
17347
  try {
17348
    return std::regex(pattern.data(), pattern.size(), flags);
17349
  } catch (const std::regex_error& e) {
17350
    (void)e;
17351
    ada_log("std_regex_provider::create_instance failed:", e.what());
17352
    return std::nullopt;
17353
  }
17354
}
17355
17356
std::optional<std::vector<std::optional<std::string>>>
17357
std_regex_provider::regex_search(std::string_view input,
17358
                                 const std::regex& pattern) {
17359
  // Use iterator-based regex_search to avoid string allocation
17360
  std::match_results<std::string_view::const_iterator> match_result;
17361
  if (!std::regex_search(input.begin(), input.end(), match_result, pattern,
17362
                         std::regex_constants::match_any)) {
17363
    return std::nullopt;
17364
  }
17365
  std::vector<std::optional<std::string>> matches;
17366
  // If input is empty, let's assume the result will be empty as well.
17367
  if (input.empty() || match_result.empty()) {
17368
    return matches;
17369
  }
17370
  matches.reserve(match_result.size());
17371
  for (size_t i = 1; i < match_result.size(); ++i) {
17372
    if (auto entry = match_result[i]; entry.matched) {
17373
      matches.emplace_back(entry.str());
17374
    }
17375
  }
17376
  return matches;
17377
}
17378
17379
bool std_regex_provider::regex_match(std::string_view input,
17380
                                     const std::regex& pattern) {
17381
  return std::regex_match(input.begin(), input.end(), pattern);
17382
}
17383
17384
#endif  // ADA_USE_UNSAFE_STD_REGEX_PROVIDER
17385
17386
}  // namespace ada::url_pattern_regex
17387
17388
#endif  // ADA_INCLUDE_URL_PATTERN
17389
/* end file src/url_pattern_regex.cpp */
17390
#endif  // ADA_INCLUDE_URL_PATTERN
17391
17392
/* begin file src/ada_c.cpp */
17393
// NOLINTBEGIN(bugprone-exception-escape,
17394
// bugprone-suspicious-stringview-data-usage)
17395
17396
244k
ada::result<ada::url_aggregator>& get_instance(void* result) noexcept {
17397
244k
  return *(ada::result<ada::url_aggregator>*)result;
17398
244k
}
17399
17400
extern "C" {
17401
typedef void* ada_url;
17402
typedef void* ada_url_search_params;
17403
typedef void* ada_strings;
17404
typedef void* ada_url_search_params_keys_iter;
17405
typedef void* ada_url_search_params_values_iter;
17406
typedef void* ada_url_search_params_entries_iter;
17407
17408
struct ada_string {
17409
  const char* data;
17410
  size_t length;
17411
};
17412
17413
struct ada_owned_string {
17414
  const char* data;
17415
  size_t length;
17416
};
17417
17418
struct ada_string_pair {
17419
  ada_string key;
17420
  ada_string value;
17421
};
17422
17423
65.5k
ada_string ada_string_create(const char* data, size_t length) {
17424
65.5k
  ada_string out{};
17425
65.5k
  out.data = data;
17426
65.5k
  out.length = length;
17427
65.5k
  return out;
17428
65.5k
}
17429
17430
struct ada_url_components {
17431
  /*
17432
   * By using 32-bit integers, we implicitly assume that the URL string
17433
   * cannot exceed 4 GB.
17434
   *
17435
   * https://user:pass@example.com:1234/foo/bar?baz#quux
17436
   *       |     |    |          | ^^^^|       |   |
17437
   *       |     |    |          | |   |       |   `----- hash_start
17438
   *       |     |    |          | |   |       `--------- search_start
17439
   *       |     |    |          | |   `----------------- pathname_start
17440
   *       |     |    |          | `--------------------- port
17441
   *       |     |    |          `----------------------- host_end
17442
   *       |     |    `---------------------------------- host_start
17443
   *       |     `--------------------------------------- username_end
17444
   *       `--------------------------------------------- protocol_end
17445
   */
17446
  uint32_t protocol_end;
17447
  /**
17448
   * Username end is not `omitted` by default (-1) to make username and password
17449
   * getters less costly to implement.
17450
   */
17451
  uint32_t username_end;
17452
  uint32_t host_start;
17453
  uint32_t host_end;
17454
  uint32_t port;
17455
  uint32_t pathname_start;
17456
  uint32_t search_start;
17457
  uint32_t hash_start;
17458
};
17459
17460
8.59k
ada_url ada_parse(const char* input, size_t length) noexcept {
17461
8.59k
  return new ada::result<ada::url_aggregator>(
17462
8.59k
      ada::parse<ada::url_aggregator>(std::string_view(input, length)));
17463
8.59k
}
17464
17465
ada_url ada_parse_with_base(const char* input, size_t input_length,
17466
0
                            const char* base, size_t base_length) noexcept {
17467
0
  auto base_out =
17468
0
      ada::parse<ada::url_aggregator>(std::string_view(base, base_length));
17469
17470
0
  if (!base_out) {
17471
0
    return new ada::result<ada::url_aggregator>(base_out);
17472
0
  }
17473
17474
0
  return new ada::result<ada::url_aggregator>(ada::parse<ada::url_aggregator>(
17475
0
      std::string_view(input, input_length), &base_out.value()));
17476
0
}
17477
17478
8.59k
bool ada_can_parse(const char* input, size_t length) noexcept {
17479
8.59k
  return ada::can_parse(std::string_view(input, length));
17480
8.59k
}
17481
17482
bool ada_can_parse_with_base(const char* input, size_t input_length,
17483
0
                             const char* base, size_t base_length) noexcept {
17484
0
  std::string_view base_view(base, base_length);
17485
0
  return ada::can_parse(std::string_view(input, input_length), &base_view);
17486
0
}
17487
17488
8.59k
void ada_free(ada_url result) noexcept {
17489
8.59k
  auto* r = (ada::result<ada::url_aggregator>*)result;
17490
8.59k
  delete r;
17491
8.59k
}
17492
17493
0
ada_url ada_copy(ada_url input) noexcept {
17494
0
  ada::result<ada::url_aggregator>& r = get_instance(input);
17495
0
  return new ada::result<ada::url_aggregator>(r);
17496
0
}
17497
17498
8.59k
bool ada_is_valid(ada_url result) noexcept {
17499
8.59k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17500
8.59k
  return r.has_value();
17501
8.59k
}
17502
17503
// caller must free the result with ada_free_owned_string
17504
6.55k
ada_owned_string ada_get_origin(ada_url result) noexcept {
17505
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17506
6.55k
  ada_owned_string owned{};
17507
6.55k
  if (!r) {
17508
0
    owned.data = nullptr;
17509
0
    owned.length = 0;
17510
0
    return owned;
17511
0
  }
17512
6.55k
  std::string out = r->get_origin();
17513
6.55k
  owned.length = out.size();
17514
6.55k
  owned.data = new char[owned.length];
17515
6.55k
  memcpy((void*)owned.data, out.data(), owned.length);
17516
6.55k
  return owned;
17517
6.55k
}
17518
17519
6.55k
void ada_free_owned_string(ada_owned_string owned) noexcept {
17520
6.55k
  delete[] owned.data;
17521
6.55k
}
17522
17523
6.55k
ada_string ada_get_href(ada_url result) noexcept {
17524
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17525
6.55k
  if (!r) {
17526
0
    return ada_string_create(nullptr, 0);
17527
0
  }
17528
6.55k
  std::string_view out = r->get_href();
17529
6.55k
  return ada_string_create(out.data(), out.length());
17530
6.55k
}
17531
17532
6.55k
ada_string ada_get_username(ada_url result) noexcept {
17533
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17534
6.55k
  if (!r) {
17535
0
    return ada_string_create(nullptr, 0);
17536
0
  }
17537
6.55k
  std::string_view out = r->get_username();
17538
6.55k
  return ada_string_create(out.data(), out.length());
17539
6.55k
}
17540
17541
6.55k
ada_string ada_get_password(ada_url result) noexcept {
17542
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17543
6.55k
  if (!r) {
17544
0
    return ada_string_create(nullptr, 0);
17545
0
  }
17546
6.55k
  std::string_view out = r->get_password();
17547
6.55k
  return ada_string_create(out.data(), out.length());
17548
6.55k
}
17549
17550
6.55k
ada_string ada_get_port(ada_url result) noexcept {
17551
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17552
6.55k
  if (!r) {
17553
0
    return ada_string_create(nullptr, 0);
17554
0
  }
17555
6.55k
  std::string_view out = r->get_port();
17556
6.55k
  return ada_string_create(out.data(), out.length());
17557
6.55k
}
17558
17559
6.55k
ada_string ada_get_hash(ada_url result) noexcept {
17560
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17561
6.55k
  if (!r) {
17562
0
    return ada_string_create(nullptr, 0);
17563
0
  }
17564
6.55k
  std::string_view out = r->get_hash();
17565
6.55k
  return ada_string_create(out.data(), out.length());
17566
6.55k
}
17567
17568
6.55k
ada_string ada_get_host(ada_url result) noexcept {
17569
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17570
6.55k
  if (!r) {
17571
0
    return ada_string_create(nullptr, 0);
17572
0
  }
17573
6.55k
  std::string_view out = r->get_host();
17574
6.55k
  return ada_string_create(out.data(), out.length());
17575
6.55k
}
17576
17577
6.55k
ada_string ada_get_hostname(ada_url result) noexcept {
17578
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17579
6.55k
  if (!r) {
17580
0
    return ada_string_create(nullptr, 0);
17581
0
  }
17582
6.55k
  std::string_view out = r->get_hostname();
17583
6.55k
  return ada_string_create(out.data(), out.length());
17584
6.55k
}
17585
17586
6.55k
ada_string ada_get_pathname(ada_url result) noexcept {
17587
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17588
6.55k
  if (!r) {
17589
0
    return ada_string_create(nullptr, 0);
17590
0
  }
17591
6.55k
  std::string_view out = r->get_pathname();
17592
6.55k
  return ada_string_create(out.data(), out.length());
17593
6.55k
}
17594
17595
6.55k
ada_string ada_get_search(ada_url result) noexcept {
17596
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17597
6.55k
  if (!r) {
17598
0
    return ada_string_create(nullptr, 0);
17599
0
  }
17600
6.55k
  std::string_view out = r->get_search();
17601
6.55k
  return ada_string_create(out.data(), out.length());
17602
6.55k
}
17603
17604
6.55k
ada_string ada_get_protocol(ada_url result) noexcept {
17605
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17606
6.55k
  if (!r) {
17607
0
    return ada_string_create(nullptr, 0);
17608
0
  }
17609
6.55k
  std::string_view out = r->get_protocol();
17610
6.55k
  return ada_string_create(out.data(), out.length());
17611
6.55k
}
17612
17613
6.55k
uint8_t ada_get_host_type(ada_url result) noexcept {
17614
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17615
6.55k
  if (!r) {
17616
0
    return 0;
17617
0
  }
17618
6.55k
  return r->host_type;
17619
6.55k
}
17620
17621
6.55k
uint8_t ada_get_scheme_type(ada_url result) noexcept {
17622
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17623
6.55k
  if (!r) {
17624
0
    return 0;
17625
0
  }
17626
6.55k
  return r->type;
17627
6.55k
}
17628
17629
6.55k
bool ada_set_href(ada_url result, const char* input, size_t length) noexcept {
17630
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17631
6.55k
  if (!r) {
17632
0
    return false;
17633
0
  }
17634
6.55k
  return r->set_href(std::string_view(input, length));
17635
6.55k
}
17636
17637
6.55k
bool ada_set_host(ada_url result, const char* input, size_t length) noexcept {
17638
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17639
6.55k
  if (!r) {
17640
0
    return false;
17641
0
  }
17642
6.55k
  return r->set_host(std::string_view(input, length));
17643
6.55k
}
17644
17645
bool ada_set_hostname(ada_url result, const char* input,
17646
6.55k
                      size_t length) noexcept {
17647
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17648
6.55k
  if (!r) {
17649
0
    return false;
17650
0
  }
17651
6.55k
  return r->set_hostname(std::string_view(input, length));
17652
6.55k
}
17653
17654
bool ada_set_protocol(ada_url result, const char* input,
17655
6.55k
                      size_t length) noexcept {
17656
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17657
6.55k
  if (!r) {
17658
0
    return false;
17659
0
  }
17660
6.55k
  return r->set_protocol(std::string_view(input, length));
17661
6.55k
}
17662
17663
bool ada_set_username(ada_url result, const char* input,
17664
6.55k
                      size_t length) noexcept {
17665
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17666
6.55k
  if (!r) {
17667
0
    return false;
17668
0
  }
17669
6.55k
  return r->set_username(std::string_view(input, length));
17670
6.55k
}
17671
17672
bool ada_set_password(ada_url result, const char* input,
17673
6.55k
                      size_t length) noexcept {
17674
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17675
6.55k
  if (!r) {
17676
0
    return false;
17677
0
  }
17678
6.55k
  return r->set_password(std::string_view(input, length));
17679
6.55k
}
17680
17681
6.55k
bool ada_set_port(ada_url result, const char* input, size_t length) noexcept {
17682
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17683
6.55k
  if (!r) {
17684
0
    return false;
17685
0
  }
17686
6.55k
  return r->set_port(std::string_view(input, length));
17687
6.55k
}
17688
17689
bool ada_set_pathname(ada_url result, const char* input,
17690
6.55k
                      size_t length) noexcept {
17691
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17692
6.55k
  if (!r) {
17693
0
    return false;
17694
0
  }
17695
6.55k
  return r->set_pathname(std::string_view(input, length));
17696
6.55k
}
17697
17698
/**
17699
 * Update the search/query of the URL.
17700
 *
17701
 * If a URL has `?` as the search value, passing empty string to this function
17702
 * does not remove the attribute. If you need to remove it, please use
17703
 * `ada_clear_search` method.
17704
 */
17705
6.55k
void ada_set_search(ada_url result, const char* input, size_t length) noexcept {
17706
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17707
6.55k
  if (r) {
17708
6.55k
    r->set_search(std::string_view(input, length));
17709
6.55k
  }
17710
6.55k
}
17711
17712
/**
17713
 * Update the hash/fragment of the URL.
17714
 *
17715
 * If a URL has `#` as the hash value, passing empty string to this function
17716
 * does not remove the attribute. If you need to remove it, please use
17717
 * `ada_clear_hash` method.
17718
 */
17719
6.55k
void ada_set_hash(ada_url result, const char* input, size_t length) noexcept {
17720
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17721
6.55k
  if (r) {
17722
6.55k
    r->set_hash(std::string_view(input, length));
17723
6.55k
  }
17724
6.55k
}
17725
17726
6.55k
void ada_clear_port(ada_url result) noexcept {
17727
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17728
6.55k
  if (r) {
17729
6.55k
    r->clear_port();
17730
6.55k
  }
17731
6.55k
}
17732
17733
/**
17734
 * Removes the hash of the URL.
17735
 *
17736
 * Despite `ada_set_hash` method, this function allows the complete
17737
 * removal of the hash attribute, even if it has a value of `#`.
17738
 */
17739
6.55k
void ada_clear_hash(ada_url result) noexcept {
17740
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17741
6.55k
  if (r) {
17742
6.55k
    r->clear_hash();
17743
6.55k
  }
17744
6.55k
}
17745
17746
/**
17747
 * Removes the search of the URL.
17748
 *
17749
 * Despite `ada_set_search` method, this function allows the complete
17750
 * removal of the search attribute, even if it has a value of `?`.
17751
 */
17752
6.55k
void ada_clear_search(ada_url result) noexcept {
17753
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17754
6.55k
  if (r) {
17755
6.55k
    r->clear_search();
17756
6.55k
  }
17757
6.55k
}
17758
17759
6.55k
bool ada_has_credentials(ada_url result) noexcept {
17760
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17761
6.55k
  if (!r) {
17762
0
    return false;
17763
0
  }
17764
6.55k
  return r->has_credentials();
17765
6.55k
}
17766
17767
6.55k
bool ada_has_empty_hostname(ada_url result) noexcept {
17768
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17769
6.55k
  if (!r) {
17770
0
    return false;
17771
0
  }
17772
6.55k
  return r->has_empty_hostname();
17773
6.55k
}
17774
17775
6.55k
bool ada_has_hostname(ada_url result) noexcept {
17776
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17777
6.55k
  if (!r) {
17778
0
    return false;
17779
0
  }
17780
6.55k
  return r->has_hostname();
17781
6.55k
}
17782
17783
6.55k
bool ada_has_non_empty_username(ada_url result) noexcept {
17784
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17785
6.55k
  if (!r) {
17786
0
    return false;
17787
0
  }
17788
6.55k
  return r->has_non_empty_username();
17789
6.55k
}
17790
17791
6.55k
bool ada_has_non_empty_password(ada_url result) noexcept {
17792
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17793
6.55k
  if (!r) {
17794
0
    return false;
17795
0
  }
17796
6.55k
  return r->has_non_empty_password();
17797
6.55k
}
17798
17799
6.55k
bool ada_has_port(ada_url result) noexcept {
17800
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17801
6.55k
  if (!r) {
17802
0
    return false;
17803
0
  }
17804
6.55k
  return r->has_port();
17805
6.55k
}
17806
17807
6.55k
bool ada_has_password(ada_url result) noexcept {
17808
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17809
6.55k
  if (!r) {
17810
0
    return false;
17811
0
  }
17812
6.55k
  return r->has_password();
17813
6.55k
}
17814
17815
6.55k
bool ada_has_hash(ada_url result) noexcept {
17816
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17817
6.55k
  if (!r) {
17818
0
    return false;
17819
0
  }
17820
6.55k
  return r->has_hash();
17821
6.55k
}
17822
17823
6.55k
bool ada_has_search(ada_url result) noexcept {
17824
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17825
6.55k
  if (!r) {
17826
0
    return false;
17827
0
  }
17828
6.55k
  return r->has_search();
17829
6.55k
}
17830
17831
// returns a pointer to the internal url_aggregator::url_components
17832
6.55k
const ada_url_components* ada_get_components(ada_url result) noexcept {
17833
6.55k
  static_assert(sizeof(ada_url_components) == sizeof(ada::url_components));
17834
6.55k
  ada::result<ada::url_aggregator>& r = get_instance(result);
17835
6.55k
  if (!r) {
17836
0
    return nullptr;
17837
0
  }
17838
6.55k
  return reinterpret_cast<const ada_url_components*>(&r->get_components());
17839
6.55k
}
17840
17841
0
ada_owned_string ada_idna_to_unicode(const char* input, size_t length) {
17842
0
  std::string out = ada::idna::to_unicode(std::string_view(input, length));
17843
0
  ada_owned_string owned{};
17844
0
  owned.length = out.length();
17845
0
  owned.data = new char[owned.length];
17846
0
  memcpy((void*)owned.data, out.data(), owned.length);
17847
0
  return owned;
17848
0
}
17849
17850
0
ada_owned_string ada_idna_to_ascii(const char* input, size_t length) {
17851
0
  std::string out = ada::idna::to_ascii(std::string_view(input, length));
17852
0
  ada_owned_string owned{};
17853
0
  owned.length = out.size();
17854
0
  owned.data = new char[owned.length];
17855
0
  memcpy((void*)owned.data, out.data(), owned.length);
17856
0
  return owned;
17857
0
}
17858
17859
ada_url_search_params ada_parse_search_params(const char* input,
17860
0
                                              size_t length) {
17861
0
  return new ada::result<ada::url_search_params>(
17862
0
      ada::url_search_params(std::string_view(input, length)));
17863
0
}
17864
17865
0
void ada_free_search_params(ada_url_search_params result) {
17866
0
  auto* r = (ada::result<ada::url_search_params>*)result;
17867
0
  delete r;
17868
0
}
17869
17870
0
ada_owned_string ada_search_params_to_string(ada_url_search_params result) {
17871
0
  ada::result<ada::url_search_params>& r =
17872
0
      *(ada::result<ada::url_search_params>*)result;
17873
0
  if (!r) return ada_owned_string{nullptr, 0};
17874
0
  std::string out = r->to_string();
17875
0
  ada_owned_string owned{};
17876
0
  owned.length = out.size();
17877
0
  owned.data = new char[owned.length];
17878
0
  memcpy((void*)owned.data, out.data(), owned.length);
17879
0
  return owned;
17880
0
}
17881
17882
0
size_t ada_search_params_size(ada_url_search_params result) {
17883
0
  ada::result<ada::url_search_params>& r =
17884
0
      *(ada::result<ada::url_search_params>*)result;
17885
0
  if (!r) {
17886
0
    return 0;
17887
0
  }
17888
0
  return r->size();
17889
0
}
17890
17891
0
void ada_search_params_sort(ada_url_search_params result) {
17892
0
  ada::result<ada::url_search_params>& r =
17893
0
      *(ada::result<ada::url_search_params>*)result;
17894
0
  if (r) {
17895
0
    r->sort();
17896
0
  }
17897
0
}
17898
17899
void ada_search_params_reset(ada_url_search_params result, const char* input,
17900
0
                             size_t length) {
17901
0
  ada::result<ada::url_search_params>& r =
17902
0
      *(ada::result<ada::url_search_params>*)result;
17903
0
  if (r) {
17904
0
    r->reset(std::string_view(input, length));
17905
0
  }
17906
0
}
17907
17908
void ada_search_params_append(ada_url_search_params result, const char* key,
17909
                              size_t key_length, const char* value,
17910
0
                              size_t value_length) {
17911
0
  ada::result<ada::url_search_params>& r =
17912
0
      *(ada::result<ada::url_search_params>*)result;
17913
0
  if (r) {
17914
0
    r->append(std::string_view(key, key_length),
17915
0
              std::string_view(value, value_length));
17916
0
  }
17917
0
}
17918
17919
void ada_search_params_set(ada_url_search_params result, const char* key,
17920
                           size_t key_length, const char* value,
17921
0
                           size_t value_length) {
17922
0
  ada::result<ada::url_search_params>& r =
17923
0
      *(ada::result<ada::url_search_params>*)result;
17924
0
  if (r) {
17925
0
    r->set(std::string_view(key, key_length),
17926
0
           std::string_view(value, value_length));
17927
0
  }
17928
0
}
17929
17930
void ada_search_params_remove(ada_url_search_params result, const char* key,
17931
0
                              size_t key_length) {
17932
0
  ada::result<ada::url_search_params>& r =
17933
0
      *(ada::result<ada::url_search_params>*)result;
17934
0
  if (r) {
17935
0
    r->remove(std::string_view(key, key_length));
17936
0
  }
17937
0
}
17938
17939
void ada_search_params_remove_value(ada_url_search_params result,
17940
                                    const char* key, size_t key_length,
17941
0
                                    const char* value, size_t value_length) {
17942
0
  ada::result<ada::url_search_params>& r =
17943
0
      *(ada::result<ada::url_search_params>*)result;
17944
0
  if (r) {
17945
0
    r->remove(std::string_view(key, key_length),
17946
0
              std::string_view(value, value_length));
17947
0
  }
17948
0
}
17949
17950
bool ada_search_params_has(ada_url_search_params result, const char* key,
17951
0
                           size_t key_length) {
17952
0
  ada::result<ada::url_search_params>& r =
17953
0
      *(ada::result<ada::url_search_params>*)result;
17954
0
  if (!r) {
17955
0
    return false;
17956
0
  }
17957
0
  return r->has(std::string_view(key, key_length));
17958
0
}
17959
17960
bool ada_search_params_has_value(ada_url_search_params result, const char* key,
17961
                                 size_t key_length, const char* value,
17962
0
                                 size_t value_length) {
17963
0
  ada::result<ada::url_search_params>& r =
17964
0
      *(ada::result<ada::url_search_params>*)result;
17965
0
  if (!r) {
17966
0
    return false;
17967
0
  }
17968
0
  return r->has(std::string_view(key, key_length),
17969
0
                std::string_view(value, value_length));
17970
0
}
17971
17972
ada_string ada_search_params_get(ada_url_search_params result, const char* key,
17973
0
                                 size_t key_length) {
17974
0
  ada::result<ada::url_search_params>& r =
17975
0
      *(ada::result<ada::url_search_params>*)result;
17976
0
  if (!r) {
17977
0
    return ada_string_create(nullptr, 0);
17978
0
  }
17979
0
  auto found = r->get(std::string_view(key, key_length));
17980
0
  if (!found.has_value()) {
17981
0
    return ada_string_create(nullptr, 0);
17982
0
  }
17983
0
  return ada_string_create(found->data(), found->length());
17984
0
}
17985
17986
ada_strings ada_search_params_get_all(ada_url_search_params result,
17987
0
                                      const char* key, size_t key_length) {
17988
0
  ada::result<ada::url_search_params>& r =
17989
0
      *(ada::result<ada::url_search_params>*)result;
17990
0
  if (!r) {
17991
0
    return new ada::result<std::vector<std::string>>(
17992
0
        std::vector<std::string>());
17993
0
  }
17994
0
  return new ada::result<std::vector<std::string>>(
17995
0
      r->get_all(std::string_view(key, key_length)));
17996
0
}
17997
17998
ada_url_search_params_keys_iter ada_search_params_get_keys(
17999
0
    ada_url_search_params result) {
18000
0
  ada::result<ada::url_search_params>& r =
18001
0
      *(ada::result<ada::url_search_params>*)result;
18002
0
  if (!r) {
18003
0
    return new ada::result<ada::url_search_params_keys_iter>(
18004
0
        ada::url_search_params_keys_iter());
18005
0
  }
18006
0
  return new ada::result<ada::url_search_params_keys_iter>(r->get_keys());
18007
0
}
18008
18009
ada_url_search_params_values_iter ada_search_params_get_values(
18010
0
    ada_url_search_params result) {
18011
0
  ada::result<ada::url_search_params>& r =
18012
0
      *(ada::result<ada::url_search_params>*)result;
18013
0
  if (!r) {
18014
0
    return new ada::result<ada::url_search_params_values_iter>(
18015
0
        ada::url_search_params_values_iter());
18016
0
  }
18017
0
  return new ada::result<ada::url_search_params_values_iter>(r->get_values());
18018
0
}
18019
18020
ada_url_search_params_entries_iter ada_search_params_get_entries(
18021
0
    ada_url_search_params result) {
18022
0
  ada::result<ada::url_search_params>& r =
18023
0
      *(ada::result<ada::url_search_params>*)result;
18024
0
  if (!r) {
18025
0
    return new ada::result<ada::url_search_params_entries_iter>(
18026
0
        ada::url_search_params_entries_iter());
18027
0
  }
18028
0
  return new ada::result<ada::url_search_params_entries_iter>(r->get_entries());
18029
0
}
18030
18031
0
void ada_free_strings(ada_strings result) {
18032
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
18033
0
  delete r;
18034
0
}
18035
18036
0
size_t ada_strings_size(ada_strings result) {
18037
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
18038
0
  if (!r) {
18039
0
    return 0;
18040
0
  }
18041
0
  return (*r)->size();
18042
0
}
18043
18044
0
ada_string ada_strings_get(ada_strings result, size_t index) {
18045
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
18046
0
  if (!r) {
18047
0
    return ada_string_create(nullptr, 0);
18048
0
  }
18049
0
  std::string_view view = (*r)->at(index);
18050
0
  return ada_string_create(view.data(), view.length());
18051
0
}
18052
18053
0
void ada_free_search_params_keys_iter(ada_url_search_params_keys_iter result) {
18054
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
18055
0
  delete r;
18056
0
}
18057
18058
ada_string ada_search_params_keys_iter_next(
18059
0
    ada_url_search_params_keys_iter result) {
18060
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
18061
0
  if (!r) {
18062
0
    return ada_string_create(nullptr, 0);
18063
0
  }
18064
0
  auto next = (*r)->next();
18065
0
  if (!next.has_value()) {
18066
0
    return ada_string_create(nullptr, 0);
18067
0
  }
18068
0
  return ada_string_create(next->data(), next->length());
18069
0
}
18070
18071
bool ada_search_params_keys_iter_has_next(
18072
0
    ada_url_search_params_keys_iter result) {
18073
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
18074
0
  if (!r) {
18075
0
    return false;
18076
0
  }
18077
0
  return (*r)->has_next();
18078
0
}
18079
18080
void ada_free_search_params_values_iter(
18081
0
    ada_url_search_params_values_iter result) {
18082
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
18083
0
  delete r;
18084
0
}
18085
18086
ada_string ada_search_params_values_iter_next(
18087
0
    ada_url_search_params_values_iter result) {
18088
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
18089
0
  if (!r) {
18090
0
    return ada_string_create(nullptr, 0);
18091
0
  }
18092
0
  auto next = (*r)->next();
18093
0
  if (!next.has_value()) {
18094
0
    return ada_string_create(nullptr, 0);
18095
0
  }
18096
0
  return ada_string_create(next->data(), next->length());
18097
0
}
18098
18099
bool ada_search_params_values_iter_has_next(
18100
0
    ada_url_search_params_values_iter result) {
18101
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
18102
0
  if (!r) {
18103
0
    return false;
18104
0
  }
18105
0
  return (*r)->has_next();
18106
0
}
18107
18108
void ada_free_search_params_entries_iter(
18109
0
    ada_url_search_params_entries_iter result) {
18110
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
18111
0
  delete r;
18112
0
}
18113
18114
ada_string_pair ada_search_params_entries_iter_next(
18115
0
    ada_url_search_params_entries_iter result) {
18116
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
18117
0
  if (!r) return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)};
18118
0
  auto next = (*r)->next();
18119
0
  if (!next.has_value()) {
18120
0
    return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)};
18121
0
  }
18122
0
  return ada_string_pair{
18123
0
      ada_string_create(next->first.data(), next->first.length()),
18124
0
      ada_string_create(next->second.data(), next->second.length())};
18125
0
}
18126
18127
bool ada_search_params_entries_iter_has_next(
18128
0
    ada_url_search_params_entries_iter result) {
18129
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
18130
0
  if (!r) {
18131
0
    return false;
18132
0
  }
18133
0
  return (*r)->has_next();
18134
0
}
18135
18136
typedef struct {
18137
  int major;
18138
  int minor;
18139
  int revision;
18140
} ada_version_components;
18141
18142
0
const char* ada_get_version() { return ADA_VERSION; }
18143
18144
0
ada_version_components ada_get_version_components() {
18145
0
  return ada_version_components{
18146
0
      .major = ada::ADA_VERSION_MAJOR,
18147
0
      .minor = ada::ADA_VERSION_MINOR,
18148
0
      .revision = ada::ADA_VERSION_REVISION,
18149
0
  };
18150
0
}
18151
18152
}  // extern "C"
18153
// NOLINTEND(bugprone-exception-escape,
18154
// bugprone-suspicious-stringview-data-usage)
18155
/* end file src/ada_c.cpp */
18156
/* end file src/ada.cpp */