Coverage Report

Created: 2026-02-14 06:22

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-06 15:50:02 -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
36.3k
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
36.3k
  if (view.ends_with('.')) {
21
1.46k
    view.remove_suffix(1);
22
1.46k
    if (view.empty()) {
23
588
      return false;
24
588
    }
25
1.46k
  }
26
35.7k
  char last_char = view.back();
27
35.7k
  bool possible_ipv4 = (last_char >= '0' && last_char <= '9') ||
28
31.6k
                       (last_char >= 'a' && last_char <= 'f') ||
29
25.6k
                       last_char == 'x';
30
35.7k
  if (!possible_ipv4) {
31
25.0k
    return false;
32
25.0k
  }
33
  // From the last character, find the last dot.
34
10.7k
  size_t last_dot = view.rfind('.');
35
10.7k
  if (last_dot != std::string_view::npos) {
36
    // We have at least one dot.
37
2.71k
    view = view.substr(last_dot + 1);
38
2.71k
  }
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
10.7k
  if (std::ranges::all_of(view, ada::checkers::is_digit)) {
43
2.95k
    return true;
44
2.95k
  }
45
  // It could be hex (0x), but not if there is a single character.
46
7.80k
  if (view.size() == 1) {
47
1.16k
    return false;
48
1.16k
  }
49
  // It must start with 0x.
50
6.63k
  if (!view.starts_with("0x")) {
51
4.84k
    return false;
52
4.84k
  }
53
  // We must allow "0x".
54
1.79k
  if (view.size() == 2) {
55
92
    return true;
56
92
  }
57
  // We have 0x followed by some characters, we need to check that they are
58
  // hexadecimals.
59
1.69k
  view.remove_prefix(2);
60
1.69k
  return std::ranges::all_of(view, ada::unicode::is_lowercase_hex);
61
1.79k
}
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
29.5k
    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
29.5k
  size_t i = 0;
94
29.5k
  uint8_t accumulator{};
95
140k
  for (; i + 7 < input.size(); i += 8) {
96
111k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])] |
97
111k
                           path_signature_table[uint8_t(input[i + 1])] |
98
111k
                           path_signature_table[uint8_t(input[i + 2])] |
99
111k
                           path_signature_table[uint8_t(input[i + 3])] |
100
111k
                           path_signature_table[uint8_t(input[i + 4])] |
101
111k
                           path_signature_table[uint8_t(input[i + 5])] |
102
111k
                           path_signature_table[uint8_t(input[i + 6])] |
103
111k
                           path_signature_table[uint8_t(input[i + 7])]);
104
111k
  }
105
129k
  for (; i < input.size(); i++) {
106
100k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])]);
107
100k
  }
108
29.5k
  return accumulator;
109
29.5k
}
110
111
ada_really_inline constexpr bool verify_dns_length(
112
8.27k
    std::string_view input) noexcept {
113
8.27k
  if (input.back() == '.') {
114
878
    if (input.size() > 254) return false;
115
7.39k
  } else if (input.size() > 253)
116
51
    return false;
117
118
8.21k
  size_t start = 0;
119
25.0k
  while (start < input.size()) {
120
18.6k
    auto dot_location = input.find('.', start);
121
    // If not found, it's likely the end of the domain
122
18.6k
    if (dot_location == std::string_view::npos) dot_location = input.size();
123
124
18.6k
    auto label_size = dot_location - start;
125
18.6k
    if (label_size > 63 || label_size == 0) return false;
126
127
16.8k
    start = dot_location + 1;
128
16.8k
  }
129
130
6.36k
  return true;
131
8.21k
}
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
9.43k
size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) {
151
9.43k
  const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
152
9.43k
  size_t pos = 0;
153
9.43k
  const char32_t* start{utf32_output};
154
138k
  while (pos < len) {
155
    // try to convert the next block of 16 ASCII bytes
156
130k
    if (pos + 16 <= len) {  // if it is safe to read 16 more
157
                            // bytes, check that they are ascii
158
92.3k
      uint64_t v1;
159
92.3k
      std::memcpy(&v1, data + pos, sizeof(uint64_t));
160
92.3k
      uint64_t v2;
161
92.3k
      std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
162
92.3k
      uint64_t v{v1 | v2};
163
92.3k
      if ((v & 0x8080808080808080) == 0) {
164
1.66k
        size_t final_pos = pos + 16;
165
28.2k
        while (pos < final_pos) {
166
26.5k
          *utf32_output++ = char32_t(buf[pos]);
167
26.5k
          pos++;
168
26.5k
        }
169
1.66k
        continue;
170
1.66k
      }
171
92.3k
    }
172
129k
    uint8_t leading_byte = data[pos];  // leading byte
173
129k
    if (leading_byte < 0b10000000) {
174
      // converting one ASCII byte !!!
175
56.4k
      *utf32_output++ = char32_t(leading_byte);
176
56.4k
      pos++;
177
72.8k
    } else if ((leading_byte & 0b11100000) == 0b11000000) {
178
      // We have a two-byte UTF-8
179
10.0k
      if (pos + 1 >= len) {
180
214
        return 0;
181
214
      }  // minimal bound checking
182
9.84k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
183
160
        return 0;
184
160
      }
185
      // range check
186
9.68k
      uint32_t code_point =
187
9.68k
          (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
188
9.68k
      if (code_point < 0x80 || 0x7ff < code_point) {
189
18
        return 0;
190
18
      }
191
9.67k
      *utf32_output++ = char32_t(code_point);
192
9.67k
      pos += 2;
193
62.7k
    } else if ((leading_byte & 0b11110000) == 0b11100000) {
194
      // We have a three-byte UTF-8
195
60.2k
      if (pos + 2 >= len) {
196
56
        return 0;
197
56
      }  // minimal bound checking
198
199
60.2k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
200
68
        return 0;
201
68
      }
202
60.1k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
203
42
        return 0;
204
42
      }
205
      // range check
206
60.1k
      uint32_t code_point = (leading_byte & 0b00001111) << 12 |
207
60.1k
                            (data[pos + 1] & 0b00111111) << 6 |
208
60.1k
                            (data[pos + 2] & 0b00111111);
209
60.1k
      if (code_point < 0x800 || 0xffff < code_point ||
210
60.0k
          (0xd7ff < code_point && code_point < 0xe000)) {
211
28
        return 0;
212
28
      }
213
60.0k
      *utf32_output++ = char32_t(code_point);
214
60.0k
      pos += 3;
215
60.0k
    } else if ((leading_byte & 0b11111000) == 0b11110000) {  // 0b11110000
216
      // we have a 4-byte UTF-8 word.
217
1.17k
      if (pos + 3 >= len) {
218
62
        return 0;
219
62
      }  // minimal bound checking
220
1.11k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
221
70
        return 0;
222
70
      }
223
1.04k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
224
30
        return 0;
225
30
      }
226
1.01k
      if ((data[pos + 3] & 0b11000000) != 0b10000000) {
227
24
        return 0;
228
24
      }
229
230
      // range check
231
990
      uint32_t code_point = (leading_byte & 0b00000111) << 18 |
232
990
                            (data[pos + 1] & 0b00111111) << 12 |
233
990
                            (data[pos + 2] & 0b00111111) << 6 |
234
990
                            (data[pos + 3] & 0b00111111);
235
990
      if (code_point <= 0xffff || 0x10ffff < code_point) {
236
36
        return 0;
237
36
      }
238
954
      *utf32_output++ = char32_t(code_point);
239
954
      pos += 4;
240
1.31k
    } else {
241
1.31k
      return 0;
242
1.31k
    }
243
129k
  }
244
7.31k
  return utf32_output - start;
245
9.43k
}
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
9.43k
size_t utf32_length_from_utf8(const char* buf, size_t len) {
261
9.43k
  const int8_t* p = reinterpret_cast<const int8_t*>(buf);
262
336k
  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
336k
    return c > -65;
266
336k
  });
267
9.43k
}
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
180k
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
180k
  uint32_t len = std::size(table);
2800
180k
  uint32_t low = 0;
2801
180k
  uint32_t high = len - 1;
2802
2.41M
  while (low <= high) {
2803
2.31M
    uint32_t middle_index = (low + high) >> 1;  // cannot overflow
2804
2.31M
    uint32_t middle_value = table[middle_index][0];
2805
2.31M
    if (middle_value < key) {
2806
732k
      low = middle_index + 1;
2807
1.57M
    } else if (middle_value > key) {
2808
1.49M
      high = middle_index - 1;
2809
1.49M
    } else {
2810
79.2k
      return middle_index;  // perfect match
2811
79.2k
    }
2812
2.31M
  }
2813
100k
  return low == 0 ? 0 : low - 1;
2814
180k
}
2815
2816
6.44k
void ascii_map(char* input, size_t length) {
2817
19.3k
  auto broadcast = [](uint8_t v) -> uint64_t {
2818
19.3k
    return 0x101010101010101ull * v;
2819
19.3k
  };
2820
6.44k
  uint64_t broadcast_80 = broadcast(0x80);
2821
6.44k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
2822
6.44k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2823
6.44k
  size_t i = 0;
2824
2825
16.1k
  for (; i + 7 < length; i += 8) {
2826
9.67k
    uint64_t word{};
2827
9.67k
    memcpy(&word, input + i, sizeof(word));
2828
9.67k
    word ^=
2829
9.67k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2830
9.67k
    memcpy(input + i, &word, sizeof(word));
2831
9.67k
  }
2832
6.44k
  if (i < length) {
2833
5.90k
    uint64_t word{};
2834
5.90k
    memcpy(&word, input + i, length - i);
2835
5.90k
    word ^=
2836
5.90k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2837
5.90k
    memcpy(input + i, &word, length - i);
2838
5.90k
  }
2839
6.44k
}
2840
2841
// Map the characters according to IDNA, returning the empty string on error.
2842
12.2k
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.2k
  static std::u32string error = U"";
2857
12.2k
  std::u32string answer;
2858
12.2k
  answer.reserve(input.size());
2859
180k
  for (char32_t x : input) {
2860
180k
    size_t index = find_range_index(x);
2861
180k
    uint32_t descriptor = table[index][1];
2862
180k
    uint8_t code = uint8_t(descriptor);
2863
180k
    switch (code) {
2864
324
      case 0:
2865
324
        break;  // nothing to do, ignored
2866
106k
      case 1:
2867
106k
        answer.push_back(x);  // valid, we just copy it to output
2868
106k
        break;
2869
360
      case 2:
2870
360
        return error;  // disallowed
2871
      // case 3 :
2872
73.0k
      default:
2873
        // We have a mapping
2874
73.0k
        {
2875
73.0k
          size_t char_count = (descriptor >> 24);
2876
73.0k
          uint16_t char_index = uint16_t(descriptor >> 8);
2877
516k
          for (size_t idx = char_index; idx < char_index + char_count; idx++) {
2878
443k
            answer.push_back(mappings[idx]);
2879
443k
          }
2880
73.0k
        }
2881
180k
    }
2882
180k
  }
2883
11.8k
  return answer;
2884
12.2k
}
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
11.7k
    const std::u32string_view input) noexcept {
7804
11.7k
  bool decomposition_needed{false};
7805
11.7k
  size_t additional_elements{0};
7806
426k
  for (char32_t current_character : input) {
7807
426k
    size_t decomposition_length{0};
7808
7809
426k
    if (current_character >= hangul_sbase &&
7810
21.4k
        current_character < hangul_sbase + hangul_scount) {
7811
18.8k
      decomposition_length = 2;
7812
18.8k
      if ((current_character - hangul_sbase) % hangul_tcount) {
7813
5.49k
        decomposition_length = 3;
7814
5.49k
      }
7815
407k
    } else if (current_character < 0x110000) {
7816
407k
      const uint8_t di = decomposition_index[current_character >> 8];
7817
407k
      const uint16_t* const decomposition =
7818
407k
          decomposition_block[di] + (current_character % 256);
7819
407k
      decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
7820
407k
      if ((decomposition_length > 0) && (decomposition[0] & 1)) {
7821
0
        decomposition_length = 0;
7822
0
      }
7823
407k
    }
7824
426k
    if (decomposition_length != 0) {
7825
23.5k
      decomposition_needed = true;
7826
23.5k
      additional_elements += decomposition_length - 1;
7827
23.5k
    }
7828
426k
  }
7829
11.7k
  return {decomposition_needed, additional_elements};
7830
11.7k
}
7831
7832
3.79k
void decompose(std::u32string& input, size_t additional_elements) {
7833
3.79k
  input.resize(input.size() + additional_elements);
7834
3.79k
  for (size_t descending_idx = input.size(),
7835
3.79k
              input_count = descending_idx - additional_elements;
7836
216k
       input_count--;) {
7837
212k
    if (input[input_count] >= hangul_sbase &&
7838
19.5k
        input[input_count] < hangul_sbase + hangul_scount) {
7839
      // Hangul decomposition.
7840
18.8k
      char32_t s_index = input[input_count] - hangul_sbase;
7841
18.8k
      if (s_index % hangul_tcount != 0) {
7842
5.49k
        input[--descending_idx] = hangul_tbase + s_index % hangul_tcount;
7843
5.49k
      }
7844
18.8k
      input[--descending_idx] =
7845
18.8k
          hangul_vbase + (s_index % hangul_ncount) / hangul_tcount;
7846
18.8k
      input[--descending_idx] = hangul_lbase + s_index / hangul_ncount;
7847
193k
    } else if (input[input_count] < 0x110000) {
7848
      // Check decomposition_data.
7849
193k
      const uint16_t* decomposition =
7850
193k
          decomposition_block[decomposition_index[input[input_count] >> 8]] +
7851
193k
          (input[input_count] % 256);
7852
193k
      uint16_t decomposition_length =
7853
193k
          (decomposition[1] >> 2) - (decomposition[0] >> 2);
7854
193k
      if (decomposition_length > 0 && (decomposition[0] & 1)) {
7855
0
        decomposition_length = 0;
7856
0
      }
7857
193k
      if (decomposition_length > 0) {
7858
        // Non-recursive decomposition.
7859
15.6k
        while (decomposition_length-- > 0) {
7860
10.9k
          input[--descending_idx] = decomposition_data[(decomposition[0] >> 2) +
7861
10.9k
                                                       decomposition_length];
7862
10.9k
        }
7863
189k
      } else {
7864
        // No decomposition.
7865
189k
        input[--descending_idx] = input[input_count];
7866
189k
      }
7867
193k
    } else {
7868
      // Non-Unicode character.
7869
0
      input[--descending_idx] = input[input_count];
7870
0
    }
7871
212k
  }
7872
3.79k
}
7873
7874
861k
uint8_t get_ccc(char32_t c) noexcept {
7875
861k
  return c < 0x110000 ? canonical_combining_class_block
7876
861k
                            [canonical_combining_class_index[c >> 8]][c % 256]
7877
861k
                      : 0;
7878
861k
}
7879
7880
11.7k
void sort_marks(std::u32string& input) {
7881
456k
  for (size_t idx = 1; idx < input.size(); idx++) {
7882
445k
    uint8_t ccc = get_ccc(input[idx]);
7883
445k
    if (ccc == 0) {
7884
432k
      continue;
7885
432k
    }  // Skip non-combining characters.
7886
12.5k
    auto current_character = input[idx];
7887
12.5k
    size_t back_idx = idx;
7888
14.8k
    while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) {
7889
2.34k
      input[back_idx] = input[back_idx - 1];
7890
2.34k
      back_idx--;
7891
2.34k
    }
7892
12.5k
    input[back_idx] = current_character;
7893
12.5k
  }
7894
11.7k
}
7895
7896
11.7k
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
11.7k
  auto [decomposition_needed, additional_elements] =
7902
11.7k
      compute_decomposition_length(input);
7903
11.7k
  if (decomposition_needed) {
7904
3.79k
    decompose(input, additional_elements);
7905
3.79k
  }
7906
11.7k
  sort_marks(input);
7907
11.7k
}
7908
7909
11.7k
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
11.7k
  size_t input_count{0};
7915
11.7k
  size_t composition_count{0};
7916
431k
  for (; input_count < input.size(); input_count++, composition_count++) {
7917
419k
    input[composition_count] = input[input_count];
7918
419k
    if (input[input_count] >= hangul_lbase &&
7919
204k
        input[input_count] < hangul_lbase + hangul_lcount) {
7920
20.2k
      if (input_count + 1 < input.size() &&
7921
19.9k
          input[input_count + 1] >= hangul_vbase &&
7922
19.0k
          input[input_count + 1] < hangul_vbase + hangul_vcount) {
7923
18.8k
        input[composition_count] =
7924
18.8k
            hangul_sbase +
7925
18.8k
            ((input[input_count] - hangul_lbase) * hangul_vcount +
7926
18.8k
             input[input_count + 1] - hangul_vbase) *
7927
18.8k
                hangul_tcount;
7928
18.8k
        input_count++;
7929
18.8k
        if (input_count + 1 < input.size() &&
7930
18.6k
            input[input_count + 1] > hangul_tbase &&
7931
5.75k
            input[input_count + 1] < hangul_tbase + hangul_tcount) {
7932
5.49k
          input[composition_count] += input[++input_count] - hangul_tbase;
7933
5.49k
        }
7934
18.8k
      }
7935
399k
    } else if (input[input_count] >= hangul_sbase &&
7936
1.86k
               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
399k
    } else if (input[input_count] < 0x110000) {
7944
399k
      const uint16_t* composition =
7945
399k
          &composition_block[composition_index[input[input_count] >> 8]]
7946
399k
                            [input[input_count] % 256];
7947
399k
      size_t initial_composition_count = composition_count;
7948
412k
      for (int32_t previous_ccc = -1; input_count + 1 < input.size();
7949
401k
           input_count++) {
7950
401k
        uint8_t ccc = get_ccc(input[input_count + 1]);
7951
7952
401k
        if (composition[1] != composition[0] && previous_ccc < ccc) {
7953
          // Try finding a composition.
7954
88.1k
          int left = composition[0];
7955
88.1k
          int right = composition[1];
7956
218k
          while (left + 2 < right) {
7957
            // mean without overflow
7958
130k
            int middle = left + (((right - left) >> 1) & ~1);
7959
130k
            if (composition_data[middle] <= input[input_count + 1]) {
7960
11.8k
              left = middle;
7961
11.8k
            }
7962
130k
            if (composition_data[middle] >= input[input_count + 1]) {
7963
121k
              right = middle;
7964
121k
            }
7965
130k
          }
7966
88.1k
          if (composition_data[left] == input[input_count + 1]) {
7967
6.23k
            input[initial_composition_count] = composition_data[left + 1];
7968
6.23k
            composition =
7969
6.23k
                &composition_block
7970
6.23k
                    [composition_index[composition_data[left + 1] >> 8]]
7971
6.23k
                    [composition_data[left + 1] % 256];
7972
6.23k
            continue;
7973
6.23k
          }
7974
88.1k
        }
7975
7976
395k
        if (ccc == 0) {
7977
388k
          break;
7978
388k
        }  // Not a combining character.
7979
6.29k
        previous_ccc = ccc;
7980
6.29k
        input[++composition_count] = input[input_count + 1];
7981
6.29k
      }
7982
399k
    }
7983
419k
  }
7984
7985
11.7k
  if (composition_count < input_count) {
7986
3.81k
    input.resize(composition_count);
7987
3.81k
  }
7988
11.7k
}
7989
7990
11.7k
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
11.7k
  decompose_nfc(input);
7996
11.7k
  compose(input);
7997
11.7k
}
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
53.0k
static constexpr int32_t char_to_digit_value(char value) {
8016
53.0k
  if (value >= 'a' && value <= 'z') return value - 'a';
8017
6.67k
  if (value >= '0' && value <= '9') return value - '0' + 26;
8018
84
  return -1;
8019
6.67k
}
8020
8021
639k
static constexpr char digit_to_char(int32_t digit) {
8022
639k
  return digit < 26 ? char(digit + 97) : char(digit + 22);
8023
639k
}
8024
8025
288k
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
8026
288k
  if (firsttime) {
8027
35.2k
    d = d / damp;
8028
253k
  } else {
8029
253k
    d = d / 2;
8030
253k
  }
8031
288k
  d += d / n;
8032
288k
  int32_t k = 0;
8033
423k
  while (d > ((base - tmin) * tmax) / 2) {
8034
134k
    d /= base - tmin;
8035
134k
    k += base;
8036
134k
  }
8037
288k
  return k + (((base - tmin + 1) * d) / (d + skew));
8038
288k
}
8039
8040
5.52k
bool punycode_to_utf32(std::string_view input, std::u32string &out) {
8041
  // See https://github.com/whatwg/url/issues/803
8042
5.52k
  if (input.starts_with("xn--")) {
8043
6
    return false;
8044
6
  }
8045
5.51k
  int32_t written_out{0};
8046
5.51k
  out.reserve(out.size() + input.size());
8047
5.51k
  uint32_t n = initial_n;
8048
5.51k
  int32_t i = 0;
8049
5.51k
  int32_t bias = initial_bias;
8050
  // grab ascii content
8051
5.51k
  size_t end_of_ascii = input.find_last_of('-');
8052
5.51k
  if (end_of_ascii != std::string_view::npos) {
8053
4.07k
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8054
4.07k
      if (c >= 0x80) {
8055
0
        return false;
8056
0
      }
8057
4.07k
      out.push_back(c);
8058
4.07k
      written_out++;
8059
4.07k
    }
8060
624
    input.remove_prefix(end_of_ascii + 1);
8061
624
  }
8062
44.7k
  while (!input.empty()) {
8063
39.6k
    int32_t oldi = i;
8064
39.6k
    int32_t w = 1;
8065
53.2k
    for (int32_t k = base;; k += base) {
8066
53.2k
      if (input.empty()) {
8067
174
        return false;
8068
174
      }
8069
53.0k
      uint8_t code_point = input.front();
8070
53.0k
      input.remove_prefix(1);
8071
53.0k
      int32_t digit = char_to_digit_value(code_point);
8072
53.0k
      if (digit < 0) {
8073
84
        return false;
8074
84
      }
8075
52.9k
      if (digit > (0x7fffffff - i) / w) {
8076
34
        return false;
8077
34
      }
8078
52.9k
      i = i + digit * w;
8079
52.9k
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8080
52.9k
      if (digit < t) {
8081
39.3k
        break;
8082
39.3k
      }
8083
13.5k
      if (w > 0x7fffffff / (base - t)) {
8084
0
        return false;
8085
0
      }
8086
13.5k
      w = w * (base - t);
8087
13.5k
    }
8088
39.3k
    bias = adapt(i - oldi, written_out + 1, oldi == 0);
8089
39.3k
    if (i / (written_out + 1) > int32_t(0x7fffffff - n)) {
8090
70
      return false;
8091
70
    }
8092
39.2k
    n = n + i / (written_out + 1);
8093
39.2k
    i = i % (written_out + 1);
8094
39.2k
    if (n < 0x80) {
8095
0
      return false;
8096
0
    }
8097
39.2k
    out.insert(out.begin() + i, n);
8098
39.2k
    written_out++;
8099
39.2k
    ++i;
8100
39.2k
  }
8101
5.15k
  return true;
8102
5.51k
}
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
30.1k
bool utf32_to_punycode(std::u32string_view input, std::string &out) {
8166
30.1k
  out.reserve(input.size() + out.size());
8167
30.1k
  uint32_t n = initial_n;
8168
30.1k
  int32_t d = 0;
8169
30.1k
  int32_t bias = initial_bias;
8170
30.1k
  size_t h = 0;
8171
  // first push the ascii content
8172
286k
  for (uint32_t c : input) {
8173
286k
    if (c < 0x80) {
8174
36.7k
      ++h;
8175
36.7k
      out.push_back(char(c));
8176
36.7k
    }
8177
286k
    if (c > 0x10ffff || (c >= 0xd800 && c < 0xe000)) {
8178
0
      return false;
8179
0
    }
8180
286k
  }
8181
30.1k
  size_t b = h;
8182
30.1k
  if (b > 0) {
8183
10.7k
    out.push_back('-');
8184
10.7k
  }
8185
198k
  while (h < input.size()) {
8186
168k
    uint32_t m = 0x10FFFF;
8187
2.76M
    for (auto code_point : input) {
8188
2.76M
      if (code_point >= n && code_point < m) m = code_point;
8189
2.76M
    }
8190
8191
168k
    if ((m - n) > (0x7fffffff - d) / (h + 1)) {
8192
0
      return false;
8193
0
    }
8194
168k
    d = d + int32_t((m - n) * (h + 1));
8195
168k
    n = m;
8196
2.76M
    for (auto c : input) {
8197
2.76M
      if (c < n) {
8198
1.45M
        if (d == 0x7fffffff) {
8199
0
          return false;
8200
0
        }
8201
1.45M
        ++d;
8202
1.45M
      }
8203
2.76M
      if (c == n) {
8204
249k
        int32_t q = d;
8205
639k
        for (int32_t k = base;; k += base) {
8206
639k
          int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8207
8208
639k
          if (q < t) {
8209
249k
            break;
8210
249k
          }
8211
389k
          out.push_back(digit_to_char(t + ((q - t) % (base - t))));
8212
389k
          q = (q - t) / (base - t);
8213
389k
        }
8214
249k
        out.push_back(digit_to_char(q));
8215
249k
        bias = adapt(d, int32_t(h + 1), h == b);
8216
249k
        d = 0;
8217
249k
        ++h;
8218
249k
      }
8219
2.76M
    }
8220
168k
    ++d;
8221
168k
    ++n;
8222
168k
  }
8223
30.1k
  return true;
8224
30.1k
}
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
316k
inline static direction find_direction(uint32_t code_point) noexcept {
8997
316k
  auto it = std::lower_bound(
8998
316k
      std::begin(dir_table), std::end(dir_table), code_point,
8999
3.23M
      [](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
316k
  if (it == std::end(dir_table)) {
9003
0
    return direction::NONE;
9004
0
  }
9005
  // We have that d.final_code >= c.
9006
316k
  if (code_point >= it->start_code) {
9007
314k
    return it->direct;
9008
314k
  }
9009
1.23k
  return direction::NONE;
9010
316k
}
9011
9012
inline static size_t find_last_not_of_nsm(
9013
33.6k
    const std::u32string_view label) noexcept {
9014
36.1k
  for (int i = static_cast<int>(label.size() - 1); i >= 0; i--)
9015
36.1k
    if (find_direction(label[i]) != direction::NSM) return i;
9016
9017
0
  return std::u32string_view::npos;
9018
33.6k
}
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
33.6k
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
9023
33.6k
  const size_t mask =
9024
33.6k
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
9025
9026
33.6k
  size_t directions = 0;
9027
299k
  for (size_t i = 0; i < label.size(); i++) {
9028
265k
    directions |= 1u << find_direction(label[i]);
9029
265k
  }
9030
33.6k
  return (directions & mask) != 0;
9031
33.6k
}
9032
9033
35.5k
bool is_label_valid(const std::u32string_view label) {
9034
35.5k
  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
35.5k
  constexpr static uint32_t combining[] = {
9060
35.5k
      0x300,   0x301,   0x302,   0x303,   0x304,   0x305,   0x306,   0x307,
9061
35.5k
      0x308,   0x309,   0x30a,   0x30b,   0x30c,   0x30d,   0x30e,   0x30f,
9062
35.5k
      0x310,   0x311,   0x312,   0x313,   0x314,   0x315,   0x316,   0x317,
9063
35.5k
      0x318,   0x319,   0x31a,   0x31b,   0x31c,   0x31d,   0x31e,   0x31f,
9064
35.5k
      0x320,   0x321,   0x322,   0x323,   0x324,   0x325,   0x326,   0x327,
9065
35.5k
      0x328,   0x329,   0x32a,   0x32b,   0x32c,   0x32d,   0x32e,   0x32f,
9066
35.5k
      0x330,   0x331,   0x332,   0x333,   0x334,   0x335,   0x336,   0x337,
9067
35.5k
      0x338,   0x339,   0x33a,   0x33b,   0x33c,   0x33d,   0x33e,   0x33f,
9068
35.5k
      0x340,   0x341,   0x342,   0x343,   0x344,   0x345,   0x346,   0x347,
9069
35.5k
      0x348,   0x349,   0x34a,   0x34b,   0x34c,   0x34d,   0x34e,   0x34f,
9070
35.5k
      0x350,   0x351,   0x352,   0x353,   0x354,   0x355,   0x356,   0x357,
9071
35.5k
      0x358,   0x359,   0x35a,   0x35b,   0x35c,   0x35d,   0x35e,   0x35f,
9072
35.5k
      0x360,   0x361,   0x362,   0x363,   0x364,   0x365,   0x366,   0x367,
9073
35.5k
      0x368,   0x369,   0x36a,   0x36b,   0x36c,   0x36d,   0x36e,   0x36f,
9074
35.5k
      0x483,   0x484,   0x485,   0x486,   0x487,   0x488,   0x489,   0x591,
9075
35.5k
      0x592,   0x593,   0x594,   0x595,   0x596,   0x597,   0x598,   0x599,
9076
35.5k
      0x59a,   0x59b,   0x59c,   0x59d,   0x59e,   0x59f,   0x5a0,   0x5a1,
9077
35.5k
      0x5a2,   0x5a3,   0x5a4,   0x5a5,   0x5a6,   0x5a7,   0x5a8,   0x5a9,
9078
35.5k
      0x5aa,   0x5ab,   0x5ac,   0x5ad,   0x5ae,   0x5af,   0x5b0,   0x5b1,
9079
35.5k
      0x5b2,   0x5b3,   0x5b4,   0x5b5,   0x5b6,   0x5b7,   0x5b8,   0x5b9,
9080
35.5k
      0x5ba,   0x5bb,   0x5bc,   0x5bd,   0x5bf,   0x5c1,   0x5c2,   0x5c4,
9081
35.5k
      0x5c5,   0x5c7,   0x610,   0x611,   0x612,   0x613,   0x614,   0x615,
9082
35.5k
      0x616,   0x617,   0x618,   0x619,   0x61a,   0x64b,   0x64c,   0x64d,
9083
35.5k
      0x64e,   0x64f,   0x650,   0x651,   0x652,   0x653,   0x654,   0x655,
9084
35.5k
      0x656,   0x657,   0x658,   0x659,   0x65a,   0x65b,   0x65c,   0x65d,
9085
35.5k
      0x65e,   0x65f,   0x670,   0x6d6,   0x6d7,   0x6d8,   0x6d9,   0x6da,
9086
35.5k
      0x6db,   0x6dc,   0x6df,   0x6e0,   0x6e1,   0x6e2,   0x6e3,   0x6e4,
9087
35.5k
      0x6e7,   0x6e8,   0x6ea,   0x6eb,   0x6ec,   0x6ed,   0x711,   0x730,
9088
35.5k
      0x731,   0x732,   0x733,   0x734,   0x735,   0x736,   0x737,   0x738,
9089
35.5k
      0x739,   0x73a,   0x73b,   0x73c,   0x73d,   0x73e,   0x73f,   0x740,
9090
35.5k
      0x741,   0x742,   0x743,   0x744,   0x745,   0x746,   0x747,   0x748,
9091
35.5k
      0x749,   0x74a,   0x7a6,   0x7a7,   0x7a8,   0x7a9,   0x7aa,   0x7ab,
9092
35.5k
      0x7ac,   0x7ad,   0x7ae,   0x7af,   0x7b0,   0x7eb,   0x7ec,   0x7ed,
9093
35.5k
      0x7ee,   0x7ef,   0x7f0,   0x7f1,   0x7f2,   0x7f3,   0x7fd,   0x816,
9094
35.5k
      0x817,   0x818,   0x819,   0x81b,   0x81c,   0x81d,   0x81e,   0x81f,
9095
35.5k
      0x820,   0x821,   0x822,   0x823,   0x825,   0x826,   0x827,   0x829,
9096
35.5k
      0x82a,   0x82b,   0x82c,   0x82d,   0x859,   0x85a,   0x85b,   0x8d3,
9097
35.5k
      0x8d4,   0x8d5,   0x8d6,   0x8d7,   0x8d8,   0x8d9,   0x8da,   0x8db,
9098
35.5k
      0x8dc,   0x8dd,   0x8de,   0x8df,   0x8e0,   0x8e1,   0x8e3,   0x8e4,
9099
35.5k
      0x8e5,   0x8e6,   0x8e7,   0x8e8,   0x8e9,   0x8ea,   0x8eb,   0x8ec,
9100
35.5k
      0x8ed,   0x8ee,   0x8ef,   0x8f0,   0x8f1,   0x8f2,   0x8f3,   0x8f4,
9101
35.5k
      0x8f5,   0x8f6,   0x8f7,   0x8f8,   0x8f9,   0x8fa,   0x8fb,   0x8fc,
9102
35.5k
      0x8fd,   0x8fe,   0x8ff,   0x900,   0x901,   0x902,   0x903,   0x93a,
9103
35.5k
      0x93b,   0x93c,   0x93e,   0x93f,   0x940,   0x941,   0x942,   0x943,
9104
35.5k
      0x944,   0x945,   0x946,   0x947,   0x948,   0x949,   0x94a,   0x94b,
9105
35.5k
      0x94c,   0x94d,   0x94e,   0x94f,   0x951,   0x952,   0x953,   0x954,
9106
35.5k
      0x955,   0x956,   0x957,   0x962,   0x963,   0x981,   0x982,   0x983,
9107
35.5k
      0x9bc,   0x9be,   0x9bf,   0x9c0,   0x9c1,   0x9c2,   0x9c3,   0x9c4,
9108
35.5k
      0x9c7,   0x9c8,   0x9cb,   0x9cc,   0x9cd,   0x9d7,   0x9e2,   0x9e3,
9109
35.5k
      0x9fe,   0xa01,   0xa02,   0xa03,   0xa3c,   0xa3e,   0xa3f,   0xa40,
9110
35.5k
      0xa41,   0xa42,   0xa47,   0xa48,   0xa4b,   0xa4c,   0xa4d,   0xa51,
9111
35.5k
      0xa70,   0xa71,   0xa75,   0xa81,   0xa82,   0xa83,   0xabc,   0xabe,
9112
35.5k
      0xabf,   0xac0,   0xac1,   0xac2,   0xac3,   0xac4,   0xac5,   0xac7,
9113
35.5k
      0xac8,   0xac9,   0xacb,   0xacc,   0xacd,   0xae2,   0xae3,   0xafa,
9114
35.5k
      0xafb,   0xafc,   0xafd,   0xafe,   0xaff,   0xb01,   0xb02,   0xb03,
9115
35.5k
      0xb3c,   0xb3e,   0xb3f,   0xb40,   0xb41,   0xb42,   0xb43,   0xb44,
9116
35.5k
      0xb47,   0xb48,   0xb4b,   0xb4c,   0xb4d,   0xb55,   0xb56,   0xb57,
9117
35.5k
      0xb62,   0xb63,   0xb82,   0xbbe,   0xbbf,   0xbc0,   0xbc1,   0xbc2,
9118
35.5k
      0xbc6,   0xbc7,   0xbc8,   0xbca,   0xbcb,   0xbcc,   0xbcd,   0xbd7,
9119
35.5k
      0xc00,   0xc01,   0xc02,   0xc03,   0xc04,   0xc3e,   0xc3f,   0xc40,
9120
35.5k
      0xc41,   0xc42,   0xc43,   0xc44,   0xc46,   0xc47,   0xc48,   0xc4a,
9121
35.5k
      0xc4b,   0xc4c,   0xc4d,   0xc55,   0xc56,   0xc62,   0xc63,   0xc81,
9122
35.5k
      0xc82,   0xc83,   0xcbc,   0xcbe,   0xcbf,   0xcc0,   0xcc1,   0xcc2,
9123
35.5k
      0xcc3,   0xcc4,   0xcc6,   0xcc7,   0xcc8,   0xcca,   0xccb,   0xccc,
9124
35.5k
      0xccd,   0xcd5,   0xcd6,   0xce2,   0xce3,   0xd00,   0xd01,   0xd02,
9125
35.5k
      0xd03,   0xd3b,   0xd3c,   0xd3e,   0xd3f,   0xd40,   0xd41,   0xd42,
9126
35.5k
      0xd43,   0xd44,   0xd46,   0xd47,   0xd48,   0xd4a,   0xd4b,   0xd4c,
9127
35.5k
      0xd4d,   0xd57,   0xd62,   0xd63,   0xd81,   0xd82,   0xd83,   0xdca,
9128
35.5k
      0xdcf,   0xdd0,   0xdd1,   0xdd2,   0xdd3,   0xdd4,   0xdd6,   0xdd8,
9129
35.5k
      0xdd9,   0xdda,   0xddb,   0xddc,   0xddd,   0xdde,   0xddf,   0xdf2,
9130
35.5k
      0xdf3,   0xe31,   0xe34,   0xe35,   0xe36,   0xe37,   0xe38,   0xe39,
9131
35.5k
      0xe3a,   0xe47,   0xe48,   0xe49,   0xe4a,   0xe4b,   0xe4c,   0xe4d,
9132
35.5k
      0xe4e,   0xeb1,   0xeb4,   0xeb5,   0xeb6,   0xeb7,   0xeb8,   0xeb9,
9133
35.5k
      0xeba,   0xebb,   0xebc,   0xec8,   0xec9,   0xeca,   0xecb,   0xecc,
9134
35.5k
      0xecd,   0xf18,   0xf19,   0xf35,   0xf37,   0xf39,   0xf3e,   0xf3f,
9135
35.5k
      0xf71,   0xf72,   0xf73,   0xf74,   0xf75,   0xf76,   0xf77,   0xf78,
9136
35.5k
      0xf79,   0xf7a,   0xf7b,   0xf7c,   0xf7d,   0xf7e,   0xf7f,   0xf80,
9137
35.5k
      0xf81,   0xf82,   0xf83,   0xf84,   0xf86,   0xf87,   0xf8d,   0xf8e,
9138
35.5k
      0xf8f,   0xf90,   0xf91,   0xf92,   0xf93,   0xf94,   0xf95,   0xf96,
9139
35.5k
      0xf97,   0xf99,   0xf9a,   0xf9b,   0xf9c,   0xf9d,   0xf9e,   0xf9f,
9140
35.5k
      0xfa0,   0xfa1,   0xfa2,   0xfa3,   0xfa4,   0xfa5,   0xfa6,   0xfa7,
9141
35.5k
      0xfa8,   0xfa9,   0xfaa,   0xfab,   0xfac,   0xfad,   0xfae,   0xfaf,
9142
35.5k
      0xfb0,   0xfb1,   0xfb2,   0xfb3,   0xfb4,   0xfb5,   0xfb6,   0xfb7,
9143
35.5k
      0xfb8,   0xfb9,   0xfba,   0xfbb,   0xfbc,   0xfc6,   0x102b,  0x102c,
9144
35.5k
      0x102d,  0x102e,  0x102f,  0x1030,  0x1031,  0x1032,  0x1033,  0x1034,
9145
35.5k
      0x1035,  0x1036,  0x1037,  0x1038,  0x1039,  0x103a,  0x103b,  0x103c,
9146
35.5k
      0x103d,  0x103e,  0x1056,  0x1057,  0x1058,  0x1059,  0x105e,  0x105f,
9147
35.5k
      0x1060,  0x1062,  0x1063,  0x1064,  0x1067,  0x1068,  0x1069,  0x106a,
9148
35.5k
      0x106b,  0x106c,  0x106d,  0x1071,  0x1072,  0x1073,  0x1074,  0x1082,
9149
35.5k
      0x1083,  0x1084,  0x1085,  0x1086,  0x1087,  0x1088,  0x1089,  0x108a,
9150
35.5k
      0x108b,  0x108c,  0x108d,  0x108f,  0x109a,  0x109b,  0x109c,  0x109d,
9151
35.5k
      0x135d,  0x135e,  0x135f,  0x1712,  0x1713,  0x1714,  0x1732,  0x1733,
9152
35.5k
      0x1734,  0x1752,  0x1753,  0x1772,  0x1773,  0x17b4,  0x17b5,  0x17b6,
9153
35.5k
      0x17b7,  0x17b8,  0x17b9,  0x17ba,  0x17bb,  0x17bc,  0x17bd,  0x17be,
9154
35.5k
      0x17bf,  0x17c0,  0x17c1,  0x17c2,  0x17c3,  0x17c4,  0x17c5,  0x17c6,
9155
35.5k
      0x17c7,  0x17c8,  0x17c9,  0x17ca,  0x17cb,  0x17cc,  0x17cd,  0x17ce,
9156
35.5k
      0x17cf,  0x17d0,  0x17d1,  0x17d2,  0x17d3,  0x17dd,  0x180b,  0x180c,
9157
35.5k
      0x180d,  0x1885,  0x1886,  0x18a9,  0x1920,  0x1921,  0x1922,  0x1923,
9158
35.5k
      0x1924,  0x1925,  0x1926,  0x1927,  0x1928,  0x1929,  0x192a,  0x192b,
9159
35.5k
      0x1930,  0x1931,  0x1932,  0x1933,  0x1934,  0x1935,  0x1936,  0x1937,
9160
35.5k
      0x1938,  0x1939,  0x193a,  0x193b,  0x1a17,  0x1a18,  0x1a19,  0x1a1a,
9161
35.5k
      0x1a1b,  0x1a55,  0x1a56,  0x1a57,  0x1a58,  0x1a59,  0x1a5a,  0x1a5b,
9162
35.5k
      0x1a5c,  0x1a5d,  0x1a5e,  0x1a60,  0x1a61,  0x1a62,  0x1a63,  0x1a64,
9163
35.5k
      0x1a65,  0x1a66,  0x1a67,  0x1a68,  0x1a69,  0x1a6a,  0x1a6b,  0x1a6c,
9164
35.5k
      0x1a6d,  0x1a6e,  0x1a6f,  0x1a70,  0x1a71,  0x1a72,  0x1a73,  0x1a74,
9165
35.5k
      0x1a75,  0x1a76,  0x1a77,  0x1a78,  0x1a79,  0x1a7a,  0x1a7b,  0x1a7c,
9166
35.5k
      0x1a7f,  0x1ab0,  0x1ab1,  0x1ab2,  0x1ab3,  0x1ab4,  0x1ab5,  0x1ab6,
9167
35.5k
      0x1ab7,  0x1ab8,  0x1ab9,  0x1aba,  0x1abb,  0x1abc,  0x1abd,  0x1abe,
9168
35.5k
      0x1abf,  0x1ac0,  0x1b00,  0x1b01,  0x1b02,  0x1b03,  0x1b04,  0x1b34,
9169
35.5k
      0x1b35,  0x1b36,  0x1b37,  0x1b38,  0x1b39,  0x1b3a,  0x1b3b,  0x1b3c,
9170
35.5k
      0x1b3d,  0x1b3e,  0x1b3f,  0x1b40,  0x1b41,  0x1b42,  0x1b43,  0x1b44,
9171
35.5k
      0x1b6b,  0x1b6c,  0x1b6d,  0x1b6e,  0x1b6f,  0x1b70,  0x1b71,  0x1b72,
9172
35.5k
      0x1b73,  0x1b80,  0x1b81,  0x1b82,  0x1ba1,  0x1ba2,  0x1ba3,  0x1ba4,
9173
35.5k
      0x1ba5,  0x1ba6,  0x1ba7,  0x1ba8,  0x1ba9,  0x1baa,  0x1bab,  0x1bac,
9174
35.5k
      0x1bad,  0x1be6,  0x1be7,  0x1be8,  0x1be9,  0x1bea,  0x1beb,  0x1bec,
9175
35.5k
      0x1bed,  0x1bee,  0x1bef,  0x1bf0,  0x1bf1,  0x1bf2,  0x1bf3,  0x1c24,
9176
35.5k
      0x1c25,  0x1c26,  0x1c27,  0x1c28,  0x1c29,  0x1c2a,  0x1c2b,  0x1c2c,
9177
35.5k
      0x1c2d,  0x1c2e,  0x1c2f,  0x1c30,  0x1c31,  0x1c32,  0x1c33,  0x1c34,
9178
35.5k
      0x1c35,  0x1c36,  0x1c37,  0x1cd0,  0x1cd1,  0x1cd2,  0x1cd4,  0x1cd5,
9179
35.5k
      0x1cd6,  0x1cd7,  0x1cd8,  0x1cd9,  0x1cda,  0x1cdb,  0x1cdc,  0x1cdd,
9180
35.5k
      0x1cde,  0x1cdf,  0x1ce0,  0x1ce1,  0x1ce2,  0x1ce3,  0x1ce4,  0x1ce5,
9181
35.5k
      0x1ce6,  0x1ce7,  0x1ce8,  0x1ced,  0x1cf4,  0x1cf7,  0x1cf8,  0x1cf9,
9182
35.5k
      0x1dc0,  0x1dc1,  0x1dc2,  0x1dc3,  0x1dc4,  0x1dc5,  0x1dc6,  0x1dc7,
9183
35.5k
      0x1dc8,  0x1dc9,  0x1dca,  0x1dcb,  0x1dcc,  0x1dcd,  0x1dce,  0x1dcf,
9184
35.5k
      0x1dd0,  0x1dd1,  0x1dd2,  0x1dd3,  0x1dd4,  0x1dd5,  0x1dd6,  0x1dd7,
9185
35.5k
      0x1dd8,  0x1dd9,  0x1dda,  0x1ddb,  0x1ddc,  0x1ddd,  0x1dde,  0x1ddf,
9186
35.5k
      0x1de0,  0x1de1,  0x1de2,  0x1de3,  0x1de4,  0x1de5,  0x1de6,  0x1de7,
9187
35.5k
      0x1de8,  0x1de9,  0x1dea,  0x1deb,  0x1dec,  0x1ded,  0x1dee,  0x1def,
9188
35.5k
      0x1df0,  0x1df1,  0x1df2,  0x1df3,  0x1df4,  0x1df5,  0x1df6,  0x1df7,
9189
35.5k
      0x1df8,  0x1df9,  0x1dfb,  0x1dfc,  0x1dfd,  0x1dfe,  0x1dff,  0x20d0,
9190
35.5k
      0x20d1,  0x20d2,  0x20d3,  0x20d4,  0x20d5,  0x20d6,  0x20d7,  0x20d8,
9191
35.5k
      0x20d9,  0x20da,  0x20db,  0x20dc,  0x20dd,  0x20de,  0x20df,  0x20e0,
9192
35.5k
      0x20e1,  0x20e2,  0x20e3,  0x20e4,  0x20e5,  0x20e6,  0x20e7,  0x20e8,
9193
35.5k
      0x20e9,  0x20ea,  0x20eb,  0x20ec,  0x20ed,  0x20ee,  0x20ef,  0x20f0,
9194
35.5k
      0x2cef,  0x2cf0,  0x2cf1,  0x2d7f,  0x2de0,  0x2de1,  0x2de2,  0x2de3,
9195
35.5k
      0x2de4,  0x2de5,  0x2de6,  0x2de7,  0x2de8,  0x2de9,  0x2dea,  0x2deb,
9196
35.5k
      0x2dec,  0x2ded,  0x2dee,  0x2def,  0x2df0,  0x2df1,  0x2df2,  0x2df3,
9197
35.5k
      0x2df4,  0x2df5,  0x2df6,  0x2df7,  0x2df8,  0x2df9,  0x2dfa,  0x2dfb,
9198
35.5k
      0x2dfc,  0x2dfd,  0x2dfe,  0x2dff,  0x302a,  0x302b,  0x302c,  0x302d,
9199
35.5k
      0x302e,  0x302f,  0x3099,  0x309a,  0xa66f,  0xa670,  0xa671,  0xa672,
9200
35.5k
      0xa674,  0xa675,  0xa676,  0xa677,  0xa678,  0xa679,  0xa67a,  0xa67b,
9201
35.5k
      0xa67c,  0xa67d,  0xa69e,  0xa69f,  0xa6f0,  0xa6f1,  0xa802,  0xa806,
9202
35.5k
      0xa80b,  0xa823,  0xa824,  0xa825,  0xa826,  0xa827,  0xa82c,  0xa880,
9203
35.5k
      0xa881,  0xa8b4,  0xa8b5,  0xa8b6,  0xa8b7,  0xa8b8,  0xa8b9,  0xa8ba,
9204
35.5k
      0xa8bb,  0xa8bc,  0xa8bd,  0xa8be,  0xa8bf,  0xa8c0,  0xa8c1,  0xa8c2,
9205
35.5k
      0xa8c3,  0xa8c4,  0xa8c5,  0xa8e0,  0xa8e1,  0xa8e2,  0xa8e3,  0xa8e4,
9206
35.5k
      0xa8e5,  0xa8e6,  0xa8e7,  0xa8e8,  0xa8e9,  0xa8ea,  0xa8eb,  0xa8ec,
9207
35.5k
      0xa8ed,  0xa8ee,  0xa8ef,  0xa8f0,  0xa8f1,  0xa8ff,  0xa926,  0xa927,
9208
35.5k
      0xa928,  0xa929,  0xa92a,  0xa92b,  0xa92c,  0xa92d,  0xa947,  0xa948,
9209
35.5k
      0xa949,  0xa94a,  0xa94b,  0xa94c,  0xa94d,  0xa94e,  0xa94f,  0xa950,
9210
35.5k
      0xa951,  0xa952,  0xa953,  0xa980,  0xa981,  0xa982,  0xa983,  0xa9b3,
9211
35.5k
      0xa9b4,  0xa9b5,  0xa9b6,  0xa9b7,  0xa9b8,  0xa9b9,  0xa9ba,  0xa9bb,
9212
35.5k
      0xa9bc,  0xa9bd,  0xa9be,  0xa9bf,  0xa9c0,  0xa9e5,  0xaa29,  0xaa2a,
9213
35.5k
      0xaa2b,  0xaa2c,  0xaa2d,  0xaa2e,  0xaa2f,  0xaa30,  0xaa31,  0xaa32,
9214
35.5k
      0xaa33,  0xaa34,  0xaa35,  0xaa36,  0xaa43,  0xaa4c,  0xaa4d,  0xaa7b,
9215
35.5k
      0xaa7c,  0xaa7d,  0xaab0,  0xaab2,  0xaab3,  0xaab4,  0xaab7,  0xaab8,
9216
35.5k
      0xaabe,  0xaabf,  0xaac1,  0xaaeb,  0xaaec,  0xaaed,  0xaaee,  0xaaef,
9217
35.5k
      0xaaf5,  0xaaf6,  0xabe3,  0xabe4,  0xabe5,  0xabe6,  0xabe7,  0xabe8,
9218
35.5k
      0xabe9,  0xabea,  0xabec,  0xabed,  0xfb1e,  0xfe00,  0xfe01,  0xfe02,
9219
35.5k
      0xfe03,  0xfe04,  0xfe05,  0xfe06,  0xfe07,  0xfe08,  0xfe09,  0xfe0a,
9220
35.5k
      0xfe0b,  0xfe0c,  0xfe0d,  0xfe0e,  0xfe0f,  0xfe20,  0xfe21,  0xfe22,
9221
35.5k
      0xfe23,  0xfe24,  0xfe25,  0xfe26,  0xfe27,  0xfe28,  0xfe29,  0xfe2a,
9222
35.5k
      0xfe2b,  0xfe2c,  0xfe2d,  0xfe2e,  0xfe2f,  0x101fd, 0x102e0, 0x10376,
9223
35.5k
      0x10377, 0x10378, 0x10379, 0x1037a, 0x10a01, 0x10a02, 0x10a03, 0x10a05,
9224
35.5k
      0x10a06, 0x10a0c, 0x10a0d, 0x10a0e, 0x10a0f, 0x10a38, 0x10a39, 0x10a3a,
9225
35.5k
      0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d25, 0x10d26, 0x10d27, 0x10eab,
9226
35.5k
      0x10eac, 0x10f46, 0x10f47, 0x10f48, 0x10f49, 0x10f4a, 0x10f4b, 0x10f4c,
9227
35.5k
      0x10f4d, 0x10f4e, 0x10f4f, 0x10f50, 0x11000, 0x11001, 0x11002, 0x11038,
9228
35.5k
      0x11039, 0x1103a, 0x1103b, 0x1103c, 0x1103d, 0x1103e, 0x1103f, 0x11040,
9229
35.5k
      0x11041, 0x11042, 0x11043, 0x11044, 0x11045, 0x11046, 0x1107f, 0x11080,
9230
35.5k
      0x11081, 0x11082, 0x110b0, 0x110b1, 0x110b2, 0x110b3, 0x110b4, 0x110b5,
9231
35.5k
      0x110b6, 0x110b7, 0x110b8, 0x110b9, 0x110ba, 0x11100, 0x11101, 0x11102,
9232
35.5k
      0x11127, 0x11128, 0x11129, 0x1112a, 0x1112b, 0x1112c, 0x1112d, 0x1112e,
9233
35.5k
      0x1112f, 0x11130, 0x11131, 0x11132, 0x11133, 0x11134, 0x11145, 0x11146,
9234
35.5k
      0x11173, 0x11180, 0x11181, 0x11182, 0x111b3, 0x111b4, 0x111b5, 0x111b6,
9235
35.5k
      0x111b7, 0x111b8, 0x111b9, 0x111ba, 0x111bb, 0x111bc, 0x111bd, 0x111be,
9236
35.5k
      0x111bf, 0x111c0, 0x111c9, 0x111ca, 0x111cb, 0x111cc, 0x111ce, 0x111cf,
9237
35.5k
      0x1122c, 0x1122d, 0x1122e, 0x1122f, 0x11230, 0x11231, 0x11232, 0x11233,
9238
35.5k
      0x11234, 0x11235, 0x11236, 0x11237, 0x1123e, 0x112df, 0x112e0, 0x112e1,
9239
35.5k
      0x112e2, 0x112e3, 0x112e4, 0x112e5, 0x112e6, 0x112e7, 0x112e8, 0x112e9,
9240
35.5k
      0x112ea, 0x11300, 0x11301, 0x11302, 0x11303, 0x1133b, 0x1133c, 0x1133e,
9241
35.5k
      0x1133f, 0x11340, 0x11341, 0x11342, 0x11343, 0x11344, 0x11347, 0x11348,
9242
35.5k
      0x1134b, 0x1134c, 0x1134d, 0x11357, 0x11362, 0x11363, 0x11366, 0x11367,
9243
35.5k
      0x11368, 0x11369, 0x1136a, 0x1136b, 0x1136c, 0x11370, 0x11371, 0x11372,
9244
35.5k
      0x11373, 0x11374, 0x11435, 0x11436, 0x11437, 0x11438, 0x11439, 0x1143a,
9245
35.5k
      0x1143b, 0x1143c, 0x1143d, 0x1143e, 0x1143f, 0x11440, 0x11441, 0x11442,
9246
35.5k
      0x11443, 0x11444, 0x11445, 0x11446, 0x1145e, 0x114b0, 0x114b1, 0x114b2,
9247
35.5k
      0x114b3, 0x114b4, 0x114b5, 0x114b6, 0x114b7, 0x114b8, 0x114b9, 0x114ba,
9248
35.5k
      0x114bb, 0x114bc, 0x114bd, 0x114be, 0x114bf, 0x114c0, 0x114c1, 0x114c2,
9249
35.5k
      0x114c3, 0x115af, 0x115b0, 0x115b1, 0x115b2, 0x115b3, 0x115b4, 0x115b5,
9250
35.5k
      0x115b8, 0x115b9, 0x115ba, 0x115bb, 0x115bc, 0x115bd, 0x115be, 0x115bf,
9251
35.5k
      0x115c0, 0x115dc, 0x115dd, 0x11630, 0x11631, 0x11632, 0x11633, 0x11634,
9252
35.5k
      0x11635, 0x11636, 0x11637, 0x11638, 0x11639, 0x1163a, 0x1163b, 0x1163c,
9253
35.5k
      0x1163d, 0x1163e, 0x1163f, 0x11640, 0x116ab, 0x116ac, 0x116ad, 0x116ae,
9254
35.5k
      0x116af, 0x116b0, 0x116b1, 0x116b2, 0x116b3, 0x116b4, 0x116b5, 0x116b6,
9255
35.5k
      0x116b7, 0x1171d, 0x1171e, 0x1171f, 0x11720, 0x11721, 0x11722, 0x11723,
9256
35.5k
      0x11724, 0x11725, 0x11726, 0x11727, 0x11728, 0x11729, 0x1172a, 0x1172b,
9257
35.5k
      0x1182c, 0x1182d, 0x1182e, 0x1182f, 0x11830, 0x11831, 0x11832, 0x11833,
9258
35.5k
      0x11834, 0x11835, 0x11836, 0x11837, 0x11838, 0x11839, 0x1183a, 0x11930,
9259
35.5k
      0x11931, 0x11932, 0x11933, 0x11934, 0x11935, 0x11937, 0x11938, 0x1193b,
9260
35.5k
      0x1193c, 0x1193d, 0x1193e, 0x11940, 0x11942, 0x11943, 0x119d1, 0x119d2,
9261
35.5k
      0x119d3, 0x119d4, 0x119d5, 0x119d6, 0x119d7, 0x119da, 0x119db, 0x119dc,
9262
35.5k
      0x119dd, 0x119de, 0x119df, 0x119e0, 0x119e4, 0x11a01, 0x11a02, 0x11a03,
9263
35.5k
      0x11a04, 0x11a05, 0x11a06, 0x11a07, 0x11a08, 0x11a09, 0x11a0a, 0x11a33,
9264
35.5k
      0x11a34, 0x11a35, 0x11a36, 0x11a37, 0x11a38, 0x11a39, 0x11a3b, 0x11a3c,
9265
35.5k
      0x11a3d, 0x11a3e, 0x11a47, 0x11a51, 0x11a52, 0x11a53, 0x11a54, 0x11a55,
9266
35.5k
      0x11a56, 0x11a57, 0x11a58, 0x11a59, 0x11a5a, 0x11a5b, 0x11a8a, 0x11a8b,
9267
35.5k
      0x11a8c, 0x11a8d, 0x11a8e, 0x11a8f, 0x11a90, 0x11a91, 0x11a92, 0x11a93,
9268
35.5k
      0x11a94, 0x11a95, 0x11a96, 0x11a97, 0x11a98, 0x11a99, 0x11c2f, 0x11c30,
9269
35.5k
      0x11c31, 0x11c32, 0x11c33, 0x11c34, 0x11c35, 0x11c36, 0x11c38, 0x11c39,
9270
35.5k
      0x11c3a, 0x11c3b, 0x11c3c, 0x11c3d, 0x11c3e, 0x11c3f, 0x11c92, 0x11c93,
9271
35.5k
      0x11c94, 0x11c95, 0x11c96, 0x11c97, 0x11c98, 0x11c99, 0x11c9a, 0x11c9b,
9272
35.5k
      0x11c9c, 0x11c9d, 0x11c9e, 0x11c9f, 0x11ca0, 0x11ca1, 0x11ca2, 0x11ca3,
9273
35.5k
      0x11ca4, 0x11ca5, 0x11ca6, 0x11ca7, 0x11ca9, 0x11caa, 0x11cab, 0x11cac,
9274
35.5k
      0x11cad, 0x11cae, 0x11caf, 0x11cb0, 0x11cb1, 0x11cb2, 0x11cb3, 0x11cb4,
9275
35.5k
      0x11cb5, 0x11cb6, 0x11d31, 0x11d32, 0x11d33, 0x11d34, 0x11d35, 0x11d36,
9276
35.5k
      0x11d3a, 0x11d3c, 0x11d3d, 0x11d3f, 0x11d40, 0x11d41, 0x11d42, 0x11d43,
9277
35.5k
      0x11d44, 0x11d45, 0x11d47, 0x11d8a, 0x11d8b, 0x11d8c, 0x11d8d, 0x11d8e,
9278
35.5k
      0x11d90, 0x11d91, 0x11d93, 0x11d94, 0x11d95, 0x11d96, 0x11d97, 0x11ef3,
9279
35.5k
      0x11ef4, 0x11ef5, 0x11ef6, 0x16af0, 0x16af1, 0x16af2, 0x16af3, 0x16af4,
9280
35.5k
      0x16b30, 0x16b31, 0x16b32, 0x16b33, 0x16b34, 0x16b35, 0x16b36, 0x16f4f,
9281
35.5k
      0x16f51, 0x16f52, 0x16f53, 0x16f54, 0x16f55, 0x16f56, 0x16f57, 0x16f58,
9282
35.5k
      0x16f59, 0x16f5a, 0x16f5b, 0x16f5c, 0x16f5d, 0x16f5e, 0x16f5f, 0x16f60,
9283
35.5k
      0x16f61, 0x16f62, 0x16f63, 0x16f64, 0x16f65, 0x16f66, 0x16f67, 0x16f68,
9284
35.5k
      0x16f69, 0x16f6a, 0x16f6b, 0x16f6c, 0x16f6d, 0x16f6e, 0x16f6f, 0x16f70,
9285
35.5k
      0x16f71, 0x16f72, 0x16f73, 0x16f74, 0x16f75, 0x16f76, 0x16f77, 0x16f78,
9286
35.5k
      0x16f79, 0x16f7a, 0x16f7b, 0x16f7c, 0x16f7d, 0x16f7e, 0x16f7f, 0x16f80,
9287
35.5k
      0x16f81, 0x16f82, 0x16f83, 0x16f84, 0x16f85, 0x16f86, 0x16f87, 0x16f8f,
9288
35.5k
      0x16f90, 0x16f91, 0x16f92, 0x16fe4, 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e,
9289
35.5k
      0x1d165, 0x1d166, 0x1d167, 0x1d168, 0x1d169, 0x1d16d, 0x1d16e, 0x1d16f,
9290
35.5k
      0x1d170, 0x1d171, 0x1d172, 0x1d17b, 0x1d17c, 0x1d17d, 0x1d17e, 0x1d17f,
9291
35.5k
      0x1d180, 0x1d181, 0x1d182, 0x1d185, 0x1d186, 0x1d187, 0x1d188, 0x1d189,
9292
35.5k
      0x1d18a, 0x1d18b, 0x1d1aa, 0x1d1ab, 0x1d1ac, 0x1d1ad, 0x1d242, 0x1d243,
9293
35.5k
      0x1d244, 0x1da00, 0x1da01, 0x1da02, 0x1da03, 0x1da04, 0x1da05, 0x1da06,
9294
35.5k
      0x1da07, 0x1da08, 0x1da09, 0x1da0a, 0x1da0b, 0x1da0c, 0x1da0d, 0x1da0e,
9295
35.5k
      0x1da0f, 0x1da10, 0x1da11, 0x1da12, 0x1da13, 0x1da14, 0x1da15, 0x1da16,
9296
35.5k
      0x1da17, 0x1da18, 0x1da19, 0x1da1a, 0x1da1b, 0x1da1c, 0x1da1d, 0x1da1e,
9297
35.5k
      0x1da1f, 0x1da20, 0x1da21, 0x1da22, 0x1da23, 0x1da24, 0x1da25, 0x1da26,
9298
35.5k
      0x1da27, 0x1da28, 0x1da29, 0x1da2a, 0x1da2b, 0x1da2c, 0x1da2d, 0x1da2e,
9299
35.5k
      0x1da2f, 0x1da30, 0x1da31, 0x1da32, 0x1da33, 0x1da34, 0x1da35, 0x1da36,
9300
35.5k
      0x1da3b, 0x1da3c, 0x1da3d, 0x1da3e, 0x1da3f, 0x1da40, 0x1da41, 0x1da42,
9301
35.5k
      0x1da43, 0x1da44, 0x1da45, 0x1da46, 0x1da47, 0x1da48, 0x1da49, 0x1da4a,
9302
35.5k
      0x1da4b, 0x1da4c, 0x1da4d, 0x1da4e, 0x1da4f, 0x1da50, 0x1da51, 0x1da52,
9303
35.5k
      0x1da53, 0x1da54, 0x1da55, 0x1da56, 0x1da57, 0x1da58, 0x1da59, 0x1da5a,
9304
35.5k
      0x1da5b, 0x1da5c, 0x1da5d, 0x1da5e, 0x1da5f, 0x1da60, 0x1da61, 0x1da62,
9305
35.5k
      0x1da63, 0x1da64, 0x1da65, 0x1da66, 0x1da67, 0x1da68, 0x1da69, 0x1da6a,
9306
35.5k
      0x1da6b, 0x1da6c, 0x1da75, 0x1da84, 0x1da9b, 0x1da9c, 0x1da9d, 0x1da9e,
9307
35.5k
      0x1da9f, 0x1daa1, 0x1daa2, 0x1daa3, 0x1daa4, 0x1daa5, 0x1daa6, 0x1daa7,
9308
35.5k
      0x1daa8, 0x1daa9, 0x1daaa, 0x1daab, 0x1daac, 0x1daad, 0x1daae, 0x1daaf,
9309
35.5k
      0x1e000, 0x1e001, 0x1e002, 0x1e003, 0x1e004, 0x1e005, 0x1e006, 0x1e008,
9310
35.5k
      0x1e009, 0x1e00a, 0x1e00b, 0x1e00c, 0x1e00d, 0x1e00e, 0x1e00f, 0x1e010,
9311
35.5k
      0x1e011, 0x1e012, 0x1e013, 0x1e014, 0x1e015, 0x1e016, 0x1e017, 0x1e018,
9312
35.5k
      0x1e01b, 0x1e01c, 0x1e01d, 0x1e01e, 0x1e01f, 0x1e020, 0x1e021, 0x1e023,
9313
35.5k
      0x1e024, 0x1e026, 0x1e027, 0x1e028, 0x1e029, 0x1e02a, 0x1e130, 0x1e131,
9314
35.5k
      0x1e132, 0x1e133, 0x1e134, 0x1e135, 0x1e136, 0x1e2ec, 0x1e2ed, 0x1e2ee,
9315
35.5k
      0x1e2ef, 0x1e8d0, 0x1e8d1, 0x1e8d2, 0x1e8d3, 0x1e8d4, 0x1e8d5, 0x1e8d6,
9316
35.5k
      0x1e944, 0x1e945, 0x1e946, 0x1e947, 0x1e948, 0x1e949, 0x1e94a, 0xe0100,
9317
35.5k
      0xe0101, 0xe0102, 0xe0103, 0xe0104, 0xe0105, 0xe0106, 0xe0107, 0xe0108,
9318
35.5k
      0xe0109, 0xe010a, 0xe010b, 0xe010c, 0xe010d, 0xe010e, 0xe010f, 0xe0110,
9319
35.5k
      0xe0111, 0xe0112, 0xe0113, 0xe0114, 0xe0115, 0xe0116, 0xe0117, 0xe0118,
9320
35.5k
      0xe0119, 0xe011a, 0xe011b, 0xe011c, 0xe011d, 0xe011e, 0xe011f, 0xe0120,
9321
35.5k
      0xe0121, 0xe0122, 0xe0123, 0xe0124, 0xe0125, 0xe0126, 0xe0127, 0xe0128,
9322
35.5k
      0xe0129, 0xe012a, 0xe012b, 0xe012c, 0xe012d, 0xe012e, 0xe012f, 0xe0130,
9323
35.5k
      0xe0131, 0xe0132, 0xe0133, 0xe0134, 0xe0135, 0xe0136, 0xe0137, 0xe0138,
9324
35.5k
      0xe0139, 0xe013a, 0xe013b, 0xe013c, 0xe013d, 0xe013e, 0xe013f, 0xe0140,
9325
35.5k
      0xe0141, 0xe0142, 0xe0143, 0xe0144, 0xe0145, 0xe0146, 0xe0147, 0xe0148,
9326
35.5k
      0xe0149, 0xe014a, 0xe014b, 0xe014c, 0xe014d, 0xe014e, 0xe014f, 0xe0150,
9327
35.5k
      0xe0151, 0xe0152, 0xe0153, 0xe0154, 0xe0155, 0xe0156, 0xe0157, 0xe0158,
9328
35.5k
      0xe0159, 0xe015a, 0xe015b, 0xe015c, 0xe015d, 0xe015e, 0xe015f, 0xe0160,
9329
35.5k
      0xe0161, 0xe0162, 0xe0163, 0xe0164, 0xe0165, 0xe0166, 0xe0167, 0xe0168,
9330
35.5k
      0xe0169, 0xe016a, 0xe016b, 0xe016c, 0xe016d, 0xe016e, 0xe016f, 0xe0170,
9331
35.5k
      0xe0171, 0xe0172, 0xe0173, 0xe0174, 0xe0175, 0xe0176, 0xe0177, 0xe0178,
9332
35.5k
      0xe0179, 0xe017a, 0xe017b, 0xe017c, 0xe017d, 0xe017e, 0xe017f, 0xe0180,
9333
35.5k
      0xe0181, 0xe0182, 0xe0183, 0xe0184, 0xe0185, 0xe0186, 0xe0187, 0xe0188,
9334
35.5k
      0xe0189, 0xe018a, 0xe018b, 0xe018c, 0xe018d, 0xe018e, 0xe018f, 0xe0190,
9335
35.5k
      0xe0191, 0xe0192, 0xe0193, 0xe0194, 0xe0195, 0xe0196, 0xe0197, 0xe0198,
9336
35.5k
      0xe0199, 0xe019a, 0xe019b, 0xe019c, 0xe019d, 0xe019e, 0xe019f, 0xe01a0,
9337
35.5k
      0xe01a1, 0xe01a2, 0xe01a3, 0xe01a4, 0xe01a5, 0xe01a6, 0xe01a7, 0xe01a8,
9338
35.5k
      0xe01a9, 0xe01aa, 0xe01ab, 0xe01ac, 0xe01ad, 0xe01ae, 0xe01af, 0xe01b0,
9339
35.5k
      0xe01b1, 0xe01b2, 0xe01b3, 0xe01b4, 0xe01b5, 0xe01b6, 0xe01b7, 0xe01b8,
9340
35.5k
      0xe01b9, 0xe01ba, 0xe01bb, 0xe01bc, 0xe01bd, 0xe01be, 0xe01bf, 0xe01c0,
9341
35.5k
      0xe01c1, 0xe01c2, 0xe01c3, 0xe01c4, 0xe01c5, 0xe01c6, 0xe01c7, 0xe01c8,
9342
35.5k
      0xe01c9, 0xe01ca, 0xe01cb, 0xe01cc, 0xe01cd, 0xe01ce, 0xe01cf, 0xe01d0,
9343
35.5k
      0xe01d1, 0xe01d2, 0xe01d3, 0xe01d4, 0xe01d5, 0xe01d6, 0xe01d7, 0xe01d8,
9344
35.5k
      0xe01d9, 0xe01da, 0xe01db, 0xe01dc, 0xe01dd, 0xe01de, 0xe01df, 0xe01e0,
9345
35.5k
      0xe01e1, 0xe01e2, 0xe01e3, 0xe01e4, 0xe01e5, 0xe01e6, 0xe01e7, 0xe01e8,
9346
35.5k
      0xe01e9, 0xe01ea, 0xe01eb, 0xe01ec, 0xe01ed, 0xe01ee, 0xe01ef};
9347
35.5k
  if (std::binary_search(std::begin(combining), std::end(combining),
9348
35.5k
                         label.front())) {
9349
120
    return false;
9350
120
  }
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
35.4k
  constexpr static uint32_t virama[] = {
9363
35.4k
      0x094D,  0x09CD,  0x0A4D,  0x0ACD,  0x0B4D,  0x0BCD,  0x0C4D,  0x0CCD,
9364
35.4k
      0x0D3B,  0x0D3C,  0x0D4D,  0x0DCA,  0x0E3A,  0x0EBA,  0x0F84,  0x1039,
9365
35.4k
      0x103A,  0x1714,  0x1734,  0x17D2,  0x1A60,  0x1B44,  0x1BAA,  0x1BAB,
9366
35.4k
      0x1BF2,  0x1BF3,  0x2D7F,  0xA806,  0xA82C,  0xA8C4,  0xA953,  0xA9C0,
9367
35.4k
      0xAAF6,  0xABED,  0x10A3F, 0x11046, 0x1107F, 0x110B9, 0x11133, 0x11134,
9368
35.4k
      0x111C0, 0x11235, 0x112EA, 0x1134D, 0x11442, 0x114C2, 0x115BF, 0x1163F,
9369
35.4k
      0x116B6, 0x1172B, 0x11839, 0x1193D, 0x1193E, 0x119E0, 0x11A34, 0x11A47,
9370
35.4k
      0x11A99, 0x11C3F, 0x11D44, 0x11D45, 0x11D97};
9371
35.4k
  constexpr static uint32_t R[] = {
9372
35.4k
      0x622, 0x623, 0x624, 0x625, 0x627, 0x629, 0x62f, 0x630, 0x631,
9373
35.4k
      0x632, 0x648, 0x671, 0x672, 0x673, 0x675, 0x676, 0x677, 0x688,
9374
35.4k
      0x689, 0x68a, 0x68b, 0x68c, 0x68d, 0x68e, 0x68f, 0x690, 0x691,
9375
35.4k
      0x692, 0x693, 0x694, 0x695, 0x696, 0x697, 0x698, 0x699, 0x6c0,
9376
35.4k
      0x6c3, 0x6c4, 0x6c5, 0x6c6, 0x6c7, 0x6c8, 0x6c9, 0x6ca, 0x6cb,
9377
35.4k
      0x6cd, 0x6cf, 0x6d2, 0x6d3, 0x6d5, 0x6ee, 0x6ef, 0x710, 0x715,
9378
35.4k
      0x716, 0x717, 0x718, 0x719, 0x71e, 0x728, 0x72a, 0x72c, 0x72f,
9379
35.4k
      0x74d, 0x759, 0x75a, 0x75b, 0x854, 0x8aa, 0x8ab, 0x8ac};
9380
35.4k
  constexpr static uint32_t L[] = {0xa872};
9381
35.4k
  constexpr static uint32_t D[] = {
9382
35.4k
      0x620,  0x626,  0x628,  0x62a,  0x62b,  0x62c,  0x62d,  0x62e,  0x633,
9383
35.4k
      0x634,  0x635,  0x636,  0x637,  0x638,  0x639,  0x63a,  0x63b,  0x63c,
9384
35.4k
      0x63d,  0x63e,  0x63f,  0x641,  0x642,  0x643,  0x644,  0x645,  0x646,
9385
35.4k
      0x647,  0x649,  0x64a,  0x66e,  0x66f,  0x678,  0x679,  0x67a,  0x67b,
9386
35.4k
      0x67c,  0x67d,  0x67e,  0x67f,  0x680,  0x681,  0x682,  0x683,  0x684,
9387
35.4k
      0x685,  0x686,  0x687,  0x69a,  0x69b,  0x69c,  0x69d,  0x69e,  0x69f,
9388
35.4k
      0x6a0,  0x6a1,  0x6a2,  0x6a3,  0x6a4,  0x6a5,  0x6a6,  0x6a7,  0x6a8,
9389
35.4k
      0x6a9,  0x6aa,  0x6ab,  0x6ac,  0x6ad,  0x6ae,  0x6af,  0x6b0,  0x6b1,
9390
35.4k
      0x6b2,  0x6b3,  0x6b4,  0x6b5,  0x6b6,  0x6b7,  0x6b8,  0x6b9,  0x6ba,
9391
35.4k
      0x6bb,  0x6bc,  0x6bd,  0x6be,  0x6bf,  0x6c1,  0x6c2,  0x6cc,  0x6ce,
9392
35.4k
      0x6d0,  0x6d1,  0x6fa,  0x6fb,  0x6fc,  0x6ff,  0x712,  0x713,  0x714,
9393
35.4k
      0x71a,  0x71b,  0x71c,  0x71d,  0x71f,  0x720,  0x721,  0x722,  0x723,
9394
35.4k
      0x724,  0x725,  0x726,  0x727,  0x729,  0x72b,  0x72d,  0x72e,  0x74e,
9395
35.4k
      0x74f,  0x750,  0x751,  0x752,  0x753,  0x754,  0x755,  0x756,  0x757,
9396
35.4k
      0x758,  0x75c,  0x75d,  0x75e,  0x75f,  0x760,  0x761,  0x762,  0x763,
9397
35.4k
      0x764,  0x765,  0x766,  0x850,  0x851,  0x852,  0x853,  0x855,  0x8a0,
9398
35.4k
      0x8a2,  0x8a3,  0x8a4,  0x8a5,  0x8a6,  0x8a7,  0x8a8,  0x8a9,  0x1807,
9399
35.4k
      0x1820, 0x1821, 0x1822, 0x1823, 0x1824, 0x1825, 0x1826, 0x1827, 0x1828,
9400
35.4k
      0x1829, 0x182a, 0x182b, 0x182c, 0x182d, 0x182e, 0x182f, 0x1830, 0x1831,
9401
35.4k
      0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837, 0x1838, 0x1839, 0x183a,
9402
35.4k
      0x183b, 0x183c, 0x183d, 0x183e, 0x183f, 0x1840, 0x1841, 0x1842, 0x1843,
9403
35.4k
      0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x184a, 0x184b, 0x184c,
9404
35.4k
      0x184d, 0x184e, 0x184f, 0x1850, 0x1851, 0x1852, 0x1853, 0x1854, 0x1855,
9405
35.4k
      0x1856, 0x1857, 0x1858, 0x1859, 0x185a, 0x185b, 0x185c, 0x185d, 0x185e,
9406
35.4k
      0x185f, 0x1860, 0x1861, 0x1862, 0x1863, 0x1864, 0x1865, 0x1866, 0x1867,
9407
35.4k
      0x1868, 0x1869, 0x186a, 0x186b, 0x186c, 0x186d, 0x186e, 0x186f, 0x1870,
9408
35.4k
      0x1871, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, 0x1877, 0x1887, 0x1888,
9409
35.4k
      0x1889, 0x188a, 0x188b, 0x188c, 0x188d, 0x188e, 0x188f, 0x1890, 0x1891,
9410
35.4k
      0x1892, 0x1893, 0x1894, 0x1895, 0x1896, 0x1897, 0x1898, 0x1899, 0x189a,
9411
35.4k
      0x189b, 0x189c, 0x189d, 0x189e, 0x189f, 0x18a0, 0x18a1, 0x18a2, 0x18a3,
9412
35.4k
      0x18a4, 0x18a5, 0x18a6, 0x18a7, 0x18a8, 0x18aa, 0xa840, 0xa841, 0xa842,
9413
35.4k
      0xa843, 0xa844, 0xa845, 0xa846, 0xa847, 0xa848, 0xa849, 0xa84a, 0xa84b,
9414
35.4k
      0xa84c, 0xa84d, 0xa84e, 0xa84f, 0xa850, 0xa851, 0xa852, 0xa853, 0xa854,
9415
35.4k
      0xa855, 0xa856, 0xa857, 0xa858, 0xa859, 0xa85a, 0xa85b, 0xa85c, 0xa85d,
9416
35.4k
      0xa85e, 0xa85f, 0xa860, 0xa861, 0xa862, 0xa863, 0xa864, 0xa865, 0xa866,
9417
35.4k
      0xa867, 0xa868, 0xa869, 0xa86a, 0xa86b, 0xa86c, 0xa86d, 0xa86e, 0xa86f,
9418
35.4k
      0xa870, 0xa871};
9419
9420
341k
  for (size_t i = 0; i < label.size(); i++) {
9421
308k
    uint32_t c = label[i];
9422
308k
    if (c == 0x200c) {
9423
1.24k
      if (i > 0) {
9424
1.23k
        if (std::binary_search(std::begin(virama), std::end(virama),
9425
1.23k
                               label[i - 1])) {
9426
244
          return true;
9427
244
        }
9428
1.23k
      }
9429
1.00k
      if ((i == 0) || (i + 1 >= label.size())) {
9430
108
        return false;
9431
108
      }
9432
      // we go backward looking for L or D
9433
1.90k
      auto is_l_or_d = [](uint32_t code) {
9434
1.90k
        return std::binary_search(std::begin(L), std::end(L), code) ||
9435
1.84k
               std::binary_search(std::begin(D), std::end(D), code);
9436
1.90k
      };
9437
2.32k
      auto is_r_or_d = [](uint32_t code) {
9438
2.32k
        return std::binary_search(std::begin(R), std::end(R), code) ||
9439
2.05k
               std::binary_search(std::begin(D), std::end(D), code);
9440
2.32k
      };
9441
892
      std::u32string_view before = label.substr(0, i);
9442
892
      std::u32string_view after = label.substr(i + 1);
9443
892
      return (std::find_if(before.begin(), before.end(), is_l_or_d) !=
9444
892
              before.end()) &&
9445
784
             (std::find_if(after.begin(), after.end(), is_r_or_d) !=
9446
784
              after.end());
9447
307k
    } else if (c == 0x200d) {
9448
516
      if (i > 0) {
9449
502
        if (std::binary_search(std::begin(virama), std::end(virama),
9450
502
                               label[i - 1])) {
9451
372
          return true;
9452
372
        }
9453
502
      }
9454
144
      return false;
9455
516
    }
9456
308k
  }
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
33.6k
  size_t last_non_nsm_char = find_last_not_of_nsm(label);
9489
33.6k
  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
33.6k
  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.32k
    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
4.46k
      for (size_t i = 0; i < last_non_nsm_char; i++) {
9507
3.94k
        const direction d = find_direction(label[i]);
9508
3.94k
        if (!(d == direction::L || d == direction::EN || d == direction::ES ||
9509
1.40k
              d == direction::CS || d == direction::ET || d == direction::ON ||
9510
628
              d == direction::BN || d == direction::NSM)) {
9511
122
          return false;
9512
122
        }
9513
9514
3.82k
        if ((i == last_non_nsm_char) &&
9515
0
            !(d == direction::L || d == direction::EN)) {
9516
0
          return false;
9517
0
        }
9518
3.82k
      }
9519
9520
518
      return true;
9521
9522
2.68k
    } else {
9523
      // Eval as RTL
9524
9525
2.68k
      bool has_an = false;
9526
2.68k
      bool has_en = false;
9527
9.50k
      for (size_t i = 0; i <= last_non_nsm_char; i++) {
9528
7.14k
        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
7.14k
        if ((d == direction::EN && ((has_en = true) && has_an)) ||
9533
7.13k
            (d == direction::AN && ((has_an = true) && has_en))) {
9534
20
          return false;
9535
20
        }
9536
9537
7.12k
        if (!(d == direction::R || d == direction::AL || d == direction::AN ||
9538
2.74k
              d == direction::EN || d == direction::ES || d == direction::CS ||
9539
1.72k
              d == direction::ET || d == direction::ON || d == direction::BN ||
9540
790
              d == direction::NSM)) {
9541
244
          return false;
9542
244
        }
9543
9544
6.87k
        if (i == last_non_nsm_char &&
9545
2.42k
            !(d == direction::R || d == direction::AL || d == direction::AN ||
9546
282
              d == direction::EN)) {
9547
62
          return false;
9548
62
        }
9549
6.87k
      }
9550
9551
2.36k
      return true;
9552
2.68k
    }
9553
3.32k
  }
9554
9555
30.3k
  return true;
9556
33.6k
}
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
37.9k
bool constexpr is_ascii(std::u32string_view view) {
9574
61.7k
  for (uint32_t c : view) {
9575
61.7k
    if (c >= 0x80) {
9576
36.1k
      return false;
9577
36.1k
    }
9578
61.7k
  }
9579
1.80k
  return true;
9580
37.9k
}
9581
9582
15.8k
bool constexpr is_ascii(std::string_view view) {
9583
138k
  for (uint8_t c : view) {
9584
138k
    if (c >= 0x80) {
9585
9.43k
      return false;
9586
9.43k
    }
9587
138k
  }
9588
6.44k
  return true;
9589
15.8k
}
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
6.44k
static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9616
6.44k
  static const std::string error = "";
9617
  // copy and map
9618
  // we could be more efficient by avoiding the copy when unnecessary.
9619
6.44k
  std::string mapped_string = std::string(ut8_string);
9620
6.44k
  ascii_map(mapped_string.data(), mapped_string.size());
9621
6.44k
  std::string out;
9622
6.44k
  size_t label_start = 0;
9623
9624
18.7k
  while (label_start != mapped_string.size()) {
9625
13.0k
    size_t loc_dot = mapped_string.find('.', label_start);
9626
13.0k
    bool is_last_label = (loc_dot == std::string_view::npos);
9627
13.0k
    size_t label_size = is_last_label ? mapped_string.size() - label_start
9628
13.0k
                                      : loc_dot - label_start;
9629
13.0k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9630
13.0k
    std::string_view label_view(mapped_string.data() + label_start, label_size);
9631
13.0k
    label_start += label_size_with_dot;
9632
13.0k
    if (label_size == 0) {
9633
      // empty label? Nothing to do.
9634
10.4k
    } else if (label_view.starts_with("xn--")) {
9635
      // The xn-- part is the expensive game.
9636
3.52k
      out.append(label_view);
9637
3.52k
      std::string_view puny_segment_ascii(
9638
3.52k
          out.data() + out.size() - label_view.size() + 4,
9639
3.52k
          label_view.size() - 4);
9640
3.52k
      std::u32string tmp_buffer;
9641
3.52k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9642
3.52k
      if (!is_ok) {
9643
248
        return error;
9644
248
      }
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
3.27k
      if (is_ascii(tmp_buffer)) {
9649
138
        return error;
9650
138
      }
9651
3.13k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9652
3.13k
      if (tmp_buffer != post_map) {
9653
278
        return error;
9654
278
      }
9655
2.85k
      std::u32string pre_normal = post_map;
9656
2.85k
      normalize(post_map);
9657
2.85k
      if (post_map != pre_normal) {
9658
58
        return error;
9659
58
      }
9660
2.80k
      if (post_map.empty()) {
9661
0
        return error;
9662
0
      }
9663
2.80k
      if (!is_label_valid(post_map)) {
9664
46
        return error;
9665
46
      }
9666
6.88k
    } else {
9667
6.88k
      out.append(label_view);
9668
6.88k
    }
9669
12.2k
    if (!is_last_label) {
9670
6.89k
      out.push_back('.');
9671
6.89k
    }
9672
12.2k
  }
9673
5.67k
  return out;
9674
6.44k
}
9675
9676
// We return "" on error.
9677
15.8k
std::string to_ascii(std::string_view ut8_string) {
9678
15.8k
  if (is_ascii(ut8_string)) {
9679
6.44k
    return from_ascii_to_ascii(ut8_string);
9680
6.44k
  }
9681
9.43k
  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
9.43k
  size_t utf32_length =
9692
9.43k
      ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9693
9.43k
  std::u32string utf32(utf32_length, '\0');
9694
9.43k
  size_t actual_utf32_length = ada::idna::utf8_to_utf32(
9695
9.43k
      ut8_string.data(), ut8_string.size(), utf32.data());
9696
9.43k
#endif
9697
9.43k
  if (actual_utf32_length == 0) {
9698
2.12k
    return error;
9699
2.12k
  }
9700
  // mapping
9701
7.31k
  utf32 = ada::idna::map(utf32);
9702
7.31k
  normalize(utf32);
9703
7.31k
  std::string out;
9704
7.31k
  size_t label_start = 0;
9705
9706
41.9k
  while (label_start != utf32.size()) {
9707
36.2k
    size_t loc_dot = utf32.find('.', label_start);
9708
36.2k
    bool is_last_label = (loc_dot == std::string_view::npos);
9709
36.2k
    size_t label_size =
9710
36.2k
        is_last_label ? utf32.size() - label_start : loc_dot - label_start;
9711
36.2k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9712
36.2k
    std::u32string_view label_view(utf32.data() + label_start, label_size);
9713
36.2k
    label_start += label_size_with_dot;
9714
36.2k
    if (label_size == 0) {
9715
      // empty label? Nothing to do.
9716
34.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
38.9k
      for (char32_t c : label_view) {
9719
38.9k
        if (c >= 0x80) {
9720
32
          return error;
9721
32
        }
9722
38.9k
        out += (unsigned char)(c);
9723
38.9k
      }
9724
1.99k
      std::string_view puny_segment_ascii(
9725
1.99k
          out.data() + out.size() - label_view.size() + 4,
9726
1.99k
          label_view.size() - 4);
9727
1.99k
      std::u32string tmp_buffer;
9728
1.99k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9729
1.99k
      if (!is_ok) {
9730
120
        return error;
9731
120
      }
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
1.87k
      if (is_ascii(tmp_buffer)) {
9736
100
        return error;
9737
100
      }
9738
1.77k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9739
1.77k
      if (tmp_buffer != post_map) {
9740
210
        return error;
9741
210
      }
9742
1.56k
      std::u32string pre_normal = post_map;
9743
1.56k
      normalize(post_map);
9744
1.56k
      if (post_map != pre_normal) {
9745
18
        return error;
9746
18
      }
9747
1.55k
      if (post_map.empty()) {
9748
0
        return error;
9749
0
      }
9750
1.55k
      if (!is_label_valid(post_map)) {
9751
10
        return error;
9752
10
      }
9753
32.7k
    } else {
9754
      // The fast path here is an ascii label.
9755
32.7k
      if (is_ascii(label_view)) {
9756
        // no validation needed.
9757
14.0k
        for (char32_t c : label_view) {
9758
14.0k
          out += (unsigned char)(c);
9759
14.0k
        }
9760
31.2k
      } else {
9761
        // slow path.
9762
        // first check validity.
9763
31.2k
        if (!is_label_valid(label_view)) {
9764
1.07k
          return error;
9765
1.07k
        }
9766
        // It is valid! So now we must encode it as punycode...
9767
30.1k
        out.append("xn--");
9768
30.1k
        bool is_ok = ada::idna::utf32_to_punycode(label_view, out);
9769
30.1k
        if (!is_ok) {
9770
0
          return error;
9771
0
        }
9772
30.1k
      }
9773
32.7k
    }
9774
34.6k
    if (!is_last_label) {
9775
29.4k
      out.push_back('.');
9776
29.4k
    }
9777
34.6k
  }
9778
5.74k
  return out;
9779
7.31k
}
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
188k
constexpr bool is_tabs_or_newline(char c) noexcept {
10487
188k
  return c == '\r' || c == '\n' || c == '\t';
10488
188k
}
10489
10490
103k
constexpr uint64_t broadcast(uint8_t v) noexcept {
10491
103k
  return 0x101010101010101ull * v;
10492
103k
}
10493
10494
34.3k
constexpr bool to_lower_ascii(char* input, size_t length) noexcept {
10495
34.3k
  uint64_t broadcast_80 = broadcast(0x80);
10496
34.3k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
10497
34.3k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
10498
34.3k
  uint64_t non_ascii = 0;
10499
34.3k
  size_t i = 0;
10500
10501
77.1k
  for (; i + 7 < length; i += 8) {
10502
42.8k
    uint64_t word{};
10503
42.8k
    memcpy(&word, input + i, sizeof(word));
10504
42.8k
    non_ascii |= (word & broadcast_80);
10505
42.8k
    word ^=
10506
42.8k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10507
42.8k
    memcpy(input + i, &word, sizeof(word));
10508
42.8k
  }
10509
34.3k
  if (i < length) {
10510
33.1k
    uint64_t word{};
10511
33.1k
    memcpy(&word, input + i, length - i);
10512
33.1k
    non_ascii |= (word & broadcast_80);
10513
33.1k
    word ^=
10514
33.1k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10515
33.1k
    memcpy(input + i, &word, length - i);
10516
33.1k
  }
10517
34.3k
  return non_ascii == 0;
10518
34.3k
}
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
64.3k
    std::string_view user_input) noexcept {
10592
  // first check for short strings in which case we do it naively.
10593
64.3k
  if (user_input.size() < 16) {  // slow path
10594
27.0k
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10595
27.0k
  }
10596
  // fast path for long strings (expected to be common)
10597
37.3k
  size_t i = 0;
10598
37.3k
  const __m128i mask1 = _mm_set1_epi8('\r');
10599
37.3k
  const __m128i mask2 = _mm_set1_epi8('\n');
10600
37.3k
  const __m128i mask3 = _mm_set1_epi8('\t');
10601
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10602
37.3k
  __m128i running{0};
10603
142k
  for (; i + 15 < user_input.size(); i += 16) {
10604
105k
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
10605
105k
    running = _mm_or_si128(
10606
105k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10607
105k
                                           _mm_cmpeq_epi8(word, mask2))),
10608
105k
        _mm_cmpeq_epi8(word, mask3));
10609
105k
  }
10610
37.3k
  if (i < user_input.size()) {
10611
34.3k
    __m128i word = _mm_loadu_si128(
10612
34.3k
        (const __m128i*)(user_input.data() + user_input.length() - 16));
10613
34.3k
    running = _mm_or_si128(
10614
34.3k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10615
34.3k
                                           _mm_cmpeq_epi8(word, mask2))),
10616
34.3k
        _mm_cmpeq_epi8(word, mask3));
10617
34.3k
  }
10618
37.3k
  return _mm_movemask_epi8(running) != 0;
10619
64.3k
}
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
18.8k
    const char c) noexcept {
10715
18.8k
  return is_forbidden_host_code_point_table[uint8_t(c)];
10716
18.8k
}
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
788k
    const char c) noexcept {
10738
788k
  return is_forbidden_domain_code_point_table[uint8_t(c)];
10739
788k
}
10740
10741
ada_really_inline constexpr bool contains_forbidden_domain_code_point(
10742
33.6k
    const char* input, size_t length) noexcept {
10743
33.6k
  size_t i = 0;
10744
33.6k
  uint8_t accumulator{};
10745
345k
  for (; i + 4 <= length; i += 4) {
10746
311k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10747
311k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 1])];
10748
311k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 2])];
10749
311k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 3])];
10750
311k
  }
10751
95.9k
  for (; i < length; i++) {
10752
62.3k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10753
62.3k
  }
10754
33.6k
  return accumulator;
10755
33.6k
}
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
22.3k
                                              size_t length) noexcept {
10779
22.3k
  size_t i = 0;
10780
22.3k
  uint8_t accumulator{};
10781
109k
  for (; i + 4 <= length; i += 4) {
10782
87.4k
    accumulator |=
10783
87.4k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10784
87.4k
    accumulator |=
10785
87.4k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 1])];
10786
87.4k
    accumulator |=
10787
87.4k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 2])];
10788
87.4k
    accumulator |=
10789
87.4k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 3])];
10790
87.4k
  }
10791
67.6k
  for (; i < length; i++) {
10792
45.3k
    accumulator |=
10793
45.3k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10794
45.3k
  }
10795
22.3k
  return accumulator;
10796
22.3k
}
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
231k
ada_really_inline constexpr bool is_alnum_plus(const char c) noexcept {
10809
231k
  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
231k
}
10814
10815
29.8k
ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept {
10816
29.8k
  return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
10817
3.28k
         (c >= 'a' && c <= 'f');
10818
29.8k
}
10819
10820
35.9k
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
35.9k
  return (c >= '0' && c <= '9');
10824
35.9k
}
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
83.5k
ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept {
10832
83.5k
  return (unsigned char)c <= ' ';
10833
83.5k
}
10834
10835
ada_really_inline constexpr bool is_ascii_tab_or_newline(
10836
3.47M
    const char c) noexcept {
10837
3.47M
  return c == '\t' || c == '\n' || c == '\r';
10838
3.47M
}
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
116k
    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
116k
  uint64_t half_length = uint64_t(input.size()) / 2;
10850
116k
  if (half_length - 1 > 2) {
10851
61.2k
    return false;
10852
61.2k
  }
10853
  // We have a string of length 2, 4 or 6.
10854
  // We now check the first character:
10855
54.8k
  if ((input[0] != '.') && (input[0] != '%')) {
10856
9.06k
    return false;
10857
9.06k
  }
10858
  // We are unlikely the get beyond this point.
10859
45.8k
  int hash_value = (input.size() + (unsigned)(input[0])) & 3;
10860
45.8k
  const std::string_view target = table_is_double_dot_path_segment[hash_value];
10861
45.8k
  if (target.size() != input.size()) {
10862
11.9k
    return false;
10863
11.9k
  }
10864
  // We almost never get here.
10865
  // Optimizing the rest is relatively unimportant.
10866
33.8k
  auto prefix_equal_unsafe = [](std::string_view a, std::string_view b) {
10867
33.8k
    uint16_t A, B;
10868
33.8k
    memcpy(&A, a.data(), sizeof(A));
10869
33.8k
    memcpy(&B, b.data(), sizeof(B));
10870
33.8k
    return A == B;
10871
33.8k
  };
10872
33.8k
  if (!prefix_equal_unsafe(input, target)) {
10873
2.48k
    return false;
10874
2.48k
  }
10875
39.2k
  for (size_t i = 2; i < input.size(); i++) {
10876
12.7k
    char c = input[i];
10877
12.7k
    if ((uint8_t((c | 0x20) - 0x61) <= 25 ? (c | 0x20) : c) != target[i]) {
10878
4.84k
      return false;
10879
4.84k
    }
10880
12.7k
  }
10881
26.5k
  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
31.3k
}
10891
10892
ada_really_inline constexpr bool is_single_dot_path_segment(
10893
178k
    std::string_view input) noexcept {
10894
178k
  return input == "." || input == "%2e" || input == "%2E";
10895
178k
}
10896
10897
25.0k
ada_really_inline constexpr bool is_lowercase_hex(const char c) noexcept {
10898
25.0k
  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
10899
25.0k
}
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
27.0k
unsigned constexpr convert_hex_to_binary(const char c) noexcept {
10906
27.0k
  return hex_to_binary_table[c - '0'];
10907
27.0k
}
10908
10909
1.21k
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
1.21k
  if (first_percent == std::string_view::npos) {
10913
0
    return std::string(input);
10914
0
  }
10915
1.21k
  std::string dest;
10916
1.21k
  dest.reserve(input.length());
10917
1.21k
  dest.append(input.substr(0, first_percent));
10918
1.21k
  const char* pointer = input.data() + first_percent;
10919
1.21k
  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
28.5k
  while (pointer < end) {
10923
27.3k
    const char ch = pointer[0];
10924
27.3k
    size_t remaining = end - pointer - 1;
10925
27.3k
    if (ch != '%' || remaining < 2 ||
10926
13.7k
        (  // ch == '%' && // It is unnecessary to check that ch == '%'.
10927
13.7k
            (!is_ascii_hex_digit(pointer[1]) ||
10928
14.8k
             !is_ascii_hex_digit(pointer[2])))) {
10929
14.8k
      dest += ch;
10930
14.8k
      pointer++;
10931
14.8k
    } else {
10932
12.5k
      unsigned a = convert_hex_to_binary(pointer[1]);
10933
12.5k
      unsigned b = convert_hex_to_binary(pointer[2]);
10934
12.5k
      char c = static_cast<char>(a * 16 + b);
10935
12.5k
      dest += c;
10936
12.5k
      pointer += 3;
10937
12.5k
    }
10938
27.3k
  }
10939
1.21k
  return dest;
10940
1.21k
}
10941
10942
std::string percent_encode(const std::string_view input,
10943
49.6k
                           const uint8_t character_set[]) {
10944
361k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10945
361k
    return character_sets::bit_at(character_set, c);
10946
361k
  });
10947
  // Optimization: Don't iterate if percent encode is not required
10948
49.6k
  if (pointer == input.end()) {
10949
20.7k
    return std::string(input);
10950
20.7k
  }
10951
10952
28.8k
  std::string result;
10953
28.8k
  result.reserve(input.length());  // in the worst case, percent encoding might
10954
                                   // produce 3 characters.
10955
28.8k
  result.append(input.substr(0, std::distance(input.begin(), pointer)));
10956
10957
924k
  for (; pointer != input.end(); pointer++) {
10958
896k
    if (character_sets::bit_at(character_set, *pointer)) {
10959
690k
      result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10960
690k
    } else {
10961
205k
      result += *pointer;
10962
205k
    }
10963
896k
  }
10964
10965
28.8k
  return result;
10966
49.6k
}
10967
10968
template <bool append>
10969
bool percent_encode(const std::string_view input, const uint8_t character_set[],
10970
87.4k
                    std::string& out) {
10971
87.4k
  ada_log("percent_encode ", input, " to output string while ",
10972
87.4k
          append ? "appending" : "overwriting");
10973
364k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10974
364k
    return character_sets::bit_at(character_set, c);
10975
364k
  });
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
142k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10974
142k
    return character_sets::bit_at(character_set, c);
10975
142k
  });
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
221k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10974
221k
    return character_sets::bit_at(character_set, c);
10975
221k
  });
10976
87.4k
  ada_log("percent_encode done checking, moved to ",
10977
87.4k
          std::distance(input.begin(), pointer));
10978
10979
  // Optimization: Don't iterate if percent encode is not required
10980
87.4k
  if (pointer == input.end()) {
10981
46.7k
    ada_log("percent_encode encoding not needed.");
10982
46.7k
    return false;
10983
46.7k
  }
10984
40.6k
  if constexpr (!append) {
10985
31.2k
    out.clear();
10986
31.2k
  }
10987
40.6k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10988
40.6k
          " bytes");
10989
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10990
40.6k
  out.append(input.data(), std::distance(input.begin(), pointer));
10991
40.6k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10992
40.6k
          " bytes");
10993
877k
  for (; pointer != input.end(); pointer++) {
10994
837k
    if (character_sets::bit_at(character_set, *pointer)) {
10995
667k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10996
667k
    } else {
10997
170k
      out += *pointer;
10998
170k
    }
10999
837k
  }
11000
40.6k
  return true;
11001
87.4k
}
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
70.3k
                    std::string& out) {
10971
70.3k
  ada_log("percent_encode ", input, " to output string while ",
10972
70.3k
          append ? "appending" : "overwriting");
10973
70.3k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10974
70.3k
    return character_sets::bit_at(character_set, c);
10975
70.3k
  });
10976
70.3k
  ada_log("percent_encode done checking, moved to ",
10977
70.3k
          std::distance(input.begin(), pointer));
10978
10979
  // Optimization: Don't iterate if percent encode is not required
10980
70.3k
  if (pointer == input.end()) {
10981
39.1k
    ada_log("percent_encode encoding not needed.");
10982
39.1k
    return false;
10983
39.1k
  }
10984
31.2k
  if constexpr (!append) {
10985
31.2k
    out.clear();
10986
31.2k
  }
10987
31.2k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10988
31.2k
          " bytes");
10989
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10990
31.2k
  out.append(input.data(), std::distance(input.begin(), pointer));
10991
31.2k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10992
31.2k
          " bytes");
10993
522k
  for (; pointer != input.end(); pointer++) {
10994
491k
    if (character_sets::bit_at(character_set, *pointer)) {
10995
410k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10996
410k
    } else {
10997
81.4k
      out += *pointer;
10998
81.4k
    }
10999
491k
  }
11000
31.2k
  return true;
11001
70.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
17.0k
                    std::string& out) {
10971
17.0k
  ada_log("percent_encode ", input, " to output string while ",
10972
17.0k
          append ? "appending" : "overwriting");
10973
17.0k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10974
17.0k
    return character_sets::bit_at(character_set, c);
10975
17.0k
  });
10976
17.0k
  ada_log("percent_encode done checking, moved to ",
10977
17.0k
          std::distance(input.begin(), pointer));
10978
10979
  // Optimization: Don't iterate if percent encode is not required
10980
17.0k
  if (pointer == input.end()) {
10981
7.65k
    ada_log("percent_encode encoding not needed.");
10982
7.65k
    return false;
10983
7.65k
  }
10984
  if constexpr (!append) {
10985
    out.clear();
10986
  }
10987
9.41k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10988
9.41k
          " bytes");
10989
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10990
9.41k
  out.append(input.data(), std::distance(input.begin(), pointer));
10991
9.41k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10992
9.41k
          " bytes");
10993
354k
  for (; pointer != input.end(); pointer++) {
10994
345k
    if (character_sets::bit_at(character_set, *pointer)) {
10995
256k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10996
256k
    } else {
10997
88.5k
      out += *pointer;
10998
88.5k
    }
10999
345k
  }
11000
9.41k
  return true;
11001
17.0k
}
11002
11003
bool to_ascii(std::optional<std::string>& out, const std::string_view plain,
11004
15.8k
              size_t first_percent) {
11005
15.8k
  std::string percent_decoded_buffer;
11006
15.8k
  std::string_view input = plain;
11007
15.8k
  if (first_percent != std::string_view::npos) {
11008
1.21k
    percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
11009
1.21k
    input = percent_decoded_buffer;
11010
1.21k
  }
11011
  // input is a non-empty UTF-8 string, must be percent decoded
11012
15.8k
  std::string idna_ascii = ada::idna::to_ascii(input);
11013
15.8k
  if (idna_ascii.empty() || contains_forbidden_domain_code_point(
11014
11.3k
                                idna_ascii.data(), idna_ascii.size())) {
11015
8.34k
    return false;
11016
8.34k
  }
11017
7.54k
  out = std::move(idna_ascii);
11018
7.54k
  return true;
11019
15.8k
}
11020
11021
std::string percent_encode(const std::string_view input,
11022
13.2k
                           const uint8_t character_set[], size_t index) {
11023
13.2k
  std::string out;
11024
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
11025
13.2k
  out.append(input.data(), index);
11026
13.2k
  auto pointer = input.begin() + index;
11027
434k
  for (; pointer != input.end(); pointer++) {
11028
421k
    if (character_sets::bit_at(character_set, *pointer)) {
11029
316k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
11030
316k
    } else {
11031
104k
      out += *pointer;
11032
104k
    }
11033
421k
  }
11034
13.2k
  return out;
11035
13.2k
}
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
252
    size_t& compress_length) noexcept {
11049
796
  for (size_t i = 0; i < 8; i++) {
11050
670
    if (address[i] == 0) {
11051
316
      size_t next = i + 1;
11052
1.58k
      while (next != 8 && address[next] == 0) ++next;
11053
316
      const size_t count = next - i;
11054
316
      if (compress_length < count) {
11055
246
        compress_length = count;
11056
246
        compress = i;
11057
246
        if (next == 8) break;
11058
120
        i = next;
11059
120
      }
11060
316
    }
11061
670
  }
11062
252
}
11063
11064
252
std::string ipv6(const std::array<uint16_t, 8>& address) {
11065
252
  size_t compress_length = 0;  // The length of a long sequence of zeros.
11066
252
  size_t compress = 0;         // The start of a long sequence of zeros.
11067
252
  find_longest_sequence_of_ipv6_pieces(address, compress, compress_length);
11068
11069
252
  if (compress_length <= 1) {
11070
    // Optimization opportunity: Find a faster way then snprintf for imploding
11071
    // and return here.
11072
24
    compress = compress_length = 8;
11073
24
  }
11074
11075
252
  std::string output(4 * 8 + 7 + 2, '\0');
11076
252
  size_t piece_index = 0;
11077
252
  char* point = output.data();
11078
252
  char* point_end = output.data() + output.size();
11079
252
  *point++ = '[';
11080
688
  while (true) {
11081
688
    if (piece_index == compress) {
11082
228
      *point++ = ':';
11083
      // If we skip a value initially, we need to write '::', otherwise
11084
      // a single ':' will do since it follows a previous ':'.
11085
228
      if (piece_index == 0) {
11086
122
        *point++ = ':';
11087
122
      }
11088
228
      piece_index += compress_length;
11089
228
      if (piece_index == 8) {
11090
126
        break;
11091
126
      }
11092
228
    }
11093
562
    point = std::to_chars(point, point_end, address[piece_index], 16).ptr;
11094
562
    piece_index++;
11095
562
    if (piece_index == 8) {
11096
126
      break;
11097
126
    }
11098
436
    *point++ = ':';
11099
436
  }
11100
252
  *point++ = ']';
11101
252
  output.resize(point - output.data());
11102
252
  return output;
11103
252
}
11104
11105
2.99k
std::string ipv4(const uint64_t address) {
11106
2.99k
  std::string output(15, '\0');
11107
2.99k
  char* point = output.data();
11108
2.99k
  char* point_end = output.data() + output.size();
11109
2.99k
  point = std::to_chars(point, point_end, uint8_t(address >> 24)).ptr;
11110
11.9k
  for (int i = 2; i >= 0; i--) {
11111
8.98k
    *point++ = '.';
11112
8.98k
    point = std::to_chars(point, point_end, uint8_t(address >> (i * 8))).ptr;
11113
8.98k
  }
11114
2.99k
  output.resize(point - output.data());
11115
2.99k
  return output;
11116
2.99k
}
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
39.5k
    std::string_view input, const result_type* base_url) {
11130
39.5k
  result_type u =
11131
39.5k
      ada::parser::parse_url_impl<result_type, true>(input, base_url);
11132
39.5k
  if (!u.is_valid) {
11133
11.2k
    return tl::unexpected(errors::type_error);
11134
11.2k
  }
11135
28.3k
  return u;
11136
39.5k
}
tl::expected<ada::url, ada::errors> ada::parse<ada::url>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url const*)
Line
Count
Source
11129
19.7k
    std::string_view input, const result_type* base_url) {
11130
19.7k
  result_type u =
11131
19.7k
      ada::parser::parse_url_impl<result_type, true>(input, base_url);
11132
19.7k
  if (!u.is_valid) {
11133
5.54k
    return tl::unexpected(errors::type_error);
11134
5.54k
  }
11135
14.2k
  return u;
11136
19.7k
}
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
19.7k
    std::string_view input, const result_type* base_url) {
11130
19.7k
  result_type u =
11131
19.7k
      ada::parser::parse_url_impl<result_type, true>(input, base_url);
11132
19.7k
  if (!u.is_valid) {
11133
5.68k
    return tl::unexpected(errors::type_error);
11134
5.68k
  }
11135
14.0k
  return u;
11136
19.7k
}
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
8.27k
std::string href_from_file(std::string_view input) {
11144
  // This is going to be much faster than constructing a URL.
11145
8.27k
  std::string tmp_buffer;
11146
8.27k
  std::string_view internal_input;
11147
8.27k
  if (unicode::has_tabs_or_newline(input)) {
11148
166
    tmp_buffer = input;
11149
166
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
11150
166
    internal_input = tmp_buffer;
11151
8.11k
  } else {
11152
8.11k
    internal_input = input;
11153
8.11k
  }
11154
8.27k
  std::string path;
11155
8.27k
  if (internal_input.empty()) {
11156
29
    path = "/";
11157
8.24k
  } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
11158
693
    helpers::parse_prepared_path(internal_input.substr(1),
11159
693
                                 ada::scheme::type::FILE, path);
11160
7.55k
  } else {
11161
7.55k
    helpers::parse_prepared_path(internal_input, ada::scheme::type::FILE, path);
11162
7.55k
  }
11163
8.27k
  return "file://" + path;
11164
8.27k
}
11165
11166
0
bool can_parse(std::string_view input, const std::string_view* base_input) {
11167
0
  ada::url_aggregator base_aggregator;
11168
0
  ada::url_aggregator* base_pointer = nullptr;
11169
11170
0
  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
0
  ada::url_aggregator result =
11180
0
      ada::parser::parse_url_impl<ada::url_aggregator, false>(input,
11181
0
                                                              base_pointer);
11182
0
  return result.is_valid;
11183
0
}
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
90.7k
void encode_json(std::string_view view, out_iter out) {
11214
  // trivial implementation. could be faster.
11215
90.7k
  const char* hexvalues =
11216
90.7k
      "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
11217
7.07M
  for (uint8_t c : view) {
11218
7.07M
    if (c == '\\') {
11219
2.88k
      *out++ = '\\';
11220
2.88k
      *out++ = '\\';
11221
7.07M
    } else if (c == '"') {
11222
953
      *out++ = '\\';
11223
953
      *out++ = '"';
11224
7.07M
    } 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
7.07M
    } else {
11232
7.07M
      *out++ = c;
11233
7.07M
    }
11234
7.07M
  }
11235
90.7k
}
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
39.5k
    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
39.5k
  size_t location_of_first = input.find('#');
11289
39.5k
  if (location_of_first == std::string_view::npos) {
11290
39.0k
    return std::nullopt;
11291
39.0k
  }
11292
522
  std::string_view hash = input;
11293
522
  hash.remove_prefix(location_of_first + 1);
11294
522
  input.remove_suffix(input.size() - location_of_first);
11295
522
  return hash;
11296
39.5k
}
11297
11298
26.5k
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
26.5k
  if (type == ada::scheme::type::FILE &&
11303
20.2k
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11304
11.5k
    if (checkers::is_normalized_windows_drive_letter(
11305
11.5k
            helpers::substring(path, 1))) {
11306
3.79k
      return false;
11307
3.79k
    }
11308
11.5k
  }
11309
11310
  // Remove path's last item, if any.
11311
22.7k
  size_t last_delimiter = path.rfind('/');
11312
22.7k
  if (last_delimiter != std::string::npos) {
11313
13.7k
    path.erase(last_delimiter);
11314
13.7k
    return true;
11315
13.7k
  }
11316
11317
9.00k
  return false;
11318
22.7k
}
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
104k
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
104k
  std::erase_if(input, ada::unicode::is_ascii_tab_or_newline);
11349
104k
}
11350
11351
ada_really_inline constexpr std::string_view substring(std::string_view input,
11352
25.8k
                                                       size_t pos) {
11353
25.8k
  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
25.8k
  return input.substr(pos);
11357
25.8k
}
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
12.8k
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
12.8k
  return __builtin_ctzl(input_num);
11375
12.8k
#endif  // ADA_REGULAR_VISUAL_STUDIO
11376
12.8k
}
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
56.1k
    std::string_view view, size_t location) noexcept {
11514
  // first check for short strings in which case we do it naively.
11515
56.1k
  if (view.size() - location < 16) {  // slow path
11516
366k
    for (size_t i = location; i < view.size(); i++) {
11517
339k
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11518
328k
          view[i] == '?' || view[i] == '[') {
11519
13.2k
        return i;
11520
13.2k
      }
11521
339k
    }
11522
26.7k
    return size_t(view.size());
11523
39.9k
  }
11524
  // fast path for long strings (expected to be common)
11525
16.1k
  size_t i = location;
11526
16.1k
  const __m128i mask1 = _mm_set1_epi8(':');
11527
16.1k
  const __m128i mask2 = _mm_set1_epi8('/');
11528
16.1k
  const __m128i mask3 = _mm_set1_epi8('\\');
11529
16.1k
  const __m128i mask4 = _mm_set1_epi8('?');
11530
16.1k
  const __m128i mask5 = _mm_set1_epi8('[');
11531
11532
41.2k
  for (; i + 15 < view.size(); i += 16) {
11533
36.1k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11534
36.1k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11535
36.1k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11536
36.1k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11537
36.1k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11538
36.1k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11539
36.1k
    __m128i m = _mm_or_si128(
11540
36.1k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11541
36.1k
    int mask = _mm_movemask_epi8(m);
11542
36.1k
    if (mask != 0) {
11543
11.0k
      return i + trailing_zeroes(mask);
11544
11.0k
    }
11545
36.1k
  }
11546
5.08k
  if (i < view.size()) {
11547
4.48k
    __m128i word =
11548
4.48k
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11549
4.48k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11550
4.48k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11551
4.48k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11552
4.48k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11553
4.48k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11554
4.48k
    __m128i m = _mm_or_si128(
11555
4.48k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11556
4.48k
    int mask = _mm_movemask_epi8(m);
11557
4.48k
    if (mask != 0) {
11558
1.20k
      return view.length() - 16 + trailing_zeroes(mask);
11559
1.20k
    }
11560
4.48k
  }
11561
3.88k
  return size_t(view.length());
11562
5.08k
}
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
1.23k
                                                  size_t location) noexcept {
11803
  // first check for short strings in which case we do it naively.
11804
1.23k
  if (view.size() - location < 16) {  // slow path
11805
1.72k
    for (size_t i = location; i < view.size(); i++) {
11806
1.40k
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11807
1.28k
          view[i] == '[') {
11808
274
        return i;
11809
274
      }
11810
1.40k
    }
11811
320
    return size_t(view.size());
11812
594
  }
11813
  // fast path for long strings (expected to be common)
11814
636
  size_t i = location;
11815
636
  const __m128i mask1 = _mm_set1_epi8(':');
11816
636
  const __m128i mask2 = _mm_set1_epi8('/');
11817
636
  const __m128i mask4 = _mm_set1_epi8('?');
11818
636
  const __m128i mask5 = _mm_set1_epi8('[');
11819
11820
2.04k
  for (; i + 15 < view.size(); i += 16) {
11821
1.88k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11822
1.88k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11823
1.88k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11824
1.88k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11825
1.88k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11826
1.88k
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
11827
1.88k
    int mask = _mm_movemask_epi8(m);
11828
1.88k
    if (mask != 0) {
11829
476
      return i + trailing_zeroes(mask);
11830
476
    }
11831
1.88k
  }
11832
160
  if (i < view.size()) {
11833
126
    __m128i word =
11834
126
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11835
126
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11836
126
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11837
126
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11838
126
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11839
126
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
11840
126
    int mask = _mm_movemask_epi8(m);
11841
126
    if (mask != 0) {
11842
60
      return view.length() - 16 + trailing_zeroes(mask);
11843
60
    }
11844
126
  }
11845
100
  return size_t(view.length());
11846
160
}
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
52.6k
    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
52.6k
  const size_t view_size = view.size();
11946
52.6k
  size_t location = 0;
11947
52.6k
  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
52.6k
  if (is_special) {
11968
    // We move to the next delimiter.
11969
51.8k
    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
56.1k
    for (; location < view_size;
11973
51.8k
         location = find_next_host_delimiter_special(view, location)) {
11974
25.4k
      if (view[location] == '[') {
11975
4.45k
        location = view.find(']', location);
11976
4.45k
        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
226
          location = view_size;
11981
226
          break;
11982
226
        }
11983
21.0k
      } else {
11984
21.0k
        found_colon = view[location] == ':';
11985
21.0k
        break;
11986
21.0k
      }
11987
25.4k
    }
11988
51.8k
  } else {
11989
    // We move to the next delimiter.
11990
716
    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
1.23k
    for (; location < view_size;
11994
810
         location = find_next_host_delimiter(view, location)) {
11995
810
      if (view[location] == '[') {
11996
552
        location = view.find(']', location);
11997
552
        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
38
          location = view_size;
12002
38
          break;
12003
38
        }
12004
552
      } else {
12005
258
        found_colon = view[location] == ':';
12006
258
        break;
12007
258
      }
12008
810
    }
12009
716
  }
12010
  // performance: remove_suffix may translate into a single instruction.
12011
52.6k
  view.remove_suffix(view_size - location);
12012
52.6k
  return {location, found_colon};
12013
52.6k
}
12014
12015
39.5k
void trim_c0_whitespace(std::string_view& input) noexcept {
12016
41.4k
  while (!input.empty() &&
12017
41.3k
         ada::unicode::is_c0_control_or_space(input.front())) {
12018
1.89k
    input.remove_prefix(1);
12019
1.89k
  }
12020
42.3k
  while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
12021
2.77k
    input.remove_suffix(1);
12022
2.77k
  }
12023
39.5k
}
12024
12025
ada_really_inline void parse_prepared_path(std::string_view input,
12026
                                           ada::scheme::type type,
12027
18.9k
                                           std::string& path) {
12028
18.9k
  ada_log("parse_prepared_path ", input);
12029
18.9k
  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
18.9k
  constexpr uint8_t need_encoding = 1;
12035
18.9k
  constexpr uint8_t backslash_char = 2;
12036
18.9k
  constexpr uint8_t dot_char = 4;
12037
18.9k
  constexpr uint8_t percent_char = 8;
12038
18.9k
  bool special = type != ada::scheme::NOT_SPECIAL;
12039
18.9k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
12040
9.76k
                                      checkers::is_windows_drive_letter(input));
12041
18.9k
  bool trivial_path =
12042
18.9k
      (special ? (accumulator == 0)
12043
18.9k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
12044
846
                  0)) &&
12045
3.81k
      (!may_need_slow_file_handling);
12046
18.9k
  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
3.69k
    if (input[0] != '.') {
12055
2.82k
      size_t slashdot = 0;
12056
2.82k
      bool dot_is_file = true;
12057
13.2k
      for (;;) {
12058
13.2k
        slashdot = input.find("/.", slashdot);
12059
13.2k
        if (slashdot == std::string_view::npos) {  // common case
12060
2.82k
          break;
12061
10.4k
        } else {  // uncommon
12062
          // only three cases matter: /./, /.. or a final /
12063
10.4k
          slashdot += 2;
12064
10.4k
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
12065
1.80k
                           input[slashdot] == '/');
12066
10.4k
        }
12067
13.2k
      }
12068
2.82k
      trivial_path = dot_is_file;
12069
2.82k
    }
12070
3.69k
  }
12071
18.9k
  if (trivial_path) {
12072
4.92k
    ada_log("parse_path trivial");
12073
4.92k
    path += '/';
12074
4.92k
    path += input;
12075
4.92k
    return;
12076
4.92k
  }
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
14.0k
  bool fast_path =
12082
14.0k
      (special &&
12083
13.2k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
12084
2.53k
      (type != ada::scheme::type::FILE);
12085
14.0k
  if (fast_path) {
12086
1.22k
    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
1.22k
    size_t previous_location = 0;  // We start at 0.
12092
16.2k
    do {
12093
16.2k
      size_t new_location = input.find('/', previous_location);
12094
      // std::string_view path_view = input;
12095
      //  We process the last segment separately:
12096
16.2k
      if (new_location == std::string_view::npos) {
12097
1.22k
        std::string_view path_view = input.substr(previous_location);
12098
1.22k
        if (path_view == "..") {  // The path ends with ..
12099
          // e.g., if you receive ".." with an empty path, you go to "/".
12100
166
          if (path.empty()) {
12101
63
            path = '/';
12102
63
            return;
12103
63
          }
12104
          // Fast case where we have nothing to do:
12105
103
          if (path.back() == '/') {
12106
34
            return;
12107
34
          }
12108
          // If you have the path "/joe/myfriend",
12109
          // then you delete 'myfriend'.
12110
69
          path.resize(path.rfind('/') + 1);
12111
69
          return;
12112
103
        }
12113
1.06k
        path += '/';
12114
1.06k
        if (path_view != ".") {
12115
824
          path.append(path_view);
12116
824
        }
12117
1.06k
        return;
12118
15.0k
      } else {
12119
        // This is a non-final segment.
12120
15.0k
        std::string_view path_view =
12121
15.0k
            input.substr(previous_location, new_location - previous_location);
12122
15.0k
        previous_location = new_location + 1;
12123
15.0k
        if (path_view == "..") {
12124
3.73k
          size_t last_delimiter = path.rfind('/');
12125
3.73k
          if (last_delimiter != std::string::npos) {
12126
1.91k
            path.erase(last_delimiter);
12127
1.91k
          }
12128
11.2k
        } else if (path_view != ".") {
12129
9.60k
          path += '/';
12130
9.60k
          path.append(path_view);
12131
9.60k
        }
12132
15.0k
      }
12133
16.2k
    } while (true);
12134
12.7k
  } else {
12135
12.7k
    ada_log("parse_path slow");
12136
    // we have reached the general case
12137
12.7k
    bool needs_percent_encoding = (accumulator & 1);
12138
12.7k
    std::string path_buffer_tmp;
12139
74.6k
    do {
12140
74.6k
      size_t location = (special && (accumulator & 2))
12141
74.6k
                            ? input.find_first_of("/\\")
12142
74.6k
                            : input.find('/');
12143
74.6k
      std::string_view path_view = input;
12144
74.6k
      if (location != std::string_view::npos) {
12145
61.8k
        path_view.remove_suffix(path_view.size() - location);
12146
61.8k
        input.remove_prefix(location + 1);
12147
61.8k
      }
12148
      // path_buffer is either path_view or it might point at a percent encoded
12149
      // temporary file.
12150
74.6k
      std::string_view path_buffer =
12151
74.6k
          (needs_percent_encoding &&
12152
43.4k
           ada::unicode::percent_encode<false>(
12153
43.4k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
12154
74.6k
              ? path_buffer_tmp
12155
74.6k
              : path_view;
12156
74.6k
      if (unicode::is_double_dot_path_segment(path_buffer)) {
12157
16.5k
        helpers::shorten_path(path, type);
12158
16.5k
        if (location == std::string_view::npos) {
12159
1.21k
          path += '/';
12160
1.21k
        }
12161
58.1k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
12162
4.39k
                 (location == std::string_view::npos)) {
12163
404
        path += '/';
12164
404
      }
12165
      // Otherwise, if path_buffer is not a single-dot path segment, then:
12166
57.7k
      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
53.7k
        if (type == ada::scheme::type::FILE && path.empty() &&
12171
11.5k
            checkers::is_windows_drive_letter(path_buffer)) {
12172
706
          path += '/';
12173
706
          path += path_buffer[0];
12174
706
          path += ':';
12175
706
          path_buffer.remove_prefix(2);
12176
706
          path.append(path_buffer);
12177
53.0k
        } else {
12178
          // Append path_buffer to url's path.
12179
53.0k
          path += '/';
12180
53.0k
          path.append(path_buffer);
12181
53.0k
        }
12182
53.7k
      }
12183
74.6k
      if (location == std::string_view::npos) {
12184
12.7k
        return;
12185
12.7k
      }
12186
74.6k
    } while (true);
12187
12.7k
  }
12188
14.0k
}
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
8
ada_really_inline void strip_trailing_spaces_from_opaque_path(url_type& url) {
12200
8
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
12201
8
  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
}
void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url>(ada::url&)
Line
Count
Source
12199
4
ada_really_inline void strip_trailing_spaces_from_opaque_path(url_type& url) {
12200
4
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
12201
4
  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
}
void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url_aggregator>(ada::url_aggregator&)
Line
Count
Source
12199
4
ada_really_inline void strip_trailing_spaces_from_opaque_path(url_type& url) {
12200
4
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
12201
4
  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
}
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
12.9k
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
64.6k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12227
63.6k
    if (authority_delimiter_special[(uint8_t)*pos]) {
12228
12.0k
      return pos - view.begin();
12229
12.0k
    }
12230
63.6k
  }
12231
976
  return size_t(view.size());
12232
12.9k
}
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.83k
find_authority_delimiter(std::string_view view) noexcept {
12245
  // performance note: we might be able to gain further performance
12246
  // with SIMD instrinsics.
12247
9.80k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12248
9.64k
    if (authority_delimiter[(uint8_t)*pos]) {
12249
1.67k
      return pos - view.begin();
12250
1.67k
    }
12251
9.64k
  }
12252
152
  return size_t(view.size());
12253
1.83k
}
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
247
bool url::parse_opaque_host(std::string_view input) {
12276
247
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
12277
247
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
12278
21
    return is_valid = false;
12279
21
  }
12280
12281
  // Return the result of running UTF-8 percent-encode on input using the C0
12282
  // control percent-encode set.
12283
226
  host = ada::unicode::percent_encode(
12284
226
      input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
12285
226
  return true;
12286
247
}
12287
12288
2.16k
bool url::parse_ipv4(std::string_view input) {
12289
2.16k
  ada_log("parse_ipv4 ", input, " [", input.size(), " bytes]");
12290
2.16k
  if (input.back() == '.') {
12291
59
    input.remove_suffix(1);
12292
59
  }
12293
2.16k
  size_t digit_count{0};
12294
2.16k
  int pure_decimal_count = 0;  // entries that are decimal
12295
2.16k
  std::string_view original_input =
12296
2.16k
      input;  // we might use this if pure_decimal_count == 4.
12297
2.16k
  uint64_t ipv4{0};
12298
  // we could unroll for better performance?
12299
2.62k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
12300
2.59k
    uint32_t
12301
2.59k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
12302
2.59k
    bool is_hex = checkers::has_hex_prefix(input);
12303
2.59k
    if (is_hex && ((input.length() == 2) ||
12304
784
                   ((input.length() > 2) && (input[2] == '.')))) {
12305
      // special case
12306
47
      segment_result = 0;
12307
47
      input.remove_prefix(2);
12308
2.55k
    } else {
12309
2.55k
      std::from_chars_result r{};
12310
2.55k
      if (is_hex) {
12311
769
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
12312
769
                            segment_result, 16);
12313
1.78k
      } else if ((input.length() >= 2) && input[0] == '0' &&
12314
518
                 checkers::is_digit(input[1])) {
12315
421
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
12316
421
                            segment_result, 8);
12317
1.36k
      } else {
12318
1.36k
        pure_decimal_count++;
12319
1.36k
        r = std::from_chars(input.data(), input.data() + input.size(),
12320
1.36k
                            segment_result, 10);
12321
1.36k
      }
12322
2.55k
      if (r.ec != std::errc()) {
12323
421
        return is_valid = false;
12324
421
      }
12325
2.13k
      input.remove_prefix(r.ptr - input.data());
12326
2.13k
    }
12327
2.17k
    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
1.53k
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
12332
39
        return is_valid = false;
12333
39
      }
12334
1.50k
      ipv4 <<= (32 - digit_count * 8);
12335
1.50k
      ipv4 |= segment_result;
12336
1.50k
      goto final;
12337
1.53k
    } else {
12338
      // There is more, so that the value must no be larger than 255
12339
      // and we must have a '.'.
12340
638
      if ((segment_result > 255) || (input[0] != '.')) {
12341
178
        return is_valid = false;
12342
178
      }
12343
460
      ipv4 <<= 8;
12344
460
      ipv4 |= segment_result;
12345
460
      input.remove_prefix(1);  // remove '.'
12346
460
    }
12347
2.17k
  }
12348
24
  if ((digit_count != 4) || (!input.empty())) {
12349
24
    return is_valid = false;
12350
24
  }
12351
1.50k
final:
12352
  // We could also check r.ptr to see where the parsing ended.
12353
1.50k
  if (pure_decimal_count == 4) {
12354
4
    host = original_input;  // The original input was already all decimal and we
12355
                            // validated it.
12356
1.49k
  } else {
12357
1.49k
    host = ada::serializers::ipv4(ipv4);  // We have to reserialize the address.
12358
1.49k
  }
12359
1.50k
  host_type = IPV4;
12360
1.50k
  return true;
12361
24
}
12362
12363
396
bool url::parse_ipv6(std::string_view input) {
12364
396
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
12365
12366
396
  if (input.empty()) {
12367
18
    return is_valid = false;
12368
18
  }
12369
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
12370
378
  std::array<uint16_t, 8> address{};
12371
12372
  // Let pieceIndex be 0.
12373
378
  int piece_index = 0;
12374
12375
  // Let compress be null.
12376
378
  std::optional<int> compress{};
12377
12378
  // Let pointer be a pointer for input.
12379
378
  std::string_view::iterator pointer = input.begin();
12380
12381
  // If c is U+003A (:), then:
12382
378
  if (input[0] == ':') {
12383
    // If remaining does not start with U+003A (:), validation error, return
12384
    // failure.
12385
82
    if (input.size() == 1 || input[1] != ':') {
12386
19
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
12387
19
      return is_valid = false;
12388
19
    }
12389
12390
    // Increase pointer by 2.
12391
63
    pointer += 2;
12392
12393
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
12394
63
    compress = ++piece_index;
12395
63
  }
12396
12397
  // While c is not the EOF code point:
12398
887
  while (pointer != input.end()) {
12399
    // If pieceIndex is 8, validation error, return failure.
12400
715
    if (piece_index == 8) {
12401
5
      ada_log("parse_ipv6 piece_index == 8");
12402
5
      return is_valid = false;
12403
5
    }
12404
12405
    // If c is U+003A (:), then:
12406
710
    if (*pointer == ':') {
12407
      // If compress is non-null, validation error, return failure.
12408
80
      if (compress.has_value()) {
12409
8
        ada_log("parse_ipv6 compress is non-null");
12410
8
        return is_valid = false;
12411
8
      }
12412
12413
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
12414
      // then continue.
12415
72
      pointer++;
12416
72
      compress = ++piece_index;
12417
72
      continue;
12418
80
    }
12419
12420
    // Let value and length be 0.
12421
630
    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
1.59k
    while (length < 4 && pointer != input.end() &&
12427
1.42k
           unicode::is_ascii_hex_digit(*pointer)) {
12428
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12429
963
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
12430
963
      pointer++;
12431
963
      length++;
12432
963
    }
12433
12434
    // If c is U+002E (.), then:
12435
630
    if (pointer != input.end() && *pointer == '.') {
12436
      // If length is 0, validation error, return failure.
12437
71
      if (length == 0) {
12438
3
        ada_log("parse_ipv6 length is 0");
12439
3
        return is_valid = false;
12440
3
      }
12441
12442
      // Decrease pointer by length.
12443
68
      pointer -= length;
12444
12445
      // If pieceIndex is greater than 6, validation error, return failure.
12446
68
      if (piece_index > 6) {
12447
3
        ada_log("parse_ipv6 piece_index > 6");
12448
3
        return is_valid = false;
12449
3
      }
12450
12451
      // Let numbersSeen be 0.
12452
65
      int numbers_seen = 0;
12453
12454
      // While c is not the EOF code point:
12455
158
      while (pointer != input.end()) {
12456
        // Let ipv4Piece be null.
12457
144
        std::optional<uint16_t> ipv4_piece{};
12458
12459
        // If numbersSeen is greater than 0, then:
12460
144
        if (numbers_seen > 0) {
12461
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
12462
          // pointer by 1.
12463
79
          if (*pointer == '.' && numbers_seen < 4) {
12464
71
            pointer++;
12465
71
          }
12466
          // Otherwise, validation error, return failure.
12467
8
          else {
12468
8
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
12469
8
            return is_valid = false;
12470
8
          }
12471
79
        }
12472
12473
        // If c is not an ASCII digit, validation error, return failure.
12474
136
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
12475
26
          ada_log(
12476
26
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
12477
26
              "failure");
12478
26
          return is_valid = false;
12479
26
        }
12480
12481
        // While c is an ASCII digit:
12482
299
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
12483
          // Let number be c interpreted as decimal number.
12484
206
          int number = *pointer - '0';
12485
12486
          // If ipv4Piece is null, then set ipv4Piece to number.
12487
206
          if (!ipv4_piece.has_value()) {
12488
110
            ipv4_piece = number;
12489
110
          }
12490
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
12491
96
          else if (ipv4_piece == 0) {
12492
3
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
12493
3
            return is_valid = false;
12494
3
          }
12495
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
12496
93
          else {
12497
93
            ipv4_piece = *ipv4_piece * 10 + number;
12498
93
          }
12499
12500
          // If ipv4Piece is greater than 255, validation error, return failure.
12501
203
          if (ipv4_piece > 255) {
12502
14
            ada_log("parse_ipv6 ipv4_piece > 255");
12503
14
            return is_valid = false;
12504
14
          }
12505
12506
          // Increase pointer by 1.
12507
189
          pointer++;
12508
189
        }
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
93
        address[piece_index] =
12514
93
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
12515
12516
        // Increase numbersSeen by 1.
12517
93
        numbers_seen++;
12518
12519
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
12520
93
        if (numbers_seen == 2 || numbers_seen == 4) {
12521
32
          piece_index++;
12522
32
        }
12523
93
      }
12524
12525
      // If numbersSeen is not 4, validation error, return failure.
12526
14
      if (numbers_seen != 4) {
12527
11
        return is_valid = false;
12528
11
      }
12529
12530
      // Break.
12531
3
      break;
12532
14
    }
12533
    // Otherwise, if c is U+003A (:):
12534
559
    else if ((pointer != input.end()) && (*pointer == ':')) {
12535
      // Increase pointer by 1.
12536
348
      pointer++;
12537
12538
      // If c is the EOF code point, validation error, return failure.
12539
348
      if (pointer == input.end()) {
12540
3
        ada_log(
12541
3
            "parse_ipv6 If c is the EOF code point, validation error, return "
12542
3
            "failure");
12543
3
        return is_valid = false;
12544
3
      }
12545
348
    }
12546
    // Otherwise, if c is not the EOF code point, validation error, return
12547
    // failure.
12548
211
    else if (pointer != input.end()) {
12549
100
      ada_log(
12550
100
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
12551
100
          "error, return failure");
12552
100
      return is_valid = false;
12553
100
    }
12554
12555
    // Set address[pieceIndex] to value.
12556
456
    address[piece_index] = value;
12557
12558
    // Increase pieceIndex by 1.
12559
456
    piece_index++;
12560
456
  }
12561
12562
  // If compress is non-null, then:
12563
175
  if (compress.has_value()) {
12564
    // Let swaps be pieceIndex - compress.
12565
117
    int swaps = piece_index - *compress;
12566
12567
    // Set pieceIndex to 7.
12568
117
    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
228
    while (piece_index != 0 && swaps > 0) {
12574
111
      std::swap(address[piece_index], address[*compress + swaps - 1]);
12575
111
      piece_index--;
12576
111
      swaps--;
12577
111
    }
12578
117
  }
12579
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
12580
  // return failure.
12581
58
  else if (piece_index != 8) {
12582
49
    ada_log(
12583
49
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
12584
49
        "error, return failure");
12585
49
    return is_valid = false;
12586
49
  }
12587
126
  host = ada::serializers::ipv6(address);
12588
126
  ada_log("parse_ipv6 ", *host);
12589
126
  host_type = IPV6;
12590
126
  return true;
12591
175
}
12592
12593
template <bool has_state_override>
12594
18.5k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12595
18.5k
  auto parsed_type = ada::scheme::get_scheme_type(input);
12596
18.5k
  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
18.5k
  if (is_input_special) {  // fast path!!!
12602
12.5k
    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
1.47k
      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
1.47k
      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
1.47k
      if (type == ada::scheme::type::FILE && host.has_value() &&
12619
0
          host.value().empty()) {
12620
0
        return false;
12621
0
      }
12622
1.47k
    }
12623
12624
1.47k
    type = parsed_type;
12625
12626
12.5k
    if constexpr (has_state_override) {
12627
      // This is uncommon.
12628
1.47k
      uint16_t urls_scheme_port = get_special_port();
12629
12630
1.47k
      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
991
        if (port.has_value() && *port == urls_scheme_port) {
12634
0
          port = std::nullopt;
12635
0
        }
12636
991
      }
12637
1.47k
    }
12638
12.5k
  } else {  // slow path
12639
5.99k
    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
5.99k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
12645
12646
5.99k
    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
2.22k
      if (is_special() != ada::scheme::is_special(_buffer)) {
12651
1.61k
        return true;
12652
1.61k
      }
12653
12654
      // If url includes credentials or has a non-null port, and buffer is
12655
      // "file", then return.
12656
604
      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
604
      if (type == ada::scheme::type::FILE && host.has_value() &&
12663
0
          host.value().empty()) {
12664
0
        return true;
12665
0
      }
12666
604
    }
12667
12668
604
    set_scheme(std::move(_buffer));
12669
12670
5.99k
    if constexpr (has_state_override) {
12671
      // This is uncommon.
12672
2.22k
      uint16_t urls_scheme_port = get_special_port();
12673
12674
2.22k
      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
409
        if (port.has_value() && *port == urls_scheme_port) {
12678
0
          port = std::nullopt;
12679
0
        }
12680
409
      }
12681
2.22k
    }
12682
5.99k
  }
12683
12684
0
  return true;
12685
18.5k
}
bool ada::url::parse_scheme<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
12594
3.69k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12595
3.69k
  auto parsed_type = ada::scheme::get_scheme_type(input);
12596
3.69k
  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
3.69k
  if (is_input_special) {  // fast path!!!
12602
1.47k
    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
1.47k
      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
1.47k
      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
1.47k
      if (type == ada::scheme::type::FILE && host.has_value() &&
12619
0
          host.value().empty()) {
12620
0
        return false;
12621
0
      }
12622
1.47k
    }
12623
12624
1.47k
    type = parsed_type;
12625
12626
1.47k
    if constexpr (has_state_override) {
12627
      // This is uncommon.
12628
1.47k
      uint16_t urls_scheme_port = get_special_port();
12629
12630
1.47k
      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
991
        if (port.has_value() && *port == urls_scheme_port) {
12634
0
          port = std::nullopt;
12635
0
        }
12636
991
      }
12637
1.47k
    }
12638
2.22k
  } else {  // slow path
12639
2.22k
    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
2.22k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
12645
12646
2.22k
    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
2.22k
      if (is_special() != ada::scheme::is_special(_buffer)) {
12651
1.61k
        return true;
12652
1.61k
      }
12653
12654
      // If url includes credentials or has a non-null port, and buffer is
12655
      // "file", then return.
12656
604
      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
604
      if (type == ada::scheme::type::FILE && host.has_value() &&
12663
0
          host.value().empty()) {
12664
0
        return true;
12665
0
      }
12666
604
    }
12667
12668
604
    set_scheme(std::move(_buffer));
12669
12670
2.22k
    if constexpr (has_state_override) {
12671
      // This is uncommon.
12672
2.22k
      uint16_t urls_scheme_port = get_special_port();
12673
12674
2.22k
      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
409
        if (port.has_value() && *port == urls_scheme_port) {
12678
0
          port = std::nullopt;
12679
0
        }
12680
409
      }
12681
2.22k
    }
12682
2.22k
  }
12683
12684
0
  return true;
12685
3.69k
}
bool ada::url::parse_scheme<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
12594
14.8k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12595
14.8k
  auto parsed_type = ada::scheme::get_scheme_type(input);
12596
14.8k
  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
14.8k
  if (is_input_special) {  // fast path!!!
12602
    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
      if (is_special() != is_input_special) {
12606
        return false;
12607
      }
12608
12609
      // If url includes credentials or has a non-null port, and buffer is
12610
      // "file", then return.
12611
      if ((has_credentials() || port.has_value()) &&
12612
          parsed_type == ada::scheme::type::FILE) {
12613
        return false;
12614
      }
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
      if (type == ada::scheme::type::FILE && host.has_value() &&
12619
          host.value().empty()) {
12620
        return false;
12621
      }
12622
    }
12623
12624
11.0k
    type = parsed_type;
12625
12626
    if constexpr (has_state_override) {
12627
      // This is uncommon.
12628
      uint16_t urls_scheme_port = get_special_port();
12629
12630
      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
        if (port.has_value() && *port == urls_scheme_port) {
12634
          port = std::nullopt;
12635
        }
12636
      }
12637
    }
12638
11.0k
  } else {  // slow path
12639
3.77k
    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
3.77k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
12645
12646
    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
      if (is_special() != ada::scheme::is_special(_buffer)) {
12651
        return true;
12652
      }
12653
12654
      // If url includes credentials or has a non-null port, and buffer is
12655
      // "file", then return.
12656
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
12657
        return true;
12658
      }
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
      if (type == ada::scheme::type::FILE && host.has_value() &&
12663
          host.value().empty()) {
12664
        return true;
12665
      }
12666
    }
12667
12668
3.77k
    set_scheme(std::move(_buffer));
12669
12670
    if constexpr (has_state_override) {
12671
      // This is uncommon.
12672
      uint16_t urls_scheme_port = get_special_port();
12673
12674
      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
        if (port.has_value() && *port == urls_scheme_port) {
12678
          port = std::nullopt;
12679
        }
12680
      }
12681
    }
12682
3.77k
  }
12683
12684
14.8k
  return true;
12685
14.8k
}
12686
12687
23.2k
ada_really_inline bool url::parse_host(std::string_view input) {
12688
23.2k
  ada_log("parse_host ", input, " [", input.size(), " bytes]");
12689
23.2k
  if (input.empty()) {
12690
10
    return is_valid = false;
12691
10
  }  // technically unnecessary.
12692
  // If input starts with U+005B ([), then:
12693
23.2k
  if (input[0] == '[') {
12694
    // If input does not end with U+005D (]), validation error, return failure.
12695
605
    if (input.back() != ']') {
12696
209
      return is_valid = false;
12697
209
    }
12698
396
    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
396
    input.remove_prefix(1);
12703
396
    input.remove_suffix(1);
12704
396
    return parse_ipv6(input);
12705
605
  }
12706
12707
  // If isNotSpecial is true, then return the result of opaque-host parsing
12708
  // input.
12709
22.6k
  if (!is_special()) {
12710
247
    return parse_opaque_host(input);
12711
247
  }
12712
12713
  // Fast path: try to parse as pure decimal IPv4(a.b.c.d) first.
12714
22.4k
  const uint64_t fast_result = checkers::try_parse_ipv4_fast(input);
12715
22.4k
  if (fast_result < checkers::ipv4_fast_fail) {
12716
    // Fast path succeeded - input is pure decimal IPv4
12717
48
    if (!input.empty() && input.back() == '.') {
12718
24
      host = input.substr(0, input.size() - 1);
12719
24
    } else {
12720
24
      host = input;
12721
24
    }
12722
48
    host_type = IPV4;
12723
48
    ada_log("parse_host fast path decimal ipv4");
12724
48
    return true;
12725
48
  }
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
22.3k
  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
22.3k
  unicode::to_lower_ascii(buffer.data(), buffer.size());
12736
22.3k
  bool is_forbidden = unicode::contains_forbidden_domain_code_point(
12737
22.3k
      buffer.data(), buffer.size());
12738
22.3k
  if (is_forbidden == 0 && buffer.find("xn-") == std::string_view::npos) {
12739
    // fast path
12740
15.3k
    host = std::move(buffer);
12741
12742
    // Check for other IPv4 formats (hex, octal, etc.)
12743
15.3k
    if (checkers::is_ipv4(host.value())) {
12744
1.92k
      ada_log("parse_host fast path ipv4");
12745
1.92k
      return parse_ipv4(host.value());
12746
1.92k
    }
12747
13.4k
    ada_log("parse_host fast path ", *host);
12748
13.4k
    return true;
12749
15.3k
  }
12750
7.02k
  ada_log("parse_host calling to_ascii");
12751
7.02k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
12752
7.02k
  if (!is_valid) {
12753
4.07k
    ada_log("parse_host to_ascii returns false");
12754
4.07k
    return is_valid = false;
12755
4.07k
  }
12756
2.95k
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
12757
2.95k
          " bytes]");
12758
12759
2.95k
  if (std::any_of(host.value().begin(), host.value().end(),
12760
2.95k
                  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
2.95k
  if (checkers::is_ipv4(host.value())) {
12768
238
    ada_log("parse_host got ipv4 ", *host);
12769
238
    return parse_ipv4(host.value());
12770
238
  }
12771
12772
2.71k
  return true;
12773
2.95k
}
12774
12775
8.27k
ada_really_inline void url::parse_path(std::string_view input) {
12776
8.27k
  ada_log("parse_path ", input);
12777
8.27k
  std::string tmp_buffer;
12778
8.27k
  std::string_view internal_input;
12779
8.27k
  if (unicode::has_tabs_or_newline(input)) {
12780
166
    tmp_buffer = input;
12781
    // Optimization opportunity: Instead of copying and then pruning, we could
12782
    // just directly build the string from user_input.
12783
166
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12784
166
    internal_input = tmp_buffer;
12785
8.11k
  } else {
12786
8.11k
    internal_input = input;
12787
8.11k
  }
12788
12789
  // If url is special, then:
12790
8.27k
  if (is_special()) {
12791
8.27k
    if (internal_input.empty()) {
12792
29
      path = "/";
12793
8.24k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
12794
693
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
12795
7.55k
    } else {
12796
7.55k
      helpers::parse_prepared_path(internal_input, type, path);
12797
7.55k
    }
12798
8.27k
  } 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
8.27k
}
12810
12811
8.27k
[[nodiscard]] std::string url::to_string() const {
12812
8.27k
  if (!is_valid) {
12813
2.21k
    return "null";
12814
2.21k
  }
12815
6.06k
  std::string answer;
12816
6.06k
  auto back = std::back_insert_iterator(answer);
12817
6.06k
  answer.append("{\n");
12818
6.06k
  answer.append("\t\"protocol\":\"");
12819
6.06k
  helpers::encode_json(get_protocol(), back);
12820
6.06k
  answer.append("\",\n");
12821
6.06k
  if (has_credentials()) {
12822
6.05k
    answer.append("\t\"username\":\"");
12823
6.05k
    helpers::encode_json(username, back);
12824
6.05k
    answer.append("\",\n");
12825
6.05k
    answer.append("\t\"password\":\"");
12826
6.05k
    helpers::encode_json(password, back);
12827
6.05k
    answer.append("\",\n");
12828
6.05k
  }
12829
6.06k
  if (host.has_value()) {
12830
6.06k
    answer.append("\t\"host\":\"");
12831
6.06k
    helpers::encode_json(host.value(), back);
12832
6.06k
    answer.append("\",\n");
12833
6.06k
  }
12834
6.06k
  if (port.has_value()) {
12835
967
    answer.append("\t\"port\":\"");
12836
967
    answer.append(std::to_string(port.value()));
12837
967
    answer.append("\",\n");
12838
967
  }
12839
6.06k
  answer.append("\t\"path\":\"");
12840
6.06k
  helpers::encode_json(path, back);
12841
6.06k
  answer.append("\",\n");
12842
6.06k
  answer.append("\t\"opaque path\":");
12843
6.06k
  answer.append((has_opaque_path ? "true" : "false"));
12844
6.06k
  if (has_search()) {
12845
6.05k
    answer.append(",\n");
12846
6.05k
    answer.append("\t\"query\":\"");
12847
    // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
12848
6.05k
    helpers::encode_json(query.value(), back);
12849
6.05k
    answer.append("\"");
12850
6.05k
  }
12851
6.06k
  if (hash.has_value()) {
12852
6.05k
    answer.append(",\n");
12853
6.05k
    answer.append("\t\"hash\":\"");
12854
6.05k
    helpers::encode_json(hash.value(), back);
12855
6.05k
    answer.append("\"");
12856
6.05k
  }
12857
6.06k
  answer.append("\n}");
12858
6.06k
  return answer;
12859
8.27k
}
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
11.2k
[[nodiscard]] std::string url::get_origin() const {
12869
11.2k
  if (is_special()) {
12870
    // Return a new opaque origin.
12871
9.97k
    if (type == scheme::FILE) {
12872
1.28k
      return "null";
12873
1.28k
    }
12874
8.69k
    return ada::helpers::concat(get_protocol(), "//", get_host());
12875
9.97k
  }
12876
12877
1.23k
  if (non_special_scheme == "blob") {
12878
428
    if (!path.empty()) {
12879
420
      auto result = ada::parse<ada::url>(path);
12880
420
      if (result &&
12881
214
          (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
15
        return ada::helpers::concat(result->get_protocol(), "//",
12885
15
                                    result->get_host());
12886
15
      }
12887
420
    }
12888
428
  }
12889
12890
  // Return a new opaque origin.
12891
1.22k
  return "null";
12892
1.23k
}
12893
12894
34.3k
[[nodiscard]] std::string url::get_protocol() const {
12895
34.3k
  if (is_special()) {
12896
29.4k
    return helpers::concat(ada::scheme::details::is_special_list[type], ":");
12897
29.4k
  }
12898
  // We only move the 'scheme' if it is non-special.
12899
4.94k
  return helpers::concat(non_special_scheme, ":");
12900
34.3k
}
12901
12902
16.9k
[[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
16.9k
  if (!host.has_value()) {
12908
0
    return "";
12909
0
  }
12910
16.9k
  if (port.has_value()) {
12911
1.99k
    return host.value() + ":" + get_port();
12912
1.99k
  }
12913
14.9k
  return host.value();
12914
16.9k
}
12915
12916
8.27k
[[nodiscard]] std::string url::get_hostname() const {
12917
8.27k
  return host.value_or("");
12918
8.27k
}
12919
12920
8.27k
[[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
8.27k
  return (!query.has_value() || (query.value().empty())) ? ""
12924
8.27k
                                                         : "?" + query.value();
12925
8.27k
}
12926
12927
8.27k
[[nodiscard]] const std::string& url::get_username() const noexcept {
12928
8.27k
  return username;
12929
8.27k
}
12930
12931
8.60k
[[nodiscard]] const std::string& url::get_password() const noexcept {
12932
8.60k
  return password;
12933
8.60k
}
12934
12935
10.4k
[[nodiscard]] std::string url::get_port() const {
12936
10.4k
  return port.has_value() ? std::to_string(port.value()) : "";
12937
10.4k
}
12938
12939
8.27k
[[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
8.27k
  return (!hash.has_value() || (hash.value().empty())) ? ""
12943
8.27k
                                                       : "#" + hash.value();
12944
8.27k
}
12945
12946
template <bool override_hostname>
12947
16.5k
bool url::set_host_or_hostname(const std::string_view input) {
12948
16.5k
  if (has_opaque_path) {
12949
0
    return false;
12950
0
  }
12951
12952
16.5k
  std::optional<std::string> previous_host = host;
12953
16.5k
  std::optional<uint16_t> previous_port = port;
12954
12955
16.5k
  size_t host_end_pos = input.find('#');
12956
16.5k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
12957
16.5k
                                      ? host_end_pos
12958
16.5k
                                      : input.size());
12959
16.5k
  helpers::remove_ascii_tab_or_newline(_host);
12960
16.5k
  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
16.5k
  if (type != ada::scheme::type::FILE) {
12965
15.1k
    std::string_view host_view(_host.data(), _host.length());
12966
15.1k
    auto [location, found_colon] =
12967
15.1k
        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
15.1k
    if (found_colon) {
12973
      // If buffer is the empty string, host-missing validation error, return
12974
      // failure.
12975
6.82k
      std::string_view buffer = host_view.substr(0, location);
12976
6.82k
      if (buffer.empty()) {
12977
24
        return false;
12978
24
      }
12979
12980
      // If state override is given and state override is hostname state, then
12981
      // return failure.
12982
6.80k
      if constexpr (override_hostname) {
12983
3.40k
        return false;
12984
3.40k
      }
12985
12986
      // Let host be the result of host parsing buffer with url is not special.
12987
0
      bool succeeded = parse_host(buffer);
12988
6.80k
      if (!succeeded) {
12989
363
        host = std::move(previous_host);
12990
363
        update_base_port(previous_port);
12991
363
        return false;
12992
363
      }
12993
12994
      // Set url's host to host, buffer to the empty string, and state to port
12995
      // state.
12996
6.43k
      std::string_view port_buffer = new_host.substr(location + 1);
12997
6.43k
      if (!port_buffer.empty()) {
12998
2.63k
        set_port(port_buffer);
12999
2.63k
      }
13000
6.43k
      return true;
13001
6.80k
    }
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
8.36k
    else {
13006
      // If url is special and host_view is the empty string, host-missing
13007
      // validation error, return failure.
13008
8.36k
      if (host_view.empty() && is_special()) {
13009
1.50k
        return false;
13010
1.50k
      }
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
6.85k
      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
6.85k
      if (host_view.empty() && !is_special()) {
13022
0
        host = "";
13023
0
        return true;
13024
0
      }
13025
13026
6.85k
      bool succeeded = parse_host(host_view);
13027
6.85k
      if (!succeeded) {
13028
3.07k
        host = std::move(previous_host);
13029
3.07k
        update_base_port(previous_port);
13030
3.07k
        return false;
13031
3.07k
      }
13032
3.78k
      return true;
13033
6.85k
    }
13034
15.1k
  }
13035
13036
1.36k
  size_t location = new_host.find_first_of("/\\?");
13037
1.36k
  if (location != std::string_view::npos) {
13038
1.24k
    new_host.remove_suffix(new_host.length() - location);
13039
1.24k
  }
13040
13041
1.36k
  if (new_host.empty()) {
13042
    // Set url's host to the empty string.
13043
0
    host = "";
13044
1.36k
  } else {
13045
    // Let host be the result of host parsing buffer with url is not special.
13046
1.36k
    if (!parse_host(new_host)) {
13047
1.36k
      host = std::move(previous_host);
13048
1.36k
      update_base_port(previous_port);
13049
1.36k
      return false;
13050
1.36k
    }
13051
13052
    // If host is "localhost", then set host to the empty string.
13053
4
    if (host == "localhost") {
13054
0
      host = "";
13055
0
    }
13056
4
  }
13057
4
  return true;
13058
1.36k
}
bool ada::url::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
12947
8.27k
bool url::set_host_or_hostname(const std::string_view input) {
12948
8.27k
  if (has_opaque_path) {
12949
0
    return false;
12950
0
  }
12951
12952
8.27k
  std::optional<std::string> previous_host = host;
12953
8.27k
  std::optional<uint16_t> previous_port = port;
12954
12955
8.27k
  size_t host_end_pos = input.find('#');
12956
8.27k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
12957
8.27k
                                      ? host_end_pos
12958
8.27k
                                      : input.size());
12959
8.27k
  helpers::remove_ascii_tab_or_newline(_host);
12960
8.27k
  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
8.27k
  if (type != ada::scheme::type::FILE) {
12965
7.59k
    std::string_view host_view(_host.data(), _host.length());
12966
7.59k
    auto [location, found_colon] =
12967
7.59k
        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
7.59k
    if (found_colon) {
12973
      // If buffer is the empty string, host-missing validation error, return
12974
      // failure.
12975
3.41k
      std::string_view buffer = host_view.substr(0, location);
12976
3.41k
      if (buffer.empty()) {
12977
12
        return false;
12978
12
      }
12979
12980
      // If state override is given and state override is hostname state, then
12981
      // return failure.
12982
      if constexpr (override_hostname) {
12983
        return false;
12984
      }
12985
12986
      // Let host be the result of host parsing buffer with url is not special.
12987
3.40k
      bool succeeded = parse_host(buffer);
12988
3.40k
      if (!succeeded) {
12989
363
        host = std::move(previous_host);
12990
363
        update_base_port(previous_port);
12991
363
        return false;
12992
363
      }
12993
12994
      // Set url's host to host, buffer to the empty string, and state to port
12995
      // state.
12996
3.03k
      std::string_view port_buffer = new_host.substr(location + 1);
12997
3.03k
      if (!port_buffer.empty()) {
12998
2.63k
        set_port(port_buffer);
12999
2.63k
      }
13000
3.03k
      return true;
13001
3.40k
    }
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
4.18k
    else {
13006
      // If url is special and host_view is the empty string, host-missing
13007
      // validation error, return failure.
13008
4.18k
      if (host_view.empty() && is_special()) {
13009
751
        return false;
13010
751
      }
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
3.42k
      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
3.42k
      if (host_view.empty() && !is_special()) {
13022
0
        host = "";
13023
0
        return true;
13024
0
      }
13025
13026
3.42k
      bool succeeded = parse_host(host_view);
13027
3.42k
      if (!succeeded) {
13028
1.53k
        host = std::move(previous_host);
13029
1.53k
        update_base_port(previous_port);
13030
1.53k
        return false;
13031
1.53k
      }
13032
1.89k
      return true;
13033
3.42k
    }
13034
7.59k
  }
13035
13036
683
  size_t location = new_host.find_first_of("/\\?");
13037
683
  if (location != std::string_view::npos) {
13038
622
    new_host.remove_suffix(new_host.length() - location);
13039
622
  }
13040
13041
683
  if (new_host.empty()) {
13042
    // Set url's host to the empty string.
13043
0
    host = "";
13044
683
  } else {
13045
    // Let host be the result of host parsing buffer with url is not special.
13046
683
    if (!parse_host(new_host)) {
13047
681
      host = std::move(previous_host);
13048
681
      update_base_port(previous_port);
13049
681
      return false;
13050
681
    }
13051
13052
    // If host is "localhost", then set host to the empty string.
13053
2
    if (host == "localhost") {
13054
0
      host = "";
13055
0
    }
13056
2
  }
13057
2
  return true;
13058
683
}
bool ada::url::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
12947
8.27k
bool url::set_host_or_hostname(const std::string_view input) {
12948
8.27k
  if (has_opaque_path) {
12949
0
    return false;
12950
0
  }
12951
12952
8.27k
  std::optional<std::string> previous_host = host;
12953
8.27k
  std::optional<uint16_t> previous_port = port;
12954
12955
8.27k
  size_t host_end_pos = input.find('#');
12956
8.27k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
12957
8.27k
                                      ? host_end_pos
12958
8.27k
                                      : input.size());
12959
8.27k
  helpers::remove_ascii_tab_or_newline(_host);
12960
8.27k
  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
8.27k
  if (type != ada::scheme::type::FILE) {
12965
7.59k
    std::string_view host_view(_host.data(), _host.length());
12966
7.59k
    auto [location, found_colon] =
12967
7.59k
        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
7.59k
    if (found_colon) {
12973
      // If buffer is the empty string, host-missing validation error, return
12974
      // failure.
12975
3.41k
      std::string_view buffer = host_view.substr(0, location);
12976
3.41k
      if (buffer.empty()) {
12977
12
        return false;
12978
12
      }
12979
12980
      // If state override is given and state override is hostname state, then
12981
      // return failure.
12982
3.40k
      if constexpr (override_hostname) {
12983
3.40k
        return false;
12984
3.40k
      }
12985
12986
      // Let host be the result of host parsing buffer with url is not special.
12987
0
      bool succeeded = parse_host(buffer);
12988
3.40k
      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
3.40k
      std::string_view port_buffer = new_host.substr(location + 1);
12997
3.40k
      if (!port_buffer.empty()) {
12998
0
        set_port(port_buffer);
12999
0
      }
13000
3.40k
      return true;
13001
3.40k
    }
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
4.18k
    else {
13006
      // If url is special and host_view is the empty string, host-missing
13007
      // validation error, return failure.
13008
4.18k
      if (host_view.empty() && is_special()) {
13009
751
        return false;
13010
751
      }
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
3.42k
      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
3.42k
      if (host_view.empty() && !is_special()) {
13022
0
        host = "";
13023
0
        return true;
13024
0
      }
13025
13026
3.42k
      bool succeeded = parse_host(host_view);
13027
3.42k
      if (!succeeded) {
13028
1.53k
        host = std::move(previous_host);
13029
1.53k
        update_base_port(previous_port);
13030
1.53k
        return false;
13031
1.53k
      }
13032
1.89k
      return true;
13033
3.42k
    }
13034
7.59k
  }
13035
13036
683
  size_t location = new_host.find_first_of("/\\?");
13037
683
  if (location != std::string_view::npos) {
13038
622
    new_host.remove_suffix(new_host.length() - location);
13039
622
  }
13040
13041
683
  if (new_host.empty()) {
13042
    // Set url's host to the empty string.
13043
0
    host = "";
13044
683
  } else {
13045
    // Let host be the result of host parsing buffer with url is not special.
13046
683
    if (!parse_host(new_host)) {
13047
681
      host = std::move(previous_host);
13048
681
      update_base_port(previous_port);
13049
681
      return false;
13050
681
    }
13051
13052
    // If host is "localhost", then set host to the empty string.
13053
2
    if (host == "localhost") {
13054
0
      host = "";
13055
0
    }
13056
2
  }
13057
2
  return true;
13058
683
}
13059
13060
8.27k
bool url::set_host(const std::string_view input) {
13061
8.27k
  return set_host_or_hostname<false>(input);
13062
8.27k
}
13063
13064
8.27k
bool url::set_hostname(const std::string_view input) {
13065
8.27k
  return set_host_or_hostname<true>(input);
13066
8.27k
}
13067
13068
8.27k
bool url::set_username(const std::string_view input) {
13069
8.27k
  if (cannot_have_credentials_or_port()) {
13070
683
    return false;
13071
683
  }
13072
7.59k
  username = ada::unicode::percent_encode(
13073
7.59k
      input, character_sets::USERINFO_PERCENT_ENCODE);
13074
7.59k
  return true;
13075
8.27k
}
13076
13077
8.27k
bool url::set_password(const std::string_view input) {
13078
8.27k
  if (cannot_have_credentials_or_port()) {
13079
683
    return false;
13080
683
  }
13081
7.59k
  password = ada::unicode::percent_encode(
13082
7.59k
      input, character_sets::USERINFO_PERCENT_ENCODE);
13083
7.59k
  return true;
13084
8.27k
}
13085
13086
10.9k
bool url::set_port(const std::string_view input) {
13087
10.9k
  if (cannot_have_credentials_or_port()) {
13088
683
    return false;
13089
683
  }
13090
13091
10.2k
  if (input.empty()) {
13092
2
    port = std::nullopt;
13093
2
    return true;
13094
2
  }
13095
13096
10.2k
  std::string trimmed(input);
13097
10.2k
  helpers::remove_ascii_tab_or_newline(trimmed);
13098
13099
10.2k
  if (trimmed.empty()) {
13100
27
    return true;
13101
27
  }
13102
13103
  // Input should not start with a non-digit character.
13104
10.1k
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
13105
8.62k
    return false;
13106
8.62k
  }
13107
13108
  // Find the first non-digit character to determine the length of digits
13109
1.56k
  auto first_non_digit =
13110
1.56k
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
13111
1.56k
  std::string_view digits_to_parse =
13112
1.56k
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
13113
13114
  // Revert changes if parse_port fails.
13115
1.56k
  std::optional<uint16_t> previous_port = port;
13116
1.56k
  parse_port(digits_to_parse);
13117
1.56k
  if (is_valid) {
13118
1.07k
    return true;
13119
1.07k
  }
13120
494
  port = std::move(previous_port);
13121
494
  is_valid = true;
13122
494
  return false;
13123
1.56k
}
13124
13125
8.27k
void url::set_hash(const std::string_view input) {
13126
8.27k
  if (input.empty()) {
13127
2
    hash = std::nullopt;
13128
2
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13129
2
    return;
13130
2
  }
13131
13132
8.27k
  std::string new_value;
13133
8.27k
  new_value = input[0] == '#' ? input.substr(1) : input;
13134
8.27k
  helpers::remove_ascii_tab_or_newline(new_value);
13135
8.27k
  hash = unicode::percent_encode(new_value,
13136
8.27k
                                 ada::character_sets::FRAGMENT_PERCENT_ENCODE);
13137
8.27k
}
13138
13139
8.27k
void url::set_search(const std::string_view input) {
13140
8.27k
  if (input.empty()) {
13141
2
    query = std::nullopt;
13142
2
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13143
2
    return;
13144
2
  }
13145
13146
8.27k
  std::string new_value;
13147
8.27k
  new_value = input[0] == '?' ? input.substr(1) : input;
13148
8.27k
  helpers::remove_ascii_tab_or_newline(new_value);
13149
13150
8.27k
  auto query_percent_encode_set =
13151
8.27k
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13152
8.27k
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
13153
13154
8.27k
  query = ada::unicode::percent_encode(new_value, query_percent_encode_set);
13155
8.27k
}
13156
13157
8.27k
bool url::set_pathname(const std::string_view input) {
13158
8.27k
  if (has_opaque_path) {
13159
0
    return false;
13160
0
  }
13161
8.27k
  path.clear();
13162
8.27k
  parse_path(input);
13163
8.27k
  return true;
13164
8.27k
}
13165
13166
8.27k
bool url::set_protocol(const std::string_view input) {
13167
8.27k
  std::string view(input);
13168
8.27k
  helpers::remove_ascii_tab_or_newline(view);
13169
8.27k
  if (view.empty()) {
13170
29
    return true;
13171
29
  }
13172
13173
  // Schemes should start with alpha values.
13174
8.24k
  if (!checkers::is_alpha(view[0])) {
13175
4.02k
    return false;
13176
4.02k
  }
13177
13178
4.22k
  view.append(":");
13179
13180
4.22k
  std::string::iterator pointer =
13181
4.22k
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
13182
13183
4.22k
  if (pointer != view.end() && *pointer == ':') {
13184
3.69k
    return parse_scheme<true>(
13185
3.69k
        std::string_view(view.data(), pointer - view.begin()));
13186
3.69k
  }
13187
521
  return false;
13188
4.22k
}
13189
13190
2.80k
bool url::set_href(const std::string_view input) {
13191
2.80k
  ada::result<ada::url> out = ada::parse<ada::url>(input);
13192
13193
2.80k
  if (out) {
13194
2.80k
    *this = *out;
13195
2.80k
  }
13196
13197
2.80k
  return out.has_value();
13198
2.80k
}
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
39.5k
                           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
39.5k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13219
39.5k
  constexpr bool result_type_is_ada_url_aggregator =
13220
39.5k
      std::is_same_v<url_aggregator, result_type>;
13221
39.5k
  static_assert(result_type_is_ada_url ||
13222
39.5k
                result_type_is_ada_url_aggregator);  // We don't support
13223
                                                     // anything else for now.
13224
13225
39.5k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13226
39.5k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13227
39.5k
          ")");
13228
13229
39.5k
  state state = state::SCHEME_START;
13230
39.5k
  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
39.5k
  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
39.5k
  if (base_url != nullptr) {
13241
0
    url.is_valid &= base_url->is_valid;
13242
0
  }
13243
39.5k
  if (!url.is_valid) {
13244
0
    return url;
13245
0
  }
13246
39.5k
  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
19.7k
    uint32_t reserve_capacity =
13259
19.7k
        (0xFFFFFFFF >>
13260
19.7k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13261
19.7k
        1;
13262
19.7k
    url.reserve(reserve_capacity);
13263
19.7k
  }
13264
39.5k
  std::string tmp_buffer;
13265
39.5k
  std::string_view url_data;
13266
39.5k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13267
424
    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
424
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13271
424
    url_data = tmp_buffer;
13272
39.1k
  } else [[likely]] {
13273
39.1k
    url_data = user_input;
13274
39.1k
  }
13275
13276
  // Leading and trailing control characters are uncommon and easy to deal with
13277
  // (no performance concern).
13278
39.5k
  helpers::trim_c0_whitespace(url_data);
13279
13280
  // Optimization opportunity. Most websites do not have fragment.
13281
39.5k
  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
39.5k
  size_t input_position = 0;
13291
39.5k
  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
193k
  while (input_position <= input_size) {
13297
185k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13298
185k
            " in state ", ada::to_string(state));
13299
185k
    switch (state) {
13300
39.5k
      case state::SCHEME_START: {
13301
39.5k
        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
39.5k
        if ((input_position != input_size) &&
13305
39.4k
            checkers::is_alpha(url_data[input_position])) {
13306
31.5k
          state = state::SCHEME;
13307
31.5k
          input_position++;
13308
31.5k
        } else {
13309
          // Otherwise, if state override is not given, set state to no scheme
13310
          // state and decrease pointer by 1.
13311
8.04k
          state = state::NO_SCHEME;
13312
8.04k
        }
13313
39.5k
        break;
13314
0
      }
13315
31.5k
      case state::SCHEME: {
13316
31.5k
        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
167k
        while ((input_position != input_size) &&
13320
166k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13321
135k
          input_position++;
13322
135k
        }
13323
        // Otherwise, if c is U+003A (:), then:
13324
31.5k
        if ((input_position != input_size) &&
13325
30.7k
            (url_data[input_position] == ':')) {
13326
29.7k
          ada_log("SCHEME the scheme should be ",
13327
29.7k
                  url_data.substr(0, input_position));
13328
29.7k
          if constexpr (result_type_is_ada_url) {
13329
14.8k
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13330
0
              return url;
13331
0
            }
13332
14.8k
          } else {
13333
            // we pass the colon along instead of painfully adding it back.
13334
14.8k
            if (!url.parse_scheme_with_colon(
13335
14.8k
                    url_data.substr(0, input_position + 1))) {
13336
0
              return url;
13337
0
            }
13338
14.8k
          }
13339
29.7k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13340
13341
          // If url's scheme is "file", then:
13342
29.7k
          if (url.type == scheme::type::FILE) {
13343
            // Set state to file state.
13344
2.72k
            state = state::FILE;
13345
2.72k
          }
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
27.0k
          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
27.0k
          else if (url.is_special()) {
13357
21.6k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13358
21.6k
          }
13359
          // Otherwise, if remaining starts with an U+002F (/), set state to
13360
          // path or authority state and increase pointer by 1.
13361
5.34k
          else if (input_position + 1 < input_size &&
13362
4.66k
                   url_data[input_position + 1] == '/') {
13363
2.29k
            state = state::PATH_OR_AUTHORITY;
13364
2.29k
            input_position++;
13365
2.29k
          }
13366
          // Otherwise, set url's path to the empty string and set state to
13367
          // opaque path state.
13368
3.05k
          else {
13369
3.05k
            state = state::OPAQUE_PATH;
13370
3.05k
          }
13371
29.7k
        }
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
1.78k
        else {
13376
1.78k
          state = state::NO_SCHEME;
13377
1.78k
          input_position = 0;
13378
1.78k
          break;
13379
1.78k
        }
13380
29.7k
        input_position++;
13381
29.7k
        break;
13382
31.5k
      }
13383
9.82k
      case state::NO_SCHEME: {
13384
9.82k
        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
9.82k
        if (base_url == nullptr ||
13388
9.82k
            (base_url->has_opaque_path && !fragment.has_value())) {
13389
9.82k
          ada_log("NO_SCHEME validation error");
13390
9.82k
          url.is_valid = false;
13391
9.82k
          return url;
13392
9.82k
        }
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
9.82k
      }
13425
22.3k
      case state::AUTHORITY: {
13426
22.3k
        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
22.3k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13438
21.0k
          state = state::HOST;
13439
21.0k
          break;
13440
21.0k
        }
13441
1.30k
        bool at_sign_seen{false};
13442
1.30k
        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
14.8k
        do {
13449
14.8k
          std::string_view view = url_data.substr(input_position);
13450
          // The delimiters are @, /, ? \\.
13451
14.8k
          size_t location =
13452
14.8k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13453
14.8k
                               : helpers::find_authority_delimiter(view);
13454
14.8k
          std::string_view authority_view = view.substr(0, location);
13455
14.8k
          size_t end_of_authority = input_position + authority_view.size();
13456
          // If c is U+0040 (@), then:
13457
14.8k
          if ((end_of_authority != input_size) &&
13458
13.6k
              (url_data[end_of_authority] == '@')) {
13459
            // If atSignSeen is true, then prepend "%40" to buffer.
13460
13.5k
            if (at_sign_seen) {
13461
12.2k
              if (password_token_seen) {
13462
5.42k
                if constexpr (result_type_is_ada_url) {
13463
2.71k
                  url.password += "%40";
13464
2.71k
                } else {
13465
2.71k
                  url.append_base_password("%40");
13466
2.71k
                }
13467
6.85k
              } else {
13468
6.85k
                if constexpr (result_type_is_ada_url) {
13469
3.42k
                  url.username += "%40";
13470
3.42k
                } else {
13471
3.42k
                  url.append_base_username("%40");
13472
3.42k
                }
13473
6.85k
              }
13474
12.2k
            }
13475
13476
13.5k
            at_sign_seen = true;
13477
13478
13.5k
            if (!password_token_seen) {
13479
8.07k
              size_t password_token_location = authority_view.find(':');
13480
8.07k
              password_token_seen =
13481
8.07k
                  password_token_location != std::string_view::npos;
13482
13483
8.07k
              if constexpr (store_values) {
13484
8.07k
                if (!password_token_seen) {
13485
7.50k
                  if constexpr (result_type_is_ada_url) {
13486
3.75k
                    url.username += unicode::percent_encode(
13487
3.75k
                        authority_view,
13488
3.75k
                        character_sets::USERINFO_PERCENT_ENCODE);
13489
3.75k
                  } else {
13490
3.75k
                    url.append_base_username(unicode::percent_encode(
13491
3.75k
                        authority_view,
13492
3.75k
                        character_sets::USERINFO_PERCENT_ENCODE));
13493
3.75k
                  }
13494
7.50k
                } else {
13495
568
                  if constexpr (result_type_is_ada_url) {
13496
284
                    url.username += unicode::percent_encode(
13497
284
                        authority_view.substr(0, password_token_location),
13498
284
                        character_sets::USERINFO_PERCENT_ENCODE);
13499
284
                    url.password += unicode::percent_encode(
13500
284
                        authority_view.substr(password_token_location + 1),
13501
284
                        character_sets::USERINFO_PERCENT_ENCODE);
13502
284
                  } else {
13503
284
                    url.append_base_username(unicode::percent_encode(
13504
284
                        authority_view.substr(0, password_token_location),
13505
284
                        character_sets::USERINFO_PERCENT_ENCODE));
13506
284
                    url.append_base_password(unicode::percent_encode(
13507
284
                        authority_view.substr(password_token_location + 1),
13508
284
                        character_sets::USERINFO_PERCENT_ENCODE));
13509
284
                  }
13510
568
                }
13511
8.07k
              }
13512
8.07k
            } else if constexpr (store_values) {
13513
5.42k
              if constexpr (result_type_is_ada_url) {
13514
2.71k
                url.password += unicode::percent_encode(
13515
2.71k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13516
2.71k
              } else {
13517
2.71k
                url.append_base_password(unicode::percent_encode(
13518
2.71k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13519
2.71k
              }
13520
5.42k
            }
13521
13.5k
          }
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.30k
          else if (end_of_authority == input_size ||
13526
180
                   url_data[end_of_authority] == '/' ||
13527
40
                   url_data[end_of_authority] == '?' ||
13528
1.30k
                   (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.30k
            if (at_sign_seen && authority_view.empty()) {
13532
146
              url.is_valid = false;
13533
146
              return url;
13534
146
            }
13535
1.16k
            state = state::HOST;
13536
1.16k
            break;
13537
1.30k
          }
13538
13.5k
          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
13.5k
          input_position = end_of_authority + 1;
13547
13.5k
        } while (true);
13548
13549
1.16k
        break;
13550
1.30k
      }
13551
1.16k
      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.30k
      }
13569
2.29k
      case state::PATH_OR_AUTHORITY: {
13570
2.29k
        ada_log("PATH_OR_AUTHORITY ",
13571
2.29k
                helpers::substring(url_data, input_position));
13572
13573
        // If c is U+002F (/), then set state to authority state.
13574
2.29k
        if ((input_position != input_size) &&
13575
2.27k
            (url_data[input_position] == '/')) {
13576
724
          state = state::AUTHORITY;
13577
724
          input_position++;
13578
1.56k
        } else {
13579
          // Otherwise, set state to path state, and decrease pointer by 1.
13580
1.56k
          state = state::PATH;
13581
1.56k
        }
13582
13583
2.29k
        break;
13584
1.30k
      }
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
21.6k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13705
21.6k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13706
21.6k
                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
21.6k
        if (url_data.substr(input_position, 2) == "//") {
13712
16.5k
          input_position += 2;
13713
16.5k
        }
13714
13715
21.6k
        [[fallthrough]];
13716
21.6k
      }
13717
21.6k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13718
21.6k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13719
21.6k
                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
22.8k
        while ((input_position != input_size) &&
13724
22.8k
               ((url_data[input_position] == '/') ||
13725
22.0k
                (url_data[input_position] == '\\'))) {
13726
1.17k
          input_position++;
13727
1.17k
        }
13728
21.6k
        state = state::AUTHORITY;
13729
13730
21.6k
        break;
13731
21.6k
      }
13732
643
      case state::QUERY: {
13733
643
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13734
643
        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
643
          const uint8_t* query_percent_encode_set =
13738
643
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13739
643
                               : 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
643
          url.update_base_search(url_data.substr(input_position),
13744
643
                                 query_percent_encode_set);
13745
643
          ada_log("QUERY update_base_search completed ");
13746
643
          if (fragment.has_value()) {
13747
41
            url.update_unencoded_base_hash(*fragment);
13748
41
          }
13749
643
        }
13750
643
        return url;
13751
21.6k
      }
13752
22.2k
      case state::HOST: {
13753
22.2k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13754
13755
22.2k
        std::string_view host_view = url_data.substr(input_position);
13756
22.2k
        auto [location, found_colon] =
13757
22.2k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13758
22.2k
        input_position = (location != std::string_view::npos)
13759
22.2k
                             ? input_position + location
13760
22.2k
                             : 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
22.2k
        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.37k
          ada_log("HOST parsing ", host_view);
13769
1.37k
          if (!url.parse_host(host_view)) {
13770
185
            return url;
13771
185
          }
13772
1.18k
          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.18k
          state = state::PORT;
13776
1.18k
          input_position++;
13777
1.18k
        }
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
20.8k
        else {
13784
          // If url is special and host_view is the empty string, validation
13785
          // error, return failure.
13786
20.8k
          if (host_view.empty() && url.is_special()) {
13787
16
            url.is_valid = false;
13788
16
            return url;
13789
16
          }
13790
20.8k
          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
20.8k
          if (host_view.empty()) {
13794
88
            url.update_base_hostname("");
13795
20.7k
          } else if (!url.parse_host(host_view)) {
13796
610
            return url;
13797
610
          }
13798
20.2k
          ada_log("HOST parsing results in ", url.get_hostname(),
13799
20.2k
                  " href=", url.get_href());
13800
13801
          // Set url's host to host, and state to path start state.
13802
20.2k
          state = state::PATH_START;
13803
20.2k
        }
13804
13805
21.4k
        break;
13806
22.2k
      }
13807
21.4k
      case state::OPAQUE_PATH: {
13808
3.05k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13809
3.05k
        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.05k
        size_t location = view.find('?');
13813
3.05k
        if (location != std::string_view::npos) {
13814
332
          view.remove_suffix(view.size() - location);
13815
332
          state = state::QUERY;
13816
332
          input_position += location + 1;
13817
2.71k
        } else {
13818
2.71k
          input_position = input_size + 1;
13819
2.71k
        }
13820
3.05k
        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.05k
        if (view.ends_with(' ')) {
13825
116
          std::string modified_view =
13826
116
              std::string(view.substr(0, view.size() - 1)) + "%20";
13827
116
          url.update_base_pathname(unicode::percent_encode(
13828
116
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13829
2.93k
        } else {
13830
2.93k
          url.update_base_pathname(unicode::percent_encode(
13831
2.93k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13832
2.93k
        }
13833
3.05k
        break;
13834
22.2k
      }
13835
1.18k
      case state::PORT: {
13836
1.18k
        ada_log("PORT ", helpers::substring(url_data, input_position));
13837
1.18k
        std::string_view port_view = url_data.substr(input_position);
13838
1.18k
        input_position += url.parse_port(port_view, true);
13839
1.18k
        if (!url.is_valid) {
13840
211
          return url;
13841
211
        }
13842
974
        state = state::PATH_START;
13843
974
        [[fallthrough]];
13844
974
      }
13845
22.1k
      case state::PATH_START: {
13846
22.1k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13847
13848
        // If url is special, then:
13849
22.1k
        if (url.is_special()) {
13850
          // Set state to path state.
13851
21.6k
          state = state::PATH;
13852
13853
          // Optimization: Avoiding going into PATH state improves the
13854
          // performance of urls ending with /.
13855
21.6k
          if (input_position == input_size) {
13856
20.0k
            if constexpr (store_values) {
13857
20.0k
              url.update_base_pathname("/");
13858
20.0k
              if (fragment.has_value()) {
13859
125
                url.update_unencoded_base_hash(*fragment);
13860
125
              }
13861
20.0k
            }
13862
20.0k
            return url;
13863
20.0k
          }
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.58k
          if ((url_data[input_position] != '/') &&
13868
201
              (url_data[input_position] != '\\')) {
13869
173
            break;
13870
173
          }
13871
1.58k
        }
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
508
        else if ((input_position != input_size) &&
13875
136
                 (url_data[input_position] == '?')) {
13876
12
          state = state::QUERY;
13877
12
        }
13878
        // Otherwise, if c is not the EOF code point:
13879
496
        else if (input_position != input_size) {
13880
          // Set state to path state.
13881
124
          state = state::PATH;
13882
13883
          // If c is not U+002F (/), then decrease pointer by 1.
13884
124
          if (url_data[input_position] != '/') {
13885
0
            break;
13886
0
          }
13887
124
        }
13888
13889
1.91k
        input_position++;
13890
1.91k
        break;
13891
22.1k
      }
13892
4.79k
      case state::PATH: {
13893
4.79k
        ada_log("PATH ", helpers::substring(url_data, input_position));
13894
4.79k
        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.79k
        size_t locofquestionmark = view.find('?');
13899
4.79k
        if (locofquestionmark != std::string_view::npos) {
13900
299
          state = state::QUERY;
13901
299
          view.remove_suffix(view.size() - locofquestionmark);
13902
299
          input_position += locofquestionmark + 1;
13903
4.49k
        } else {
13904
4.49k
          input_position = input_size + 1;
13905
4.49k
        }
13906
4.79k
        if constexpr (store_values) {
13907
4.79k
          if constexpr (result_type_is_ada_url) {
13908
2.45k
            helpers::parse_prepared_path(view, url.type, url.path);
13909
2.45k
          } else {
13910
2.34k
            url.consume_prepared_path(view);
13911
2.34k
            ADA_ASSERT_TRUE(url.validate());
13912
2.34k
          }
13913
4.79k
        }
13914
4.79k
        break;
13915
22.1k
      }
13916
1.61k
      case state::FILE_SLASH: {
13917
1.61k
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13918
13919
        // If c is U+002F (/) or U+005C (\), then:
13920
1.61k
        if ((input_position != input_size) &&
13921
1.60k
            (url_data[input_position] == '/' ||
13922
1.20k
             url_data[input_position] == '\\')) {
13923
1.20k
          ada_log("FILE_SLASH c is U+002F or U+005C");
13924
          // Set state to file host state.
13925
1.20k
          state = state::FILE_HOST;
13926
1.20k
          input_position++;
13927
1.20k
        } else {
13928
406
          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
406
          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
406
          state = state::PATH;
13968
406
        }
13969
13970
1.61k
        break;
13971
22.1k
      }
13972
1.20k
      case state::FILE_HOST: {
13973
1.20k
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13974
1.20k
        std::string_view view = url_data.substr(input_position);
13975
13976
1.20k
        size_t location = view.find_first_of("/\\?");
13977
1.20k
        std::string_view file_host_buffer(
13978
1.20k
            view.data(),
13979
1.20k
            (location != std::string_view::npos) ? location : view.size());
13980
13981
1.20k
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13982
10
          state = state::PATH;
13983
1.19k
        } else if (file_host_buffer.empty()) {
13984
          // Set url's host to the empty string.
13985
56
          if constexpr (result_type_is_ada_url) {
13986
28
            url.host = "";
13987
28
          } else {
13988
28
            url.update_base_hostname("");
13989
28
          }
13990
          // Set state to path start state.
13991
56
          state = state::PATH_START;
13992
1.14k
        } else {
13993
1.14k
          size_t consumed_bytes = file_host_buffer.size();
13994
1.14k
          input_position += consumed_bytes;
13995
          // Let host be the result of host parsing buffer with url is not
13996
          // special.
13997
1.14k
          if (!url.parse_host(file_host_buffer)) {
13998
237
            return url;
13999
237
          }
14000
14001
903
          if constexpr (result_type_is_ada_url) {
14002
            // If host is "localhost", then set host to the empty string.
14003
461
            if (url.host.has_value() && url.host.value() == "localhost") {
14004
3
              url.host = "";
14005
3
            }
14006
461
          } else {
14007
442
            if (url.get_hostname() == "localhost") {
14008
3
              url.update_base_hostname("");
14009
3
            }
14010
442
          }
14011
14012
          // Set buffer to the empty string and state to path start state.
14013
903
          state = state::PATH_START;
14014
903
        }
14015
14016
969
        break;
14017
1.20k
      }
14018
2.72k
      case state::FILE: {
14019
2.72k
        ada_log("FILE ", helpers::substring(url_data, input_position));
14020
2.72k
        std::string_view file_view = url_data.substr(input_position);
14021
14022
2.72k
        url.set_protocol_as_file();
14023
2.72k
        if constexpr (result_type_is_ada_url) {
14024
          // Set url's host to the empty string.
14025
1.36k
          url.host = "";
14026
1.36k
        } else {
14027
1.36k
          url.update_base_hostname("");
14028
1.36k
        }
14029
        // If c is U+002F (/) or U+005C (\), then:
14030
2.72k
        if (input_position != input_size &&
14031
2.68k
            (url_data[input_position] == '/' ||
14032
1.61k
             url_data[input_position] == '\\')) {
14033
1.61k
          ada_log("FILE c is U+002F or U+005C");
14034
          // Set state to file slash state.
14035
1.61k
          state = state::FILE_SLASH;
14036
1.61k
        }
14037
        // Otherwise, if base is non-null and base's scheme is "file":
14038
1.11k
        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.11k
        else {
14088
1.11k
          ada_log("FILE go to path");
14089
1.11k
          state = state::PATH;
14090
1.11k
          break;
14091
1.11k
        }
14092
14093
1.61k
        input_position++;
14094
1.61k
        break;
14095
2.72k
      }
14096
0
      default:
14097
0
        unreachable();
14098
185k
    }
14099
185k
  }
14100
7.58k
  if constexpr (store_values) {
14101
7.58k
    if (fragment.has_value()) {
14102
252
      url.update_unencoded_base_hash(*fragment);
14103
252
    }
14104
7.58k
  }
14105
7.58k
  return url;
14106
39.5k
}
ada::url ada::parser::parse_url_impl<ada::url, true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url const*)
Line
Count
Source
13212
19.7k
                           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
19.7k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13219
19.7k
  constexpr bool result_type_is_ada_url_aggregator =
13220
19.7k
      std::is_same_v<url_aggregator, result_type>;
13221
19.7k
  static_assert(result_type_is_ada_url ||
13222
19.7k
                result_type_is_ada_url_aggregator);  // We don't support
13223
                                                     // anything else for now.
13224
13225
19.7k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13226
19.7k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13227
19.7k
          ")");
13228
13229
19.7k
  state state = state::SCHEME_START;
13230
19.7k
  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
19.7k
  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
19.7k
  if (base_url != nullptr) {
13241
0
    url.is_valid &= base_url->is_valid;
13242
0
  }
13243
19.7k
  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
19.7k
  std::string tmp_buffer;
13265
19.7k
  std::string_view url_data;
13266
19.7k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13267
212
    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
212
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13271
212
    url_data = tmp_buffer;
13272
19.5k
  } else [[likely]] {
13273
19.5k
    url_data = user_input;
13274
19.5k
  }
13275
13276
  // Leading and trailing control characters are uncommon and easy to deal with
13277
  // (no performance concern).
13278
19.7k
  helpers::trim_c0_whitespace(url_data);
13279
13280
  // Optimization opportunity. Most websites do not have fragment.
13281
19.7k
  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
19.7k
  size_t input_position = 0;
13291
19.7k
  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
96.9k
  while (input_position <= input_size) {
13297
93.0k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13298
93.0k
            " in state ", ada::to_string(state));
13299
93.0k
    switch (state) {
13300
19.7k
      case state::SCHEME_START: {
13301
19.7k
        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
19.7k
        if ((input_position != input_size) &&
13305
19.7k
            checkers::is_alpha(url_data[input_position])) {
13306
15.7k
          state = state::SCHEME;
13307
15.7k
          input_position++;
13308
15.7k
        } else {
13309
          // Otherwise, if state override is not given, set state to no scheme
13310
          // state and decrease pointer by 1.
13311
4.02k
          state = state::NO_SCHEME;
13312
4.02k
        }
13313
19.7k
        break;
13314
0
      }
13315
15.7k
      case state::SCHEME: {
13316
15.7k
        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
83.5k
        while ((input_position != input_size) &&
13320
83.1k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13321
67.7k
          input_position++;
13322
67.7k
        }
13323
        // Otherwise, if c is U+003A (:), then:
13324
15.7k
        if ((input_position != input_size) &&
13325
15.3k
            (url_data[input_position] == ':')) {
13326
14.8k
          ada_log("SCHEME the scheme should be ",
13327
14.8k
                  url_data.substr(0, input_position));
13328
14.8k
          if constexpr (result_type_is_ada_url) {
13329
14.8k
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13330
0
              return url;
13331
0
            }
13332
          } else {
13333
            // we pass the colon along instead of painfully adding it back.
13334
            if (!url.parse_scheme_with_colon(
13335
                    url_data.substr(0, input_position + 1))) {
13336
              return url;
13337
            }
13338
          }
13339
14.8k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13340
13341
          // If url's scheme is "file", then:
13342
14.8k
          if (url.type == scheme::type::FILE) {
13343
            // Set state to file state.
13344
1.36k
            state = state::FILE;
13345
1.36k
          }
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
10.8k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13358
10.8k
          }
13359
          // Otherwise, if remaining starts with an U+002F (/), set state to
13360
          // path or authority state and increase pointer by 1.
13361
2.67k
          else if (input_position + 1 < input_size &&
13362
2.33k
                   url_data[input_position + 1] == '/') {
13363
1.14k
            state = state::PATH_OR_AUTHORITY;
13364
1.14k
            input_position++;
13365
1.14k
          }
13366
          // Otherwise, set url's path to the empty string and set state to
13367
          // opaque path state.
13368
1.52k
          else {
13369
1.52k
            state = state::OPAQUE_PATH;
13370
1.52k
          }
13371
14.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
891
        else {
13376
891
          state = state::NO_SCHEME;
13377
891
          input_position = 0;
13378
891
          break;
13379
891
        }
13380
14.8k
        input_position++;
13381
14.8k
        break;
13382
15.7k
      }
13383
4.91k
      case state::NO_SCHEME: {
13384
4.91k
        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
4.91k
        if (base_url == nullptr ||
13388
4.91k
            (base_url->has_opaque_path && !fragment.has_value())) {
13389
4.91k
          ada_log("NO_SCHEME validation error");
13390
4.91k
          url.is_valid = false;
13391
4.91k
          return url;
13392
4.91k
        }
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
          } else {
13406
            url.update_base_pathname(base_url->get_pathname());
13407
            url.update_base_search(base_url->get_search());
13408
          }
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
4.91k
      }
13425
11.1k
      case state::AUTHORITY: {
13426
11.1k
        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
11.1k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13438
10.5k
          state = state::HOST;
13439
10.5k
          break;
13440
10.5k
        }
13441
654
        bool at_sign_seen{false};
13442
654
        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.40k
        do {
13449
7.40k
          std::string_view view = url_data.substr(input_position);
13450
          // The delimiters are @, /, ? \\.
13451
7.40k
          size_t location =
13452
7.40k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13453
7.40k
                               : helpers::find_authority_delimiter(view);
13454
7.40k
          std::string_view authority_view = view.substr(0, location);
13455
7.40k
          size_t end_of_authority = input_position + authority_view.size();
13456
          // If c is U+0040 (@), then:
13457
7.40k
          if ((end_of_authority != input_size) &&
13458
6.84k
              (url_data[end_of_authority] == '@')) {
13459
            // If atSignSeen is true, then prepend "%40" to buffer.
13460
6.75k
            if (at_sign_seen) {
13461
6.14k
              if (password_token_seen) {
13462
2.71k
                if constexpr (result_type_is_ada_url) {
13463
2.71k
                  url.password += "%40";
13464
                } else {
13465
                  url.append_base_password("%40");
13466
                }
13467
3.42k
              } else {
13468
3.42k
                if constexpr (result_type_is_ada_url) {
13469
3.42k
                  url.username += "%40";
13470
                } else {
13471
                  url.append_base_username("%40");
13472
                }
13473
3.42k
              }
13474
6.14k
            }
13475
13476
6.75k
            at_sign_seen = true;
13477
13478
6.75k
            if (!password_token_seen) {
13479
4.03k
              size_t password_token_location = authority_view.find(':');
13480
4.03k
              password_token_seen =
13481
4.03k
                  password_token_location != std::string_view::npos;
13482
13483
4.03k
              if constexpr (store_values) {
13484
4.03k
                if (!password_token_seen) {
13485
3.75k
                  if constexpr (result_type_is_ada_url) {
13486
3.75k
                    url.username += unicode::percent_encode(
13487
3.75k
                        authority_view,
13488
3.75k
                        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
3.75k
                } else {
13495
284
                  if constexpr (result_type_is_ada_url) {
13496
284
                    url.username += unicode::percent_encode(
13497
284
                        authority_view.substr(0, password_token_location),
13498
284
                        character_sets::USERINFO_PERCENT_ENCODE);
13499
284
                    url.password += unicode::percent_encode(
13500
284
                        authority_view.substr(password_token_location + 1),
13501
284
                        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
284
                }
13511
4.03k
              }
13512
4.03k
            } else if constexpr (store_values) {
13513
2.71k
              if constexpr (result_type_is_ada_url) {
13514
2.71k
                url.password += unicode::percent_encode(
13515
2.71k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13516
              } else {
13517
                url.append_base_password(unicode::percent_encode(
13518
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13519
              }
13520
2.71k
            }
13521
6.75k
          }
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
654
          else if (end_of_authority == input_size ||
13526
90
                   url_data[end_of_authority] == '/' ||
13527
20
                   url_data[end_of_authority] == '?' ||
13528
654
                   (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
654
            if (at_sign_seen && authority_view.empty()) {
13532
73
              url.is_valid = false;
13533
73
              return url;
13534
73
            }
13535
581
            state = state::HOST;
13536
581
            break;
13537
654
          }
13538
6.75k
          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
6.75k
          input_position = end_of_authority + 1;
13547
6.75k
        } while (true);
13548
13549
581
        break;
13550
654
      }
13551
581
      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
654
      }
13569
1.14k
      case state::PATH_OR_AUTHORITY: {
13570
1.14k
        ada_log("PATH_OR_AUTHORITY ",
13571
1.14k
                helpers::substring(url_data, input_position));
13572
13573
        // If c is U+002F (/), then set state to authority state.
13574
1.14k
        if ((input_position != input_size) &&
13575
1.13k
            (url_data[input_position] == '/')) {
13576
362
          state = state::AUTHORITY;
13577
362
          input_position++;
13578
784
        } else {
13579
          // Otherwise, set state to path state, and decrease pointer by 1.
13580
784
          state = state::PATH;
13581
784
        }
13582
13583
1.14k
        break;
13584
654
      }
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
          } else {
13624
            url.update_base_authority(base_url->get_href(),
13625
                                      base_url->get_components());
13626
            url.update_host_to_base_host(base_url->get_hostname());
13627
            url.update_base_port(base_url->retrieve_base_port());
13628
            // cloning the base path includes cloning the has_opaque_path flag
13629
            url.has_opaque_path = base_url->has_opaque_path;
13630
            url.update_base_pathname(base_url->get_pathname());
13631
            url.update_base_search(base_url->get_search());
13632
          }
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
            } else {
13650
              std::string_view path = url.get_pathname();
13651
              if (helpers::shorten_path(path, url.type)) {
13652
                url.update_base_pathname(std::move(std::string(path)));
13653
              }
13654
            }
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
          } else {
13692
            url.update_base_authority(base_url->get_href(),
13693
                                      base_url->get_components());
13694
            url.update_host_to_base_host(base_url->get_hostname());
13695
            url.update_base_port(base_url->retrieve_base_port());
13696
          }
13697
0
          state = state::PATH;
13698
0
          break;
13699
0
        }
13700
13701
0
        input_position++;
13702
0
        break;
13703
0
      }
13704
10.8k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13705
10.8k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13706
10.8k
                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
10.8k
        if (url_data.substr(input_position, 2) == "//") {
13712
8.29k
          input_position += 2;
13713
8.29k
        }
13714
13715
10.8k
        [[fallthrough]];
13716
10.8k
      }
13717
10.8k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13718
10.8k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13719
10.8k
                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
11.4k
        while ((input_position != input_size) &&
13724
11.4k
               ((url_data[input_position] == '/') ||
13725
11.0k
                (url_data[input_position] == '\\'))) {
13726
585
          input_position++;
13727
585
        }
13728
10.8k
        state = state::AUTHORITY;
13729
13730
10.8k
        break;
13731
10.8k
      }
13732
325
      case state::QUERY: {
13733
325
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13734
325
        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
325
          const uint8_t* query_percent_encode_set =
13738
325
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13739
325
                               : 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
325
          url.update_base_search(url_data.substr(input_position),
13744
325
                                 query_percent_encode_set);
13745
325
          ada_log("QUERY update_base_search completed ");
13746
325
          if (fragment.has_value()) {
13747
21
            url.update_unencoded_base_hash(*fragment);
13748
21
          }
13749
325
        }
13750
325
        return url;
13751
10.8k
      }
13752
11.1k
      case state::HOST: {
13753
11.1k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13754
13755
11.1k
        std::string_view host_view = url_data.substr(input_position);
13756
11.1k
        auto [location, found_colon] =
13757
11.1k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13758
11.1k
        input_position = (location != std::string_view::npos)
13759
11.1k
                             ? input_position + location
13760
11.1k
                             : 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
11.1k
        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
685
          ada_log("HOST parsing ", host_view);
13769
685
          if (!url.parse_host(host_view)) {
13770
84
            return url;
13771
84
          }
13772
601
          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
601
          state = state::PORT;
13776
601
          input_position++;
13777
601
        }
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
10.4k
        else {
13784
          // If url is special and host_view is the empty string, validation
13785
          // error, return failure.
13786
10.4k
          if (host_view.empty() && url.is_special()) {
13787
8
            url.is_valid = false;
13788
8
            return url;
13789
8
          }
13790
10.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
10.4k
          if (host_view.empty()) {
13794
44
            url.update_base_hostname("");
13795
10.3k
          } else if (!url.parse_host(host_view)) {
13796
254
            return url;
13797
254
          }
13798
10.1k
          ada_log("HOST parsing results in ", url.get_hostname(),
13799
10.1k
                  " href=", url.get_href());
13800
13801
          // Set url's host to host, and state to path start state.
13802
10.1k
          state = state::PATH_START;
13803
10.1k
        }
13804
13805
10.7k
        break;
13806
11.1k
      }
13807
10.7k
      case state::OPAQUE_PATH: {
13808
1.52k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13809
1.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
1.52k
        size_t location = view.find('?');
13813
1.52k
        if (location != std::string_view::npos) {
13814
166
          view.remove_suffix(view.size() - location);
13815
166
          state = state::QUERY;
13816
166
          input_position += location + 1;
13817
1.35k
        } else {
13818
1.35k
          input_position = input_size + 1;
13819
1.35k
        }
13820
1.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
1.52k
        if (view.ends_with(' ')) {
13825
58
          std::string modified_view =
13826
58
              std::string(view.substr(0, view.size() - 1)) + "%20";
13827
58
          url.update_base_pathname(unicode::percent_encode(
13828
58
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13829
1.46k
        } else {
13830
1.46k
          url.update_base_pathname(unicode::percent_encode(
13831
1.46k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13832
1.46k
        }
13833
1.52k
        break;
13834
11.1k
      }
13835
601
      case state::PORT: {
13836
601
        ada_log("PORT ", helpers::substring(url_data, input_position));
13837
601
        std::string_view port_view = url_data.substr(input_position);
13838
601
        input_position += url.parse_port(port_view, true);
13839
601
        if (!url.is_valid) {
13840
107
          return url;
13841
107
        }
13842
494
        state = state::PATH_START;
13843
494
        [[fallthrough]];
13844
494
      }
13845
11.1k
      case state::PATH_START: {
13846
11.1k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13847
13848
        // If url is special, then:
13849
11.1k
        if (url.is_special()) {
13850
          // Set state to path state.
13851
10.9k
          state = state::PATH;
13852
13853
          // Optimization: Avoiding going into PATH state improves the
13854
          // performance of urls ending with /.
13855
10.9k
          if (input_position == input_size) {
13856
10.0k
            if constexpr (store_values) {
13857
10.0k
              url.update_base_pathname("/");
13858
10.0k
              if (fragment.has_value()) {
13859
63
                url.update_unencoded_base_hash(*fragment);
13860
63
              }
13861
10.0k
            }
13862
10.0k
            return url;
13863
10.0k
          }
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
846
          if ((url_data[input_position] != '/') &&
13868
104
              (url_data[input_position] != '\\')) {
13869
89
            break;
13870
89
          }
13871
846
        }
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
254
        else if ((input_position != input_size) &&
13875
68
                 (url_data[input_position] == '?')) {
13876
6
          state = state::QUERY;
13877
6
        }
13878
        // Otherwise, if c is not the EOF code point:
13879
248
        else if (input_position != input_size) {
13880
          // Set state to path state.
13881
62
          state = state::PATH;
13882
13883
          // If c is not U+002F (/), then decrease pointer by 1.
13884
62
          if (url_data[input_position] != '/') {
13885
0
            break;
13886
0
          }
13887
62
        }
13888
13889
1.01k
        input_position++;
13890
1.01k
        break;
13891
11.1k
      }
13892
2.45k
      case state::PATH: {
13893
2.45k
        ada_log("PATH ", helpers::substring(url_data, input_position));
13894
2.45k
        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.45k
        size_t locofquestionmark = view.find('?');
13899
2.45k
        if (locofquestionmark != std::string_view::npos) {
13900
153
          state = state::QUERY;
13901
153
          view.remove_suffix(view.size() - locofquestionmark);
13902
153
          input_position += locofquestionmark + 1;
13903
2.30k
        } else {
13904
2.30k
          input_position = input_size + 1;
13905
2.30k
        }
13906
2.45k
        if constexpr (store_values) {
13907
2.45k
          if constexpr (result_type_is_ada_url) {
13908
2.45k
            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
2.45k
        }
13914
2.45k
        break;
13915
11.1k
      }
13916
806
      case state::FILE_SLASH: {
13917
806
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13918
13919
        // If c is U+002F (/) or U+005C (\), then:
13920
806
        if ((input_position != input_size) &&
13921
800
            (url_data[input_position] == '/' ||
13922
603
             url_data[input_position] == '\\')) {
13923
603
          ada_log("FILE_SLASH c is U+002F or U+005C");
13924
          // Set state to file host state.
13925
603
          state = state::FILE_HOST;
13926
603
          input_position++;
13927
603
        } else {
13928
203
          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
203
          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
            } else {
13937
              url.update_host_to_base_host(base_url->get_host());
13938
            }
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
                  } else {
13958
                    url.append_base_pathname(
13959
                        helpers::concat("/", first_base_url_path));
13960
                  }
13961
0
                }
13962
0
              }
13963
0
            }
13964
0
          }
13965
13966
          // Set state to path state, and decrease pointer by 1.
13967
203
          state = state::PATH;
13968
203
        }
13969
13970
806
        break;
13971
11.1k
      }
13972
603
      case state::FILE_HOST: {
13973
603
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13974
603
        std::string_view view = url_data.substr(input_position);
13975
13976
603
        size_t location = view.find_first_of("/\\?");
13977
603
        std::string_view file_host_buffer(
13978
603
            view.data(),
13979
603
            (location != std::string_view::npos) ? location : view.size());
13980
13981
603
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13982
5
          state = state::PATH;
13983
598
        } else if (file_host_buffer.empty()) {
13984
          // Set url's host to the empty string.
13985
28
          if constexpr (result_type_is_ada_url) {
13986
28
            url.host = "";
13987
          } else {
13988
            url.update_base_hostname("");
13989
          }
13990
          // Set state to path start state.
13991
28
          state = state::PATH_START;
13992
570
        } else {
13993
570
          size_t consumed_bytes = file_host_buffer.size();
13994
570
          input_position += consumed_bytes;
13995
          // Let host be the result of host parsing buffer with url is not
13996
          // special.
13997
570
          if (!url.parse_host(file_host_buffer)) {
13998
109
            return url;
13999
109
          }
14000
14001
461
          if constexpr (result_type_is_ada_url) {
14002
            // If host is "localhost", then set host to the empty string.
14003
461
            if (url.host.has_value() && url.host.value() == "localhost") {
14004
3
              url.host = "";
14005
3
            }
14006
          } else {
14007
            if (url.get_hostname() == "localhost") {
14008
              url.update_base_hostname("");
14009
            }
14010
          }
14011
14012
          // Set buffer to the empty string and state to path start state.
14013
461
          state = state::PATH_START;
14014
461
        }
14015
14016
494
        break;
14017
603
      }
14018
1.36k
      case state::FILE: {
14019
1.36k
        ada_log("FILE ", helpers::substring(url_data, input_position));
14020
1.36k
        std::string_view file_view = url_data.substr(input_position);
14021
14022
1.36k
        url.set_protocol_as_file();
14023
1.36k
        if constexpr (result_type_is_ada_url) {
14024
          // Set url's host to the empty string.
14025
1.36k
          url.host = "";
14026
        } else {
14027
          url.update_base_hostname("");
14028
        }
14029
        // If c is U+002F (/) or U+005C (\), then:
14030
1.36k
        if (input_position != input_size &&
14031
1.34k
            (url_data[input_position] == '/' ||
14032
806
             url_data[input_position] == '\\')) {
14033
806
          ada_log("FILE c is U+002F or U+005C");
14034
          // Set state to file slash state.
14035
806
          state = state::FILE_SLASH;
14036
806
        }
14037
        // Otherwise, if base is non-null and base's scheme is "file":
14038
555
        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
          } else {
14047
            url.update_host_to_base_host(base_url->get_hostname());
14048
            url.update_base_pathname(base_url->get_pathname());
14049
            url.update_base_search(base_url->get_search());
14050
          }
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
              } else {
14068
                std::string_view path = url.get_pathname();
14069
                if (helpers::shorten_path(path, url.type)) {
14070
                  url.update_base_pathname(std::move(std::string(path)));
14071
                }
14072
              }
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
555
        else {
14088
555
          ada_log("FILE go to path");
14089
555
          state = state::PATH;
14090
555
          break;
14091
555
        }
14092
14093
806
        input_position++;
14094
806
        break;
14095
1.36k
      }
14096
0
      default:
14097
0
        unreachable();
14098
93.0k
    }
14099
93.0k
  }
14100
3.84k
  if constexpr (store_values) {
14101
3.84k
    if (fragment.has_value()) {
14102
128
      url.update_unencoded_base_hash(*fragment);
14103
128
    }
14104
3.84k
  }
14105
3.84k
  return url;
14106
19.7k
}
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
19.7k
                           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
19.7k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13219
19.7k
  constexpr bool result_type_is_ada_url_aggregator =
13220
19.7k
      std::is_same_v<url_aggregator, result_type>;
13221
19.7k
  static_assert(result_type_is_ada_url ||
13222
19.7k
                result_type_is_ada_url_aggregator);  // We don't support
13223
                                                     // anything else for now.
13224
13225
19.7k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13226
19.7k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13227
19.7k
          ")");
13228
13229
19.7k
  state state = state::SCHEME_START;
13230
19.7k
  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
19.7k
  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
19.7k
  if (base_url != nullptr) {
13241
0
    url.is_valid &= base_url->is_valid;
13242
0
  }
13243
19.7k
  if (!url.is_valid) {
13244
0
    return url;
13245
0
  }
13246
19.7k
  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
19.7k
    uint32_t reserve_capacity =
13259
19.7k
        (0xFFFFFFFF >>
13260
19.7k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13261
19.7k
        1;
13262
19.7k
    url.reserve(reserve_capacity);
13263
19.7k
  }
13264
19.7k
  std::string tmp_buffer;
13265
19.7k
  std::string_view url_data;
13266
19.7k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13267
212
    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
212
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13271
212
    url_data = tmp_buffer;
13272
19.5k
  } else [[likely]] {
13273
19.5k
    url_data = user_input;
13274
19.5k
  }
13275
13276
  // Leading and trailing control characters are uncommon and easy to deal with
13277
  // (no performance concern).
13278
19.7k
  helpers::trim_c0_whitespace(url_data);
13279
13280
  // Optimization opportunity. Most websites do not have fragment.
13281
19.7k
  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
19.7k
  size_t input_position = 0;
13291
19.7k
  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
96.5k
  while (input_position <= input_size) {
13297
92.8k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13298
92.8k
            " in state ", ada::to_string(state));
13299
92.8k
    switch (state) {
13300
19.7k
      case state::SCHEME_START: {
13301
19.7k
        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
19.7k
        if ((input_position != input_size) &&
13305
19.7k
            checkers::is_alpha(url_data[input_position])) {
13306
15.7k
          state = state::SCHEME;
13307
15.7k
          input_position++;
13308
15.7k
        } else {
13309
          // Otherwise, if state override is not given, set state to no scheme
13310
          // state and decrease pointer by 1.
13311
4.02k
          state = state::NO_SCHEME;
13312
4.02k
        }
13313
19.7k
        break;
13314
0
      }
13315
15.7k
      case state::SCHEME: {
13316
15.7k
        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
83.5k
        while ((input_position != input_size) &&
13320
83.1k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13321
67.7k
          input_position++;
13322
67.7k
        }
13323
        // Otherwise, if c is U+003A (:), then:
13324
15.7k
        if ((input_position != input_size) &&
13325
15.3k
            (url_data[input_position] == ':')) {
13326
14.8k
          ada_log("SCHEME the scheme should be ",
13327
14.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
14.8k
          } else {
13333
            // we pass the colon along instead of painfully adding it back.
13334
14.8k
            if (!url.parse_scheme_with_colon(
13335
14.8k
                    url_data.substr(0, input_position + 1))) {
13336
0
              return url;
13337
0
            }
13338
14.8k
          }
13339
14.8k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13340
13341
          // If url's scheme is "file", then:
13342
14.8k
          if (url.type == scheme::type::FILE) {
13343
            // Set state to file state.
13344
1.36k
            state = state::FILE;
13345
1.36k
          }
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
10.8k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13358
10.8k
          }
13359
          // Otherwise, if remaining starts with an U+002F (/), set state to
13360
          // path or authority state and increase pointer by 1.
13361
2.67k
          else if (input_position + 1 < input_size &&
13362
2.33k
                   url_data[input_position + 1] == '/') {
13363
1.14k
            state = state::PATH_OR_AUTHORITY;
13364
1.14k
            input_position++;
13365
1.14k
          }
13366
          // Otherwise, set url's path to the empty string and set state to
13367
          // opaque path state.
13368
1.52k
          else {
13369
1.52k
            state = state::OPAQUE_PATH;
13370
1.52k
          }
13371
14.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
891
        else {
13376
891
          state = state::NO_SCHEME;
13377
891
          input_position = 0;
13378
891
          break;
13379
891
        }
13380
14.8k
        input_position++;
13381
14.8k
        break;
13382
15.7k
      }
13383
4.91k
      case state::NO_SCHEME: {
13384
4.91k
        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
4.91k
        if (base_url == nullptr ||
13388
4.91k
            (base_url->has_opaque_path && !fragment.has_value())) {
13389
4.91k
          ada_log("NO_SCHEME validation error");
13390
4.91k
          url.is_valid = false;
13391
4.91k
          return url;
13392
4.91k
        }
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
4.91k
      }
13425
11.1k
      case state::AUTHORITY: {
13426
11.1k
        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
11.1k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13438
10.5k
          state = state::HOST;
13439
10.5k
          break;
13440
10.5k
        }
13441
654
        bool at_sign_seen{false};
13442
654
        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.40k
        do {
13449
7.40k
          std::string_view view = url_data.substr(input_position);
13450
          // The delimiters are @, /, ? \\.
13451
7.40k
          size_t location =
13452
7.40k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13453
7.40k
                               : helpers::find_authority_delimiter(view);
13454
7.40k
          std::string_view authority_view = view.substr(0, location);
13455
7.40k
          size_t end_of_authority = input_position + authority_view.size();
13456
          // If c is U+0040 (@), then:
13457
7.40k
          if ((end_of_authority != input_size) &&
13458
6.84k
              (url_data[end_of_authority] == '@')) {
13459
            // If atSignSeen is true, then prepend "%40" to buffer.
13460
6.75k
            if (at_sign_seen) {
13461
6.14k
              if (password_token_seen) {
13462
                if constexpr (result_type_is_ada_url) {
13463
                  url.password += "%40";
13464
2.71k
                } else {
13465
2.71k
                  url.append_base_password("%40");
13466
2.71k
                }
13467
3.42k
              } else {
13468
                if constexpr (result_type_is_ada_url) {
13469
                  url.username += "%40";
13470
3.42k
                } else {
13471
3.42k
                  url.append_base_username("%40");
13472
3.42k
                }
13473
3.42k
              }
13474
6.14k
            }
13475
13476
6.75k
            at_sign_seen = true;
13477
13478
6.75k
            if (!password_token_seen) {
13479
4.03k
              size_t password_token_location = authority_view.find(':');
13480
4.03k
              password_token_seen =
13481
4.03k
                  password_token_location != std::string_view::npos;
13482
13483
4.03k
              if constexpr (store_values) {
13484
4.03k
                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
3.75k
                  } else {
13490
3.75k
                    url.append_base_username(unicode::percent_encode(
13491
3.75k
                        authority_view,
13492
3.75k
                        character_sets::USERINFO_PERCENT_ENCODE));
13493
3.75k
                  }
13494
3.75k
                } 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
284
                  } else {
13503
284
                    url.append_base_username(unicode::percent_encode(
13504
284
                        authority_view.substr(0, password_token_location),
13505
284
                        character_sets::USERINFO_PERCENT_ENCODE));
13506
284
                    url.append_base_password(unicode::percent_encode(
13507
284
                        authority_view.substr(password_token_location + 1),
13508
284
                        character_sets::USERINFO_PERCENT_ENCODE));
13509
284
                  }
13510
284
                }
13511
4.03k
              }
13512
4.03k
            } 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
2.71k
              } else {
13517
2.71k
                url.append_base_password(unicode::percent_encode(
13518
2.71k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13519
2.71k
              }
13520
2.71k
            }
13521
6.75k
          }
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
654
          else if (end_of_authority == input_size ||
13526
90
                   url_data[end_of_authority] == '/' ||
13527
20
                   url_data[end_of_authority] == '?' ||
13528
654
                   (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
654
            if (at_sign_seen && authority_view.empty()) {
13532
73
              url.is_valid = false;
13533
73
              return url;
13534
73
            }
13535
581
            state = state::HOST;
13536
581
            break;
13537
654
          }
13538
6.75k
          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
6.75k
          input_position = end_of_authority + 1;
13547
6.75k
        } while (true);
13548
13549
581
        break;
13550
654
      }
13551
581
      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
654
      }
13569
1.14k
      case state::PATH_OR_AUTHORITY: {
13570
1.14k
        ada_log("PATH_OR_AUTHORITY ",
13571
1.14k
                helpers::substring(url_data, input_position));
13572
13573
        // If c is U+002F (/), then set state to authority state.
13574
1.14k
        if ((input_position != input_size) &&
13575
1.13k
            (url_data[input_position] == '/')) {
13576
362
          state = state::AUTHORITY;
13577
362
          input_position++;
13578
784
        } else {
13579
          // Otherwise, set state to path state, and decrease pointer by 1.
13580
784
          state = state::PATH;
13581
784
        }
13582
13583
1.14k
        break;
13584
654
      }
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
10.8k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13705
10.8k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13706
10.8k
                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
10.8k
        if (url_data.substr(input_position, 2) == "//") {
13712
8.29k
          input_position += 2;
13713
8.29k
        }
13714
13715
10.8k
        [[fallthrough]];
13716
10.8k
      }
13717
10.8k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13718
10.8k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13719
10.8k
                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
11.4k
        while ((input_position != input_size) &&
13724
11.4k
               ((url_data[input_position] == '/') ||
13725
11.0k
                (url_data[input_position] == '\\'))) {
13726
585
          input_position++;
13727
585
        }
13728
10.8k
        state = state::AUTHORITY;
13729
13730
10.8k
        break;
13731
10.8k
      }
13732
318
      case state::QUERY: {
13733
318
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13734
318
        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
318
          const uint8_t* query_percent_encode_set =
13738
318
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13739
318
                               : 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
318
          url.update_base_search(url_data.substr(input_position),
13744
318
                                 query_percent_encode_set);
13745
318
          ada_log("QUERY update_base_search completed ");
13746
318
          if (fragment.has_value()) {
13747
20
            url.update_unencoded_base_hash(*fragment);
13748
20
          }
13749
318
        }
13750
318
        return url;
13751
10.8k
      }
13752
11.1k
      case state::HOST: {
13753
11.1k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13754
13755
11.1k
        std::string_view host_view = url_data.substr(input_position);
13756
11.1k
        auto [location, found_colon] =
13757
11.1k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13758
11.1k
        input_position = (location != std::string_view::npos)
13759
11.1k
                             ? input_position + location
13760
11.1k
                             : 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
11.1k
        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
685
          ada_log("HOST parsing ", host_view);
13769
685
          if (!url.parse_host(host_view)) {
13770
101
            return url;
13771
101
          }
13772
584
          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
584
          state = state::PORT;
13776
584
          input_position++;
13777
584
        }
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
10.4k
        else {
13784
          // If url is special and host_view is the empty string, validation
13785
          // error, return failure.
13786
10.4k
          if (host_view.empty() && url.is_special()) {
13787
8
            url.is_valid = false;
13788
8
            return url;
13789
8
          }
13790
10.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
10.4k
          if (host_view.empty()) {
13794
44
            url.update_base_hostname("");
13795
10.3k
          } else if (!url.parse_host(host_view)) {
13796
356
            return url;
13797
356
          }
13798
10.0k
          ada_log("HOST parsing results in ", url.get_hostname(),
13799
10.0k
                  " href=", url.get_href());
13800
13801
          // Set url's host to host, and state to path start state.
13802
10.0k
          state = state::PATH_START;
13803
10.0k
        }
13804
13805
10.6k
        break;
13806
11.1k
      }
13807
10.6k
      case state::OPAQUE_PATH: {
13808
1.52k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13809
1.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
1.52k
        size_t location = view.find('?');
13813
1.52k
        if (location != std::string_view::npos) {
13814
166
          view.remove_suffix(view.size() - location);
13815
166
          state = state::QUERY;
13816
166
          input_position += location + 1;
13817
1.35k
        } else {
13818
1.35k
          input_position = input_size + 1;
13819
1.35k
        }
13820
1.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
1.52k
        if (view.ends_with(' ')) {
13825
58
          std::string modified_view =
13826
58
              std::string(view.substr(0, view.size() - 1)) + "%20";
13827
58
          url.update_base_pathname(unicode::percent_encode(
13828
58
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13829
1.46k
        } else {
13830
1.46k
          url.update_base_pathname(unicode::percent_encode(
13831
1.46k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13832
1.46k
        }
13833
1.52k
        break;
13834
11.1k
      }
13835
584
      case state::PORT: {
13836
584
        ada_log("PORT ", helpers::substring(url_data, input_position));
13837
584
        std::string_view port_view = url_data.substr(input_position);
13838
584
        input_position += url.parse_port(port_view, true);
13839
584
        if (!url.is_valid) {
13840
104
          return url;
13841
104
        }
13842
480
        state = state::PATH_START;
13843
480
        [[fallthrough]];
13844
480
      }
13845
11.0k
      case state::PATH_START: {
13846
11.0k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13847
13848
        // If url is special, then:
13849
11.0k
        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
10.0k
            if constexpr (store_values) {
13857
10.0k
              url.update_base_pathname("/");
13858
10.0k
              if (fragment.has_value()) {
13859
62
                url.update_unencoded_base_hash(*fragment);
13860
62
              }
13861
10.0k
            }
13862
10.0k
            return url;
13863
10.0k
          }
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
734
          if ((url_data[input_position] != '/') &&
13868
97
              (url_data[input_position] != '\\')) {
13869
84
            break;
13870
84
          }
13871
734
        }
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
254
        else if ((input_position != input_size) &&
13875
68
                 (url_data[input_position] == '?')) {
13876
6
          state = state::QUERY;
13877
6
        }
13878
        // Otherwise, if c is not the EOF code point:
13879
248
        else if (input_position != input_size) {
13880
          // Set state to path state.
13881
62
          state = state::PATH;
13882
13883
          // If c is not U+002F (/), then decrease pointer by 1.
13884
62
          if (url_data[input_position] != '/') {
13885
0
            break;
13886
0
          }
13887
62
        }
13888
13889
904
        input_position++;
13890
904
        break;
13891
11.0k
      }
13892
2.34k
      case state::PATH: {
13893
2.34k
        ada_log("PATH ", helpers::substring(url_data, input_position));
13894
2.34k
        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.34k
        size_t locofquestionmark = view.find('?');
13899
2.34k
        if (locofquestionmark != std::string_view::npos) {
13900
146
          state = state::QUERY;
13901
146
          view.remove_suffix(view.size() - locofquestionmark);
13902
146
          input_position += locofquestionmark + 1;
13903
2.19k
        } else {
13904
2.19k
          input_position = input_size + 1;
13905
2.19k
        }
13906
2.34k
        if constexpr (store_values) {
13907
          if constexpr (result_type_is_ada_url) {
13908
            helpers::parse_prepared_path(view, url.type, url.path);
13909
2.34k
          } else {
13910
2.34k
            url.consume_prepared_path(view);
13911
2.34k
            ADA_ASSERT_TRUE(url.validate());
13912
2.34k
          }
13913
2.34k
        }
13914
2.34k
        break;
13915
11.0k
      }
13916
806
      case state::FILE_SLASH: {
13917
806
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13918
13919
        // If c is U+002F (/) or U+005C (\), then:
13920
806
        if ((input_position != input_size) &&
13921
800
            (url_data[input_position] == '/' ||
13922
603
             url_data[input_position] == '\\')) {
13923
603
          ada_log("FILE_SLASH c is U+002F or U+005C");
13924
          // Set state to file host state.
13925
603
          state = state::FILE_HOST;
13926
603
          input_position++;
13927
603
        } else {
13928
203
          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
203
          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
203
          state = state::PATH;
13968
203
        }
13969
13970
806
        break;
13971
11.0k
      }
13972
603
      case state::FILE_HOST: {
13973
603
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13974
603
        std::string_view view = url_data.substr(input_position);
13975
13976
603
        size_t location = view.find_first_of("/\\?");
13977
603
        std::string_view file_host_buffer(
13978
603
            view.data(),
13979
603
            (location != std::string_view::npos) ? location : view.size());
13980
13981
603
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13982
5
          state = state::PATH;
13983
598
        } 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
28
          } else {
13988
28
            url.update_base_hostname("");
13989
28
          }
13990
          // Set state to path start state.
13991
28
          state = state::PATH_START;
13992
570
        } else {
13993
570
          size_t consumed_bytes = file_host_buffer.size();
13994
570
          input_position += consumed_bytes;
13995
          // Let host be the result of host parsing buffer with url is not
13996
          // special.
13997
570
          if (!url.parse_host(file_host_buffer)) {
13998
128
            return url;
13999
128
          }
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
442
          } else {
14007
442
            if (url.get_hostname() == "localhost") {
14008
3
              url.update_base_hostname("");
14009
3
            }
14010
442
          }
14011
14012
          // Set buffer to the empty string and state to path start state.
14013
442
          state = state::PATH_START;
14014
442
        }
14015
14016
475
        break;
14017
603
      }
14018
1.36k
      case state::FILE: {
14019
1.36k
        ada_log("FILE ", helpers::substring(url_data, input_position));
14020
1.36k
        std::string_view file_view = url_data.substr(input_position);
14021
14022
1.36k
        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.36k
        } else {
14027
1.36k
          url.update_base_hostname("");
14028
1.36k
        }
14029
        // If c is U+002F (/) or U+005C (\), then:
14030
1.36k
        if (input_position != input_size &&
14031
1.34k
            (url_data[input_position] == '/' ||
14032
806
             url_data[input_position] == '\\')) {
14033
806
          ada_log("FILE c is U+002F or U+005C");
14034
          // Set state to file slash state.
14035
806
          state = state::FILE_SLASH;
14036
806
        }
14037
        // Otherwise, if base is non-null and base's scheme is "file":
14038
555
        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
555
        else {
14088
555
          ada_log("FILE go to path");
14089
555
          state = state::PATH;
14090
555
          break;
14091
555
        }
14092
14093
806
        input_position++;
14094
806
        break;
14095
1.36k
      }
14096
0
      default:
14097
0
        unreachable();
14098
92.8k
    }
14099
92.8k
  }
14100
3.74k
  if constexpr (store_values) {
14101
3.74k
    if (fragment.has_value()) {
14102
124
      url.update_unencoded_base_hash(*fragment);
14103
124
    }
14104
3.74k
  }
14105
3.74k
  return url;
14106
19.7k
}
Unexecuted instantiation: 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*)
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
18.5k
    const std::string_view input_with_colon) {
14186
18.5k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14187
18.5k
  ADA_ASSERT_TRUE(validate());
14188
18.5k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14189
18.5k
  std::string_view input{input_with_colon};
14190
18.5k
  input.remove_suffix(1);
14191
18.5k
  auto parsed_type = ada::scheme::get_scheme_type(input);
14192
18.5k
  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
18.5k
  if (is_input_special) {  // fast path!!!
14198
12.5k
    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
1.47k
      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
1.47k
      if ((has_credentials() || components.port != url_components::omitted) &&
14208
0
          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
1.47k
      if (type == ada::scheme::type::FILE &&
14215
0
          components.host_start == components.host_end) {
14216
0
        return false;
14217
0
      }
14218
1.47k
    }
14219
14220
1.47k
    type = parsed_type;
14221
12.5k
    set_scheme_from_view_with_colon(input_with_colon);
14222
14223
12.5k
    if constexpr (has_state_override) {
14224
      // This is uncommon.
14225
1.47k
      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
1.47k
      if (components.port == urls_scheme_port) {
14230
0
        clear_port();
14231
0
      }
14232
1.47k
    }
14233
12.5k
  } else {  // slow path
14234
5.99k
    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
5.99k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14239
14240
5.99k
    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
2.22k
      if (is_special() != ada::scheme::is_special(_buffer)) {
14245
1.61k
        return true;
14246
1.61k
      }
14247
14248
      // If url includes credentials or has a non-null port, and buffer is
14249
      // "file", then return.
14250
604
      if ((has_credentials() || components.port != url_components::omitted) &&
14251
0
          _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
604
      if (type == ada::scheme::type::FILE &&
14258
0
          components.host_start == components.host_end) {
14259
0
        return true;
14260
0
      }
14261
604
    }
14262
14263
604
    set_scheme(_buffer);
14264
14265
5.99k
    if constexpr (has_state_override) {
14266
      // This is uncommon.
14267
2.22k
      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
2.22k
      if (components.port == urls_scheme_port) {
14272
0
        clear_port();
14273
0
      }
14274
2.22k
    }
14275
5.99k
  }
14276
0
  ADA_ASSERT_TRUE(validate());
14277
18.5k
  return true;
14278
18.5k
}
bool ada::url_aggregator::parse_scheme_with_colon<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14185
14.8k
    const std::string_view input_with_colon) {
14186
14.8k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14187
14.8k
  ADA_ASSERT_TRUE(validate());
14188
14.8k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14189
14.8k
  std::string_view input{input_with_colon};
14190
14.8k
  input.remove_suffix(1);
14191
14.8k
  auto parsed_type = ada::scheme::get_scheme_type(input);
14192
14.8k
  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
14.8k
  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
11.0k
    type = parsed_type;
14221
11.0k
    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
11.0k
  } else {  // slow path
14234
3.77k
    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.77k
    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
3.77k
    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
3.77k
  }
14276
14.8k
  ADA_ASSERT_TRUE(validate());
14277
14.8k
  return true;
14278
14.8k
}
bool ada::url_aggregator::parse_scheme_with_colon<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14185
3.69k
    const std::string_view input_with_colon) {
14186
3.69k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14187
3.69k
  ADA_ASSERT_TRUE(validate());
14188
3.69k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14189
3.69k
  std::string_view input{input_with_colon};
14190
3.69k
  input.remove_suffix(1);
14191
3.69k
  auto parsed_type = ada::scheme::get_scheme_type(input);
14192
3.69k
  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
3.69k
  if (is_input_special) {  // fast path!!!
14198
1.47k
    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
1.47k
      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
1.47k
      if ((has_credentials() || components.port != url_components::omitted) &&
14208
0
          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
1.47k
      if (type == ada::scheme::type::FILE &&
14215
0
          components.host_start == components.host_end) {
14216
0
        return false;
14217
0
      }
14218
1.47k
    }
14219
14220
1.47k
    type = parsed_type;
14221
1.47k
    set_scheme_from_view_with_colon(input_with_colon);
14222
14223
1.47k
    if constexpr (has_state_override) {
14224
      // This is uncommon.
14225
1.47k
      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
1.47k
      if (components.port == urls_scheme_port) {
14230
0
        clear_port();
14231
0
      }
14232
1.47k
    }
14233
2.22k
  } else {  // slow path
14234
2.22k
    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
2.22k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14239
14240
2.22k
    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
2.22k
      if (is_special() != ada::scheme::is_special(_buffer)) {
14245
1.61k
        return true;
14246
1.61k
      }
14247
14248
      // If url includes credentials or has a non-null port, and buffer is
14249
      // "file", then return.
14250
604
      if ((has_credentials() || components.port != url_components::omitted) &&
14251
0
          _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
604
      if (type == ada::scheme::type::FILE &&
14258
0
          components.host_start == components.host_end) {
14259
0
        return true;
14260
0
      }
14261
604
    }
14262
14263
604
    set_scheme(_buffer);
14264
14265
2.22k
    if constexpr (has_state_override) {
14266
      // This is uncommon.
14267
2.22k
      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
2.22k
      if (components.port == urls_scheme_port) {
14272
0
        clear_port();
14273
0
      }
14274
2.22k
    }
14275
2.22k
  }
14276
0
  ADA_ASSERT_TRUE(validate());
14277
3.69k
  return true;
14278
3.69k
}
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
12.5k
    std::string_view new_scheme_with_colon) {
14312
12.5k
  ada_log("url_aggregator::set_scheme_from_view_with_colon ",
14313
12.5k
          new_scheme_with_colon);
14314
12.5k
  ADA_ASSERT_TRUE(validate());
14315
12.5k
  ADA_ASSERT_TRUE(!new_scheme_with_colon.empty() &&
14316
12.5k
                  new_scheme_with_colon.back() == ':');
14317
  // next line could overflow but unsigned arithmetic has well-defined
14318
  // overflows.
14319
12.5k
  uint32_t new_difference =
14320
12.5k
      uint32_t(new_scheme_with_colon.size()) - components.protocol_end;
14321
14322
12.5k
  if (buffer.empty()) {
14323
11.0k
    buffer.append(new_scheme_with_colon);
14324
11.0k
  } else {
14325
1.47k
    buffer.erase(0, components.protocol_end);
14326
1.47k
    buffer.insert(0, new_scheme_with_colon);
14327
1.47k
  }
14328
12.5k
  components.protocol_end += new_difference;
14329
14330
  // Update the rest of the components.
14331
12.5k
  components.username_end += new_difference;
14332
12.5k
  components.host_start += new_difference;
14333
12.5k
  components.host_end += new_difference;
14334
12.5k
  components.pathname_start += new_difference;
14335
12.5k
  if (components.search_start != url_components::omitted) {
14336
0
    components.search_start += new_difference;
14337
0
  }
14338
12.5k
  if (components.hash_start != url_components::omitted) {
14339
0
    components.hash_start += new_difference;
14340
0
  }
14341
12.5k
  ADA_ASSERT_TRUE(validate());
14342
12.5k
}
14343
14344
4.38k
inline void url_aggregator::set_scheme(std::string_view new_scheme) {
14345
4.38k
  ada_log("url_aggregator::set_scheme ", new_scheme);
14346
4.38k
  ADA_ASSERT_TRUE(validate());
14347
4.38k
  ADA_ASSERT_TRUE(new_scheme.empty() || new_scheme.back() != ':');
14348
  // next line could overflow but unsigned arithmetic has well-defined
14349
  // overflows.
14350
4.38k
  uint32_t new_difference =
14351
4.38k
      uint32_t(new_scheme.size()) - components.protocol_end + 1;
14352
14353
4.38k
  type = ada::scheme::get_scheme_type(new_scheme);
14354
4.38k
  if (buffer.empty()) {
14355
3.77k
    buffer.append(helpers::concat(new_scheme, ":"));
14356
3.77k
  } else {
14357
604
    buffer.erase(0, components.protocol_end);
14358
604
    buffer.insert(0, helpers::concat(new_scheme, ":"));
14359
604
  }
14360
4.38k
  components.protocol_end = uint32_t(new_scheme.size() + 1);
14361
14362
  // Update the rest of the components.
14363
4.38k
  components.username_end += new_difference;
14364
4.38k
  components.host_start += new_difference;
14365
4.38k
  components.host_end += new_difference;
14366
4.38k
  components.pathname_start += new_difference;
14367
4.38k
  if (components.search_start != url_components::omitted) {
14368
0
    components.search_start += new_difference;
14369
0
  }
14370
4.38k
  if (components.hash_start != url_components::omitted) {
14371
0
    components.hash_start += new_difference;
14372
0
  }
14373
4.38k
  ADA_ASSERT_TRUE(validate());
14374
4.38k
}
14375
14376
8.27k
bool url_aggregator::set_protocol(const std::string_view input) {
14377
8.27k
  ada_log("url_aggregator::set_protocol ", input);
14378
8.27k
  ADA_ASSERT_TRUE(validate());
14379
8.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14380
8.27k
  std::string view(input);
14381
8.27k
  helpers::remove_ascii_tab_or_newline(view);
14382
8.27k
  if (view.empty()) {
14383
29
    return true;
14384
29
  }
14385
14386
  // Schemes should start with alpha values.
14387
8.24k
  if (!checkers::is_alpha(view[0])) {
14388
4.02k
    return false;
14389
4.02k
  }
14390
14391
4.22k
  view.append(":");
14392
14393
4.22k
  std::string::iterator pointer =
14394
4.22k
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
14395
14396
4.22k
  if (pointer != view.end() && *pointer == ':') {
14397
3.69k
    return parse_scheme_with_colon<true>(
14398
3.69k
        view.substr(0, pointer - view.begin() + 1));
14399
3.69k
  }
14400
521
  return false;
14401
4.22k
}
14402
14403
8.27k
bool url_aggregator::set_username(const std::string_view input) {
14404
8.27k
  ada_log("url_aggregator::set_username '", input, "' ");
14405
8.27k
  ADA_ASSERT_TRUE(validate());
14406
8.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14407
8.27k
  if (cannot_have_credentials_or_port()) {
14408
683
    return false;
14409
683
  }
14410
7.59k
  size_t idx = ada::unicode::percent_encode_index(
14411
7.59k
      input, character_sets::USERINFO_PERCENT_ENCODE);
14412
7.59k
  if (idx == input.size()) {
14413
1.03k
    update_base_username(input);
14414
6.55k
  } else {
14415
    // We only create a temporary string if we have to!
14416
6.55k
    update_base_username(ada::unicode::percent_encode(
14417
6.55k
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14418
6.55k
  }
14419
7.59k
  ADA_ASSERT_TRUE(validate());
14420
7.59k
  return true;
14421
8.27k
}
14422
14423
8.27k
bool url_aggregator::set_password(const std::string_view input) {
14424
8.27k
  ada_log("url_aggregator::set_password '", input, "'");
14425
8.27k
  ADA_ASSERT_TRUE(validate());
14426
8.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14427
8.27k
  if (cannot_have_credentials_or_port()) {
14428
683
    return false;
14429
683
  }
14430
7.59k
  size_t idx = ada::unicode::percent_encode_index(
14431
7.59k
      input, character_sets::USERINFO_PERCENT_ENCODE);
14432
7.59k
  if (idx == input.size()) {
14433
1.03k
    update_base_password(input);
14434
6.55k
  } else {
14435
    // We only create a temporary string if we have to!
14436
6.55k
    update_base_password(ada::unicode::percent_encode(
14437
6.55k
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14438
6.55k
  }
14439
7.59k
  ADA_ASSERT_TRUE(validate());
14440
7.59k
  return true;
14441
8.27k
}
14442
14443
10.8k
bool url_aggregator::set_port(const std::string_view input) {
14444
10.8k
  ada_log("url_aggregator::set_port ", input);
14445
10.8k
  ADA_ASSERT_TRUE(validate());
14446
10.8k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14447
10.8k
  if (cannot_have_credentials_or_port()) {
14448
683
    return false;
14449
683
  }
14450
14451
10.2k
  if (input.empty()) {
14452
2
    clear_port();
14453
2
    return true;
14454
2
  }
14455
14456
10.2k
  std::string trimmed(input);
14457
10.2k
  helpers::remove_ascii_tab_or_newline(trimmed);
14458
14459
10.2k
  if (trimmed.empty()) {
14460
27
    return true;
14461
27
  }
14462
14463
  // Input should not start with a non-digit character.
14464
10.1k
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
14465
8.62k
    return false;
14466
8.62k
  }
14467
14468
  // Find the first non-digit character to determine the length of digits
14469
1.55k
  auto first_non_digit =
14470
1.55k
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
14471
1.55k
  std::string_view digits_to_parse =
14472
1.55k
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
14473
14474
  // Revert changes if parse_port fails.
14475
1.55k
  uint32_t previous_port = components.port;
14476
1.55k
  parse_port(digits_to_parse);
14477
1.55k
  if (is_valid) {
14478
1.06k
    return true;
14479
1.06k
  }
14480
496
  update_base_port(previous_port);
14481
496
  is_valid = true;
14482
496
  ADA_ASSERT_TRUE(validate());
14483
496
  return false;
14484
1.55k
}
14485
14486
8.27k
bool url_aggregator::set_pathname(const std::string_view input) {
14487
8.27k
  ada_log("url_aggregator::set_pathname ", input);
14488
8.27k
  ADA_ASSERT_TRUE(validate());
14489
8.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14490
8.27k
  if (has_opaque_path) {
14491
0
    return false;
14492
0
  }
14493
8.27k
  clear_pathname();
14494
8.27k
  parse_path(input);
14495
8.27k
  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
8.27k
  ADA_ASSERT_TRUE(validate());
14506
8.27k
  return true;
14507
8.27k
}
14508
14509
8.27k
ada_really_inline void url_aggregator::parse_path(std::string_view input) {
14510
8.27k
  ada_log("url_aggregator::parse_path ", input);
14511
8.27k
  ADA_ASSERT_TRUE(validate());
14512
8.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14513
8.27k
  std::string tmp_buffer;
14514
8.27k
  std::string_view internal_input;
14515
8.27k
  if (unicode::has_tabs_or_newline(input)) {
14516
166
    tmp_buffer = input;
14517
    // Optimization opportunity: Instead of copying and then pruning, we could
14518
    // just directly build the string from user_input.
14519
166
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
14520
166
    internal_input = tmp_buffer;
14521
8.11k
  } else {
14522
8.11k
    internal_input = input;
14523
8.11k
  }
14524
14525
  // If url is special, then:
14526
8.27k
  if (is_special()) {
14527
8.27k
    if (internal_input.empty()) {
14528
29
      update_base_pathname("/");
14529
8.24k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
14530
693
      consume_prepared_path(internal_input.substr(1));
14531
7.55k
    } else {
14532
7.55k
      consume_prepared_path(internal_input);
14533
7.55k
    }
14534
8.27k
  } else if (!internal_input.empty()) {
14535
0
    if (internal_input[0] == '/') {
14536
0
      consume_prepared_path(internal_input.substr(1));
14537
0
    } else {
14538
0
      consume_prepared_path(internal_input);
14539
0
    }
14540
0
  } 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
8.27k
  ADA_ASSERT_TRUE(validate());
14548
8.27k
}
14549
14550
8.27k
void url_aggregator::set_search(const std::string_view input) {
14551
8.27k
  ada_log("url_aggregator::set_search ", input);
14552
8.27k
  ADA_ASSERT_TRUE(validate());
14553
8.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14554
8.27k
  if (input.empty()) {
14555
2
    clear_search();
14556
2
    helpers::strip_trailing_spaces_from_opaque_path(*this);
14557
2
    return;
14558
2
  }
14559
14560
8.27k
  std::string new_value;
14561
8.27k
  new_value = input[0] == '?' ? input.substr(1) : input;
14562
8.27k
  helpers::remove_ascii_tab_or_newline(new_value);
14563
14564
8.27k
  auto query_percent_encode_set =
14565
8.27k
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
14566
8.27k
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
14567
14568
8.27k
  update_base_search(new_value, query_percent_encode_set);
14569
8.27k
  ADA_ASSERT_TRUE(validate());
14570
8.27k
}
14571
14572
8.27k
void url_aggregator::set_hash(const std::string_view input) {
14573
8.27k
  ada_log("url_aggregator::set_hash ", input);
14574
8.27k
  ADA_ASSERT_TRUE(validate());
14575
8.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14576
8.27k
  if (input.empty()) {
14577
2
    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
2
    helpers::strip_trailing_spaces_from_opaque_path(*this);
14582
2
    return;
14583
2
  }
14584
14585
8.27k
  std::string new_value;
14586
8.27k
  new_value = input[0] == '#' ? input.substr(1) : input;
14587
8.27k
  helpers::remove_ascii_tab_or_newline(new_value);
14588
8.27k
  update_unencoded_base_hash(new_value);
14589
8.27k
  ADA_ASSERT_TRUE(validate());
14590
8.27k
}
14591
14592
2.80k
bool url_aggregator::set_href(const std::string_view input) {
14593
2.80k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14594
2.80k
  ada_log("url_aggregator::set_href ", input, " [", input.size(), " bytes]");
14595
2.80k
  ada::result<url_aggregator> out = ada::parse<url_aggregator>(input);
14596
2.80k
  ada_log("url_aggregator::set_href, success :", out.has_value());
14597
14598
2.80k
  if (out) {
14599
2.80k
    ada_log("url_aggregator::set_href, parsed ", out->to_string());
14600
    // TODO: Figure out why the following line puts test to never finish.
14601
2.80k
    *this = *out;
14602
2.80k
  }
14603
14604
2.80k
  return out.has_value();
14605
2.80k
}
14606
14607
23.2k
ada_really_inline bool url_aggregator::parse_host(std::string_view input) {
14608
23.2k
  ada_log("url_aggregator:parse_host \"", input, "\" [", input.size(),
14609
23.2k
          " bytes]");
14610
23.2k
  ADA_ASSERT_TRUE(validate());
14611
23.2k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14612
23.2k
  if (input.empty()) {
14613
10
    return is_valid = false;
14614
10
  }  // technically unnecessary.
14615
  // If input starts with U+005B ([), then:
14616
23.2k
  if (input[0] == '[') {
14617
    // If input does not end with U+005D (]), validation error, return failure.
14618
605
    if (input.back() != ']') {
14619
209
      return is_valid = false;
14620
209
    }
14621
396
    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
396
    input.remove_prefix(1);
14626
396
    input.remove_suffix(1);
14627
396
    return parse_ipv6(input);
14628
605
  }
14629
14630
  // If isNotSpecial is true, then return the result of opaque-host parsing
14631
  // input.
14632
22.6k
  if (!is_special()) {
14633
247
    return parse_opaque_host(input);
14634
247
  }
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
22.4k
  const uint64_t fast_result = checkers::try_parse_ipv4_fast(input);
14647
22.4k
  if (fast_result < checkers::ipv4_fast_fail) {
14648
    // Fast path succeeded - input is pure decimal IPv4
14649
48
    if (!input.empty() && input.back() == '.') {
14650
24
      update_base_hostname(input.substr(0, input.size() - 1));
14651
24
    } else {
14652
24
      update_base_hostname(input);
14653
24
    }
14654
48
    host_type = IPV4;
14655
48
    ada_log("parse_host fast path decimal ipv4");
14656
48
    ADA_ASSERT_TRUE(validate());
14657
48
    return true;
14658
48
  }
14659
22.3k
  uint8_t is_forbidden_or_upper =
14660
22.3k
      unicode::contains_forbidden_domain_code_point_or_upper(input.data(),
14661
22.3k
                                                             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
22.3k
  if (is_forbidden_or_upper == 0 &&
14669
13.7k
      input.find("xn-") == std::string_view::npos) {
14670
    // fast path
14671
13.4k
    update_base_hostname(input);
14672
14673
    // Check for other IPv4 formats (hex, octal, etc.)
14674
13.4k
    if (checkers::is_ipv4(get_hostname())) {
14675
1.51k
      ada_log("parse_host fast path ipv4");
14676
1.51k
      return parse_ipv4(get_hostname(), true);
14677
1.51k
    }
14678
11.9k
    ada_log("parse_host fast path ", get_hostname());
14679
11.9k
    return true;
14680
13.4k
  }
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
8.85k
  ada_log("parse_host calling to_ascii");
14686
8.85k
  std::optional<std::string> host = std::string(get_hostname());
14687
8.85k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
14688
8.85k
  if (!is_valid) {
14689
4.27k
    ada_log("parse_host to_ascii returns false");
14690
4.27k
    return is_valid = false;
14691
4.27k
  }
14692
4.58k
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
14693
4.58k
          " bytes]");
14694
14695
4.58k
  if (std::ranges::any_of(host.value(),
14696
4.58k
                          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
4.58k
  if (checkers::is_ipv4(host.value())) {
14703
622
    ada_log("parse_host got ipv4 ", *host);
14704
622
    return parse_ipv4(host.value(), false);
14705
622
  }
14706
14707
3.96k
  update_base_hostname(host.value());
14708
3.96k
  ADA_ASSERT_TRUE(validate());
14709
3.96k
  return true;
14710
4.58k
}
14711
14712
template <bool override_hostname>
14713
16.5k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14714
16.5k
  ada_log("url_aggregator::set_host_or_hostname ", input);
14715
16.5k
  ADA_ASSERT_TRUE(validate());
14716
16.5k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14717
16.5k
  if (has_opaque_path) {
14718
0
    return false;
14719
0
  }
14720
14721
16.5k
  std::string previous_host(get_hostname());
14722
16.5k
  uint32_t previous_port = components.port;
14723
14724
16.5k
  size_t host_end_pos = input.find('#');
14725
16.5k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14726
16.5k
                                      ? host_end_pos
14727
16.5k
                                      : input.size());
14728
16.5k
  helpers::remove_ascii_tab_or_newline(_host);
14729
16.5k
  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
16.5k
  if (type != ada::scheme::type::FILE) {
14734
15.1k
    std::string_view host_view(_host.data(), _host.length());
14735
15.1k
    auto [location, found_colon] =
14736
15.1k
        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
15.1k
    if (found_colon) {
14742
      // If buffer is the empty string, host-missing validation error, return
14743
      // failure.
14744
6.82k
      std::string_view host_buffer = host_view.substr(0, location);
14745
6.82k
      if (host_buffer.empty()) {
14746
24
        return false;
14747
24
      }
14748
14749
      // If state override is given and state override is hostname state, then
14750
      // return failure.
14751
6.80k
      if constexpr (override_hostname) {
14752
3.40k
        return false;
14753
3.40k
      }
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
6.80k
      if (!succeeded) {
14758
383
        update_base_hostname(previous_host);
14759
383
        update_base_port(previous_port);
14760
383
        return false;
14761
383
      }
14762
14763
      // Set url's host to host, buffer to the empty string, and state to port
14764
      // state.
14765
6.41k
      std::string_view port_buffer = new_host.substr(location + 1);
14766
6.41k
      if (!port_buffer.empty()) {
14767
2.61k
        set_port(port_buffer);
14768
2.61k
      }
14769
6.41k
      return true;
14770
6.80k
    }
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
8.36k
    else {
14775
      // If url is special and host_view is the empty string, host-missing
14776
      // validation error, return failure.
14777
8.36k
      if (host_view.empty() && is_special()) {
14778
1.50k
        return false;
14779
1.50k
      }
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
6.85k
      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
6.85k
      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
6.85k
      bool succeeded = parse_host(host_view);
14801
6.85k
      if (!succeeded) {
14802
3.08k
        update_base_hostname(previous_host);
14803
3.08k
        update_base_port(previous_port);
14804
3.08k
        return false;
14805
3.77k
      } else if (has_dash_dot()) {
14806
        // Should remove dash_dot from pathname
14807
0
        delete_dash_dot();
14808
0
      }
14809
3.77k
      return true;
14810
6.85k
    }
14811
15.1k
  }
14812
14813
1.36k
  size_t location = new_host.find_first_of("/\\?");
14814
1.36k
  if (location != std::string_view::npos) {
14815
1.24k
    new_host.remove_suffix(new_host.length() - location);
14816
1.24k
  }
14817
14818
1.36k
  if (new_host.empty()) {
14819
    // Set url's host to the empty string.
14820
0
    clear_hostname();
14821
1.36k
  } else {
14822
    // Let host be the result of host parsing buffer with url is not special.
14823
1.36k
    if (!parse_host(new_host)) {
14824
1.36k
      update_base_hostname(previous_host);
14825
1.36k
      update_base_port(previous_port);
14826
1.36k
      return false;
14827
1.36k
    }
14828
14829
    // If host is "localhost", then set host to the empty string.
14830
4
    if (helpers::substring(buffer, components.host_start,
14831
4
                           components.host_end) == "localhost") {
14832
0
      clear_hostname();
14833
0
    }
14834
4
  }
14835
4
  ADA_ASSERT_TRUE(validate());
14836
4
  return true;
14837
1.36k
}
bool ada::url_aggregator::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14713
8.27k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14714
8.27k
  ada_log("url_aggregator::set_host_or_hostname ", input);
14715
8.27k
  ADA_ASSERT_TRUE(validate());
14716
8.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14717
8.27k
  if (has_opaque_path) {
14718
0
    return false;
14719
0
  }
14720
14721
8.27k
  std::string previous_host(get_hostname());
14722
8.27k
  uint32_t previous_port = components.port;
14723
14724
8.27k
  size_t host_end_pos = input.find('#');
14725
8.27k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14726
8.27k
                                      ? host_end_pos
14727
8.27k
                                      : input.size());
14728
8.27k
  helpers::remove_ascii_tab_or_newline(_host);
14729
8.27k
  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
8.27k
  if (type != ada::scheme::type::FILE) {
14734
7.59k
    std::string_view host_view(_host.data(), _host.length());
14735
7.59k
    auto [location, found_colon] =
14736
7.59k
        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
7.59k
    if (found_colon) {
14742
      // If buffer is the empty string, host-missing validation error, return
14743
      // failure.
14744
3.41k
      std::string_view host_buffer = host_view.substr(0, location);
14745
3.41k
      if (host_buffer.empty()) {
14746
12
        return false;
14747
12
      }
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
3.40k
      bool succeeded = parse_host(host_buffer);
14757
3.40k
      if (!succeeded) {
14758
383
        update_base_hostname(previous_host);
14759
383
        update_base_port(previous_port);
14760
383
        return false;
14761
383
      }
14762
14763
      // Set url's host to host, buffer to the empty string, and state to port
14764
      // state.
14765
3.01k
      std::string_view port_buffer = new_host.substr(location + 1);
14766
3.01k
      if (!port_buffer.empty()) {
14767
2.61k
        set_port(port_buffer);
14768
2.61k
      }
14769
3.01k
      return true;
14770
3.40k
    }
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
4.18k
    else {
14775
      // If url is special and host_view is the empty string, host-missing
14776
      // validation error, return failure.
14777
4.18k
      if (host_view.empty() && is_special()) {
14778
751
        return false;
14779
751
      }
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
3.42k
      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
3.42k
      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
3.42k
      bool succeeded = parse_host(host_view);
14801
3.42k
      if (!succeeded) {
14802
1.54k
        update_base_hostname(previous_host);
14803
1.54k
        update_base_port(previous_port);
14804
1.54k
        return false;
14805
1.88k
      } else if (has_dash_dot()) {
14806
        // Should remove dash_dot from pathname
14807
0
        delete_dash_dot();
14808
0
      }
14809
1.88k
      return true;
14810
3.42k
    }
14811
7.59k
  }
14812
14813
683
  size_t location = new_host.find_first_of("/\\?");
14814
683
  if (location != std::string_view::npos) {
14815
622
    new_host.remove_suffix(new_host.length() - location);
14816
622
  }
14817
14818
683
  if (new_host.empty()) {
14819
    // Set url's host to the empty string.
14820
0
    clear_hostname();
14821
683
  } else {
14822
    // Let host be the result of host parsing buffer with url is not special.
14823
683
    if (!parse_host(new_host)) {
14824
681
      update_base_hostname(previous_host);
14825
681
      update_base_port(previous_port);
14826
681
      return false;
14827
681
    }
14828
14829
    // If host is "localhost", then set host to the empty string.
14830
2
    if (helpers::substring(buffer, components.host_start,
14831
2
                           components.host_end) == "localhost") {
14832
0
      clear_hostname();
14833
0
    }
14834
2
  }
14835
2
  ADA_ASSERT_TRUE(validate());
14836
2
  return true;
14837
683
}
bool ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14713
8.27k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14714
8.27k
  ada_log("url_aggregator::set_host_or_hostname ", input);
14715
8.27k
  ADA_ASSERT_TRUE(validate());
14716
8.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14717
8.27k
  if (has_opaque_path) {
14718
0
    return false;
14719
0
  }
14720
14721
8.27k
  std::string previous_host(get_hostname());
14722
8.27k
  uint32_t previous_port = components.port;
14723
14724
8.27k
  size_t host_end_pos = input.find('#');
14725
8.27k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14726
8.27k
                                      ? host_end_pos
14727
8.27k
                                      : input.size());
14728
8.27k
  helpers::remove_ascii_tab_or_newline(_host);
14729
8.27k
  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
8.27k
  if (type != ada::scheme::type::FILE) {
14734
7.59k
    std::string_view host_view(_host.data(), _host.length());
14735
7.59k
    auto [location, found_colon] =
14736
7.59k
        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
7.59k
    if (found_colon) {
14742
      // If buffer is the empty string, host-missing validation error, return
14743
      // failure.
14744
3.41k
      std::string_view host_buffer = host_view.substr(0, location);
14745
3.41k
      if (host_buffer.empty()) {
14746
12
        return false;
14747
12
      }
14748
14749
      // If state override is given and state override is hostname state, then
14750
      // return failure.
14751
3.40k
      if constexpr (override_hostname) {
14752
3.40k
        return false;
14753
3.40k
      }
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
3.40k
      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
3.40k
      std::string_view port_buffer = new_host.substr(location + 1);
14766
3.40k
      if (!port_buffer.empty()) {
14767
0
        set_port(port_buffer);
14768
0
      }
14769
3.40k
      return true;
14770
3.40k
    }
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
4.18k
    else {
14775
      // If url is special and host_view is the empty string, host-missing
14776
      // validation error, return failure.
14777
4.18k
      if (host_view.empty() && is_special()) {
14778
751
        return false;
14779
751
      }
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
3.42k
      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
3.42k
      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
3.42k
      bool succeeded = parse_host(host_view);
14801
3.42k
      if (!succeeded) {
14802
1.54k
        update_base_hostname(previous_host);
14803
1.54k
        update_base_port(previous_port);
14804
1.54k
        return false;
14805
1.88k
      } else if (has_dash_dot()) {
14806
        // Should remove dash_dot from pathname
14807
0
        delete_dash_dot();
14808
0
      }
14809
1.88k
      return true;
14810
3.42k
    }
14811
7.59k
  }
14812
14813
683
  size_t location = new_host.find_first_of("/\\?");
14814
683
  if (location != std::string_view::npos) {
14815
622
    new_host.remove_suffix(new_host.length() - location);
14816
622
  }
14817
14818
683
  if (new_host.empty()) {
14819
    // Set url's host to the empty string.
14820
0
    clear_hostname();
14821
683
  } else {
14822
    // Let host be the result of host parsing buffer with url is not special.
14823
683
    if (!parse_host(new_host)) {
14824
681
      update_base_hostname(previous_host);
14825
681
      update_base_port(previous_port);
14826
681
      return false;
14827
681
    }
14828
14829
    // If host is "localhost", then set host to the empty string.
14830
2
    if (helpers::substring(buffer, components.host_start,
14831
2
                           components.host_end) == "localhost") {
14832
0
      clear_hostname();
14833
0
    }
14834
2
  }
14835
2
  ADA_ASSERT_TRUE(validate());
14836
2
  return true;
14837
683
}
14838
14839
8.27k
bool url_aggregator::set_host(const std::string_view input) {
14840
8.27k
  ada_log("url_aggregator::set_host '", input, "'");
14841
8.27k
  ADA_ASSERT_TRUE(validate());
14842
8.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14843
8.27k
  return set_host_or_hostname<false>(input);
14844
8.27k
}
14845
14846
8.27k
bool url_aggregator::set_hostname(const std::string_view input) {
14847
8.27k
  ada_log("url_aggregator::set_hostname '", input, "'");
14848
8.27k
  ADA_ASSERT_TRUE(validate());
14849
8.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14850
8.27k
  return set_host_or_hostname<true>(input);
14851
8.27k
}
14852
14853
11.0k
[[nodiscard]] std::string url_aggregator::get_origin() const {
14854
11.0k
  ada_log("url_aggregator::get_origin");
14855
11.0k
  if (is_special()) {
14856
    // Return a new opaque origin.
14857
9.84k
    if (type == scheme::FILE) {
14858
1.26k
      return "null";
14859
1.26k
    }
14860
14861
8.57k
    return helpers::concat(get_protocol(), "//", get_host());
14862
9.84k
  }
14863
14864
1.23k
  if (get_protocol() == "blob:") {
14865
428
    std::string_view path = get_pathname();
14866
428
    if (!path.empty()) {
14867
420
      auto out = ada::parse<ada::url_aggregator>(path);
14868
420
      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
15
        return helpers::concat(out->get_protocol(), "//", out->get_host());
14872
15
      }
14873
420
    }
14874
428
  }
14875
14876
  // Return a new opaque origin.
14877
1.22k
  return "null";
14878
1.23k
}
14879
14880
[[nodiscard]] std::string_view url_aggregator::get_username() const
14881
14.3k
    ada_lifetime_bound {
14882
14.3k
  ada_log("url_aggregator::get_username");
14883
14.3k
  if (has_non_empty_username()) {
14884
13.6k
    return helpers::substring(buffer, components.protocol_end + 2,
14885
13.6k
                              components.username_end);
14886
13.6k
  }
14887
685
  return "";
14888
14.3k
}
14889
14890
[[nodiscard]] std::string_view url_aggregator::get_password() const
14891
14.3k
    ada_lifetime_bound {
14892
14.3k
  ada_log("url_aggregator::get_password");
14893
14.3k
  if (has_non_empty_password()) {
14894
13.6k
    return helpers::substring(buffer, components.username_end + 1,
14895
13.6k
                              components.host_start);
14896
13.6k
  }
14897
685
  return "";
14898
14.3k
}
14899
14900
[[nodiscard]] std::string_view url_aggregator::get_port() const
14901
8.27k
    ada_lifetime_bound {
14902
8.27k
  ada_log("url_aggregator::get_port");
14903
8.27k
  if (components.port == url_components::omitted) {
14904
7.32k
    return "";
14905
7.32k
  }
14906
956
  return helpers::substring(buffer, components.host_end + 1,
14907
956
                            components.pathname_start);
14908
8.27k
}
14909
14910
[[nodiscard]] std::string_view url_aggregator::get_hash() const
14911
14.3k
    ada_lifetime_bound {
14912
14.3k
  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
14.3k
  if (components.hash_start == url_components::omitted) {
14916
2
    return "";
14917
2
  }
14918
14.3k
  if (buffer.size() - components.hash_start <= 1) {
14919
58
    return "";
14920
58
  }
14921
14.2k
  return helpers::substring(buffer, components.hash_start);
14922
14.3k
}
14923
14924
[[nodiscard]] std::string_view url_aggregator::get_host() const
14925
22.9k
    ada_lifetime_bound {
14926
22.9k
  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
22.9k
  size_t start = components.host_start;
14931
22.9k
  if (components.host_end > components.host_start &&
14932
22.9k
      buffer[components.host_start] == '@') {
14933
21.4k
    start++;
14934
21.4k
  }
14935
  // if we have an empty host, then the space between components.host_end and
14936
  // components.pathname_start may be occupied by /.
14937
22.9k
  if (start == components.host_end) {
14938
0
    return {};
14939
0
  }
14940
22.9k
  return helpers::substring(buffer, start, components.pathname_start);
14941
22.9k
}
14942
14943
[[nodiscard]] std::string_view url_aggregator::get_hostname() const
14944
49.1k
    ada_lifetime_bound {
14945
49.1k
  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
49.1k
  size_t start = components.host_start;
14950
  // So host_start is not where the host begins.
14951
49.1k
  if (components.host_end > components.host_start &&
14952
47.7k
      buffer[components.host_start] == '@') {
14953
34.1k
    start++;
14954
34.1k
  }
14955
49.1k
  return helpers::substring(buffer, start, components.host_end);
14956
49.1k
}
14957
14958
[[nodiscard]] std::string_view url_aggregator::get_search() const
14959
14.3k
    ada_lifetime_bound {
14960
14.3k
  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
14.3k
  if (components.search_start == url_components::omitted) {
14964
2
    return "";
14965
2
  }
14966
14.3k
  auto ending_index = uint32_t(buffer.size());
14967
14.3k
  if (components.hash_start != url_components::omitted) {
14968
14.3k
    ending_index = components.hash_start;
14969
14.3k
  }
14970
14.3k
  if (ending_index - components.search_start <= 1) {
14971
56
    return "";
14972
56
  }
14973
14.2k
  return helpers::substring(buffer, components.search_start, ending_index);
14974
14.3k
}
14975
14976
[[nodiscard]] std::string_view url_aggregator::get_protocol() const
14977
26.9k
    ada_lifetime_bound {
14978
26.9k
  ada_log("url_aggregator::get_protocol");
14979
26.9k
  return helpers::substring(buffer, 0, components.protocol_end);
14980
26.9k
}
14981
14982
8.27k
[[nodiscard]] std::string ada::url_aggregator::to_string() const {
14983
8.27k
  ada_log("url_aggregator::to_string buffer:", buffer, " [", buffer.size(),
14984
8.27k
          " bytes]");
14985
8.27k
  if (!is_valid) {
14986
2.23k
    return "null";
14987
2.23k
  }
14988
14989
6.04k
  std::string answer;
14990
6.04k
  auto back = std::back_insert_iterator(answer);
14991
6.04k
  answer.append("{\n");
14992
14993
6.04k
  answer.append("\t\"buffer\":\"");
14994
6.04k
  helpers::encode_json(buffer, back);
14995
6.04k
  answer.append("\",\n");
14996
14997
6.04k
  answer.append("\t\"protocol\":\"");
14998
6.04k
  helpers::encode_json(get_protocol(), back);
14999
6.04k
  answer.append("\",\n");
15000
15001
6.04k
  if (has_credentials()) {
15002
6.03k
    answer.append("\t\"username\":\"");
15003
6.03k
    helpers::encode_json(get_username(), back);
15004
6.03k
    answer.append("\",\n");
15005
6.03k
    answer.append("\t\"password\":\"");
15006
6.03k
    helpers::encode_json(get_password(), back);
15007
6.03k
    answer.append("\",\n");
15008
6.03k
  }
15009
15010
6.04k
  answer.append("\t\"host\":\"");
15011
6.04k
  helpers::encode_json(get_host(), back);
15012
6.04k
  answer.append("\",\n");
15013
15014
6.04k
  answer.append("\t\"path\":\"");
15015
6.04k
  helpers::encode_json(get_pathname(), back);
15016
6.04k
  answer.append("\",\n");
15017
6.04k
  answer.append("\t\"opaque path\":");
15018
6.04k
  answer.append((has_opaque_path ? "true" : "false"));
15019
6.04k
  answer.append(",\n");
15020
15021
6.04k
  if (components.search_start != url_components::omitted) {
15022
6.03k
    answer.append("\t\"query\":\"");
15023
6.03k
    helpers::encode_json(get_search(), back);
15024
6.03k
    answer.append("\",\n");
15025
6.03k
  }
15026
6.04k
  if (components.hash_start != url_components::omitted) {
15027
6.03k
    answer.append("\t\"fragment\":\"");
15028
6.03k
    helpers::encode_json(get_hash(), back);
15029
6.03k
    answer.append("\",\n");
15030
6.03k
  }
15031
15032
48.3k
  auto convert_offset_to_string = [](uint32_t offset) -> std::string {
15033
48.3k
    if (offset == url_components::omitted) {
15034
5.08k
      return "null";
15035
43.2k
    } else {
15036
43.2k
      return std::to_string(offset);
15037
43.2k
    }
15038
48.3k
  };
15039
15040
6.04k
  answer.append("\t\"protocol_end\":");
15041
6.04k
  answer.append(convert_offset_to_string(components.protocol_end));
15042
6.04k
  answer.append(",\n");
15043
15044
6.04k
  answer.append("\t\"username_end\":");
15045
6.04k
  answer.append(convert_offset_to_string(components.username_end));
15046
6.04k
  answer.append(",\n");
15047
15048
6.04k
  answer.append("\t\"host_start\":");
15049
6.04k
  answer.append(convert_offset_to_string(components.host_start));
15050
6.04k
  answer.append(",\n");
15051
15052
6.04k
  answer.append("\t\"host_end\":");
15053
6.04k
  answer.append(convert_offset_to_string(components.host_end));
15054
6.04k
  answer.append(",\n");
15055
15056
6.04k
  answer.append("\t\"port\":");
15057
6.04k
  answer.append(convert_offset_to_string(components.port));
15058
6.04k
  answer.append(",\n");
15059
15060
6.04k
  answer.append("\t\"pathname_start\":");
15061
6.04k
  answer.append(convert_offset_to_string(components.pathname_start));
15062
6.04k
  answer.append(",\n");
15063
15064
6.04k
  answer.append("\t\"search_start\":");
15065
6.04k
  answer.append(convert_offset_to_string(components.search_start));
15066
6.04k
  answer.append(",\n");
15067
15068
6.04k
  answer.append("\t\"hash_start\":");
15069
6.04k
  answer.append(convert_offset_to_string(components.hash_start));
15070
6.04k
  answer.append("\n}");
15071
15072
6.04k
  return answer;
15073
8.27k
}
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
2.13k
bool url_aggregator::parse_ipv4(std::string_view input, bool in_place) {
15083
2.13k
  ada_log("parse_ipv4 ", input, " [", input.size(),
15084
2.13k
          " bytes], overlaps with buffer: ",
15085
2.13k
          helpers::overlaps(input, buffer) ? "yes" : "no");
15086
2.13k
  ADA_ASSERT_TRUE(validate());
15087
2.13k
  const bool trailing_dot = (input.back() == '.');
15088
2.13k
  if (trailing_dot) {
15089
59
    input.remove_suffix(1);
15090
59
  }
15091
2.13k
  size_t digit_count{0};
15092
2.13k
  int pure_decimal_count = 0;  // entries that are decimal
15093
2.13k
  uint64_t ipv4{0};
15094
  // we could unroll for better performance?
15095
2.58k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
15096
2.55k
    uint32_t
15097
2.55k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
15098
2.55k
    bool is_hex = checkers::has_hex_prefix(input);
15099
2.55k
    if (is_hex && ((input.length() == 2) ||
15100
777
                   ((input.length() > 2) && (input[2] == '.')))) {
15101
      // special case
15102
47
      segment_result = 0;
15103
47
      input.remove_prefix(2);
15104
2.51k
    } else {
15105
2.51k
      std::from_chars_result r{};
15106
2.51k
      if (is_hex) {
15107
762
        ada_log("parse_ipv4 trying to parse hex number");
15108
762
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
15109
762
                            segment_result, 16);
15110
1.75k
      } else if ((input.length() >= 2) && input[0] == '0' &&
15111
513
                 checkers::is_digit(input[1])) {
15112
421
        ada_log("parse_ipv4 trying to parse octal number");
15113
421
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
15114
421
                            segment_result, 8);
15115
1.32k
      } else {
15116
1.32k
        ada_log("parse_ipv4 trying to parse decimal number");
15117
1.32k
        pure_decimal_count++;
15118
1.32k
        r = std::from_chars(input.data(), input.data() + input.size(),
15119
1.32k
                            segment_result, 10);
15120
1.32k
      }
15121
2.51k
      if (r.ec != std::errc()) {
15122
407
        ada_log("parse_ipv4 parsing failed");
15123
407
        return is_valid = false;
15124
407
      }
15125
2.10k
      ada_log("parse_ipv4 parsed ", segment_result);
15126
2.10k
      input.remove_prefix(r.ptr - input.data());
15127
2.10k
    }
15128
2.15k
    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
1.53k
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
15133
39
        return is_valid = false;
15134
39
      }
15135
1.50k
      ipv4 <<= (32 - digit_count * 8);
15136
1.50k
      ipv4 |= segment_result;
15137
1.50k
      goto final;
15138
1.53k
    } else {
15139
      // There is more, so that the value must no be larger than 255
15140
      // and we must have a '.'.
15141
613
      if ((segment_result > 255) || (input[0] != '.')) {
15142
168
        return is_valid = false;
15143
168
      }
15144
445
      ipv4 <<= 8;
15145
445
      ipv4 |= segment_result;
15146
445
      input.remove_prefix(1);  // remove '.'
15147
445
    }
15148
2.15k
  }
15149
24
  if ((digit_count != 4) || (!input.empty())) {
15150
24
    ada_log("parse_ipv4 found invalid (more than 4 numbers or empty) ");
15151
24
    return is_valid = false;
15152
24
  }
15153
1.50k
final:
15154
1.50k
  ada_log("url_aggregator::parse_ipv4 completed ", get_href(),
15155
1.50k
          " host: ", get_host());
15156
15157
  // We could also check r.ptr to see where the parsing ended.
15158
1.50k
  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
1.50k
  } else {
15165
1.50k
    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
1.50k
    update_base_hostname(
15171
1.50k
        ada::serializers::ipv4(ipv4));  // We have to reserialize the address.
15172
1.50k
  }
15173
1.50k
  host_type = IPV4;
15174
1.50k
  ADA_ASSERT_TRUE(validate());
15175
1.50k
  return true;
15176
24
}
15177
15178
396
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
396
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
15184
396
  ADA_ASSERT_TRUE(validate());
15185
396
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15186
396
  if (input.empty()) {
15187
18
    return is_valid = false;
15188
18
  }
15189
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
15190
378
  std::array<uint16_t, 8> address{};
15191
15192
  // Let pieceIndex be 0.
15193
378
  int piece_index = 0;
15194
15195
  // Let compress be null.
15196
378
  std::optional<int> compress{};
15197
15198
  // Let pointer be a pointer for input.
15199
378
  std::string_view::iterator pointer = input.begin();
15200
15201
  // If c is U+003A (:), then:
15202
378
  if (input[0] == ':') {
15203
    // If remaining does not start with U+003A (:), validation error, return
15204
    // failure.
15205
82
    if (input.size() == 1 || input[1] != ':') {
15206
19
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
15207
19
      return is_valid = false;
15208
19
    }
15209
15210
    // Increase pointer by 2.
15211
63
    pointer += 2;
15212
15213
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
15214
63
    compress = ++piece_index;
15215
63
  }
15216
15217
  // While c is not the EOF code point:
15218
887
  while (pointer != input.end()) {
15219
    // If pieceIndex is 8, validation error, return failure.
15220
715
    if (piece_index == 8) {
15221
5
      ada_log("parse_ipv6 piece_index == 8");
15222
5
      return is_valid = false;
15223
5
    }
15224
15225
    // If c is U+003A (:), then:
15226
710
    if (*pointer == ':') {
15227
      // If compress is non-null, validation error, return failure.
15228
80
      if (compress.has_value()) {
15229
8
        ada_log("parse_ipv6 compress is non-null");
15230
8
        return is_valid = false;
15231
8
      }
15232
15233
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
15234
      // then continue.
15235
72
      pointer++;
15236
72
      compress = ++piece_index;
15237
72
      continue;
15238
80
    }
15239
15240
    // Let value and length be 0.
15241
630
    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
1.59k
    while (length < 4 && pointer != input.end() &&
15247
1.42k
           unicode::is_ascii_hex_digit(*pointer)) {
15248
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
15249
963
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
15250
963
      pointer++;
15251
963
      length++;
15252
963
    }
15253
15254
    // If c is U+002E (.), then:
15255
630
    if (pointer != input.end() && *pointer == '.') {
15256
      // If length is 0, validation error, return failure.
15257
71
      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
68
      pointer -= length;
15264
15265
      // If pieceIndex is greater than 6, validation error, return failure.
15266
68
      if (piece_index > 6) {
15267
3
        ada_log("parse_ipv6 piece_index > 6");
15268
3
        return is_valid = false;
15269
3
      }
15270
15271
      // Let numbersSeen be 0.
15272
65
      int numbers_seen = 0;
15273
15274
      // While c is not the EOF code point:
15275
158
      while (pointer != input.end()) {
15276
        // Let ipv4Piece be null.
15277
144
        std::optional<uint16_t> ipv4_piece{};
15278
15279
        // If numbersSeen is greater than 0, then:
15280
144
        if (numbers_seen > 0) {
15281
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
15282
          // pointer by 1.
15283
79
          if (*pointer == '.' && numbers_seen < 4) {
15284
71
            pointer++;
15285
71
          } else {
15286
            // Otherwise, validation error, return failure.
15287
8
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
15288
8
            return is_valid = false;
15289
8
          }
15290
79
        }
15291
15292
        // If c is not an ASCII digit, validation error, return failure.
15293
136
        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
299
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
15302
          // Let number be c interpreted as decimal number.
15303
206
          int number = *pointer - '0';
15304
15305
          // If ipv4Piece is null, then set ipv4Piece to number.
15306
206
          if (!ipv4_piece.has_value()) {
15307
110
            ipv4_piece = number;
15308
110
          }
15309
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
15310
96
          else if (ipv4_piece == 0) {
15311
3
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
15312
3
            return is_valid = false;
15313
3
          }
15314
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
15315
93
          else {
15316
93
            ipv4_piece = *ipv4_piece * 10 + number;
15317
93
          }
15318
15319
          // If ipv4Piece is greater than 255, validation error, return failure.
15320
203
          if (ipv4_piece > 255) {
15321
14
            ada_log("parse_ipv6 ipv4_piece > 255");
15322
14
            return is_valid = false;
15323
14
          }
15324
15325
          // Increase pointer by 1.
15326
189
          pointer++;
15327
189
        }
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
93
        address[piece_index] =
15333
93
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
15334
15335
        // Increase numbersSeen by 1.
15336
93
        numbers_seen++;
15337
15338
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
15339
93
        if (numbers_seen == 2 || numbers_seen == 4) {
15340
32
          piece_index++;
15341
32
        }
15342
93
      }
15343
15344
      // If numbersSeen is not 4, validation error, return failure.
15345
14
      if (numbers_seen != 4) {
15346
11
        return is_valid = false;
15347
11
      }
15348
15349
      // Break.
15350
3
      break;
15351
14
    }
15352
    // Otherwise, if c is U+003A (:):
15353
559
    else if ((pointer != input.end()) && (*pointer == ':')) {
15354
      // Increase pointer by 1.
15355
348
      pointer++;
15356
15357
      // If c is the EOF code point, validation error, return failure.
15358
348
      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
348
    }
15365
    // Otherwise, if c is not the EOF code point, validation error, return
15366
    // failure.
15367
211
    else if (pointer != input.end()) {
15368
100
      ada_log(
15369
100
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
15370
100
          "error, return failure");
15371
100
      return is_valid = false;
15372
100
    }
15373
15374
    // Set address[pieceIndex] to value.
15375
456
    address[piece_index] = value;
15376
15377
    // Increase pieceIndex by 1.
15378
456
    piece_index++;
15379
456
  }
15380
15381
  // If compress is non-null, then:
15382
175
  if (compress.has_value()) {
15383
    // Let swaps be pieceIndex - compress.
15384
117
    int swaps = piece_index - *compress;
15385
15386
    // Set pieceIndex to 7.
15387
117
    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
228
    while (piece_index != 0 && swaps > 0) {
15393
111
      std::swap(address[piece_index], address[*compress + swaps - 1]);
15394
111
      piece_index--;
15395
111
      swaps--;
15396
111
    }
15397
117
  }
15398
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
15399
  // return failure.
15400
58
  else if (piece_index != 8) {
15401
49
    ada_log(
15402
49
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
15403
49
        "error, return failure");
15404
49
    return is_valid = false;
15405
49
  }
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
126
  update_base_hostname(ada::serializers::ipv6(address));
15410
126
  ada_log("parse_ipv6 ", get_hostname());
15411
126
  ADA_ASSERT_TRUE(validate());
15412
126
  host_type = IPV6;
15413
126
  return true;
15414
175
}
15415
15416
247
bool url_aggregator::parse_opaque_host(std::string_view input) {
15417
247
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
15418
247
  ADA_ASSERT_TRUE(validate());
15419
247
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15420
247
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
15421
21
    return is_valid = false;
15422
21
  }
15423
15424
  // Return the result of running UTF-8 percent-encode on input using the C0
15425
  // control percent-encode set.
15426
226
  size_t idx = ada::unicode::percent_encode_index(
15427
226
      input, character_sets::C0_CONTROL_PERCENT_ENCODE);
15428
226
  if (idx == input.size()) {
15429
111
    update_base_hostname(input);
15430
115
  } else {
15431
    // We only create a temporary string if we need to.
15432
115
    update_base_hostname(ada::unicode::percent_encode(
15433
115
        input, character_sets::C0_CONTROL_PERCENT_ENCODE, idx));
15434
115
  }
15435
226
  ADA_ASSERT_TRUE(validate());
15436
226
  return true;
15437
247
}
15438
15439
8.27k
[[nodiscard]] std::string url_aggregator::to_diagram() const {
15440
8.27k
  if (!is_valid) {
15441
2.23k
    return "invalid";
15442
2.23k
  }
15443
6.04k
  std::string answer;
15444
6.04k
  answer.append(buffer);
15445
6.04k
  answer.append(" [");
15446
6.04k
  answer.append(std::to_string(buffer.size()));
15447
6.04k
  answer.append(" bytes]");
15448
6.04k
  answer.append("\n");
15449
  // first line
15450
6.04k
  std::string line1;
15451
6.04k
  line1.resize(buffer.size(), ' ');
15452
6.04k
  if (components.hash_start != url_components::omitted) {
15453
6.03k
    line1[components.hash_start] = '|';
15454
6.03k
  }
15455
6.04k
  if (components.search_start != url_components::omitted) {
15456
6.03k
    line1[components.search_start] = '|';
15457
6.03k
  }
15458
6.04k
  if (components.pathname_start != buffer.size()) {
15459
6.04k
    line1[components.pathname_start] = '|';
15460
6.04k
  }
15461
6.04k
  if (components.host_end != buffer.size()) {
15462
6.04k
    line1[components.host_end] = '|';
15463
6.04k
  }
15464
6.04k
  if (components.host_start != buffer.size()) {
15465
6.04k
    line1[components.host_start] = '|';
15466
6.04k
  }
15467
6.04k
  if (components.username_end != buffer.size()) {
15468
6.04k
    line1[components.username_end] = '|';
15469
6.04k
  }
15470
6.04k
  if (components.protocol_end != buffer.size()) {
15471
6.04k
    line1[components.protocol_end] = '|';
15472
6.04k
  }
15473
6.04k
  answer.append(line1);
15474
6.04k
  answer.append("\n");
15475
15476
6.04k
  std::string line2 = line1;
15477
6.04k
  if (components.hash_start != url_components::omitted) {
15478
6.03k
    line2[components.hash_start] = '`';
15479
6.03k
    line1[components.hash_start] = ' ';
15480
15481
406k
    for (size_t i = components.hash_start + 1; i < line2.size(); i++) {
15482
400k
      line2[i] = '-';
15483
400k
    }
15484
6.03k
    line2.append(" hash_start");
15485
6.03k
    answer.append(line2);
15486
6.03k
    answer.append("\n");
15487
6.03k
  }
15488
15489
6.04k
  std::string line3 = line1;
15490
6.04k
  if (components.search_start != url_components::omitted) {
15491
6.03k
    line3[components.search_start] = '`';
15492
6.03k
    line1[components.search_start] = ' ';
15493
15494
815k
    for (size_t i = components.search_start + 1; i < line3.size(); i++) {
15495
809k
      line3[i] = '-';
15496
809k
    }
15497
6.03k
    line3.append(" search_start ");
15498
6.03k
    line3.append(std::to_string(components.search_start));
15499
6.03k
    answer.append(line3);
15500
6.03k
    answer.append("\n");
15501
6.03k
  }
15502
15503
6.04k
  std::string line4 = line1;
15504
6.04k
  if (components.pathname_start != buffer.size()) {
15505
6.04k
    line4[components.pathname_start] = '`';
15506
6.04k
    line1[components.pathname_start] = ' ';
15507
1.18M
    for (size_t i = components.pathname_start + 1; i < line4.size(); i++) {
15508
1.18M
      line4[i] = '-';
15509
1.18M
    }
15510
6.04k
    line4.append(" pathname_start ");
15511
6.04k
    line4.append(std::to_string(components.pathname_start));
15512
6.04k
    answer.append(line4);
15513
6.04k
    answer.append("\n");
15514
6.04k
  }
15515
15516
6.04k
  std::string line5 = line1;
15517
6.04k
  if (components.host_end != buffer.size()) {
15518
6.04k
    line5[components.host_end] = '`';
15519
6.04k
    line1[components.host_end] = ' ';
15520
15521
1.19M
    for (size_t i = components.host_end + 1; i < line5.size(); i++) {
15522
1.18M
      line5[i] = '-';
15523
1.18M
    }
15524
6.04k
    line5.append(" host_end ");
15525
6.04k
    line5.append(std::to_string(components.host_end));
15526
6.04k
    answer.append(line5);
15527
6.04k
    answer.append("\n");
15528
6.04k
  }
15529
15530
6.04k
  std::string line6 = line1;
15531
6.04k
  if (components.host_start != buffer.size()) {
15532
6.04k
    line6[components.host_start] = '`';
15533
6.04k
    line1[components.host_start] = ' ';
15534
15535
1.37M
    for (size_t i = components.host_start + 1; i < line6.size(); i++) {
15536
1.37M
      line6[i] = '-';
15537
1.37M
    }
15538
6.04k
    line6.append(" host_start ");
15539
6.04k
    line6.append(std::to_string(components.host_start));
15540
6.04k
    answer.append(line6);
15541
6.04k
    answer.append("\n");
15542
6.04k
  }
15543
15544
6.04k
  std::string line7 = line1;
15545
6.04k
  if (components.username_end != buffer.size()) {
15546
6.04k
    line7[components.username_end] = '`';
15547
6.04k
    line1[components.username_end] = ' ';
15548
15549
1.85M
    for (size_t i = components.username_end + 1; i < line7.size(); i++) {
15550
1.85M
      line7[i] = '-';
15551
1.85M
    }
15552
6.04k
    line7.append(" username_end ");
15553
6.04k
    line7.append(std::to_string(components.username_end));
15554
6.04k
    answer.append(line7);
15555
6.04k
    answer.append("\n");
15556
6.04k
  }
15557
15558
6.04k
  std::string line8 = line1;
15559
6.04k
  if (components.protocol_end != buffer.size()) {
15560
6.04k
    line8[components.protocol_end] = '`';
15561
6.04k
    line1[components.protocol_end] = ' ';
15562
15563
2.34M
    for (size_t i = components.protocol_end + 1; i < line8.size(); i++) {
15564
2.34M
      line8[i] = '-';
15565
2.34M
    }
15566
6.04k
    line8.append(" protocol_end ");
15567
6.04k
    line8.append(std::to_string(components.protocol_end));
15568
6.04k
    answer.append(line8);
15569
6.04k
    answer.append("\n");
15570
6.04k
  }
15571
15572
6.04k
  if (components.hash_start == url_components::omitted) {
15573
2
    answer.append("note: hash omitted\n");
15574
2
  }
15575
6.04k
  if (components.search_start == url_components::omitted) {
15576
2
    answer.append("note: search omitted\n");
15577
2
  }
15578
6.04k
  if (components.protocol_end > buffer.size()) {
15579
0
    answer.append("warning: protocol_end overflows\n");
15580
0
  }
15581
6.04k
  if (components.username_end > buffer.size()) {
15582
0
    answer.append("warning: username_end overflows\n");
15583
0
  }
15584
6.04k
  if (components.host_start > buffer.size()) {
15585
0
    answer.append("warning: host_start overflows\n");
15586
0
  }
15587
6.04k
  if (components.host_end > buffer.size()) {
15588
0
    answer.append("warning: host_end overflows\n");
15589
0
  }
15590
6.04k
  if (components.pathname_start > buffer.size()) {
15591
0
    answer.append("warning: pathname_start overflows\n");
15592
0
  }
15593
6.04k
  return answer;
15594
8.27k
}
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
10.5k
inline void url_aggregator::consume_prepared_path(std::string_view input) {
15613
10.5k
  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
10.5k
  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
10.5k
  constexpr uint8_t need_encoding = 1;
15629
10.5k
  constexpr uint8_t backslash_char = 2;
15630
10.5k
  constexpr uint8_t dot_char = 4;
15631
10.5k
  constexpr uint8_t percent_char = 8;
15632
10.5k
  bool special = type != ada::scheme::NOT_SPECIAL;
15633
10.5k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
15634
1.50k
                                      checkers::is_windows_drive_letter(input));
15635
10.5k
  bool trivial_path =
15636
10.5k
      (special ? (accumulator == 0)
15637
10.5k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
15638
846
                  0)) &&
15639
2.02k
      (!may_need_slow_file_handling);
15640
10.5k
  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
2.29k
    if (input[0] != '.') {
15649
1.65k
      size_t slashdot = 0;
15650
1.65k
      bool dot_is_file = true;
15651
8.28k
      for (;;) {
15652
8.28k
        slashdot = input.find("/.", slashdot);
15653
8.28k
        if (slashdot == std::string_view::npos) {  // common case
15654
1.65k
          break;
15655
6.63k
        } else {  // uncommon
15656
          // only three cases matter: /./, /.. or a final /
15657
6.63k
          slashdot += 2;
15658
6.63k
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
15659
1.23k
                           input[slashdot] == '/');
15660
6.63k
        }
15661
8.28k
      }
15662
1.65k
      trivial_path = dot_is_file;
15663
1.65k
    }
15664
2.29k
  }
15665
10.5k
  if (trivial_path && is_at_path()) {
15666
2.63k
    ada_log("parse_path trivial");
15667
2.63k
    buffer += '/';
15668
2.63k
    buffer += input;
15669
2.63k
    return;
15670
2.63k
  }
15671
7.95k
  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
7.95k
  bool fast_path =
15677
7.95k
      (special &&
15678
7.18k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
15679
1.54k
      (type != ada::scheme::type::FILE);
15680
7.95k
  if (fast_path) {
15681
1.19k
    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
1.19k
    size_t previous_location = 0;  // We start at 0.
15687
16.0k
    do {
15688
16.0k
      size_t new_location = input.find('/', previous_location);
15689
      // std::string_view path_view = input;
15690
      //  We process the last segment separately:
15691
16.0k
      if (new_location == std::string_view::npos) {
15692
1.19k
        std::string_view path_view = input.substr(previous_location);
15693
1.19k
        if (path_view == "..") {  // The path ends with ..
15694
          // e.g., if you receive ".." with an empty path, you go to "/".
15695
159
          if (path.empty()) {
15696
61
            path = '/';
15697
61
            update_base_pathname(path);
15698
61
            return;
15699
61
          }
15700
          // Fast case where we have nothing to do:
15701
98
          if (path.back() == '/') {
15702
33
            update_base_pathname(path);
15703
33
            return;
15704
33
          }
15705
          // If you have the path "/joe/myfriend",
15706
          // then you delete 'myfriend'.
15707
65
          path.resize(path.rfind('/') + 1);
15708
65
          update_base_pathname(path);
15709
65
          return;
15710
98
        }
15711
1.03k
        path += '/';
15712
1.03k
        if (path_view != ".") {
15713
803
          path.append(path_view);
15714
803
        }
15715
1.03k
        update_base_pathname(path);
15716
1.03k
        return;
15717
14.8k
      } else {
15718
        // This is a non-final segment.
15719
14.8k
        std::string_view path_view =
15720
14.8k
            input.substr(previous_location, new_location - previous_location);
15721
14.8k
        previous_location = new_location + 1;
15722
14.8k
        if (path_view == "..") {
15723
3.71k
          size_t last_delimiter = path.rfind('/');
15724
3.71k
          if (last_delimiter != std::string::npos) {
15725
1.90k
            path.erase(last_delimiter);
15726
1.90k
          }
15727
11.1k
        } else if (path_view != ".") {
15728
9.49k
          path += '/';
15729
9.49k
          path.append(path_view);
15730
9.49k
        }
15731
14.8k
      }
15732
16.0k
    } while (true);
15733
6.75k
  } else {
15734
6.75k
    ada_log("parse_path slow");
15735
    // we have reached the general case
15736
6.75k
    bool needs_percent_encoding = (accumulator & 1);
15737
6.75k
    std::string path_buffer_tmp;
15738
41.4k
    do {
15739
41.4k
      size_t location = (special && (accumulator & 2))
15740
41.4k
                            ? input.find_first_of("/\\")
15741
41.4k
                            : input.find('/');
15742
41.4k
      std::string_view path_view = input;
15743
41.4k
      if (location != std::string_view::npos) {
15744
34.6k
        path_view.remove_suffix(path_view.size() - location);
15745
34.6k
        input.remove_prefix(location + 1);
15746
34.6k
      }
15747
      // path_buffer is either path_view or it might point at a percent encoded
15748
      // temporary string.
15749
41.4k
      std::string_view path_buffer =
15750
41.4k
          (needs_percent_encoding &&
15751
26.9k
           ada::unicode::percent_encode<false>(
15752
26.9k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
15753
41.4k
              ? path_buffer_tmp
15754
41.4k
              : path_view;
15755
41.4k
      if (unicode::is_double_dot_path_segment(path_buffer)) {
15756
10.0k
        helpers::shorten_path(path, type);
15757
10.0k
        if (location == std::string_view::npos) {
15758
748
          path += '/';
15759
748
        }
15760
31.4k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
15761
1.89k
                 (location == std::string_view::npos)) {
15762
166
        path += '/';
15763
166
      }
15764
      // Otherwise, if path_buffer is not a single-dot path segment, then:
15765
31.2k
      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
29.5k
        if (type == ada::scheme::type::FILE && path.empty() &&
15770
3.83k
            checkers::is_windows_drive_letter(path_buffer)) {
15771
140
          path += '/';
15772
140
          path += path_buffer[0];
15773
140
          path += ':';
15774
140
          path_buffer.remove_prefix(2);
15775
140
          path.append(path_buffer);
15776
29.3k
        } else {
15777
          // Append path_buffer to url's path.
15778
29.3k
          path += '/';
15779
29.3k
          path.append(path_buffer);
15780
29.3k
        }
15781
29.5k
      }
15782
41.4k
      if (location == std::string_view::npos) {
15783
6.75k
        update_base_pathname(path);
15784
6.75k
        return;
15785
6.75k
      }
15786
41.4k
    } while (true);
15787
6.75k
  }
15788
7.95k
}
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
0
ada::result<ada::url_aggregator>& get_instance(void* result) noexcept {
17397
0
  return *(ada::result<ada::url_aggregator>*)result;
17398
0
}
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
0
ada_string ada_string_create(const char* data, size_t length) {
17424
0
  ada_string out{};
17425
0
  out.data = data;
17426
0
  out.length = length;
17427
0
  return out;
17428
0
}
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
0
ada_url ada_parse(const char* input, size_t length) noexcept {
17461
0
  return new ada::result<ada::url_aggregator>(
17462
0
      ada::parse<ada::url_aggregator>(std::string_view(input, length)));
17463
0
}
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
0
bool ada_can_parse(const char* input, size_t length) noexcept {
17479
0
  return ada::can_parse(std::string_view(input, length));
17480
0
}
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
0
void ada_free(ada_url result) noexcept {
17489
0
  auto* r = (ada::result<ada::url_aggregator>*)result;
17490
0
  delete r;
17491
0
}
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
0
bool ada_is_valid(ada_url result) noexcept {
17499
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17500
0
  return r.has_value();
17501
0
}
17502
17503
// caller must free the result with ada_free_owned_string
17504
0
ada_owned_string ada_get_origin(ada_url result) noexcept {
17505
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17506
0
  ada_owned_string owned{};
17507
0
  if (!r) {
17508
0
    owned.data = nullptr;
17509
0
    owned.length = 0;
17510
0
    return owned;
17511
0
  }
17512
0
  std::string out = r->get_origin();
17513
0
  owned.length = out.size();
17514
0
  owned.data = new char[owned.length];
17515
0
  memcpy((void*)owned.data, out.data(), owned.length);
17516
0
  return owned;
17517
0
}
17518
17519
0
void ada_free_owned_string(ada_owned_string owned) noexcept {
17520
0
  delete[] owned.data;
17521
0
}
17522
17523
0
ada_string ada_get_href(ada_url result) noexcept {
17524
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17525
0
  if (!r) {
17526
0
    return ada_string_create(nullptr, 0);
17527
0
  }
17528
0
  std::string_view out = r->get_href();
17529
0
  return ada_string_create(out.data(), out.length());
17530
0
}
17531
17532
0
ada_string ada_get_username(ada_url result) noexcept {
17533
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17534
0
  if (!r) {
17535
0
    return ada_string_create(nullptr, 0);
17536
0
  }
17537
0
  std::string_view out = r->get_username();
17538
0
  return ada_string_create(out.data(), out.length());
17539
0
}
17540
17541
0
ada_string ada_get_password(ada_url result) noexcept {
17542
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17543
0
  if (!r) {
17544
0
    return ada_string_create(nullptr, 0);
17545
0
  }
17546
0
  std::string_view out = r->get_password();
17547
0
  return ada_string_create(out.data(), out.length());
17548
0
}
17549
17550
0
ada_string ada_get_port(ada_url result) noexcept {
17551
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17552
0
  if (!r) {
17553
0
    return ada_string_create(nullptr, 0);
17554
0
  }
17555
0
  std::string_view out = r->get_port();
17556
0
  return ada_string_create(out.data(), out.length());
17557
0
}
17558
17559
0
ada_string ada_get_hash(ada_url result) noexcept {
17560
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17561
0
  if (!r) {
17562
0
    return ada_string_create(nullptr, 0);
17563
0
  }
17564
0
  std::string_view out = r->get_hash();
17565
0
  return ada_string_create(out.data(), out.length());
17566
0
}
17567
17568
0
ada_string ada_get_host(ada_url result) noexcept {
17569
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17570
0
  if (!r) {
17571
0
    return ada_string_create(nullptr, 0);
17572
0
  }
17573
0
  std::string_view out = r->get_host();
17574
0
  return ada_string_create(out.data(), out.length());
17575
0
}
17576
17577
0
ada_string ada_get_hostname(ada_url result) noexcept {
17578
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17579
0
  if (!r) {
17580
0
    return ada_string_create(nullptr, 0);
17581
0
  }
17582
0
  std::string_view out = r->get_hostname();
17583
0
  return ada_string_create(out.data(), out.length());
17584
0
}
17585
17586
0
ada_string ada_get_pathname(ada_url result) noexcept {
17587
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17588
0
  if (!r) {
17589
0
    return ada_string_create(nullptr, 0);
17590
0
  }
17591
0
  std::string_view out = r->get_pathname();
17592
0
  return ada_string_create(out.data(), out.length());
17593
0
}
17594
17595
0
ada_string ada_get_search(ada_url result) noexcept {
17596
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17597
0
  if (!r) {
17598
0
    return ada_string_create(nullptr, 0);
17599
0
  }
17600
0
  std::string_view out = r->get_search();
17601
0
  return ada_string_create(out.data(), out.length());
17602
0
}
17603
17604
0
ada_string ada_get_protocol(ada_url result) noexcept {
17605
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17606
0
  if (!r) {
17607
0
    return ada_string_create(nullptr, 0);
17608
0
  }
17609
0
  std::string_view out = r->get_protocol();
17610
0
  return ada_string_create(out.data(), out.length());
17611
0
}
17612
17613
0
uint8_t ada_get_host_type(ada_url result) noexcept {
17614
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17615
0
  if (!r) {
17616
0
    return 0;
17617
0
  }
17618
0
  return r->host_type;
17619
0
}
17620
17621
0
uint8_t ada_get_scheme_type(ada_url result) noexcept {
17622
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17623
0
  if (!r) {
17624
0
    return 0;
17625
0
  }
17626
0
  return r->type;
17627
0
}
17628
17629
0
bool ada_set_href(ada_url result, const char* input, size_t length) noexcept {
17630
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17631
0
  if (!r) {
17632
0
    return false;
17633
0
  }
17634
0
  return r->set_href(std::string_view(input, length));
17635
0
}
17636
17637
0
bool ada_set_host(ada_url result, const char* input, size_t length) noexcept {
17638
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17639
0
  if (!r) {
17640
0
    return false;
17641
0
  }
17642
0
  return r->set_host(std::string_view(input, length));
17643
0
}
17644
17645
bool ada_set_hostname(ada_url result, const char* input,
17646
0
                      size_t length) noexcept {
17647
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17648
0
  if (!r) {
17649
0
    return false;
17650
0
  }
17651
0
  return r->set_hostname(std::string_view(input, length));
17652
0
}
17653
17654
bool ada_set_protocol(ada_url result, const char* input,
17655
0
                      size_t length) noexcept {
17656
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17657
0
  if (!r) {
17658
0
    return false;
17659
0
  }
17660
0
  return r->set_protocol(std::string_view(input, length));
17661
0
}
17662
17663
bool ada_set_username(ada_url result, const char* input,
17664
0
                      size_t length) noexcept {
17665
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17666
0
  if (!r) {
17667
0
    return false;
17668
0
  }
17669
0
  return r->set_username(std::string_view(input, length));
17670
0
}
17671
17672
bool ada_set_password(ada_url result, const char* input,
17673
0
                      size_t length) noexcept {
17674
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17675
0
  if (!r) {
17676
0
    return false;
17677
0
  }
17678
0
  return r->set_password(std::string_view(input, length));
17679
0
}
17680
17681
0
bool ada_set_port(ada_url result, const char* input, size_t length) noexcept {
17682
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17683
0
  if (!r) {
17684
0
    return false;
17685
0
  }
17686
0
  return r->set_port(std::string_view(input, length));
17687
0
}
17688
17689
bool ada_set_pathname(ada_url result, const char* input,
17690
0
                      size_t length) noexcept {
17691
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17692
0
  if (!r) {
17693
0
    return false;
17694
0
  }
17695
0
  return r->set_pathname(std::string_view(input, length));
17696
0
}
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
0
void ada_set_search(ada_url result, const char* input, size_t length) noexcept {
17706
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17707
0
  if (r) {
17708
0
    r->set_search(std::string_view(input, length));
17709
0
  }
17710
0
}
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
0
void ada_set_hash(ada_url result, const char* input, size_t length) noexcept {
17720
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17721
0
  if (r) {
17722
0
    r->set_hash(std::string_view(input, length));
17723
0
  }
17724
0
}
17725
17726
0
void ada_clear_port(ada_url result) noexcept {
17727
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17728
0
  if (r) {
17729
0
    r->clear_port();
17730
0
  }
17731
0
}
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
0
void ada_clear_hash(ada_url result) noexcept {
17740
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17741
0
  if (r) {
17742
0
    r->clear_hash();
17743
0
  }
17744
0
}
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
0
void ada_clear_search(ada_url result) noexcept {
17753
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17754
0
  if (r) {
17755
0
    r->clear_search();
17756
0
  }
17757
0
}
17758
17759
0
bool ada_has_credentials(ada_url result) noexcept {
17760
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17761
0
  if (!r) {
17762
0
    return false;
17763
0
  }
17764
0
  return r->has_credentials();
17765
0
}
17766
17767
0
bool ada_has_empty_hostname(ada_url result) noexcept {
17768
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17769
0
  if (!r) {
17770
0
    return false;
17771
0
  }
17772
0
  return r->has_empty_hostname();
17773
0
}
17774
17775
0
bool ada_has_hostname(ada_url result) noexcept {
17776
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17777
0
  if (!r) {
17778
0
    return false;
17779
0
  }
17780
0
  return r->has_hostname();
17781
0
}
17782
17783
0
bool ada_has_non_empty_username(ada_url result) noexcept {
17784
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17785
0
  if (!r) {
17786
0
    return false;
17787
0
  }
17788
0
  return r->has_non_empty_username();
17789
0
}
17790
17791
0
bool ada_has_non_empty_password(ada_url result) noexcept {
17792
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17793
0
  if (!r) {
17794
0
    return false;
17795
0
  }
17796
0
  return r->has_non_empty_password();
17797
0
}
17798
17799
0
bool ada_has_port(ada_url result) noexcept {
17800
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17801
0
  if (!r) {
17802
0
    return false;
17803
0
  }
17804
0
  return r->has_port();
17805
0
}
17806
17807
0
bool ada_has_password(ada_url result) noexcept {
17808
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17809
0
  if (!r) {
17810
0
    return false;
17811
0
  }
17812
0
  return r->has_password();
17813
0
}
17814
17815
0
bool ada_has_hash(ada_url result) noexcept {
17816
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17817
0
  if (!r) {
17818
0
    return false;
17819
0
  }
17820
0
  return r->has_hash();
17821
0
}
17822
17823
0
bool ada_has_search(ada_url result) noexcept {
17824
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17825
0
  if (!r) {
17826
0
    return false;
17827
0
  }
17828
0
  return r->has_search();
17829
0
}
17830
17831
// returns a pointer to the internal url_aggregator::url_components
17832
0
const ada_url_components* ada_get_components(ada_url result) noexcept {
17833
0
  static_assert(sizeof(ada_url_components) == sizeof(ada::url_components));
17834
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17835
0
  if (!r) {
17836
0
    return nullptr;
17837
0
  }
17838
0
  return reinterpret_cast<const ada_url_components*>(&r->get_components());
17839
0
}
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 */