Coverage Report

Created: 2026-02-26 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ada-url/build/singleheader/ada.cpp
Line
Count
Source
1
/* auto-generated on 2026-02-23 21:29:24 -0500. Do not edit! */
2
/* begin file src/ada.cpp */
3
#include "ada.h"
4
/* begin file src/checkers.cpp */
5
6
#include <algorithm>
7
#include <array>
8
#include <string_view>
9
10
namespace ada::checkers {
11
12
39.6k
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
39.6k
  if (view.ends_with('.')) {
21
1.48k
    view.remove_suffix(1);
22
1.48k
    if (view.empty()) {
23
572
      return false;
24
572
    }
25
1.48k
  }
26
39.0k
  char last_char = view.back();
27
39.0k
  bool possible_ipv4 = (last_char >= '0' && last_char <= '9') ||
28
34.7k
                       (last_char >= 'a' && last_char <= 'f') ||
29
27.9k
                       last_char == 'x';
30
39.0k
  if (!possible_ipv4) {
31
27.3k
    return false;
32
27.3k
  }
33
  // From the last character, find the last dot.
34
11.7k
  size_t last_dot = view.rfind('.');
35
11.7k
  if (last_dot != std::string_view::npos) {
36
    // We have at least one dot.
37
2.98k
    view = view.substr(last_dot + 1);
38
2.98k
  }
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
11.7k
  if (std::ranges::all_of(view, ada::checkers::is_digit)) {
43
3.02k
    return true;
44
3.02k
  }
45
  // It could be hex (0x), but not if there is a single character.
46
8.70k
  if (view.size() == 1) {
47
1.37k
    return false;
48
1.37k
  }
49
  // It must start with 0x.
50
7.33k
  if (!view.starts_with("0x")) {
51
5.30k
    return false;
52
5.30k
  }
53
  // We must allow "0x".
54
2.03k
  if (view.size() == 2) {
55
94
    return true;
56
94
  }
57
  // We have 0x followed by some characters, we need to check that they are
58
  // hexadecimals.
59
1.93k
  view.remove_prefix(2);
60
1.93k
  return std::ranges::all_of(view, ada::unicode::is_lowercase_hex);
61
2.03k
}
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
32.0k
    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
32.0k
  size_t i = 0;
94
32.0k
  uint8_t accumulator{};
95
148k
  for (; i + 7 < input.size(); i += 8) {
96
116k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])] |
97
116k
                           path_signature_table[uint8_t(input[i + 1])] |
98
116k
                           path_signature_table[uint8_t(input[i + 2])] |
99
116k
                           path_signature_table[uint8_t(input[i + 3])] |
100
116k
                           path_signature_table[uint8_t(input[i + 4])] |
101
116k
                           path_signature_table[uint8_t(input[i + 5])] |
102
116k
                           path_signature_table[uint8_t(input[i + 6])] |
103
116k
                           path_signature_table[uint8_t(input[i + 7])]);
104
116k
  }
105
142k
  for (; i < input.size(); i++) {
106
110k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])]);
107
110k
  }
108
32.0k
  return accumulator;
109
32.0k
}
110
111
ada_really_inline constexpr bool verify_dns_length(
112
9.00k
    std::string_view input) noexcept {
113
9.00k
  if (input.back() == '.') {
114
947
    if (input.size() > 254) return false;
115
8.05k
  } else if (input.size() > 253)
116
48
    return false;
117
118
8.94k
  size_t start = 0;
119
27.2k
  while (start < input.size()) {
120
20.3k
    auto dot_location = input.find('.', start);
121
    // If not found, it's likely the end of the domain
122
20.3k
    if (dot_location == std::string_view::npos) dot_location = input.size();
123
124
20.3k
    auto label_size = dot_location - start;
125
20.3k
    if (label_size > 63 || label_size == 0) return false;
126
127
18.3k
    start = dot_location + 1;
128
18.3k
  }
129
130
6.95k
  return true;
131
8.94k
}
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
10.5k
size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) {
151
10.5k
  const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
152
10.5k
  size_t pos = 0;
153
10.5k
  const char32_t* start{utf32_output};
154
156k
  while (pos < len) {
155
    // try to convert the next block of 16 ASCII bytes
156
148k
    if (pos + 16 <= len) {  // if it is safe to read 16 more
157
                            // bytes, check that they are ascii
158
104k
      uint64_t v1;
159
104k
      std::memcpy(&v1, data + pos, sizeof(uint64_t));
160
104k
      uint64_t v2;
161
104k
      std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
162
104k
      uint64_t v{v1 | v2};
163
104k
      if ((v & 0x8080808080808080) == 0) {
164
1.96k
        size_t final_pos = pos + 16;
165
33.3k
        while (pos < final_pos) {
166
31.4k
          *utf32_output++ = char32_t(buf[pos]);
167
31.4k
          pos++;
168
31.4k
        }
169
1.96k
        continue;
170
1.96k
      }
171
104k
    }
172
146k
    uint8_t leading_byte = data[pos];  // leading byte
173
146k
    if (leading_byte < 0b10000000) {
174
      // converting one ASCII byte !!!
175
63.5k
      *utf32_output++ = char32_t(leading_byte);
176
63.5k
      pos++;
177
82.6k
    } else if ((leading_byte & 0b11100000) == 0b11000000) {
178
      // We have a two-byte UTF-8
179
10.7k
      if (pos + 1 >= len) {
180
278
        return 0;
181
278
      }  // minimal bound checking
182
10.4k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
183
184
        return 0;
184
184
      }
185
      // range check
186
10.2k
      uint32_t code_point =
187
10.2k
          (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
188
10.2k
      if (code_point < 0x80 || 0x7ff < code_point) {
189
14
        return 0;
190
14
      }
191
10.2k
      *utf32_output++ = char32_t(code_point);
192
10.2k
      pos += 2;
193
71.8k
    } else if ((leading_byte & 0b11110000) == 0b11100000) {
194
      // We have a three-byte UTF-8
195
69.0k
      if (pos + 2 >= len) {
196
76
        return 0;
197
76
      }  // minimal bound checking
198
199
68.9k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
200
86
        return 0;
201
86
      }
202
68.8k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
203
18
        return 0;
204
18
      }
205
      // range check
206
68.8k
      uint32_t code_point = (leading_byte & 0b00001111) << 12 |
207
68.8k
                            (data[pos + 1] & 0b00111111) << 6 |
208
68.8k
                            (data[pos + 2] & 0b00111111);
209
68.8k
      if (code_point < 0x800 || 0xffff < code_point ||
210
68.8k
          (0xd7ff < code_point && code_point < 0xe000)) {
211
32
        return 0;
212
32
      }
213
68.8k
      *utf32_output++ = char32_t(code_point);
214
68.8k
      pos += 3;
215
68.8k
    } else if ((leading_byte & 0b11111000) == 0b11110000) {  // 0b11110000
216
      // we have a 4-byte UTF-8 word.
217
1.40k
      if (pos + 3 >= len) {
218
76
        return 0;
219
76
      }  // minimal bound checking
220
1.32k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
221
70
        return 0;
222
70
      }
223
1.25k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
224
22
        return 0;
225
22
      }
226
1.23k
      if ((data[pos + 3] & 0b11000000) != 0b10000000) {
227
22
        return 0;
228
22
      }
229
230
      // range check
231
1.21k
      uint32_t code_point = (leading_byte & 0b00000111) << 18 |
232
1.21k
                            (data[pos + 1] & 0b00111111) << 12 |
233
1.21k
                            (data[pos + 2] & 0b00111111) << 6 |
234
1.21k
                            (data[pos + 3] & 0b00111111);
235
1.21k
      if (code_point <= 0xffff || 0x10ffff < code_point) {
236
40
        return 0;
237
40
      }
238
1.17k
      *utf32_output++ = char32_t(code_point);
239
1.17k
      pos += 4;
240
1.41k
    } else {
241
1.41k
      return 0;
242
1.41k
    }
243
146k
  }
244
8.18k
  return utf32_output - start;
245
10.5k
}
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
10.5k
size_t utf32_length_from_utf8(const char* buf, size_t len) {
261
10.5k
  const int8_t* p = reinterpret_cast<const int8_t*>(buf);
262
381k
  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
381k
    return c > -65;
266
381k
  });
267
10.5k
}
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
201k
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
201k
  uint32_t len = std::size(table);
2800
201k
  uint32_t low = 0;
2801
201k
  uint32_t high = len - 1;
2802
2.69M
  while (low <= high) {
2803
2.58M
    uint32_t middle_index = (low + high) >> 1;  // cannot overflow
2804
2.58M
    uint32_t middle_value = table[middle_index][0];
2805
2.58M
    if (middle_value < key) {
2806
817k
      low = middle_index + 1;
2807
1.76M
    } else if (middle_value > key) {
2808
1.67M
      high = middle_index - 1;
2809
1.67M
    } else {
2810
89.4k
      return middle_index;  // perfect match
2811
89.4k
    }
2812
2.58M
  }
2813
112k
  return low == 0 ? 0 : low - 1;
2814
201k
}
2815
2816
6.78k
void ascii_map(char* input, size_t length) {
2817
20.3k
  auto broadcast = [](uint8_t v) -> uint64_t {
2818
20.3k
    return 0x101010101010101ull * v;
2819
20.3k
  };
2820
6.78k
  uint64_t broadcast_80 = broadcast(0x80);
2821
6.78k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
2822
6.78k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2823
6.78k
  size_t i = 0;
2824
2825
16.5k
  for (; i + 7 < length; i += 8) {
2826
9.75k
    uint64_t word{};
2827
9.75k
    memcpy(&word, input + i, sizeof(word));
2828
9.75k
    word ^=
2829
9.75k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2830
9.75k
    memcpy(input + i, &word, sizeof(word));
2831
9.75k
  }
2832
6.78k
  if (i < length) {
2833
6.25k
    uint64_t word{};
2834
6.25k
    memcpy(&word, input + i, length - i);
2835
6.25k
    word ^=
2836
6.25k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2837
6.25k
    memcpy(input + i, &word, length - i);
2838
6.25k
  }
2839
6.78k
}
2840
2841
// Map the characters according to IDNA, returning the empty string on error.
2842
13.3k
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
13.3k
  static std::u32string error = U"";
2857
13.3k
  std::u32string answer;
2858
13.3k
  answer.reserve(input.size());
2859
201k
  for (char32_t x : input) {
2860
201k
    size_t index = find_range_index(x);
2861
201k
    uint32_t descriptor = table[index][1];
2862
201k
    uint8_t code = uint8_t(descriptor);
2863
201k
    switch (code) {
2864
272
      case 0:
2865
272
        break;  // nothing to do, ignored
2866
119k
      case 1:
2867
119k
        answer.push_back(x);  // valid, we just copy it to output
2868
119k
        break;
2869
440
      case 2:
2870
440
        return error;  // disallowed
2871
      // case 3 :
2872
81.5k
      default:
2873
        // We have a mapping
2874
81.5k
        {
2875
81.5k
          size_t char_count = (descriptor >> 24);
2876
81.5k
          uint16_t char_index = uint16_t(descriptor >> 8);
2877
568k
          for (size_t idx = char_index; idx < char_index + char_count; idx++) {
2878
486k
            answer.push_back(mappings[idx]);
2879
486k
          }
2880
81.5k
        }
2881
201k
    }
2882
201k
  }
2883
12.9k
  return answer;
2884
13.3k
}
2885
}  // namespace ada::idna
2886
/* end file src/mapping.cpp */
2887
/* begin file src/normalization.cpp */
2888
/* begin file src/normalization_tables.cpp */
2889
// IDNA  17.0.0
2890
2891
// clang-format off
2892
#ifndef ADA_IDNA_NORMALIZATION_TABLES_H
2893
#define ADA_IDNA_NORMALIZATION_TABLES_H
2894
#include <cstdint>
2895
2896
/**
2897
 * Unicode Standard Annex #15
2898
 *
2899
 * UNICODE NORMALIZATION FORMS
2900
 * https://www.unicode.org/reports/tr15/
2901
 *
2902
 * See https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/data/data_norm.h for reference.
2903
 */
2904
2905
namespace ada::idna {
2906
2907
const uint8_t decomposition_index[4352] = {
2908
    0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  9,  10, 11, 12, 13, 14, 15, 7,  7,
2909
    7,  7,  7,  7,  7,  7,  7,  7,  16, 7,  17, 18, 19, 20, 21, 22, 23, 24, 7,
2910
    7,  7,  7,  7,  25, 7,  26, 27, 28, 29, 30, 31, 32, 33, 7,  7,  7,  7,  7,
2911
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2912
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2913
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2914
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2915
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2916
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  34, 35, 7,  7,  7,
2917
    36, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2918
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2919
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2920
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2921
    7,  7,  37, 38, 39, 40, 41, 42, 43, 7,  7,  7,  7,  7,  7,  7,  44, 7,  7,
2922
    7,  7,  7,  7,  7,  7,  45, 46, 7,  47, 48, 49, 7,  7,  7,  50, 7,  7,  7,
2923
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2924
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2925
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2926
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2927
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2928
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2929
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2930
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2931
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2932
    7,  7,  7,  7,  7,  7,  7,  7,  7,  51, 7,  52, 53, 54, 55, 56, 7,  7,  7,
2933
    7,  7,  7,  7,  7,  57, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  58,
2934
    59, 7,  60, 61, 62, 7,  7,  7,  7,  7,  7,  7,  7,  63, 7,  7,  7,  7,  7,
2935
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2936
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2937
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2938
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2939
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2940
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2941
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2942
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2943
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2944
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2945
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2946
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2947
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2948
    64, 65, 66, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2949
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2950
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2951
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2952
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2953
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2954
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2955
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2956
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2957
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2958
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2959
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2960
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2961
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2962
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2963
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2964
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2965
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2966
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2967
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2968
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2969
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2970
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2971
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2972
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2973
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2974
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2975
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2976
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2977
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2978
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2979
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2980
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2981
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2982
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2983
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2984
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2985
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2986
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2987
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2988
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2989
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2990
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2991
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2992
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2993
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2994
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2995
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2996
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2997
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2998
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2999
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3000
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3001
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3002
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3003
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3004
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3005
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3006
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3007
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3008
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3009
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3010
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3011
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3012
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3013
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3014
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3015
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3016
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3017
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3018
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3019
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3020
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3021
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3022
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3023
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3024
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3025
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3026
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3027
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3028
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3029
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3030
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3031
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3032
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3033
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3034
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3035
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3036
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3037
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3038
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3039
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3040
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3041
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3042
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3043
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3044
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3045
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3046
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3047
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3048
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3049
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3050
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3051
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3052
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3053
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3054
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3055
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3056
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3057
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3058
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3059
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3060
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3061
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3062
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3063
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3064
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3065
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3066
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3067
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3068
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3069
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3070
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3071
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3072
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3073
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3074
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3075
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3076
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3077
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3078
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3079
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3080
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3081
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3082
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3083
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3084
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3085
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3086
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3087
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3088
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3089
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3090
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3091
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3092
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3093
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3094
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3095
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3096
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3097
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3098
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3099
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3100
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3101
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3102
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3103
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3104
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3105
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3106
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3107
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3108
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3109
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3110
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3111
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3112
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3113
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3114
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3115
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3116
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3117
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3118
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3119
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3120
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3121
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3122
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3123
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3124
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3125
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3126
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3127
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3128
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3129
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3130
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3131
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3132
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3133
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3134
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3135
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3136
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3137
    7};
3138
3139
const uint16_t decomposition_block[67][257] = {
3140
    {4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3141
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3142
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3143
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3144
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3145
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3146
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3147
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3148
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3149
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3150
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   5,   8,   8,   8,   8,
3151
     8,   8,   8,   9,   16,  17,  20,  20,  20,  20,  21,  28,  28,  29,  33,
3152
     37,  45,  48,  48,  49,  57,  61,  64,  65,  77,  89,  100, 100, 108, 116,
3153
     124, 132, 140, 148, 148, 156, 164, 172, 180, 188, 196, 204, 212, 220, 220,
3154
     228, 236, 244, 252, 260, 268, 268, 268, 276, 284, 292, 300, 308, 308, 308,
3155
     316, 324, 332, 340, 348, 356, 356, 364, 372, 380, 388, 396, 404, 412, 420,
3156
     428, 428, 436, 444, 452, 460, 468, 476, 476, 476, 484, 492, 500, 508, 516,
3157
     516, 524},
3158
    {524,  532,  540,  548,  556,  564,  572,  580,  588,  596,  604,  612,
3159
     620,  628,  636,  644,  652,  652,  652,  660,  668,  676,  684,  692,
3160
     700,  708,  716,  724,  732,  740,  748,  756,  764,  772,  780,  788,
3161
     796,  804,  812,  812,  812,  820,  828,  836,  844,  852,  860,  868,
3162
     876,  884,  885,  893,  900,  908,  916,  924,  932,  932,  940,  948,
3163
     956,  964,  972,  981,  989,  996,  996,  996,  1004, 1012, 1020, 1028,
3164
     1036, 1045, 1052, 1052, 1052, 1060, 1068, 1076, 1084, 1092, 1100, 1100,
3165
     1100, 1108, 1116, 1124, 1132, 1140, 1148, 1156, 1164, 1172, 1180, 1188,
3166
     1196, 1204, 1212, 1220, 1228, 1236, 1244, 1244, 1244, 1252, 1260, 1268,
3167
     1276, 1284, 1292, 1300, 1308, 1316, 1324, 1332, 1340, 1348, 1356, 1364,
3168
     1372, 1380, 1388, 1396, 1404, 1412, 1420, 1429, 1432, 1432, 1432, 1432,
3169
     1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3170
     1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3171
     1432, 1432, 1432, 1432, 1432, 1440, 1448, 1448, 1448, 1448, 1448, 1448,
3172
     1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1456, 1464, 1464, 1464,
3173
     1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464,
3174
     1464, 1464, 1464, 1464, 1465, 1477, 1489, 1501, 1509, 1517, 1525, 1533,
3175
     1541, 1548, 1556, 1564, 1572, 1580, 1588, 1596, 1604, 1612, 1624, 1636,
3176
     1648, 1660, 1672, 1684, 1696, 1708, 1708, 1720, 1732, 1744, 1756, 1764,
3177
     1772, 1772, 1772, 1780, 1788, 1796, 1804, 1812, 1820, 1832, 1844, 1852,
3178
     1860, 1869, 1877, 1885, 1892, 1900, 1908, 1908, 1908, 1916, 1924, 1936,
3179
     1948, 1956, 1964, 1972, 1980},
3180
    {1980, 1988, 1996, 2004, 2012, 2020, 2028, 2036, 2044, 2052, 2060, 2068,
3181
     2076, 2084, 2092, 2100, 2108, 2116, 2124, 2132, 2140, 2148, 2156, 2164,
3182
     2172, 2180, 2188, 2196, 2204, 2204, 2204, 2212, 2220, 2220, 2220, 2220,
3183
     2220, 2220, 2220, 2228, 2236, 2244, 2252, 2264, 2276, 2288, 2300, 2308,
3184
     2316, 2328, 2340, 2348, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3185
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3186
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3187
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3188
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3189
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3190
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3191
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3192
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3193
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3194
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2357, 2361, 2365, 2369,
3195
     2373, 2377, 2381, 2385, 2389, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3196
     2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3197
     2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3198
     2393, 2401, 2409, 2417, 2425, 2433, 2440, 2440, 2441, 2445, 2449, 2453,
3199
     2457, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3200
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3201
     2460, 2460, 2460, 2460, 2460},
3202
    {2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3203
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3204
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3205
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3206
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3207
     2460, 2460, 2460, 2460, 2460, 2464, 2468, 2468, 2472, 2480, 2480, 2480,
3208
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3209
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3210
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3211
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2484, 2484, 2484,
3212
     2484, 2484, 2485, 2492, 2492, 2492, 2492, 2496, 2496, 2496, 2496, 2496,
3213
     2497, 2506, 2512, 2520, 2524, 2532, 2540, 2548, 2548, 2556, 2556, 2564,
3214
     2572, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3215
     2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3216
     2584, 2584, 2584, 2592, 2600, 2608, 2616, 2624, 2632, 2644, 2644, 2644,
3217
     2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644,
3218
     2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2652,
3219
     2660, 2668, 2676, 2684, 2685, 2689, 2693, 2698, 2706, 2713, 2717, 2720,
3220
     2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3221
     2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3222
     2721, 2725, 2729, 2732, 2733, 2737, 2740, 2740, 2740, 2741, 2744, 2744,
3223
     2744, 2744, 2744, 2744, 2744},
3224
    {2744, 2752, 2760, 2760, 2768, 2768, 2768, 2768, 2776, 2776, 2776, 2776,
3225
     2776, 2784, 2792, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800,
3226
     2800, 2800, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3227
     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3228
     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2816, 2816,
3229
     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816,
3230
     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2824, 2832, 2832,
3231
     2840, 2840, 2840, 2840, 2848, 2848, 2848, 2848, 2848, 2856, 2864, 2872,
3232
     2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872,
3233
     2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2880,
3234
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3235
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3236
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3237
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3238
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3239
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3240
     2888, 2888, 2896, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904,
3241
     2904, 2904, 2904, 2904, 2904, 2912, 2920, 2928, 2936, 2936, 2936, 2944,
3242
     2952, 2952, 2952, 2960, 2968, 2976, 2984, 2992, 3000, 3000, 3000, 3008,
3243
     3016, 3024, 3032, 3040, 3048, 3048, 3048, 3056, 3064, 3072, 3080, 3088,
3244
     3096, 3104, 3112, 3120, 3128, 3136, 3144, 3144, 3144, 3152, 3160, 3160,
3245
     3160, 3160, 3160, 3160, 3160},
3246
    {3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3247
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3248
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3249
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3250
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3251
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3252
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3253
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3254
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3255
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3256
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3257
     3160, 3160, 3160, 3161, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3258
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3259
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3260
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3261
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3262
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3263
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3264
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3265
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3266
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3267
     3168, 3168, 3168, 3168, 3168},
3268
    {3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3269
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3270
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3176,
3271
     3184, 3192, 3200, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3272
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3273
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3274
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3275
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3276
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3277
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3209, 3217, 3225,
3278
     3233, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3279
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3280
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3281
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3282
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3283
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3284
     3240, 3248, 3248, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256,
3285
     3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3264, 3264, 3264, 3264,
3286
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3287
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3288
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3289
     3264, 3264, 3264, 3264, 3264},
3290
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3291
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3292
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3293
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3294
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3295
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3296
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3297
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3298
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3299
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3300
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
3301
    {3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3302
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3303
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3304
     3264, 3264, 3264, 3264, 3264, 3264, 3272, 3272, 3272, 3272, 3272, 3272,
3305
     3272, 3272, 3280, 3280, 3280, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3306
     3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3307
     3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3308
     3288, 3288, 3288, 3288, 3288, 3296, 3304, 3312, 3320, 3328, 3336, 3344,
3309
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3310
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3311
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3312
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3313
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3314
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3315
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3316
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3317
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3318
     3360, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368,
3319
     3368, 3368, 3368, 3368, 3368, 3376, 3384, 3384, 3392, 3392, 3392, 3392,
3320
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3321
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3322
     3392, 3392, 3392, 3392, 3392},
3323
    {3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3324
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3325
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3326
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3327
     3392, 3392, 3392, 3392, 3400, 3400, 3400, 3408, 3408, 3408, 3408, 3408,
3328
     3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3329
     3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3330
     3408, 3408, 3408, 3408, 3408, 3408, 3416, 3424, 3432, 3432, 3432, 3440,
3331
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3332
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3333
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3334
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3335
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3336
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3337
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3338
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3339
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3340
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3341
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3342
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3343
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3344
     3440, 3440, 3440, 3440, 3440},
3345
    {3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3346
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3347
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3348
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3349
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3350
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3351
     3440, 3448, 3448, 3448, 3456, 3464, 3464, 3464, 3464, 3464, 3464, 3464,
3352
     3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3472, 3480, 3480,
3353
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3354
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3355
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3356
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3357
     3480, 3480, 3480, 3480, 3480, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3358
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3359
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3360
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3361
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3496,
3362
     3504, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3363
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3364
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3365
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3366
     3512, 3512, 3512, 3512, 3512},
3367
    {3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3368
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3369
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3370
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3371
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3372
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3373
     3512, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3374
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3375
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3376
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3377
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3378
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3379
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3380
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3381
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3382
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3383
     3520, 3528, 3528, 3528, 3528, 3528, 3528, 3528, 3536, 3544, 3544, 3552,
3384
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3385
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3386
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3387
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3388
     3564, 3564, 3564, 3564, 3564},
3389
    {3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3390
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3391
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3392
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3393
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3394
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3395
     3564, 3564, 3564, 3572, 3580, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3396
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3397
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3398
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3399
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3400
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3401
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3402
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3403
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3404
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3405
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3406
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3407
     3588, 3588, 3588, 3596, 3596, 3604, 3616, 3624, 3624, 3624, 3624, 3624,
3408
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3409
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3410
     3624, 3624, 3624, 3624, 3624},
3411
    {3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3412
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3413
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3414
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3415
     3624, 3624, 3624, 3625, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3416
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3417
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3418
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3419
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3420
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3421
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3422
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3423
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3424
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3425
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3633,
3426
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3427
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3428
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3429
     3640, 3640, 3640, 3640, 3641, 3649, 3656, 3656, 3656, 3656, 3656, 3656,
3430
     3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3431
     3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3432
     3656, 3656, 3656, 3656, 3656},
3433
    {3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3434
     3657, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3435
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3436
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3437
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3438
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3668, 3668, 3668, 3668,
3439
     3668, 3668, 3668, 3668, 3668, 3668, 3676, 3676, 3676, 3676, 3676, 3684,
3440
     3684, 3684, 3684, 3684, 3692, 3692, 3692, 3692, 3692, 3700, 3700, 3700,
3441
     3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3708, 3708,
3442
     3708, 3708, 3708, 3708, 3708, 3708, 3708, 3708, 3716, 3716, 3724, 3733,
3443
     3744, 3753, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3772, 3772,
3444
     3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772,
3445
     3772, 3772, 3772, 3772, 3780, 3780, 3780, 3780, 3780, 3780, 3780, 3780,
3446
     3780, 3780, 3788, 3788, 3788, 3788, 3788, 3796, 3796, 3796, 3796, 3796,
3447
     3804, 3804, 3804, 3804, 3804, 3812, 3812, 3812, 3812, 3812, 3812, 3812,
3448
     3812, 3812, 3812, 3812, 3812, 3812, 3820, 3820, 3820, 3820, 3820, 3820,
3449
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3450
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3451
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3452
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3453
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3454
     3820, 3820, 3820, 3820, 3820},
3455
    {3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3456
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3457
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3458
     3820, 3820, 3820, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3459
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3460
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3461
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3462
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3463
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3464
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3465
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3466
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3467
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3468
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3469
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3470
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3471
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3472
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3473
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3474
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3475
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3476
     3829, 3832, 3832, 3832, 3832},
3477
    {3832, 3832, 3832, 3832, 3832, 3832, 3832, 3840, 3840, 3848, 3848, 3856,
3478
     3856, 3864, 3864, 3872, 3872, 3872, 3872, 3880, 3880, 3880, 3880, 3880,
3479
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3480
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3481
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3482
     3888, 3888, 3896, 3896, 3896, 3904, 3912, 3912, 3920, 3920, 3920, 3920,
3483
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3484
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3485
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3486
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3487
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3488
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3489
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3490
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3491
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3492
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3493
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3494
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3495
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3496
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3497
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3498
     3920, 3920, 3920, 3920, 3920},
3499
    {3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3500
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3501
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3502
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3921, 3925, 3929, 3932,
3503
     3933, 3937, 3941, 3945, 3949, 3953, 3957, 3961, 3965, 3969, 3973, 3976,
3504
     3977, 3981, 3985, 3989, 3993, 3997, 4001, 4005, 4009, 4013, 4017, 4021,
3505
     4025, 4029, 4033, 4037, 4041, 4045, 4048, 4049, 4053, 4057, 4061, 4065,
3506
     4069, 4073, 4077, 4081, 4085, 4089, 4093, 4097, 4101, 4105, 4109, 4113,
3507
     4117, 4121, 4125, 4129, 4133, 4137, 4141, 4145, 4149, 4153, 4157, 4160,
3508
     4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160,
3509
     4161, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3510
     4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3511
     4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4165,
3512
     4169, 4173, 4177, 4181, 4185, 4189, 4193, 4197, 4201, 4205, 4209, 4213,
3513
     4217, 4221, 4225, 4229, 4233, 4237, 4241, 4245, 4249, 4253, 4257, 4261,
3514
     4265, 4269, 4273, 4277, 4281, 4285, 4289, 4293, 4297, 4301, 4305, 4309,
3515
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3516
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3517
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3518
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3519
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3520
     4312, 4312, 4312, 4312, 4312},
3521
    {4312, 4320, 4328, 4336, 4344, 4352, 4360, 4368, 4376, 4388, 4400, 4408,
3522
     4416, 4424, 4432, 4440, 4448, 4456, 4464, 4472, 4480, 4492, 4504, 4516,
3523
     4528, 4536, 4544, 4552, 4560, 4572, 4584, 4592, 4600, 4608, 4616, 4624,
3524
     4632, 4640, 4648, 4656, 4664, 4672, 4680, 4688, 4696, 4704, 4712, 4724,
3525
     4736, 4744, 4752, 4760, 4768, 4776, 4784, 4792, 4800, 4812, 4824, 4832,
3526
     4840, 4848, 4856, 4864, 4872, 4880, 4888, 4896, 4904, 4912, 4920, 4928,
3527
     4936, 4944, 4952, 4960, 4968, 4980, 4992, 5004, 5016, 5028, 5040, 5052,
3528
     5064, 5072, 5080, 5088, 5096, 5104, 5112, 5120, 5128, 5140, 5152, 5160,
3529
     5168, 5176, 5184, 5192, 5200, 5212, 5224, 5236, 5248, 5260, 5272, 5280,
3530
     5288, 5296, 5304, 5312, 5320, 5328, 5336, 5344, 5352, 5360, 5368, 5376,
3531
     5384, 5396, 5408, 5420, 5432, 5440, 5448, 5456, 5464, 5472, 5480, 5488,
3532
     5496, 5504, 5512, 5520, 5528, 5536, 5544, 5552, 5560, 5568, 5576, 5584,
3533
     5592, 5600, 5608, 5616, 5624, 5632, 5640, 5648, 5656, 5664, 5673, 5682,
3534
     5688, 5688, 5688, 5688, 5688, 5696, 5704, 5712, 5720, 5732, 5744, 5756,
3535
     5768, 5780, 5792, 5804, 5816, 5828, 5840, 5852, 5864, 5876, 5888, 5900,
3536
     5912, 5924, 5936, 5948, 5960, 5968, 5976, 5984, 5992, 6000, 6008, 6020,
3537
     6032, 6044, 6056, 6068, 6080, 6092, 6104, 6116, 6128, 6136, 6144, 6152,
3538
     6160, 6168, 6176, 6184, 6192, 6204, 6216, 6228, 6240, 6252, 6264, 6276,
3539
     6288, 6300, 6312, 6324, 6336, 6348, 6360, 6372, 6384, 6396, 6408, 6420,
3540
     6432, 6440, 6448, 6456, 6464, 6476, 6488, 6500, 6512, 6524, 6536, 6548,
3541
     6560, 6572, 6584, 6592, 6600, 6608, 6616, 6624, 6632, 6640, 6648, 6648,
3542
     6648, 6648, 6648, 6648, 6648},
3543
    {6648, 6656, 6664, 6676, 6688, 6700, 6712, 6724, 6736, 6744, 6752, 6764,
3544
     6776, 6788, 6800, 6812, 6824, 6832, 6840, 6852, 6864, 6876, 6888, 6888,
3545
     6888, 6896, 6904, 6916, 6928, 6940, 6952, 6952, 6952, 6960, 6968, 6980,
3546
     6992, 7004, 7016, 7028, 7040, 7048, 7056, 7068, 7080, 7092, 7104, 7116,
3547
     7128, 7136, 7144, 7156, 7168, 7180, 7192, 7204, 7216, 7224, 7232, 7244,
3548
     7256, 7268, 7280, 7292, 7304, 7312, 7320, 7332, 7344, 7356, 7368, 7368,
3549
     7368, 7376, 7384, 7396, 7408, 7420, 7432, 7432, 7432, 7440, 7448, 7460,
3550
     7472, 7484, 7496, 7508, 7520, 7520, 7528, 7528, 7540, 7540, 7552, 7552,
3551
     7564, 7572, 7580, 7592, 7604, 7616, 7628, 7640, 7652, 7660, 7668, 7680,
3552
     7692, 7704, 7716, 7728, 7740, 7748, 7756, 7764, 7772, 7780, 7788, 7796,
3553
     7804, 7812, 7820, 7828, 7836, 7844, 7852, 7852, 7852, 7864, 7876, 7892,
3554
     7908, 7924, 7940, 7956, 7972, 7984, 7996, 8012, 8028, 8044, 8060, 8076,
3555
     8092, 8104, 8116, 8132, 8148, 8164, 8180, 8196, 8212, 8224, 8236, 8252,
3556
     8268, 8284, 8300, 8316, 8332, 8344, 8356, 8372, 8388, 8404, 8420, 8436,
3557
     8452, 8464, 8476, 8492, 8508, 8524, 8540, 8556, 8572, 8580, 8588, 8600,
3558
     8608, 8620, 8620, 8628, 8640, 8648, 8656, 8664, 8672, 8681, 8688, 8693,
3559
     8701, 8710, 8716, 8728, 8736, 8748, 8748, 8756, 8768, 8776, 8784, 8792,
3560
     8800, 8810, 8818, 8826, 8832, 8840, 8848, 8860, 8872, 8872, 8872, 8880,
3561
     8892, 8900, 8908, 8916, 8924, 8926, 8934, 8942, 8948, 8956, 8964, 8976,
3562
     8988, 8996, 9004, 9012, 9024, 9032, 9040, 9048, 9056, 9066, 9074, 9080,
3563
     9084, 9084, 9084, 9096, 9104, 9116, 9116, 9124, 9136, 9144, 9152, 9160,
3564
     9168, 9178, 9181, 9188, 9190},
3565
    {9190, 9194, 9197, 9201, 9205, 9209, 9213, 9217, 9221, 9225, 9229, 9232,
3566
     9232, 9232, 9232, 9232, 9232, 9233, 9236, 9236, 9236, 9236, 9236, 9237,
3567
     9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244,
3568
     9245, 9249, 9257, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9269,
3569
     9272, 9272, 9272, 9273, 9281, 9292, 9293, 9301, 9312, 9312, 9312, 9312,
3570
     9313, 9320, 9321, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9329,
3571
     9337, 9345, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352,
3572
     9352, 9352, 9352, 9353, 9368, 9368, 9368, 9368, 9368, 9368, 9368, 9369,
3573
     9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372,
3574
     9372, 9372, 9372, 9372, 9373, 9377, 9380, 9380, 9381, 9385, 9389, 9393,
3575
     9397, 9401, 9405, 9409, 9413, 9417, 9421, 9425, 9429, 9433, 9437, 9441,
3576
     9445, 9449, 9453, 9457, 9461, 9465, 9469, 9473, 9477, 9481, 9485, 9488,
3577
     9489, 9493, 9497, 9501, 9505, 9509, 9513, 9517, 9521, 9525, 9529, 9533,
3578
     9537, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540,
3579
     9541, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3580
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3581
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3582
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3583
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3584
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3585
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3586
     9548, 9548, 9548, 9548, 9549},
3587
    {9549,  9561,  9573,  9577,  9584,  9585,  9597,  9609,  9612,  9613,
3588
     9621,  9625,  9629,  9633,  9637,  9641,  9645,  9649,  9653,  9657,
3589
     9660,  9661,  9665,  9672,  9672,  9673,  9677,  9681,  9685,  9689,
3590
     9692,  9692,  9693,  9701,  9713,  9720,  9721,  9724,  9724,  9728,
3591
     9729,  9732,  9732,  9736,  9745,  9749,  9752,  9753,  9757,  9761,
3592
     9764,  9765,  9769,  9773,  9777,  9781,  9785,  9789,  9792,  9793,
3593
     9805,  9809,  9813,  9817,  9821,  9824,  9824,  9824,  9824,  9825,
3594
     9829,  9833,  9837,  9841,  9844,  9844,  9844,  9844,  9844,  9844,
3595
     9845,  9857,  9869,  9885,  9897,  9909,  9921,  9933,  9945,  9957,
3596
     9969,  9981,  9993,  10005, 10017, 10029, 10037, 10041, 10049, 10061,
3597
     10069, 10073, 10081, 10093, 10109, 10117, 10121, 10129, 10141, 10145,
3598
     10149, 10153, 10157, 10161, 10169, 10181, 10189, 10193, 10201, 10213,
3599
     10229, 10237, 10241, 10249, 10261, 10265, 10269, 10273, 10276, 10276,
3600
     10276, 10276, 10276, 10276, 10276, 10276, 10276, 10277, 10288, 10288,
3601
     10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288,
3602
     10288, 10288, 10288, 10288, 10288, 10296, 10304, 10304, 10304, 10304,
3603
     10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304,
3604
     10304, 10304, 10304, 10304, 10304, 10312, 10312, 10312, 10312, 10312,
3605
     10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3606
     10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3607
     10312, 10312, 10312, 10312, 10312, 10312, 10320, 10328, 10336, 10336,
3608
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3609
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3610
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3611
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3612
     10336, 10336, 10336, 10336, 10336, 10336, 10336},
3613
    {10336, 10336, 10336, 10336, 10336, 10344, 10344, 10344, 10344, 10344,
3614
     10352, 10352, 10352, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3615
     10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3616
     10360, 10360, 10360, 10360, 10360, 10360, 10360, 10368, 10368, 10376,
3617
     10376, 10376, 10376, 10376, 10377, 10385, 10396, 10397, 10405, 10416,
3618
     10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416,
3619
     10416, 10416, 10416, 10416, 10416, 10416, 10424, 10424, 10424, 10432,
3620
     10432, 10432, 10440, 10440, 10448, 10448, 10448, 10448, 10448, 10448,
3621
     10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448,
3622
     10448, 10448, 10448, 10448, 10448, 10448, 10448, 10456, 10456, 10464,
3623
     10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464,
3624
     10472, 10480, 10488, 10496, 10504, 10504, 10504, 10512, 10520, 10520,
3625
     10520, 10528, 10536, 10536, 10536, 10536, 10536, 10536, 10536, 10544,
3626
     10552, 10552, 10552, 10560, 10568, 10568, 10568, 10576, 10584, 10584,
3627
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3628
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3629
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3630
     10584, 10584, 10584, 10592, 10600, 10608, 10616, 10616, 10616, 10616,
3631
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3632
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3633
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3634
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3635
     10616, 10616, 10616, 10616, 10616, 10624, 10632, 10640, 10648, 10648,
3636
     10648, 10648, 10648, 10648, 10648, 10656, 10664, 10672, 10680, 10680,
3637
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3638
     10680, 10680, 10680, 10680, 10680, 10680, 10680},
3639
    {10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3640
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3641
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3642
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3643
     10680, 10680, 10684, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3644
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3645
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3646
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3647
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3648
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3649
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3650
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3651
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3652
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3653
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3654
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3655
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3656
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3657
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3658
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3659
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3660
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3661
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3662
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3663
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3664
     10688, 10688, 10688, 10688, 10688, 10688, 10688},
3665
    {10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3666
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3667
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3668
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3669
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3670
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3671
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3672
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3673
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3674
     10688, 10688, 10688, 10688, 10688, 10688, 10689, 10693, 10697, 10701,
3675
     10705, 10709, 10713, 10717, 10721, 10725, 10733, 10741, 10749, 10757,
3676
     10765, 10773, 10781, 10789, 10797, 10805, 10813, 10825, 10837, 10849,
3677
     10861, 10873, 10885, 10897, 10909, 10921, 10937, 10953, 10969, 10985,
3678
     11001, 11017, 11033, 11049, 11065, 11081, 11097, 11105, 11113, 11121,
3679
     11129, 11137, 11145, 11153, 11161, 11169, 11181, 11193, 11205, 11217,
3680
     11229, 11241, 11253, 11265, 11277, 11289, 11301, 11313, 11325, 11337,
3681
     11349, 11361, 11373, 11385, 11397, 11409, 11421, 11433, 11445, 11457,
3682
     11469, 11481, 11493, 11505, 11517, 11529, 11541, 11553, 11565, 11577,
3683
     11589, 11601, 11613, 11617, 11621, 11625, 11629, 11633, 11637, 11641,
3684
     11645, 11649, 11653, 11657, 11661, 11665, 11669, 11673, 11677, 11681,
3685
     11685, 11689, 11693, 11697, 11701, 11705, 11709, 11713, 11717, 11721,
3686
     11725, 11729, 11733, 11737, 11741, 11745, 11749, 11753, 11757, 11761,
3687
     11765, 11769, 11773, 11777, 11781, 11785, 11789, 11793, 11797, 11801,
3688
     11805, 11809, 11813, 11817, 11821, 11824, 11824, 11824, 11824, 11824,
3689
     11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3690
     11824, 11824, 11824, 11824, 11824, 11824, 11824},
3691
    {11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3692
     11824, 11824, 11825, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3693
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3694
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3695
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3696
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3697
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3698
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3699
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3700
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3701
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3702
     11840, 11840, 11840, 11840, 11840, 11840, 11841, 11853, 11861, 11872,
3703
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3704
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3705
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3706
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3707
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3708
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3709
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3710
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3711
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3712
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3713
     11872, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3714
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3715
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3716
     11880, 11880, 11880, 11880, 11880, 11880, 11880},
3717
    {11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3718
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3719
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3720
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3721
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3722
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3723
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3724
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3725
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3726
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3727
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3728
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3729
     11880, 11880, 11880, 11880, 11881, 11885, 11888, 11888, 11888, 11888,
3730
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3731
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3732
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3733
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3734
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3735
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3736
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3737
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3738
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3739
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3740
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3741
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3742
     11888, 11888, 11888, 11888, 11888, 11888, 11888},
3743
    {11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3744
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3745
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3746
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3747
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3748
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3749
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3750
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3751
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3752
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3753
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3754
     11888, 11889, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3755
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3756
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3757
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3758
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3759
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3760
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3761
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3762
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3763
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3764
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3765
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3766
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3767
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3768
     11892, 11892, 11892, 11892, 11892, 11892, 11892},
3769
    {11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3770
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3771
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3772
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3773
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3774
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3775
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3776
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3777
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3778
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3779
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3780
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3781
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3782
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3783
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3784
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11893,
3785
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3786
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3787
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3788
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3789
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3790
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3791
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3792
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3793
     11896, 11896, 11896, 11897, 11900, 11900, 11900, 11900, 11900, 11900,
3794
     11900, 11900, 11900, 11900, 11900, 11900, 11901},
3795
    {11901, 11905, 11909, 11913, 11917, 11921, 11925, 11929, 11933, 11937,
3796
     11941, 11945, 11949, 11953, 11957, 11961, 11965, 11969, 11973, 11977,
3797
     11981, 11985, 11989, 11993, 11997, 12001, 12005, 12009, 12013, 12017,
3798
     12021, 12025, 12029, 12033, 12037, 12041, 12045, 12049, 12053, 12057,
3799
     12061, 12065, 12069, 12073, 12077, 12081, 12085, 12089, 12093, 12097,
3800
     12101, 12105, 12109, 12113, 12117, 12121, 12125, 12129, 12133, 12137,
3801
     12141, 12145, 12149, 12153, 12157, 12161, 12165, 12169, 12173, 12177,
3802
     12181, 12185, 12189, 12193, 12197, 12201, 12205, 12209, 12213, 12217,
3803
     12221, 12225, 12229, 12233, 12237, 12241, 12245, 12249, 12253, 12257,
3804
     12261, 12265, 12269, 12273, 12277, 12281, 12285, 12289, 12293, 12297,
3805
     12301, 12305, 12309, 12313, 12317, 12321, 12325, 12329, 12333, 12337,
3806
     12341, 12345, 12349, 12353, 12357, 12361, 12365, 12369, 12373, 12377,
3807
     12381, 12385, 12389, 12393, 12397, 12401, 12405, 12409, 12413, 12417,
3808
     12421, 12425, 12429, 12433, 12437, 12441, 12445, 12449, 12453, 12457,
3809
     12461, 12465, 12469, 12473, 12477, 12481, 12485, 12489, 12493, 12497,
3810
     12501, 12505, 12509, 12513, 12517, 12521, 12525, 12529, 12533, 12537,
3811
     12541, 12545, 12549, 12553, 12557, 12561, 12565, 12569, 12573, 12577,
3812
     12581, 12585, 12589, 12593, 12597, 12601, 12605, 12609, 12613, 12617,
3813
     12621, 12625, 12629, 12633, 12637, 12641, 12645, 12649, 12653, 12657,
3814
     12661, 12665, 12669, 12673, 12677, 12681, 12685, 12689, 12693, 12697,
3815
     12701, 12705, 12709, 12713, 12717, 12721, 12725, 12729, 12733, 12737,
3816
     12741, 12745, 12749, 12753, 12756, 12756, 12756, 12756, 12756, 12756,
3817
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3818
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3819
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3820
     12756, 12756, 12756, 12756, 12756, 12756, 12757},
3821
    {12757, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3822
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3823
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3824
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3825
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3826
     12760, 12760, 12760, 12760, 12761, 12764, 12765, 12769, 12773, 12776,
3827
     12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776,
3828
     12776, 12776, 12776, 12776, 12776, 12776, 12776, 12784, 12784, 12792,
3829
     12792, 12800, 12800, 12808, 12808, 12816, 12816, 12824, 12824, 12832,
3830
     12832, 12840, 12840, 12848, 12848, 12856, 12856, 12864, 12864, 12872,
3831
     12872, 12872, 12880, 12880, 12888, 12888, 12896, 12896, 12896, 12896,
3832
     12896, 12896, 12896, 12904, 12912, 12912, 12920, 12928, 12928, 12936,
3833
     12944, 12944, 12952, 12960, 12960, 12968, 12976, 12976, 12976, 12976,
3834
     12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976,
3835
     12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12984,
3836
     12984, 12984, 12984, 12984, 12984, 12985, 12993, 13000, 13000, 13009,
3837
     13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016,
3838
     13016, 13016, 13016, 13024, 13024, 13032, 13032, 13040, 13040, 13048,
3839
     13048, 13056, 13056, 13064, 13064, 13072, 13072, 13080, 13080, 13088,
3840
     13088, 13096, 13096, 13104, 13104, 13112, 13112, 13112, 13120, 13120,
3841
     13128, 13128, 13136, 13136, 13136, 13136, 13136, 13136, 13136, 13144,
3842
     13152, 13152, 13160, 13168, 13168, 13176, 13184, 13184, 13192, 13200,
3843
     13200, 13208, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3844
     13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3845
     13216, 13216, 13216, 13216, 13216, 13224, 13224, 13224, 13232, 13240,
3846
     13248, 13256, 13256, 13256, 13256, 13265, 13272},
3847
    {13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3848
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3849
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3850
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3851
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13273,
3852
     13277, 13281, 13285, 13289, 13293, 13297, 13301, 13305, 13309, 13313,
3853
     13317, 13321, 13325, 13329, 13333, 13337, 13341, 13345, 13349, 13353,
3854
     13357, 13361, 13365, 13369, 13373, 13377, 13381, 13385, 13389, 13393,
3855
     13397, 13401, 13405, 13409, 13413, 13417, 13421, 13425, 13429, 13433,
3856
     13437, 13441, 13445, 13449, 13453, 13457, 13461, 13465, 13469, 13473,
3857
     13477, 13481, 13485, 13489, 13493, 13497, 13501, 13505, 13509, 13513,
3858
     13517, 13521, 13525, 13529, 13533, 13537, 13541, 13545, 13549, 13553,
3859
     13557, 13561, 13565, 13569, 13573, 13577, 13581, 13585, 13589, 13593,
3860
     13597, 13601, 13605, 13609, 13613, 13617, 13621, 13625, 13629, 13633,
3861
     13637, 13641, 13645, 13648, 13648, 13648, 13649, 13653, 13657, 13661,
3862
     13665, 13669, 13673, 13677, 13681, 13685, 13689, 13693, 13697, 13701,
3863
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3864
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3865
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3866
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3867
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3868
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3869
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3870
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3871
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3872
     13704, 13704, 13704, 13704, 13704, 13704, 13705},
3873
    {13705, 13717, 13729, 13741, 13753, 13765, 13777, 13789, 13801, 13813,
3874
     13825, 13837, 13849, 13861, 13873, 13889, 13905, 13921, 13937, 13953,
3875
     13969, 13985, 14001, 14017, 14033, 14049, 14065, 14081, 14097, 14113,
3876
     14141, 14164, 14165, 14177, 14189, 14201, 14213, 14225, 14237, 14249,
3877
     14261, 14273, 14285, 14297, 14309, 14321, 14333, 14345, 14357, 14369,
3878
     14381, 14393, 14405, 14417, 14429, 14441, 14453, 14465, 14477, 14489,
3879
     14501, 14513, 14525, 14537, 14549, 14561, 14573, 14585, 14597, 14601,
3880
     14605, 14609, 14612, 14612, 14612, 14612, 14612, 14612, 14612, 14612,
3881
     14613, 14625, 14633, 14641, 14649, 14657, 14665, 14673, 14681, 14689,
3882
     14697, 14705, 14713, 14721, 14729, 14737, 14745, 14749, 14753, 14757,
3883
     14761, 14765, 14769, 14773, 14777, 14781, 14785, 14789, 14793, 14797,
3884
     14801, 14809, 14817, 14825, 14833, 14841, 14849, 14857, 14865, 14873,
3885
     14881, 14889, 14897, 14905, 14913, 14933, 14949, 14956, 14957, 14961,
3886
     14965, 14969, 14973, 14977, 14981, 14985, 14989, 14993, 14997, 15001,
3887
     15005, 15009, 15013, 15017, 15021, 15025, 15029, 15033, 15037, 15041,
3888
     15045, 15049, 15053, 15057, 15061, 15065, 15069, 15073, 15077, 15081,
3889
     15085, 15089, 15093, 15097, 15101, 15105, 15109, 15113, 15117, 15121,
3890
     15125, 15129, 15133, 15137, 15141, 15145, 15149, 15153, 15161, 15169,
3891
     15177, 15185, 15193, 15201, 15209, 15217, 15225, 15233, 15241, 15249,
3892
     15257, 15265, 15273, 15281, 15289, 15297, 15305, 15313, 15321, 15329,
3893
     15337, 15345, 15357, 15369, 15381, 15389, 15401, 15409, 15421, 15425,
3894
     15429, 15433, 15437, 15441, 15445, 15449, 15453, 15457, 15461, 15465,
3895
     15469, 15473, 15477, 15481, 15485, 15489, 15493, 15497, 15501, 15505,
3896
     15509, 15513, 15517, 15521, 15525, 15529, 15533, 15537, 15541, 15545,
3897
     15549, 15553, 15557, 15561, 15565, 15569, 15573, 15577, 15581, 15585,
3898
     15589, 15593, 15597, 15601, 15605, 15609, 15617},
3899
    {15617, 15637, 15653, 15673, 15685, 15705, 15717, 15729, 15753, 15769,
3900
     15781, 15793, 15805, 15821, 15837, 15853, 15869, 15885, 15901, 15917,
3901
     15941, 15949, 15973, 15997, 16017, 16033, 16057, 16081, 16097, 16109,
3902
     16121, 16137, 16153, 16173, 16193, 16205, 16217, 16233, 16245, 16257,
3903
     16265, 16273, 16285, 16297, 16321, 16337, 16357, 16381, 16397, 16409,
3904
     16421, 16445, 16461, 16485, 16497, 16517, 16529, 16545, 16557, 16573,
3905
     16593, 16609, 16629, 16645, 16653, 16673, 16685, 16697, 16713, 16725,
3906
     16737, 16749, 16769, 16785, 16793, 16817, 16829, 16849, 16865, 16881,
3907
     16893, 16905, 16921, 16929, 16945, 16965, 16973, 16997, 17009, 17017,
3908
     17025, 17033, 17041, 17049, 17057, 17065, 17073, 17081, 17089, 17101,
3909
     17113, 17125, 17137, 17149, 17161, 17173, 17185, 17197, 17209, 17221,
3910
     17233, 17245, 17257, 17269, 17281, 17289, 17297, 17309, 17317, 17325,
3911
     17333, 17345, 17357, 17365, 17373, 17381, 17389, 17397, 17413, 17421,
3912
     17429, 17437, 17445, 17453, 17461, 17469, 17477, 17489, 17505, 17513,
3913
     17521, 17529, 17537, 17545, 17553, 17561, 17573, 17585, 17597, 17609,
3914
     17617, 17625, 17633, 17641, 17649, 17657, 17665, 17673, 17681, 17689,
3915
     17701, 17713, 17721, 17733, 17745, 17757, 17765, 17777, 17789, 17805,
3916
     17813, 17825, 17837, 17849, 17861, 17881, 17905, 17913, 17921, 17929,
3917
     17937, 17945, 17953, 17961, 17969, 17977, 17985, 17993, 18001, 18009,
3918
     18017, 18025, 18033, 18041, 18049, 18065, 18073, 18081, 18089, 18105,
3919
     18117, 18125, 18133, 18141, 18149, 18157, 18165, 18173, 18181, 18189,
3920
     18197, 18209, 18217, 18225, 18237, 18249, 18257, 18273, 18285, 18293,
3921
     18301, 18309, 18317, 18329, 18341, 18349, 18357, 18365, 18373, 18381,
3922
     18389, 18397, 18405, 18413, 18425, 18437, 18449, 18461, 18473, 18485,
3923
     18497, 18509, 18521, 18533, 18545, 18557, 18569, 18581, 18593, 18605,
3924
     18617, 18629, 18641, 18653, 18665, 18677, 18688},
3925
    {18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3926
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3927
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3928
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3929
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3930
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3931
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3932
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3933
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3934
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3935
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3936
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3937
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3938
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3939
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3940
     18688, 18688, 18688, 18688, 18688, 18688, 18689, 18693, 18696, 18696,
3941
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3942
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3943
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3944
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3945
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3946
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3947
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3948
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3949
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3950
     18696, 18696, 18696, 18696, 18696, 18696, 18696},
3951
    {18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3952
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3953
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3954
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3955
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3956
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3957
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3958
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3959
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3960
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3961
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3962
     18696, 18696, 18697, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3963
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3964
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3965
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3966
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3967
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3968
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3969
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3970
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3971
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3972
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3973
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3974
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3975
     18700, 18700, 18701, 18705, 18709, 18712, 18712, 18712, 18713, 18717,
3976
     18720, 18720, 18720, 18720, 18720, 18720, 18720},
3977
    {18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3978
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3979
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3980
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3981
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3982
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3983
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3984
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3985
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3986
     18720, 18720, 18721, 18725, 18729, 18733, 18736, 18736, 18736, 18736,
3987
     18736, 18736, 18736, 18736, 18736, 18737, 18740, 18740, 18740, 18740,
3988
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3989
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3990
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3991
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3992
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3993
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3994
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3995
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3996
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3997
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3998
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3999
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4000
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4001
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4002
     18740, 18740, 18740, 18740, 18740, 18740, 18740},
4003
    {18740, 18744, 18748, 18752, 18756, 18760, 18764, 18768, 18772, 18776,
4004
     18780, 18784, 18788, 18792, 18796, 18800, 18804, 18808, 18812, 18816,
4005
     18820, 18824, 18828, 18832, 18836, 18840, 18844, 18848, 18852, 18856,
4006
     18860, 18864, 18868, 18872, 18876, 18880, 18884, 18888, 18892, 18896,
4007
     18900, 18904, 18908, 18912, 18916, 18920, 18924, 18928, 18932, 18936,
4008
     18940, 18944, 18948, 18952, 18956, 18960, 18964, 18968, 18972, 18976,
4009
     18980, 18984, 18988, 18992, 18996, 19000, 19004, 19008, 19012, 19016,
4010
     19020, 19024, 19028, 19032, 19036, 19040, 19044, 19048, 19052, 19056,
4011
     19060, 19064, 19068, 19072, 19076, 19080, 19084, 19088, 19092, 19096,
4012
     19100, 19104, 19108, 19112, 19116, 19120, 19124, 19128, 19132, 19136,
4013
     19140, 19144, 19148, 19152, 19156, 19160, 19164, 19168, 19172, 19176,
4014
     19180, 19184, 19188, 19192, 19196, 19200, 19204, 19208, 19212, 19216,
4015
     19220, 19224, 19228, 19232, 19236, 19240, 19244, 19248, 19252, 19256,
4016
     19260, 19264, 19268, 19272, 19276, 19280, 19284, 19288, 19292, 19296,
4017
     19300, 19304, 19308, 19312, 19316, 19320, 19324, 19328, 19332, 19336,
4018
     19340, 19344, 19348, 19352, 19356, 19360, 19364, 19368, 19372, 19376,
4019
     19380, 19384, 19388, 19392, 19396, 19400, 19404, 19408, 19412, 19416,
4020
     19420, 19424, 19428, 19432, 19436, 19440, 19444, 19448, 19452, 19456,
4021
     19460, 19464, 19468, 19472, 19476, 19480, 19484, 19488, 19492, 19496,
4022
     19500, 19504, 19508, 19512, 19516, 19520, 19524, 19528, 19532, 19536,
4023
     19540, 19544, 19548, 19552, 19556, 19560, 19564, 19568, 19572, 19576,
4024
     19580, 19584, 19588, 19592, 19596, 19600, 19604, 19608, 19612, 19616,
4025
     19620, 19624, 19628, 19632, 19636, 19640, 19644, 19648, 19652, 19656,
4026
     19660, 19664, 19668, 19672, 19676, 19680, 19684, 19688, 19692, 19696,
4027
     19700, 19704, 19708, 19712, 19716, 19720, 19724, 19728, 19732, 19736,
4028
     19740, 19744, 19748, 19752, 19756, 19760, 19764},
4029
    {19764, 19768, 19772, 19776, 19780, 19784, 19788, 19792, 19796, 19800,
4030
     19804, 19808, 19812, 19816, 19820, 19820, 19820, 19824, 19824, 19828,
4031
     19828, 19828, 19832, 19836, 19840, 19844, 19848, 19852, 19856, 19860,
4032
     19864, 19868, 19868, 19872, 19872, 19876, 19876, 19876, 19880, 19884,
4033
     19884, 19884, 19884, 19888, 19892, 19896, 19900, 19904, 19908, 19912,
4034
     19916, 19920, 19924, 19928, 19932, 19936, 19940, 19944, 19948, 19952,
4035
     19956, 19960, 19964, 19968, 19972, 19976, 19980, 19984, 19988, 19992,
4036
     19996, 20000, 20004, 20008, 20012, 20016, 20020, 20024, 20028, 20032,
4037
     20036, 20040, 20044, 20048, 20052, 20056, 20060, 20064, 20068, 20072,
4038
     20076, 20080, 20084, 20088, 20092, 20096, 20100, 20104, 20108, 20112,
4039
     20116, 20120, 20124, 20128, 20132, 20136, 20140, 20144, 20148, 20152,
4040
     20156, 20156, 20156, 20160, 20164, 20168, 20172, 20176, 20180, 20184,
4041
     20188, 20192, 20196, 20200, 20204, 20208, 20212, 20216, 20220, 20224,
4042
     20228, 20232, 20236, 20240, 20244, 20248, 20252, 20256, 20260, 20264,
4043
     20268, 20272, 20276, 20280, 20284, 20288, 20292, 20296, 20300, 20304,
4044
     20308, 20312, 20316, 20320, 20324, 20328, 20332, 20336, 20340, 20344,
4045
     20348, 20352, 20356, 20360, 20364, 20368, 20372, 20376, 20380, 20384,
4046
     20388, 20392, 20396, 20400, 20404, 20408, 20412, 20416, 20420, 20424,
4047
     20428, 20432, 20436, 20440, 20444, 20448, 20452, 20456, 20460, 20464,
4048
     20468, 20472, 20476, 20480, 20484, 20488, 20492, 20496, 20500, 20504,
4049
     20508, 20512, 20516, 20520, 20524, 20528, 20532, 20536, 20540, 20544,
4050
     20548, 20552, 20556, 20560, 20564, 20568, 20572, 20576, 20580, 20580,
4051
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4052
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4053
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4054
     20580, 20580, 20580, 20580, 20580, 20580, 20581},
4055
    {20581, 20589, 20597, 20605, 20617, 20629, 20637, 20644, 20644, 20644,
4056
     20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20645,
4057
     20653, 20661, 20669, 20677, 20684, 20684, 20684, 20684, 20684, 20684,
4058
     20692, 20692, 20701, 20705, 20709, 20713, 20717, 20721, 20725, 20729,
4059
     20733, 20737, 20740, 20748, 20756, 20768, 20780, 20788, 20796, 20804,
4060
     20812, 20820, 20828, 20836, 20844, 20852, 20852, 20860, 20868, 20876,
4061
     20884, 20892, 20892, 20900, 20900, 20908, 20916, 20916, 20924, 20932,
4062
     20932, 20940, 20948, 20956, 20964, 20972, 20980, 20988, 20996, 21005,
4063
     21013, 21017, 21021, 21025, 21029, 21033, 21037, 21041, 21045, 21049,
4064
     21053, 21057, 21061, 21065, 21069, 21073, 21077, 21081, 21085, 21089,
4065
     21093, 21097, 21101, 21105, 21109, 21113, 21117, 21121, 21125, 21129,
4066
     21133, 21137, 21141, 21145, 21149, 21153, 21157, 21161, 21165, 21169,
4067
     21173, 21177, 21181, 21185, 21189, 21193, 21197, 21201, 21205, 21209,
4068
     21213, 21217, 21221, 21225, 21229, 21233, 21237, 21241, 21245, 21249,
4069
     21253, 21257, 21261, 21265, 21269, 21273, 21277, 21281, 21285, 21289,
4070
     21293, 21297, 21301, 21305, 21309, 21313, 21317, 21321, 21325, 21329,
4071
     21333, 21337, 21341, 21345, 21349, 21357, 21365, 21369, 21373, 21377,
4072
     21381, 21385, 21389, 21393, 21397, 21401, 21405, 21413, 21420, 21420,
4073
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4074
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4075
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4076
     21420, 21421, 21425, 21429, 21433, 21437, 21441, 21445, 21449, 21453,
4077
     21457, 21461, 21469, 21473, 21477, 21481, 21485, 21489, 21493, 21497,
4078
     21501, 21505, 21509, 21513, 21517, 21529, 21541, 21553, 21565, 21577,
4079
     21589, 21601, 21613, 21625, 21637, 21649, 21661, 21673, 21685, 21697,
4080
     21709, 21721, 21733, 21737, 21741, 21745, 21749},
4081
    {21749, 21761, 21773, 21785, 21797, 21809, 21817, 21825, 21833, 21841,
4082
     21849, 21857, 21865, 21873, 21881, 21889, 21897, 21905, 21913, 21921,
4083
     21929, 21937, 21945, 21953, 21961, 21969, 21977, 21985, 21993, 22001,
4084
     22009, 22017, 22025, 22033, 22041, 22049, 22057, 22065, 22073, 22081,
4085
     22089, 22097, 22105, 22113, 22121, 22129, 22137, 22145, 22153, 22161,
4086
     22169, 22177, 22185, 22193, 22201, 22209, 22217, 22225, 22233, 22241,
4087
     22249, 22257, 22265, 22273, 22281, 22289, 22297, 22305, 22313, 22321,
4088
     22329, 22337, 22345, 22353, 22361, 22369, 22377, 22385, 22393, 22401,
4089
     22409, 22417, 22425, 22433, 22441, 22449, 22457, 22465, 22473, 22481,
4090
     22489, 22497, 22505, 22513, 22521, 22533, 22545, 22557, 22569, 22581,
4091
     22593, 22605, 22617, 22629, 22641, 22653, 22665, 22673, 22681, 22689,
4092
     22697, 22705, 22713, 22721, 22729, 22737, 22745, 22753, 22761, 22769,
4093
     22777, 22785, 22793, 22801, 22809, 22817, 22825, 22833, 22841, 22849,
4094
     22857, 22865, 22873, 22881, 22889, 22897, 22905, 22913, 22921, 22929,
4095
     22937, 22945, 22953, 22961, 22969, 22977, 22985, 22993, 23001, 23009,
4096
     23017, 23025, 23037, 23049, 23061, 23073, 23085, 23093, 23101, 23109,
4097
     23117, 23125, 23133, 23141, 23149, 23157, 23165, 23173, 23181, 23189,
4098
     23197, 23205, 23213, 23221, 23229, 23237, 23245, 23253, 23261, 23269,
4099
     23277, 23285, 23293, 23301, 23309, 23317, 23325, 23333, 23341, 23349,
4100
     23357, 23365, 23373, 23381, 23389, 23397, 23405, 23413, 23421, 23429,
4101
     23437, 23445, 23453, 23461, 23469, 23477, 23485, 23493, 23501, 23509,
4102
     23517, 23525, 23533, 23541, 23549, 23557, 23565, 23573, 23581, 23589,
4103
     23597, 23605, 23613, 23621, 23633, 23645, 23653, 23661, 23669, 23677,
4104
     23685, 23693, 23701, 23709, 23717, 23725, 23733, 23741, 23749, 23757,
4105
     23765, 23773, 23781, 23793, 23805, 23817, 23825, 23833, 23841, 23849,
4106
     23857, 23865, 23873, 23881, 23889, 23897, 23905},
4107
    {23905, 23913, 23921, 23929, 23937, 23945, 23953, 23961, 23969, 23977,
4108
     23985, 23993, 24001, 24009, 24017, 24025, 24033, 24041, 24049, 24057,
4109
     24065, 24073, 24081, 24089, 24097, 24105, 24113, 24121, 24129, 24137,
4110
     24145, 24153, 24161, 24169, 24177, 24185, 24193, 24201, 24209, 24217,
4111
     24225, 24233, 24241, 24249, 24257, 24265, 24273, 24281, 24289, 24297,
4112
     24305, 24313, 24321, 24329, 24337, 24345, 24353, 24361, 24369, 24377,
4113
     24385, 24393, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4114
     24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4115
     24401, 24413, 24425, 24437, 24449, 24461, 24473, 24485, 24497, 24509,
4116
     24521, 24533, 24545, 24557, 24569, 24581, 24593, 24605, 24617, 24629,
4117
     24641, 24653, 24665, 24677, 24689, 24701, 24713, 24725, 24737, 24749,
4118
     24761, 24773, 24785, 24797, 24809, 24821, 24833, 24845, 24857, 24869,
4119
     24881, 24893, 24905, 24917, 24929, 24941, 24953, 24965, 24977, 24989,
4120
     25001, 25013, 25025, 25037, 25049, 25061, 25073, 25085, 25097, 25109,
4121
     25121, 25133, 25145, 25157, 25168, 25168, 25169, 25181, 25193, 25205,
4122
     25217, 25229, 25241, 25253, 25265, 25277, 25289, 25301, 25313, 25325,
4123
     25337, 25349, 25361, 25373, 25385, 25397, 25409, 25421, 25433, 25445,
4124
     25457, 25469, 25481, 25493, 25505, 25517, 25529, 25541, 25553, 25565,
4125
     25577, 25589, 25601, 25613, 25625, 25637, 25649, 25661, 25673, 25685,
4126
     25697, 25709, 25721, 25733, 25745, 25757, 25769, 25781, 25793, 25805,
4127
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4128
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4129
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4130
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4131
     25817, 25829, 25841, 25857, 25873, 25889, 25905, 25921, 25937, 25953,
4132
     25965, 26037, 26069, 26084, 26084, 26084, 26084},
4133
    {26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084,
4134
     26084, 26084, 26084, 26084, 26084, 26084, 26085, 26089, 26093, 26097,
4135
     26101, 26105, 26109, 26113, 26117, 26121, 26132, 26132, 26132, 26132,
4136
     26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132,
4137
     26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26133, 26141,
4138
     26145, 26149, 26153, 26157, 26161, 26165, 26169, 26173, 26177, 26181,
4139
     26185, 26189, 26193, 26197, 26201, 26205, 26209, 26213, 26217, 26220,
4140
     26220, 26221, 26225, 26229, 26237, 26245, 26253, 26261, 26265, 26269,
4141
     26273, 26277, 26281, 26284, 26285, 26289, 26293, 26297, 26301, 26305,
4142
     26309, 26313, 26317, 26321, 26325, 26329, 26333, 26337, 26341, 26345,
4143
     26349, 26353, 26357, 26360, 26361, 26365, 26369, 26373, 26376, 26376,
4144
     26376, 26376, 26377, 26385, 26393, 26400, 26401, 26408, 26409, 26417,
4145
     26425, 26433, 26441, 26449, 26457, 26465, 26473, 26481, 26489, 26493,
4146
     26501, 26509, 26517, 26525, 26533, 26541, 26549, 26557, 26565, 26573,
4147
     26581, 26589, 26593, 26597, 26601, 26605, 26609, 26613, 26617, 26621,
4148
     26625, 26629, 26633, 26637, 26641, 26645, 26649, 26653, 26657, 26661,
4149
     26665, 26669, 26673, 26677, 26681, 26685, 26689, 26693, 26697, 26701,
4150
     26705, 26709, 26713, 26717, 26721, 26725, 26729, 26733, 26737, 26741,
4151
     26745, 26749, 26753, 26757, 26761, 26765, 26769, 26773, 26777, 26781,
4152
     26785, 26789, 26793, 26797, 26801, 26805, 26809, 26813, 26817, 26821,
4153
     26825, 26829, 26833, 26837, 26841, 26845, 26849, 26853, 26857, 26861,
4154
     26865, 26869, 26873, 26877, 26881, 26885, 26889, 26893, 26897, 26901,
4155
     26905, 26909, 26913, 26917, 26921, 26925, 26929, 26933, 26937, 26941,
4156
     26945, 26949, 26953, 26957, 26961, 26965, 26969, 26973, 26977, 26981,
4157
     26985, 26989, 26993, 26997, 27001, 27005, 27017, 27029, 27041, 27053,
4158
     27065, 27077, 27085, 27092, 27092, 27092, 27092},
4159
    {27092, 27093, 27097, 27101, 27105, 27109, 27113, 27117, 27121, 27125,
4160
     27129, 27133, 27137, 27141, 27145, 27149, 27153, 27157, 27161, 27165,
4161
     27169, 27173, 27177, 27181, 27185, 27189, 27193, 27197, 27201, 27205,
4162
     27209, 27213, 27217, 27221, 27225, 27229, 27233, 27237, 27241, 27245,
4163
     27249, 27253, 27257, 27261, 27265, 27269, 27273, 27277, 27281, 27285,
4164
     27289, 27293, 27297, 27301, 27305, 27309, 27313, 27317, 27321, 27325,
4165
     27329, 27333, 27337, 27341, 27345, 27349, 27353, 27357, 27361, 27365,
4166
     27369, 27373, 27377, 27381, 27385, 27389, 27393, 27397, 27401, 27405,
4167
     27409, 27413, 27417, 27421, 27425, 27429, 27433, 27437, 27441, 27445,
4168
     27449, 27453, 27457, 27461, 27465, 27469, 27473, 27477, 27481, 27485,
4169
     27489, 27493, 27497, 27501, 27505, 27509, 27513, 27517, 27521, 27525,
4170
     27529, 27533, 27537, 27541, 27545, 27549, 27553, 27557, 27561, 27565,
4171
     27569, 27573, 27577, 27581, 27585, 27589, 27593, 27597, 27601, 27605,
4172
     27609, 27613, 27617, 27621, 27625, 27629, 27633, 27637, 27641, 27645,
4173
     27649, 27653, 27657, 27661, 27665, 27669, 27673, 27677, 27681, 27685,
4174
     27689, 27693, 27697, 27701, 27705, 27709, 27713, 27717, 27721, 27725,
4175
     27729, 27733, 27737, 27741, 27745, 27749, 27753, 27757, 27761, 27765,
4176
     27769, 27773, 27777, 27781, 27785, 27789, 27793, 27797, 27801, 27805,
4177
     27809, 27813, 27817, 27821, 27825, 27829, 27833, 27837, 27841, 27845,
4178
     27849, 27852, 27852, 27852, 27853, 27857, 27861, 27865, 27869, 27873,
4179
     27876, 27876, 27877, 27881, 27885, 27889, 27893, 27897, 27900, 27900,
4180
     27901, 27905, 27909, 27913, 27917, 27921, 27924, 27924, 27925, 27929,
4181
     27933, 27936, 27936, 27936, 27937, 27941, 27945, 27949, 27957, 27961,
4182
     27965, 27968, 27969, 27973, 27977, 27981, 27985, 27989, 27993, 27996,
4183
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4184
     27996, 27996, 27996, 27996, 27996, 27996, 27996},
4185
    {27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4186
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4187
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4188
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4189
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4190
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4191
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4192
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4193
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4194
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4195
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4196
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4197
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27997,
4198
     28001, 28005, 28009, 28013, 28016, 28017, 28021, 28025, 28029, 28033,
4199
     28037, 28041, 28045, 28049, 28053, 28057, 28061, 28065, 28069, 28073,
4200
     28077, 28081, 28085, 28089, 28093, 28097, 28101, 28105, 28109, 28113,
4201
     28117, 28121, 28125, 28129, 28133, 28137, 28141, 28145, 28149, 28153,
4202
     28157, 28161, 28165, 28169, 28173, 28177, 28181, 28184, 28185, 28189,
4203
     28193, 28197, 28201, 28205, 28209, 28213, 28217, 28220, 28220, 28220,
4204
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4205
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4206
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4207
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4208
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4209
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4210
     28220, 28220, 28220, 28220, 28220, 28220, 28220},
4211
    {28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4212
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4213
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4214
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4215
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4216
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4217
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4218
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4219
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4220
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4221
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4222
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4223
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4224
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4225
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4226
     28220, 28220, 28220, 28220, 28220, 28228, 28228, 28236, 28236, 28236,
4227
     28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236,
4228
     28236, 28236, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4229
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4230
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4231
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4232
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4233
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4234
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4235
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4236
     28244, 28244, 28244, 28244, 28244, 28244, 28244},
4237
    {28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4238
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4239
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4240
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4241
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28252, 28260, 28260,
4242
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4243
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4244
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4245
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4246
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4247
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4248
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4249
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4250
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4251
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4252
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4253
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4254
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4255
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4256
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4257
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4258
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4259
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4260
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4261
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4262
     28260, 28260, 28260, 28260, 28260, 28260, 28260},
4263
    {28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4264
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4265
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4266
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4267
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4268
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4269
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4270
     28260, 28260, 28260, 28260, 28260, 28260, 28268, 28276, 28276, 28276,
4271
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4272
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4273
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4274
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4275
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4276
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4277
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4278
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4279
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4280
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4281
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4282
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4283
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4284
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4285
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4286
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4287
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4288
     28276, 28276, 28276, 28276, 28276, 28276, 28276},
4289
    {28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4290
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4291
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4292
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4293
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4294
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4295
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4296
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4297
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4298
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4299
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4300
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4301
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4302
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4303
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4304
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4305
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4306
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4307
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28284, 28292,
4308
     28292, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4309
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4310
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4311
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4312
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4313
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4314
     28300, 28300, 28300, 28300, 28300, 28300, 28300},
4315
    {28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4316
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4317
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4318
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4319
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4320
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4321
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4322
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4323
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4324
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4325
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4326
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4327
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4328
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4329
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4330
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4331
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4332
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4333
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28308, 28316, 28316,
4334
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4335
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4336
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4337
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4338
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4339
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4340
     28316, 28316, 28316, 28316, 28316, 28316, 28316},
4341
    {28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4342
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4343
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4344
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4345
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4346
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28324, 28324, 28324,
4347
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4348
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4349
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4350
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4351
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4352
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4353
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4354
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4355
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4356
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4357
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4358
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4359
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4360
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4361
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4362
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4363
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4364
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4365
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4366
     28324, 28324, 28324, 28324, 28324, 28324, 28324},
4367
    {28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4368
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4369
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4370
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4371
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4372
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4373
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4374
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4375
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4376
     28324, 28324, 28324, 28324, 28324, 28332, 28340, 28352, 28364, 28376,
4377
     28388, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4378
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4379
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4380
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4381
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4382
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4383
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4384
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4385
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28408, 28416,
4386
     28428, 28440, 28452, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4387
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4388
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4389
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4390
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4391
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4392
     28464, 28464, 28464, 28464, 28464, 28464, 28464},
4393
    {28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4394
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4395
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4396
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4397
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4398
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4399
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4400
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4401
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4402
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4403
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4404
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4405
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4406
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4407
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4408
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4409
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4410
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4411
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4412
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4413
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4414
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4415
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4416
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4417
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4418
     28464, 28464, 28464, 28464, 28464, 28464, 28465},
4419
    {28465, 28469, 28473, 28477, 28481, 28485, 28489, 28493, 28497, 28501,
4420
     28505, 28509, 28513, 28517, 28521, 28525, 28529, 28533, 28537, 28541,
4421
     28545, 28549, 28553, 28557, 28561, 28565, 28569, 28573, 28577, 28581,
4422
     28585, 28589, 28593, 28597, 28601, 28605, 28609, 28613, 28617, 28621,
4423
     28625, 28629, 28633, 28637, 28641, 28645, 28649, 28653, 28657, 28661,
4424
     28665, 28669, 28673, 28677, 28681, 28685, 28689, 28693, 28697, 28701,
4425
     28705, 28709, 28713, 28717, 28721, 28725, 28729, 28733, 28737, 28741,
4426
     28745, 28749, 28753, 28757, 28761, 28765, 28769, 28773, 28777, 28781,
4427
     28785, 28789, 28793, 28797, 28801, 28804, 28805, 28809, 28813, 28817,
4428
     28821, 28825, 28829, 28833, 28837, 28841, 28845, 28849, 28853, 28857,
4429
     28861, 28865, 28869, 28873, 28877, 28881, 28885, 28889, 28893, 28897,
4430
     28901, 28905, 28909, 28913, 28917, 28921, 28925, 28929, 28933, 28937,
4431
     28941, 28945, 28949, 28953, 28957, 28961, 28965, 28969, 28973, 28977,
4432
     28981, 28985, 28989, 28993, 28997, 29001, 29005, 29009, 29013, 29017,
4433
     29021, 29025, 29029, 29033, 29037, 29041, 29045, 29049, 29053, 29057,
4434
     29061, 29065, 29069, 29073, 29077, 29081, 29085, 29088, 29089, 29093,
4435
     29096, 29096, 29097, 29100, 29100, 29101, 29105, 29108, 29108, 29109,
4436
     29113, 29117, 29121, 29124, 29125, 29129, 29133, 29137, 29141, 29145,
4437
     29149, 29153, 29157, 29161, 29165, 29169, 29172, 29173, 29176, 29177,
4438
     29181, 29185, 29189, 29193, 29197, 29201, 29204, 29205, 29209, 29213,
4439
     29217, 29221, 29225, 29229, 29233, 29237, 29241, 29245, 29249, 29253,
4440
     29257, 29261, 29265, 29269, 29273, 29277, 29281, 29285, 29289, 29293,
4441
     29297, 29301, 29305, 29309, 29313, 29317, 29321, 29325, 29329, 29333,
4442
     29337, 29341, 29345, 29349, 29353, 29357, 29361, 29365, 29369, 29373,
4443
     29377, 29381, 29385, 29389, 29393, 29397, 29401, 29405, 29409, 29413,
4444
     29417, 29421, 29425, 29429, 29433, 29437, 29441},
4445
    {29441, 29445, 29449, 29453, 29457, 29461, 29464, 29465, 29469, 29473,
4446
     29477, 29480, 29480, 29481, 29485, 29489, 29493, 29497, 29501, 29505,
4447
     29509, 29512, 29513, 29517, 29521, 29525, 29529, 29533, 29537, 29540,
4448
     29541, 29545, 29549, 29553, 29557, 29561, 29565, 29569, 29573, 29577,
4449
     29581, 29585, 29589, 29593, 29597, 29601, 29605, 29609, 29613, 29617,
4450
     29621, 29625, 29629, 29633, 29637, 29641, 29645, 29649, 29652, 29653,
4451
     29657, 29661, 29665, 29668, 29669, 29673, 29677, 29681, 29685, 29688,
4452
     29689, 29692, 29692, 29692, 29693, 29697, 29701, 29705, 29709, 29713,
4453
     29717, 29720, 29721, 29725, 29729, 29733, 29737, 29741, 29745, 29749,
4454
     29753, 29757, 29761, 29765, 29769, 29773, 29777, 29781, 29785, 29789,
4455
     29793, 29797, 29801, 29805, 29809, 29813, 29817, 29821, 29825, 29829,
4456
     29833, 29837, 29841, 29845, 29849, 29853, 29857, 29861, 29865, 29869,
4457
     29873, 29877, 29881, 29885, 29889, 29893, 29897, 29901, 29905, 29909,
4458
     29913, 29917, 29921, 29925, 29929, 29933, 29937, 29941, 29945, 29949,
4459
     29953, 29957, 29961, 29965, 29969, 29973, 29977, 29981, 29985, 29989,
4460
     29993, 29997, 30001, 30005, 30009, 30013, 30017, 30021, 30025, 30029,
4461
     30033, 30037, 30041, 30045, 30049, 30053, 30057, 30061, 30065, 30069,
4462
     30073, 30077, 30081, 30085, 30089, 30093, 30097, 30101, 30105, 30109,
4463
     30113, 30117, 30121, 30125, 30129, 30133, 30137, 30141, 30145, 30149,
4464
     30153, 30157, 30161, 30165, 30169, 30173, 30177, 30181, 30185, 30189,
4465
     30193, 30197, 30201, 30205, 30209, 30213, 30217, 30221, 30225, 30229,
4466
     30233, 30237, 30241, 30245, 30249, 30253, 30257, 30261, 30265, 30269,
4467
     30273, 30277, 30281, 30285, 30289, 30293, 30297, 30301, 30305, 30309,
4468
     30313, 30317, 30321, 30325, 30329, 30333, 30337, 30341, 30345, 30349,
4469
     30353, 30357, 30361, 30365, 30369, 30373, 30377, 30381, 30385, 30389,
4470
     30393, 30397, 30401, 30405, 30409, 30413, 30417},
4471
    {30417, 30421, 30425, 30429, 30433, 30437, 30441, 30445, 30449, 30453,
4472
     30457, 30461, 30465, 30469, 30473, 30477, 30481, 30485, 30489, 30493,
4473
     30497, 30501, 30505, 30509, 30513, 30517, 30521, 30525, 30529, 30533,
4474
     30537, 30541, 30545, 30549, 30553, 30557, 30561, 30565, 30569, 30573,
4475
     30577, 30581, 30585, 30589, 30593, 30597, 30601, 30605, 30609, 30613,
4476
     30617, 30621, 30625, 30629, 30633, 30637, 30641, 30645, 30649, 30653,
4477
     30657, 30661, 30665, 30669, 30673, 30677, 30681, 30685, 30689, 30693,
4478
     30697, 30701, 30705, 30709, 30713, 30717, 30721, 30725, 30729, 30733,
4479
     30737, 30741, 30745, 30749, 30753, 30757, 30761, 30765, 30769, 30773,
4480
     30777, 30781, 30785, 30789, 30793, 30797, 30801, 30805, 30809, 30813,
4481
     30817, 30821, 30825, 30829, 30833, 30837, 30841, 30845, 30849, 30853,
4482
     30857, 30861, 30865, 30869, 30873, 30877, 30881, 30885, 30889, 30893,
4483
     30897, 30901, 30905, 30909, 30913, 30917, 30921, 30925, 30929, 30933,
4484
     30937, 30941, 30945, 30949, 30953, 30957, 30961, 30965, 30969, 30973,
4485
     30977, 30981, 30985, 30989, 30993, 30997, 31001, 31005, 31009, 31013,
4486
     31017, 31021, 31025, 31029, 31033, 31037, 31041, 31045, 31049, 31053,
4487
     31057, 31061, 31065, 31069, 31073, 31077, 31080, 31080, 31081, 31085,
4488
     31089, 31093, 31097, 31101, 31105, 31109, 31113, 31117, 31121, 31125,
4489
     31129, 31133, 31137, 31141, 31145, 31149, 31153, 31157, 31161, 31165,
4490
     31169, 31173, 31177, 31181, 31185, 31189, 31193, 31197, 31201, 31205,
4491
     31209, 31213, 31217, 31221, 31225, 31229, 31233, 31237, 31241, 31245,
4492
     31249, 31253, 31257, 31261, 31265, 31269, 31273, 31277, 31281, 31285,
4493
     31289, 31293, 31297, 31301, 31305, 31309, 31313, 31317, 31321, 31325,
4494
     31329, 31333, 31337, 31341, 31345, 31349, 31353, 31357, 31361, 31365,
4495
     31369, 31373, 31377, 31381, 31385, 31389, 31393, 31397, 31401, 31405,
4496
     31409, 31413, 31417, 31421, 31425, 31429, 31433},
4497
    {31433, 31437, 31441, 31445, 31449, 31453, 31457, 31461, 31465, 31469,
4498
     31473, 31477, 31481, 31485, 31489, 31493, 31497, 31501, 31505, 31509,
4499
     31513, 31517, 31521, 31525, 31529, 31533, 31537, 31541, 31545, 31549,
4500
     31553, 31557, 31561, 31565, 31569, 31573, 31577, 31581, 31585, 31589,
4501
     31593, 31597, 31601, 31605, 31609, 31613, 31617, 31621, 31625, 31629,
4502
     31633, 31637, 31641, 31645, 31649, 31653, 31657, 31661, 31665, 31669,
4503
     31673, 31677, 31681, 31685, 31689, 31693, 31697, 31701, 31705, 31709,
4504
     31713, 31717, 31721, 31725, 31729, 31733, 31737, 31741, 31745, 31749,
4505
     31753, 31757, 31761, 31765, 31769, 31773, 31777, 31781, 31785, 31789,
4506
     31793, 31797, 31801, 31805, 31809, 31813, 31817, 31821, 31825, 31829,
4507
     31833, 31837, 31841, 31845, 31849, 31853, 31857, 31861, 31865, 31869,
4508
     31873, 31877, 31881, 31885, 31889, 31893, 31897, 31901, 31905, 31909,
4509
     31913, 31917, 31921, 31925, 31929, 31933, 31937, 31941, 31945, 31949,
4510
     31953, 31957, 31961, 31965, 31969, 31973, 31977, 31981, 31985, 31989,
4511
     31993, 31997, 32001, 32005, 32009, 32013, 32017, 32021, 32025, 32029,
4512
     32033, 32037, 32041, 32045, 32049, 32053, 32057, 32061, 32065, 32069,
4513
     32073, 32077, 32081, 32085, 32089, 32093, 32097, 32101, 32105, 32109,
4514
     32113, 32117, 32121, 32125, 32129, 32133, 32137, 32141, 32145, 32149,
4515
     32153, 32157, 32161, 32165, 32169, 32173, 32177, 32181, 32185, 32189,
4516
     32193, 32197, 32201, 32205, 32209, 32213, 32217, 32221, 32225, 32229,
4517
     32233, 32237, 32241, 32245, 32248, 32248, 32249, 32253, 32257, 32261,
4518
     32265, 32269, 32273, 32277, 32281, 32285, 32289, 32293, 32297, 32301,
4519
     32305, 32309, 32313, 32317, 32321, 32325, 32329, 32333, 32337, 32341,
4520
     32345, 32349, 32353, 32357, 32361, 32365, 32369, 32373, 32377, 32381,
4521
     32385, 32389, 32393, 32397, 32401, 32405, 32409, 32413, 32417, 32421,
4522
     32425, 32429, 32433, 32437, 32441, 32445, 32448},
4523
    {32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4524
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4525
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4526
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4527
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32449, 32453,
4528
     32457, 32461, 32465, 32469, 32473, 32477, 32481, 32485, 32489, 32493,
4529
     32497, 32501, 32505, 32509, 32513, 32517, 32521, 32525, 32529, 32533,
4530
     32537, 32541, 32545, 32549, 32553, 32557, 32561, 32565, 32569, 32573,
4531
     32577, 32581, 32585, 32589, 32593, 32597, 32601, 32605, 32609, 32613,
4532
     32617, 32621, 32625, 32629, 32633, 32637, 32641, 32645, 32649, 32653,
4533
     32657, 32661, 32665, 32669, 32673, 32677, 32681, 32685, 32689, 32693,
4534
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4535
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4536
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4537
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4538
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4539
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4540
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4541
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4542
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4543
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4544
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4545
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4546
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4547
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4548
     32696, 32696, 32696, 32696, 32696, 32696, 32696},
4549
    {32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4550
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4551
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4552
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4553
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4554
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4555
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4556
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4557
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4558
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4559
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4560
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4561
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4562
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4563
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4564
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4565
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4566
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4567
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4568
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4569
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4570
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4571
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4572
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4573
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4574
     32696, 32696, 32696, 32696, 32696, 32696, 32697},
4575
    {32697, 32701, 32705, 32709, 32712, 32713, 32717, 32721, 32725, 32729,
4576
     32733, 32737, 32741, 32745, 32749, 32753, 32757, 32761, 32765, 32769,
4577
     32773, 32777, 32781, 32785, 32789, 32793, 32797, 32801, 32805, 32809,
4578
     32813, 32817, 32820, 32821, 32825, 32828, 32829, 32832, 32832, 32833,
4579
     32836, 32837, 32841, 32845, 32849, 32853, 32857, 32861, 32865, 32869,
4580
     32873, 32876, 32877, 32881, 32885, 32889, 32892, 32893, 32896, 32897,
4581
     32900, 32900, 32900, 32900, 32900, 32900, 32901, 32904, 32904, 32904,
4582
     32904, 32905, 32908, 32909, 32912, 32913, 32916, 32917, 32921, 32925,
4583
     32928, 32929, 32933, 32936, 32937, 32940, 32940, 32941, 32944, 32945,
4584
     32948, 32949, 32952, 32953, 32956, 32957, 32960, 32961, 32965, 32968,
4585
     32969, 32972, 32972, 32973, 32977, 32981, 32985, 32988, 32989, 32993,
4586
     32997, 33001, 33005, 33009, 33013, 33016, 33017, 33021, 33025, 33029,
4587
     33032, 33033, 33037, 33041, 33045, 33048, 33049, 33052, 33053, 33057,
4588
     33061, 33065, 33069, 33073, 33077, 33081, 33085, 33089, 33092, 33093,
4589
     33097, 33101, 33105, 33109, 33113, 33117, 33121, 33125, 33129, 33133,
4590
     33137, 33141, 33145, 33149, 33153, 33157, 33160, 33160, 33160, 33160,
4591
     33160, 33161, 33165, 33169, 33172, 33173, 33177, 33181, 33185, 33189,
4592
     33192, 33193, 33197, 33201, 33205, 33209, 33213, 33217, 33221, 33225,
4593
     33229, 33233, 33237, 33241, 33245, 33249, 33253, 33257, 33260, 33260,
4594
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4595
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4596
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4597
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4598
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4599
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4600
     33260, 33260, 33260, 33260, 33260, 33260, 33260},
4601
    {33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4602
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4603
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4604
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4605
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4606
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4607
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4608
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4609
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4610
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4611
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4612
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4613
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4614
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4615
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4616
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4617
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4618
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4619
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4620
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4621
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4622
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4623
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4624
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4625
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4626
     33260, 33260, 33260, 33260, 33260, 33260, 33261},
4627
    {33261, 33269, 33277, 33285, 33293, 33301, 33309, 33317, 33325, 33333,
4628
     33341, 33348, 33348, 33348, 33348, 33348, 33349, 33361, 33373, 33385,
4629
     33397, 33409, 33421, 33433, 33445, 33457, 33469, 33481, 33493, 33505,
4630
     33517, 33529, 33541, 33553, 33565, 33577, 33589, 33601, 33613, 33625,
4631
     33637, 33649, 33661, 33673, 33677, 33681, 33689, 33696, 33697, 33701,
4632
     33705, 33709, 33713, 33717, 33721, 33725, 33729, 33733, 33737, 33741,
4633
     33745, 33749, 33753, 33757, 33761, 33765, 33769, 33773, 33777, 33781,
4634
     33785, 33789, 33793, 33797, 33801, 33809, 33817, 33825, 33833, 33845,
4635
     33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4636
     33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4637
     33852, 33852, 33852, 33852, 33852, 33852, 33853, 33861, 33869, 33876,
4638
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4639
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4640
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4641
     33876, 33876, 33876, 33876, 33877, 33884, 33884, 33884, 33884, 33884,
4642
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4643
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4644
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4645
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4646
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4647
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4648
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4649
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4650
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4651
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4652
     33884, 33884, 33884, 33884, 33884, 33884, 33885},
4653
    {33885, 33893, 33901, 33904, 33904, 33904, 33904, 33904, 33904, 33904,
4654
     33904, 33904, 33904, 33904, 33904, 33904, 33905, 33909, 33913, 33917,
4655
     33925, 33929, 33933, 33937, 33941, 33945, 33949, 33953, 33957, 33961,
4656
     33965, 33969, 33973, 33977, 33981, 33985, 33989, 33993, 33997, 34001,
4657
     34005, 34009, 34013, 34017, 34021, 34025, 34029, 34033, 34037, 34041,
4658
     34045, 34049, 34053, 34057, 34061, 34065, 34069, 34073, 34077, 34081,
4659
     34084, 34084, 34084, 34084, 34085, 34097, 34109, 34121, 34133, 34145,
4660
     34157, 34169, 34181, 34192, 34192, 34192, 34192, 34192, 34192, 34192,
4661
     34193, 34197, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4662
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4663
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4664
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4665
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4666
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4667
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4668
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4669
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4670
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4671
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4672
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4673
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4674
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4675
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4676
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4677
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4678
     34200, 34200, 34200, 34200, 34200, 34200, 34200},
4679
    {34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4680
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4681
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4682
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4683
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4684
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4685
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4686
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4687
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4688
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4689
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4690
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4691
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4692
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4693
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4694
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4695
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4696
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4697
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4698
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4699
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4700
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4701
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4702
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4703
     34201, 34205, 34209, 34213, 34217, 34221, 34225, 34229, 34233, 34237,
4704
     34240, 34240, 34240, 34240, 34240, 34240, 34240},
4705
    {34240, 34244, 34248, 34252, 34256, 34260, 34264, 34268, 34272, 34276,
4706
     34280, 34284, 34288, 34292, 34296, 34300, 34304, 34308, 34312, 34316,
4707
     34320, 34324, 34328, 34332, 34336, 34340, 34344, 34348, 34352, 34356,
4708
     34360, 34364, 34368, 34372, 34376, 34380, 34384, 34388, 34392, 34396,
4709
     34400, 34404, 34408, 34412, 34416, 34420, 34424, 34428, 34432, 34436,
4710
     34440, 34444, 34448, 34452, 34456, 34460, 34464, 34468, 34472, 34476,
4711
     34480, 34484, 34488, 34492, 34496, 34500, 34504, 34508, 34512, 34516,
4712
     34520, 34524, 34528, 34532, 34536, 34540, 34544, 34548, 34552, 34556,
4713
     34560, 34564, 34568, 34572, 34576, 34580, 34584, 34588, 34592, 34596,
4714
     34600, 34604, 34608, 34612, 34616, 34620, 34624, 34628, 34632, 34636,
4715
     34640, 34644, 34648, 34652, 34656, 34660, 34664, 34668, 34672, 34676,
4716
     34680, 34684, 34688, 34692, 34696, 34700, 34704, 34708, 34712, 34716,
4717
     34720, 34724, 34728, 34732, 34736, 34740, 34744, 34748, 34752, 34756,
4718
     34760, 34764, 34768, 34772, 34776, 34780, 34784, 34788, 34792, 34796,
4719
     34800, 34804, 34808, 34812, 34816, 34820, 34824, 34828, 34832, 34836,
4720
     34840, 34844, 34848, 34852, 34856, 34860, 34864, 34868, 34872, 34876,
4721
     34880, 34884, 34888, 34892, 34896, 34900, 34904, 34908, 34912, 34916,
4722
     34920, 34924, 34928, 34932, 34936, 34940, 34944, 34948, 34952, 34956,
4723
     34960, 34964, 34968, 34972, 34976, 34980, 34984, 34988, 34992, 34996,
4724
     35000, 35004, 35008, 35012, 35016, 35020, 35024, 35028, 35032, 35036,
4725
     35040, 35044, 35048, 35052, 35056, 35060, 35064, 35068, 35072, 35076,
4726
     35080, 35084, 35088, 35092, 35096, 35100, 35104, 35108, 35112, 35116,
4727
     35120, 35124, 35128, 35132, 35136, 35140, 35144, 35148, 35152, 35156,
4728
     35160, 35164, 35168, 35172, 35176, 35180, 35184, 35188, 35192, 35196,
4729
     35200, 35204, 35208, 35212, 35216, 35220, 35224, 35228, 35232, 35236,
4730
     35240, 35244, 35248, 35252, 35256, 35260, 35264},
4731
    {35264, 35268, 35272, 35276, 35280, 35284, 35288, 35292, 35296, 35300,
4732
     35304, 35308, 35312, 35316, 35320, 35324, 35328, 35332, 35336, 35340,
4733
     35344, 35348, 35352, 35356, 35360, 35364, 35368, 35372, 35376, 35380,
4734
     35384, 35388, 35392, 35396, 35400, 35404, 35408, 35412, 35416, 35420,
4735
     35424, 35428, 35432, 35436, 35440, 35444, 35448, 35452, 35456, 35460,
4736
     35464, 35468, 35472, 35476, 35480, 35484, 35488, 35492, 35496, 35500,
4737
     35504, 35508, 35512, 35516, 35520, 35524, 35528, 35532, 35536, 35540,
4738
     35544, 35548, 35552, 35556, 35560, 35564, 35568, 35572, 35576, 35580,
4739
     35584, 35588, 35592, 35596, 35600, 35604, 35608, 35612, 35616, 35620,
4740
     35624, 35628, 35632, 35636, 35640, 35644, 35648, 35652, 35656, 35660,
4741
     35664, 35668, 35672, 35676, 35680, 35684, 35688, 35692, 35696, 35700,
4742
     35704, 35708, 35712, 35716, 35720, 35724, 35728, 35732, 35736, 35740,
4743
     35744, 35748, 35752, 35756, 35760, 35764, 35768, 35772, 35776, 35780,
4744
     35784, 35788, 35792, 35796, 35800, 35804, 35808, 35812, 35816, 35820,
4745
     35824, 35828, 35832, 35836, 35840, 35844, 35848, 35852, 35856, 35860,
4746
     35864, 35868, 35872, 35876, 35880, 35884, 35888, 35892, 35896, 35900,
4747
     35904, 35908, 35912, 35916, 35920, 35924, 35928, 35932, 35936, 35940,
4748
     35944, 35948, 35952, 35956, 35960, 35964, 35968, 35972, 35976, 35980,
4749
     35984, 35988, 35992, 35996, 36000, 36004, 36008, 36012, 36016, 36020,
4750
     36024, 36028, 36032, 36036, 36040, 36044, 36048, 36052, 36056, 36060,
4751
     36064, 36068, 36072, 36076, 36080, 36084, 36088, 36092, 36096, 36100,
4752
     36104, 36108, 36112, 36116, 36120, 36124, 36128, 36132, 36136, 36140,
4753
     36144, 36148, 36152, 36156, 36160, 36164, 36168, 36172, 36176, 36180,
4754
     36184, 36188, 36192, 36196, 36200, 36204, 36208, 36212, 36216, 36220,
4755
     36224, 36228, 36232, 36236, 36240, 36244, 36248, 36252, 36256, 36260,
4756
     36264, 36268, 36272, 36276, 36280, 36284, 36288},
4757
    {36288, 36292, 36296, 36300, 36304, 36308, 36312, 36316, 36320, 36324,
4758
     36328, 36332, 36336, 36340, 36344, 36348, 36352, 36356, 36360, 36364,
4759
     36368, 36372, 36376, 36380, 36384, 36388, 36392, 36396, 36400, 36404,
4760
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4761
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4762
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4763
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4764
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4765
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4766
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4767
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4768
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4769
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4770
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4771
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4772
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4773
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4774
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4775
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4776
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4777
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4778
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4779
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4780
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4781
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4782
     36408, 36408, 36408, 36408, 36408, 36408, 36408}};
4783
const char32_t decomposition_data[9102] = {
4784
    0,      32,     32,     776,    97,     32,     772,    50,     51,
4785
    32,     769,    956,    32,     807,    49,     111,    49,     8260,
4786
    52,     49,     8260,   50,     51,     8260,   52,     65,     768,
4787
    65,     769,    65,     770,    65,     771,    65,     776,    65,
4788
    778,    67,     807,    69,     768,    69,     769,    69,     770,
4789
    69,     776,    73,     768,    73,     769,    73,     770,    73,
4790
    776,    78,     771,    79,     768,    79,     769,    79,     770,
4791
    79,     771,    79,     776,    85,     768,    85,     769,    85,
4792
    770,    85,     776,    89,     769,    97,     768,    97,     769,
4793
    97,     770,    97,     771,    97,     776,    97,     778,    99,
4794
    807,    101,    768,    101,    769,    101,    770,    101,    776,
4795
    105,    768,    105,    769,    105,    770,    105,    776,    110,
4796
    771,    111,    768,    111,    769,    111,    770,    111,    771,
4797
    111,    776,    117,    768,    117,    769,    117,    770,    117,
4798
    776,    121,    769,    121,    776,    65,     772,    97,     772,
4799
    65,     774,    97,     774,    65,     808,    97,     808,    67,
4800
    769,    99,     769,    67,     770,    99,     770,    67,     775,
4801
    99,     775,    67,     780,    99,     780,    68,     780,    100,
4802
    780,    69,     772,    101,    772,    69,     774,    101,    774,
4803
    69,     775,    101,    775,    69,     808,    101,    808,    69,
4804
    780,    101,    780,    71,     770,    103,    770,    71,     774,
4805
    103,    774,    71,     775,    103,    775,    71,     807,    103,
4806
    807,    72,     770,    104,    770,    73,     771,    105,    771,
4807
    73,     772,    105,    772,    73,     774,    105,    774,    73,
4808
    808,    105,    808,    73,     775,    73,     74,     105,    106,
4809
    74,     770,    106,    770,    75,     807,    107,    807,    76,
4810
    769,    108,    769,    76,     807,    108,    807,    76,     780,
4811
    108,    780,    76,     183,    108,    183,    78,     769,    110,
4812
    769,    78,     807,    110,    807,    78,     780,    110,    780,
4813
    700,    110,    79,     772,    111,    772,    79,     774,    111,
4814
    774,    79,     779,    111,    779,    82,     769,    114,    769,
4815
    82,     807,    114,    807,    82,     780,    114,    780,    83,
4816
    769,    115,    769,    83,     770,    115,    770,    83,     807,
4817
    115,    807,    83,     780,    115,    780,    84,     807,    116,
4818
    807,    84,     780,    116,    780,    85,     771,    117,    771,
4819
    85,     772,    117,    772,    85,     774,    117,    774,    85,
4820
    778,    117,    778,    85,     779,    117,    779,    85,     808,
4821
    117,    808,    87,     770,    119,    770,    89,     770,    121,
4822
    770,    89,     776,    90,     769,    122,    769,    90,     775,
4823
    122,    775,    90,     780,    122,    780,    115,    79,     795,
4824
    111,    795,    85,     795,    117,    795,    68,     90,     780,
4825
    68,     122,    780,    100,    122,    780,    76,     74,     76,
4826
    106,    108,    106,    78,     74,     78,     106,    110,    106,
4827
    65,     780,    97,     780,    73,     780,    105,    780,    79,
4828
    780,    111,    780,    85,     780,    117,    780,    85,     776,
4829
    772,    117,    776,    772,    85,     776,    769,    117,    776,
4830
    769,    85,     776,    780,    117,    776,    780,    85,     776,
4831
    768,    117,    776,    768,    65,     776,    772,    97,     776,
4832
    772,    65,     775,    772,    97,     775,    772,    198,    772,
4833
    230,    772,    71,     780,    103,    780,    75,     780,    107,
4834
    780,    79,     808,    111,    808,    79,     808,    772,    111,
4835
    808,    772,    439,    780,    658,    780,    106,    780,    68,
4836
    90,     68,     122,    100,    122,    71,     769,    103,    769,
4837
    78,     768,    110,    768,    65,     778,    769,    97,     778,
4838
    769,    198,    769,    230,    769,    216,    769,    248,    769,
4839
    65,     783,    97,     783,    65,     785,    97,     785,    69,
4840
    783,    101,    783,    69,     785,    101,    785,    73,     783,
4841
    105,    783,    73,     785,    105,    785,    79,     783,    111,
4842
    783,    79,     785,    111,    785,    82,     783,    114,    783,
4843
    82,     785,    114,    785,    85,     783,    117,    783,    85,
4844
    785,    117,    785,    83,     806,    115,    806,    84,     806,
4845
    116,    806,    72,     780,    104,    780,    65,     775,    97,
4846
    775,    69,     807,    101,    807,    79,     776,    772,    111,
4847
    776,    772,    79,     771,    772,    111,    771,    772,    79,
4848
    775,    111,    775,    79,     775,    772,    111,    775,    772,
4849
    89,     772,    121,    772,    104,    614,    106,    114,    633,
4850
    635,    641,    119,    121,    32,     774,    32,     775,    32,
4851
    778,    32,     808,    32,     771,    32,     779,    611,    108,
4852
    115,    120,    661,    768,    769,    787,    776,    769,    697,
4853
    32,     837,    59,     32,     769,    168,    769,    913,    769,
4854
    183,    917,    769,    919,    769,    921,    769,    927,    769,
4855
    933,    769,    937,    769,    953,    776,    769,    921,    776,
4856
    933,    776,    945,    769,    949,    769,    951,    769,    953,
4857
    769,    965,    776,    769,    953,    776,    965,    776,    959,
4858
    769,    965,    769,    969,    769,    946,    952,    933,    978,
4859
    769,    978,    776,    966,    960,    954,    961,    962,    920,
4860
    949,    931,    1045,   768,    1045,   776,    1043,   769,    1030,
4861
    776,    1050,   769,    1048,   768,    1059,   774,    1048,   774,
4862
    1080,   774,    1077,   768,    1077,   776,    1075,   769,    1110,
4863
    776,    1082,   769,    1080,   768,    1091,   774,    1140,   783,
4864
    1141,   783,    1046,   774,    1078,   774,    1040,   774,    1072,
4865
    774,    1040,   776,    1072,   776,    1045,   774,    1077,   774,
4866
    1240,   776,    1241,   776,    1046,   776,    1078,   776,    1047,
4867
    776,    1079,   776,    1048,   772,    1080,   772,    1048,   776,
4868
    1080,   776,    1054,   776,    1086,   776,    1256,   776,    1257,
4869
    776,    1069,   776,    1101,   776,    1059,   772,    1091,   772,
4870
    1059,   776,    1091,   776,    1059,   779,    1091,   779,    1063,
4871
    776,    1095,   776,    1067,   776,    1099,   776,    1381,   1410,
4872
    1575,   1619,   1575,   1620,   1608,   1620,   1575,   1621,   1610,
4873
    1620,   1575,   1652,   1608,   1652,   1735,   1652,   1610,   1652,
4874
    1749,   1620,   1729,   1620,   1746,   1620,   2344,   2364,   2352,
4875
    2364,   2355,   2364,   2325,   2364,   2326,   2364,   2327,   2364,
4876
    2332,   2364,   2337,   2364,   2338,   2364,   2347,   2364,   2351,
4877
    2364,   2503,   2494,   2503,   2519,   2465,   2492,   2466,   2492,
4878
    2479,   2492,   2610,   2620,   2616,   2620,   2582,   2620,   2583,
4879
    2620,   2588,   2620,   2603,   2620,   2887,   2902,   2887,   2878,
4880
    2887,   2903,   2849,   2876,   2850,   2876,   2962,   3031,   3014,
4881
    3006,   3015,   3006,   3014,   3031,   3142,   3158,   3263,   3285,
4882
    3270,   3285,   3270,   3286,   3270,   3266,   3270,   3266,   3285,
4883
    3398,   3390,   3399,   3390,   3398,   3415,   3545,   3530,   3545,
4884
    3535,   3545,   3535,   3530,   3545,   3551,   3661,   3634,   3789,
4885
    3762,   3755,   3737,   3755,   3745,   3851,   3906,   4023,   3916,
4886
    4023,   3921,   4023,   3926,   4023,   3931,   4023,   3904,   4021,
4887
    3953,   3954,   3953,   3956,   4018,   3968,   4018,   3953,   3968,
4888
    4019,   3968,   4019,   3953,   3968,   3953,   3968,   3986,   4023,
4889
    3996,   4023,   4001,   4023,   4006,   4023,   4011,   4023,   3984,
4890
    4021,   4133,   4142,   4316,   6917,   6965,   6919,   6965,   6921,
4891
    6965,   6923,   6965,   6925,   6965,   6929,   6965,   6970,   6965,
4892
    6972,   6965,   6974,   6965,   6975,   6965,   6978,   6965,   65,
4893
    198,    66,     68,     69,     398,    71,     72,     73,     74,
4894
    75,     76,     77,     78,     79,     546,    80,     82,     84,
4895
    85,     87,     97,     592,    593,    7426,   98,     100,    101,
4896
    601,    603,    604,    103,    107,    109,    331,    111,    596,
4897
    7446,   7447,   112,    116,    117,    7453,   623,    118,    7461,
4898
    946,    947,    948,    966,    967,    105,    114,    117,    118,
4899
    946,    947,    961,    966,    967,    1085,   594,    99,     597,
4900
    240,    604,    102,    607,    609,    613,    616,    617,    618,
4901
    7547,   669,    621,    7557,   671,    625,    624,    626,    627,
4902
    628,    629,    632,    642,    643,    427,    649,    650,    7452,
4903
    651,    652,    122,    656,    657,    658,    952,    65,     805,
4904
    97,     805,    66,     775,    98,     775,    66,     803,    98,
4905
    803,    66,     817,    98,     817,    67,     807,    769,    99,
4906
    807,    769,    68,     775,    100,    775,    68,     803,    100,
4907
    803,    68,     817,    100,    817,    68,     807,    100,    807,
4908
    68,     813,    100,    813,    69,     772,    768,    101,    772,
4909
    768,    69,     772,    769,    101,    772,    769,    69,     813,
4910
    101,    813,    69,     816,    101,    816,    69,     807,    774,
4911
    101,    807,    774,    70,     775,    102,    775,    71,     772,
4912
    103,    772,    72,     775,    104,    775,    72,     803,    104,
4913
    803,    72,     776,    104,    776,    72,     807,    104,    807,
4914
    72,     814,    104,    814,    73,     816,    105,    816,    73,
4915
    776,    769,    105,    776,    769,    75,     769,    107,    769,
4916
    75,     803,    107,    803,    75,     817,    107,    817,    76,
4917
    803,    108,    803,    76,     803,    772,    108,    803,    772,
4918
    76,     817,    108,    817,    76,     813,    108,    813,    77,
4919
    769,    109,    769,    77,     775,    109,    775,    77,     803,
4920
    109,    803,    78,     775,    110,    775,    78,     803,    110,
4921
    803,    78,     817,    110,    817,    78,     813,    110,    813,
4922
    79,     771,    769,    111,    771,    769,    79,     771,    776,
4923
    111,    771,    776,    79,     772,    768,    111,    772,    768,
4924
    79,     772,    769,    111,    772,    769,    80,     769,    112,
4925
    769,    80,     775,    112,    775,    82,     775,    114,    775,
4926
    82,     803,    114,    803,    82,     803,    772,    114,    803,
4927
    772,    82,     817,    114,    817,    83,     775,    115,    775,
4928
    83,     803,    115,    803,    83,     769,    775,    115,    769,
4929
    775,    83,     780,    775,    115,    780,    775,    83,     803,
4930
    775,    115,    803,    775,    84,     775,    116,    775,    84,
4931
    803,    116,    803,    84,     817,    116,    817,    84,     813,
4932
    116,    813,    85,     804,    117,    804,    85,     816,    117,
4933
    816,    85,     813,    117,    813,    85,     771,    769,    117,
4934
    771,    769,    85,     772,    776,    117,    772,    776,    86,
4935
    771,    118,    771,    86,     803,    118,    803,    87,     768,
4936
    119,    768,    87,     769,    119,    769,    87,     776,    119,
4937
    776,    87,     775,    119,    775,    87,     803,    119,    803,
4938
    88,     775,    120,    775,    88,     776,    120,    776,    89,
4939
    775,    121,    775,    90,     770,    122,    770,    90,     803,
4940
    122,    803,    90,     817,    122,    817,    104,    817,    116,
4941
    776,    119,    778,    121,    778,    97,     702,    383,    775,
4942
    65,     803,    97,     803,    65,     777,    97,     777,    65,
4943
    770,    769,    97,     770,    769,    65,     770,    768,    97,
4944
    770,    768,    65,     770,    777,    97,     770,    777,    65,
4945
    770,    771,    97,     770,    771,    65,     803,    770,    97,
4946
    803,    770,    65,     774,    769,    97,     774,    769,    65,
4947
    774,    768,    97,     774,    768,    65,     774,    777,    97,
4948
    774,    777,    65,     774,    771,    97,     774,    771,    65,
4949
    803,    774,    97,     803,    774,    69,     803,    101,    803,
4950
    69,     777,    101,    777,    69,     771,    101,    771,    69,
4951
    770,    769,    101,    770,    769,    69,     770,    768,    101,
4952
    770,    768,    69,     770,    777,    101,    770,    777,    69,
4953
    770,    771,    101,    770,    771,    69,     803,    770,    101,
4954
    803,    770,    73,     777,    105,    777,    73,     803,    105,
4955
    803,    79,     803,    111,    803,    79,     777,    111,    777,
4956
    79,     770,    769,    111,    770,    769,    79,     770,    768,
4957
    111,    770,    768,    79,     770,    777,    111,    770,    777,
4958
    79,     770,    771,    111,    770,    771,    79,     803,    770,
4959
    111,    803,    770,    79,     795,    769,    111,    795,    769,
4960
    79,     795,    768,    111,    795,    768,    79,     795,    777,
4961
    111,    795,    777,    79,     795,    771,    111,    795,    771,
4962
    79,     795,    803,    111,    795,    803,    85,     803,    117,
4963
    803,    85,     777,    117,    777,    85,     795,    769,    117,
4964
    795,    769,    85,     795,    768,    117,    795,    768,    85,
4965
    795,    777,    117,    795,    777,    85,     795,    771,    117,
4966
    795,    771,    85,     795,    803,    117,    795,    803,    89,
4967
    768,    121,    768,    89,     803,    121,    803,    89,     777,
4968
    121,    777,    89,     771,    121,    771,    945,    787,    945,
4969
    788,    945,    787,    768,    945,    788,    768,    945,    787,
4970
    769,    945,    788,    769,    945,    787,    834,    945,    788,
4971
    834,    913,    787,    913,    788,    913,    787,    768,    913,
4972
    788,    768,    913,    787,    769,    913,    788,    769,    913,
4973
    787,    834,    913,    788,    834,    949,    787,    949,    788,
4974
    949,    787,    768,    949,    788,    768,    949,    787,    769,
4975
    949,    788,    769,    917,    787,    917,    788,    917,    787,
4976
    768,    917,    788,    768,    917,    787,    769,    917,    788,
4977
    769,    951,    787,    951,    788,    951,    787,    768,    951,
4978
    788,    768,    951,    787,    769,    951,    788,    769,    951,
4979
    787,    834,    951,    788,    834,    919,    787,    919,    788,
4980
    919,    787,    768,    919,    788,    768,    919,    787,    769,
4981
    919,    788,    769,    919,    787,    834,    919,    788,    834,
4982
    953,    787,    953,    788,    953,    787,    768,    953,    788,
4983
    768,    953,    787,    769,    953,    788,    769,    953,    787,
4984
    834,    953,    788,    834,    921,    787,    921,    788,    921,
4985
    787,    768,    921,    788,    768,    921,    787,    769,    921,
4986
    788,    769,    921,    787,    834,    921,    788,    834,    959,
4987
    787,    959,    788,    959,    787,    768,    959,    788,    768,
4988
    959,    787,    769,    959,    788,    769,    927,    787,    927,
4989
    788,    927,    787,    768,    927,    788,    768,    927,    787,
4990
    769,    927,    788,    769,    965,    787,    965,    788,    965,
4991
    787,    768,    965,    788,    768,    965,    787,    769,    965,
4992
    788,    769,    965,    787,    834,    965,    788,    834,    933,
4993
    788,    933,    788,    768,    933,    788,    769,    933,    788,
4994
    834,    969,    787,    969,    788,    969,    787,    768,    969,
4995
    788,    768,    969,    787,    769,    969,    788,    769,    969,
4996
    787,    834,    969,    788,    834,    937,    787,    937,    788,
4997
    937,    787,    768,    937,    788,    768,    937,    787,    769,
4998
    937,    788,    769,    937,    787,    834,    937,    788,    834,
4999
    945,    768,    945,    769,    949,    768,    949,    769,    951,
5000
    768,    951,    769,    953,    768,    953,    769,    959,    768,
5001
    959,    769,    965,    768,    965,    769,    969,    768,    969,
5002
    769,    945,    787,    837,    945,    788,    837,    945,    787,
5003
    768,    837,    945,    788,    768,    837,    945,    787,    769,
5004
    837,    945,    788,    769,    837,    945,    787,    834,    837,
5005
    945,    788,    834,    837,    913,    787,    837,    913,    788,
5006
    837,    913,    787,    768,    837,    913,    788,    768,    837,
5007
    913,    787,    769,    837,    913,    788,    769,    837,    913,
5008
    787,    834,    837,    913,    788,    834,    837,    951,    787,
5009
    837,    951,    788,    837,    951,    787,    768,    837,    951,
5010
    788,    768,    837,    951,    787,    769,    837,    951,    788,
5011
    769,    837,    951,    787,    834,    837,    951,    788,    834,
5012
    837,    919,    787,    837,    919,    788,    837,    919,    787,
5013
    768,    837,    919,    788,    768,    837,    919,    787,    769,
5014
    837,    919,    788,    769,    837,    919,    787,    834,    837,
5015
    919,    788,    834,    837,    969,    787,    837,    969,    788,
5016
    837,    969,    787,    768,    837,    969,    788,    768,    837,
5017
    969,    787,    769,    837,    969,    788,    769,    837,    969,
5018
    787,    834,    837,    969,    788,    834,    837,    937,    787,
5019
    837,    937,    788,    837,    937,    787,    768,    837,    937,
5020
    788,    768,    837,    937,    787,    769,    837,    937,    788,
5021
    769,    837,    937,    787,    834,    837,    937,    788,    834,
5022
    837,    945,    774,    945,    772,    945,    768,    837,    945,
5023
    837,    945,    769,    837,    945,    834,    945,    834,    837,
5024
    913,    774,    913,    772,    913,    768,    913,    769,    913,
5025
    837,    32,     787,    953,    32,     787,    32,     834,    168,
5026
    834,    951,    768,    837,    951,    837,    951,    769,    837,
5027
    951,    834,    951,    834,    837,    917,    768,    917,    769,
5028
    919,    768,    919,    769,    919,    837,    8127,   768,    8127,
5029
    769,    8127,   834,    953,    774,    953,    772,    953,    776,
5030
    768,    953,    776,    769,    953,    834,    953,    776,    834,
5031
    921,    774,    921,    772,    921,    768,    921,    769,    8190,
5032
    768,    8190,   769,    8190,   834,    965,    774,    965,    772,
5033
    965,    776,    768,    965,    776,    769,    961,    787,    961,
5034
    788,    965,    834,    965,    776,    834,    933,    774,    933,
5035
    772,    933,    768,    933,    769,    929,    788,    168,    768,
5036
    168,    769,    96,     969,    768,    837,    969,    837,    969,
5037
    769,    837,    969,    834,    969,    834,    837,    927,    768,
5038
    927,    769,    937,    768,    937,    769,    937,    837,    180,
5039
    32,     788,    8194,   8195,   32,     32,     32,     32,     32,
5040
    32,     32,     32,     32,     8208,   32,     819,    46,     46,
5041
    46,     46,     46,     46,     32,     8242,   8242,   8242,   8242,
5042
    8242,   8245,   8245,   8245,   8245,   8245,   33,     33,     32,
5043
    773,    63,     63,     63,     33,     33,     63,     8242,   8242,
5044
    8242,   8242,   32,     48,     105,    52,     53,     54,     55,
5045
    56,     57,     43,     8722,   61,     40,     41,     110,    48,
5046
    49,     50,     51,     52,     53,     54,     55,     56,     57,
5047
    43,     8722,   61,     40,     41,     97,     101,    111,    120,
5048
    601,    104,    107,    108,    109,    110,    112,    115,    116,
5049
    82,     115,    97,     47,     99,     97,     47,     115,    67,
5050
    176,    67,     99,     47,     111,    99,     47,     117,    400,
5051
    176,    70,     103,    72,     72,     72,     104,    295,    73,
5052
    73,     76,     108,    78,     78,     111,    80,     81,     82,
5053
    82,     82,     83,     77,     84,     69,     76,     84,     77,
5054
    90,     937,    90,     75,     65,     778,    66,     67,     101,
5055
    69,     70,     77,     111,    1488,   1489,   1490,   1491,   105,
5056
    70,     65,     88,     960,    947,    915,    928,    8721,   68,
5057
    100,    101,    105,    106,    49,     8260,   55,     49,     8260,
5058
    57,     49,     8260,   49,     48,     49,     8260,   51,     50,
5059
    8260,   51,     49,     8260,   53,     50,     8260,   53,     51,
5060
    8260,   53,     52,     8260,   53,     49,     8260,   54,     53,
5061
    8260,   54,     49,     8260,   56,     51,     8260,   56,     53,
5062
    8260,   56,     55,     8260,   56,     49,     8260,   73,     73,
5063
    73,     73,     73,     73,     73,     86,     86,     86,     73,
5064
    86,     73,     73,     86,     73,     73,     73,     73,     88,
5065
    88,     88,     73,     88,     73,     73,     76,     67,     68,
5066
    77,     105,    105,    105,    105,    105,    105,    105,    118,
5067
    118,    118,    105,    118,    105,    105,    118,    105,    105,
5068
    105,    105,    120,    120,    120,    105,    120,    105,    105,
5069
    108,    99,     100,    109,    48,     8260,   51,     8592,   824,
5070
    8594,   824,    8596,   824,    8656,   824,    8660,   824,    8658,
5071
    824,    8707,   824,    8712,   824,    8715,   824,    8739,   824,
5072
    8741,   824,    8747,   8747,   8747,   8747,   8747,   8750,   8750,
5073
    8750,   8750,   8750,   8764,   824,    8771,   824,    8773,   824,
5074
    8776,   824,    61,     824,    8801,   824,    8781,   824,    60,
5075
    824,    62,     824,    8804,   824,    8805,   824,    8818,   824,
5076
    8819,   824,    8822,   824,    8823,   824,    8826,   824,    8827,
5077
    824,    8834,   824,    8835,   824,    8838,   824,    8839,   824,
5078
    8866,   824,    8872,   824,    8873,   824,    8875,   824,    8828,
5079
    824,    8829,   824,    8849,   824,    8850,   824,    8882,   824,
5080
    8883,   824,    8884,   824,    8885,   824,    12296,  12297,  49,
5081
    50,     51,     52,     53,     54,     55,     56,     57,     49,
5082
    48,     49,     49,     49,     50,     49,     51,     49,     52,
5083
    49,     53,     49,     54,     49,     55,     49,     56,     49,
5084
    57,     50,     48,     40,     49,     41,     40,     50,     41,
5085
    40,     51,     41,     40,     52,     41,     40,     53,     41,
5086
    40,     54,     41,     40,     55,     41,     40,     56,     41,
5087
    40,     57,     41,     40,     49,     48,     41,     40,     49,
5088
    49,     41,     40,     49,     50,     41,     40,     49,     51,
5089
    41,     40,     49,     52,     41,     40,     49,     53,     41,
5090
    40,     49,     54,     41,     40,     49,     55,     41,     40,
5091
    49,     56,     41,     40,     49,     57,     41,     40,     50,
5092
    48,     41,     49,     46,     50,     46,     51,     46,     52,
5093
    46,     53,     46,     54,     46,     55,     46,     56,     46,
5094
    57,     46,     49,     48,     46,     49,     49,     46,     49,
5095
    50,     46,     49,     51,     46,     49,     52,     46,     49,
5096
    53,     46,     49,     54,     46,     49,     55,     46,     49,
5097
    56,     46,     49,     57,     46,     50,     48,     46,     40,
5098
    97,     41,     40,     98,     41,     40,     99,     41,     40,
5099
    100,    41,     40,     101,    41,     40,     102,    41,     40,
5100
    103,    41,     40,     104,    41,     40,     105,    41,     40,
5101
    106,    41,     40,     107,    41,     40,     108,    41,     40,
5102
    109,    41,     40,     110,    41,     40,     111,    41,     40,
5103
    112,    41,     40,     113,    41,     40,     114,    41,     40,
5104
    115,    41,     40,     116,    41,     40,     117,    41,     40,
5105
    118,    41,     40,     119,    41,     40,     120,    41,     40,
5106
    121,    41,     40,     122,    41,     65,     66,     67,     68,
5107
    69,     70,     71,     72,     73,     74,     75,     76,     77,
5108
    78,     79,     80,     81,     82,     83,     84,     85,     86,
5109
    87,     88,     89,     90,     97,     98,     99,     100,    101,
5110
    102,    103,    104,    105,    106,    107,    108,    109,    110,
5111
    111,    112,    113,    114,    115,    116,    117,    118,    119,
5112
    120,    121,    122,    48,     8747,   8747,   8747,   8747,   58,
5113
    58,     61,     61,     61,     61,     61,     61,     10973,  824,
5114
    106,    86,     11617,  27597,  40863,  19968,  20008,  20022,  20031,
5115
    20057,  20101,  20108,  20128,  20154,  20799,  20837,  20843,  20866,
5116
    20886,  20907,  20960,  20981,  20992,  21147,  21241,  21269,  21274,
5117
    21304,  21313,  21340,  21353,  21378,  21430,  21448,  21475,  22231,
5118
    22303,  22763,  22786,  22794,  22805,  22823,  22899,  23376,  23424,
5119
    23544,  23567,  23586,  23608,  23662,  23665,  24027,  24037,  24049,
5120
    24062,  24178,  24186,  24191,  24308,  24318,  24331,  24339,  24400,
5121
    24417,  24435,  24515,  25096,  25142,  25163,  25903,  25908,  25991,
5122
    26007,  26020,  26041,  26080,  26085,  26352,  26376,  26408,  27424,
5123
    27490,  27513,  27571,  27595,  27604,  27611,  27663,  27668,  27700,
5124
    28779,  29226,  29238,  29243,  29247,  29255,  29273,  29275,  29356,
5125
    29572,  29577,  29916,  29926,  29976,  29983,  29992,  30000,  30091,
5126
    30098,  30326,  30333,  30382,  30399,  30446,  30683,  30690,  30707,
5127
    31034,  31160,  31166,  31348,  31435,  31481,  31859,  31992,  32566,
5128
    32593,  32650,  32701,  32769,  32780,  32786,  32819,  32895,  32905,
5129
    33251,  33258,  33267,  33276,  33292,  33307,  33311,  33390,  33394,
5130
    33400,  34381,  34411,  34880,  34892,  34915,  35198,  35211,  35282,
5131
    35328,  35895,  35910,  35925,  35960,  35997,  36196,  36208,  36275,
5132
    36523,  36554,  36763,  36784,  36789,  37009,  37193,  37318,  37324,
5133
    37329,  38263,  38272,  38428,  38582,  38585,  38632,  38737,  38750,
5134
    38754,  38761,  38859,  38893,  38899,  38913,  39080,  39131,  39135,
5135
    39318,  39321,  39340,  39592,  39640,  39647,  39717,  39727,  39730,
5136
    39740,  39770,  40165,  40565,  40575,  40613,  40635,  40643,  40653,
5137
    40657,  40697,  40701,  40718,  40723,  40736,  40763,  40778,  40786,
5138
    40845,  40860,  40864,  32,     12306,  21313,  21316,  21317,  12363,
5139
    12441,  12365,  12441,  12367,  12441,  12369,  12441,  12371,  12441,
5140
    12373,  12441,  12375,  12441,  12377,  12441,  12379,  12441,  12381,
5141
    12441,  12383,  12441,  12385,  12441,  12388,  12441,  12390,  12441,
5142
    12392,  12441,  12399,  12441,  12399,  12442,  12402,  12441,  12402,
5143
    12442,  12405,  12441,  12405,  12442,  12408,  12441,  12408,  12442,
5144
    12411,  12441,  12411,  12442,  12358,  12441,  32,     12441,  32,
5145
    12442,  12445,  12441,  12424,  12426,  12459,  12441,  12461,  12441,
5146
    12463,  12441,  12465,  12441,  12467,  12441,  12469,  12441,  12471,
5147
    12441,  12473,  12441,  12475,  12441,  12477,  12441,  12479,  12441,
5148
    12481,  12441,  12484,  12441,  12486,  12441,  12488,  12441,  12495,
5149
    12441,  12495,  12442,  12498,  12441,  12498,  12442,  12501,  12441,
5150
    12501,  12442,  12504,  12441,  12504,  12442,  12507,  12441,  12507,
5151
    12442,  12454,  12441,  12527,  12441,  12528,  12441,  12529,  12441,
5152
    12530,  12441,  12541,  12441,  12467,  12488,  4352,   4353,   4522,
5153
    4354,   4524,   4525,   4355,   4356,   4357,   4528,   4529,   4530,
5154
    4531,   4532,   4533,   4378,   4358,   4359,   4360,   4385,   4361,
5155
    4362,   4363,   4364,   4365,   4366,   4367,   4368,   4369,   4370,
5156
    4449,   4450,   4451,   4452,   4453,   4454,   4455,   4456,   4457,
5157
    4458,   4459,   4460,   4461,   4462,   4463,   4464,   4465,   4466,
5158
    4467,   4468,   4469,   4448,   4372,   4373,   4551,   4552,   4556,
5159
    4558,   4563,   4567,   4569,   4380,   4573,   4575,   4381,   4382,
5160
    4384,   4386,   4387,   4391,   4393,   4395,   4396,   4397,   4398,
5161
    4399,   4402,   4406,   4416,   4423,   4428,   4593,   4594,   4439,
5162
    4440,   4441,   4484,   4485,   4488,   4497,   4498,   4500,   4510,
5163
    4513,   19968,  20108,  19977,  22235,  19978,  20013,  19979,  30002,
5164
    20057,  19993,  19969,  22825,  22320,  20154,  40,     4352,   41,
5165
    40,     4354,   41,     40,     4355,   41,     40,     4357,   41,
5166
    40,     4358,   41,     40,     4359,   41,     40,     4361,   41,
5167
    40,     4363,   41,     40,     4364,   41,     40,     4366,   41,
5168
    40,     4367,   41,     40,     4368,   41,     40,     4369,   41,
5169
    40,     4370,   41,     40,     4352,   4449,   41,     40,     4354,
5170
    4449,   41,     40,     4355,   4449,   41,     40,     4357,   4449,
5171
    41,     40,     4358,   4449,   41,     40,     4359,   4449,   41,
5172
    40,     4361,   4449,   41,     40,     4363,   4449,   41,     40,
5173
    4364,   4449,   41,     40,     4366,   4449,   41,     40,     4367,
5174
    4449,   41,     40,     4368,   4449,   41,     40,     4369,   4449,
5175
    41,     40,     4370,   4449,   41,     40,     4364,   4462,   41,
5176
    40,     4363,   4457,   4364,   4453,   4523,   41,     40,     4363,
5177
    4457,   4370,   4462,   41,     40,     19968,  41,     40,     20108,
5178
    41,     40,     19977,  41,     40,     22235,  41,     40,     20116,
5179
    41,     40,     20845,  41,     40,     19971,  41,     40,     20843,
5180
    41,     40,     20061,  41,     40,     21313,  41,     40,     26376,
5181
    41,     40,     28779,  41,     40,     27700,  41,     40,     26408,
5182
    41,     40,     37329,  41,     40,     22303,  41,     40,     26085,
5183
    41,     40,     26666,  41,     40,     26377,  41,     40,     31038,
5184
    41,     40,     21517,  41,     40,     29305,  41,     40,     36001,
5185
    41,     40,     31069,  41,     40,     21172,  41,     40,     20195,
5186
    41,     40,     21628,  41,     40,     23398,  41,     40,     30435,
5187
    41,     40,     20225,  41,     40,     36039,  41,     40,     21332,
5188
    41,     40,     31085,  41,     40,     20241,  41,     40,     33258,
5189
    41,     40,     33267,  41,     21839,  24188,  25991,  31631,  80,
5190
    84,     69,     50,     49,     50,     50,     50,     51,     50,
5191
    52,     50,     53,     50,     54,     50,     55,     50,     56,
5192
    50,     57,     51,     48,     51,     49,     51,     50,     51,
5193
    51,     51,     52,     51,     53,     4352,   4354,   4355,   4357,
5194
    4358,   4359,   4361,   4363,   4364,   4366,   4367,   4368,   4369,
5195
    4370,   4352,   4449,   4354,   4449,   4355,   4449,   4357,   4449,
5196
    4358,   4449,   4359,   4449,   4361,   4449,   4363,   4449,   4364,
5197
    4449,   4366,   4449,   4367,   4449,   4368,   4449,   4369,   4449,
5198
    4370,   4449,   4366,   4449,   4535,   4352,   4457,   4364,   4462,
5199
    4363,   4468,   4363,   4462,   19968,  20108,  19977,  22235,  20116,
5200
    20845,  19971,  20843,  20061,  21313,  26376,  28779,  27700,  26408,
5201
    37329,  22303,  26085,  26666,  26377,  31038,  21517,  29305,  36001,
5202
    31069,  21172,  31192,  30007,  22899,  36969,  20778,  21360,  27880,
5203
    38917,  20241,  20889,  27491,  19978,  20013,  19979,  24038,  21491,
5204
    21307,  23447,  23398,  30435,  20225,  36039,  21332,  22812,  51,
5205
    54,     51,     55,     51,     56,     51,     57,     52,     48,
5206
    52,     49,     52,     50,     52,     51,     52,     52,     52,
5207
    53,     52,     54,     52,     55,     52,     56,     52,     57,
5208
    53,     48,     49,     26376,  50,     26376,  51,     26376,  52,
5209
    26376,  53,     26376,  54,     26376,  55,     26376,  56,     26376,
5210
    57,     26376,  49,     48,     26376,  49,     49,     26376,  49,
5211
    50,     26376,  72,     103,    101,    114,    103,    101,    86,
5212
    76,     84,     68,     12450,  12452,  12454,  12456,  12458,  12459,
5213
    12461,  12463,  12465,  12467,  12469,  12471,  12473,  12475,  12477,
5214
    12479,  12481,  12484,  12486,  12488,  12490,  12491,  12492,  12493,
5215
    12494,  12495,  12498,  12501,  12504,  12507,  12510,  12511,  12512,
5216
    12513,  12514,  12516,  12518,  12520,  12521,  12522,  12523,  12524,
5217
    12525,  12527,  12528,  12529,  12530,  20196,  21644,  12450,  12495,
5218
    12442,  12540,  12488,  12450,  12523,  12501,  12449,  12450,  12531,
5219
    12504,  12442,  12450,  12450,  12540,  12523,  12452,  12491,  12531,
5220
    12463,  12441,  12452,  12531,  12481,  12454,  12457,  12531,  12456,
5221
    12473,  12463,  12540,  12488,  12441,  12456,  12540,  12459,  12540,
5222
    12458,  12531,  12473,  12458,  12540,  12512,  12459,  12452,  12522,
5223
    12459,  12521,  12483,  12488,  12459,  12525,  12522,  12540,  12459,
5224
    12441,  12525,  12531,  12459,  12441,  12531,  12510,  12461,  12441,
5225
    12459,  12441,  12461,  12441,  12491,  12540,  12461,  12517,  12522,
5226
    12540,  12461,  12441,  12523,  12479,  12441,  12540,  12461,  12525,
5227
    12461,  12525,  12463,  12441,  12521,  12512,  12461,  12525,  12513,
5228
    12540,  12488,  12523,  12461,  12525,  12527,  12483,  12488,  12463,
5229
    12441,  12521,  12512,  12463,  12441,  12521,  12512,  12488,  12531,
5230
    12463,  12523,  12475,  12441,  12452,  12525,  12463,  12525,  12540,
5231
    12493,  12465,  12540,  12473,  12467,  12523,  12490,  12467,  12540,
5232
    12507,  12442,  12469,  12452,  12463,  12523,  12469,  12531,  12481,
5233
    12540,  12512,  12471,  12522,  12531,  12463,  12441,  12475,  12531,
5234
    12481,  12475,  12531,  12488,  12479,  12441,  12540,  12473,  12486,
5235
    12441,  12471,  12488,  12441,  12523,  12488,  12531,  12490,  12494,
5236
    12494,  12483,  12488,  12495,  12452,  12484,  12495,  12442,  12540,
5237
    12475,  12531,  12488,  12495,  12442,  12540,  12484,  12495,  12441,
5238
    12540,  12524,  12523,  12498,  12442,  12450,  12473,  12488,  12523,
5239
    12498,  12442,  12463,  12523,  12498,  12442,  12467,  12498,  12441,
5240
    12523,  12501,  12449,  12521,  12483,  12488,  12441,  12501,  12451,
5241
    12540,  12488,  12501,  12441,  12483,  12471,  12455,  12523,  12501,
5242
    12521,  12531,  12504,  12463,  12479,  12540,  12523,  12504,  12442,
5243
    12477,  12504,  12442,  12491,  12498,  12504,  12523,  12484,  12504,
5244
    12442,  12531,  12473,  12504,  12442,  12540,  12471,  12441,  12504,
5245
    12441,  12540,  12479,  12507,  12442,  12452,  12531,  12488,  12507,
5246
    12441,  12523,  12488,  12507,  12531,  12507,  12442,  12531,  12488,
5247
    12441,  12507,  12540,  12523,  12507,  12540,  12531,  12510,  12452,
5248
    12463,  12525,  12510,  12452,  12523,  12510,  12483,  12495,  12510,
5249
    12523,  12463,  12510,  12531,  12471,  12519,  12531,  12511,  12463,
5250
    12525,  12531,  12511,  12522,  12511,  12522,  12495,  12441,  12540,
5251
    12523,  12513,  12459,  12441,  12513,  12459,  12441,  12488,  12531,
5252
    12513,  12540,  12488,  12523,  12516,  12540,  12488,  12441,  12516,
5253
    12540,  12523,  12518,  12450,  12531,  12522,  12483,  12488,  12523,
5254
    12522,  12521,  12523,  12498,  12442,  12540,  12523,  12540,  12501,
5255
    12441,  12523,  12524,  12512,  12524,  12531,  12488,  12465,  12441,
5256
    12531,  12527,  12483,  12488,  48,     28857,  49,     28857,  50,
5257
    28857,  51,     28857,  52,     28857,  53,     28857,  54,     28857,
5258
    55,     28857,  56,     28857,  57,     28857,  49,     48,     28857,
5259
    49,     49,     28857,  49,     50,     28857,  49,     51,     28857,
5260
    49,     52,     28857,  49,     53,     28857,  49,     54,     28857,
5261
    49,     55,     28857,  49,     56,     28857,  49,     57,     28857,
5262
    50,     48,     28857,  50,     49,     28857,  50,     50,     28857,
5263
    50,     51,     28857,  50,     52,     28857,  104,    80,     97,
5264
    100,    97,     65,     85,     98,     97,     114,    111,    86,
5265
    112,    99,     100,    109,    100,    109,    50,     100,    109,
5266
    51,     73,     85,     24179,  25104,  26157,  21644,  22823,  27491,
5267
    26126,  27835,  26666,  24335,  20250,  31038,  112,    65,     110,
5268
    65,     956,    65,     109,    65,     107,    65,     75,     66,
5269
    77,     66,     71,     66,     99,     97,     108,    107,    99,
5270
    97,     108,    112,    70,     110,    70,     956,    70,     956,
5271
    103,    109,    103,    107,    103,    72,     122,    107,    72,
5272
    122,    77,     72,     122,    71,     72,     122,    84,     72,
5273
    122,    956,    108,    109,    108,    100,    108,    107,    108,
5274
    102,    109,    110,    109,    956,    109,    109,    109,    99,
5275
    109,    107,    109,    109,    109,    50,     99,     109,    50,
5276
    109,    50,     107,    109,    50,     109,    109,    51,     99,
5277
    109,    51,     109,    51,     107,    109,    51,     109,    8725,
5278
    115,    109,    8725,   115,    50,     80,     97,     107,    80,
5279
    97,     77,     80,     97,     71,     80,     97,     114,    97,
5280
    100,    114,    97,     100,    8725,   115,    114,    97,     100,
5281
    8725,   115,    50,     112,    115,    110,    115,    956,    115,
5282
    109,    115,    112,    86,     110,    86,     956,    86,     109,
5283
    86,     107,    86,     77,     86,     112,    87,     110,    87,
5284
    956,    87,     109,    87,     107,    87,     77,     87,     107,
5285
    937,    77,     937,    97,     46,     109,    46,     66,     113,
5286
    99,     99,     99,     100,    67,     8725,   107,    103,    67,
5287
    111,    46,     100,    66,     71,     121,    104,    97,     72,
5288
    80,     105,    110,    75,     75,     75,     77,     107,    116,
5289
    108,    109,    108,    110,    108,    111,    103,    108,    120,
5290
    109,    98,     109,    105,    108,    109,    111,    108,    80,
5291
    72,     112,    46,     109,    46,     80,     80,     77,     80,
5292
    82,     115,    114,    83,     118,    87,     98,     86,     8725,
5293
    109,    65,     8725,   109,    49,     26085,  50,     26085,  51,
5294
    26085,  52,     26085,  53,     26085,  54,     26085,  55,     26085,
5295
    56,     26085,  57,     26085,  49,     48,     26085,  49,     49,
5296
    26085,  49,     50,     26085,  49,     51,     26085,  49,     52,
5297
    26085,  49,     53,     26085,  49,     54,     26085,  49,     55,
5298
    26085,  49,     56,     26085,  49,     57,     26085,  50,     48,
5299
    26085,  50,     49,     26085,  50,     50,     26085,  50,     51,
5300
    26085,  50,     52,     26085,  50,     53,     26085,  50,     54,
5301
    26085,  50,     55,     26085,  50,     56,     26085,  50,     57,
5302
    26085,  51,     48,     26085,  51,     49,     26085,  103,    97,
5303
    108,    1098,   1100,   42863,  67,     70,     81,     294,    339,
5304
    42791,  43831,  619,    43858,  653,    35912,  26356,  36554,  36040,
5305
    28369,  20018,  21477,  40860,  40860,  22865,  37329,  21895,  22856,
5306
    25078,  30313,  32645,  34367,  34746,  35064,  37007,  27138,  27931,
5307
    28889,  29662,  33853,  37226,  39409,  20098,  21365,  27396,  29211,
5308
    34349,  40478,  23888,  28651,  34253,  35172,  25289,  33240,  34847,
5309
    24266,  26391,  28010,  29436,  37070,  20358,  20919,  21214,  25796,
5310
    27347,  29200,  30439,  32769,  34310,  34396,  36335,  38706,  39791,
5311
    40442,  30860,  31103,  32160,  33737,  37636,  40575,  35542,  22751,
5312
    24324,  31840,  32894,  29282,  30922,  36034,  38647,  22744,  23650,
5313
    27155,  28122,  28431,  32047,  32311,  38475,  21202,  32907,  20956,
5314
    20940,  31260,  32190,  33777,  38517,  35712,  25295,  27138,  35582,
5315
    20025,  23527,  24594,  29575,  30064,  21271,  30971,  20415,  24489,
5316
    19981,  27852,  25976,  32034,  21443,  22622,  30465,  33865,  35498,
5317
    27578,  36784,  27784,  25342,  33509,  25504,  30053,  20142,  20841,
5318
    20937,  26753,  31975,  33391,  35538,  37327,  21237,  21570,  22899,
5319
    24300,  26053,  28670,  31018,  38317,  39530,  40599,  40654,  21147,
5320
    26310,  27511,  36706,  24180,  24976,  25088,  25754,  28451,  29001,
5321
    29833,  31178,  32244,  32879,  36646,  34030,  36899,  37706,  21015,
5322
    21155,  21693,  28872,  35010,  35498,  24265,  24565,  25467,  27566,
5323
    31806,  29557,  20196,  22265,  23527,  23994,  24604,  29618,  29801,
5324
    32666,  32838,  37428,  38646,  38728,  38936,  20363,  31150,  37300,
5325
    38584,  24801,  20102,  20698,  23534,  23615,  26009,  27138,  29134,
5326
    30274,  34044,  36988,  40845,  26248,  38446,  21129,  26491,  26611,
5327
    27969,  28316,  29705,  30041,  30827,  32016,  39006,  20845,  25134,
5328
    38520,  20523,  23833,  28138,  36650,  24459,  24900,  26647,  29575,
5329
    38534,  21033,  21519,  23653,  26131,  26446,  26792,  27877,  29702,
5330
    30178,  32633,  35023,  35041,  37324,  38626,  21311,  28346,  21533,
5331
    29136,  29848,  34298,  38563,  40023,  40607,  26519,  28107,  33256,
5332
    31435,  31520,  31890,  29376,  28825,  35672,  20160,  33590,  21050,
5333
    20999,  24230,  25299,  31958,  23429,  27934,  26292,  36667,  34892,
5334
    38477,  35211,  24275,  20800,  21952,  22618,  26228,  20958,  29482,
5335
    30410,  31036,  31070,  31077,  31119,  38742,  31934,  32701,  34322,
5336
    35576,  36920,  37117,  39151,  39164,  39208,  40372,  37086,  38583,
5337
    20398,  20711,  20813,  21193,  21220,  21329,  21917,  22022,  22120,
5338
    22592,  22696,  23652,  23662,  24724,  24936,  24974,  25074,  25935,
5339
    26082,  26257,  26757,  28023,  28186,  28450,  29038,  29227,  29730,
5340
    30865,  31038,  31049,  31048,  31056,  31062,  31069,  31117,  31118,
5341
    31296,  31361,  31680,  32244,  32265,  32321,  32626,  32773,  33261,
5342
    33401,  33401,  33879,  35088,  35222,  35585,  35641,  36051,  36104,
5343
    36790,  36920,  38627,  38911,  38971,  24693,  148206, 33304,  20006,
5344
    20917,  20840,  20352,  20805,  20864,  21191,  21242,  21917,  21845,
5345
    21913,  21986,  22618,  22707,  22852,  22868,  23138,  23336,  24274,
5346
    24281,  24425,  24493,  24792,  24910,  24840,  24974,  24928,  25074,
5347
    25140,  25540,  25628,  25682,  25942,  26228,  26391,  26395,  26454,
5348
    27513,  27578,  27969,  28379,  28363,  28450,  28702,  29038,  30631,
5349
    29237,  29359,  29482,  29809,  29958,  30011,  30237,  30239,  30410,
5350
    30427,  30452,  30538,  30528,  30924,  31409,  31680,  31867,  32091,
5351
    32244,  32574,  32773,  33618,  33775,  34681,  35137,  35206,  35222,
5352
    35519,  35576,  35531,  35585,  35582,  35565,  35641,  35722,  36104,
5353
    36664,  36978,  37273,  37494,  38524,  38627,  38742,  38875,  38911,
5354
    38923,  38971,  39698,  40860,  141386, 141380, 144341, 15261,  16408,
5355
    16441,  152137, 154832, 163539, 40771,  40846,  102,    102,    102,
5356
    105,    102,    108,    102,    102,    105,    102,    102,    108,
5357
    115,    116,    115,    116,    1396,   1398,   1396,   1381,   1396,
5358
    1387,   1406,   1398,   1396,   1389,   1497,   1460,   1522,   1463,
5359
    1506,   1488,   1491,   1492,   1499,   1500,   1501,   1512,   1514,
5360
    43,     1513,   1473,   1513,   1474,   1513,   1468,   1473,   1513,
5361
    1468,   1474,   1488,   1463,   1488,   1464,   1488,   1468,   1489,
5362
    1468,   1490,   1468,   1491,   1468,   1492,   1468,   1493,   1468,
5363
    1494,   1468,   1496,   1468,   1497,   1468,   1498,   1468,   1499,
5364
    1468,   1500,   1468,   1502,   1468,   1504,   1468,   1505,   1468,
5365
    1507,   1468,   1508,   1468,   1510,   1468,   1511,   1468,   1512,
5366
    1468,   1513,   1468,   1514,   1468,   1493,   1465,   1489,   1471,
5367
    1499,   1471,   1508,   1471,   1488,   1500,   1649,   1649,   1659,
5368
    1659,   1659,   1659,   1662,   1662,   1662,   1662,   1664,   1664,
5369
    1664,   1664,   1658,   1658,   1658,   1658,   1663,   1663,   1663,
5370
    1663,   1657,   1657,   1657,   1657,   1700,   1700,   1700,   1700,
5371
    1702,   1702,   1702,   1702,   1668,   1668,   1668,   1668,   1667,
5372
    1667,   1667,   1667,   1670,   1670,   1670,   1670,   1671,   1671,
5373
    1671,   1671,   1677,   1677,   1676,   1676,   1678,   1678,   1672,
5374
    1672,   1688,   1688,   1681,   1681,   1705,   1705,   1705,   1705,
5375
    1711,   1711,   1711,   1711,   1715,   1715,   1715,   1715,   1713,
5376
    1713,   1713,   1713,   1722,   1722,   1723,   1723,   1723,   1723,
5377
    1749,   1620,   1749,   1620,   1729,   1729,   1729,   1729,   1726,
5378
    1726,   1726,   1726,   1746,   1746,   1746,   1620,   1746,   1620,
5379
    1709,   1709,   1709,   1709,   1735,   1735,   1734,   1734,   1736,
5380
    1736,   1735,   1652,   1739,   1739,   1733,   1733,   1737,   1737,
5381
    1744,   1744,   1744,   1744,   1609,   1609,   1610,   1620,   1575,
5382
    1610,   1620,   1575,   1610,   1620,   1749,   1610,   1620,   1749,
5383
    1610,   1620,   1608,   1610,   1620,   1608,   1610,   1620,   1735,
5384
    1610,   1620,   1735,   1610,   1620,   1734,   1610,   1620,   1734,
5385
    1610,   1620,   1736,   1610,   1620,   1736,   1610,   1620,   1744,
5386
    1610,   1620,   1744,   1610,   1620,   1744,   1610,   1620,   1609,
5387
    1610,   1620,   1609,   1610,   1620,   1609,   1740,   1740,   1740,
5388
    1740,   1610,   1620,   1580,   1610,   1620,   1581,   1610,   1620,
5389
    1605,   1610,   1620,   1609,   1610,   1620,   1610,   1576,   1580,
5390
    1576,   1581,   1576,   1582,   1576,   1605,   1576,   1609,   1576,
5391
    1610,   1578,   1580,   1578,   1581,   1578,   1582,   1578,   1605,
5392
    1578,   1609,   1578,   1610,   1579,   1580,   1579,   1605,   1579,
5393
    1609,   1579,   1610,   1580,   1581,   1580,   1605,   1581,   1580,
5394
    1581,   1605,   1582,   1580,   1582,   1581,   1582,   1605,   1587,
5395
    1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,   1581,
5396
    1589,   1605,   1590,   1580,   1590,   1581,   1590,   1582,   1590,
5397
    1605,   1591,   1581,   1591,   1605,   1592,   1605,   1593,   1580,
5398
    1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,   1601,
5399
    1581,   1601,   1582,   1601,   1605,   1601,   1609,   1601,   1610,
5400
    1602,   1581,   1602,   1605,   1602,   1609,   1602,   1610,   1603,
5401
    1575,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5402
    1603,   1605,   1603,   1609,   1603,   1610,   1604,   1580,   1604,
5403
    1581,   1604,   1582,   1604,   1605,   1604,   1609,   1604,   1610,
5404
    1605,   1580,   1605,   1581,   1605,   1582,   1605,   1605,   1605,
5405
    1609,   1605,   1610,   1606,   1580,   1606,   1581,   1606,   1582,
5406
    1606,   1605,   1606,   1609,   1606,   1610,   1607,   1580,   1607,
5407
    1605,   1607,   1609,   1607,   1610,   1610,   1580,   1610,   1581,
5408
    1610,   1582,   1610,   1605,   1610,   1609,   1610,   1610,   1584,
5409
    1648,   1585,   1648,   1609,   1648,   32,     1612,   1617,   32,
5410
    1613,   1617,   32,     1614,   1617,   32,     1615,   1617,   32,
5411
    1616,   1617,   32,     1617,   1648,   1610,   1620,   1585,   1610,
5412
    1620,   1586,   1610,   1620,   1605,   1610,   1620,   1606,   1610,
5413
    1620,   1609,   1610,   1620,   1610,   1576,   1585,   1576,   1586,
5414
    1576,   1605,   1576,   1606,   1576,   1609,   1576,   1610,   1578,
5415
    1585,   1578,   1586,   1578,   1605,   1578,   1606,   1578,   1609,
5416
    1578,   1610,   1579,   1585,   1579,   1586,   1579,   1605,   1579,
5417
    1606,   1579,   1609,   1579,   1610,   1601,   1609,   1601,   1610,
5418
    1602,   1609,   1602,   1610,   1603,   1575,   1603,   1604,   1603,
5419
    1605,   1603,   1609,   1603,   1610,   1604,   1605,   1604,   1609,
5420
    1604,   1610,   1605,   1575,   1605,   1605,   1606,   1585,   1606,
5421
    1586,   1606,   1605,   1606,   1606,   1606,   1609,   1606,   1610,
5422
    1609,   1648,   1610,   1585,   1610,   1586,   1610,   1605,   1610,
5423
    1606,   1610,   1609,   1610,   1610,   1610,   1620,   1580,   1610,
5424
    1620,   1581,   1610,   1620,   1582,   1610,   1620,   1605,   1610,
5425
    1620,   1607,   1576,   1580,   1576,   1581,   1576,   1582,   1576,
5426
    1605,   1576,   1607,   1578,   1580,   1578,   1581,   1578,   1582,
5427
    1578,   1605,   1578,   1607,   1579,   1605,   1580,   1581,   1580,
5428
    1605,   1581,   1580,   1581,   1605,   1582,   1580,   1582,   1605,
5429
    1587,   1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,
5430
    1581,   1589,   1582,   1589,   1605,   1590,   1580,   1590,   1581,
5431
    1590,   1582,   1590,   1605,   1591,   1581,   1592,   1605,   1593,
5432
    1580,   1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,
5433
    1601,   1581,   1601,   1582,   1601,   1605,   1602,   1581,   1602,
5434
    1605,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5435
    1603,   1605,   1604,   1580,   1604,   1581,   1604,   1582,   1604,
5436
    1605,   1604,   1607,   1605,   1580,   1605,   1581,   1605,   1582,
5437
    1605,   1605,   1606,   1580,   1606,   1581,   1606,   1582,   1606,
5438
    1605,   1606,   1607,   1607,   1580,   1607,   1605,   1607,   1648,
5439
    1610,   1580,   1610,   1581,   1610,   1582,   1610,   1605,   1610,
5440
    1607,   1610,   1620,   1605,   1610,   1620,   1607,   1576,   1605,
5441
    1576,   1607,   1578,   1605,   1578,   1607,   1579,   1605,   1579,
5442
    1607,   1587,   1605,   1587,   1607,   1588,   1605,   1588,   1607,
5443
    1603,   1604,   1603,   1605,   1604,   1605,   1606,   1605,   1606,
5444
    1607,   1610,   1605,   1610,   1607,   1600,   1614,   1617,   1600,
5445
    1615,   1617,   1600,   1616,   1617,   1591,   1609,   1591,   1610,
5446
    1593,   1609,   1593,   1610,   1594,   1609,   1594,   1610,   1587,
5447
    1609,   1587,   1610,   1588,   1609,   1588,   1610,   1581,   1609,
5448
    1581,   1610,   1580,   1609,   1580,   1610,   1582,   1609,   1582,
5449
    1610,   1589,   1609,   1589,   1610,   1590,   1609,   1590,   1610,
5450
    1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1588,
5451
    1585,   1587,   1585,   1589,   1585,   1590,   1585,   1591,   1609,
5452
    1591,   1610,   1593,   1609,   1593,   1610,   1594,   1609,   1594,
5453
    1610,   1587,   1609,   1587,   1610,   1588,   1609,   1588,   1610,
5454
    1581,   1609,   1581,   1610,   1580,   1609,   1580,   1610,   1582,
5455
    1609,   1582,   1610,   1589,   1609,   1589,   1610,   1590,   1609,
5456
    1590,   1610,   1588,   1580,   1588,   1581,   1588,   1582,   1588,
5457
    1605,   1588,   1585,   1587,   1585,   1589,   1585,   1590,   1585,
5458
    1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1587,
5459
    1607,   1588,   1607,   1591,   1605,   1587,   1580,   1587,   1581,
5460
    1587,   1582,   1588,   1580,   1588,   1581,   1588,   1582,   1591,
5461
    1605,   1592,   1605,   1575,   1611,   1575,   1611,   1578,   1580,
5462
    1605,   1578,   1581,   1580,   1578,   1581,   1580,   1578,   1581,
5463
    1605,   1578,   1582,   1605,   1578,   1605,   1580,   1578,   1605,
5464
    1581,   1578,   1605,   1582,   1580,   1605,   1581,   1580,   1605,
5465
    1581,   1581,   1605,   1610,   1581,   1605,   1609,   1587,   1581,
5466
    1580,   1587,   1580,   1581,   1587,   1580,   1609,   1587,   1605,
5467
    1581,   1587,   1605,   1581,   1587,   1605,   1580,   1587,   1605,
5468
    1605,   1587,   1605,   1605,   1589,   1581,   1581,   1589,   1581,
5469
    1581,   1589,   1605,   1605,   1588,   1581,   1605,   1588,   1581,
5470
    1605,   1588,   1580,   1610,   1588,   1605,   1582,   1588,   1605,
5471
    1582,   1588,   1605,   1605,   1588,   1605,   1605,   1590,   1581,
5472
    1609,   1590,   1582,   1605,   1590,   1582,   1605,   1591,   1605,
5473
    1581,   1591,   1605,   1581,   1591,   1605,   1605,   1591,   1605,
5474
    1610,   1593,   1580,   1605,   1593,   1605,   1605,   1593,   1605,
5475
    1605,   1593,   1605,   1609,   1594,   1605,   1605,   1594,   1605,
5476
    1610,   1594,   1605,   1609,   1601,   1582,   1605,   1601,   1582,
5477
    1605,   1602,   1605,   1581,   1602,   1605,   1605,   1604,   1581,
5478
    1605,   1604,   1581,   1610,   1604,   1581,   1609,   1604,   1580,
5479
    1580,   1604,   1580,   1580,   1604,   1582,   1605,   1604,   1582,
5480
    1605,   1604,   1605,   1581,   1604,   1605,   1581,   1605,   1581,
5481
    1580,   1605,   1581,   1605,   1605,   1581,   1610,   1605,   1580,
5482
    1581,   1605,   1580,   1605,   1605,   1582,   1580,   1605,   1582,
5483
    1605,   1605,   1580,   1582,   1607,   1605,   1580,   1607,   1605,
5484
    1605,   1606,   1581,   1605,   1606,   1581,   1609,   1606,   1580,
5485
    1605,   1606,   1580,   1605,   1606,   1580,   1609,   1606,   1605,
5486
    1610,   1606,   1605,   1609,   1610,   1605,   1605,   1610,   1605,
5487
    1605,   1576,   1582,   1610,   1578,   1580,   1610,   1578,   1580,
5488
    1609,   1578,   1582,   1610,   1578,   1582,   1609,   1578,   1605,
5489
    1610,   1578,   1605,   1609,   1580,   1605,   1610,   1580,   1581,
5490
    1609,   1580,   1605,   1609,   1587,   1582,   1609,   1589,   1581,
5491
    1610,   1588,   1581,   1610,   1590,   1581,   1610,   1604,   1580,
5492
    1610,   1604,   1605,   1610,   1610,   1581,   1610,   1610,   1580,
5493
    1610,   1610,   1605,   1610,   1605,   1605,   1610,   1602,   1605,
5494
    1610,   1606,   1581,   1610,   1602,   1605,   1581,   1604,   1581,
5495
    1605,   1593,   1605,   1610,   1603,   1605,   1610,   1606,   1580,
5496
    1581,   1605,   1582,   1610,   1604,   1580,   1605,   1603,   1605,
5497
    1605,   1604,   1580,   1605,   1606,   1580,   1581,   1580,   1581,
5498
    1610,   1581,   1580,   1610,   1605,   1580,   1610,   1601,   1605,
5499
    1610,   1576,   1581,   1610,   1603,   1605,   1605,   1593,   1580,
5500
    1605,   1589,   1605,   1605,   1587,   1582,   1610,   1606,   1580,
5501
    1610,   1589,   1604,   1746,   1602,   1604,   1746,   1575,   1604,
5502
    1604,   1607,   1575,   1603,   1576,   1585,   1605,   1581,   1605,
5503
    1583,   1589,   1604,   1593,   1605,   1585,   1587,   1608,   1604,
5504
    1593,   1604,   1610,   1607,   1608,   1587,   1604,   1605,   1589,
5505
    1604,   1609,   1589,   1604,   1609,   32,     1575,   1604,   1604,
5506
    1607,   32,     1593,   1604,   1610,   1607,   32,     1608,   1587,
5507
    1604,   1605,   1580,   1604,   32,     1580,   1604,   1575,   1604,
5508
    1607,   1585,   1740,   1575,   1604,   44,     12289,  12290,  58,
5509
    59,     33,     63,     12310,  12311,  46,     46,     46,     46,
5510
    46,     8212,   8211,   95,     95,     40,     41,     123,    125,
5511
    12308,  12309,  12304,  12305,  12298,  12299,  12296,  12297,  12300,
5512
    12301,  12302,  12303,  91,     93,     32,     773,    32,     773,
5513
    32,     773,    32,     773,    95,     95,     95,     44,     12289,
5514
    46,     59,     58,     63,     33,     8212,   40,     41,     123,
5515
    125,    12308,  12309,  35,     38,     42,     43,     45,     60,
5516
    62,     61,     92,     36,     37,     64,     32,     1611,   1600,
5517
    1611,   32,     1612,   32,     1613,   32,     1614,   1600,   1614,
5518
    32,     1615,   1600,   1615,   32,     1616,   1600,   1616,   32,
5519
    1617,   1600,   1617,   32,     1618,   1600,   1618,   1569,   1575,
5520
    1619,   1575,   1619,   1575,   1620,   1575,   1620,   1608,   1620,
5521
    1608,   1620,   1575,   1621,   1575,   1621,   1610,   1620,   1610,
5522
    1620,   1610,   1620,   1610,   1620,   1575,   1575,   1576,   1576,
5523
    1576,   1576,   1577,   1577,   1578,   1578,   1578,   1578,   1579,
5524
    1579,   1579,   1579,   1580,   1580,   1580,   1580,   1581,   1581,
5525
    1581,   1581,   1582,   1582,   1582,   1582,   1583,   1583,   1584,
5526
    1584,   1585,   1585,   1586,   1586,   1587,   1587,   1587,   1587,
5527
    1588,   1588,   1588,   1588,   1589,   1589,   1589,   1589,   1590,
5528
    1590,   1590,   1590,   1591,   1591,   1591,   1591,   1592,   1592,
5529
    1592,   1592,   1593,   1593,   1593,   1593,   1594,   1594,   1594,
5530
    1594,   1601,   1601,   1601,   1601,   1602,   1602,   1602,   1602,
5531
    1603,   1603,   1603,   1603,   1604,   1604,   1604,   1604,   1605,
5532
    1605,   1605,   1605,   1606,   1606,   1606,   1606,   1607,   1607,
5533
    1607,   1607,   1608,   1608,   1609,   1609,   1610,   1610,   1610,
5534
    1610,   1604,   1575,   1619,   1604,   1575,   1619,   1604,   1575,
5535
    1620,   1604,   1575,   1620,   1604,   1575,   1621,   1604,   1575,
5536
    1621,   1604,   1575,   1604,   1575,   33,     34,     35,     36,
5537
    37,     38,     39,     40,     41,     42,     43,     44,     45,
5538
    46,     47,     48,     49,     50,     51,     52,     53,     54,
5539
    55,     56,     57,     58,     59,     60,     61,     62,     63,
5540
    64,     65,     66,     67,     68,     69,     70,     71,     72,
5541
    73,     74,     75,     76,     77,     78,     79,     80,     81,
5542
    82,     83,     84,     85,     86,     87,     88,     89,     90,
5543
    91,     92,     93,     94,     95,     96,     97,     98,     99,
5544
    100,    101,    102,    103,    104,    105,    106,    107,    108,
5545
    109,    110,    111,    112,    113,    114,    115,    116,    117,
5546
    118,    119,    120,    121,    122,    123,    124,    125,    126,
5547
    10629,  10630,  12290,  12300,  12301,  12289,  12539,  12530,  12449,
5548
    12451,  12453,  12455,  12457,  12515,  12517,  12519,  12483,  12540,
5549
    12450,  12452,  12454,  12456,  12458,  12459,  12461,  12463,  12465,
5550
    12467,  12469,  12471,  12473,  12475,  12477,  12479,  12481,  12484,
5551
    12486,  12488,  12490,  12491,  12492,  12493,  12494,  12495,  12498,
5552
    12501,  12504,  12507,  12510,  12511,  12512,  12513,  12514,  12516,
5553
    12518,  12520,  12521,  12522,  12523,  12524,  12525,  12527,  12531,
5554
    12441,  12442,  4448,   4352,   4353,   4522,   4354,   4524,   4525,
5555
    4355,   4356,   4357,   4528,   4529,   4530,   4531,   4532,   4533,
5556
    4378,   4358,   4359,   4360,   4385,   4361,   4362,   4363,   4364,
5557
    4365,   4366,   4367,   4368,   4369,   4370,   4449,   4450,   4451,
5558
    4452,   4453,   4454,   4455,   4456,   4457,   4458,   4459,   4460,
5559
    4461,   4462,   4463,   4464,   4465,   4466,   4467,   4468,   4469,
5560
    162,    163,    172,    32,     772,    166,    165,    8361,   9474,
5561
    8592,   8593,   8594,   8595,   9632,   9675,   720,    721,    230,
5562
    665,    595,    675,    43878,  677,    676,    598,    599,    7569,
5563
    600,    606,    681,    612,    610,    608,    667,    295,    668,
5564
    615,    644,    682,    683,    620,    122628, 42894,  622,    122629,
5565
    654,    122630, 248,    630,    631,    113,    634,    122632, 637,
5566
    638,    640,    680,    678,    43879,  679,    648,    11377,  655,
5567
    673,    674,    664,    448,    449,    450,    122634, 122654, 69785,
5568
    69818,  69787,  69818,  69797,  69818,  69937,  69927,  69938,  69927,
5569
    70471,  70462,  70471,  70487,  70841,  70842,  70841,  70832,  70841,
5570
    70845,  71096,  71087,  71097,  71087,  71989,  71984,  119127, 119141,
5571
    119128, 119141, 119128, 119141, 119150, 119128, 119141, 119151, 119128,
5572
    119141, 119152, 119128, 119141, 119153, 119128, 119141, 119154, 119225,
5573
    119141, 119226, 119141, 119225, 119141, 119150, 119226, 119141, 119150,
5574
    119225, 119141, 119151, 119226, 119141, 119151, 65,     66,     67,
5575
    68,     69,     70,     71,     72,     73,     74,     75,     76,
5576
    77,     78,     79,     80,     81,     82,     83,     84,     85,
5577
    86,     87,     88,     89,     90,     97,     98,     99,     100,
5578
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5579
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5580
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5581
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5582
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5583
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5584
    103,    105,    106,    107,    108,    109,    110,    111,    112,
5585
    113,    114,    115,    116,    117,    118,    119,    120,    121,
5586
    122,    65,     66,     67,     68,     69,     70,     71,     72,
5587
    73,     74,     75,     76,     77,     78,     79,     80,     81,
5588
    82,     83,     84,     85,     86,     87,     88,     89,     90,
5589
    97,     98,     99,     100,    101,    102,    103,    104,    105,
5590
    106,    107,    108,    109,    110,    111,    112,    113,    114,
5591
    115,    116,    117,    118,    119,    120,    121,    122,    65,
5592
    67,     68,     71,     74,     75,     78,     79,     80,     81,
5593
    83,     84,     85,     86,     87,     88,     89,     90,     97,
5594
    98,     99,     100,    102,    104,    105,    106,    107,    108,
5595
    109,    110,    112,    113,    114,    115,    116,    117,    118,
5596
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5597
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5598
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5599
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5600
    103,    104,    105,    106,    107,    108,    109,    110,    111,
5601
    112,    113,    114,    115,    116,    117,    118,    119,    120,
5602
    121,    122,    65,     66,     68,     69,     70,     71,     74,
5603
    75,     76,     77,     78,     79,     80,     81,     83,     84,
5604
    85,     86,     87,     88,     89,     97,     98,     99,     100,
5605
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5606
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5607
    119,    120,    121,    122,    65,     66,     68,     69,     70,
5608
    71,     73,     74,     75,     76,     77,     79,     83,     84,
5609
    85,     86,     87,     88,     89,     97,     98,     99,     100,
5610
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5611
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5612
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5613
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5614
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5615
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5616
    103,    104,    105,    106,    107,    108,    109,    110,    111,
5617
    112,    113,    114,    115,    116,    117,    118,    119,    120,
5618
    121,    122,    65,     66,     67,     68,     69,     70,     71,
5619
    72,     73,     74,     75,     76,     77,     78,     79,     80,
5620
    81,     82,     83,     84,     85,     86,     87,     88,     89,
5621
    90,     97,     98,     99,     100,    101,    102,    103,    104,
5622
    105,    106,    107,    108,    109,    110,    111,    112,    113,
5623
    114,    115,    116,    117,    118,    119,    120,    121,    122,
5624
    65,     66,     67,     68,     69,     70,     71,     72,     73,
5625
    74,     75,     76,     77,     78,     79,     80,     81,     82,
5626
    83,     84,     85,     86,     87,     88,     89,     90,     97,
5627
    98,     99,     100,    101,    102,    103,    104,    105,    106,
5628
    107,    108,    109,    110,    111,    112,    113,    114,    115,
5629
    116,    117,    118,    119,    120,    121,    122,    65,     66,
5630
    67,     68,     69,     70,     71,     72,     73,     74,     75,
5631
    76,     77,     78,     79,     80,     81,     82,     83,     84,
5632
    85,     86,     87,     88,     89,     90,     97,     98,     99,
5633
    100,    101,    102,    103,    104,    105,    106,    107,    108,
5634
    109,    110,    111,    112,    113,    114,    115,    116,    117,
5635
    118,    119,    120,    121,    122,    65,     66,     67,     68,
5636
    69,     70,     71,     72,     73,     74,     75,     76,     77,
5637
    78,     79,     80,     81,     82,     83,     84,     85,     86,
5638
    87,     88,     89,     90,     97,     98,     99,     100,    101,
5639
    102,    103,    104,    105,    106,    107,    108,    109,    110,
5640
    111,    112,    113,    114,    115,    116,    117,    118,    119,
5641
    120,    121,    122,    65,     66,     67,     68,     69,     70,
5642
    71,     72,     73,     74,     75,     76,     77,     78,     79,
5643
    80,     81,     82,     83,     84,     85,     86,     87,     88,
5644
    89,     90,     97,     98,     99,     100,    101,    102,    103,
5645
    104,    105,    106,    107,    108,    109,    110,    111,    112,
5646
    113,    114,    115,    116,    117,    118,    119,    120,    121,
5647
    122,    305,    567,    913,    914,    915,    916,    917,    918,
5648
    919,    920,    921,    922,    923,    924,    925,    926,    927,
5649
    928,    929,    920,    931,    932,    933,    934,    935,    936,
5650
    937,    8711,   945,    946,    947,    948,    949,    950,    951,
5651
    952,    953,    954,    955,    956,    957,    958,    959,    960,
5652
    961,    962,    963,    964,    965,    966,    967,    968,    969,
5653
    8706,   949,    952,    954,    966,    961,    960,    913,    914,
5654
    915,    916,    917,    918,    919,    920,    921,    922,    923,
5655
    924,    925,    926,    927,    928,    929,    920,    931,    932,
5656
    933,    934,    935,    936,    937,    8711,   945,    946,    947,
5657
    948,    949,    950,    951,    952,    953,    954,    955,    956,
5658
    957,    958,    959,    960,    961,    962,    963,    964,    965,
5659
    966,    967,    968,    969,    8706,   949,    952,    954,    966,
5660
    961,    960,    913,    914,    915,    916,    917,    918,    919,
5661
    920,    921,    922,    923,    924,    925,    926,    927,    928,
5662
    929,    920,    931,    932,    933,    934,    935,    936,    937,
5663
    8711,   945,    946,    947,    948,    949,    950,    951,    952,
5664
    953,    954,    955,    956,    957,    958,    959,    960,    961,
5665
    962,    963,    964,    965,    966,    967,    968,    969,    8706,
5666
    949,    952,    954,    966,    961,    960,    913,    914,    915,
5667
    916,    917,    918,    919,    920,    921,    922,    923,    924,
5668
    925,    926,    927,    928,    929,    920,    931,    932,    933,
5669
    934,    935,    936,    937,    8711,   945,    946,    947,    948,
5670
    949,    950,    951,    952,    953,    954,    955,    956,    957,
5671
    958,    959,    960,    961,    962,    963,    964,    965,    966,
5672
    967,    968,    969,    8706,   949,    952,    954,    966,    961,
5673
    960,    913,    914,    915,    916,    917,    918,    919,    920,
5674
    921,    922,    923,    924,    925,    926,    927,    928,    929,
5675
    920,    931,    932,    933,    934,    935,    936,    937,    8711,
5676
    945,    946,    947,    948,    949,    950,    951,    952,    953,
5677
    954,    955,    956,    957,    958,    959,    960,    961,    962,
5678
    963,    964,    965,    966,    967,    968,    969,    8706,   949,
5679
    952,    954,    966,    961,    960,    988,    989,    48,     49,
5680
    50,     51,     52,     53,     54,     55,     56,     57,     48,
5681
    49,     50,     51,     52,     53,     54,     55,     56,     57,
5682
    48,     49,     50,     51,     52,     53,     54,     55,     56,
5683
    57,     48,     49,     50,     51,     52,     53,     54,     55,
5684
    56,     57,     48,     49,     50,     51,     52,     53,     54,
5685
    55,     56,     57,     1072,   1073,   1074,   1075,   1076,   1077,
5686
    1078,   1079,   1080,   1082,   1083,   1084,   1086,   1087,   1088,
5687
    1089,   1090,   1091,   1092,   1093,   1094,   1095,   1096,   1099,
5688
    1101,   1102,   42633,  1241,   1110,   1112,   1257,   1199,   1231,
5689
    1072,   1073,   1074,   1075,   1076,   1077,   1078,   1079,   1080,
5690
    1082,   1083,   1086,   1087,   1089,   1091,   1092,   1093,   1094,
5691
    1095,   1096,   1098,   1099,   1169,   1110,   1109,   1119,   1195,
5692
    42577,  1201,   1575,   1576,   1580,   1583,   1608,   1586,   1581,
5693
    1591,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5694
    1589,   1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,
5695
    1592,   1594,   1646,   1722,   1697,   1647,   1576,   1580,   1607,
5696
    1581,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5697
    1589,   1602,   1588,   1578,   1579,   1582,   1590,   1594,   1580,
5698
    1581,   1610,   1604,   1606,   1587,   1593,   1589,   1602,   1588,
5699
    1582,   1590,   1594,   1722,   1647,   1576,   1580,   1607,   1581,
5700
    1591,   1610,   1603,   1605,   1606,   1587,   1593,   1601,   1589,
5701
    1602,   1588,   1578,   1579,   1582,   1590,   1592,   1594,   1646,
5702
    1697,   1575,   1576,   1580,   1583,   1607,   1608,   1586,   1581,
5703
    1591,   1610,   1604,   1605,   1606,   1587,   1593,   1601,   1589,
5704
    1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,   1592,
5705
    1594,   1576,   1580,   1583,   1608,   1586,   1581,   1591,   1610,
5706
    1604,   1605,   1606,   1587,   1593,   1601,   1589,   1602,   1585,
5707
    1588,   1578,   1579,   1582,   1584,   1590,   1592,   1594,   48,
5708
    46,     48,     44,     49,     44,     50,     44,     51,     44,
5709
    52,     44,     53,     44,     54,     44,     55,     44,     56,
5710
    44,     57,     44,     40,     65,     41,     40,     66,     41,
5711
    40,     67,     41,     40,     68,     41,     40,     69,     41,
5712
    40,     70,     41,     40,     71,     41,     40,     72,     41,
5713
    40,     73,     41,     40,     74,     41,     40,     75,     41,
5714
    40,     76,     41,     40,     77,     41,     40,     78,     41,
5715
    40,     79,     41,     40,     80,     41,     40,     81,     41,
5716
    40,     82,     41,     40,     83,     41,     40,     84,     41,
5717
    40,     85,     41,     40,     86,     41,     40,     87,     41,
5718
    40,     88,     41,     40,     89,     41,     40,     90,     41,
5719
    12308,  83,     12309,  67,     82,     67,     68,     87,     90,
5720
    65,     66,     67,     68,     69,     70,     71,     72,     73,
5721
    74,     75,     76,     77,     78,     79,     80,     81,     82,
5722
    83,     84,     85,     86,     87,     88,     89,     90,     72,
5723
    86,     77,     86,     83,     68,     83,     83,     80,     80,
5724
    86,     87,     67,     77,     67,     77,     68,     77,     82,
5725
    68,     74,     12411,  12363,  12467,  12467,  12469,  25163,  23383,
5726
    21452,  12486,  12441,  20108,  22810,  35299,  22825,  20132,  26144,
5727
    28961,  26009,  21069,  24460,  20877,  26032,  21021,  32066,  29983,
5728
    36009,  22768,  21561,  28436,  25237,  25429,  19968,  19977,  36938,
5729
    24038,  20013,  21491,  25351,  36208,  25171,  31105,  31354,  21512,
5730
    28288,  26377,  26376,  30003,  21106,  21942,  37197,  12308,  26412,
5731
    12309,  12308,  19977,  12309,  12308,  20108,  12309,  12308,  23433,
5732
    12309,  12308,  28857,  12309,  12308,  25171,  12309,  12308,  30423,
5733
    12309,  12308,  21213,  12309,  12308,  25943,  12309,  24471,  21487,
5734
    48,     49,     50,     51,     52,     53,     54,     55,     56,
5735
    57,     20029,  20024,  20033,  131362, 20320,  20398,  20411,  20482,
5736
    20602,  20633,  20711,  20687,  13470,  132666, 20813,  20820,  20836,
5737
    20855,  132380, 13497,  20839,  20877,  132427, 20887,  20900,  20172,
5738
    20908,  20917,  168415, 20981,  20995,  13535,  21051,  21062,  21106,
5739
    21111,  13589,  21191,  21193,  21220,  21242,  21253,  21254,  21271,
5740
    21321,  21329,  21338,  21363,  21373,  21375,  21375,  21375,  133676,
5741
    28784,  21450,  21471,  133987, 21483,  21489,  21510,  21662,  21560,
5742
    21576,  21608,  21666,  21750,  21776,  21843,  21859,  21892,  21892,
5743
    21913,  21931,  21939,  21954,  22294,  22022,  22295,  22097,  22132,
5744
    20999,  22766,  22478,  22516,  22541,  22411,  22578,  22577,  22700,
5745
    136420, 22770,  22775,  22790,  22810,  22818,  22882,  136872, 136938,
5746
    23020,  23067,  23079,  23000,  23142,  14062,  14076,  23304,  23358,
5747
    23358,  137672, 23491,  23512,  23527,  23539,  138008, 23551,  23558,
5748
    24403,  23586,  14209,  23648,  23662,  23744,  23693,  138724, 23875,
5749
    138726, 23918,  23915,  23932,  24033,  24034,  14383,  24061,  24104,
5750
    24125,  24169,  14434,  139651, 14460,  24240,  24243,  24246,  24266,
5751
    172946, 24318,  140081, 140081, 33281,  24354,  24354,  14535,  144056,
5752
    156122, 24418,  24427,  14563,  24474,  24525,  24535,  24569,  24705,
5753
    14650,  14620,  24724,  141012, 24775,  24904,  24908,  24910,  24908,
5754
    24954,  24974,  25010,  24996,  25007,  25054,  25074,  25078,  25104,
5755
    25115,  25181,  25265,  25300,  25424,  142092, 25405,  25340,  25448,
5756
    25475,  25572,  142321, 25634,  25541,  25513,  14894,  25705,  25726,
5757
    25757,  25719,  14956,  25935,  25964,  143370, 26083,  26360,  26185,
5758
    15129,  26257,  15112,  15076,  20882,  20885,  26368,  26268,  32941,
5759
    17369,  26391,  26395,  26401,  26462,  26451,  144323, 15177,  26618,
5760
    26501,  26706,  26757,  144493, 26766,  26655,  26900,  15261,  26946,
5761
    27043,  27114,  27304,  145059, 27355,  15384,  27425,  145575, 27476,
5762
    15438,  27506,  27551,  27578,  27579,  146061, 138507, 146170, 27726,
5763
    146620, 27839,  27853,  27751,  27926,  27966,  28023,  27969,  28009,
5764
    28024,  28037,  146718, 27956,  28207,  28270,  15667,  28363,  28359,
5765
    147153, 28153,  28526,  147294, 147342, 28614,  28729,  28702,  28699,
5766
    15766,  28746,  28797,  28791,  28845,  132389, 28997,  148067, 29084,
5767
    148395, 29224,  29237,  29264,  149000, 29312,  29333,  149301, 149524,
5768
    29562,  29579,  16044,  29605,  16056,  16056,  29767,  29788,  29809,
5769
    29829,  29898,  16155,  29988,  150582, 30014,  150674, 30064,  139679,
5770
    30224,  151457, 151480, 151620, 16380,  16392,  30452,  151795, 151794,
5771
    151833, 151859, 30494,  30495,  30495,  30538,  16441,  30603,  16454,
5772
    16534,  152605, 30798,  30860,  30924,  16611,  153126, 31062,  153242,
5773
    153285, 31119,  31211,  16687,  31296,  31306,  31311,  153980, 154279,
5774
    154279, 31470,  16898,  154539, 31686,  31689,  16935,  154752, 31954,
5775
    17056,  31976,  31971,  32000,  155526, 32099,  17153,  32199,  32258,
5776
    32325,  17204,  156200, 156231, 17241,  156377, 32634,  156478, 32661,
5777
    32762,  32773,  156890, 156963, 32864,  157096, 32880,  144223, 17365,
5778
    32946,  33027,  17419,  33086,  23221,  157607, 157621, 144275, 144284,
5779
    33281,  33284,  36766,  17515,  33425,  33419,  33437,  21171,  33457,
5780
    33459,  33469,  33510,  158524, 33509,  33565,  33635,  33709,  33571,
5781
    33725,  33767,  33879,  33619,  33738,  33740,  33756,  158774, 159083,
5782
    158933, 17707,  34033,  34035,  34070,  160714, 34148,  159532, 17757,
5783
    17761,  159665, 159954, 17771,  34384,  34396,  34407,  34409,  34473,
5784
    34440,  34574,  34530,  34681,  34600,  34667,  34694,  17879,  34785,
5785
    34817,  17913,  34912,  34915,  161383, 35031,  35038,  17973,  35066,
5786
    13499,  161966, 162150, 18110,  18119,  35488,  35565,  35722,  35925,
5787
    162984, 36011,  36033,  36123,  36215,  163631, 133124, 36299,  36284,
5788
    36336,  133342, 36564,  36664,  165330, 165357, 37012,  37105,  37137,
5789
    165678, 37147,  37432,  37591,  37592,  37500,  37881,  37909,  166906,
5790
    38283,  18837,  38327,  167287, 18918,  38595,  23986,  38691,  168261,
5791
    168474, 19054,  19062,  38880,  168970, 19122,  169110, 38923,  38923,
5792
    38953,  169398, 39138,  19251,  39209,  39335,  39362,  39422,  19406,
5793
    170800, 39698,  40000,  40189,  19662,  19693,  40295,  172238, 19704,
5794
    172293, 172558, 172689, 40635,  19798,  40697,  40702,  40709,  40719,
5795
    40726,  40763,  173568};
5796
5797
const uint8_t canonical_combining_class_index[4352] = {
5798
    0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 0,  0,
5799
    15, 0,  0,  0,  16, 17, 18, 19, 20, 21, 22, 0,  0,  23, 0,  0,  0,  0,  0,
5800
    0,  0,  0,  0,  0,  0,  24, 25, 0,  0,  26, 0,  0,  0,  0,  0,  0,  0,  0,
5801
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5802
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5803
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5804
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5805
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5806
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  27, 0,  28, 29, 30,
5807
    31, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5808
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5809
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5810
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5811
    0,  0,  0,  0,  32, 0,  0,  33, 0,  0,  34, 35, 36, 0,  0,  0,  0,  0,  0,
5812
    37, 0,  0,  38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,  52,
5813
    53, 0,  54, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5814
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5815
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5816
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5817
    0,  55, 56, 0,  0,  0,  57, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5818
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5819
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5820
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5821
    0,  0,  0,  0,  0,  0,  0,  58, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5822
    0,  0,  0,  0,  0,  0,  0,  0,  0,  59, 60, 0,  0,  0,  0,  0,  0,  0,  0,
5823
    0,  0,  0,  0,  0,  61, 56, 62, 0,  63, 0,  0,  0,  64, 65, 0,  0,  0,  0,
5824
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5825
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5826
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5827
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5828
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5829
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5830
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5831
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5832
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5833
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5834
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5835
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5836
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5837
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5838
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5839
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5840
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5841
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5842
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5843
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5844
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5845
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5846
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5847
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5848
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5849
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5850
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5851
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5852
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5853
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5854
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5855
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5856
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5857
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5858
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5859
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5860
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5861
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5862
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5863
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5864
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5865
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5866
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5867
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5868
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5869
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5870
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5871
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5872
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5873
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5874
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5875
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5876
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5877
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5878
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5879
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5880
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5881
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5882
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5883
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5884
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5885
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5886
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5887
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5888
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5889
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5890
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5891
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5892
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5893
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5894
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5895
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5896
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5897
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5898
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5899
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5900
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5901
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5902
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5903
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5904
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5905
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5906
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5907
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5908
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5909
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5910
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5911
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5912
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5913
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5914
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5915
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5916
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5917
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5918
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5919
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5920
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5921
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5922
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5923
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5924
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5925
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5926
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5927
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5928
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5929
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5930
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5931
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5932
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5933
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5934
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5935
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5936
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5937
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5938
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5939
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5940
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5941
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5942
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5943
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5944
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5945
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5946
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5947
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5948
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5949
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5950
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5951
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5952
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5953
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5954
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5955
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5956
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5957
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5958
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5959
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5960
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5961
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5962
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5963
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5964
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5965
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5966
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5967
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5968
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5969
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5970
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5971
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5972
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5973
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5974
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5975
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5976
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5977
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5978
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5979
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5980
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5981
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5982
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5983
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5984
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5985
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5986
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5987
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5988
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5989
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5990
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5991
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5992
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5993
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5994
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5995
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5996
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5997
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5998
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5999
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6000
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6001
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6002
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6003
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6004
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6005
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6006
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6007
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6008
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6009
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6010
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6011
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6012
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6013
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6014
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6015
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6016
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6017
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6018
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6019
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6020
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6021
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6022
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6023
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6024
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6025
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6026
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6027
    0};
6028
const uint8_t canonical_combining_class_block[67][256] = {
6029
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6030
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6031
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6032
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6033
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6034
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6035
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6036
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6037
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6038
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6039
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6040
    {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6041
     230, 230, 230, 230, 230, 230, 232, 220, 220, 220, 220, 232, 216, 220, 220,
6042
     220, 220, 220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220,
6043
     220, 220, 220, 220, 220, 220, 220, 1,   1,   1,   1,   1,   220, 220, 220,
6044
     220, 230, 230, 230, 230, 230, 230, 230, 230, 240, 230, 220, 220, 220, 230,
6045
     230, 230, 220, 220, 0,   230, 230, 230, 220, 220, 220, 220, 230, 232, 220,
6046
     220, 230, 233, 234, 234, 233, 234, 234, 233, 230, 230, 230, 230, 230, 230,
6047
     230, 230, 230, 230, 230, 230, 230, 0,   0,   0,   0,   0,   0,   0,   0,
6048
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6049
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6050
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6051
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6052
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6053
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6054
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6055
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6056
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6057
     0},
6058
    {0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6059
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6060
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6061
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6062
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6063
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230,
6064
     230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6065
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6066
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6067
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6068
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6069
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6070
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6071
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6072
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6073
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6074
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6075
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6076
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6077
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6078
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6079
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 230, 230, 230, 230,
6080
     220, 230, 230, 230, 222, 220, 230, 230, 230, 230, 230, 230, 220, 220, 220,
6081
     220, 220, 220, 230, 230, 220, 230, 230, 222, 228, 230, 10,  11,  12,  13,
6082
     14,  15,  16,  17,  18,  19,  19,  20,  21,  22,  0,   23,  0,   24,  25,
6083
     0,   230, 220, 0,   18,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6084
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6085
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6086
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6087
     0},
6088
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6089
     0,   230, 230, 230, 230, 230, 230, 230, 230, 30,  31,  32,  0,   0,   0,
6090
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6091
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6092
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6093
     27,  28,  29,  30,  31,  32,  33,  34,  230, 230, 220, 220, 230, 230, 230,
6094
     230, 230, 220, 230, 230, 220, 0,   0,   0,   0,   0,   0,   0,   0,   0,
6095
     0,   0,   0,   0,   0,   0,   0,   35,  0,   0,   0,   0,   0,   0,   0,
6096
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6097
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6098
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6099
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6100
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6101
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6102
     0,   0,   0,   0,   230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230,
6103
     230, 230, 220, 230, 0,   0,   230, 230, 0,   220, 230, 230, 220, 0,   0,
6104
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6105
     0},
6106
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6107
     0,   0,   36,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6108
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6109
     0,   0,   0,   230, 220, 230, 230, 220, 230, 230, 220, 220, 220, 230, 220,
6110
     220, 230, 220, 230, 230, 230, 220, 230, 220, 230, 220, 230, 220, 230, 230,
6111
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6112
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6113
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6114
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6115
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6116
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6117
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6118
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6119
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6120
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6121
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 230,
6122
     230, 230, 220, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 0,
6123
     0},
6124
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6125
     0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 0,   230, 230, 230,
6126
     230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 0,   230, 230, 230, 230,
6127
     230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6128
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6129
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   220,
6130
     220, 220, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6131
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6132
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6133
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6134
     0,   0,   230, 220, 220, 220, 230, 230, 230, 230, 0,   0,   0,   0,   0,
6135
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6136
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6137
     0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 230, 220, 220, 220,
6138
     220, 220, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6139
     230, 0,   220, 230, 230, 220, 230, 230, 220, 230, 230, 230, 220, 220, 220,
6140
     27,  28,  29,  230, 230, 230, 220, 230, 230, 220, 220, 230, 230, 230, 230,
6141
     230},
6142
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6143
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6144
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   7,   0,   0,   0, 0, 0,
6145
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0, 0, 230, 220, 230, 230, 0, 0, 0,
6146
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6147
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6148
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6149
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6150
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6151
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6152
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6153
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0},
6154
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6155
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6156
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6157
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6158
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6159
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6160
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6161
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
6162
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6163
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6164
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6165
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6166
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6167
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6168
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6169
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6170
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6171
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6172
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6173
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6174
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6175
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6176
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6177
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6178
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6179
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 84, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6180
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6181
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6182
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6183
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 7, 0, 0, 0,
6184
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6185
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6186
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0},
6187
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6188
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6189
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6190
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6191
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6192
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6193
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6194
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6195
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6196
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6197
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6198
    {0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6199
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6200
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6201
     0,   0,   103, 103, 9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6202
     107, 107, 107, 107, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6203
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6204
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6205
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6206
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6207
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6208
     0,   0,   0,   0,   118, 118, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6209
     0,   0,   122, 122, 122, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6210
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6211
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6212
     0,   0,   0,   0},
6213
    {0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6214
     0,   0, 0,   0,   0,   0,   0, 0, 0,   220, 220, 0,   0,   0, 0,
6215
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6216
     0,   0, 0,   0,   0,   0,   0, 0, 220, 0,   220, 0,   216, 0, 0,
6217
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6218
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6219
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6220
     0,   0, 0,   0,   0,   0,   0, 0, 129, 130, 0,   132, 0,   0, 0,
6221
     0,   0, 130, 130, 130, 130, 0, 0, 130, 0,   230, 230, 9,   0, 230,
6222
     230, 0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6223
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6224
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6225
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6226
     0,   0, 0,   220, 0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6227
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6228
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6229
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6230
     0},
6231
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6232
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6233
     0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6234
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6235
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6236
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0,
6237
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6238
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6239
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6240
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6241
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6242
    {0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6243
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6244
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6245
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6246
     0, 0, 0, 0, 0, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6247
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6248
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6249
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6250
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6251
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6252
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6253
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0},
6254
    {0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0,
6255
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6256
     0, 0, 0, 0, 9, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6257
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6258
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6259
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6260
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6261
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6262
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6263
     0, 0, 0, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6264
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6265
    {0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6266
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6267
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6268
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6269
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6270
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6271
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6272
     0, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6273
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6274
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6275
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6276
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6277
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6278
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 230, 220, 0, 0, 0, 0, 0, 0,
6279
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6280
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6281
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6282
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6283
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6284
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6285
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6286
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6287
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6288
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6289
     0,   0,   0,   0,   0,   0,   0,   0,   230, 220, 0,   0,   0,   0,   0,
6290
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6291
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6292
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6293
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6294
     0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6295
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230,
6296
     230, 230, 230, 230, 230, 0,   0,   220, 0,   0,   0,   0,   0,   0,   0,
6297
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6298
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6299
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230,
6300
     230, 220, 220, 220, 220, 220, 220, 230, 230, 220, 0,   220, 220, 230, 230,
6301
     220, 220, 230, 230, 230, 230, 230, 220, 230, 230, 230, 230, 0,   0,   0,
6302
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6303
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6304
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6305
     0},
6306
    {0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6307
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6308
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   7,   0,   0,   0,   0,
6309
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0,   0,   0,   0,   0,   0,
6310
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6311
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 230, 230, 230, 230, 230,
6312
     230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6313
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6314
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   9,
6315
     9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6316
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6317
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6318
     0,   0,   7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   9,   9,   0,   0,   0,
6319
     0,   0,   0, 0, 0, 0, 0, 0, 0},
6320
    {0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6321
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6322
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6323
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   7,   0,   0,   0,   0,
6324
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6325
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6326
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6327
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6328
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6329
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6330
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6331
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6332
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6333
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230,
6334
     230, 0, 1, 220, 220, 220, 220, 220, 230, 230, 220, 220, 220, 220, 230,
6335
     0,   1, 1, 1,   1,   1,   1,   1,   0,   0,   0,   0,   220, 0,   0,
6336
     0,   0, 0, 0,   230, 0,   0,   0,   230, 230, 0,   0,   0,   0,   0,
6337
     0},
6338
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6339
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6340
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6341
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6342
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6343
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6344
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6345
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6346
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6347
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6348
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6349
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6350
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 220,
6351
     230, 230, 230, 230, 230, 230, 230, 220, 230, 230, 234, 214, 220, 202, 230,
6352
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6353
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6354
     230, 230, 230, 230, 230, 230, 232, 228, 228, 220, 218, 230, 233, 220, 230,
6355
     220},
6356
    {0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6357
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6358
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6359
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6360
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6361
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6362
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6363
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6364
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6365
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6366
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6367
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6368
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6369
     230, 230, 1, 1, 230, 230, 230, 230, 1,   1,   1, 230, 230, 0,   0,   0,
6370
     0,   230, 0, 0, 0,   1,   1,   230, 220, 230, 1, 1,   220, 220, 220, 220,
6371
     230, 0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0},
6372
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6373
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6374
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6375
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6376
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6377
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6378
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6379
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6380
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6381
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6382
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230,
6383
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6384
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6385
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6386
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6387
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6388
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6389
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6390
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6391
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6392
     0,   0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,
6393
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6394
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6395
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6396
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6397
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6398
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6399
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6400
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6401
     230},
6402
    {0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6403
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6404
     0, 0, 218, 228, 232, 222, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6405
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6406
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6407
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6408
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6409
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0,
6410
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6411
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6412
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6413
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6414
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0},
6415
    {0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6416
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6417
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6418
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6419
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6420
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6421
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6422
     0,   0,   0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,
6423
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6424
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230,
6425
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6426
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6427
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6428
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6429
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6430
     230, 230, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0},
6431
    {0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6432
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6433
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   9,
6434
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6435
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6436
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6437
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6438
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6439
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6440
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6441
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6442
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6443
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6444
     0,   9,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6445
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6446
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6447
     230, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6448
     0},
6449
    {0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6450
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220,
6451
     220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6452
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
6453
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6454
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6455
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6456
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6457
     0,   0,   0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6458
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6459
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6460
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6461
    {0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6462
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6463
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6464
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6465
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6466
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6467
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6468
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6469
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6470
     0,   0,   0, 0,   0, 230, 0, 230, 230, 220, 0, 0, 230, 230, 0, 0, 0, 0, 0,
6471
     230, 230, 0, 230, 0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6472
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6473
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 9,
6474
     0,   0,   0, 0,   0, 0,   0, 0,   0},
6475
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6476
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6477
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6478
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6479
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6480
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6481
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6482
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6483
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6484
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0,
6485
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6486
    {0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6487
     0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6488
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6489
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6490
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6491
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6492
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6493
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6494
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6495
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6496
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0},
6497
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6498
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6499
     0,   0,   230, 230, 230, 230, 230, 230, 230, 220, 220, 220, 220, 220, 220,
6500
     220, 230, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6501
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6502
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6503
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6504
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6505
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6506
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6507
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6508
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6509
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6510
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6511
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6512
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6513
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6514
     0},
6515
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6516
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6517
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6518
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6519
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6520
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6521
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6522
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6523
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6524
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6525
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0},
6526
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6527
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6528
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6529
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6530
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6531
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6532
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6533
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6534
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6535
     0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6536
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0},
6537
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6538
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6539
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6540
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6541
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6542
     0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6543
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6544
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6545
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6546
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6547
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6548
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0},
6549
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 220, 0, 230, 0,   0, 0,   0,
6550
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6551
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   230, 1, 220, 0,
6552
     0, 0, 0, 9, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6553
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6554
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6555
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6556
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6557
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6558
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6559
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6560
     0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 0, 0, 0,   0, 0,   0,   0, 0,   0,
6561
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0},
6562
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6563
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0, 0, 0, 0,
6564
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6565
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6566
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6567
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6568
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6569
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6570
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6571
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6572
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6573
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6574
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6575
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6576
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6577
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6578
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6579
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6580
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6581
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 230, 230, 0, 0, 0,
6582
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6583
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6584
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6585
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220},
6586
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6587
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6588
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6589
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 220, 220,
6590
     230, 230, 230, 220, 230, 220, 220, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6591
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6592
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6593
     0,   0,   0,   0,   230, 220, 230, 220, 0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6594
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6595
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6596
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6597
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6598
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6599
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6600
     0,   0,   0,   0},
6601
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6602
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6603
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,
6604
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6605
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
6606
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6607
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6608
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0,
6609
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6610
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6611
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6612
    {230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6613
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6614
     0,   0,   0,   0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6615
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6616
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6617
     0,   0,   0,   0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6618
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6619
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6620
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6621
     0,   0,   0,   0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6622
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6623
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6624
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6625
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6626
     0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6627
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6628
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6629
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6630
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6631
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6632
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6633
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 0, 0, 0, 0, 0,
6634
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6635
    {0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6636
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6637
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6638
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   7,   7,   0, 0, 0,
6639
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   9, 0, 0,
6640
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6641
     0,   0,   0,   0,   0,   0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0,
6642
     230, 230, 230, 230, 230, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6643
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6644
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6645
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6646
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6647
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6648
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6649
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6650
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0},
6651
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6652
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6653
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 7,   0,
6654
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0,
6655
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6656
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6657
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6658
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6659
     0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6660
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6661
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6662
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6663
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6664
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6665
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6666
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6667
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6668
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6669
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
6670
     7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6671
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6672
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6673
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6674
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6675
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
6676
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6677
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6678
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6679
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6680
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0,
6681
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6682
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6683
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6684
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6685
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
6686
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6687
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6688
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6689
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6690
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6691
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6692
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6693
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6694
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6695
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6696
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6697
     0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6698
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6699
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6700
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6701
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6702
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6703
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6704
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6705
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6706
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6707
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6708
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 7, 0, 0, 0, 0,
6709
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6710
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6711
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6712
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6713
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6714
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6715
     0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6716
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6717
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6718
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6719
     0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
6720
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6721
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6722
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6723
     0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6724
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6725
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6726
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6727
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6728
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6729
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6730
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
6731
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6732
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6733
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6734
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6735
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6736
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6737
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6738
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6739
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6740
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6741
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0,
6742
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6743
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6744
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6745
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6746
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6747
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6748
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6749
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6750
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6751
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6752
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0,
6753
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6754
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6755
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6756
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6757
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6758
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6759
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6760
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6761
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6762
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6763
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6764
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6765
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6766
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6767
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6768
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6769
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6770
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6771
     1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6772
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6773
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6774
     0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0,
6775
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6776
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6777
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6778
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6779
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6780
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6781
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6782
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6783
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6784
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0},
6785
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6786
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6787
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6788
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6789
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6790
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6791
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6792
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6793
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6794
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6795
     6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6796
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6797
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6798
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6799
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6800
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6801
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6802
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6803
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6804
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6805
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6806
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6807
    {0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6808
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6809
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6810
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6811
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6812
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6813
     0,   0,   0,   0, 0, 216, 216, 1,   1,   1,   0,   0,   0,   226, 216, 216,
6814
     216, 216, 216, 0, 0, 0,   0,   0,   0,   0,   0,   220, 220, 220, 220, 220,
6815
     220, 220, 220, 0, 0, 230, 230, 230, 230, 230, 220, 220, 0,   0,   0,   0,
6816
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6817
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   230, 230, 230, 230, 0,   0,
6818
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6819
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6820
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6821
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6822
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0},
6823
    {0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6824
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6825
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6826
     230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6827
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6828
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6829
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6830
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6831
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6832
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6833
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6834
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6835
    {230, 230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 230, 230, 230, 230,
6836
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230, 230,
6837
     230, 230, 230, 230, 0,   230, 230, 0,   230, 230, 230, 230, 230, 0,   0,
6838
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6839
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6840
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6841
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6842
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6843
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6844
     0,   0,   0,   0,   0,   0,   0,   0,   230, 0,   0,   0,   0,   0,   0,
6845
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6846
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6847
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6848
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6849
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6850
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6851
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6852
     0},
6853
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6854
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6855
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6856
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6857
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6858
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6859
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6860
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   230, 0,
6861
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6862
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6863
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0,   0,
6864
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6865
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6866
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6867
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6868
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6869
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6870
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6871
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6872
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6873
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6874
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6875
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 232, 220, 230, 0, 0,
6876
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6877
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6878
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6879
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6880
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6881
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6882
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6883
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6884
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6885
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6886
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6887
     0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 220, 220, 220, 220, 0, 0, 0, 0, 0,
6888
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6889
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0},
6890
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6891
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6892
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6893
     0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 7, 0, 0, 0, 0, 0,
6894
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6895
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6896
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6897
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6898
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6899
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6900
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6901
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6902
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0}};
6903
6904
const uint8_t composition_index[4352] = {
6905
    0, 1, 2, 3, 4,  5,  6, 5, 5,  7,  5, 8,  9,  10, 5, 5, 11, 5,  5, 5, 5, 5,
6906
    5, 5, 5, 5, 5,  12, 5, 5, 13, 14, 5, 15, 16, 5,  5, 5, 5,  5,  5, 5, 5, 5,
6907
    5, 5, 5, 5, 17, 5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6908
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6909
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6910
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6911
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6912
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6913
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6914
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6915
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6916
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6917
    5, 5, 5, 5, 5,  5,  5, 5, 18, 19, 5, 20, 21, 22, 5, 5, 5,  23, 5, 5, 5, 5,
6918
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6919
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6920
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6921
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6922
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6923
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6924
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6925
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6926
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6927
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6928
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6929
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6930
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6931
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6932
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6933
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6934
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6935
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6936
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6937
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6938
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6939
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6940
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6941
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6942
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6943
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6944
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6945
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6946
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6947
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6948
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6949
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6950
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6951
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6952
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6953
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6954
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6955
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6956
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6957
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6958
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6959
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6960
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6961
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6962
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6963
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6964
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6965
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6966
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6967
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6968
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6969
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6970
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6971
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6972
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6973
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6974
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6975
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6976
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6977
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6978
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6979
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6980
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6981
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6982
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6983
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6984
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6985
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6986
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6987
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6988
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6989
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6990
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6991
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6992
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6993
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6994
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6995
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6996
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6997
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6998
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6999
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7000
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7001
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7002
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7003
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7004
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7005
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7006
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7007
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7008
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7009
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7010
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7011
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7012
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7013
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7014
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7015
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7016
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7017
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7018
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7019
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7020
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7021
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7022
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7023
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7024
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7025
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7026
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7027
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7028
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7029
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7030
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7031
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7032
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7033
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7034
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7035
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7036
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7037
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7038
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7039
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7040
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7041
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7042
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7043
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7044
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7045
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7046
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7047
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7048
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7049
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7050
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7051
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7052
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7053
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7054
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7055
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7056
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7057
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7058
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7059
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7060
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7061
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7062
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7063
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7064
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7065
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7066
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7067
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7068
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7069
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7070
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7071
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7072
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7073
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7074
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7075
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7076
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7077
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7078
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7079
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7080
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7081
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7082
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7083
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7084
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7085
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7086
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7087
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7088
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7089
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7090
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7091
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7092
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7093
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7094
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7095
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7096
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7097
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7098
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7099
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7100
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7101
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7102
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5};
7103
const uint16_t composition_block[67][257] = {
7104
    {1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7105
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7106
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7107
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7108
     1,   3,   5,   7,   7,   7,   39,  45,  55,  67,  101, 103, 117, 131, 161,
7109
     163, 173, 185, 191, 209, 241, 245, 245, 261, 275, 289, 327, 331, 343, 347,
7110
     365, 377, 377, 377, 377, 377, 377, 377, 409, 415, 425, 437, 471, 473, 487,
7111
     503, 531, 535, 545, 557, 563, 581, 613, 617, 617, 633, 647, 663, 701, 705,
7112
     719, 723, 743, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7113
     755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7114
     755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7115
     755, 755, 755, 755, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7116
     761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7117
     769, 769, 771, 773, 777, 779, 779, 779, 787, 787, 787, 787, 787, 789, 789,
7118
     789, 789, 789, 797, 803, 805, 805, 807, 807, 807, 807, 815, 815, 815, 815,
7119
     815, 815, 823, 823, 825, 827, 831, 833, 833, 833, 841, 841, 841, 841, 841,
7120
     843, 843, 843, 843, 843, 851, 857, 859, 859, 861, 861, 861, 861, 869, 869,
7121
     869, 869},
7122
    {869, 869, 869, 877, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885,
7123
     885, 885, 885, 885, 889, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7124
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7125
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7126
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7127
     893, 893, 897, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901,
7128
     901, 903, 905, 905, 905, 905, 905, 907, 909, 909, 909, 909, 909, 909, 909,
7129
     911, 913, 915, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917,
7130
     917, 917, 917, 917, 917, 917, 917, 917, 919, 919, 919, 919, 919, 919, 919,
7131
     919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919,
7132
     919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 929, 939, 939, 939,
7133
     939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 949, 959, 959, 959,
7134
     959, 959, 959, 959, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7135
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7136
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7137
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 963, 965, 965, 965, 965,
7138
     965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7139
     965, 965},
7140
    {965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7141
     965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7142
     965, 965, 965, 965, 965, 965, 965, 965, 965, 967, 969, 971, 973, 973, 973,
7143
     973, 973, 975, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7144
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7145
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7146
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7147
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7148
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7149
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 979, 979, 979,
7150
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7151
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7152
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7153
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7154
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7155
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7156
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7157
     979, 979},
7158
    {979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7159
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7160
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7161
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7162
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7163
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7164
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7165
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7166
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7167
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7168
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7169
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7170
     979,  979,  993,  993,  993,  993,  1001, 1001, 1011, 1011, 1025, 1025,
7171
     1025, 1025, 1025, 1025, 1033, 1033, 1035, 1035, 1035, 1035, 1047, 1047,
7172
     1047, 1047, 1057, 1057, 1057, 1059, 1059, 1061, 1061, 1061, 1077, 1077,
7173
     1077, 1077, 1085, 1085, 1097, 1097, 1113, 1113, 1113, 1113, 1113, 1113,
7174
     1121, 1121, 1125, 1125, 1125, 1125, 1141, 1141, 1141, 1141, 1153, 1159,
7175
     1165, 1165, 1165, 1167, 1167, 1167, 1167, 1171, 1171, 1171, 1171, 1171,
7176
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7177
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7178
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7179
     1171, 1171, 1171, 1171, 1171},
7180
    {1171, 1171, 1171, 1171, 1171, 1171, 1171, 1173, 1173, 1173, 1173, 1173,
7181
     1173, 1173, 1173, 1173, 1173, 1177, 1177, 1177, 1179, 1179, 1185, 1189,
7182
     1191, 1199, 1199, 1201, 1201, 1201, 1201, 1203, 1203, 1203, 1203, 1203,
7183
     1211, 1211, 1211, 1211, 1213, 1213, 1213, 1213, 1215, 1215, 1217, 1217,
7184
     1217, 1221, 1221, 1221, 1223, 1223, 1229, 1233, 1235, 1243, 1243, 1245,
7185
     1245, 1245, 1245, 1247, 1247, 1247, 1247, 1247, 1255, 1255, 1255, 1255,
7186
     1257, 1257, 1257, 1257, 1259, 1259, 1261, 1261, 1261, 1261, 1261, 1261,
7187
     1261, 1261, 1261, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7188
     1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7189
     1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1265, 1267, 1267,
7190
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7191
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7192
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7193
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7194
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7195
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7196
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7197
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7198
     1267, 1269, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271,
7199
     1271, 1271, 1271, 1271, 1271, 1273, 1275, 1275, 1275, 1275, 1275, 1275,
7200
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7201
     1275, 1275, 1275, 1275, 1275},
7202
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7203
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7204
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7205
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7206
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7207
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7208
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7209
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7210
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7211
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7212
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
7213
    {1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7214
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7215
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7216
     1275, 1275, 1275, 1275, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7217
     1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7218
     1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7219
     1281, 1283, 1283, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7220
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7221
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7222
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7223
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7224
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7225
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7226
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7227
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7228
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7229
     1285, 1285, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
7230
     1287, 1287, 1287, 1287, 1287, 1287, 1287, 1289, 1289, 1289, 1291, 1291,
7231
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7232
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7233
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7234
     1291, 1291, 1291, 1291, 1291},
7235
    {1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7236
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7237
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7238
     1291, 1291, 1291, 1291, 1291, 1293, 1293, 1293, 1293, 1293, 1293, 1293,
7239
     1293, 1295, 1295, 1295, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7240
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7241
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7242
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7243
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7244
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7245
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7246
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7247
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7248
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7249
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7250
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7251
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1301, 1301, 1301, 1301,
7252
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7253
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7254
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7255
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7256
     1301, 1301, 1301, 1301, 1301},
7257
    {1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7258
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7259
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7260
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7261
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7262
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7263
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7264
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7265
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7266
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7267
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7268
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7269
     1307, 1307, 1307, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7270
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7271
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7272
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7273
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1313, 1315, 1315, 1315, 1315,
7274
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7275
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7276
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7277
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7278
     1315, 1315, 1315, 1315, 1315},
7279
    {1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7280
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7281
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7282
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7283
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7284
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1317,
7285
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7286
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7287
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7288
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7289
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7290
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7291
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7292
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7293
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7294
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7295
     1319, 1319, 1319, 1319, 1319, 1319, 1319, 1325, 1325, 1325, 1325, 1327,
7296
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7297
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7298
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7299
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7300
     1327, 1327, 1327, 1327, 1327},
7301
    {1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7302
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7303
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7304
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7305
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7306
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1331,
7307
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7308
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7309
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7310
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7311
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7312
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7313
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7314
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7315
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7316
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7317
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7318
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7319
     1333, 1333, 1339, 1339, 1339, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7320
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7321
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7322
     1341, 1341, 1341, 1341, 1341},
7323
    {1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7324
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7325
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7326
     1341, 1341, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7327
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7328
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7329
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7330
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7331
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7332
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7333
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7334
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7335
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7336
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7337
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7338
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7339
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7340
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7341
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7342
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7343
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7344
     1343, 1343, 1343, 1343, 1343},
7345
    {1343, 1343, 1343, 1343, 1343, 1343, 1345, 1345, 1347, 1347, 1349, 1349,
7346
     1351, 1351, 1353, 1353, 1353, 1353, 1355, 1355, 1355, 1355, 1355, 1355,
7347
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7348
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7349
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1357,
7350
     1357, 1359, 1359, 1361, 1363, 1363, 1363, 1365, 1365, 1365, 1365, 1365,
7351
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7352
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7353
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7354
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7355
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7356
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7357
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7358
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7359
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7360
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7361
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7362
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7363
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7364
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7365
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7366
     1365, 1365, 1365, 1365, 1365},
7367
    {1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7368
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7369
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7370
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7371
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1367, 1369, 1369, 1369, 1369,
7372
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7373
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7374
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1371, 1373, 1373, 1373, 1373,
7375
     1373, 1373, 1373, 1375, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7376
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7377
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7378
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7379
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7380
     1377, 1377, 1377, 1377, 1377, 1381, 1385, 1385, 1385, 1385, 1385, 1385,
7381
     1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385,
7382
     1385, 1385, 1385, 1385, 1385, 1387, 1389, 1389, 1389, 1389, 1389, 1389,
7383
     1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389,
7384
     1389, 1391, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7385
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7386
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7387
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7388
     1393, 1393, 1393, 1393, 1393},
7389
    {1393, 1401, 1409, 1411, 1413, 1415, 1417, 1419, 1421, 1429, 1437, 1439,
7390
     1441, 1443, 1445, 1447, 1449, 1453, 1457, 1457, 1457, 1457, 1457, 1457,
7391
     1457, 1461, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1473, 1481, 1483,
7392
     1485, 1487, 1489, 1491, 1493, 1501, 1509, 1511, 1513, 1515, 1517, 1519,
7393
     1521, 1527, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1539, 1545, 1545,
7394
     1545, 1545, 1545, 1545, 1545, 1549, 1553, 1553, 1553, 1553, 1553, 1553,
7395
     1553, 1557, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1567, 1573, 1573,
7396
     1573, 1573, 1573, 1573, 1573, 1573, 1579, 1579, 1579, 1579, 1579, 1579,
7397
     1579, 1587, 1595, 1597, 1599, 1601, 1603, 1605, 1607, 1615, 1623, 1625,
7398
     1627, 1629, 1631, 1633, 1635, 1637, 1637, 1637, 1637, 1639, 1639, 1639,
7399
     1639, 1639, 1639, 1639, 1639, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7400
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7401
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7402
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7403
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7404
     1641, 1641, 1641, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643,
7405
     1649, 1649, 1649, 1649, 1649, 1649, 1649, 1651, 1651, 1651, 1651, 1651,
7406
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7407
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7408
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7409
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1653, 1653, 1653, 1653, 1653,
7410
     1653, 1653, 1653, 1659, 1659},
7411
    {1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7412
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7413
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7414
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7415
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7416
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7417
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7418
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7419
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7420
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7421
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7422
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7423
     1659, 1661, 1661, 1663, 1663, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7424
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7425
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7426
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7427
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7428
     1665, 1665, 1665, 1665, 1665, 1667, 1667, 1669, 1669, 1671, 1671, 1671,
7429
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7430
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7431
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7432
     1671, 1671, 1671, 1671, 1671},
7433
    {1671, 1671, 1671, 1671, 1673, 1673, 1673, 1673, 1673, 1675, 1675, 1675,
7434
     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7435
     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7436
     1679, 1679, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7437
     1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7438
     1681, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1685, 1685, 1687, 1687,
7439
     1687, 1689, 1689, 1689, 1689, 1689, 1691, 1691, 1691, 1691, 1691, 1691,
7440
     1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691,
7441
     1691, 1691, 1693, 1693, 1693, 1695, 1697, 1697, 1697, 1697, 1697, 1697,
7442
     1697, 1697, 1697, 1697, 1697, 1697, 1697, 1699, 1701, 1701, 1701, 1703,
7443
     1705, 1705, 1705, 1707, 1709, 1711, 1713, 1713, 1713, 1713, 1713, 1715,
7444
     1717, 1717, 1717, 1719, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
7445
     1721, 1721, 1723, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725,
7446
     1725, 1725, 1725, 1725, 1725, 1725, 1725, 1727, 1727, 1727, 1727, 1727,
7447
     1727, 1729, 1731, 1731, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1735,
7448
     1737, 1739, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7449
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7450
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7451
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7452
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7453
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7454
     1741, 1741, 1741, 1741, 1741},
7455
    {1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7456
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7457
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7458
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7459
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7460
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1743,
7461
     1743, 1743, 1743, 1743, 1745, 1745, 1747, 1747, 1749, 1749, 1751, 1751,
7462
     1753, 1753, 1755, 1755, 1757, 1757, 1759, 1759, 1761, 1761, 1763, 1763,
7463
     1765, 1765, 1767, 1767, 1767, 1769, 1769, 1771, 1771, 1773, 1773, 1773,
7464
     1773, 1773, 1773, 1773, 1777, 1777, 1777, 1781, 1781, 1781, 1785, 1785,
7465
     1785, 1789, 1789, 1789, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7466
     1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7467
     1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7468
     1793, 1793, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1797,
7469
     1797, 1797, 1797, 1797, 1799, 1799, 1801, 1801, 1803, 1803, 1805, 1805,
7470
     1807, 1807, 1809, 1809, 1811, 1811, 1813, 1813, 1815, 1815, 1817, 1817,
7471
     1819, 1819, 1821, 1821, 1821, 1823, 1823, 1825, 1825, 1827, 1827, 1827,
7472
     1827, 1827, 1827, 1827, 1831, 1831, 1831, 1835, 1835, 1835, 1839, 1839,
7473
     1839, 1843, 1843, 1843, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7474
     1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7475
     1849, 1851, 1853, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855,
7476
     1855, 1855, 1857, 1857, 1857},
7477
    {1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7478
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7479
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7480
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7481
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7482
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7483
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7484
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7485
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7486
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7487
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7488
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7489
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1859, 1859,
7490
     1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1863, 1863,
7491
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7492
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7493
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7494
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7495
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7496
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7497
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7498
     1863, 1863, 1863, 1863, 1863},
7499
    {1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7500
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7501
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7502
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7503
     1863, 1863, 1865, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7504
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7505
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7506
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7507
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7508
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7509
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7510
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7511
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7512
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7513
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7514
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7515
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7516
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7517
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7518
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7519
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7520
     1867, 1867, 1867, 1867, 1867},
7521
    {1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7522
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7523
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7524
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7525
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7526
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7527
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7528
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7529
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7530
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7531
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7532
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7533
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7534
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7535
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7536
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7537
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7538
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7539
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7540
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7541
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7542
     1871, 1871, 1871, 1871, 1871},
7543
    {1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7544
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7545
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7546
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7547
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7548
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7549
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7550
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7551
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7552
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7553
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7554
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7555
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7556
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7557
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7558
     1871, 1871, 1871, 1871, 1871, 1871, 1877, 1877, 1877, 1877, 1877, 1877,
7559
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7560
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7561
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7562
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7563
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7564
     1877, 1877, 1877, 1877, 1877},
7565
    {1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7566
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7567
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7568
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7569
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7570
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7571
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7572
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7573
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7574
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7575
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7576
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7577
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7578
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7579
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7580
     1877, 1877, 1877, 1877, 1877, 1879, 1881, 1881, 1881, 1881, 1881, 1881,
7581
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7582
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7583
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7584
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7585
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7586
     1881, 1881, 1881, 1881, 1881},
7587
    {1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7588
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7589
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7590
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7591
     1881, 1881, 1881, 1881, 1881, 1881, 1883, 1883, 1883, 1883, 1883, 1883,
7592
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7593
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7594
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7595
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7596
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7597
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7598
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7599
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7600
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7601
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7602
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7603
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7604
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7605
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7606
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7607
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7608
     1883, 1883, 1883, 1883, 1883}};
7609
const char32_t composition_data[1883] = {
7610
    0,     824,   8814,  824,   8800,  824,   8815,  768,   192,   769,   193,
7611
    770,   194,   771,   195,   772,   256,   774,   258,   775,   550,   776,
7612
    196,   777,   7842,  778,   197,   780,   461,   783,   512,   785,   514,
7613
    803,   7840,  805,   7680,  808,   260,   775,   7682,  803,   7684,  817,
7614
    7686,  769,   262,   770,   264,   775,   266,   780,   268,   807,   199,
7615
    775,   7690,  780,   270,   803,   7692,  807,   7696,  813,   7698,  817,
7616
    7694,  768,   200,   769,   201,   770,   202,   771,   7868,  772,   274,
7617
    774,   276,   775,   278,   776,   203,   777,   7866,  780,   282,   783,
7618
    516,   785,   518,   803,   7864,  807,   552,   808,   280,   813,   7704,
7619
    816,   7706,  775,   7710,  769,   500,   770,   284,   772,   7712,  774,
7620
    286,   775,   288,   780,   486,   807,   290,   770,   292,   775,   7714,
7621
    776,   7718,  780,   542,   803,   7716,  807,   7720,  814,   7722,  768,
7622
    204,   769,   205,   770,   206,   771,   296,   772,   298,   774,   300,
7623
    775,   304,   776,   207,   777,   7880,  780,   463,   783,   520,   785,
7624
    522,   803,   7882,  808,   302,   816,   7724,  770,   308,   769,   7728,
7625
    780,   488,   803,   7730,  807,   310,   817,   7732,  769,   313,   780,
7626
    317,   803,   7734,  807,   315,   813,   7740,  817,   7738,  769,   7742,
7627
    775,   7744,  803,   7746,  768,   504,   769,   323,   771,   209,   775,
7628
    7748,  780,   327,   803,   7750,  807,   325,   813,   7754,  817,   7752,
7629
    768,   210,   769,   211,   770,   212,   771,   213,   772,   332,   774,
7630
    334,   775,   558,   776,   214,   777,   7886,  779,   336,   780,   465,
7631
    783,   524,   785,   526,   795,   416,   803,   7884,  808,   490,   769,
7632
    7764,  775,   7766,  769,   340,   775,   7768,  780,   344,   783,   528,
7633
    785,   530,   803,   7770,  807,   342,   817,   7774,  769,   346,   770,
7634
    348,   775,   7776,  780,   352,   803,   7778,  806,   536,   807,   350,
7635
    775,   7786,  780,   356,   803,   7788,  806,   538,   807,   354,   813,
7636
    7792,  817,   7790,  768,   217,   769,   218,   770,   219,   771,   360,
7637
    772,   362,   774,   364,   776,   220,   777,   7910,  778,   366,   779,
7638
    368,   780,   467,   783,   532,   785,   534,   795,   431,   803,   7908,
7639
    804,   7794,  808,   370,   813,   7798,  816,   7796,  771,   7804,  803,
7640
    7806,  768,   7808,  769,   7810,  770,   372,   775,   7814,  776,   7812,
7641
    803,   7816,  775,   7818,  776,   7820,  768,   7922,  769,   221,   770,
7642
    374,   771,   7928,  772,   562,   775,   7822,  776,   376,   777,   7926,
7643
    803,   7924,  769,   377,   770,   7824,  775,   379,   780,   381,   803,
7644
    7826,  817,   7828,  768,   224,   769,   225,   770,   226,   771,   227,
7645
    772,   257,   774,   259,   775,   551,   776,   228,   777,   7843,  778,
7646
    229,   780,   462,   783,   513,   785,   515,   803,   7841,  805,   7681,
7647
    808,   261,   775,   7683,  803,   7685,  817,   7687,  769,   263,   770,
7648
    265,   775,   267,   780,   269,   807,   231,   775,   7691,  780,   271,
7649
    803,   7693,  807,   7697,  813,   7699,  817,   7695,  768,   232,   769,
7650
    233,   770,   234,   771,   7869,  772,   275,   774,   277,   775,   279,
7651
    776,   235,   777,   7867,  780,   283,   783,   517,   785,   519,   803,
7652
    7865,  807,   553,   808,   281,   813,   7705,  816,   7707,  775,   7711,
7653
    769,   501,   770,   285,   772,   7713,  774,   287,   775,   289,   780,
7654
    487,   807,   291,   770,   293,   775,   7715,  776,   7719,  780,   543,
7655
    803,   7717,  807,   7721,  814,   7723,  817,   7830,  768,   236,   769,
7656
    237,   770,   238,   771,   297,   772,   299,   774,   301,   776,   239,
7657
    777,   7881,  780,   464,   783,   521,   785,   523,   803,   7883,  808,
7658
    303,   816,   7725,  770,   309,   780,   496,   769,   7729,  780,   489,
7659
    803,   7731,  807,   311,   817,   7733,  769,   314,   780,   318,   803,
7660
    7735,  807,   316,   813,   7741,  817,   7739,  769,   7743,  775,   7745,
7661
    803,   7747,  768,   505,   769,   324,   771,   241,   775,   7749,  780,
7662
    328,   803,   7751,  807,   326,   813,   7755,  817,   7753,  768,   242,
7663
    769,   243,   770,   244,   771,   245,   772,   333,   774,   335,   775,
7664
    559,   776,   246,   777,   7887,  779,   337,   780,   466,   783,   525,
7665
    785,   527,   795,   417,   803,   7885,  808,   491,   769,   7765,  775,
7666
    7767,  769,   341,   775,   7769,  780,   345,   783,   529,   785,   531,
7667
    803,   7771,  807,   343,   817,   7775,  769,   347,   770,   349,   775,
7668
    7777,  780,   353,   803,   7779,  806,   537,   807,   351,   775,   7787,
7669
    776,   7831,  780,   357,   803,   7789,  806,   539,   807,   355,   813,
7670
    7793,  817,   7791,  768,   249,   769,   250,   770,   251,   771,   361,
7671
    772,   363,   774,   365,   776,   252,   777,   7911,  778,   367,   779,
7672
    369,   780,   468,   783,   533,   785,   535,   795,   432,   803,   7909,
7673
    804,   7795,  808,   371,   813,   7799,  816,   7797,  771,   7805,  803,
7674
    7807,  768,   7809,  769,   7811,  770,   373,   775,   7815,  776,   7813,
7675
    778,   7832,  803,   7817,  775,   7819,  776,   7821,  768,   7923,  769,
7676
    253,   770,   375,   771,   7929,  772,   563,   775,   7823,  776,   255,
7677
    777,   7927,  778,   7833,  803,   7925,  769,   378,   770,   7825,  775,
7678
    380,   780,   382,   803,   7827,  817,   7829,  768,   8173,  769,   901,
7679
    834,   8129,  768,   7846,  769,   7844,  771,   7850,  777,   7848,  772,
7680
    478,   769,   506,   769,   508,   772,   482,   769,   7688,  768,   7872,
7681
    769,   7870,  771,   7876,  777,   7874,  769,   7726,  768,   7890,  769,
7682
    7888,  771,   7894,  777,   7892,  769,   7756,  772,   556,   776,   7758,
7683
    772,   554,   769,   510,   768,   475,   769,   471,   772,   469,   780,
7684
    473,   768,   7847,  769,   7845,  771,   7851,  777,   7849,  772,   479,
7685
    769,   507,   769,   509,   772,   483,   769,   7689,  768,   7873,  769,
7686
    7871,  771,   7877,  777,   7875,  769,   7727,  768,   7891,  769,   7889,
7687
    771,   7895,  777,   7893,  769,   7757,  772,   557,   776,   7759,  772,
7688
    555,   769,   511,   768,   476,   769,   472,   772,   470,   780,   474,
7689
    768,   7856,  769,   7854,  771,   7860,  777,   7858,  768,   7857,  769,
7690
    7855,  771,   7861,  777,   7859,  768,   7700,  769,   7702,  768,   7701,
7691
    769,   7703,  768,   7760,  769,   7762,  768,   7761,  769,   7763,  775,
7692
    7780,  775,   7781,  775,   7782,  775,   7783,  769,   7800,  769,   7801,
7693
    776,   7802,  776,   7803,  775,   7835,  768,   7900,  769,   7898,  771,
7694
    7904,  777,   7902,  803,   7906,  768,   7901,  769,   7899,  771,   7905,
7695
    777,   7903,  803,   7907,  768,   7914,  769,   7912,  771,   7918,  777,
7696
    7916,  803,   7920,  768,   7915,  769,   7913,  771,   7919,  777,   7917,
7697
    803,   7921,  780,   494,   772,   492,   772,   493,   772,   480,   772,
7698
    481,   774,   7708,  774,   7709,  772,   560,   772,   561,   780,   495,
7699
    768,   8122,  769,   902,   772,   8121,  774,   8120,  787,   7944,  788,
7700
    7945,  837,   8124,  768,   8136,  769,   904,   787,   7960,  788,   7961,
7701
    768,   8138,  769,   905,   787,   7976,  788,   7977,  837,   8140,  768,
7702
    8154,  769,   906,   772,   8153,  774,   8152,  776,   938,   787,   7992,
7703
    788,   7993,  768,   8184,  769,   908,   787,   8008,  788,   8009,  788,
7704
    8172,  768,   8170,  769,   910,   772,   8169,  774,   8168,  776,   939,
7705
    788,   8025,  768,   8186,  769,   911,   787,   8040,  788,   8041,  837,
7706
    8188,  837,   8116,  837,   8132,  768,   8048,  769,   940,   772,   8113,
7707
    774,   8112,  787,   7936,  788,   7937,  834,   8118,  837,   8115,  768,
7708
    8050,  769,   941,   787,   7952,  788,   7953,  768,   8052,  769,   942,
7709
    787,   7968,  788,   7969,  834,   8134,  837,   8131,  768,   8054,  769,
7710
    943,   772,   8145,  774,   8144,  776,   970,   787,   7984,  788,   7985,
7711
    834,   8150,  768,   8056,  769,   972,   787,   8000,  788,   8001,  787,
7712
    8164,  788,   8165,  768,   8058,  769,   973,   772,   8161,  774,   8160,
7713
    776,   971,   787,   8016,  788,   8017,  834,   8166,  768,   8060,  769,
7714
    974,   787,   8032,  788,   8033,  834,   8182,  837,   8179,  768,   8146,
7715
    769,   912,   834,   8151,  768,   8162,  769,   944,   834,   8167,  837,
7716
    8180,  769,   979,   776,   980,   776,   1031,  774,   1232,  776,   1234,
7717
    769,   1027,  768,   1024,  774,   1238,  776,   1025,  774,   1217,  776,
7718
    1244,  776,   1246,  768,   1037,  772,   1250,  774,   1049,  776,   1252,
7719
    769,   1036,  776,   1254,  772,   1262,  774,   1038,  776,   1264,  779,
7720
    1266,  776,   1268,  776,   1272,  776,   1260,  774,   1233,  776,   1235,
7721
    769,   1107,  768,   1104,  774,   1239,  776,   1105,  774,   1218,  776,
7722
    1245,  776,   1247,  768,   1117,  772,   1251,  774,   1081,  776,   1253,
7723
    769,   1116,  776,   1255,  772,   1263,  774,   1118,  776,   1265,  779,
7724
    1267,  776,   1269,  776,   1273,  776,   1261,  776,   1111,  783,   1142,
7725
    783,   1143,  776,   1242,  776,   1243,  776,   1258,  776,   1259,  1619,
7726
    1570,  1620,  1571,  1621,  1573,  1620,  1572,  1620,  1574,  1620,  1730,
7727
    1620,  1747,  1620,  1728,  2364,  2345,  2364,  2353,  2364,  2356,  2494,
7728
    2507,  2519,  2508,  2878,  2891,  2902,  2888,  2903,  2892,  3031,  2964,
7729
    3006,  3018,  3031,  3020,  3006,  3019,  3158,  3144,  3285,  3264,  3266,
7730
    3274,  3285,  3271,  3286,  3272,  3285,  3275,  3390,  3402,  3415,  3404,
7731
    3390,  3403,  3530,  3546,  3535,  3548,  3551,  3550,  3530,  3549,  4142,
7732
    4134,  6965,  6918,  6965,  6920,  6965,  6922,  6965,  6924,  6965,  6926,
7733
    6965,  6930,  6965,  6971,  6965,  6973,  6965,  6976,  6965,  6977,  6965,
7734
    6979,  772,   7736,  772,   7737,  772,   7772,  772,   7773,  775,   7784,
7735
    775,   7785,  770,   7852,  774,   7862,  770,   7853,  774,   7863,  770,
7736
    7878,  770,   7879,  770,   7896,  770,   7897,  768,   7938,  769,   7940,
7737
    834,   7942,  837,   8064,  768,   7939,  769,   7941,  834,   7943,  837,
7738
    8065,  837,   8066,  837,   8067,  837,   8068,  837,   8069,  837,   8070,
7739
    837,   8071,  768,   7946,  769,   7948,  834,   7950,  837,   8072,  768,
7740
    7947,  769,   7949,  834,   7951,  837,   8073,  837,   8074,  837,   8075,
7741
    837,   8076,  837,   8077,  837,   8078,  837,   8079,  768,   7954,  769,
7742
    7956,  768,   7955,  769,   7957,  768,   7962,  769,   7964,  768,   7963,
7743
    769,   7965,  768,   7970,  769,   7972,  834,   7974,  837,   8080,  768,
7744
    7971,  769,   7973,  834,   7975,  837,   8081,  837,   8082,  837,   8083,
7745
    837,   8084,  837,   8085,  837,   8086,  837,   8087,  768,   7978,  769,
7746
    7980,  834,   7982,  837,   8088,  768,   7979,  769,   7981,  834,   7983,
7747
    837,   8089,  837,   8090,  837,   8091,  837,   8092,  837,   8093,  837,
7748
    8094,  837,   8095,  768,   7986,  769,   7988,  834,   7990,  768,   7987,
7749
    769,   7989,  834,   7991,  768,   7994,  769,   7996,  834,   7998,  768,
7750
    7995,  769,   7997,  834,   7999,  768,   8002,  769,   8004,  768,   8003,
7751
    769,   8005,  768,   8010,  769,   8012,  768,   8011,  769,   8013,  768,
7752
    8018,  769,   8020,  834,   8022,  768,   8019,  769,   8021,  834,   8023,
7753
    768,   8027,  769,   8029,  834,   8031,  768,   8034,  769,   8036,  834,
7754
    8038,  837,   8096,  768,   8035,  769,   8037,  834,   8039,  837,   8097,
7755
    837,   8098,  837,   8099,  837,   8100,  837,   8101,  837,   8102,  837,
7756
    8103,  768,   8042,  769,   8044,  834,   8046,  837,   8104,  768,   8043,
7757
    769,   8045,  834,   8047,  837,   8105,  837,   8106,  837,   8107,  837,
7758
    8108,  837,   8109,  837,   8110,  837,   8111,  837,   8114,  837,   8130,
7759
    837,   8178,  837,   8119,  768,   8141,  769,   8142,  834,   8143,  837,
7760
    8135,  837,   8183,  768,   8157,  769,   8158,  834,   8159,  824,   8602,
7761
    824,   8603,  824,   8622,  824,   8653,  824,   8655,  824,   8654,  824,
7762
    8708,  824,   8713,  824,   8716,  824,   8740,  824,   8742,  824,   8769,
7763
    824,   8772,  824,   8775,  824,   8777,  824,   8813,  824,   8802,  824,
7764
    8816,  824,   8817,  824,   8820,  824,   8821,  824,   8824,  824,   8825,
7765
    824,   8832,  824,   8833,  824,   8928,  824,   8929,  824,   8836,  824,
7766
    8837,  824,   8840,  824,   8841,  824,   8930,  824,   8931,  824,   8876,
7767
    824,   8877,  824,   8878,  824,   8879,  824,   8938,  824,   8939,  824,
7768
    8940,  824,   8941,  12441, 12436, 12441, 12364, 12441, 12366, 12441, 12368,
7769
    12441, 12370, 12441, 12372, 12441, 12374, 12441, 12376, 12441, 12378, 12441,
7770
    12380, 12441, 12382, 12441, 12384, 12441, 12386, 12441, 12389, 12441, 12391,
7771
    12441, 12393, 12441, 12400, 12442, 12401, 12441, 12403, 12442, 12404, 12441,
7772
    12406, 12442, 12407, 12441, 12409, 12442, 12410, 12441, 12412, 12442, 12413,
7773
    12441, 12446, 12441, 12532, 12441, 12460, 12441, 12462, 12441, 12464, 12441,
7774
    12466, 12441, 12468, 12441, 12470, 12441, 12472, 12441, 12474, 12441, 12476,
7775
    12441, 12478, 12441, 12480, 12441, 12482, 12441, 12485, 12441, 12487, 12441,
7776
    12489, 12441, 12496, 12442, 12497, 12441, 12499, 12442, 12500, 12441, 12502,
7777
    12442, 12503, 12441, 12505, 12442, 12506, 12441, 12508, 12442, 12509, 12441,
7778
    12535, 12441, 12536, 12441, 12537, 12441, 12538, 12441, 12542, 69818, 69786,
7779
    69818, 69788, 69818, 69803, 69927, 69934, 69927, 69935, 70462, 70475, 70487,
7780
    70476, 70832, 70844, 70842, 70843, 70845, 70846, 71087, 71098, 71087, 71099,
7781
    71984, 71992};
7782
7783
}  // namespace ada::idna
7784
#endif  // ADA_IDNA_NORMALIZATION_TABLES_H
7785
/* end file src/normalization_tables.cpp */
7786
7787
namespace ada::idna {
7788
7789
// See
7790
// https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/impl_norm.h#L467
7791
constexpr char32_t hangul_sbase = 0xAC00;
7792
constexpr char32_t hangul_tbase = 0x11A7;
7793
constexpr char32_t hangul_vbase = 0x1161;
7794
constexpr char32_t hangul_lbase = 0x1100;
7795
constexpr char32_t hangul_lcount = 19;
7796
constexpr char32_t hangul_vcount = 21;
7797
constexpr char32_t hangul_tcount = 28;
7798
constexpr char32_t hangul_ncount = hangul_vcount * hangul_tcount;
7799
constexpr char32_t hangul_scount =
7800
    hangul_lcount * hangul_vcount * hangul_tcount;
7801
7802
std::pair<bool, size_t> compute_decomposition_length(
7803
12.8k
    const std::u32string_view input) noexcept {
7804
12.8k
  bool decomposition_needed{false};
7805
12.8k
  size_t additional_elements{0};
7806
491k
  for (char32_t current_character : input) {
7807
491k
    size_t decomposition_length{0};
7808
7809
491k
    if (current_character >= hangul_sbase &&
7810
26.8k
        current_character < hangul_sbase + hangul_scount) {
7811
23.7k
      decomposition_length = 2;
7812
23.7k
      if ((current_character - hangul_sbase) % hangul_tcount) {
7813
8.77k
        decomposition_length = 3;
7814
8.77k
      }
7815
468k
    } else if (current_character < 0x110000) {
7816
468k
      const uint8_t di = decomposition_index[current_character >> 8];
7817
468k
      const uint16_t* const decomposition =
7818
468k
          decomposition_block[di] + (current_character % 256);
7819
468k
      decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
7820
468k
      if ((decomposition_length > 0) && (decomposition[0] & 1)) {
7821
0
        decomposition_length = 0;
7822
0
      }
7823
468k
    }
7824
491k
    if (decomposition_length != 0) {
7825
27.9k
      decomposition_needed = true;
7826
27.9k
      additional_elements += decomposition_length - 1;
7827
27.9k
    }
7828
491k
  }
7829
12.8k
  return {decomposition_needed, additional_elements};
7830
12.8k
}
7831
7832
3.87k
void decompose(std::u32string& input, size_t additional_elements) {
7833
3.87k
  input.resize(input.size() + additional_elements);
7834
3.87k
  for (size_t descending_idx = input.size(),
7835
3.87k
              input_count = descending_idx - additional_elements;
7836
252k
       input_count--;) {
7837
248k
    if (input[input_count] >= hangul_sbase &&
7838
24.4k
        input[input_count] < hangul_sbase + hangul_scount) {
7839
      // Hangul decomposition.
7840
23.7k
      char32_t s_index = input[input_count] - hangul_sbase;
7841
23.7k
      if (s_index % hangul_tcount != 0) {
7842
8.77k
        input[--descending_idx] = hangul_tbase + s_index % hangul_tcount;
7843
8.77k
      }
7844
23.7k
      input[--descending_idx] =
7845
23.7k
          hangul_vbase + (s_index % hangul_ncount) / hangul_tcount;
7846
23.7k
      input[--descending_idx] = hangul_lbase + s_index / hangul_ncount;
7847
224k
    } else if (input[input_count] < 0x110000) {
7848
      // Check decomposition_data.
7849
224k
      const uint16_t* decomposition =
7850
224k
          decomposition_block[decomposition_index[input[input_count] >> 8]] +
7851
224k
          (input[input_count] % 256);
7852
224k
      uint16_t decomposition_length =
7853
224k
          (decomposition[1] >> 2) - (decomposition[0] >> 2);
7854
224k
      if (decomposition_length > 0 && (decomposition[0] & 1)) {
7855
0
        decomposition_length = 0;
7856
0
      }
7857
224k
      if (decomposition_length > 0) {
7858
        // Non-recursive decomposition.
7859
13.8k
        while (decomposition_length-- > 0) {
7860
9.68k
          input[--descending_idx] = decomposition_data[(decomposition[0] >> 2) +
7861
9.68k
                                                       decomposition_length];
7862
9.68k
        }
7863
220k
      } else {
7864
        // No decomposition.
7865
220k
        input[--descending_idx] = input[input_count];
7866
220k
      }
7867
224k
    } else {
7868
      // Non-Unicode character.
7869
0
      input[--descending_idx] = input[input_count];
7870
0
    }
7871
248k
  }
7872
3.87k
}
7873
7874
992k
uint8_t get_ccc(char32_t c) noexcept {
7875
992k
  return c < 0x110000 ? canonical_combining_class_block
7876
992k
                            [canonical_combining_class_index[c >> 8]][c % 256]
7877
992k
                      : 0;
7878
992k
}
7879
7880
12.8k
void sort_marks(std::u32string& input) {
7881
530k
  for (size_t idx = 1; idx < input.size(); idx++) {
7882
517k
    uint8_t ccc = get_ccc(input[idx]);
7883
517k
    if (ccc == 0) {
7884
504k
      continue;
7885
504k
    }  // Skip non-combining characters.
7886
12.7k
    auto current_character = input[idx];
7887
12.7k
    size_t back_idx = idx;
7888
14.8k
    while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) {
7889
2.14k
      input[back_idx] = input[back_idx - 1];
7890
2.14k
      back_idx--;
7891
2.14k
    }
7892
12.7k
    input[back_idx] = current_character;
7893
12.7k
  }
7894
12.8k
}
7895
7896
12.8k
void decompose_nfc(std::u32string& input) {
7897
  /**
7898
   * Decompose the domain_name string to Unicode Normalization Form C.
7899
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepDecompose
7900
   */
7901
12.8k
  auto [decomposition_needed, additional_elements] =
7902
12.8k
      compute_decomposition_length(input);
7903
12.8k
  if (decomposition_needed) {
7904
3.87k
    decompose(input, additional_elements);
7905
3.87k
  }
7906
12.8k
  sort_marks(input);
7907
12.8k
}
7908
7909
12.8k
void compose(std::u32string& input) {
7910
  /**
7911
   * Compose the domain_name string to Unicode Normalization Form C.
7912
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepCompose
7913
   */
7914
12.8k
  size_t input_count{0};
7915
12.8k
  size_t composition_count{0};
7916
497k
  for (; input_count < input.size(); input_count++, composition_count++) {
7917
484k
    input[composition_count] = input[input_count];
7918
484k
    if (input[input_count] >= hangul_lbase &&
7919
232k
        input[input_count] < hangul_lbase + hangul_lcount) {
7920
25.2k
      if (input_count + 1 < input.size() &&
7921
24.9k
          input[input_count + 1] >= hangul_vbase &&
7922
24.0k
          input[input_count + 1] < hangul_vbase + hangul_vcount) {
7923
23.7k
        input[composition_count] =
7924
23.7k
            hangul_sbase +
7925
23.7k
            ((input[input_count] - hangul_lbase) * hangul_vcount +
7926
23.7k
             input[input_count + 1] - hangul_vbase) *
7927
23.7k
                hangul_tcount;
7928
23.7k
        input_count++;
7929
23.7k
        if (input_count + 1 < input.size() &&
7930
23.5k
            input[input_count + 1] > hangul_tbase &&
7931
9.07k
            input[input_count + 1] < hangul_tbase + hangul_tcount) {
7932
8.77k
          input[composition_count] += input[++input_count] - hangul_tbase;
7933
8.77k
        }
7934
23.7k
      }
7935
459k
    } else if (input[input_count] >= hangul_sbase &&
7936
2.05k
               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
459k
    } else if (input[input_count] < 0x110000) {
7944
459k
      const uint16_t* composition =
7945
459k
          &composition_block[composition_index[input[input_count] >> 8]]
7946
459k
                            [input[input_count] % 256];
7947
459k
      size_t initial_composition_count = composition_count;
7948
472k
      for (int32_t previous_ccc = -1; input_count + 1 < input.size();
7949
460k
           input_count++) {
7950
460k
        uint8_t ccc = get_ccc(input[input_count + 1]);
7951
7952
460k
        if (composition[1] != composition[0] && previous_ccc < ccc) {
7953
          // Try finding a composition.
7954
96.9k
          int left = composition[0];
7955
96.9k
          int right = composition[1];
7956
233k
          while (left + 2 < right) {
7957
            // mean without overflow
7958
136k
            int middle = left + (((right - left) >> 1) & ~1);
7959
136k
            if (composition_data[middle] <= input[input_count + 1]) {
7960
11.1k
              left = middle;
7961
11.1k
            }
7962
136k
            if (composition_data[middle] >= input[input_count + 1]) {
7963
128k
              right = middle;
7964
128k
            }
7965
136k
          }
7966
96.9k
          if (composition_data[left] == input[input_count + 1]) {
7967
5.52k
            input[initial_composition_count] = composition_data[left + 1];
7968
5.52k
            composition =
7969
5.52k
                &composition_block
7970
5.52k
                    [composition_index[composition_data[left + 1] >> 8]]
7971
5.52k
                    [composition_data[left + 1] % 256];
7972
5.52k
            continue;
7973
5.52k
          }
7974
96.9k
        }
7975
7976
454k
        if (ccc == 0) {
7977
447k
          break;
7978
447k
        }  // Not a combining character.
7979
7.23k
        previous_ccc = ccc;
7980
7.23k
        input[++composition_count] = input[input_count + 1];
7981
7.23k
      }
7982
459k
    }
7983
484k
  }
7984
7985
12.8k
  if (composition_count < input_count) {
7986
3.89k
    input.resize(composition_count);
7987
3.89k
  }
7988
12.8k
}
7989
7990
12.8k
void normalize(std::u32string& input) {
7991
  /**
7992
   * Normalize the domain_name string to Unicode Normalization Form C.
7993
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepNormalize
7994
   */
7995
12.8k
  decompose_nfc(input);
7996
12.8k
  compose(input);
7997
12.8k
}
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
55.8k
static constexpr int32_t char_to_digit_value(char value) {
8016
55.8k
  if (value >= 'a' && value <= 'z') return value - 'a';
8017
7.03k
  if (value >= '0' && value <= '9') return value - '0' + 26;
8018
62
  return -1;
8019
7.03k
}
8020
8021
734k
static constexpr char digit_to_char(int32_t digit) {
8022
734k
  return digit < 26 ? char(digit + 97) : char(digit + 22);
8023
734k
}
8024
8025
333k
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
8026
333k
  if (firsttime) {
8027
38.9k
    d = d / damp;
8028
294k
  } else {
8029
294k
    d = d / 2;
8030
294k
  }
8031
333k
  d += d / n;
8032
333k
  int32_t k = 0;
8033
485k
  while (d > ((base - tmin) * tmax) / 2) {
8034
152k
    d /= base - tmin;
8035
152k
    k += base;
8036
152k
  }
8037
333k
  return k + (((base - tmin + 1) * d) / (d + skew));
8038
333k
}
8039
8040
5.82k
bool punycode_to_utf32(std::string_view input, std::u32string &out) {
8041
  // See https://github.com/whatwg/url/issues/803
8042
5.82k
  if (input.starts_with("xn--")) {
8043
6
    return false;
8044
6
  }
8045
5.81k
  int32_t written_out{0};
8046
5.81k
  out.reserve(out.size() + input.size());
8047
5.81k
  uint32_t n = initial_n;
8048
5.81k
  int32_t i = 0;
8049
5.81k
  int32_t bias = initial_bias;
8050
  // grab ascii content
8051
5.81k
  size_t end_of_ascii = input.find_last_of('-');
8052
5.81k
  if (end_of_ascii != std::string_view::npos) {
8053
5.26k
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8054
5.26k
      if (c >= 0x80) {
8055
0
        return false;
8056
0
      }
8057
5.26k
      out.push_back(c);
8058
5.26k
      written_out++;
8059
5.26k
    }
8060
756
    input.remove_prefix(end_of_ascii + 1);
8061
756
  }
8062
46.9k
  while (!input.empty()) {
8063
41.4k
    int32_t oldi = i;
8064
41.4k
    int32_t w = 1;
8065
56.0k
    for (int32_t k = base;; k += base) {
8066
56.0k
      if (input.empty()) {
8067
182
        return false;
8068
182
      }
8069
55.8k
      uint8_t code_point = input.front();
8070
55.8k
      input.remove_prefix(1);
8071
55.8k
      int32_t digit = char_to_digit_value(code_point);
8072
55.8k
      if (digit < 0) {
8073
62
        return false;
8074
62
      }
8075
55.8k
      if (digit > (0x7fffffff - i) / w) {
8076
18
        return false;
8077
18
      }
8078
55.8k
      i = i + digit * w;
8079
55.8k
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8080
55.8k
      if (digit < t) {
8081
41.1k
        break;
8082
41.1k
      }
8083
14.6k
      if (w > 0x7fffffff / (base - t)) {
8084
0
        return false;
8085
0
      }
8086
14.6k
      w = w * (base - t);
8087
14.6k
    }
8088
41.1k
    bias = adapt(i - oldi, written_out + 1, oldi == 0);
8089
41.1k
    if (i / (written_out + 1) > int32_t(0x7fffffff - n)) {
8090
100
      return false;
8091
100
    }
8092
41.0k
    n = n + i / (written_out + 1);
8093
41.0k
    i = i % (written_out + 1);
8094
41.0k
    if (n < 0x80) {
8095
0
      return false;
8096
0
    }
8097
41.0k
    out.insert(out.begin() + i, n);
8098
41.0k
    written_out++;
8099
41.0k
    ++i;
8100
41.0k
  }
8101
5.45k
  return true;
8102
5.81k
}
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
33.5k
bool utf32_to_punycode(std::u32string_view input, std::string &out) {
8166
33.5k
  out.reserve(input.size() + out.size());
8167
33.5k
  uint32_t n = initial_n;
8168
33.5k
  int32_t d = 0;
8169
33.5k
  int32_t bias = initial_bias;
8170
33.5k
  size_t h = 0;
8171
  // first push the ascii content
8172
336k
  for (uint32_t c : input) {
8173
336k
    if (c < 0x80) {
8174
44.5k
      ++h;
8175
44.5k
      out.push_back(char(c));
8176
44.5k
    }
8177
336k
    if (c > 0x10ffff || (c >= 0xd800 && c < 0xe000)) {
8178
0
      return false;
8179
0
    }
8180
336k
  }
8181
33.5k
  size_t b = h;
8182
33.5k
  if (b > 0) {
8183
12.0k
    out.push_back('-');
8184
12.0k
  }
8185
223k
  while (h < input.size()) {
8186
189k
    uint32_t m = 0x10FFFF;
8187
3.40M
    for (auto code_point : input) {
8188
3.40M
      if (code_point >= n && code_point < m) m = code_point;
8189
3.40M
    }
8190
8191
189k
    if ((m - n) > (0x7fffffff - d) / (h + 1)) {
8192
0
      return false;
8193
0
    }
8194
189k
    d = d + int32_t((m - n) * (h + 1));
8195
189k
    n = m;
8196
3.40M
    for (auto c : input) {
8197
3.40M
      if (c < n) {
8198
1.79M
        if (d == 0x7fffffff) {
8199
0
          return false;
8200
0
        }
8201
1.79M
        ++d;
8202
1.79M
      }
8203
3.40M
      if (c == n) {
8204
291k
        int32_t q = d;
8205
734k
        for (int32_t k = base;; k += base) {
8206
734k
          int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8207
8208
734k
          if (q < t) {
8209
291k
            break;
8210
291k
          }
8211
442k
          out.push_back(digit_to_char(t + ((q - t) % (base - t))));
8212
442k
          q = (q - t) / (base - t);
8213
442k
        }
8214
291k
        out.push_back(digit_to_char(q));
8215
291k
        bias = adapt(d, int32_t(h + 1), h == b);
8216
291k
        d = 0;
8217
291k
        ++h;
8218
291k
      }
8219
3.40M
    }
8220
189k
    ++d;
8221
189k
    ++n;
8222
189k
  }
8223
33.5k
  return true;
8224
33.5k
}
8225
8226
}  // namespace ada::idna
8227
/* end file src/punycode.cpp */
8228
/* begin file src/validity.cpp */
8229
#include <algorithm>
8230
#include <string_view>
8231
8232
namespace ada::idna {
8233
8234
enum direction : uint8_t {
8235
  NONE,
8236
  BN,
8237
  CS,
8238
  ES,
8239
  ON,
8240
  EN,
8241
  L,
8242
  R,
8243
  NSM,
8244
  AL,
8245
  AN,
8246
  ET,
8247
  WS,
8248
  RLO,
8249
  LRO,
8250
  PDF,
8251
  RLE,
8252
  RLI,
8253
  FSI,
8254
  PDI,
8255
  LRI,
8256
  B,
8257
  S,
8258
  LRE
8259
};
8260
8261
struct directions {
8262
  uint32_t start_code;
8263
  uint32_t final_code;
8264
  direction direct;
8265
};
8266
8267
static directions dir_table[] = {
8268
    {0x0, 0x8, direction::BN},          {0x9, 0x9, direction::S},
8269
    {0xa, 0xa, direction::B},           {0xb, 0xb, direction::S},
8270
    {0xc, 0xc, direction::WS},          {0xd, 0xd, direction::B},
8271
    {0xe, 0x1b, direction::BN},         {0x1c, 0x1e, direction::B},
8272
    {0x1f, 0x1f, direction::S},         {0x20, 0x20, direction::WS},
8273
    {0x21, 0x22, direction::ON},        {0x23, 0x25, direction::ET},
8274
    {0x26, 0x2a, direction::ON},        {0x2b, 0x2b, direction::ES},
8275
    {0x2c, 0x2c, direction::CS},        {0x2d, 0x2d, direction::ES},
8276
    {0x2e, 0x2f, direction::CS},        {0x30, 0x39, direction::EN},
8277
    {0x3a, 0x3a, direction::CS},        {0x3b, 0x40, direction::ON},
8278
    {0x41, 0x5a, direction::L},         {0x5b, 0x60, direction::ON},
8279
    {0x61, 0x7a, direction::L},         {0x7b, 0x7e, direction::ON},
8280
    {0x7f, 0x84, direction::BN},        {0x85, 0x85, direction::B},
8281
    {0x86, 0x9f, direction::BN},        {0xa0, 0xa0, direction::CS},
8282
    {0xa1, 0xa1, direction::ON},        {0xa2, 0xa5, direction::ET},
8283
    {0xa6, 0xa9, direction::ON},        {0xaa, 0xaa, direction::L},
8284
    {0xab, 0xac, direction::ON},        {0xad, 0xad, direction::BN},
8285
    {0xae, 0xaf, direction::ON},        {0xb0, 0xb1, direction::ET},
8286
    {0xb2, 0xb3, direction::EN},        {0xb4, 0xb4, direction::ON},
8287
    {0xb5, 0xb5, direction::L},         {0xb6, 0xb8, direction::ON},
8288
    {0xb9, 0xb9, direction::EN},        {0xba, 0xba, direction::L},
8289
    {0xbb, 0xbf, direction::ON},        {0xc0, 0xd6, direction::L},
8290
    {0xd7, 0xd7, direction::ON},        {0xd8, 0xf6, direction::L},
8291
    {0xf7, 0xf7, direction::ON},        {0xf8, 0x2b8, direction::L},
8292
    {0x2b9, 0x2ba, direction::ON},      {0x2bb, 0x2c1, direction::L},
8293
    {0x2c2, 0x2cf, direction::ON},      {0x2d0, 0x2d1, direction::L},
8294
    {0x2d2, 0x2df, direction::ON},      {0x2e0, 0x2e4, direction::L},
8295
    {0x2e5, 0x2ed, direction::ON},      {0x2ee, 0x2ee, direction::L},
8296
    {0x2ef, 0x2ff, direction::ON},      {0x300, 0x36f, direction::NSM},
8297
    {0x370, 0x373, direction::L},       {0x374, 0x375, direction::ON},
8298
    {0x376, 0x377, direction::L},       {0x37a, 0x37d, direction::L},
8299
    {0x37e, 0x37e, direction::ON},      {0x37f, 0x37f, direction::L},
8300
    {0x384, 0x385, direction::ON},      {0x386, 0x386, direction::L},
8301
    {0x387, 0x387, direction::ON},      {0x388, 0x38a, direction::L},
8302
    {0x38c, 0x38c, direction::L},       {0x38e, 0x3a1, direction::L},
8303
    {0x3a3, 0x3f5, direction::L},       {0x3f6, 0x3f6, direction::ON},
8304
    {0x3f7, 0x482, direction::L},       {0x483, 0x489, direction::NSM},
8305
    {0x48a, 0x52f, direction::L},       {0x531, 0x556, direction::L},
8306
    {0x559, 0x589, direction::L},       {0x58a, 0x58a, direction::ON},
8307
    {0x58d, 0x58e, direction::ON},      {0x58f, 0x58f, direction::ET},
8308
    {0x591, 0x5bd, direction::NSM},     {0x5be, 0x5be, direction::R},
8309
    {0x5bf, 0x5bf, direction::NSM},     {0x5c0, 0x5c0, direction::R},
8310
    {0x5c1, 0x5c2, direction::NSM},     {0x5c3, 0x5c3, direction::R},
8311
    {0x5c4, 0x5c5, direction::NSM},     {0x5c6, 0x5c6, direction::R},
8312
    {0x5c7, 0x5c7, direction::NSM},     {0x5d0, 0x5ea, direction::R},
8313
    {0x5ef, 0x5f4, direction::R},       {0x600, 0x605, direction::AN},
8314
    {0x606, 0x607, direction::ON},      {0x608, 0x608, direction::AL},
8315
    {0x609, 0x60a, direction::ET},      {0x60b, 0x60b, direction::AL},
8316
    {0x60c, 0x60c, direction::CS},      {0x60d, 0x60d, direction::AL},
8317
    {0x60e, 0x60f, direction::ON},      {0x610, 0x61a, direction::NSM},
8318
    {0x61b, 0x61c, direction::AL},      {0x61e, 0x64a, direction::AL},
8319
    {0x64b, 0x65f, direction::NSM},     {0x660, 0x669, direction::AN},
8320
    {0x66a, 0x66a, direction::ET},      {0x66b, 0x66c, direction::AN},
8321
    {0x66d, 0x66f, direction::AL},      {0x670, 0x670, direction::NSM},
8322
    {0x671, 0x6d5, direction::AL},      {0x6d6, 0x6dc, direction::NSM},
8323
    {0x6dd, 0x6dd, direction::AN},      {0x6de, 0x6de, direction::ON},
8324
    {0x6df, 0x6e4, direction::NSM},     {0x6e5, 0x6e6, direction::AL},
8325
    {0x6e7, 0x6e8, direction::NSM},     {0x6e9, 0x6e9, direction::ON},
8326
    {0x6ea, 0x6ed, direction::NSM},     {0x6ee, 0x6ef, direction::AL},
8327
    {0x6f0, 0x6f9, direction::EN},      {0x6fa, 0x70d, direction::AL},
8328
    {0x70f, 0x710, direction::AL},      {0x711, 0x711, direction::NSM},
8329
    {0x712, 0x72f, direction::AL},      {0x730, 0x74a, direction::NSM},
8330
    {0x74d, 0x7a5, direction::AL},      {0x7a6, 0x7b0, direction::NSM},
8331
    {0x7b1, 0x7b1, direction::AL},      {0x7c0, 0x7ea, direction::R},
8332
    {0x7eb, 0x7f3, direction::NSM},     {0x7f4, 0x7f5, direction::R},
8333
    {0x7f6, 0x7f9, direction::ON},      {0x7fa, 0x7fa, direction::R},
8334
    {0x7fd, 0x7fd, direction::NSM},     {0x7fe, 0x815, direction::R},
8335
    {0x816, 0x819, direction::NSM},     {0x81a, 0x81a, direction::R},
8336
    {0x81b, 0x823, direction::NSM},     {0x824, 0x824, direction::R},
8337
    {0x825, 0x827, direction::NSM},     {0x828, 0x828, direction::R},
8338
    {0x829, 0x82d, direction::NSM},     {0x830, 0x83e, direction::R},
8339
    {0x840, 0x858, direction::R},       {0x859, 0x85b, direction::NSM},
8340
    {0x85e, 0x85e, direction::R},       {0x860, 0x86a, direction::AL},
8341
    {0x8a0, 0x8b4, direction::AL},      {0x8b6, 0x8c7, direction::AL},
8342
    {0x8d3, 0x8e1, direction::NSM},     {0x8e2, 0x8e2, direction::AN},
8343
    {0x8e3, 0x902, direction::NSM},     {0x903, 0x939, direction::L},
8344
    {0x93a, 0x93a, direction::NSM},     {0x93b, 0x93b, direction::L},
8345
    {0x93c, 0x93c, direction::NSM},     {0x93d, 0x940, direction::L},
8346
    {0x941, 0x948, direction::NSM},     {0x949, 0x94c, direction::L},
8347
    {0x94d, 0x94d, direction::NSM},     {0x94e, 0x950, direction::L},
8348
    {0x951, 0x957, direction::NSM},     {0x958, 0x961, direction::L},
8349
    {0x962, 0x963, direction::NSM},     {0x964, 0x980, direction::L},
8350
    {0x981, 0x981, direction::NSM},     {0x982, 0x983, direction::L},
8351
    {0x985, 0x98c, direction::L},       {0x98f, 0x990, direction::L},
8352
    {0x993, 0x9a8, direction::L},       {0x9aa, 0x9b0, direction::L},
8353
    {0x9b2, 0x9b2, direction::L},       {0x9b6, 0x9b9, direction::L},
8354
    {0x9bc, 0x9bc, direction::NSM},     {0x9bd, 0x9c0, direction::L},
8355
    {0x9c1, 0x9c4, direction::NSM},     {0x9c7, 0x9c8, direction::L},
8356
    {0x9cb, 0x9cc, direction::L},       {0x9cd, 0x9cd, direction::NSM},
8357
    {0x9ce, 0x9ce, direction::L},       {0x9d7, 0x9d7, direction::L},
8358
    {0x9dc, 0x9dd, direction::L},       {0x9df, 0x9e1, direction::L},
8359
    {0x9e2, 0x9e3, direction::NSM},     {0x9e6, 0x9f1, direction::L},
8360
    {0x9f2, 0x9f3, direction::ET},      {0x9f4, 0x9fa, direction::L},
8361
    {0x9fb, 0x9fb, direction::ET},      {0x9fc, 0x9fd, direction::L},
8362
    {0x9fe, 0x9fe, direction::NSM},     {0xa01, 0xa02, direction::NSM},
8363
    {0xa03, 0xa03, direction::L},       {0xa05, 0xa0a, direction::L},
8364
    {0xa0f, 0xa10, direction::L},       {0xa13, 0xa28, direction::L},
8365
    {0xa2a, 0xa30, direction::L},       {0xa32, 0xa33, direction::L},
8366
    {0xa35, 0xa36, direction::L},       {0xa38, 0xa39, direction::L},
8367
    {0xa3c, 0xa3c, direction::NSM},     {0xa3e, 0xa40, direction::L},
8368
    {0xa41, 0xa42, direction::NSM},     {0xa47, 0xa48, direction::NSM},
8369
    {0xa4b, 0xa4d, direction::NSM},     {0xa51, 0xa51, direction::NSM},
8370
    {0xa59, 0xa5c, direction::L},       {0xa5e, 0xa5e, direction::L},
8371
    {0xa66, 0xa6f, direction::L},       {0xa70, 0xa71, direction::NSM},
8372
    {0xa72, 0xa74, direction::L},       {0xa75, 0xa75, direction::NSM},
8373
    {0xa76, 0xa76, direction::L},       {0xa81, 0xa82, direction::NSM},
8374
    {0xa83, 0xa83, direction::L},       {0xa85, 0xa8d, direction::L},
8375
    {0xa8f, 0xa91, direction::L},       {0xa93, 0xaa8, direction::L},
8376
    {0xaaa, 0xab0, direction::L},       {0xab2, 0xab3, direction::L},
8377
    {0xab5, 0xab9, direction::L},       {0xabc, 0xabc, direction::NSM},
8378
    {0xabd, 0xac0, direction::L},       {0xac1, 0xac5, direction::NSM},
8379
    {0xac7, 0xac8, direction::NSM},     {0xac9, 0xac9, direction::L},
8380
    {0xacb, 0xacc, direction::L},       {0xacd, 0xacd, direction::NSM},
8381
    {0xad0, 0xad0, direction::L},       {0xae0, 0xae1, direction::L},
8382
    {0xae2, 0xae3, direction::NSM},     {0xae6, 0xaf0, direction::L},
8383
    {0xaf1, 0xaf1, direction::ET},      {0xaf9, 0xaf9, direction::L},
8384
    {0xafa, 0xaff, direction::NSM},     {0xb01, 0xb01, direction::NSM},
8385
    {0xb02, 0xb03, direction::L},       {0xb05, 0xb0c, direction::L},
8386
    {0xb0f, 0xb10, direction::L},       {0xb13, 0xb28, direction::L},
8387
    {0xb2a, 0xb30, direction::L},       {0xb32, 0xb33, direction::L},
8388
    {0xb35, 0xb39, direction::L},       {0xb3c, 0xb3c, direction::NSM},
8389
    {0xb3d, 0xb3e, direction::L},       {0xb3f, 0xb3f, direction::NSM},
8390
    {0xb40, 0xb40, direction::L},       {0xb41, 0xb44, direction::NSM},
8391
    {0xb47, 0xb48, direction::L},       {0xb4b, 0xb4c, direction::L},
8392
    {0xb4d, 0xb4d, direction::NSM},     {0xb55, 0xb56, direction::NSM},
8393
    {0xb57, 0xb57, direction::L},       {0xb5c, 0xb5d, direction::L},
8394
    {0xb5f, 0xb61, direction::L},       {0xb62, 0xb63, direction::NSM},
8395
    {0xb66, 0xb77, direction::L},       {0xb82, 0xb82, direction::NSM},
8396
    {0xb83, 0xb83, direction::L},       {0xb85, 0xb8a, direction::L},
8397
    {0xb8e, 0xb90, direction::L},       {0xb92, 0xb95, direction::L},
8398
    {0xb99, 0xb9a, direction::L},       {0xb9c, 0xb9c, direction::L},
8399
    {0xb9e, 0xb9f, direction::L},       {0xba3, 0xba4, direction::L},
8400
    {0xba8, 0xbaa, direction::L},       {0xbae, 0xbb9, direction::L},
8401
    {0xbbe, 0xbbf, direction::L},       {0xbc0, 0xbc0, direction::NSM},
8402
    {0xbc1, 0xbc2, direction::L},       {0xbc6, 0xbc8, direction::L},
8403
    {0xbca, 0xbcc, direction::L},       {0xbcd, 0xbcd, direction::NSM},
8404
    {0xbd0, 0xbd0, direction::L},       {0xbd7, 0xbd7, direction::L},
8405
    {0xbe6, 0xbf2, direction::L},       {0xbf3, 0xbf8, direction::ON},
8406
    {0xbf9, 0xbf9, direction::ET},      {0xbfa, 0xbfa, direction::ON},
8407
    {0xc00, 0xc00, direction::NSM},     {0xc01, 0xc03, direction::L},
8408
    {0xc04, 0xc04, direction::NSM},     {0xc05, 0xc0c, direction::L},
8409
    {0xc0e, 0xc10, direction::L},       {0xc12, 0xc28, direction::L},
8410
    {0xc2a, 0xc39, direction::L},       {0xc3d, 0xc3d, direction::L},
8411
    {0xc3e, 0xc40, direction::NSM},     {0xc41, 0xc44, direction::L},
8412
    {0xc46, 0xc48, direction::NSM},     {0xc4a, 0xc4d, direction::NSM},
8413
    {0xc55, 0xc56, direction::NSM},     {0xc58, 0xc5a, direction::L},
8414
    {0xc60, 0xc61, direction::L},       {0xc62, 0xc63, direction::NSM},
8415
    {0xc66, 0xc6f, direction::L},       {0xc77, 0xc77, direction::L},
8416
    {0xc78, 0xc7e, direction::ON},      {0xc7f, 0xc80, direction::L},
8417
    {0xc81, 0xc81, direction::NSM},     {0xc82, 0xc8c, direction::L},
8418
    {0xc8e, 0xc90, direction::L},       {0xc92, 0xca8, direction::L},
8419
    {0xcaa, 0xcb3, direction::L},       {0xcb5, 0xcb9, direction::L},
8420
    {0xcbc, 0xcbc, direction::NSM},     {0xcbd, 0xcc4, direction::L},
8421
    {0xcc6, 0xcc8, direction::L},       {0xcca, 0xccb, direction::L},
8422
    {0xccc, 0xccd, direction::NSM},     {0xcd5, 0xcd6, direction::L},
8423
    {0xcde, 0xcde, direction::L},       {0xce0, 0xce1, direction::L},
8424
    {0xce2, 0xce3, direction::NSM},     {0xce6, 0xcef, direction::L},
8425
    {0xcf1, 0xcf2, direction::L},       {0xd00, 0xd01, direction::NSM},
8426
    {0xd02, 0xd0c, direction::L},       {0xd0e, 0xd10, direction::L},
8427
    {0xd12, 0xd3a, direction::L},       {0xd3b, 0xd3c, direction::NSM},
8428
    {0xd3d, 0xd40, direction::L},       {0xd41, 0xd44, direction::NSM},
8429
    {0xd46, 0xd48, direction::L},       {0xd4a, 0xd4c, direction::L},
8430
    {0xd4d, 0xd4d, direction::NSM},     {0xd4e, 0xd4f, direction::L},
8431
    {0xd54, 0xd61, direction::L},       {0xd62, 0xd63, direction::NSM},
8432
    {0xd66, 0xd7f, direction::L},       {0xd81, 0xd81, direction::NSM},
8433
    {0xd82, 0xd83, direction::L},       {0xd85, 0xd96, direction::L},
8434
    {0xd9a, 0xdb1, direction::L},       {0xdb3, 0xdbb, direction::L},
8435
    {0xdbd, 0xdbd, direction::L},       {0xdc0, 0xdc6, direction::L},
8436
    {0xdca, 0xdca, direction::NSM},     {0xdcf, 0xdd1, direction::L},
8437
    {0xdd2, 0xdd4, direction::NSM},     {0xdd6, 0xdd6, direction::NSM},
8438
    {0xdd8, 0xddf, direction::L},       {0xde6, 0xdef, direction::L},
8439
    {0xdf2, 0xdf4, direction::L},       {0xe01, 0xe30, direction::L},
8440
    {0xe31, 0xe31, direction::NSM},     {0xe32, 0xe33, direction::L},
8441
    {0xe34, 0xe3a, direction::NSM},     {0xe3f, 0xe3f, direction::ET},
8442
    {0xe40, 0xe46, direction::L},       {0xe47, 0xe4e, direction::NSM},
8443
    {0xe4f, 0xe5b, direction::L},       {0xe81, 0xe82, direction::L},
8444
    {0xe84, 0xe84, direction::L},       {0xe86, 0xe8a, direction::L},
8445
    {0xe8c, 0xea3, direction::L},       {0xea5, 0xea5, direction::L},
8446
    {0xea7, 0xeb0, direction::L},       {0xeb1, 0xeb1, direction::NSM},
8447
    {0xeb2, 0xeb3, direction::L},       {0xeb4, 0xebc, direction::NSM},
8448
    {0xebd, 0xebd, direction::L},       {0xec0, 0xec4, direction::L},
8449
    {0xec6, 0xec6, direction::L},       {0xec8, 0xecd, direction::NSM},
8450
    {0xed0, 0xed9, direction::L},       {0xedc, 0xedf, direction::L},
8451
    {0xf00, 0xf17, direction::L},       {0xf18, 0xf19, direction::NSM},
8452
    {0xf1a, 0xf34, direction::L},       {0xf35, 0xf35, direction::NSM},
8453
    {0xf36, 0xf36, direction::L},       {0xf37, 0xf37, direction::NSM},
8454
    {0xf38, 0xf38, direction::L},       {0xf39, 0xf39, direction::NSM},
8455
    {0xf3a, 0xf3d, direction::ON},      {0xf3e, 0xf47, direction::L},
8456
    {0xf49, 0xf6c, direction::L},       {0xf71, 0xf7e, direction::NSM},
8457
    {0xf7f, 0xf7f, direction::L},       {0xf80, 0xf84, direction::NSM},
8458
    {0xf85, 0xf85, direction::L},       {0xf86, 0xf87, direction::NSM},
8459
    {0xf88, 0xf8c, direction::L},       {0xf8d, 0xf97, direction::NSM},
8460
    {0xf99, 0xfbc, direction::NSM},     {0xfbe, 0xfc5, direction::L},
8461
    {0xfc6, 0xfc6, direction::NSM},     {0xfc7, 0xfcc, direction::L},
8462
    {0xfce, 0xfda, direction::L},       {0x1000, 0x102c, direction::L},
8463
    {0x102d, 0x1030, direction::NSM},   {0x1031, 0x1031, direction::L},
8464
    {0x1032, 0x1037, direction::NSM},   {0x1038, 0x1038, direction::L},
8465
    {0x1039, 0x103a, direction::NSM},   {0x103b, 0x103c, direction::L},
8466
    {0x103d, 0x103e, direction::NSM},   {0x103f, 0x1057, direction::L},
8467
    {0x1058, 0x1059, direction::NSM},   {0x105a, 0x105d, direction::L},
8468
    {0x105e, 0x1060, direction::NSM},   {0x1061, 0x1070, direction::L},
8469
    {0x1071, 0x1074, direction::NSM},   {0x1075, 0x1081, direction::L},
8470
    {0x1082, 0x1082, direction::NSM},   {0x1083, 0x1084, direction::L},
8471
    {0x1085, 0x1086, direction::NSM},   {0x1087, 0x108c, direction::L},
8472
    {0x108d, 0x108d, direction::NSM},   {0x108e, 0x109c, direction::L},
8473
    {0x109d, 0x109d, direction::NSM},   {0x109e, 0x10c5, direction::L},
8474
    {0x10c7, 0x10c7, direction::L},     {0x10cd, 0x10cd, direction::L},
8475
    {0x10d0, 0x1248, direction::L},     {0x124a, 0x124d, direction::L},
8476
    {0x1250, 0x1256, direction::L},     {0x1258, 0x1258, direction::L},
8477
    {0x125a, 0x125d, direction::L},     {0x1260, 0x1288, direction::L},
8478
    {0x128a, 0x128d, direction::L},     {0x1290, 0x12b0, direction::L},
8479
    {0x12b2, 0x12b5, direction::L},     {0x12b8, 0x12be, direction::L},
8480
    {0x12c0, 0x12c0, direction::L},     {0x12c2, 0x12c5, direction::L},
8481
    {0x12c8, 0x12d6, direction::L},     {0x12d8, 0x1310, direction::L},
8482
    {0x1312, 0x1315, direction::L},     {0x1318, 0x135a, direction::L},
8483
    {0x135d, 0x135f, direction::NSM},   {0x1360, 0x137c, direction::L},
8484
    {0x1380, 0x138f, direction::L},     {0x1390, 0x1399, direction::ON},
8485
    {0x13a0, 0x13f5, direction::L},     {0x13f8, 0x13fd, direction::L},
8486
    {0x1400, 0x1400, direction::ON},    {0x1401, 0x167f, direction::L},
8487
    {0x1680, 0x1680, direction::WS},    {0x1681, 0x169a, direction::L},
8488
    {0x169b, 0x169c, direction::ON},    {0x16a0, 0x16f8, direction::L},
8489
    {0x1700, 0x170c, direction::L},     {0x170e, 0x1711, direction::L},
8490
    {0x1712, 0x1714, direction::NSM},   {0x1720, 0x1731, direction::L},
8491
    {0x1732, 0x1734, direction::NSM},   {0x1735, 0x1736, direction::L},
8492
    {0x1740, 0x1751, direction::L},     {0x1752, 0x1753, direction::NSM},
8493
    {0x1760, 0x176c, direction::L},     {0x176e, 0x1770, direction::L},
8494
    {0x1772, 0x1773, direction::NSM},   {0x1780, 0x17b3, direction::L},
8495
    {0x17b4, 0x17b5, direction::NSM},   {0x17b6, 0x17b6, direction::L},
8496
    {0x17b7, 0x17bd, direction::NSM},   {0x17be, 0x17c5, direction::L},
8497
    {0x17c6, 0x17c6, direction::NSM},   {0x17c7, 0x17c8, direction::L},
8498
    {0x17c9, 0x17d3, direction::NSM},   {0x17d4, 0x17da, direction::L},
8499
    {0x17db, 0x17db, direction::ET},    {0x17dc, 0x17dc, direction::L},
8500
    {0x17dd, 0x17dd, direction::NSM},   {0x17e0, 0x17e9, direction::L},
8501
    {0x17f0, 0x17f9, direction::ON},    {0x1800, 0x180a, direction::ON},
8502
    {0x180b, 0x180d, direction::NSM},   {0x180e, 0x180e, direction::BN},
8503
    {0x1810, 0x1819, direction::L},     {0x1820, 0x1878, direction::L},
8504
    {0x1880, 0x1884, direction::L},     {0x1885, 0x1886, direction::NSM},
8505
    {0x1887, 0x18a8, direction::L},     {0x18a9, 0x18a9, direction::NSM},
8506
    {0x18aa, 0x18aa, direction::L},     {0x18b0, 0x18f5, direction::L},
8507
    {0x1900, 0x191e, direction::L},     {0x1920, 0x1922, direction::NSM},
8508
    {0x1923, 0x1926, direction::L},     {0x1927, 0x1928, direction::NSM},
8509
    {0x1929, 0x192b, direction::L},     {0x1930, 0x1931, direction::L},
8510
    {0x1932, 0x1932, direction::NSM},   {0x1933, 0x1938, direction::L},
8511
    {0x1939, 0x193b, direction::NSM},   {0x1940, 0x1940, direction::ON},
8512
    {0x1944, 0x1945, direction::ON},    {0x1946, 0x196d, direction::L},
8513
    {0x1970, 0x1974, direction::L},     {0x1980, 0x19ab, direction::L},
8514
    {0x19b0, 0x19c9, direction::L},     {0x19d0, 0x19da, direction::L},
8515
    {0x19de, 0x19ff, direction::ON},    {0x1a00, 0x1a16, direction::L},
8516
    {0x1a17, 0x1a18, direction::NSM},   {0x1a19, 0x1a1a, direction::L},
8517
    {0x1a1b, 0x1a1b, direction::NSM},   {0x1a1e, 0x1a55, direction::L},
8518
    {0x1a56, 0x1a56, direction::NSM},   {0x1a57, 0x1a57, direction::L},
8519
    {0x1a58, 0x1a5e, direction::NSM},   {0x1a60, 0x1a60, direction::NSM},
8520
    {0x1a61, 0x1a61, direction::L},     {0x1a62, 0x1a62, direction::NSM},
8521
    {0x1a63, 0x1a64, direction::L},     {0x1a65, 0x1a6c, direction::NSM},
8522
    {0x1a6d, 0x1a72, direction::L},     {0x1a73, 0x1a7c, direction::NSM},
8523
    {0x1a7f, 0x1a7f, direction::NSM},   {0x1a80, 0x1a89, direction::L},
8524
    {0x1a90, 0x1a99, direction::L},     {0x1aa0, 0x1aad, direction::L},
8525
    {0x1ab0, 0x1ac0, direction::NSM},   {0x1b00, 0x1b03, direction::NSM},
8526
    {0x1b04, 0x1b33, direction::L},     {0x1b34, 0x1b34, direction::NSM},
8527
    {0x1b35, 0x1b35, direction::L},     {0x1b36, 0x1b3a, direction::NSM},
8528
    {0x1b3b, 0x1b3b, direction::L},     {0x1b3c, 0x1b3c, direction::NSM},
8529
    {0x1b3d, 0x1b41, direction::L},     {0x1b42, 0x1b42, direction::NSM},
8530
    {0x1b43, 0x1b4b, direction::L},     {0x1b50, 0x1b6a, direction::L},
8531
    {0x1b6b, 0x1b73, direction::NSM},   {0x1b74, 0x1b7c, direction::L},
8532
    {0x1b80, 0x1b81, direction::NSM},   {0x1b82, 0x1ba1, direction::L},
8533
    {0x1ba2, 0x1ba5, direction::NSM},   {0x1ba6, 0x1ba7, direction::L},
8534
    {0x1ba8, 0x1ba9, direction::NSM},   {0x1baa, 0x1baa, direction::L},
8535
    {0x1bab, 0x1bad, direction::NSM},   {0x1bae, 0x1be5, direction::L},
8536
    {0x1be6, 0x1be6, direction::NSM},   {0x1be7, 0x1be7, direction::L},
8537
    {0x1be8, 0x1be9, direction::NSM},   {0x1bea, 0x1bec, direction::L},
8538
    {0x1bed, 0x1bed, direction::NSM},   {0x1bee, 0x1bee, direction::L},
8539
    {0x1bef, 0x1bf1, direction::NSM},   {0x1bf2, 0x1bf3, direction::L},
8540
    {0x1bfc, 0x1c2b, direction::L},     {0x1c2c, 0x1c33, direction::NSM},
8541
    {0x1c34, 0x1c35, direction::L},     {0x1c36, 0x1c37, direction::NSM},
8542
    {0x1c3b, 0x1c49, direction::L},     {0x1c4d, 0x1c88, direction::L},
8543
    {0x1c90, 0x1cba, direction::L},     {0x1cbd, 0x1cc7, direction::L},
8544
    {0x1cd0, 0x1cd2, direction::NSM},   {0x1cd3, 0x1cd3, direction::L},
8545
    {0x1cd4, 0x1ce0, direction::NSM},   {0x1ce1, 0x1ce1, direction::L},
8546
    {0x1ce2, 0x1ce8, direction::NSM},   {0x1ce9, 0x1cec, direction::L},
8547
    {0x1ced, 0x1ced, direction::NSM},   {0x1cee, 0x1cf3, direction::L},
8548
    {0x1cf4, 0x1cf4, direction::NSM},   {0x1cf5, 0x1cf7, direction::L},
8549
    {0x1cf8, 0x1cf9, direction::NSM},   {0x1cfa, 0x1cfa, direction::L},
8550
    {0x1d00, 0x1dbf, direction::L},     {0x1dc0, 0x1df9, direction::NSM},
8551
    {0x1dfb, 0x1dff, direction::NSM},   {0x1e00, 0x1f15, direction::L},
8552
    {0x1f18, 0x1f1d, direction::L},     {0x1f20, 0x1f45, direction::L},
8553
    {0x1f48, 0x1f4d, direction::L},     {0x1f50, 0x1f57, direction::L},
8554
    {0x1f59, 0x1f59, direction::L},     {0x1f5b, 0x1f5b, direction::L},
8555
    {0x1f5d, 0x1f5d, direction::L},     {0x1f5f, 0x1f7d, direction::L},
8556
    {0x1f80, 0x1fb4, direction::L},     {0x1fb6, 0x1fbc, direction::L},
8557
    {0x1fbd, 0x1fbd, direction::ON},    {0x1fbe, 0x1fbe, direction::L},
8558
    {0x1fbf, 0x1fc1, direction::ON},    {0x1fc2, 0x1fc4, direction::L},
8559
    {0x1fc6, 0x1fcc, direction::L},     {0x1fcd, 0x1fcf, direction::ON},
8560
    {0x1fd0, 0x1fd3, direction::L},     {0x1fd6, 0x1fdb, direction::L},
8561
    {0x1fdd, 0x1fdf, direction::ON},    {0x1fe0, 0x1fec, direction::L},
8562
    {0x1fed, 0x1fef, direction::ON},    {0x1ff2, 0x1ff4, direction::L},
8563
    {0x1ff6, 0x1ffc, direction::L},     {0x1ffd, 0x1ffe, direction::ON},
8564
    {0x2000, 0x200a, direction::WS},    {0x200b, 0x200d, direction::BN},
8565
    {0x200e, 0x200e, direction::L},     {0x200f, 0x200f, direction::R},
8566
    {0x2010, 0x2027, direction::ON},    {0x2028, 0x2028, direction::WS},
8567
    {0x2029, 0x2029, direction::B},     {0x202a, 0x202a, direction::LRE},
8568
    {0x202b, 0x202b, direction::RLE},   {0x202c, 0x202c, direction::PDF},
8569
    {0x202d, 0x202d, direction::LRO},   {0x202e, 0x202e, direction::RLO},
8570
    {0x202f, 0x202f, direction::CS},    {0x2030, 0x2034, direction::ET},
8571
    {0x2035, 0x2043, direction::ON},    {0x2044, 0x2044, direction::CS},
8572
    {0x2045, 0x205e, direction::ON},    {0x205f, 0x205f, direction::WS},
8573
    {0x2060, 0x2064, direction::BN},    {0x2066, 0x2066, direction::LRI},
8574
    {0x2067, 0x2067, direction::RLI},   {0x2068, 0x2068, direction::FSI},
8575
    {0x2069, 0x2069, direction::PDI},   {0x206a, 0x206f, direction::BN},
8576
    {0x2070, 0x2070, direction::EN},    {0x2071, 0x2071, direction::L},
8577
    {0x2074, 0x2079, direction::EN},    {0x207a, 0x207b, direction::ES},
8578
    {0x207c, 0x207e, direction::ON},    {0x207f, 0x207f, direction::L},
8579
    {0x2080, 0x2089, direction::EN},    {0x208a, 0x208b, direction::ES},
8580
    {0x208c, 0x208e, direction::ON},    {0x2090, 0x209c, direction::L},
8581
    {0x20a0, 0x20bf, direction::ET},    {0x20d0, 0x20f0, direction::NSM},
8582
    {0x2100, 0x2101, direction::ON},    {0x2102, 0x2102, direction::L},
8583
    {0x2103, 0x2106, direction::ON},    {0x2107, 0x2107, direction::L},
8584
    {0x2108, 0x2109, direction::ON},    {0x210a, 0x2113, direction::L},
8585
    {0x2114, 0x2114, direction::ON},    {0x2115, 0x2115, direction::L},
8586
    {0x2116, 0x2118, direction::ON},    {0x2119, 0x211d, direction::L},
8587
    {0x211e, 0x2123, direction::ON},    {0x2124, 0x2124, direction::L},
8588
    {0x2125, 0x2125, direction::ON},    {0x2126, 0x2126, direction::L},
8589
    {0x2127, 0x2127, direction::ON},    {0x2128, 0x2128, direction::L},
8590
    {0x2129, 0x2129, direction::ON},    {0x212a, 0x212d, direction::L},
8591
    {0x212e, 0x212e, direction::ET},    {0x212f, 0x2139, direction::L},
8592
    {0x213a, 0x213b, direction::ON},    {0x213c, 0x213f, direction::L},
8593
    {0x2140, 0x2144, direction::ON},    {0x2145, 0x2149, direction::L},
8594
    {0x214a, 0x214d, direction::ON},    {0x214e, 0x214f, direction::L},
8595
    {0x2150, 0x215f, direction::ON},    {0x2160, 0x2188, direction::L},
8596
    {0x2189, 0x218b, direction::ON},    {0x2190, 0x2211, direction::ON},
8597
    {0x2212, 0x2212, direction::ES},    {0x2213, 0x2213, direction::ET},
8598
    {0x2214, 0x2335, direction::ON},    {0x2336, 0x237a, direction::L},
8599
    {0x237b, 0x2394, direction::ON},    {0x2395, 0x2395, direction::L},
8600
    {0x2396, 0x2426, direction::ON},    {0x2440, 0x244a, direction::ON},
8601
    {0x2460, 0x2487, direction::ON},    {0x2488, 0x249b, direction::EN},
8602
    {0x249c, 0x24e9, direction::L},     {0x24ea, 0x26ab, direction::ON},
8603
    {0x26ac, 0x26ac, direction::L},     {0x26ad, 0x27ff, direction::ON},
8604
    {0x2800, 0x28ff, direction::L},     {0x2900, 0x2b73, direction::ON},
8605
    {0x2b76, 0x2b95, direction::ON},    {0x2b97, 0x2bff, direction::ON},
8606
    {0x2c00, 0x2c2e, direction::L},     {0x2c30, 0x2c5e, direction::L},
8607
    {0x2c60, 0x2ce4, direction::L},     {0x2ce5, 0x2cea, direction::ON},
8608
    {0x2ceb, 0x2cee, direction::L},     {0x2cef, 0x2cf1, direction::NSM},
8609
    {0x2cf2, 0x2cf3, direction::L},     {0x2cf9, 0x2cff, direction::ON},
8610
    {0x2d00, 0x2d25, direction::L},     {0x2d27, 0x2d27, direction::L},
8611
    {0x2d2d, 0x2d2d, direction::L},     {0x2d30, 0x2d67, direction::L},
8612
    {0x2d6f, 0x2d70, direction::L},     {0x2d7f, 0x2d7f, direction::NSM},
8613
    {0x2d80, 0x2d96, direction::L},     {0x2da0, 0x2da6, direction::L},
8614
    {0x2da8, 0x2dae, direction::L},     {0x2db0, 0x2db6, direction::L},
8615
    {0x2db8, 0x2dbe, direction::L},     {0x2dc0, 0x2dc6, direction::L},
8616
    {0x2dc8, 0x2dce, direction::L},     {0x2dd0, 0x2dd6, direction::L},
8617
    {0x2dd8, 0x2dde, direction::L},     {0x2de0, 0x2dff, direction::NSM},
8618
    {0x2e00, 0x2e52, direction::ON},    {0x2e80, 0x2e99, direction::ON},
8619
    {0x2e9b, 0x2ef3, direction::ON},    {0x2f00, 0x2fd5, direction::ON},
8620
    {0x2ff0, 0x2ffb, direction::ON},    {0x3000, 0x3000, direction::WS},
8621
    {0x3001, 0x3004, direction::ON},    {0x3005, 0x3007, direction::L},
8622
    {0x3008, 0x3020, direction::ON},    {0x3021, 0x3029, direction::L},
8623
    {0x302a, 0x302d, direction::NSM},   {0x302e, 0x302f, direction::L},
8624
    {0x3030, 0x3030, direction::ON},    {0x3031, 0x3035, direction::L},
8625
    {0x3036, 0x3037, direction::ON},    {0x3038, 0x303c, direction::L},
8626
    {0x303d, 0x303f, direction::ON},    {0x3041, 0x3096, direction::L},
8627
    {0x3099, 0x309a, direction::NSM},   {0x309b, 0x309c, direction::ON},
8628
    {0x309d, 0x309f, direction::L},     {0x30a0, 0x30a0, direction::ON},
8629
    {0x30a1, 0x30fa, direction::L},     {0x30fb, 0x30fb, direction::ON},
8630
    {0x30fc, 0x30ff, direction::L},     {0x3105, 0x312f, direction::L},
8631
    {0x3131, 0x318e, direction::L},     {0x3190, 0x31bf, direction::L},
8632
    {0x31c0, 0x31e3, direction::ON},    {0x31f0, 0x321c, direction::L},
8633
    {0x321d, 0x321e, direction::ON},    {0x3220, 0x324f, direction::L},
8634
    {0x3250, 0x325f, direction::ON},    {0x3260, 0x327b, direction::L},
8635
    {0x327c, 0x327e, direction::ON},    {0x327f, 0x32b0, direction::L},
8636
    {0x32b1, 0x32bf, direction::ON},    {0x32c0, 0x32cb, direction::L},
8637
    {0x32cc, 0x32cf, direction::ON},    {0x32d0, 0x3376, direction::L},
8638
    {0x3377, 0x337a, direction::ON},    {0x337b, 0x33dd, direction::L},
8639
    {0x33de, 0x33df, direction::ON},    {0x33e0, 0x33fe, direction::L},
8640
    {0x33ff, 0x33ff, direction::ON},    {0x3400, 0x4dbf, direction::L},
8641
    {0x4dc0, 0x4dff, direction::ON},    {0x4e00, 0x9ffc, direction::L},
8642
    {0xa000, 0xa48c, direction::L},     {0xa490, 0xa4c6, direction::ON},
8643
    {0xa4d0, 0xa60c, direction::L},     {0xa60d, 0xa60f, direction::ON},
8644
    {0xa610, 0xa62b, direction::L},     {0xa640, 0xa66e, direction::L},
8645
    {0xa66f, 0xa672, direction::NSM},   {0xa673, 0xa673, direction::ON},
8646
    {0xa674, 0xa67d, direction::NSM},   {0xa67e, 0xa67f, direction::ON},
8647
    {0xa680, 0xa69d, direction::L},     {0xa69e, 0xa69f, direction::NSM},
8648
    {0xa6a0, 0xa6ef, direction::L},     {0xa6f0, 0xa6f1, direction::NSM},
8649
    {0xa6f2, 0xa6f7, direction::L},     {0xa700, 0xa721, direction::ON},
8650
    {0xa722, 0xa787, direction::L},     {0xa788, 0xa788, direction::ON},
8651
    {0xa789, 0xa7bf, direction::L},     {0xa7c2, 0xa7ca, direction::L},
8652
    {0xa7f5, 0xa801, direction::L},     {0xa802, 0xa802, direction::NSM},
8653
    {0xa803, 0xa805, direction::L},     {0xa806, 0xa806, direction::NSM},
8654
    {0xa807, 0xa80a, direction::L},     {0xa80b, 0xa80b, direction::NSM},
8655
    {0xa80c, 0xa824, direction::L},     {0xa825, 0xa826, direction::NSM},
8656
    {0xa827, 0xa827, direction::L},     {0xa828, 0xa82b, direction::ON},
8657
    {0xa82c, 0xa82c, direction::NSM},   {0xa830, 0xa837, direction::L},
8658
    {0xa838, 0xa839, direction::ET},    {0xa840, 0xa873, direction::L},
8659
    {0xa874, 0xa877, direction::ON},    {0xa880, 0xa8c3, direction::L},
8660
    {0xa8c4, 0xa8c5, direction::NSM},   {0xa8ce, 0xa8d9, direction::L},
8661
    {0xa8e0, 0xa8f1, direction::NSM},   {0xa8f2, 0xa8fe, direction::L},
8662
    {0xa8ff, 0xa8ff, direction::NSM},   {0xa900, 0xa925, direction::L},
8663
    {0xa926, 0xa92d, direction::NSM},   {0xa92e, 0xa946, direction::L},
8664
    {0xa947, 0xa951, direction::NSM},   {0xa952, 0xa953, direction::L},
8665
    {0xa95f, 0xa97c, direction::L},     {0xa980, 0xa982, direction::NSM},
8666
    {0xa983, 0xa9b2, direction::L},     {0xa9b3, 0xa9b3, direction::NSM},
8667
    {0xa9b4, 0xa9b5, direction::L},     {0xa9b6, 0xa9b9, direction::NSM},
8668
    {0xa9ba, 0xa9bb, direction::L},     {0xa9bc, 0xa9bd, direction::NSM},
8669
    {0xa9be, 0xa9cd, direction::L},     {0xa9cf, 0xa9d9, direction::L},
8670
    {0xa9de, 0xa9e4, direction::L},     {0xa9e5, 0xa9e5, direction::NSM},
8671
    {0xa9e6, 0xa9fe, direction::L},     {0xaa00, 0xaa28, direction::L},
8672
    {0xaa29, 0xaa2e, direction::NSM},   {0xaa2f, 0xaa30, direction::L},
8673
    {0xaa31, 0xaa32, direction::NSM},   {0xaa33, 0xaa34, direction::L},
8674
    {0xaa35, 0xaa36, direction::NSM},   {0xaa40, 0xaa42, direction::L},
8675
    {0xaa43, 0xaa43, direction::NSM},   {0xaa44, 0xaa4b, direction::L},
8676
    {0xaa4c, 0xaa4c, direction::NSM},   {0xaa4d, 0xaa4d, direction::L},
8677
    {0xaa50, 0xaa59, direction::L},     {0xaa5c, 0xaa7b, direction::L},
8678
    {0xaa7c, 0xaa7c, direction::NSM},   {0xaa7d, 0xaaaf, direction::L},
8679
    {0xaab0, 0xaab0, direction::NSM},   {0xaab1, 0xaab1, direction::L},
8680
    {0xaab2, 0xaab4, direction::NSM},   {0xaab5, 0xaab6, direction::L},
8681
    {0xaab7, 0xaab8, direction::NSM},   {0xaab9, 0xaabd, direction::L},
8682
    {0xaabe, 0xaabf, direction::NSM},   {0xaac0, 0xaac0, direction::L},
8683
    {0xaac1, 0xaac1, direction::NSM},   {0xaac2, 0xaac2, direction::L},
8684
    {0xaadb, 0xaaeb, direction::L},     {0xaaec, 0xaaed, direction::NSM},
8685
    {0xaaee, 0xaaf5, direction::L},     {0xaaf6, 0xaaf6, direction::NSM},
8686
    {0xab01, 0xab06, direction::L},     {0xab09, 0xab0e, direction::L},
8687
    {0xab11, 0xab16, direction::L},     {0xab20, 0xab26, direction::L},
8688
    {0xab28, 0xab2e, direction::L},     {0xab30, 0xab69, direction::L},
8689
    {0xab6a, 0xab6b, direction::ON},    {0xab70, 0xabe4, direction::L},
8690
    {0xabe5, 0xabe5, direction::NSM},   {0xabe6, 0xabe7, direction::L},
8691
    {0xabe8, 0xabe8, direction::NSM},   {0xabe9, 0xabec, direction::L},
8692
    {0xabed, 0xabed, direction::NSM},   {0xabf0, 0xabf9, direction::L},
8693
    {0xac00, 0xd7a3, direction::L},     {0xd7b0, 0xd7c6, direction::L},
8694
    {0xd7cb, 0xd7fb, direction::L},     {0xd800, 0xfa6d, direction::L},
8695
    {0xfa70, 0xfad9, direction::L},     {0xfb00, 0xfb06, direction::L},
8696
    {0xfb13, 0xfb17, direction::L},     {0xfb1d, 0xfb1d, direction::R},
8697
    {0xfb1e, 0xfb1e, direction::NSM},   {0xfb1f, 0xfb28, direction::R},
8698
    {0xfb29, 0xfb29, direction::ES},    {0xfb2a, 0xfb36, direction::R},
8699
    {0xfb38, 0xfb3c, direction::R},     {0xfb3e, 0xfb3e, direction::R},
8700
    {0xfb40, 0xfb41, direction::R},     {0xfb43, 0xfb44, direction::R},
8701
    {0xfb46, 0xfb4f, direction::R},     {0xfb50, 0xfbc1, direction::AL},
8702
    {0xfbd3, 0xfd3d, direction::AL},    {0xfd3e, 0xfd3f, direction::ON},
8703
    {0xfd50, 0xfd8f, direction::AL},    {0xfd92, 0xfdc7, direction::AL},
8704
    {0xfdf0, 0xfdfc, direction::AL},    {0xfdfd, 0xfdfd, direction::ON},
8705
    {0xfe00, 0xfe0f, direction::NSM},   {0xfe10, 0xfe19, direction::ON},
8706
    {0xfe20, 0xfe2f, direction::NSM},   {0xfe30, 0xfe4f, direction::ON},
8707
    {0xfe50, 0xfe50, direction::CS},    {0xfe51, 0xfe51, direction::ON},
8708
    {0xfe52, 0xfe52, direction::CS},    {0xfe54, 0xfe54, direction::ON},
8709
    {0xfe55, 0xfe55, direction::CS},    {0xfe56, 0xfe5e, direction::ON},
8710
    {0xfe5f, 0xfe5f, direction::ET},    {0xfe60, 0xfe61, direction::ON},
8711
    {0xfe62, 0xfe63, direction::ES},    {0xfe64, 0xfe66, direction::ON},
8712
    {0xfe68, 0xfe68, direction::ON},    {0xfe69, 0xfe6a, direction::ET},
8713
    {0xfe6b, 0xfe6b, direction::ON},    {0xfe70, 0xfe74, direction::AL},
8714
    {0xfe76, 0xfefc, direction::AL},    {0xfeff, 0xfeff, direction::BN},
8715
    {0xff01, 0xff02, direction::ON},    {0xff03, 0xff05, direction::ET},
8716
    {0xff06, 0xff0a, direction::ON},    {0xff0b, 0xff0b, direction::ES},
8717
    {0xff0c, 0xff0c, direction::CS},    {0xff0d, 0xff0d, direction::ES},
8718
    {0xff0e, 0xff0f, direction::CS},    {0xff10, 0xff19, direction::EN},
8719
    {0xff1a, 0xff1a, direction::CS},    {0xff1b, 0xff20, direction::ON},
8720
    {0xff21, 0xff3a, direction::L},     {0xff3b, 0xff40, direction::ON},
8721
    {0xff41, 0xff5a, direction::L},     {0xff5b, 0xff65, direction::ON},
8722
    {0xff66, 0xffbe, direction::L},     {0xffc2, 0xffc7, direction::L},
8723
    {0xffca, 0xffcf, direction::L},     {0xffd2, 0xffd7, direction::L},
8724
    {0xffda, 0xffdc, direction::L},     {0xffe0, 0xffe1, direction::ET},
8725
    {0xffe2, 0xffe4, direction::ON},    {0xffe5, 0xffe6, direction::ET},
8726
    {0xffe8, 0xffee, direction::ON},    {0xfff9, 0xfffd, direction::ON},
8727
    {0x10000, 0x1000b, direction::L},   {0x1000d, 0x10026, direction::L},
8728
    {0x10028, 0x1003a, direction::L},   {0x1003c, 0x1003d, direction::L},
8729
    {0x1003f, 0x1004d, direction::L},   {0x10050, 0x1005d, direction::L},
8730
    {0x10080, 0x100fa, direction::L},   {0x10100, 0x10100, direction::L},
8731
    {0x10101, 0x10101, direction::ON},  {0x10102, 0x10102, direction::L},
8732
    {0x10107, 0x10133, direction::L},   {0x10137, 0x1013f, direction::L},
8733
    {0x10140, 0x1018c, direction::ON},  {0x1018d, 0x1018e, direction::L},
8734
    {0x10190, 0x1019c, direction::ON},  {0x101a0, 0x101a0, direction::ON},
8735
    {0x101d0, 0x101fc, direction::L},   {0x101fd, 0x101fd, direction::NSM},
8736
    {0x10280, 0x1029c, direction::L},   {0x102a0, 0x102d0, direction::L},
8737
    {0x102e0, 0x102e0, direction::NSM}, {0x102e1, 0x102fb, direction::EN},
8738
    {0x10300, 0x10323, direction::L},   {0x1032d, 0x1034a, direction::L},
8739
    {0x10350, 0x10375, direction::L},   {0x10376, 0x1037a, direction::NSM},
8740
    {0x10380, 0x1039d, direction::L},   {0x1039f, 0x103c3, direction::L},
8741
    {0x103c8, 0x103d5, direction::L},   {0x10400, 0x1049d, direction::L},
8742
    {0x104a0, 0x104a9, direction::L},   {0x104b0, 0x104d3, direction::L},
8743
    {0x104d8, 0x104fb, direction::L},   {0x10500, 0x10527, direction::L},
8744
    {0x10530, 0x10563, direction::L},   {0x1056f, 0x1056f, direction::L},
8745
    {0x10600, 0x10736, direction::L},   {0x10740, 0x10755, direction::L},
8746
    {0x10760, 0x10767, direction::L},   {0x10800, 0x10805, direction::R},
8747
    {0x10808, 0x10808, direction::R},   {0x1080a, 0x10835, direction::R},
8748
    {0x10837, 0x10838, direction::R},   {0x1083c, 0x1083c, direction::R},
8749
    {0x1083f, 0x10855, direction::R},   {0x10857, 0x1089e, direction::R},
8750
    {0x108a7, 0x108af, direction::R},   {0x108e0, 0x108f2, direction::R},
8751
    {0x108f4, 0x108f5, direction::R},   {0x108fb, 0x1091b, direction::R},
8752
    {0x1091f, 0x1091f, direction::ON},  {0x10920, 0x10939, direction::R},
8753
    {0x1093f, 0x1093f, direction::R},   {0x10980, 0x109b7, direction::R},
8754
    {0x109bc, 0x109cf, direction::R},   {0x109d2, 0x10a00, direction::R},
8755
    {0x10a01, 0x10a03, direction::NSM}, {0x10a05, 0x10a06, direction::NSM},
8756
    {0x10a0c, 0x10a0f, direction::NSM}, {0x10a10, 0x10a13, direction::R},
8757
    {0x10a15, 0x10a17, direction::R},   {0x10a19, 0x10a35, direction::R},
8758
    {0x10a38, 0x10a3a, direction::NSM}, {0x10a3f, 0x10a3f, direction::NSM},
8759
    {0x10a40, 0x10a48, direction::R},   {0x10a50, 0x10a58, direction::R},
8760
    {0x10a60, 0x10a9f, direction::R},   {0x10ac0, 0x10ae4, direction::R},
8761
    {0x10ae5, 0x10ae6, direction::NSM}, {0x10aeb, 0x10af6, direction::R},
8762
    {0x10b00, 0x10b35, direction::R},   {0x10b39, 0x10b3f, direction::ON},
8763
    {0x10b40, 0x10b55, direction::R},   {0x10b58, 0x10b72, direction::R},
8764
    {0x10b78, 0x10b91, direction::R},   {0x10b99, 0x10b9c, direction::R},
8765
    {0x10ba9, 0x10baf, direction::R},   {0x10c00, 0x10c48, direction::R},
8766
    {0x10c80, 0x10cb2, direction::R},   {0x10cc0, 0x10cf2, direction::R},
8767
    {0x10cfa, 0x10cff, direction::R},   {0x10d00, 0x10d23, direction::AL},
8768
    {0x10d24, 0x10d27, direction::NSM}, {0x10d30, 0x10d39, direction::AN},
8769
    {0x10e60, 0x10e7e, direction::AN},  {0x10e80, 0x10ea9, direction::R},
8770
    {0x10eab, 0x10eac, direction::NSM}, {0x10ead, 0x10ead, direction::R},
8771
    {0x10eb0, 0x10eb1, direction::R},   {0x10f00, 0x10f27, direction::R},
8772
    {0x10f30, 0x10f45, direction::AL},  {0x10f46, 0x10f50, direction::NSM},
8773
    {0x10f51, 0x10f59, direction::AL},  {0x10fb0, 0x10fcb, direction::R},
8774
    {0x10fe0, 0x10ff6, direction::R},   {0x11000, 0x11000, direction::L},
8775
    {0x11001, 0x11001, direction::NSM}, {0x11002, 0x11037, direction::L},
8776
    {0x11038, 0x11046, direction::NSM}, {0x11047, 0x1104d, direction::L},
8777
    {0x11052, 0x11065, direction::ON},  {0x11066, 0x1106f, direction::L},
8778
    {0x1107f, 0x11081, direction::NSM}, {0x11082, 0x110b2, direction::L},
8779
    {0x110b3, 0x110b6, direction::NSM}, {0x110b7, 0x110b8, direction::L},
8780
    {0x110b9, 0x110ba, direction::NSM}, {0x110bb, 0x110c1, direction::L},
8781
    {0x110cd, 0x110cd, direction::L},   {0x110d0, 0x110e8, direction::L},
8782
    {0x110f0, 0x110f9, direction::L},   {0x11100, 0x11102, direction::NSM},
8783
    {0x11103, 0x11126, direction::L},   {0x11127, 0x1112b, direction::NSM},
8784
    {0x1112c, 0x1112c, direction::L},   {0x1112d, 0x11134, direction::NSM},
8785
    {0x11136, 0x11147, direction::L},   {0x11150, 0x11172, direction::L},
8786
    {0x11173, 0x11173, direction::NSM}, {0x11174, 0x11176, direction::L},
8787
    {0x11180, 0x11181, direction::NSM}, {0x11182, 0x111b5, direction::L},
8788
    {0x111b6, 0x111be, direction::NSM}, {0x111bf, 0x111c8, direction::L},
8789
    {0x111c9, 0x111cc, direction::NSM}, {0x111cd, 0x111ce, direction::L},
8790
    {0x111cf, 0x111cf, direction::NSM}, {0x111d0, 0x111df, direction::L},
8791
    {0x111e1, 0x111f4, direction::L},   {0x11200, 0x11211, direction::L},
8792
    {0x11213, 0x1122e, direction::L},   {0x1122f, 0x11231, direction::NSM},
8793
    {0x11232, 0x11233, direction::L},   {0x11234, 0x11234, direction::NSM},
8794
    {0x11235, 0x11235, direction::L},   {0x11236, 0x11237, direction::NSM},
8795
    {0x11238, 0x1123d, direction::L},   {0x1123e, 0x1123e, direction::NSM},
8796
    {0x11280, 0x11286, direction::L},   {0x11288, 0x11288, direction::L},
8797
    {0x1128a, 0x1128d, direction::L},   {0x1128f, 0x1129d, direction::L},
8798
    {0x1129f, 0x112a9, direction::L},   {0x112b0, 0x112de, direction::L},
8799
    {0x112df, 0x112df, direction::NSM}, {0x112e0, 0x112e2, direction::L},
8800
    {0x112e3, 0x112ea, direction::NSM}, {0x112f0, 0x112f9, direction::L},
8801
    {0x11300, 0x11301, direction::NSM}, {0x11302, 0x11303, direction::L},
8802
    {0x11305, 0x1130c, direction::L},   {0x1130f, 0x11310, direction::L},
8803
    {0x11313, 0x11328, direction::L},   {0x1132a, 0x11330, direction::L},
8804
    {0x11332, 0x11333, direction::L},   {0x11335, 0x11339, direction::L},
8805
    {0x1133b, 0x1133c, direction::NSM}, {0x1133d, 0x1133f, direction::L},
8806
    {0x11340, 0x11340, direction::NSM}, {0x11341, 0x11344, direction::L},
8807
    {0x11347, 0x11348, direction::L},   {0x1134b, 0x1134d, direction::L},
8808
    {0x11350, 0x11350, direction::L},   {0x11357, 0x11357, direction::L},
8809
    {0x1135d, 0x11363, direction::L},   {0x11366, 0x1136c, direction::NSM},
8810
    {0x11370, 0x11374, direction::NSM}, {0x11400, 0x11437, direction::L},
8811
    {0x11438, 0x1143f, direction::NSM}, {0x11440, 0x11441, direction::L},
8812
    {0x11442, 0x11444, direction::NSM}, {0x11445, 0x11445, direction::L},
8813
    {0x11446, 0x11446, direction::NSM}, {0x11447, 0x1145b, direction::L},
8814
    {0x1145d, 0x1145d, direction::L},   {0x1145e, 0x1145e, direction::NSM},
8815
    {0x1145f, 0x11461, direction::L},   {0x11480, 0x114b2, direction::L},
8816
    {0x114b3, 0x114b8, direction::NSM}, {0x114b9, 0x114b9, direction::L},
8817
    {0x114ba, 0x114ba, direction::NSM}, {0x114bb, 0x114be, direction::L},
8818
    {0x114bf, 0x114c0, direction::NSM}, {0x114c1, 0x114c1, direction::L},
8819
    {0x114c2, 0x114c3, direction::NSM}, {0x114c4, 0x114c7, direction::L},
8820
    {0x114d0, 0x114d9, direction::L},   {0x11580, 0x115b1, direction::L},
8821
    {0x115b2, 0x115b5, direction::NSM}, {0x115b8, 0x115bb, direction::L},
8822
    {0x115bc, 0x115bd, direction::NSM}, {0x115be, 0x115be, direction::L},
8823
    {0x115bf, 0x115c0, direction::NSM}, {0x115c1, 0x115db, direction::L},
8824
    {0x115dc, 0x115dd, direction::NSM}, {0x11600, 0x11632, direction::L},
8825
    {0x11633, 0x1163a, direction::NSM}, {0x1163b, 0x1163c, direction::L},
8826
    {0x1163d, 0x1163d, direction::NSM}, {0x1163e, 0x1163e, direction::L},
8827
    {0x1163f, 0x11640, direction::NSM}, {0x11641, 0x11644, direction::L},
8828
    {0x11650, 0x11659, direction::L},   {0x11660, 0x1166c, direction::ON},
8829
    {0x11680, 0x116aa, direction::L},   {0x116ab, 0x116ab, direction::NSM},
8830
    {0x116ac, 0x116ac, direction::L},   {0x116ad, 0x116ad, direction::NSM},
8831
    {0x116ae, 0x116af, direction::L},   {0x116b0, 0x116b5, direction::NSM},
8832
    {0x116b6, 0x116b6, direction::L},   {0x116b7, 0x116b7, direction::NSM},
8833
    {0x116b8, 0x116b8, direction::L},   {0x116c0, 0x116c9, direction::L},
8834
    {0x11700, 0x1171a, direction::L},   {0x1171d, 0x1171f, direction::NSM},
8835
    {0x11720, 0x11721, direction::L},   {0x11722, 0x11725, direction::NSM},
8836
    {0x11726, 0x11726, direction::L},   {0x11727, 0x1172b, direction::NSM},
8837
    {0x11730, 0x1173f, direction::L},   {0x11800, 0x1182e, direction::L},
8838
    {0x1182f, 0x11837, direction::NSM}, {0x11838, 0x11838, direction::L},
8839
    {0x11839, 0x1183a, direction::NSM}, {0x1183b, 0x1183b, direction::L},
8840
    {0x118a0, 0x118f2, direction::L},   {0x118ff, 0x11906, direction::L},
8841
    {0x11909, 0x11909, direction::L},   {0x1190c, 0x11913, direction::L},
8842
    {0x11915, 0x11916, direction::L},   {0x11918, 0x11935, direction::L},
8843
    {0x11937, 0x11938, direction::L},   {0x1193b, 0x1193c, direction::NSM},
8844
    {0x1193d, 0x1193d, direction::L},   {0x1193e, 0x1193e, direction::NSM},
8845
    {0x1193f, 0x11942, direction::L},   {0x11943, 0x11943, direction::NSM},
8846
    {0x11944, 0x11946, direction::L},   {0x11950, 0x11959, direction::L},
8847
    {0x119a0, 0x119a7, direction::L},   {0x119aa, 0x119d3, direction::L},
8848
    {0x119d4, 0x119d7, direction::NSM}, {0x119da, 0x119db, direction::NSM},
8849
    {0x119dc, 0x119df, direction::L},   {0x119e0, 0x119e0, direction::NSM},
8850
    {0x119e1, 0x119e4, direction::L},   {0x11a00, 0x11a00, direction::L},
8851
    {0x11a01, 0x11a06, direction::NSM}, {0x11a07, 0x11a08, direction::L},
8852
    {0x11a09, 0x11a0a, direction::NSM}, {0x11a0b, 0x11a32, direction::L},
8853
    {0x11a33, 0x11a38, direction::NSM}, {0x11a39, 0x11a3a, direction::L},
8854
    {0x11a3b, 0x11a3e, direction::NSM}, {0x11a3f, 0x11a46, direction::L},
8855
    {0x11a47, 0x11a47, direction::NSM}, {0x11a50, 0x11a50, direction::L},
8856
    {0x11a51, 0x11a56, direction::NSM}, {0x11a57, 0x11a58, direction::L},
8857
    {0x11a59, 0x11a5b, direction::NSM}, {0x11a5c, 0x11a89, direction::L},
8858
    {0x11a8a, 0x11a96, direction::NSM}, {0x11a97, 0x11a97, direction::L},
8859
    {0x11a98, 0x11a99, direction::NSM}, {0x11a9a, 0x11aa2, direction::L},
8860
    {0x11ac0, 0x11af8, direction::L},   {0x11c00, 0x11c08, direction::L},
8861
    {0x11c0a, 0x11c2f, direction::L},   {0x11c30, 0x11c36, direction::NSM},
8862
    {0x11c38, 0x11c3d, direction::NSM}, {0x11c3e, 0x11c45, direction::L},
8863
    {0x11c50, 0x11c6c, direction::L},   {0x11c70, 0x11c8f, direction::L},
8864
    {0x11c92, 0x11ca7, direction::NSM}, {0x11ca9, 0x11ca9, direction::L},
8865
    {0x11caa, 0x11cb0, direction::NSM}, {0x11cb1, 0x11cb1, direction::L},
8866
    {0x11cb2, 0x11cb3, direction::NSM}, {0x11cb4, 0x11cb4, direction::L},
8867
    {0x11cb5, 0x11cb6, direction::NSM}, {0x11d00, 0x11d06, direction::L},
8868
    {0x11d08, 0x11d09, direction::L},   {0x11d0b, 0x11d30, direction::L},
8869
    {0x11d31, 0x11d36, direction::NSM}, {0x11d3a, 0x11d3a, direction::NSM},
8870
    {0x11d3c, 0x11d3d, direction::NSM}, {0x11d3f, 0x11d45, direction::NSM},
8871
    {0x11d46, 0x11d46, direction::L},   {0x11d47, 0x11d47, direction::NSM},
8872
    {0x11d50, 0x11d59, direction::L},   {0x11d60, 0x11d65, direction::L},
8873
    {0x11d67, 0x11d68, direction::L},   {0x11d6a, 0x11d8e, direction::L},
8874
    {0x11d90, 0x11d91, direction::NSM}, {0x11d93, 0x11d94, direction::L},
8875
    {0x11d95, 0x11d95, direction::NSM}, {0x11d96, 0x11d96, direction::L},
8876
    {0x11d97, 0x11d97, direction::NSM}, {0x11d98, 0x11d98, direction::L},
8877
    {0x11da0, 0x11da9, direction::L},   {0x11ee0, 0x11ef2, direction::L},
8878
    {0x11ef3, 0x11ef4, direction::NSM}, {0x11ef5, 0x11ef8, direction::L},
8879
    {0x11fb0, 0x11fb0, direction::L},   {0x11fc0, 0x11fd4, direction::L},
8880
    {0x11fd5, 0x11fdc, direction::ON},  {0x11fdd, 0x11fe0, direction::ET},
8881
    {0x11fe1, 0x11ff1, direction::ON},  {0x11fff, 0x12399, direction::L},
8882
    {0x12400, 0x1246e, direction::L},   {0x12470, 0x12474, direction::L},
8883
    {0x12480, 0x12543, direction::L},   {0x13000, 0x1342e, direction::L},
8884
    {0x13430, 0x13438, direction::L},   {0x14400, 0x14646, direction::L},
8885
    {0x16800, 0x16a38, direction::L},   {0x16a40, 0x16a5e, direction::L},
8886
    {0x16a60, 0x16a69, direction::L},   {0x16a6e, 0x16a6f, direction::L},
8887
    {0x16ad0, 0x16aed, direction::L},   {0x16af0, 0x16af4, direction::NSM},
8888
    {0x16af5, 0x16af5, direction::L},   {0x16b00, 0x16b2f, direction::L},
8889
    {0x16b30, 0x16b36, direction::NSM}, {0x16b37, 0x16b45, direction::L},
8890
    {0x16b50, 0x16b59, direction::L},   {0x16b5b, 0x16b61, direction::L},
8891
    {0x16b63, 0x16b77, direction::L},   {0x16b7d, 0x16b8f, direction::L},
8892
    {0x16e40, 0x16e9a, direction::L},   {0x16f00, 0x16f4a, direction::L},
8893
    {0x16f4f, 0x16f4f, direction::NSM}, {0x16f50, 0x16f87, direction::L},
8894
    {0x16f8f, 0x16f92, direction::NSM}, {0x16f93, 0x16f9f, direction::L},
8895
    {0x16fe0, 0x16fe1, direction::L},   {0x16fe2, 0x16fe2, direction::ON},
8896
    {0x16fe3, 0x16fe3, direction::L},   {0x16fe4, 0x16fe4, direction::NSM},
8897
    {0x16ff0, 0x16ff1, direction::L},   {0x17000, 0x187f7, direction::L},
8898
    {0x18800, 0x18cd5, direction::L},   {0x18d00, 0x18d08, direction::L},
8899
    {0x1b000, 0x1b11e, direction::L},   {0x1b150, 0x1b152, direction::L},
8900
    {0x1b164, 0x1b167, direction::L},   {0x1b170, 0x1b2fb, direction::L},
8901
    {0x1bc00, 0x1bc6a, direction::L},   {0x1bc70, 0x1bc7c, direction::L},
8902
    {0x1bc80, 0x1bc88, direction::L},   {0x1bc90, 0x1bc99, direction::L},
8903
    {0x1bc9c, 0x1bc9c, direction::L},   {0x1bc9d, 0x1bc9e, direction::NSM},
8904
    {0x1bc9f, 0x1bc9f, direction::L},   {0x1bca0, 0x1bca3, direction::BN},
8905
    {0x1d000, 0x1d0f5, direction::L},   {0x1d100, 0x1d126, direction::L},
8906
    {0x1d129, 0x1d166, direction::L},   {0x1d167, 0x1d169, direction::NSM},
8907
    {0x1d16a, 0x1d172, direction::L},   {0x1d173, 0x1d17a, direction::BN},
8908
    {0x1d17b, 0x1d182, direction::NSM}, {0x1d183, 0x1d184, direction::L},
8909
    {0x1d185, 0x1d18b, direction::NSM}, {0x1d18c, 0x1d1a9, direction::L},
8910
    {0x1d1aa, 0x1d1ad, direction::NSM}, {0x1d1ae, 0x1d1e8, direction::L},
8911
    {0x1d200, 0x1d241, direction::ON},  {0x1d242, 0x1d244, direction::NSM},
8912
    {0x1d245, 0x1d245, direction::ON},  {0x1d2e0, 0x1d2f3, direction::L},
8913
    {0x1d300, 0x1d356, direction::ON},  {0x1d360, 0x1d378, direction::L},
8914
    {0x1d400, 0x1d454, direction::L},   {0x1d456, 0x1d49c, direction::L},
8915
    {0x1d49e, 0x1d49f, direction::L},   {0x1d4a2, 0x1d4a2, direction::L},
8916
    {0x1d4a5, 0x1d4a6, direction::L},   {0x1d4a9, 0x1d4ac, direction::L},
8917
    {0x1d4ae, 0x1d4b9, direction::L},   {0x1d4bb, 0x1d4bb, direction::L},
8918
    {0x1d4bd, 0x1d4c3, direction::L},   {0x1d4c5, 0x1d505, direction::L},
8919
    {0x1d507, 0x1d50a, direction::L},   {0x1d50d, 0x1d514, direction::L},
8920
    {0x1d516, 0x1d51c, direction::L},   {0x1d51e, 0x1d539, direction::L},
8921
    {0x1d53b, 0x1d53e, direction::L},   {0x1d540, 0x1d544, direction::L},
8922
    {0x1d546, 0x1d546, direction::L},   {0x1d54a, 0x1d550, direction::L},
8923
    {0x1d552, 0x1d6a5, direction::L},   {0x1d6a8, 0x1d6da, direction::L},
8924
    {0x1d6db, 0x1d6db, direction::ON},  {0x1d6dc, 0x1d714, direction::L},
8925
    {0x1d715, 0x1d715, direction::ON},  {0x1d716, 0x1d74e, direction::L},
8926
    {0x1d74f, 0x1d74f, direction::ON},  {0x1d750, 0x1d788, direction::L},
8927
    {0x1d789, 0x1d789, direction::ON},  {0x1d78a, 0x1d7c2, direction::L},
8928
    {0x1d7c3, 0x1d7c3, direction::ON},  {0x1d7c4, 0x1d7cb, direction::L},
8929
    {0x1d7ce, 0x1d7ff, direction::EN},  {0x1d800, 0x1d9ff, direction::L},
8930
    {0x1da00, 0x1da36, direction::NSM}, {0x1da37, 0x1da3a, direction::L},
8931
    {0x1da3b, 0x1da6c, direction::NSM}, {0x1da6d, 0x1da74, direction::L},
8932
    {0x1da75, 0x1da75, direction::NSM}, {0x1da76, 0x1da83, direction::L},
8933
    {0x1da84, 0x1da84, direction::NSM}, {0x1da85, 0x1da8b, direction::L},
8934
    {0x1da9b, 0x1da9f, direction::NSM}, {0x1daa1, 0x1daaf, direction::NSM},
8935
    {0x1e000, 0x1e006, direction::NSM}, {0x1e008, 0x1e018, direction::NSM},
8936
    {0x1e01b, 0x1e021, direction::NSM}, {0x1e023, 0x1e024, direction::NSM},
8937
    {0x1e026, 0x1e02a, direction::NSM}, {0x1e100, 0x1e12c, direction::L},
8938
    {0x1e130, 0x1e136, direction::NSM}, {0x1e137, 0x1e13d, direction::L},
8939
    {0x1e140, 0x1e149, direction::L},   {0x1e14e, 0x1e14f, direction::L},
8940
    {0x1e2c0, 0x1e2eb, direction::L},   {0x1e2ec, 0x1e2ef, direction::NSM},
8941
    {0x1e2f0, 0x1e2f9, direction::L},   {0x1e2ff, 0x1e2ff, direction::ET},
8942
    {0x1e800, 0x1e8c4, direction::R},   {0x1e8c7, 0x1e8cf, direction::R},
8943
    {0x1e8d0, 0x1e8d6, direction::NSM}, {0x1e900, 0x1e943, direction::R},
8944
    {0x1e944, 0x1e94a, direction::NSM}, {0x1e94b, 0x1e94b, direction::R},
8945
    {0x1e950, 0x1e959, direction::R},   {0x1e95e, 0x1e95f, direction::R},
8946
    {0x1ec71, 0x1ecb4, direction::AL},  {0x1ed01, 0x1ed3d, direction::AL},
8947
    {0x1ee00, 0x1ee03, direction::AL},  {0x1ee05, 0x1ee1f, direction::AL},
8948
    {0x1ee21, 0x1ee22, direction::AL},  {0x1ee24, 0x1ee24, direction::AL},
8949
    {0x1ee27, 0x1ee27, direction::AL},  {0x1ee29, 0x1ee32, direction::AL},
8950
    {0x1ee34, 0x1ee37, direction::AL},  {0x1ee39, 0x1ee39, direction::AL},
8951
    {0x1ee3b, 0x1ee3b, direction::AL},  {0x1ee42, 0x1ee42, direction::AL},
8952
    {0x1ee47, 0x1ee47, direction::AL},  {0x1ee49, 0x1ee49, direction::AL},
8953
    {0x1ee4b, 0x1ee4b, direction::AL},  {0x1ee4d, 0x1ee4f, direction::AL},
8954
    {0x1ee51, 0x1ee52, direction::AL},  {0x1ee54, 0x1ee54, direction::AL},
8955
    {0x1ee57, 0x1ee57, direction::AL},  {0x1ee59, 0x1ee59, direction::AL},
8956
    {0x1ee5b, 0x1ee5b, direction::AL},  {0x1ee5d, 0x1ee5d, direction::AL},
8957
    {0x1ee5f, 0x1ee5f, direction::AL},  {0x1ee61, 0x1ee62, direction::AL},
8958
    {0x1ee64, 0x1ee64, direction::AL},  {0x1ee67, 0x1ee6a, direction::AL},
8959
    {0x1ee6c, 0x1ee72, direction::AL},  {0x1ee74, 0x1ee77, direction::AL},
8960
    {0x1ee79, 0x1ee7c, direction::AL},  {0x1ee7e, 0x1ee7e, direction::AL},
8961
    {0x1ee80, 0x1ee89, direction::AL},  {0x1ee8b, 0x1ee9b, direction::AL},
8962
    {0x1eea1, 0x1eea3, direction::AL},  {0x1eea5, 0x1eea9, direction::AL},
8963
    {0x1eeab, 0x1eebb, direction::AL},  {0x1eef0, 0x1eef1, direction::ON},
8964
    {0x1f000, 0x1f02b, direction::ON},  {0x1f030, 0x1f093, direction::ON},
8965
    {0x1f0a0, 0x1f0ae, direction::ON},  {0x1f0b1, 0x1f0bf, direction::ON},
8966
    {0x1f0c1, 0x1f0cf, direction::ON},  {0x1f0d1, 0x1f0f5, direction::ON},
8967
    {0x1f100, 0x1f10a, direction::EN},  {0x1f10b, 0x1f10f, direction::ON},
8968
    {0x1f110, 0x1f12e, direction::L},   {0x1f12f, 0x1f12f, direction::ON},
8969
    {0x1f130, 0x1f169, direction::L},   {0x1f16a, 0x1f16f, direction::ON},
8970
    {0x1f170, 0x1f1ac, direction::L},   {0x1f1ad, 0x1f1ad, direction::ON},
8971
    {0x1f1e6, 0x1f202, direction::L},   {0x1f210, 0x1f23b, direction::L},
8972
    {0x1f240, 0x1f248, direction::L},   {0x1f250, 0x1f251, direction::L},
8973
    {0x1f260, 0x1f265, direction::ON},  {0x1f300, 0x1f6d7, direction::ON},
8974
    {0x1f6e0, 0x1f6ec, direction::ON},  {0x1f6f0, 0x1f6fc, direction::ON},
8975
    {0x1f700, 0x1f773, direction::ON},  {0x1f780, 0x1f7d8, direction::ON},
8976
    {0x1f7e0, 0x1f7eb, direction::ON},  {0x1f800, 0x1f80b, direction::ON},
8977
    {0x1f810, 0x1f847, direction::ON},  {0x1f850, 0x1f859, direction::ON},
8978
    {0x1f860, 0x1f887, direction::ON},  {0x1f890, 0x1f8ad, direction::ON},
8979
    {0x1f8b0, 0x1f8b1, direction::ON},  {0x1f900, 0x1f978, direction::ON},
8980
    {0x1f97a, 0x1f9cb, direction::ON},  {0x1f9cd, 0x1fa53, direction::ON},
8981
    {0x1fa60, 0x1fa6d, direction::ON},  {0x1fa70, 0x1fa74, direction::ON},
8982
    {0x1fa78, 0x1fa7a, direction::ON},  {0x1fa80, 0x1fa86, direction::ON},
8983
    {0x1fa90, 0x1faa8, direction::ON},  {0x1fab0, 0x1fab6, direction::ON},
8984
    {0x1fac0, 0x1fac2, direction::ON},  {0x1fad0, 0x1fad6, direction::ON},
8985
    {0x1fb00, 0x1fb92, direction::ON},  {0x1fb94, 0x1fbca, direction::ON},
8986
    {0x1fbf0, 0x1fbf9, direction::EN},  {0x20000, 0x2a6dd, direction::L},
8987
    {0x2a700, 0x2b734, direction::L},   {0x2b740, 0x2b81d, direction::L},
8988
    {0x2b820, 0x2cea1, direction::L},   {0x2ceb0, 0x2ebe0, direction::L},
8989
    {0x2f800, 0x2fa1d, direction::L},   {0x30000, 0x3134a, direction::L},
8990
    {0xe0001, 0xe0001, direction::BN},  {0xe0020, 0xe007f, direction::BN},
8991
    {0xe0100, 0xe01ef, direction::NSM}, {0xf0000, 0xffffd, direction::L},
8992
    {0x100000, 0x10fffd, direction::L}};
8993
8994
// CheckJoiners and CheckBidi are true for URL specification.
8995
8996
355k
inline static direction find_direction(uint32_t code_point) noexcept {
8997
355k
  auto it = std::lower_bound(
8998
355k
      std::begin(dir_table), std::end(dir_table), code_point,
8999
3.64M
      [](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
355k
  if (it == std::end(dir_table)) {
9003
0
    return direction::NONE;
9004
0
  }
9005
  // We have that d.final_code >= c.
9006
355k
  if (code_point >= it->start_code) {
9007
354k
    return it->direct;
9008
354k
  }
9009
1.15k
  return direction::NONE;
9010
355k
}
9011
9012
inline static size_t find_last_not_of_nsm(
9013
37.0k
    const std::u32string_view label) noexcept {
9014
39.8k
  for (int i = static_cast<int>(label.size() - 1); i >= 0; i--)
9015
39.8k
    if (find_direction(label[i]) != direction::NSM) return i;
9016
9017
0
  return std::u32string_view::npos;
9018
37.0k
}
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
37.0k
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
9023
37.0k
  const size_t mask =
9024
37.0k
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
9025
9026
37.0k
  size_t directions = 0;
9027
337k
  for (size_t i = 0; i < label.size(); i++) {
9028
300k
    directions |= 1u << find_direction(label[i]);
9029
300k
  }
9030
37.0k
  return (directions & mask) != 0;
9031
37.0k
}
9032
9033
39.2k
bool is_label_valid(const std::u32string_view label) {
9034
39.2k
  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
39.2k
  constexpr static uint32_t combining[] = {
9060
39.2k
      0x300,   0x301,   0x302,   0x303,   0x304,   0x305,   0x306,   0x307,
9061
39.2k
      0x308,   0x309,   0x30a,   0x30b,   0x30c,   0x30d,   0x30e,   0x30f,
9062
39.2k
      0x310,   0x311,   0x312,   0x313,   0x314,   0x315,   0x316,   0x317,
9063
39.2k
      0x318,   0x319,   0x31a,   0x31b,   0x31c,   0x31d,   0x31e,   0x31f,
9064
39.2k
      0x320,   0x321,   0x322,   0x323,   0x324,   0x325,   0x326,   0x327,
9065
39.2k
      0x328,   0x329,   0x32a,   0x32b,   0x32c,   0x32d,   0x32e,   0x32f,
9066
39.2k
      0x330,   0x331,   0x332,   0x333,   0x334,   0x335,   0x336,   0x337,
9067
39.2k
      0x338,   0x339,   0x33a,   0x33b,   0x33c,   0x33d,   0x33e,   0x33f,
9068
39.2k
      0x340,   0x341,   0x342,   0x343,   0x344,   0x345,   0x346,   0x347,
9069
39.2k
      0x348,   0x349,   0x34a,   0x34b,   0x34c,   0x34d,   0x34e,   0x34f,
9070
39.2k
      0x350,   0x351,   0x352,   0x353,   0x354,   0x355,   0x356,   0x357,
9071
39.2k
      0x358,   0x359,   0x35a,   0x35b,   0x35c,   0x35d,   0x35e,   0x35f,
9072
39.2k
      0x360,   0x361,   0x362,   0x363,   0x364,   0x365,   0x366,   0x367,
9073
39.2k
      0x368,   0x369,   0x36a,   0x36b,   0x36c,   0x36d,   0x36e,   0x36f,
9074
39.2k
      0x483,   0x484,   0x485,   0x486,   0x487,   0x488,   0x489,   0x591,
9075
39.2k
      0x592,   0x593,   0x594,   0x595,   0x596,   0x597,   0x598,   0x599,
9076
39.2k
      0x59a,   0x59b,   0x59c,   0x59d,   0x59e,   0x59f,   0x5a0,   0x5a1,
9077
39.2k
      0x5a2,   0x5a3,   0x5a4,   0x5a5,   0x5a6,   0x5a7,   0x5a8,   0x5a9,
9078
39.2k
      0x5aa,   0x5ab,   0x5ac,   0x5ad,   0x5ae,   0x5af,   0x5b0,   0x5b1,
9079
39.2k
      0x5b2,   0x5b3,   0x5b4,   0x5b5,   0x5b6,   0x5b7,   0x5b8,   0x5b9,
9080
39.2k
      0x5ba,   0x5bb,   0x5bc,   0x5bd,   0x5bf,   0x5c1,   0x5c2,   0x5c4,
9081
39.2k
      0x5c5,   0x5c7,   0x610,   0x611,   0x612,   0x613,   0x614,   0x615,
9082
39.2k
      0x616,   0x617,   0x618,   0x619,   0x61a,   0x64b,   0x64c,   0x64d,
9083
39.2k
      0x64e,   0x64f,   0x650,   0x651,   0x652,   0x653,   0x654,   0x655,
9084
39.2k
      0x656,   0x657,   0x658,   0x659,   0x65a,   0x65b,   0x65c,   0x65d,
9085
39.2k
      0x65e,   0x65f,   0x670,   0x6d6,   0x6d7,   0x6d8,   0x6d9,   0x6da,
9086
39.2k
      0x6db,   0x6dc,   0x6df,   0x6e0,   0x6e1,   0x6e2,   0x6e3,   0x6e4,
9087
39.2k
      0x6e7,   0x6e8,   0x6ea,   0x6eb,   0x6ec,   0x6ed,   0x711,   0x730,
9088
39.2k
      0x731,   0x732,   0x733,   0x734,   0x735,   0x736,   0x737,   0x738,
9089
39.2k
      0x739,   0x73a,   0x73b,   0x73c,   0x73d,   0x73e,   0x73f,   0x740,
9090
39.2k
      0x741,   0x742,   0x743,   0x744,   0x745,   0x746,   0x747,   0x748,
9091
39.2k
      0x749,   0x74a,   0x7a6,   0x7a7,   0x7a8,   0x7a9,   0x7aa,   0x7ab,
9092
39.2k
      0x7ac,   0x7ad,   0x7ae,   0x7af,   0x7b0,   0x7eb,   0x7ec,   0x7ed,
9093
39.2k
      0x7ee,   0x7ef,   0x7f0,   0x7f1,   0x7f2,   0x7f3,   0x7fd,   0x816,
9094
39.2k
      0x817,   0x818,   0x819,   0x81b,   0x81c,   0x81d,   0x81e,   0x81f,
9095
39.2k
      0x820,   0x821,   0x822,   0x823,   0x825,   0x826,   0x827,   0x829,
9096
39.2k
      0x82a,   0x82b,   0x82c,   0x82d,   0x859,   0x85a,   0x85b,   0x8d3,
9097
39.2k
      0x8d4,   0x8d5,   0x8d6,   0x8d7,   0x8d8,   0x8d9,   0x8da,   0x8db,
9098
39.2k
      0x8dc,   0x8dd,   0x8de,   0x8df,   0x8e0,   0x8e1,   0x8e3,   0x8e4,
9099
39.2k
      0x8e5,   0x8e6,   0x8e7,   0x8e8,   0x8e9,   0x8ea,   0x8eb,   0x8ec,
9100
39.2k
      0x8ed,   0x8ee,   0x8ef,   0x8f0,   0x8f1,   0x8f2,   0x8f3,   0x8f4,
9101
39.2k
      0x8f5,   0x8f6,   0x8f7,   0x8f8,   0x8f9,   0x8fa,   0x8fb,   0x8fc,
9102
39.2k
      0x8fd,   0x8fe,   0x8ff,   0x900,   0x901,   0x902,   0x903,   0x93a,
9103
39.2k
      0x93b,   0x93c,   0x93e,   0x93f,   0x940,   0x941,   0x942,   0x943,
9104
39.2k
      0x944,   0x945,   0x946,   0x947,   0x948,   0x949,   0x94a,   0x94b,
9105
39.2k
      0x94c,   0x94d,   0x94e,   0x94f,   0x951,   0x952,   0x953,   0x954,
9106
39.2k
      0x955,   0x956,   0x957,   0x962,   0x963,   0x981,   0x982,   0x983,
9107
39.2k
      0x9bc,   0x9be,   0x9bf,   0x9c0,   0x9c1,   0x9c2,   0x9c3,   0x9c4,
9108
39.2k
      0x9c7,   0x9c8,   0x9cb,   0x9cc,   0x9cd,   0x9d7,   0x9e2,   0x9e3,
9109
39.2k
      0x9fe,   0xa01,   0xa02,   0xa03,   0xa3c,   0xa3e,   0xa3f,   0xa40,
9110
39.2k
      0xa41,   0xa42,   0xa47,   0xa48,   0xa4b,   0xa4c,   0xa4d,   0xa51,
9111
39.2k
      0xa70,   0xa71,   0xa75,   0xa81,   0xa82,   0xa83,   0xabc,   0xabe,
9112
39.2k
      0xabf,   0xac0,   0xac1,   0xac2,   0xac3,   0xac4,   0xac5,   0xac7,
9113
39.2k
      0xac8,   0xac9,   0xacb,   0xacc,   0xacd,   0xae2,   0xae3,   0xafa,
9114
39.2k
      0xafb,   0xafc,   0xafd,   0xafe,   0xaff,   0xb01,   0xb02,   0xb03,
9115
39.2k
      0xb3c,   0xb3e,   0xb3f,   0xb40,   0xb41,   0xb42,   0xb43,   0xb44,
9116
39.2k
      0xb47,   0xb48,   0xb4b,   0xb4c,   0xb4d,   0xb55,   0xb56,   0xb57,
9117
39.2k
      0xb62,   0xb63,   0xb82,   0xbbe,   0xbbf,   0xbc0,   0xbc1,   0xbc2,
9118
39.2k
      0xbc6,   0xbc7,   0xbc8,   0xbca,   0xbcb,   0xbcc,   0xbcd,   0xbd7,
9119
39.2k
      0xc00,   0xc01,   0xc02,   0xc03,   0xc04,   0xc3e,   0xc3f,   0xc40,
9120
39.2k
      0xc41,   0xc42,   0xc43,   0xc44,   0xc46,   0xc47,   0xc48,   0xc4a,
9121
39.2k
      0xc4b,   0xc4c,   0xc4d,   0xc55,   0xc56,   0xc62,   0xc63,   0xc81,
9122
39.2k
      0xc82,   0xc83,   0xcbc,   0xcbe,   0xcbf,   0xcc0,   0xcc1,   0xcc2,
9123
39.2k
      0xcc3,   0xcc4,   0xcc6,   0xcc7,   0xcc8,   0xcca,   0xccb,   0xccc,
9124
39.2k
      0xccd,   0xcd5,   0xcd6,   0xce2,   0xce3,   0xd00,   0xd01,   0xd02,
9125
39.2k
      0xd03,   0xd3b,   0xd3c,   0xd3e,   0xd3f,   0xd40,   0xd41,   0xd42,
9126
39.2k
      0xd43,   0xd44,   0xd46,   0xd47,   0xd48,   0xd4a,   0xd4b,   0xd4c,
9127
39.2k
      0xd4d,   0xd57,   0xd62,   0xd63,   0xd81,   0xd82,   0xd83,   0xdca,
9128
39.2k
      0xdcf,   0xdd0,   0xdd1,   0xdd2,   0xdd3,   0xdd4,   0xdd6,   0xdd8,
9129
39.2k
      0xdd9,   0xdda,   0xddb,   0xddc,   0xddd,   0xdde,   0xddf,   0xdf2,
9130
39.2k
      0xdf3,   0xe31,   0xe34,   0xe35,   0xe36,   0xe37,   0xe38,   0xe39,
9131
39.2k
      0xe3a,   0xe47,   0xe48,   0xe49,   0xe4a,   0xe4b,   0xe4c,   0xe4d,
9132
39.2k
      0xe4e,   0xeb1,   0xeb4,   0xeb5,   0xeb6,   0xeb7,   0xeb8,   0xeb9,
9133
39.2k
      0xeba,   0xebb,   0xebc,   0xec8,   0xec9,   0xeca,   0xecb,   0xecc,
9134
39.2k
      0xecd,   0xf18,   0xf19,   0xf35,   0xf37,   0xf39,   0xf3e,   0xf3f,
9135
39.2k
      0xf71,   0xf72,   0xf73,   0xf74,   0xf75,   0xf76,   0xf77,   0xf78,
9136
39.2k
      0xf79,   0xf7a,   0xf7b,   0xf7c,   0xf7d,   0xf7e,   0xf7f,   0xf80,
9137
39.2k
      0xf81,   0xf82,   0xf83,   0xf84,   0xf86,   0xf87,   0xf8d,   0xf8e,
9138
39.2k
      0xf8f,   0xf90,   0xf91,   0xf92,   0xf93,   0xf94,   0xf95,   0xf96,
9139
39.2k
      0xf97,   0xf99,   0xf9a,   0xf9b,   0xf9c,   0xf9d,   0xf9e,   0xf9f,
9140
39.2k
      0xfa0,   0xfa1,   0xfa2,   0xfa3,   0xfa4,   0xfa5,   0xfa6,   0xfa7,
9141
39.2k
      0xfa8,   0xfa9,   0xfaa,   0xfab,   0xfac,   0xfad,   0xfae,   0xfaf,
9142
39.2k
      0xfb0,   0xfb1,   0xfb2,   0xfb3,   0xfb4,   0xfb5,   0xfb6,   0xfb7,
9143
39.2k
      0xfb8,   0xfb9,   0xfba,   0xfbb,   0xfbc,   0xfc6,   0x102b,  0x102c,
9144
39.2k
      0x102d,  0x102e,  0x102f,  0x1030,  0x1031,  0x1032,  0x1033,  0x1034,
9145
39.2k
      0x1035,  0x1036,  0x1037,  0x1038,  0x1039,  0x103a,  0x103b,  0x103c,
9146
39.2k
      0x103d,  0x103e,  0x1056,  0x1057,  0x1058,  0x1059,  0x105e,  0x105f,
9147
39.2k
      0x1060,  0x1062,  0x1063,  0x1064,  0x1067,  0x1068,  0x1069,  0x106a,
9148
39.2k
      0x106b,  0x106c,  0x106d,  0x1071,  0x1072,  0x1073,  0x1074,  0x1082,
9149
39.2k
      0x1083,  0x1084,  0x1085,  0x1086,  0x1087,  0x1088,  0x1089,  0x108a,
9150
39.2k
      0x108b,  0x108c,  0x108d,  0x108f,  0x109a,  0x109b,  0x109c,  0x109d,
9151
39.2k
      0x135d,  0x135e,  0x135f,  0x1712,  0x1713,  0x1714,  0x1732,  0x1733,
9152
39.2k
      0x1734,  0x1752,  0x1753,  0x1772,  0x1773,  0x17b4,  0x17b5,  0x17b6,
9153
39.2k
      0x17b7,  0x17b8,  0x17b9,  0x17ba,  0x17bb,  0x17bc,  0x17bd,  0x17be,
9154
39.2k
      0x17bf,  0x17c0,  0x17c1,  0x17c2,  0x17c3,  0x17c4,  0x17c5,  0x17c6,
9155
39.2k
      0x17c7,  0x17c8,  0x17c9,  0x17ca,  0x17cb,  0x17cc,  0x17cd,  0x17ce,
9156
39.2k
      0x17cf,  0x17d0,  0x17d1,  0x17d2,  0x17d3,  0x17dd,  0x180b,  0x180c,
9157
39.2k
      0x180d,  0x1885,  0x1886,  0x18a9,  0x1920,  0x1921,  0x1922,  0x1923,
9158
39.2k
      0x1924,  0x1925,  0x1926,  0x1927,  0x1928,  0x1929,  0x192a,  0x192b,
9159
39.2k
      0x1930,  0x1931,  0x1932,  0x1933,  0x1934,  0x1935,  0x1936,  0x1937,
9160
39.2k
      0x1938,  0x1939,  0x193a,  0x193b,  0x1a17,  0x1a18,  0x1a19,  0x1a1a,
9161
39.2k
      0x1a1b,  0x1a55,  0x1a56,  0x1a57,  0x1a58,  0x1a59,  0x1a5a,  0x1a5b,
9162
39.2k
      0x1a5c,  0x1a5d,  0x1a5e,  0x1a60,  0x1a61,  0x1a62,  0x1a63,  0x1a64,
9163
39.2k
      0x1a65,  0x1a66,  0x1a67,  0x1a68,  0x1a69,  0x1a6a,  0x1a6b,  0x1a6c,
9164
39.2k
      0x1a6d,  0x1a6e,  0x1a6f,  0x1a70,  0x1a71,  0x1a72,  0x1a73,  0x1a74,
9165
39.2k
      0x1a75,  0x1a76,  0x1a77,  0x1a78,  0x1a79,  0x1a7a,  0x1a7b,  0x1a7c,
9166
39.2k
      0x1a7f,  0x1ab0,  0x1ab1,  0x1ab2,  0x1ab3,  0x1ab4,  0x1ab5,  0x1ab6,
9167
39.2k
      0x1ab7,  0x1ab8,  0x1ab9,  0x1aba,  0x1abb,  0x1abc,  0x1abd,  0x1abe,
9168
39.2k
      0x1abf,  0x1ac0,  0x1b00,  0x1b01,  0x1b02,  0x1b03,  0x1b04,  0x1b34,
9169
39.2k
      0x1b35,  0x1b36,  0x1b37,  0x1b38,  0x1b39,  0x1b3a,  0x1b3b,  0x1b3c,
9170
39.2k
      0x1b3d,  0x1b3e,  0x1b3f,  0x1b40,  0x1b41,  0x1b42,  0x1b43,  0x1b44,
9171
39.2k
      0x1b6b,  0x1b6c,  0x1b6d,  0x1b6e,  0x1b6f,  0x1b70,  0x1b71,  0x1b72,
9172
39.2k
      0x1b73,  0x1b80,  0x1b81,  0x1b82,  0x1ba1,  0x1ba2,  0x1ba3,  0x1ba4,
9173
39.2k
      0x1ba5,  0x1ba6,  0x1ba7,  0x1ba8,  0x1ba9,  0x1baa,  0x1bab,  0x1bac,
9174
39.2k
      0x1bad,  0x1be6,  0x1be7,  0x1be8,  0x1be9,  0x1bea,  0x1beb,  0x1bec,
9175
39.2k
      0x1bed,  0x1bee,  0x1bef,  0x1bf0,  0x1bf1,  0x1bf2,  0x1bf3,  0x1c24,
9176
39.2k
      0x1c25,  0x1c26,  0x1c27,  0x1c28,  0x1c29,  0x1c2a,  0x1c2b,  0x1c2c,
9177
39.2k
      0x1c2d,  0x1c2e,  0x1c2f,  0x1c30,  0x1c31,  0x1c32,  0x1c33,  0x1c34,
9178
39.2k
      0x1c35,  0x1c36,  0x1c37,  0x1cd0,  0x1cd1,  0x1cd2,  0x1cd4,  0x1cd5,
9179
39.2k
      0x1cd6,  0x1cd7,  0x1cd8,  0x1cd9,  0x1cda,  0x1cdb,  0x1cdc,  0x1cdd,
9180
39.2k
      0x1cde,  0x1cdf,  0x1ce0,  0x1ce1,  0x1ce2,  0x1ce3,  0x1ce4,  0x1ce5,
9181
39.2k
      0x1ce6,  0x1ce7,  0x1ce8,  0x1ced,  0x1cf4,  0x1cf7,  0x1cf8,  0x1cf9,
9182
39.2k
      0x1dc0,  0x1dc1,  0x1dc2,  0x1dc3,  0x1dc4,  0x1dc5,  0x1dc6,  0x1dc7,
9183
39.2k
      0x1dc8,  0x1dc9,  0x1dca,  0x1dcb,  0x1dcc,  0x1dcd,  0x1dce,  0x1dcf,
9184
39.2k
      0x1dd0,  0x1dd1,  0x1dd2,  0x1dd3,  0x1dd4,  0x1dd5,  0x1dd6,  0x1dd7,
9185
39.2k
      0x1dd8,  0x1dd9,  0x1dda,  0x1ddb,  0x1ddc,  0x1ddd,  0x1dde,  0x1ddf,
9186
39.2k
      0x1de0,  0x1de1,  0x1de2,  0x1de3,  0x1de4,  0x1de5,  0x1de6,  0x1de7,
9187
39.2k
      0x1de8,  0x1de9,  0x1dea,  0x1deb,  0x1dec,  0x1ded,  0x1dee,  0x1def,
9188
39.2k
      0x1df0,  0x1df1,  0x1df2,  0x1df3,  0x1df4,  0x1df5,  0x1df6,  0x1df7,
9189
39.2k
      0x1df8,  0x1df9,  0x1dfb,  0x1dfc,  0x1dfd,  0x1dfe,  0x1dff,  0x20d0,
9190
39.2k
      0x20d1,  0x20d2,  0x20d3,  0x20d4,  0x20d5,  0x20d6,  0x20d7,  0x20d8,
9191
39.2k
      0x20d9,  0x20da,  0x20db,  0x20dc,  0x20dd,  0x20de,  0x20df,  0x20e0,
9192
39.2k
      0x20e1,  0x20e2,  0x20e3,  0x20e4,  0x20e5,  0x20e6,  0x20e7,  0x20e8,
9193
39.2k
      0x20e9,  0x20ea,  0x20eb,  0x20ec,  0x20ed,  0x20ee,  0x20ef,  0x20f0,
9194
39.2k
      0x2cef,  0x2cf0,  0x2cf1,  0x2d7f,  0x2de0,  0x2de1,  0x2de2,  0x2de3,
9195
39.2k
      0x2de4,  0x2de5,  0x2de6,  0x2de7,  0x2de8,  0x2de9,  0x2dea,  0x2deb,
9196
39.2k
      0x2dec,  0x2ded,  0x2dee,  0x2def,  0x2df0,  0x2df1,  0x2df2,  0x2df3,
9197
39.2k
      0x2df4,  0x2df5,  0x2df6,  0x2df7,  0x2df8,  0x2df9,  0x2dfa,  0x2dfb,
9198
39.2k
      0x2dfc,  0x2dfd,  0x2dfe,  0x2dff,  0x302a,  0x302b,  0x302c,  0x302d,
9199
39.2k
      0x302e,  0x302f,  0x3099,  0x309a,  0xa66f,  0xa670,  0xa671,  0xa672,
9200
39.2k
      0xa674,  0xa675,  0xa676,  0xa677,  0xa678,  0xa679,  0xa67a,  0xa67b,
9201
39.2k
      0xa67c,  0xa67d,  0xa69e,  0xa69f,  0xa6f0,  0xa6f1,  0xa802,  0xa806,
9202
39.2k
      0xa80b,  0xa823,  0xa824,  0xa825,  0xa826,  0xa827,  0xa82c,  0xa880,
9203
39.2k
      0xa881,  0xa8b4,  0xa8b5,  0xa8b6,  0xa8b7,  0xa8b8,  0xa8b9,  0xa8ba,
9204
39.2k
      0xa8bb,  0xa8bc,  0xa8bd,  0xa8be,  0xa8bf,  0xa8c0,  0xa8c1,  0xa8c2,
9205
39.2k
      0xa8c3,  0xa8c4,  0xa8c5,  0xa8e0,  0xa8e1,  0xa8e2,  0xa8e3,  0xa8e4,
9206
39.2k
      0xa8e5,  0xa8e6,  0xa8e7,  0xa8e8,  0xa8e9,  0xa8ea,  0xa8eb,  0xa8ec,
9207
39.2k
      0xa8ed,  0xa8ee,  0xa8ef,  0xa8f0,  0xa8f1,  0xa8ff,  0xa926,  0xa927,
9208
39.2k
      0xa928,  0xa929,  0xa92a,  0xa92b,  0xa92c,  0xa92d,  0xa947,  0xa948,
9209
39.2k
      0xa949,  0xa94a,  0xa94b,  0xa94c,  0xa94d,  0xa94e,  0xa94f,  0xa950,
9210
39.2k
      0xa951,  0xa952,  0xa953,  0xa980,  0xa981,  0xa982,  0xa983,  0xa9b3,
9211
39.2k
      0xa9b4,  0xa9b5,  0xa9b6,  0xa9b7,  0xa9b8,  0xa9b9,  0xa9ba,  0xa9bb,
9212
39.2k
      0xa9bc,  0xa9bd,  0xa9be,  0xa9bf,  0xa9c0,  0xa9e5,  0xaa29,  0xaa2a,
9213
39.2k
      0xaa2b,  0xaa2c,  0xaa2d,  0xaa2e,  0xaa2f,  0xaa30,  0xaa31,  0xaa32,
9214
39.2k
      0xaa33,  0xaa34,  0xaa35,  0xaa36,  0xaa43,  0xaa4c,  0xaa4d,  0xaa7b,
9215
39.2k
      0xaa7c,  0xaa7d,  0xaab0,  0xaab2,  0xaab3,  0xaab4,  0xaab7,  0xaab8,
9216
39.2k
      0xaabe,  0xaabf,  0xaac1,  0xaaeb,  0xaaec,  0xaaed,  0xaaee,  0xaaef,
9217
39.2k
      0xaaf5,  0xaaf6,  0xabe3,  0xabe4,  0xabe5,  0xabe6,  0xabe7,  0xabe8,
9218
39.2k
      0xabe9,  0xabea,  0xabec,  0xabed,  0xfb1e,  0xfe00,  0xfe01,  0xfe02,
9219
39.2k
      0xfe03,  0xfe04,  0xfe05,  0xfe06,  0xfe07,  0xfe08,  0xfe09,  0xfe0a,
9220
39.2k
      0xfe0b,  0xfe0c,  0xfe0d,  0xfe0e,  0xfe0f,  0xfe20,  0xfe21,  0xfe22,
9221
39.2k
      0xfe23,  0xfe24,  0xfe25,  0xfe26,  0xfe27,  0xfe28,  0xfe29,  0xfe2a,
9222
39.2k
      0xfe2b,  0xfe2c,  0xfe2d,  0xfe2e,  0xfe2f,  0x101fd, 0x102e0, 0x10376,
9223
39.2k
      0x10377, 0x10378, 0x10379, 0x1037a, 0x10a01, 0x10a02, 0x10a03, 0x10a05,
9224
39.2k
      0x10a06, 0x10a0c, 0x10a0d, 0x10a0e, 0x10a0f, 0x10a38, 0x10a39, 0x10a3a,
9225
39.2k
      0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d25, 0x10d26, 0x10d27, 0x10eab,
9226
39.2k
      0x10eac, 0x10f46, 0x10f47, 0x10f48, 0x10f49, 0x10f4a, 0x10f4b, 0x10f4c,
9227
39.2k
      0x10f4d, 0x10f4e, 0x10f4f, 0x10f50, 0x11000, 0x11001, 0x11002, 0x11038,
9228
39.2k
      0x11039, 0x1103a, 0x1103b, 0x1103c, 0x1103d, 0x1103e, 0x1103f, 0x11040,
9229
39.2k
      0x11041, 0x11042, 0x11043, 0x11044, 0x11045, 0x11046, 0x1107f, 0x11080,
9230
39.2k
      0x11081, 0x11082, 0x110b0, 0x110b1, 0x110b2, 0x110b3, 0x110b4, 0x110b5,
9231
39.2k
      0x110b6, 0x110b7, 0x110b8, 0x110b9, 0x110ba, 0x11100, 0x11101, 0x11102,
9232
39.2k
      0x11127, 0x11128, 0x11129, 0x1112a, 0x1112b, 0x1112c, 0x1112d, 0x1112e,
9233
39.2k
      0x1112f, 0x11130, 0x11131, 0x11132, 0x11133, 0x11134, 0x11145, 0x11146,
9234
39.2k
      0x11173, 0x11180, 0x11181, 0x11182, 0x111b3, 0x111b4, 0x111b5, 0x111b6,
9235
39.2k
      0x111b7, 0x111b8, 0x111b9, 0x111ba, 0x111bb, 0x111bc, 0x111bd, 0x111be,
9236
39.2k
      0x111bf, 0x111c0, 0x111c9, 0x111ca, 0x111cb, 0x111cc, 0x111ce, 0x111cf,
9237
39.2k
      0x1122c, 0x1122d, 0x1122e, 0x1122f, 0x11230, 0x11231, 0x11232, 0x11233,
9238
39.2k
      0x11234, 0x11235, 0x11236, 0x11237, 0x1123e, 0x112df, 0x112e0, 0x112e1,
9239
39.2k
      0x112e2, 0x112e3, 0x112e4, 0x112e5, 0x112e6, 0x112e7, 0x112e8, 0x112e9,
9240
39.2k
      0x112ea, 0x11300, 0x11301, 0x11302, 0x11303, 0x1133b, 0x1133c, 0x1133e,
9241
39.2k
      0x1133f, 0x11340, 0x11341, 0x11342, 0x11343, 0x11344, 0x11347, 0x11348,
9242
39.2k
      0x1134b, 0x1134c, 0x1134d, 0x11357, 0x11362, 0x11363, 0x11366, 0x11367,
9243
39.2k
      0x11368, 0x11369, 0x1136a, 0x1136b, 0x1136c, 0x11370, 0x11371, 0x11372,
9244
39.2k
      0x11373, 0x11374, 0x11435, 0x11436, 0x11437, 0x11438, 0x11439, 0x1143a,
9245
39.2k
      0x1143b, 0x1143c, 0x1143d, 0x1143e, 0x1143f, 0x11440, 0x11441, 0x11442,
9246
39.2k
      0x11443, 0x11444, 0x11445, 0x11446, 0x1145e, 0x114b0, 0x114b1, 0x114b2,
9247
39.2k
      0x114b3, 0x114b4, 0x114b5, 0x114b6, 0x114b7, 0x114b8, 0x114b9, 0x114ba,
9248
39.2k
      0x114bb, 0x114bc, 0x114bd, 0x114be, 0x114bf, 0x114c0, 0x114c1, 0x114c2,
9249
39.2k
      0x114c3, 0x115af, 0x115b0, 0x115b1, 0x115b2, 0x115b3, 0x115b4, 0x115b5,
9250
39.2k
      0x115b8, 0x115b9, 0x115ba, 0x115bb, 0x115bc, 0x115bd, 0x115be, 0x115bf,
9251
39.2k
      0x115c0, 0x115dc, 0x115dd, 0x11630, 0x11631, 0x11632, 0x11633, 0x11634,
9252
39.2k
      0x11635, 0x11636, 0x11637, 0x11638, 0x11639, 0x1163a, 0x1163b, 0x1163c,
9253
39.2k
      0x1163d, 0x1163e, 0x1163f, 0x11640, 0x116ab, 0x116ac, 0x116ad, 0x116ae,
9254
39.2k
      0x116af, 0x116b0, 0x116b1, 0x116b2, 0x116b3, 0x116b4, 0x116b5, 0x116b6,
9255
39.2k
      0x116b7, 0x1171d, 0x1171e, 0x1171f, 0x11720, 0x11721, 0x11722, 0x11723,
9256
39.2k
      0x11724, 0x11725, 0x11726, 0x11727, 0x11728, 0x11729, 0x1172a, 0x1172b,
9257
39.2k
      0x1182c, 0x1182d, 0x1182e, 0x1182f, 0x11830, 0x11831, 0x11832, 0x11833,
9258
39.2k
      0x11834, 0x11835, 0x11836, 0x11837, 0x11838, 0x11839, 0x1183a, 0x11930,
9259
39.2k
      0x11931, 0x11932, 0x11933, 0x11934, 0x11935, 0x11937, 0x11938, 0x1193b,
9260
39.2k
      0x1193c, 0x1193d, 0x1193e, 0x11940, 0x11942, 0x11943, 0x119d1, 0x119d2,
9261
39.2k
      0x119d3, 0x119d4, 0x119d5, 0x119d6, 0x119d7, 0x119da, 0x119db, 0x119dc,
9262
39.2k
      0x119dd, 0x119de, 0x119df, 0x119e0, 0x119e4, 0x11a01, 0x11a02, 0x11a03,
9263
39.2k
      0x11a04, 0x11a05, 0x11a06, 0x11a07, 0x11a08, 0x11a09, 0x11a0a, 0x11a33,
9264
39.2k
      0x11a34, 0x11a35, 0x11a36, 0x11a37, 0x11a38, 0x11a39, 0x11a3b, 0x11a3c,
9265
39.2k
      0x11a3d, 0x11a3e, 0x11a47, 0x11a51, 0x11a52, 0x11a53, 0x11a54, 0x11a55,
9266
39.2k
      0x11a56, 0x11a57, 0x11a58, 0x11a59, 0x11a5a, 0x11a5b, 0x11a8a, 0x11a8b,
9267
39.2k
      0x11a8c, 0x11a8d, 0x11a8e, 0x11a8f, 0x11a90, 0x11a91, 0x11a92, 0x11a93,
9268
39.2k
      0x11a94, 0x11a95, 0x11a96, 0x11a97, 0x11a98, 0x11a99, 0x11c2f, 0x11c30,
9269
39.2k
      0x11c31, 0x11c32, 0x11c33, 0x11c34, 0x11c35, 0x11c36, 0x11c38, 0x11c39,
9270
39.2k
      0x11c3a, 0x11c3b, 0x11c3c, 0x11c3d, 0x11c3e, 0x11c3f, 0x11c92, 0x11c93,
9271
39.2k
      0x11c94, 0x11c95, 0x11c96, 0x11c97, 0x11c98, 0x11c99, 0x11c9a, 0x11c9b,
9272
39.2k
      0x11c9c, 0x11c9d, 0x11c9e, 0x11c9f, 0x11ca0, 0x11ca1, 0x11ca2, 0x11ca3,
9273
39.2k
      0x11ca4, 0x11ca5, 0x11ca6, 0x11ca7, 0x11ca9, 0x11caa, 0x11cab, 0x11cac,
9274
39.2k
      0x11cad, 0x11cae, 0x11caf, 0x11cb0, 0x11cb1, 0x11cb2, 0x11cb3, 0x11cb4,
9275
39.2k
      0x11cb5, 0x11cb6, 0x11d31, 0x11d32, 0x11d33, 0x11d34, 0x11d35, 0x11d36,
9276
39.2k
      0x11d3a, 0x11d3c, 0x11d3d, 0x11d3f, 0x11d40, 0x11d41, 0x11d42, 0x11d43,
9277
39.2k
      0x11d44, 0x11d45, 0x11d47, 0x11d8a, 0x11d8b, 0x11d8c, 0x11d8d, 0x11d8e,
9278
39.2k
      0x11d90, 0x11d91, 0x11d93, 0x11d94, 0x11d95, 0x11d96, 0x11d97, 0x11ef3,
9279
39.2k
      0x11ef4, 0x11ef5, 0x11ef6, 0x16af0, 0x16af1, 0x16af2, 0x16af3, 0x16af4,
9280
39.2k
      0x16b30, 0x16b31, 0x16b32, 0x16b33, 0x16b34, 0x16b35, 0x16b36, 0x16f4f,
9281
39.2k
      0x16f51, 0x16f52, 0x16f53, 0x16f54, 0x16f55, 0x16f56, 0x16f57, 0x16f58,
9282
39.2k
      0x16f59, 0x16f5a, 0x16f5b, 0x16f5c, 0x16f5d, 0x16f5e, 0x16f5f, 0x16f60,
9283
39.2k
      0x16f61, 0x16f62, 0x16f63, 0x16f64, 0x16f65, 0x16f66, 0x16f67, 0x16f68,
9284
39.2k
      0x16f69, 0x16f6a, 0x16f6b, 0x16f6c, 0x16f6d, 0x16f6e, 0x16f6f, 0x16f70,
9285
39.2k
      0x16f71, 0x16f72, 0x16f73, 0x16f74, 0x16f75, 0x16f76, 0x16f77, 0x16f78,
9286
39.2k
      0x16f79, 0x16f7a, 0x16f7b, 0x16f7c, 0x16f7d, 0x16f7e, 0x16f7f, 0x16f80,
9287
39.2k
      0x16f81, 0x16f82, 0x16f83, 0x16f84, 0x16f85, 0x16f86, 0x16f87, 0x16f8f,
9288
39.2k
      0x16f90, 0x16f91, 0x16f92, 0x16fe4, 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e,
9289
39.2k
      0x1d165, 0x1d166, 0x1d167, 0x1d168, 0x1d169, 0x1d16d, 0x1d16e, 0x1d16f,
9290
39.2k
      0x1d170, 0x1d171, 0x1d172, 0x1d17b, 0x1d17c, 0x1d17d, 0x1d17e, 0x1d17f,
9291
39.2k
      0x1d180, 0x1d181, 0x1d182, 0x1d185, 0x1d186, 0x1d187, 0x1d188, 0x1d189,
9292
39.2k
      0x1d18a, 0x1d18b, 0x1d1aa, 0x1d1ab, 0x1d1ac, 0x1d1ad, 0x1d242, 0x1d243,
9293
39.2k
      0x1d244, 0x1da00, 0x1da01, 0x1da02, 0x1da03, 0x1da04, 0x1da05, 0x1da06,
9294
39.2k
      0x1da07, 0x1da08, 0x1da09, 0x1da0a, 0x1da0b, 0x1da0c, 0x1da0d, 0x1da0e,
9295
39.2k
      0x1da0f, 0x1da10, 0x1da11, 0x1da12, 0x1da13, 0x1da14, 0x1da15, 0x1da16,
9296
39.2k
      0x1da17, 0x1da18, 0x1da19, 0x1da1a, 0x1da1b, 0x1da1c, 0x1da1d, 0x1da1e,
9297
39.2k
      0x1da1f, 0x1da20, 0x1da21, 0x1da22, 0x1da23, 0x1da24, 0x1da25, 0x1da26,
9298
39.2k
      0x1da27, 0x1da28, 0x1da29, 0x1da2a, 0x1da2b, 0x1da2c, 0x1da2d, 0x1da2e,
9299
39.2k
      0x1da2f, 0x1da30, 0x1da31, 0x1da32, 0x1da33, 0x1da34, 0x1da35, 0x1da36,
9300
39.2k
      0x1da3b, 0x1da3c, 0x1da3d, 0x1da3e, 0x1da3f, 0x1da40, 0x1da41, 0x1da42,
9301
39.2k
      0x1da43, 0x1da44, 0x1da45, 0x1da46, 0x1da47, 0x1da48, 0x1da49, 0x1da4a,
9302
39.2k
      0x1da4b, 0x1da4c, 0x1da4d, 0x1da4e, 0x1da4f, 0x1da50, 0x1da51, 0x1da52,
9303
39.2k
      0x1da53, 0x1da54, 0x1da55, 0x1da56, 0x1da57, 0x1da58, 0x1da59, 0x1da5a,
9304
39.2k
      0x1da5b, 0x1da5c, 0x1da5d, 0x1da5e, 0x1da5f, 0x1da60, 0x1da61, 0x1da62,
9305
39.2k
      0x1da63, 0x1da64, 0x1da65, 0x1da66, 0x1da67, 0x1da68, 0x1da69, 0x1da6a,
9306
39.2k
      0x1da6b, 0x1da6c, 0x1da75, 0x1da84, 0x1da9b, 0x1da9c, 0x1da9d, 0x1da9e,
9307
39.2k
      0x1da9f, 0x1daa1, 0x1daa2, 0x1daa3, 0x1daa4, 0x1daa5, 0x1daa6, 0x1daa7,
9308
39.2k
      0x1daa8, 0x1daa9, 0x1daaa, 0x1daab, 0x1daac, 0x1daad, 0x1daae, 0x1daaf,
9309
39.2k
      0x1e000, 0x1e001, 0x1e002, 0x1e003, 0x1e004, 0x1e005, 0x1e006, 0x1e008,
9310
39.2k
      0x1e009, 0x1e00a, 0x1e00b, 0x1e00c, 0x1e00d, 0x1e00e, 0x1e00f, 0x1e010,
9311
39.2k
      0x1e011, 0x1e012, 0x1e013, 0x1e014, 0x1e015, 0x1e016, 0x1e017, 0x1e018,
9312
39.2k
      0x1e01b, 0x1e01c, 0x1e01d, 0x1e01e, 0x1e01f, 0x1e020, 0x1e021, 0x1e023,
9313
39.2k
      0x1e024, 0x1e026, 0x1e027, 0x1e028, 0x1e029, 0x1e02a, 0x1e130, 0x1e131,
9314
39.2k
      0x1e132, 0x1e133, 0x1e134, 0x1e135, 0x1e136, 0x1e2ec, 0x1e2ed, 0x1e2ee,
9315
39.2k
      0x1e2ef, 0x1e8d0, 0x1e8d1, 0x1e8d2, 0x1e8d3, 0x1e8d4, 0x1e8d5, 0x1e8d6,
9316
39.2k
      0x1e944, 0x1e945, 0x1e946, 0x1e947, 0x1e948, 0x1e949, 0x1e94a, 0xe0100,
9317
39.2k
      0xe0101, 0xe0102, 0xe0103, 0xe0104, 0xe0105, 0xe0106, 0xe0107, 0xe0108,
9318
39.2k
      0xe0109, 0xe010a, 0xe010b, 0xe010c, 0xe010d, 0xe010e, 0xe010f, 0xe0110,
9319
39.2k
      0xe0111, 0xe0112, 0xe0113, 0xe0114, 0xe0115, 0xe0116, 0xe0117, 0xe0118,
9320
39.2k
      0xe0119, 0xe011a, 0xe011b, 0xe011c, 0xe011d, 0xe011e, 0xe011f, 0xe0120,
9321
39.2k
      0xe0121, 0xe0122, 0xe0123, 0xe0124, 0xe0125, 0xe0126, 0xe0127, 0xe0128,
9322
39.2k
      0xe0129, 0xe012a, 0xe012b, 0xe012c, 0xe012d, 0xe012e, 0xe012f, 0xe0130,
9323
39.2k
      0xe0131, 0xe0132, 0xe0133, 0xe0134, 0xe0135, 0xe0136, 0xe0137, 0xe0138,
9324
39.2k
      0xe0139, 0xe013a, 0xe013b, 0xe013c, 0xe013d, 0xe013e, 0xe013f, 0xe0140,
9325
39.2k
      0xe0141, 0xe0142, 0xe0143, 0xe0144, 0xe0145, 0xe0146, 0xe0147, 0xe0148,
9326
39.2k
      0xe0149, 0xe014a, 0xe014b, 0xe014c, 0xe014d, 0xe014e, 0xe014f, 0xe0150,
9327
39.2k
      0xe0151, 0xe0152, 0xe0153, 0xe0154, 0xe0155, 0xe0156, 0xe0157, 0xe0158,
9328
39.2k
      0xe0159, 0xe015a, 0xe015b, 0xe015c, 0xe015d, 0xe015e, 0xe015f, 0xe0160,
9329
39.2k
      0xe0161, 0xe0162, 0xe0163, 0xe0164, 0xe0165, 0xe0166, 0xe0167, 0xe0168,
9330
39.2k
      0xe0169, 0xe016a, 0xe016b, 0xe016c, 0xe016d, 0xe016e, 0xe016f, 0xe0170,
9331
39.2k
      0xe0171, 0xe0172, 0xe0173, 0xe0174, 0xe0175, 0xe0176, 0xe0177, 0xe0178,
9332
39.2k
      0xe0179, 0xe017a, 0xe017b, 0xe017c, 0xe017d, 0xe017e, 0xe017f, 0xe0180,
9333
39.2k
      0xe0181, 0xe0182, 0xe0183, 0xe0184, 0xe0185, 0xe0186, 0xe0187, 0xe0188,
9334
39.2k
      0xe0189, 0xe018a, 0xe018b, 0xe018c, 0xe018d, 0xe018e, 0xe018f, 0xe0190,
9335
39.2k
      0xe0191, 0xe0192, 0xe0193, 0xe0194, 0xe0195, 0xe0196, 0xe0197, 0xe0198,
9336
39.2k
      0xe0199, 0xe019a, 0xe019b, 0xe019c, 0xe019d, 0xe019e, 0xe019f, 0xe01a0,
9337
39.2k
      0xe01a1, 0xe01a2, 0xe01a3, 0xe01a4, 0xe01a5, 0xe01a6, 0xe01a7, 0xe01a8,
9338
39.2k
      0xe01a9, 0xe01aa, 0xe01ab, 0xe01ac, 0xe01ad, 0xe01ae, 0xe01af, 0xe01b0,
9339
39.2k
      0xe01b1, 0xe01b2, 0xe01b3, 0xe01b4, 0xe01b5, 0xe01b6, 0xe01b7, 0xe01b8,
9340
39.2k
      0xe01b9, 0xe01ba, 0xe01bb, 0xe01bc, 0xe01bd, 0xe01be, 0xe01bf, 0xe01c0,
9341
39.2k
      0xe01c1, 0xe01c2, 0xe01c3, 0xe01c4, 0xe01c5, 0xe01c6, 0xe01c7, 0xe01c8,
9342
39.2k
      0xe01c9, 0xe01ca, 0xe01cb, 0xe01cc, 0xe01cd, 0xe01ce, 0xe01cf, 0xe01d0,
9343
39.2k
      0xe01d1, 0xe01d2, 0xe01d3, 0xe01d4, 0xe01d5, 0xe01d6, 0xe01d7, 0xe01d8,
9344
39.2k
      0xe01d9, 0xe01da, 0xe01db, 0xe01dc, 0xe01dd, 0xe01de, 0xe01df, 0xe01e0,
9345
39.2k
      0xe01e1, 0xe01e2, 0xe01e3, 0xe01e4, 0xe01e5, 0xe01e6, 0xe01e7, 0xe01e8,
9346
39.2k
      0xe01e9, 0xe01ea, 0xe01eb, 0xe01ec, 0xe01ed, 0xe01ee, 0xe01ef};
9347
39.2k
  if (std::binary_search(std::begin(combining), std::end(combining),
9348
39.2k
                         label.front())) {
9349
122
    return false;
9350
122
  }
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
39.1k
  constexpr static uint32_t virama[] = {
9363
39.1k
      0x094D,  0x09CD,  0x0A4D,  0x0ACD,  0x0B4D,  0x0BCD,  0x0C4D,  0x0CCD,
9364
39.1k
      0x0D3B,  0x0D3C,  0x0D4D,  0x0DCA,  0x0E3A,  0x0EBA,  0x0F84,  0x1039,
9365
39.1k
      0x103A,  0x1714,  0x1734,  0x17D2,  0x1A60,  0x1B44,  0x1BAA,  0x1BAB,
9366
39.1k
      0x1BF2,  0x1BF3,  0x2D7F,  0xA806,  0xA82C,  0xA8C4,  0xA953,  0xA9C0,
9367
39.1k
      0xAAF6,  0xABED,  0x10A3F, 0x11046, 0x1107F, 0x110B9, 0x11133, 0x11134,
9368
39.1k
      0x111C0, 0x11235, 0x112EA, 0x1134D, 0x11442, 0x114C2, 0x115BF, 0x1163F,
9369
39.1k
      0x116B6, 0x1172B, 0x11839, 0x1193D, 0x1193E, 0x119E0, 0x11A34, 0x11A47,
9370
39.1k
      0x11A99, 0x11C3F, 0x11D44, 0x11D45, 0x11D97};
9371
39.1k
  constexpr static uint32_t R[] = {
9372
39.1k
      0x622, 0x623, 0x624, 0x625, 0x627, 0x629, 0x62f, 0x630, 0x631,
9373
39.1k
      0x632, 0x648, 0x671, 0x672, 0x673, 0x675, 0x676, 0x677, 0x688,
9374
39.1k
      0x689, 0x68a, 0x68b, 0x68c, 0x68d, 0x68e, 0x68f, 0x690, 0x691,
9375
39.1k
      0x692, 0x693, 0x694, 0x695, 0x696, 0x697, 0x698, 0x699, 0x6c0,
9376
39.1k
      0x6c3, 0x6c4, 0x6c5, 0x6c6, 0x6c7, 0x6c8, 0x6c9, 0x6ca, 0x6cb,
9377
39.1k
      0x6cd, 0x6cf, 0x6d2, 0x6d3, 0x6d5, 0x6ee, 0x6ef, 0x710, 0x715,
9378
39.1k
      0x716, 0x717, 0x718, 0x719, 0x71e, 0x728, 0x72a, 0x72c, 0x72f,
9379
39.1k
      0x74d, 0x759, 0x75a, 0x75b, 0x854, 0x8aa, 0x8ab, 0x8ac};
9380
39.1k
  constexpr static uint32_t L[] = {0xa872};
9381
39.1k
  constexpr static uint32_t D[] = {
9382
39.1k
      0x620,  0x626,  0x628,  0x62a,  0x62b,  0x62c,  0x62d,  0x62e,  0x633,
9383
39.1k
      0x634,  0x635,  0x636,  0x637,  0x638,  0x639,  0x63a,  0x63b,  0x63c,
9384
39.1k
      0x63d,  0x63e,  0x63f,  0x641,  0x642,  0x643,  0x644,  0x645,  0x646,
9385
39.1k
      0x647,  0x649,  0x64a,  0x66e,  0x66f,  0x678,  0x679,  0x67a,  0x67b,
9386
39.1k
      0x67c,  0x67d,  0x67e,  0x67f,  0x680,  0x681,  0x682,  0x683,  0x684,
9387
39.1k
      0x685,  0x686,  0x687,  0x69a,  0x69b,  0x69c,  0x69d,  0x69e,  0x69f,
9388
39.1k
      0x6a0,  0x6a1,  0x6a2,  0x6a3,  0x6a4,  0x6a5,  0x6a6,  0x6a7,  0x6a8,
9389
39.1k
      0x6a9,  0x6aa,  0x6ab,  0x6ac,  0x6ad,  0x6ae,  0x6af,  0x6b0,  0x6b1,
9390
39.1k
      0x6b2,  0x6b3,  0x6b4,  0x6b5,  0x6b6,  0x6b7,  0x6b8,  0x6b9,  0x6ba,
9391
39.1k
      0x6bb,  0x6bc,  0x6bd,  0x6be,  0x6bf,  0x6c1,  0x6c2,  0x6cc,  0x6ce,
9392
39.1k
      0x6d0,  0x6d1,  0x6fa,  0x6fb,  0x6fc,  0x6ff,  0x712,  0x713,  0x714,
9393
39.1k
      0x71a,  0x71b,  0x71c,  0x71d,  0x71f,  0x720,  0x721,  0x722,  0x723,
9394
39.1k
      0x724,  0x725,  0x726,  0x727,  0x729,  0x72b,  0x72d,  0x72e,  0x74e,
9395
39.1k
      0x74f,  0x750,  0x751,  0x752,  0x753,  0x754,  0x755,  0x756,  0x757,
9396
39.1k
      0x758,  0x75c,  0x75d,  0x75e,  0x75f,  0x760,  0x761,  0x762,  0x763,
9397
39.1k
      0x764,  0x765,  0x766,  0x850,  0x851,  0x852,  0x853,  0x855,  0x8a0,
9398
39.1k
      0x8a2,  0x8a3,  0x8a4,  0x8a5,  0x8a6,  0x8a7,  0x8a8,  0x8a9,  0x1807,
9399
39.1k
      0x1820, 0x1821, 0x1822, 0x1823, 0x1824, 0x1825, 0x1826, 0x1827, 0x1828,
9400
39.1k
      0x1829, 0x182a, 0x182b, 0x182c, 0x182d, 0x182e, 0x182f, 0x1830, 0x1831,
9401
39.1k
      0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837, 0x1838, 0x1839, 0x183a,
9402
39.1k
      0x183b, 0x183c, 0x183d, 0x183e, 0x183f, 0x1840, 0x1841, 0x1842, 0x1843,
9403
39.1k
      0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x184a, 0x184b, 0x184c,
9404
39.1k
      0x184d, 0x184e, 0x184f, 0x1850, 0x1851, 0x1852, 0x1853, 0x1854, 0x1855,
9405
39.1k
      0x1856, 0x1857, 0x1858, 0x1859, 0x185a, 0x185b, 0x185c, 0x185d, 0x185e,
9406
39.1k
      0x185f, 0x1860, 0x1861, 0x1862, 0x1863, 0x1864, 0x1865, 0x1866, 0x1867,
9407
39.1k
      0x1868, 0x1869, 0x186a, 0x186b, 0x186c, 0x186d, 0x186e, 0x186f, 0x1870,
9408
39.1k
      0x1871, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, 0x1877, 0x1887, 0x1888,
9409
39.1k
      0x1889, 0x188a, 0x188b, 0x188c, 0x188d, 0x188e, 0x188f, 0x1890, 0x1891,
9410
39.1k
      0x1892, 0x1893, 0x1894, 0x1895, 0x1896, 0x1897, 0x1898, 0x1899, 0x189a,
9411
39.1k
      0x189b, 0x189c, 0x189d, 0x189e, 0x189f, 0x18a0, 0x18a1, 0x18a2, 0x18a3,
9412
39.1k
      0x18a4, 0x18a5, 0x18a6, 0x18a7, 0x18a8, 0x18aa, 0xa840, 0xa841, 0xa842,
9413
39.1k
      0xa843, 0xa844, 0xa845, 0xa846, 0xa847, 0xa848, 0xa849, 0xa84a, 0xa84b,
9414
39.1k
      0xa84c, 0xa84d, 0xa84e, 0xa84f, 0xa850, 0xa851, 0xa852, 0xa853, 0xa854,
9415
39.1k
      0xa855, 0xa856, 0xa857, 0xa858, 0xa859, 0xa85a, 0xa85b, 0xa85c, 0xa85d,
9416
39.1k
      0xa85e, 0xa85f, 0xa860, 0xa861, 0xa862, 0xa863, 0xa864, 0xa865, 0xa866,
9417
39.1k
      0xa867, 0xa868, 0xa869, 0xa86a, 0xa86b, 0xa86c, 0xa86d, 0xa86e, 0xa86f,
9418
39.1k
      0xa870, 0xa871};
9419
9420
390k
  for (size_t i = 0; i < label.size(); i++) {
9421
353k
    uint32_t c = label[i];
9422
353k
    if (c == 0x200c) {
9423
1.45k
      if (i > 0) {
9424
1.45k
        if (std::binary_search(std::begin(virama), std::end(virama),
9425
1.45k
                               label[i - 1])) {
9426
252
          return true;
9427
252
        }
9428
1.45k
      }
9429
1.20k
      if ((i == 0) || (i + 1 >= label.size())) {
9430
128
        return false;
9431
128
      }
9432
      // we go backward looking for L or D
9433
2.66k
      auto is_l_or_d = [](uint32_t code) {
9434
2.66k
        return std::binary_search(std::begin(L), std::end(L), code) ||
9435
2.60k
               std::binary_search(std::begin(D), std::end(D), code);
9436
2.66k
      };
9437
2.22k
      auto is_r_or_d = [](uint32_t code) {
9438
2.22k
        return std::binary_search(std::begin(R), std::end(R), code) ||
9439
1.89k
               std::binary_search(std::begin(D), std::end(D), code);
9440
2.22k
      };
9441
1.07k
      std::u32string_view before = label.substr(0, i);
9442
1.07k
      std::u32string_view after = label.substr(i + 1);
9443
1.07k
      return (std::find_if(before.begin(), before.end(), is_l_or_d) !=
9444
1.07k
              before.end()) &&
9445
940
             (std::find_if(after.begin(), after.end(), is_r_or_d) !=
9446
940
              after.end());
9447
352k
    } else if (c == 0x200d) {
9448
656
      if (i > 0) {
9449
642
        if (std::binary_search(std::begin(virama), std::end(virama),
9450
642
                               label[i - 1])) {
9451
492
          return true;
9452
492
        }
9453
642
      }
9454
164
      return false;
9455
656
    }
9456
353k
  }
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
37.0k
  size_t last_non_nsm_char = find_last_not_of_nsm(label);
9489
37.0k
  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
37.0k
  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.33k
    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.82k
      for (size_t i = 0; i < last_non_nsm_char; i++) {
9507
4.24k
        const direction d = find_direction(label[i]);
9508
4.24k
        if (!(d == direction::L || d == direction::EN || d == direction::ES ||
9509
2.39k
              d == direction::CS || d == direction::ET || d == direction::ON ||
9510
1.39k
              d == direction::BN || d == direction::NSM)) {
9511
102
          return false;
9512
102
        }
9513
9514
4.13k
        if ((i == last_non_nsm_char) &&
9515
0
            !(d == direction::L || d == direction::EN)) {
9516
0
          return false;
9517
0
        }
9518
4.13k
      }
9519
9520
588
      return true;
9521
9522
2.64k
    } else {
9523
      // Eval as RTL
9524
9525
2.64k
      bool has_an = false;
9526
2.64k
      bool has_en = false;
9527
10.0k
      for (size_t i = 0; i <= last_non_nsm_char; i++) {
9528
7.72k
        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.72k
        if ((d == direction::EN && ((has_en = true) && has_an)) ||
9533
7.71k
            (d == direction::AN && ((has_an = true) && has_en))) {
9534
18
          return false;
9535
18
        }
9536
9537
7.70k
        if (!(d == direction::R || d == direction::AL || d == direction::AN ||
9538
3.21k
              d == direction::EN || d == direction::ES || d == direction::CS ||
9539
2.09k
              d == direction::ET || d == direction::ON || d == direction::BN ||
9540
560
              d == direction::NSM)) {
9541
230
          return false;
9542
230
        }
9543
9544
7.47k
        if (i == last_non_nsm_char &&
9545
2.39k
            !(d == direction::R || d == direction::AL || d == direction::AN ||
9546
314
              d == direction::EN)) {
9547
78
          return false;
9548
78
        }
9549
7.47k
      }
9550
9551
2.31k
      return true;
9552
2.64k
    }
9553
3.33k
  }
9554
9555
33.6k
  return true;
9556
37.0k
}
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
41.9k
bool constexpr is_ascii(std::u32string_view view) {
9574
68.3k
  for (uint32_t c : view) {
9575
68.3k
    if (c >= 0x80) {
9576
39.8k
      return false;
9577
39.8k
    }
9578
68.3k
  }
9579
2.08k
  return true;
9580
41.9k
}
9581
9582
17.3k
bool constexpr is_ascii(std::string_view view) {
9583
143k
  for (uint8_t c : view) {
9584
143k
    if (c >= 0x80) {
9585
10.5k
      return false;
9586
10.5k
    }
9587
143k
  }
9588
6.78k
  return true;
9589
17.3k
}
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.78k
static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9616
6.78k
  static const std::string error = "";
9617
  // copy and map
9618
  // we could be more efficient by avoiding the copy when unnecessary.
9619
6.78k
  std::string mapped_string = std::string(ut8_string);
9620
6.78k
  ascii_map(mapped_string.data(), mapped_string.size());
9621
6.78k
  std::string out;
9622
6.78k
  size_t label_start = 0;
9623
9624
19.9k
  while (label_start != mapped_string.size()) {
9625
13.9k
    size_t loc_dot = mapped_string.find('.', label_start);
9626
13.9k
    bool is_last_label = (loc_dot == std::string_view::npos);
9627
13.9k
    size_t label_size = is_last_label ? mapped_string.size() - label_start
9628
13.9k
                                      : loc_dot - label_start;
9629
13.9k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9630
13.9k
    std::string_view label_view(mapped_string.data() + label_start, label_size);
9631
13.9k
    label_start += label_size_with_dot;
9632
13.9k
    if (label_size == 0) {
9633
      // empty label? Nothing to do.
9634
10.8k
    } else if (label_view.starts_with("xn--")) {
9635
      // The xn-- part is the expensive game.
9636
3.64k
      out.append(label_view);
9637
3.64k
      std::string_view puny_segment_ascii(
9638
3.64k
          out.data() + out.size() - label_view.size() + 4,
9639
3.64k
          label_view.size() - 4);
9640
3.64k
      std::u32string tmp_buffer;
9641
3.64k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9642
3.64k
      if (!is_ok) {
9643
262
        return error;
9644
262
      }
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.38k
      if (is_ascii(tmp_buffer)) {
9649
156
        return error;
9650
156
      }
9651
3.22k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9652
3.22k
      if (tmp_buffer != post_map) {
9653
308
        return error;
9654
308
      }
9655
2.91k
      std::u32string pre_normal = post_map;
9656
2.91k
      normalize(post_map);
9657
2.91k
      if (post_map != pre_normal) {
9658
72
        return error;
9659
72
      }
9660
2.84k
      if (post_map.empty()) {
9661
0
        return error;
9662
0
      }
9663
2.84k
      if (!is_label_valid(post_map)) {
9664
32
        return error;
9665
32
      }
9666
7.16k
    } else {
9667
7.16k
      out.append(label_view);
9668
7.16k
    }
9669
13.1k
    if (!is_last_label) {
9670
7.51k
      out.push_back('.');
9671
7.51k
    }
9672
13.1k
  }
9673
5.95k
  return out;
9674
6.78k
}
9675
9676
// We return "" on error.
9677
17.3k
std::string to_ascii(std::string_view ut8_string) {
9678
17.3k
  if (is_ascii(ut8_string)) {
9679
6.78k
    return from_ascii_to_ascii(ut8_string);
9680
6.78k
  }
9681
10.5k
  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
10.5k
  size_t utf32_length =
9692
10.5k
      ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9693
10.5k
  std::u32string utf32(utf32_length, '\0');
9694
10.5k
  size_t actual_utf32_length = ada::idna::utf8_to_utf32(
9695
10.5k
      ut8_string.data(), ut8_string.size(), utf32.data());
9696
10.5k
#endif
9697
10.5k
  if (actual_utf32_length == 0) {
9698
2.33k
    return error;
9699
2.33k
  }
9700
  // mapping
9701
8.18k
  utf32 = ada::idna::map(utf32);
9702
8.18k
  normalize(utf32);
9703
8.18k
  std::string out;
9704
8.18k
  size_t label_start = 0;
9705
9706
46.6k
  while (label_start != utf32.size()) {
9707
40.1k
    size_t loc_dot = utf32.find('.', label_start);
9708
40.1k
    bool is_last_label = (loc_dot == std::string_view::npos);
9709
40.1k
    size_t label_size =
9710
40.1k
        is_last_label ? utf32.size() - label_start : loc_dot - label_start;
9711
40.1k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9712
40.1k
    std::u32string_view label_view(utf32.data() + label_start, label_size);
9713
40.1k
    label_start += label_size_with_dot;
9714
40.1k
    if (label_size == 0) {
9715
      // empty label? Nothing to do.
9716
38.7k
    } 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
42.6k
      for (char32_t c : label_view) {
9719
42.6k
        if (c >= 0x80) {
9720
38
          return error;
9721
38
        }
9722
42.5k
        out += (unsigned char)(c);
9723
42.5k
      }
9724
2.18k
      std::string_view puny_segment_ascii(
9725
2.18k
          out.data() + out.size() - label_view.size() + 4,
9726
2.18k
          label_view.size() - 4);
9727
2.18k
      std::u32string tmp_buffer;
9728
2.18k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9729
2.18k
      if (!is_ok) {
9730
106
        return error;
9731
106
      }
9732
      // If the input is just ASCII, it should not have been encoded
9733
      // as punycode.
9734
      // https://github.com/whatwg/url/issues/760
9735
2.07k
      if (is_ascii(tmp_buffer)) {
9736
120
        return error;
9737
120
      }
9738
1.95k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9739
1.95k
      if (tmp_buffer != post_map) {
9740
210
        return error;
9741
210
      }
9742
1.74k
      std::u32string pre_normal = post_map;
9743
1.74k
      normalize(post_map);
9744
1.74k
      if (post_map != pre_normal) {
9745
28
        return error;
9746
28
      }
9747
1.71k
      if (post_map.empty()) {
9748
0
        return error;
9749
0
      }
9750
1.71k
      if (!is_label_valid(post_map)) {
9751
10
        return error;
9752
10
      }
9753
36.5k
    } else {
9754
      // The fast path here is an ascii label.
9755
36.5k
      if (is_ascii(label_view)) {
9756
        // no validation needed.
9757
14.6k
        for (char32_t c : label_view) {
9758
14.6k
          out += (unsigned char)(c);
9759
14.6k
        }
9760
34.6k
      } else {
9761
        // slow path.
9762
        // first check validity.
9763
34.6k
        if (!is_label_valid(label_view)) {
9764
1.17k
          return error;
9765
1.17k
        }
9766
        // It is valid! So now we must encode it as punycode...
9767
33.5k
        out.append("xn--");
9768
33.5k
        bool is_ok = ada::idna::utf32_to_punycode(label_view, out);
9769
33.5k
        if (!is_ok) {
9770
0
          return error;
9771
0
        }
9772
33.5k
      }
9773
36.5k
    }
9774
38.4k
    if (!is_last_label) {
9775
32.5k
      out.push_back('.');
9776
32.5k
    }
9777
38.4k
  }
9778
6.49k
  return out;
9779
8.18k
}
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
209k
constexpr bool is_tabs_or_newline(char c) noexcept {
10487
209k
  return c == '\r' || c == '\n' || c == '\t';
10488
209k
}
10489
10490
112k
constexpr uint64_t broadcast(uint8_t v) noexcept {
10491
112k
  return 0x101010101010101ull * v;
10492
112k
}
10493
10494
37.5k
constexpr bool to_lower_ascii(char* input, size_t length) noexcept {
10495
37.5k
  uint64_t broadcast_80 = broadcast(0x80);
10496
37.5k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
10497
37.5k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
10498
37.5k
  uint64_t non_ascii = 0;
10499
37.5k
  size_t i = 0;
10500
10501
84.8k
  for (; i + 7 < length; i += 8) {
10502
47.3k
    uint64_t word{};
10503
47.3k
    memcpy(&word, input + i, sizeof(word));
10504
47.3k
    non_ascii |= (word & broadcast_80);
10505
47.3k
    word ^=
10506
47.3k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10507
47.3k
    memcpy(input + i, &word, sizeof(word));
10508
47.3k
  }
10509
37.5k
  if (i < length) {
10510
36.3k
    uint64_t word{};
10511
36.3k
    memcpy(&word, input + i, length - i);
10512
36.3k
    non_ascii |= (word & broadcast_80);
10513
36.3k
    word ^=
10514
36.3k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10515
36.3k
    memcpy(input + i, &word, length - i);
10516
36.3k
  }
10517
37.5k
  return non_ascii == 0;
10518
37.5k
}
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
70.0k
    std::string_view user_input) noexcept {
10592
  // first check for short strings in which case we do it naively.
10593
70.0k
  if (user_input.size() < 16) {  // slow path
10594
29.5k
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10595
29.5k
  }
10596
  // fast path for long strings (expected to be common)
10597
40.5k
  size_t i = 0;
10598
40.5k
  const __m128i mask1 = _mm_set1_epi8('\r');
10599
40.5k
  const __m128i mask2 = _mm_set1_epi8('\n');
10600
40.5k
  const __m128i mask3 = _mm_set1_epi8('\t');
10601
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10602
40.5k
  __m128i running{0};
10603
151k
  for (; i + 15 < user_input.size(); i += 16) {
10604
111k
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
10605
111k
    running = _mm_or_si128(
10606
111k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10607
111k
                                           _mm_cmpeq_epi8(word, mask2))),
10608
111k
        _mm_cmpeq_epi8(word, mask3));
10609
111k
  }
10610
40.5k
  if (i < user_input.size()) {
10611
37.7k
    __m128i word = _mm_loadu_si128(
10612
37.7k
        (const __m128i*)(user_input.data() + user_input.length() - 16));
10613
37.7k
    running = _mm_or_si128(
10614
37.7k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10615
37.7k
                                           _mm_cmpeq_epi8(word, mask2))),
10616
37.7k
        _mm_cmpeq_epi8(word, mask3));
10617
37.7k
  }
10618
40.5k
  return _mm_movemask_epi8(running) != 0;
10619
70.0k
}
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
19.4k
    const char c) noexcept {
10715
19.4k
  return is_forbidden_host_code_point_table[uint8_t(c)];
10716
19.4k
}
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
882k
    const char c) noexcept {
10738
882k
  return is_forbidden_domain_code_point_table[uint8_t(c)];
10739
882k
}
10740
10741
ada_really_inline constexpr bool contains_forbidden_domain_code_point(
10742
36.6k
    const char* input, size_t length) noexcept {
10743
36.6k
  size_t i = 0;
10744
36.6k
  uint8_t accumulator{};
10745
390k
  for (; i + 4 <= length; i += 4) {
10746
353k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10747
353k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 1])];
10748
353k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 2])];
10749
353k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 3])];
10750
353k
  }
10751
104k
  for (; i < length; i++) {
10752
68.2k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10753
68.2k
  }
10754
36.6k
  return accumulator;
10755
36.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
24.3k
                                              size_t length) noexcept {
10779
24.3k
  size_t i = 0;
10780
24.3k
  uint8_t accumulator{};
10781
120k
  for (; i + 4 <= length; i += 4) {
10782
96.6k
    accumulator |=
10783
96.6k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10784
96.6k
    accumulator |=
10785
96.6k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 1])];
10786
96.6k
    accumulator |=
10787
96.6k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 2])];
10788
96.6k
    accumulator |=
10789
96.6k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 3])];
10790
96.6k
  }
10791
73.9k
  for (; i < length; i++) {
10792
49.5k
    accumulator |=
10793
49.5k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10794
49.5k
  }
10795
24.3k
  return accumulator;
10796
24.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
246k
ada_really_inline constexpr bool is_alnum_plus(const char c) noexcept {
10809
246k
  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
246k
}
10814
10815
33.1k
ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept {
10816
33.1k
  return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
10817
3.58k
         (c >= 'a' && c <= 'f');
10818
33.1k
}
10819
10820
38.6k
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
38.6k
  return (c >= '0' && c <= '9');
10824
38.6k
}
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
91.3k
ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept {
10832
91.3k
  return (unsigned char)c <= ' ';
10833
91.3k
}
10834
10835
ada_really_inline constexpr bool is_ascii_tab_or_newline(
10836
3.69M
    const char c) noexcept {
10837
3.69M
  return c == '\t' || c == '\n' || c == '\r';
10838
3.69M
}
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
119k
    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
119k
  uint64_t half_length = uint64_t(input.size()) / 2;
10850
119k
  if (half_length - 1 > 2) {
10851
63.3k
    return false;
10852
63.3k
  }
10853
  // We have a string of length 2, 4 or 6.
10854
  // We now check the first character:
10855
55.6k
  if ((input[0] != '.') && (input[0] != '%')) {
10856
9.81k
    return false;
10857
9.81k
  }
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
12.1k
    return false;
10863
12.1k
  }
10864
  // We almost never get here.
10865
  // Optimizing the rest is relatively unimportant.
10866
33.7k
  auto prefix_equal_unsafe = [](std::string_view a, std::string_view b) {
10867
33.7k
    uint16_t A, B;
10868
33.7k
    memcpy(&A, a.data(), sizeof(A));
10869
33.7k
    memcpy(&B, b.data(), sizeof(B));
10870
33.7k
    return A == B;
10871
33.7k
  };
10872
33.7k
  if (!prefix_equal_unsafe(input, target)) {
10873
2.38k
    return false;
10874
2.38k
  }
10875
39.5k
  for (size_t i = 2; i < input.size(); i++) {
10876
12.8k
    char c = input[i];
10877
12.8k
    if ((uint8_t((c | 0x20) - 0x61) <= 25 ? (c | 0x20) : c) != target[i]) {
10878
4.72k
      return false;
10879
4.72k
    }
10880
12.8k
  }
10881
26.6k
  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
184k
    std::string_view input) noexcept {
10894
184k
  return input == "." || input == "%2e" || input == "%2E";
10895
184k
}
10896
10897
28.3k
ada_really_inline constexpr bool is_lowercase_hex(const char c) noexcept {
10898
28.3k
  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
10899
28.3k
}
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
30.1k
unsigned constexpr convert_hex_to_binary(const char c) noexcept {
10906
30.1k
  return hex_to_binary_table[c - '0'];
10907
30.1k
}
10908
10909
1.15k
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.15k
  if (first_percent == std::string_view::npos) {
10913
0
    return std::string(input);
10914
0
  }
10915
1.15k
  std::string dest;
10916
1.15k
  dest.reserve(input.length());
10917
1.15k
  dest.append(input.substr(0, first_percent));
10918
1.15k
  const char* pointer = input.data() + first_percent;
10919
1.15k
  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
31.3k
  while (pointer < end) {
10923
30.1k
    const char ch = pointer[0];
10924
30.1k
    size_t remaining = end - pointer - 1;
10925
30.1k
    if (ch != '%' || remaining < 2 ||
10926
15.3k
        (  // ch == '%' && // It is unnecessary to check that ch == '%'.
10927
15.3k
            (!is_ascii_hex_digit(pointer[1]) ||
10928
16.1k
             !is_ascii_hex_digit(pointer[2])))) {
10929
16.1k
      dest += ch;
10930
16.1k
      pointer++;
10931
16.1k
    } else {
10932
14.0k
      unsigned a = convert_hex_to_binary(pointer[1]);
10933
14.0k
      unsigned b = convert_hex_to_binary(pointer[2]);
10934
14.0k
      char c = static_cast<char>(a * 16 + b);
10935
14.0k
      dest += c;
10936
14.0k
      pointer += 3;
10937
14.0k
    }
10938
30.1k
  }
10939
1.15k
  return dest;
10940
1.15k
}
10941
10942
std::string percent_encode(const std::string_view input,
10943
56.2k
                           const uint8_t character_set[]) {
10944
370k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10945
370k
    return character_sets::bit_at(character_set, c);
10946
370k
  });
10947
  // Optimization: Don't iterate if percent encode is not required
10948
56.2k
  if (pointer == input.end()) {
10949
23.8k
    return std::string(input);
10950
23.8k
  }
10951
10952
32.4k
  std::string result;
10953
32.4k
  result.reserve(input.length());  // in the worst case, percent encoding might
10954
                                   // produce 3 characters.
10955
32.4k
  result.append(input.substr(0, std::distance(input.begin(), pointer)));
10956
10957
989k
  for (; pointer != input.end(); pointer++) {
10958
957k
    if (character_sets::bit_at(character_set, *pointer)) {
10959
744k
      result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10960
744k
    } else {
10961
212k
      result += *pointer;
10962
212k
    }
10963
957k
  }
10964
10965
32.4k
  return result;
10966
56.2k
}
10967
10968
template <bool append>
10969
bool percent_encode(const std::string_view input, const uint8_t character_set[],
10970
91.7k
                    std::string& out) {
10971
91.7k
  ada_log("percent_encode ", input, " to output string while ",
10972
91.7k
          append ? "appending" : "overwriting");
10973
372k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10974
372k
    return character_sets::bit_at(character_set, c);
10975
372k
  });
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
144k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10974
144k
    return character_sets::bit_at(character_set, c);
10975
144k
  });
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
228k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10974
228k
    return character_sets::bit_at(character_set, c);
10975
228k
  });
10976
91.7k
  ada_log("percent_encode done checking, moved to ",
10977
91.7k
          std::distance(input.begin(), pointer));
10978
10979
  // Optimization: Don't iterate if percent encode is not required
10980
91.7k
  if (pointer == input.end()) {
10981
48.3k
    ada_log("percent_encode encoding not needed.");
10982
48.3k
    return false;
10983
48.3k
  }
10984
43.4k
  if constexpr (!append) {
10985
32.9k
    out.clear();
10986
32.9k
  }
10987
43.4k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10988
43.4k
          " bytes");
10989
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10990
43.4k
  out.append(input.data(), std::distance(input.begin(), pointer));
10991
43.4k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10992
43.4k
          " bytes");
10993
957k
  for (; pointer != input.end(); pointer++) {
10994
913k
    if (character_sets::bit_at(character_set, *pointer)) {
10995
731k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10996
731k
    } else {
10997
181k
      out += *pointer;
10998
181k
    }
10999
913k
  }
11000
43.4k
  return true;
11001
91.7k
}
bool ada::unicode::percent_encode<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Line
Count
Source
10970
73.1k
                    std::string& out) {
10971
73.1k
  ada_log("percent_encode ", input, " to output string while ",
10972
73.1k
          append ? "appending" : "overwriting");
10973
73.1k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10974
73.1k
    return character_sets::bit_at(character_set, c);
10975
73.1k
  });
10976
73.1k
  ada_log("percent_encode done checking, moved to ",
10977
73.1k
          std::distance(input.begin(), pointer));
10978
10979
  // Optimization: Don't iterate if percent encode is not required
10980
73.1k
  if (pointer == input.end()) {
10981
40.1k
    ada_log("percent_encode encoding not needed.");
10982
40.1k
    return false;
10983
40.1k
  }
10984
32.9k
  if constexpr (!append) {
10985
32.9k
    out.clear();
10986
32.9k
  }
10987
32.9k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10988
32.9k
          " bytes");
10989
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10990
32.9k
  out.append(input.data(), std::distance(input.begin(), pointer));
10991
32.9k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10992
32.9k
          " bytes");
10993
570k
  for (; pointer != input.end(); pointer++) {
10994
537k
    if (character_sets::bit_at(character_set, *pointer)) {
10995
449k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10996
449k
    } else {
10997
87.7k
      out += *pointer;
10998
87.7k
    }
10999
537k
  }
11000
32.9k
  return true;
11001
73.1k
}
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
18.5k
                    std::string& out) {
10971
18.5k
  ada_log("percent_encode ", input, " to output string while ",
10972
18.5k
          append ? "appending" : "overwriting");
10973
18.5k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10974
18.5k
    return character_sets::bit_at(character_set, c);
10975
18.5k
  });
10976
18.5k
  ada_log("percent_encode done checking, moved to ",
10977
18.5k
          std::distance(input.begin(), pointer));
10978
10979
  // Optimization: Don't iterate if percent encode is not required
10980
18.5k
  if (pointer == input.end()) {
10981
8.10k
    ada_log("percent_encode encoding not needed.");
10982
8.10k
    return false;
10983
8.10k
  }
10984
  if constexpr (!append) {
10985
    out.clear();
10986
  }
10987
10.4k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10988
10.4k
          " bytes");
10989
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10990
10.4k
  out.append(input.data(), std::distance(input.begin(), pointer));
10991
10.4k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10992
10.4k
          " bytes");
10993
386k
  for (; pointer != input.end(); pointer++) {
10994
376k
    if (character_sets::bit_at(character_set, *pointer)) {
10995
282k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10996
282k
    } else {
10997
94.1k
      out += *pointer;
10998
94.1k
    }
10999
376k
  }
11000
10.4k
  return true;
11001
18.5k
}
11002
11003
bool to_ascii(std::optional<std::string>& out, const std::string_view plain,
11004
17.3k
              size_t first_percent) {
11005
17.3k
  std::string percent_decoded_buffer;
11006
17.3k
  std::string_view input = plain;
11007
17.3k
  if (first_percent != std::string_view::npos) {
11008
1.15k
    percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
11009
1.15k
    input = percent_decoded_buffer;
11010
1.15k
  }
11011
  // input is a non-empty UTF-8 string, must be percent decoded
11012
17.3k
  std::string idna_ascii = ada::idna::to_ascii(input);
11013
17.3k
  if (idna_ascii.empty() || contains_forbidden_domain_code_point(
11014
12.3k
                                idna_ascii.data(), idna_ascii.size())) {
11015
9.04k
    return false;
11016
9.04k
  }
11017
8.27k
  out = std::move(idna_ascii);
11018
8.27k
  return true;
11019
17.3k
}
11020
11021
std::string percent_encode(const std::string_view input,
11022
14.4k
                           const uint8_t character_set[], size_t index) {
11023
14.4k
  std::string out;
11024
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
11025
14.4k
  out.append(input.data(), index);
11026
14.4k
  auto pointer = input.begin() + index;
11027
467k
  for (; pointer != input.end(); pointer++) {
11028
453k
    if (character_sets::bit_at(character_set, *pointer)) {
11029
345k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
11030
345k
    } else {
11031
107k
      out += *pointer;
11032
107k
    }
11033
453k
  }
11034
14.4k
  return out;
11035
14.4k
}
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
264
    size_t& compress_length) noexcept {
11049
828
  for (size_t i = 0; i < 8; i++) {
11050
678
    if (address[i] == 0) {
11051
320
      size_t next = i + 1;
11052
1.65k
      while (next != 8 && address[next] == 0) ++next;
11053
320
      const size_t count = next - i;
11054
320
      if (compress_length < count) {
11055
252
        compress_length = count;
11056
252
        compress = i;
11057
252
        if (next == 8) break;
11058
138
        i = next;
11059
138
      }
11060
320
    }
11061
678
  }
11062
264
}
11063
11064
264
std::string ipv6(const std::array<uint16_t, 8>& address) {
11065
264
  size_t compress_length = 0;  // The length of a long sequence of zeros.
11066
264
  size_t compress = 0;         // The start of a long sequence of zeros.
11067
264
  find_longest_sequence_of_ipv6_pieces(address, compress, compress_length);
11068
11069
264
  if (compress_length <= 1) {
11070
    // Optimization opportunity: Find a faster way then snprintf for imploding
11071
    // and return here.
11072
28
    compress = compress_length = 8;
11073
28
  }
11074
11075
264
  std::string output(4 * 8 + 7 + 2, '\0');
11076
264
  size_t piece_index = 0;
11077
264
  char* point = output.data();
11078
264
  char* point_end = output.data() + output.size();
11079
264
  *point++ = '[';
11080
694
  while (true) {
11081
694
    if (piece_index == compress) {
11082
236
      *point++ = ':';
11083
      // If we skip a value initially, we need to write '::', otherwise
11084
      // a single ':' will do since it follows a previous ':'.
11085
236
      if (piece_index == 0) {
11086
136
        *point++ = ':';
11087
136
      }
11088
236
      piece_index += compress_length;
11089
236
      if (piece_index == 8) {
11090
114
        break;
11091
114
      }
11092
236
    }
11093
580
    point = std::to_chars(point, point_end, address[piece_index], 16).ptr;
11094
580
    piece_index++;
11095
580
    if (piece_index == 8) {
11096
150
      break;
11097
150
    }
11098
430
    *point++ = ':';
11099
430
  }
11100
264
  *point++ = ']';
11101
264
  output.resize(point - output.data());
11102
264
  return output;
11103
264
}
11104
11105
3.17k
std::string ipv4(const uint64_t address) {
11106
3.17k
  std::string output(15, '\0');
11107
3.17k
  char* point = output.data();
11108
3.17k
  char* point_end = output.data() + output.size();
11109
3.17k
  point = std::to_chars(point, point_end, uint8_t(address >> 24)).ptr;
11110
12.6k
  for (int i = 2; i >= 0; i--) {
11111
9.52k
    *point++ = '.';
11112
9.52k
    point = std::to_chars(point, point_end, uint8_t(address >> (i * 8))).ptr;
11113
9.52k
  }
11114
3.17k
  output.resize(point - output.data());
11115
3.17k
  return output;
11116
3.17k
}
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
43.0k
    std::string_view input, const result_type* base_url) {
11130
43.0k
  result_type u =
11131
43.0k
      ada::parser::parse_url_impl<result_type, true>(input, base_url);
11132
43.0k
  if (!u.is_valid) {
11133
12.2k
    return tl::unexpected(errors::type_error);
11134
12.2k
  }
11135
30.8k
  return u;
11136
43.0k
}
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
21.5k
    std::string_view input, const result_type* base_url) {
11130
21.5k
  result_type u =
11131
21.5k
      ada::parser::parse_url_impl<result_type, true>(input, base_url);
11132
21.5k
  if (!u.is_valid) {
11133
6.04k
    return tl::unexpected(errors::type_error);
11134
6.04k
  }
11135
15.4k
  return u;
11136
21.5k
}
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
21.5k
    std::string_view input, const result_type* base_url) {
11130
21.5k
  result_type u =
11131
21.5k
      ada::parser::parse_url_impl<result_type, true>(input, base_url);
11132
21.5k
  if (!u.is_valid) {
11133
6.17k
    return tl::unexpected(errors::type_error);
11134
6.17k
  }
11135
15.3k
  return u;
11136
21.5k
}
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
9.00k
std::string href_from_file(std::string_view input) {
11144
  // This is going to be much faster than constructing a URL.
11145
9.00k
  std::string tmp_buffer;
11146
9.00k
  std::string_view internal_input;
11147
9.00k
  if (unicode::has_tabs_or_newline(input)) {
11148
157
    tmp_buffer = input;
11149
157
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
11150
157
    internal_input = tmp_buffer;
11151
8.84k
  } else {
11152
8.84k
    internal_input = input;
11153
8.84k
  }
11154
9.00k
  std::string path;
11155
9.00k
  if (internal_input.empty()) {
11156
34
    path = "/";
11157
8.96k
  } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
11158
713
    helpers::parse_prepared_path(internal_input.substr(1),
11159
713
                                 ada::scheme::type::FILE, path);
11160
8.25k
  } else {
11161
8.25k
    helpers::parse_prepared_path(internal_input, ada::scheme::type::FILE, path);
11162
8.25k
  }
11163
9.00k
  return "file://" + path;
11164
9.00k
}
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
98.9k
void encode_json(std::string_view view, out_iter out) {
11214
  // trivial implementation. could be faster.
11215
98.9k
  const char* hexvalues =
11216
98.9k
      "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
11217
7.57M
  for (uint8_t c : view) {
11218
7.57M
    if (c == '\\') {
11219
3.09k
      *out++ = '\\';
11220
3.09k
      *out++ = '\\';
11221
7.56M
    } else if (c == '"') {
11222
703
      *out++ = '\\';
11223
703
      *out++ = '"';
11224
7.56M
    } 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.56M
    } else {
11232
7.56M
      *out++ = c;
11233
7.56M
    }
11234
7.57M
  }
11235
98.9k
}
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
43.0k
    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
43.0k
  size_t location_of_first = input.find('#');
11289
43.0k
  if (location_of_first == std::string_view::npos) {
11290
42.4k
    return std::nullopt;
11291
42.4k
  }
11292
638
  std::string_view hash = input;
11293
638
  hash.remove_prefix(location_of_first + 1);
11294
638
  input.remove_suffix(input.size() - location_of_first);
11295
638
  return hash;
11296
43.0k
}
11297
11298
26.6k
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.6k
  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.34k
      return false;
11307
3.34k
    }
11308
11.5k
  }
11309
11310
  // Remove path's last item, if any.
11311
23.3k
  size_t last_delimiter = path.rfind('/');
11312
23.3k
  if (last_delimiter != std::string::npos) {
11313
14.3k
    path.erase(last_delimiter);
11314
14.3k
    return true;
11315
14.3k
  }
11316
11317
8.92k
  return false;
11318
23.3k
}
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
113k
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
113k
  std::erase_if(input, ada::unicode::is_ascii_tab_or_newline);
11349
113k
}
11350
11351
ada_really_inline constexpr std::string_view substring(std::string_view input,
11352
27.0k
                                                       size_t pos) {
11353
27.0k
  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
27.0k
  return input.substr(pos);
11357
27.0k
}
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
13.0k
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
13.0k
  return __builtin_ctzl(input_num);
11375
13.0k
#endif  // ADA_REGULAR_VISUAL_STUDIO
11376
13.0k
}
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
60.2k
    std::string_view view, size_t location) noexcept {
11514
  // first check for short strings in which case we do it naively.
11515
60.2k
  if (view.size() - location < 16) {  // slow path
11516
398k
    for (size_t i = location; i < view.size(); i++) {
11517
369k
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11518
356k
          view[i] == '?' || view[i] == '[') {
11519
14.5k
        return i;
11520
14.5k
      }
11521
369k
    }
11522
28.8k
    return size_t(view.size());
11523
43.3k
  }
11524
  // fast path for long strings (expected to be common)
11525
16.8k
  size_t i = location;
11526
16.8k
  const __m128i mask1 = _mm_set1_epi8(':');
11527
16.8k
  const __m128i mask2 = _mm_set1_epi8('/');
11528
16.8k
  const __m128i mask3 = _mm_set1_epi8('\\');
11529
16.8k
  const __m128i mask4 = _mm_set1_epi8('?');
11530
16.8k
  const __m128i mask5 = _mm_set1_epi8('[');
11531
11532
45.3k
  for (; i + 15 < view.size(); i += 16) {
11533
39.6k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11534
39.6k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11535
39.6k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11536
39.6k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11537
39.6k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11538
39.6k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11539
39.6k
    __m128i m = _mm_or_si128(
11540
39.6k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11541
39.6k
    int mask = _mm_movemask_epi8(m);
11542
39.6k
    if (mask != 0) {
11543
11.1k
      return i + trailing_zeroes(mask);
11544
11.1k
    }
11545
39.6k
  }
11546
5.69k
  if (i < view.size()) {
11547
5.10k
    __m128i word =
11548
5.10k
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11549
5.10k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11550
5.10k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11551
5.10k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11552
5.10k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11553
5.10k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11554
5.10k
    __m128i m = _mm_or_si128(
11555
5.10k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11556
5.10k
    int mask = _mm_movemask_epi8(m);
11557
5.10k
    if (mask != 0) {
11558
1.35k
      return view.length() - 16 + trailing_zeroes(mask);
11559
1.35k
    }
11560
5.10k
  }
11561
4.33k
  return size_t(view.length());
11562
5.69k
}
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.27k
                                                  size_t location) noexcept {
11803
  // first check for short strings in which case we do it naively.
11804
1.27k
  if (view.size() - location < 16) {  // slow path
11805
1.70k
    for (size_t i = location; i < view.size(); i++) {
11806
1.35k
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11807
1.22k
          view[i] == '[') {
11808
290
        return i;
11809
290
      }
11810
1.35k
    }
11811
356
    return size_t(view.size());
11812
646
  }
11813
  // fast path for long strings (expected to be common)
11814
628
  size_t i = location;
11815
628
  const __m128i mask1 = _mm_set1_epi8(':');
11816
628
  const __m128i mask2 = _mm_set1_epi8('/');
11817
628
  const __m128i mask4 = _mm_set1_epi8('?');
11818
628
  const __m128i mask5 = _mm_set1_epi8('[');
11819
11820
2.17k
  for (; i + 15 < view.size(); i += 16) {
11821
1.97k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11822
1.97k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11823
1.97k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11824
1.97k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11825
1.97k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11826
1.97k
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
11827
1.97k
    int mask = _mm_movemask_epi8(m);
11828
1.97k
    if (mask != 0) {
11829
432
      return i + trailing_zeroes(mask);
11830
432
    }
11831
1.97k
  }
11832
196
  if (i < view.size()) {
11833
160
    __m128i word =
11834
160
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11835
160
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11836
160
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11837
160
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11838
160
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11839
160
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
11840
160
    int mask = _mm_movemask_epi8(m);
11841
160
    if (mask != 0) {
11842
64
      return view.length() - 16 + trailing_zeroes(mask);
11843
64
    }
11844
160
  }
11845
132
  return size_t(view.length());
11846
196
}
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
57.2k
    const bool is_special, std::string_view& view) noexcept {
11937
  /**
11938
   * The spec at https://url.spec.whatwg.org/#hostname-state expects us to
11939
   * compute a variable called insideBrackets but this variable is only used
11940
   * once, to check whether a ':' character was found outside brackets. Exact
11941
   * text: "Otherwise, if c is U+003A (:) and insideBrackets is false, then:".
11942
   * It is conceptually simpler and arguably more efficient to just return a
11943
   * Boolean indicating whether ':' was found outside brackets.
11944
   */
11945
57.2k
  const size_t view_size = view.size();
11946
57.2k
  size_t location = 0;
11947
57.2k
  bool found_colon = false;
11948
  /**
11949
   * Performance analysis:
11950
   *
11951
   * We are basically seeking the end of the hostname which can be indicated
11952
   * by the end of the view, or by one of the characters ':', '/', '?', '\\'
11953
   * (where '\\' is only applicable for special URLs). However, these must
11954
   * appear outside a bracket range. E.g., if you have [something?]fd: then the
11955
   * '?' does not count.
11956
   *
11957
   * So we can skip ahead to the next delimiter, as long as we include '[' in
11958
   * the set of delimiters, and that we handle it first.
11959
   *
11960
   * So the trick is to have a fast function that locates the next delimiter.
11961
   * Unless we find '[', then it only needs to be called once! Ideally, such a
11962
   * function would be provided by the C++ standard library, but it seems that
11963
   * find_first_of is not very fast, so we are forced to roll our own.
11964
   *
11965
   * We do not break into two loops for speed, but for clarity.
11966
   */
11967
57.2k
  if (is_special) {
11968
    // We move to the next delimiter.
11969
56.4k
    location = find_next_host_delimiter_special(view, location);
11970
    // Unless we find '[' then we are going only going to have to call
11971
    // find_next_host_delimiter_special once.
11972
60.2k
    for (; location < view_size;
11973
56.4k
         location = find_next_host_delimiter_special(view, location)) {
11974
27.0k
      if (view[location] == '[') {
11975
4.09k
        location = view.find(']', location);
11976
4.09k
        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
272
          location = view_size;
11981
272
          break;
11982
272
        }
11983
22.9k
      } else {
11984
22.9k
        found_colon = view[location] == ':';
11985
22.9k
        break;
11986
22.9k
      }
11987
27.0k
    }
11988
56.4k
  } else {
11989
    // We move to the next delimiter.
11990
782
    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.27k
    for (; location < view_size;
11994
786
         location = find_next_host_delimiter(view, location)) {
11995
786
      if (view[location] == '[') {
11996
530
        location = view.find(']', location);
11997
530
        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
530
      } else {
12005
256
        found_colon = view[location] == ':';
12006
256
        break;
12007
256
      }
12008
786
    }
12009
782
  }
12010
  // performance: remove_suffix may translate into a single instruction.
12011
57.2k
  view.remove_suffix(view_size - location);
12012
57.2k
  return {location, found_colon};
12013
57.2k
}
12014
12015
43.0k
void trim_c0_whitespace(std::string_view& input) noexcept {
12016
45.6k
  while (!input.empty() &&
12017
45.5k
         ada::unicode::is_c0_control_or_space(input.front())) {
12018
2.63k
    input.remove_prefix(1);
12019
2.63k
  }
12020
45.8k
  while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
12021
2.83k
    input.remove_suffix(1);
12022
2.83k
  }
12023
43.0k
}
12024
12025
ada_really_inline void parse_prepared_path(std::string_view input,
12026
                                           ada::scheme::type type,
12027
20.5k
                                           std::string& path) {
12028
20.5k
  ada_log("parse_prepared_path ", input);
12029
20.5k
  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
20.5k
  constexpr uint8_t need_encoding = 1;
12035
20.5k
  constexpr uint8_t backslash_char = 2;
12036
20.5k
  constexpr uint8_t dot_char = 4;
12037
20.5k
  constexpr uint8_t percent_char = 8;
12038
20.5k
  bool special = type != ada::scheme::NOT_SPECIAL;
12039
20.5k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
12040
10.5k
                                      checkers::is_windows_drive_letter(input));
12041
20.5k
  bool trivial_path =
12042
20.5k
      (special ? (accumulator == 0)
12043
20.5k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
12044
928
                  0)) &&
12045
4.03k
      (!may_need_slow_file_handling);
12046
20.5k
  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.93k
    if (input[0] != '.') {
12055
3.01k
      size_t slashdot = 0;
12056
3.01k
      bool dot_is_file = true;
12057
13.5k
      for (;;) {
12058
13.5k
        slashdot = input.find("/.", slashdot);
12059
13.5k
        if (slashdot == std::string_view::npos) {  // common case
12060
3.01k
          break;
12061
10.5k
        } else {  // uncommon
12062
          // only three cases matter: /./, /.. or a final /
12063
10.5k
          slashdot += 2;
12064
10.5k
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
12065
1.96k
                           input[slashdot] == '/');
12066
10.5k
        }
12067
13.5k
      }
12068
3.01k
      trivial_path = dot_is_file;
12069
3.01k
    }
12070
3.93k
  }
12071
20.5k
  if (trivial_path) {
12072
5.17k
    ada_log("parse_path trivial");
12073
5.17k
    path += '/';
12074
5.17k
    path += input;
12075
5.17k
    return;
12076
5.17k
  }
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
15.3k
  bool fast_path =
12082
15.3k
      (special &&
12083
14.5k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
12084
2.72k
      (type != ada::scheme::type::FILE);
12085
15.3k
  if (fast_path) {
12086
1.32k
    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.32k
    size_t previous_location = 0;  // We start at 0.
12092
17.0k
    do {
12093
17.0k
      size_t new_location = input.find('/', previous_location);
12094
      // std::string_view path_view = input;
12095
      //  We process the last segment separately:
12096
17.0k
      if (new_location == std::string_view::npos) {
12097
1.32k
        std::string_view path_view = input.substr(previous_location);
12098
1.32k
        if (path_view == "..") {  // The path ends with ..
12099
          // e.g., if you receive ".." with an empty path, you go to "/".
12100
179
          if (path.empty()) {
12101
70
            path = '/';
12102
70
            return;
12103
70
          }
12104
          // Fast case where we have nothing to do:
12105
109
          if (path.back() == '/') {
12106
41
            return;
12107
41
          }
12108
          // If you have the path "/joe/myfriend",
12109
          // then you delete 'myfriend'.
12110
68
          path.resize(path.rfind('/') + 1);
12111
68
          return;
12112
109
        }
12113
1.14k
        path += '/';
12114
1.14k
        if (path_view != ".") {
12115
893
          path.append(path_view);
12116
893
        }
12117
1.14k
        return;
12118
15.7k
      } else {
12119
        // This is a non-final segment.
12120
15.7k
        std::string_view path_view =
12121
15.7k
            input.substr(previous_location, new_location - previous_location);
12122
15.7k
        previous_location = new_location + 1;
12123
15.7k
        if (path_view == "..") {
12124
3.79k
          size_t last_delimiter = path.rfind('/');
12125
3.79k
          if (last_delimiter != std::string::npos) {
12126
1.83k
            path.erase(last_delimiter);
12127
1.83k
          }
12128
11.9k
        } else if (path_view != ".") {
12129
10.2k
          path += '/';
12130
10.2k
          path.append(path_view);
12131
10.2k
        }
12132
15.7k
      }
12133
17.0k
    } while (true);
12134
14.0k
  } else {
12135
14.0k
    ada_log("parse_path slow");
12136
    // we have reached the general case
12137
14.0k
    bool needs_percent_encoding = (accumulator & 1);
12138
14.0k
    std::string path_buffer_tmp;
12139
76.6k
    do {
12140
76.6k
      size_t location = (special && (accumulator & 2))
12141
76.6k
                            ? input.find_first_of("/\\")
12142
76.6k
                            : input.find('/');
12143
76.6k
      std::string_view path_view = input;
12144
76.6k
      if (location != std::string_view::npos) {
12145
62.5k
        path_view.remove_suffix(path_view.size() - location);
12146
62.5k
        input.remove_prefix(location + 1);
12147
62.5k
      }
12148
      // path_buffer is either path_view or it might point at a percent encoded
12149
      // temporary file.
12150
76.6k
      std::string_view path_buffer =
12151
76.6k
          (needs_percent_encoding &&
12152
45.2k
           ada::unicode::percent_encode<false>(
12153
45.2k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
12154
76.6k
              ? path_buffer_tmp
12155
76.6k
              : path_view;
12156
76.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.34k
          path += '/';
12160
1.34k
        }
12161
60.0k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
12162
4.32k
                 (location == std::string_view::npos)) {
12163
399
        path += '/';
12164
399
      }
12165
      // Otherwise, if path_buffer is not a single-dot path segment, then:
12166
59.6k
      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
55.7k
        if (type == ada::scheme::type::FILE && path.empty() &&
12171
12.4k
            checkers::is_windows_drive_letter(path_buffer)) {
12172
801
          path += '/';
12173
801
          path += path_buffer[0];
12174
801
          path += ':';
12175
801
          path_buffer.remove_prefix(2);
12176
801
          path.append(path_buffer);
12177
54.9k
        } else {
12178
          // Append path_buffer to url's path.
12179
54.9k
          path += '/';
12180
54.9k
          path.append(path_buffer);
12181
54.9k
        }
12182
55.7k
      }
12183
76.6k
      if (location == std::string_view::npos) {
12184
14.0k
        return;
12185
14.0k
      }
12186
76.6k
    } while (true);
12187
14.0k
  }
12188
15.3k
}
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
16.2k
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
61.8k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12227
60.8k
    if (authority_delimiter_special[(uint8_t)*pos]) {
12228
15.1k
      return pos - view.begin();
12229
15.1k
    }
12230
60.8k
  }
12231
1.05k
  return size_t(view.size());
12232
16.2k
}
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
2.09k
find_authority_delimiter(std::string_view view) noexcept {
12245
  // performance note: we might be able to gain further performance
12246
  // with SIMD instrinsics.
12247
8.07k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12248
7.90k
    if (authority_delimiter[(uint8_t)*pos]) {
12249
1.91k
      return pos - view.begin();
12250
1.91k
    }
12251
7.90k
  }
12252
178
  return size_t(view.size());
12253
2.09k
}
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
268
bool url::parse_opaque_host(std::string_view input) {
12276
268
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
12277
268
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
12278
28
    return is_valid = false;
12279
28
  }
12280
12281
  // Return the result of running UTF-8 percent-encode on input using the C0
12282
  // control percent-encode set.
12283
240
  host = ada::unicode::percent_encode(
12284
240
      input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
12285
240
  return true;
12286
268
}
12287
12288
2.30k
bool url::parse_ipv4(std::string_view input) {
12289
2.30k
  ada_log("parse_ipv4 ", input, " [", input.size(), " bytes]");
12290
2.30k
  if (input.back() == '.') {
12291
56
    input.remove_suffix(1);
12292
56
  }
12293
2.30k
  size_t digit_count{0};
12294
2.30k
  int pure_decimal_count = 0;  // entries that are decimal
12295
2.30k
  std::string_view original_input =
12296
2.30k
      input;  // we might use this if pure_decimal_count == 4.
12297
2.30k
  uint64_t ipv4{0};
12298
  // we could unroll for better performance?
12299
2.78k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
12300
2.76k
    uint32_t
12301
2.76k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
12302
2.76k
    bool is_hex = checkers::has_hex_prefix(input);
12303
2.76k
    if (is_hex && ((input.length() == 2) ||
12304
887
                   ((input.length() > 2) && (input[2] == '.')))) {
12305
      // special case
12306
56
      segment_result = 0;
12307
56
      input.remove_prefix(2);
12308
2.70k
    } else {
12309
2.70k
      std::from_chars_result r{};
12310
2.70k
      if (is_hex) {
12311
867
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
12312
867
                            segment_result, 16);
12313
1.83k
      } else if ((input.length() >= 2) && input[0] == '0' &&
12314
528
                 checkers::is_digit(input[1])) {
12315
412
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
12316
412
                            segment_result, 8);
12317
1.42k
      } else {
12318
1.42k
        pure_decimal_count++;
12319
1.42k
        r = std::from_chars(input.data(), input.data() + input.size(),
12320
1.42k
                            segment_result, 10);
12321
1.42k
      }
12322
2.70k
      if (r.ec != std::errc()) {
12323
436
        return is_valid = false;
12324
436
      }
12325
2.26k
      input.remove_prefix(r.ptr - input.data());
12326
2.26k
    }
12327
2.32k
    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.64k
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
12332
55
        return is_valid = false;
12333
55
      }
12334
1.58k
      ipv4 <<= (32 - digit_count * 8);
12335
1.58k
      ipv4 |= segment_result;
12336
1.58k
      goto final;
12337
1.64k
    } else {
12338
      // There is more, so that the value must no be larger than 255
12339
      // and we must have a '.'.
12340
681
      if ((segment_result > 255) || (input[0] != '.')) {
12341
206
        return is_valid = false;
12342
206
      }
12343
475
      ipv4 <<= 8;
12344
475
      ipv4 |= segment_result;
12345
475
      input.remove_prefix(1);  // remove '.'
12346
475
    }
12347
2.32k
  }
12348
20
  if ((digit_count != 4) || (!input.empty())) {
12349
20
    return is_valid = false;
12350
20
  }
12351
1.58k
final:
12352
  // We could also check r.ptr to see where the parsing ended.
12353
1.58k
  if (pure_decimal_count == 4) {
12354
4
    host = original_input;  // The original input was already all decimal and we
12355
                            // validated it.
12356
1.58k
  } else {
12357
1.58k
    host = ada::serializers::ipv4(ipv4);  // We have to reserialize the address.
12358
1.58k
  }
12359
1.58k
  host_type = IPV4;
12360
1.58k
  return true;
12361
20
}
12362
12363
420
bool url::parse_ipv6(std::string_view input) {
12364
420
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
12365
12366
420
  if (input.empty()) {
12367
25
    return is_valid = false;
12368
25
  }
12369
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
12370
395
  std::array<uint16_t, 8> address{};
12371
12372
  // Let pieceIndex be 0.
12373
395
  int piece_index = 0;
12374
12375
  // Let compress be null.
12376
395
  std::optional<int> compress{};
12377
12378
  // Let pointer be a pointer for input.
12379
395
  std::string_view::iterator pointer = input.begin();
12380
12381
  // If c is U+003A (:), then:
12382
395
  if (input[0] == ':') {
12383
    // If remaining does not start with U+003A (:), validation error, return
12384
    // failure.
12385
91
    if (input.size() == 1 || input[1] != ':') {
12386
18
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
12387
18
      return is_valid = false;
12388
18
    }
12389
12390
    // Increase pointer by 2.
12391
73
    pointer += 2;
12392
12393
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
12394
73
    compress = ++piece_index;
12395
73
  }
12396
12397
  // While c is not the EOF code point:
12398
907
  while (pointer != input.end()) {
12399
    // If pieceIndex is 8, validation error, return failure.
12400
726
    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
721
    if (*pointer == ':') {
12407
      // If compress is non-null, validation error, return failure.
12408
66
      if (compress.has_value()) {
12409
5
        ada_log("parse_ipv6 compress is non-null");
12410
5
        return is_valid = false;
12411
5
      }
12412
12413
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
12414
      // then continue.
12415
61
      pointer++;
12416
61
      compress = ++piece_index;
12417
61
      continue;
12418
66
    }
12419
12420
    // Let value and length be 0.
12421
655
    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.68k
    while (length < 4 && pointer != input.end() &&
12427
1.49k
           unicode::is_ascii_hex_digit(*pointer)) {
12428
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12429
1.03k
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
12430
1.03k
      pointer++;
12431
1.03k
      length++;
12432
1.03k
    }
12433
12434
    // If c is U+002E (.), then:
12435
655
    if (pointer != input.end() && *pointer == '.') {
12436
      // If length is 0, validation error, return failure.
12437
78
      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
75
      pointer -= length;
12444
12445
      // If pieceIndex is greater than 6, validation error, return failure.
12446
75
      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
72
      int numbers_seen = 0;
12453
12454
      // While c is not the EOF code point:
12455
174
      while (pointer != input.end()) {
12456
        // Let ipv4Piece be null.
12457
158
        std::optional<uint16_t> ipv4_piece{};
12458
12459
        // If numbersSeen is greater than 0, then:
12460
158
        if (numbers_seen > 0) {
12461
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
12462
          // pointer by 1.
12463
86
          if (*pointer == '.' && numbers_seen < 4) {
12464
76
            pointer++;
12465
76
          }
12466
          // Otherwise, validation error, return failure.
12467
10
          else {
12468
10
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
12469
10
            return is_valid = false;
12470
10
          }
12471
86
        }
12472
12473
        // If c is not an ASCII digit, validation error, return failure.
12474
148
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
12475
29
          ada_log(
12476
29
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
12477
29
              "failure");
12478
29
          return is_valid = false;
12479
29
        }
12480
12481
        // While c is an ASCII digit:
12482
316
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
12483
          // Let number be c interpreted as decimal number.
12484
214
          int number = *pointer - '0';
12485
12486
          // If ipv4Piece is null, then set ipv4Piece to number.
12487
214
          if (!ipv4_piece.has_value()) {
12488
119
            ipv4_piece = number;
12489
119
          }
12490
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
12491
95
          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
92
          else {
12497
92
            ipv4_piece = *ipv4_piece * 10 + number;
12498
92
          }
12499
12500
          // If ipv4Piece is greater than 255, validation error, return failure.
12501
211
          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
197
          pointer++;
12508
197
        }
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
102
        address[piece_index] =
12514
102
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
12515
12516
        // Increase numbersSeen by 1.
12517
102
        numbers_seen++;
12518
12519
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
12520
102
        if (numbers_seen == 2 || numbers_seen == 4) {
12521
36
          piece_index++;
12522
36
        }
12523
102
      }
12524
12525
      // If numbersSeen is not 4, validation error, return failure.
12526
16
      if (numbers_seen != 4) {
12527
13
        return is_valid = false;
12528
13
      }
12529
12530
      // Break.
12531
3
      break;
12532
16
    }
12533
    // Otherwise, if c is U+003A (:):
12534
577
    else if ((pointer != input.end()) && (*pointer == ':')) {
12535
      // Increase pointer by 1.
12536
347
      pointer++;
12537
12538
      // If c is the EOF code point, validation error, return failure.
12539
347
      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
347
    }
12546
    // Otherwise, if c is not the EOF code point, validation error, return
12547
    // failure.
12548
230
    else if (pointer != input.end()) {
12549
105
      ada_log(
12550
105
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
12551
105
          "error, return failure");
12552
105
      return is_valid = false;
12553
105
    }
12554
12555
    // Set address[pieceIndex] to value.
12556
469
    address[piece_index] = value;
12557
12558
    // Increase pieceIndex by 1.
12559
469
    piece_index++;
12560
469
  }
12561
12562
  // If compress is non-null, then:
12563
184
  if (compress.has_value()) {
12564
    // Let swaps be pieceIndex - compress.
12565
123
    int swaps = piece_index - *compress;
12566
12567
    // Set pieceIndex to 7.
12568
123
    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
249
    while (piece_index != 0 && swaps > 0) {
12574
126
      std::swap(address[piece_index], address[*compress + swaps - 1]);
12575
126
      piece_index--;
12576
126
      swaps--;
12577
126
    }
12578
123
  }
12579
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
12580
  // return failure.
12581
61
  else if (piece_index != 8) {
12582
52
    ada_log(
12583
52
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
12584
52
        "error, return failure");
12585
52
    return is_valid = false;
12586
52
  }
12587
132
  host = ada::serializers::ipv6(address);
12588
132
  ada_log("parse_ipv6 ", *host);
12589
132
  host_type = IPV6;
12590
132
  return true;
12591
184
}
12592
12593
template <bool has_state_override>
12594
20.2k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12595
20.2k
  auto parsed_type = ada::scheme::get_scheme_type(input);
12596
20.2k
  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
20.2k
  if (is_input_special) {  // fast path!!!
12602
13.6k
    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.59k
      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.59k
      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.59k
      if (type == ada::scheme::type::FILE && host.has_value() &&
12619
0
          host.value().empty()) {
12620
0
        return false;
12621
0
      }
12622
1.59k
    }
12623
12624
1.59k
    type = parsed_type;
12625
12626
13.6k
    if constexpr (has_state_override) {
12627
      // This is uncommon.
12628
1.59k
      uint16_t urls_scheme_port = get_special_port();
12629
12630
1.59k
      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
1.05k
        if (port.has_value() && *port == urls_scheme_port) {
12634
0
          port = std::nullopt;
12635
0
        }
12636
1.05k
      }
12637
1.59k
    }
12638
13.6k
  } else {  // slow path
12639
6.59k
    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
6.59k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
12645
12646
6.59k
    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.44k
      if (is_special() != ada::scheme::is_special(_buffer)) {
12651
1.78k
        return true;
12652
1.78k
      }
12653
12654
      // If url includes credentials or has a non-null port, and buffer is
12655
      // "file", then return.
12656
657
      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
657
      if (type == ada::scheme::type::FILE && host.has_value() &&
12663
0
          host.value().empty()) {
12664
0
        return true;
12665
0
      }
12666
657
    }
12667
12668
657
    set_scheme(std::move(_buffer));
12669
12670
6.59k
    if constexpr (has_state_override) {
12671
      // This is uncommon.
12672
2.44k
      uint16_t urls_scheme_port = get_special_port();
12673
12674
2.44k
      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
467
        if (port.has_value() && *port == urls_scheme_port) {
12678
0
          port = std::nullopt;
12679
0
        }
12680
467
      }
12681
2.44k
    }
12682
6.59k
  }
12683
12684
0
  return true;
12685
20.2k
}
bool ada::url::parse_scheme<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
12594
4.03k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12595
4.03k
  auto parsed_type = ada::scheme::get_scheme_type(input);
12596
4.03k
  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
4.03k
  if (is_input_special) {  // fast path!!!
12602
1.59k
    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.59k
      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.59k
      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.59k
      if (type == ada::scheme::type::FILE && host.has_value() &&
12619
0
          host.value().empty()) {
12620
0
        return false;
12621
0
      }
12622
1.59k
    }
12623
12624
1.59k
    type = parsed_type;
12625
12626
1.59k
    if constexpr (has_state_override) {
12627
      // This is uncommon.
12628
1.59k
      uint16_t urls_scheme_port = get_special_port();
12629
12630
1.59k
      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
1.05k
        if (port.has_value() && *port == urls_scheme_port) {
12634
0
          port = std::nullopt;
12635
0
        }
12636
1.05k
      }
12637
1.59k
    }
12638
2.44k
  } else {  // slow path
12639
2.44k
    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.44k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
12645
12646
2.44k
    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.44k
      if (is_special() != ada::scheme::is_special(_buffer)) {
12651
1.78k
        return true;
12652
1.78k
      }
12653
12654
      // If url includes credentials or has a non-null port, and buffer is
12655
      // "file", then return.
12656
657
      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
657
      if (type == ada::scheme::type::FILE && host.has_value() &&
12663
0
          host.value().empty()) {
12664
0
        return true;
12665
0
      }
12666
657
    }
12667
12668
657
    set_scheme(std::move(_buffer));
12669
12670
2.44k
    if constexpr (has_state_override) {
12671
      // This is uncommon.
12672
2.44k
      uint16_t urls_scheme_port = get_special_port();
12673
12674
2.44k
      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
467
        if (port.has_value() && *port == urls_scheme_port) {
12678
0
          port = std::nullopt;
12679
0
        }
12680
467
      }
12681
2.44k
    }
12682
2.44k
  }
12683
12684
0
  return true;
12685
4.03k
}
bool ada::url::parse_scheme<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
12594
16.2k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12595
16.2k
  auto parsed_type = ada::scheme::get_scheme_type(input);
12596
16.2k
  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
16.2k
  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
12.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
12.0k
  } else {  // slow path
12639
4.15k
    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
4.15k
    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
4.15k
    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
4.15k
  }
12683
12684
16.2k
  return true;
12685
16.2k
}
12686
12687
25.3k
ada_really_inline bool url::parse_host(std::string_view input) {
12688
25.3k
  ada_log("parse_host ", input, " [", input.size(), " bytes]");
12689
25.3k
  if (input.empty()) {
12690
9
    return is_valid = false;
12691
9
  }  // technically unnecessary.
12692
  // If input starts with U+005B ([), then:
12693
25.2k
  if (input[0] == '[') {
12694
    // If input does not end with U+005D (]), validation error, return failure.
12695
654
    if (input.back() != ']') {
12696
234
      return is_valid = false;
12697
234
    }
12698
420
    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
420
    input.remove_prefix(1);
12703
420
    input.remove_suffix(1);
12704
420
    return parse_ipv6(input);
12705
654
  }
12706
12707
  // If isNotSpecial is true, then return the result of opaque-host parsing
12708
  // input.
12709
24.6k
  if (!is_special()) {
12710
268
    return parse_opaque_host(input);
12711
268
  }
12712
12713
  // Fast path: try to parse as pure decimal IPv4(a.b.c.d) first.
12714
24.3k
  const uint64_t fast_result = checkers::try_parse_ipv4_fast(input);
12715
24.3k
  if (fast_result < checkers::ipv4_fast_fail) {
12716
    // Fast path succeeded - input is pure decimal IPv4
12717
49
    if (!input.empty() && input.back() == '.') {
12718
19
      host = input.substr(0, input.size() - 1);
12719
30
    } else {
12720
30
      host = input;
12721
30
    }
12722
49
    host_type = IPV4;
12723
49
    ada_log("parse_host fast path decimal ipv4");
12724
49
    return true;
12725
49
  }
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
24.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
24.3k
  unicode::to_lower_ascii(buffer.data(), buffer.size());
12736
24.3k
  bool is_forbidden = unicode::contains_forbidden_domain_code_point(
12737
24.3k
      buffer.data(), buffer.size());
12738
24.3k
  if (is_forbidden == 0 && buffer.find("xn-") == std::string_view::npos) {
12739
    // fast path
12740
16.6k
    host = std::move(buffer);
12741
12742
    // Check for other IPv4 formats (hex, octal, etc.)
12743
16.6k
    if (checkers::is_ipv4(host.value())) {
12744
2.04k
      ada_log("parse_host fast path ipv4");
12745
2.04k
      return parse_ipv4(host.value());
12746
2.04k
    }
12747
14.5k
    ada_log("parse_host fast path ", *host);
12748
14.5k
    return true;
12749
16.6k
  }
12750
7.70k
  ada_log("parse_host calling to_ascii");
12751
7.70k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
12752
7.70k
  if (!is_valid) {
12753
4.41k
    ada_log("parse_host to_ascii returns false");
12754
4.41k
    return is_valid = false;
12755
4.41k
  }
12756
3.29k
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
12757
3.29k
          " bytes]");
12758
12759
3.29k
  if (std::any_of(host.value().begin(), host.value().end(),
12760
3.29k
                  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
3.29k
  if (checkers::is_ipv4(host.value())) {
12768
264
    ada_log("parse_host got ipv4 ", *host);
12769
264
    return parse_ipv4(host.value());
12770
264
  }
12771
12772
3.02k
  return true;
12773
3.29k
}
12774
12775
9.00k
ada_really_inline void url::parse_path(std::string_view input) {
12776
9.00k
  ada_log("parse_path ", input);
12777
9.00k
  std::string tmp_buffer;
12778
9.00k
  std::string_view internal_input;
12779
9.00k
  if (unicode::has_tabs_or_newline(input)) {
12780
157
    tmp_buffer = input;
12781
    // Optimization opportunity: Instead of copying and then pruning, we could
12782
    // just directly build the string from user_input.
12783
157
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12784
157
    internal_input = tmp_buffer;
12785
8.84k
  } else {
12786
8.84k
    internal_input = input;
12787
8.84k
  }
12788
12789
  // If url is special, then:
12790
9.00k
  if (is_special()) {
12791
9.00k
    if (internal_input.empty()) {
12792
34
      path = "/";
12793
8.96k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
12794
713
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
12795
8.25k
    } else {
12796
8.25k
      helpers::parse_prepared_path(internal_input, type, path);
12797
8.25k
    }
12798
9.00k
  } 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
9.00k
}
12810
12811
9.00k
[[nodiscard]] std::string url::to_string() const {
12812
9.00k
  if (!is_valid) {
12813
2.38k
    return "null";
12814
2.38k
  }
12815
6.61k
  std::string answer;
12816
6.61k
  auto back = std::back_insert_iterator(answer);
12817
6.61k
  answer.append("{\n");
12818
6.61k
  answer.append("\t\"protocol\":\"");
12819
6.61k
  helpers::encode_json(get_protocol(), back);
12820
6.61k
  answer.append("\",\n");
12821
6.61k
  if (has_credentials()) {
12822
6.60k
    answer.append("\t\"username\":\"");
12823
6.60k
    helpers::encode_json(username, back);
12824
6.60k
    answer.append("\",\n");
12825
6.60k
    answer.append("\t\"password\":\"");
12826
6.60k
    helpers::encode_json(password, back);
12827
6.60k
    answer.append("\",\n");
12828
6.60k
  }
12829
6.61k
  if (host.has_value()) {
12830
6.61k
    answer.append("\t\"host\":\"");
12831
6.61k
    helpers::encode_json(host.value(), back);
12832
6.61k
    answer.append("\",\n");
12833
6.61k
  }
12834
6.61k
  if (port.has_value()) {
12835
1.06k
    answer.append("\t\"port\":\"");
12836
1.06k
    answer.append(std::to_string(port.value()));
12837
1.06k
    answer.append("\",\n");
12838
1.06k
  }
12839
6.61k
  answer.append("\t\"path\":\"");
12840
6.61k
  helpers::encode_json(path, back);
12841
6.61k
  answer.append("\",\n");
12842
6.61k
  answer.append("\t\"opaque path\":");
12843
6.61k
  answer.append((has_opaque_path ? "true" : "false"));
12844
6.61k
  if (has_search()) {
12845
6.60k
    answer.append(",\n");
12846
6.60k
    answer.append("\t\"query\":\"");
12847
    // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
12848
6.60k
    helpers::encode_json(query.value(), back);
12849
6.60k
    answer.append("\"");
12850
6.60k
  }
12851
6.61k
  if (hash.has_value()) {
12852
6.60k
    answer.append(",\n");
12853
6.60k
    answer.append("\t\"hash\":\"");
12854
6.60k
    helpers::encode_json(hash.value(), back);
12855
6.60k
    answer.append("\"");
12856
6.60k
  }
12857
6.61k
  answer.append("\n}");
12858
6.61k
  return answer;
12859
9.00k
}
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
12.1k
[[nodiscard]] std::string url::get_origin() const {
12869
12.1k
  if (is_special()) {
12870
    // Return a new opaque origin.
12871
10.8k
    if (type == scheme::FILE) {
12872
1.37k
      return "null";
12873
1.37k
    }
12874
9.44k
    return ada::helpers::concat(get_protocol(), "//", get_host());
12875
10.8k
  }
12876
12877
1.37k
  if (non_special_scheme == "blob") {
12878
481
    if (!path.empty()) {
12879
472
      auto result = ada::parse<ada::url>(path);
12880
472
      if (result &&
12881
236
          (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
20
        return ada::helpers::concat(result->get_protocol(), "//",
12885
20
                                    result->get_host());
12886
20
      }
12887
472
    }
12888
481
  }
12889
12890
  // Return a new opaque origin.
12891
1.35k
  return "null";
12892
1.37k
}
12893
12894
37.4k
[[nodiscard]] std::string url::get_protocol() const {
12895
37.4k
  if (is_special()) {
12896
31.9k
    return helpers::concat(ada::scheme::details::is_special_list[type], ":");
12897
31.9k
  }
12898
  // We only move the 'scheme' if it is non-special.
12899
5.50k
  return helpers::concat(non_special_scheme, ":");
12900
37.4k
}
12901
12902
18.4k
[[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
18.4k
  if (!host.has_value()) {
12908
0
    return "";
12909
0
  }
12910
18.4k
  if (port.has_value()) {
12911
2.19k
    return host.value() + ":" + get_port();
12912
2.19k
  }
12913
16.2k
  return host.value();
12914
18.4k
}
12915
12916
9.00k
[[nodiscard]] std::string url::get_hostname() const {
12917
9.00k
  return host.value_or("");
12918
9.00k
}
12919
12920
9.00k
[[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
9.00k
  return (!query.has_value() || (query.value().empty())) ? ""
12924
9.00k
                                                         : "?" + query.value();
12925
9.00k
}
12926
12927
9.00k
[[nodiscard]] const std::string& url::get_username() const noexcept {
12928
9.00k
  return username;
12929
9.00k
}
12930
12931
9.32k
[[nodiscard]] const std::string& url::get_password() const noexcept {
12932
9.32k
  return password;
12933
9.32k
}
12934
12935
11.4k
[[nodiscard]] std::string url::get_port() const {
12936
11.4k
  return port.has_value() ? std::to_string(port.value()) : "";
12937
11.4k
}
12938
12939
9.00k
[[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
9.00k
  return (!hash.has_value() || (hash.value().empty())) ? ""
12943
9.00k
                                                       : "#" + hash.value();
12944
9.00k
}
12945
12946
template <bool override_hostname>
12947
18.0k
bool url::set_host_or_hostname(const std::string_view input) {
12948
18.0k
  if (has_opaque_path) {
12949
0
    return false;
12950
0
  }
12951
12952
18.0k
  std::optional<std::string> previous_host = host;
12953
18.0k
  std::optional<uint16_t> previous_port = port;
12954
12955
18.0k
  size_t host_end_pos = input.find('#');
12956
18.0k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
12957
18.0k
                                      ? host_end_pos
12958
18.0k
                                      : input.size());
12959
18.0k
  helpers::remove_ascii_tab_or_newline(_host);
12960
18.0k
  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
18.0k
  if (type != ada::scheme::type::FILE) {
12965
16.5k
    std::string_view host_view(_host.data(), _host.length());
12966
16.5k
    auto [location, found_colon] =
12967
16.5k
        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
16.5k
    if (found_colon) {
12973
      // If buffer is the empty string, host-missing validation error, return
12974
      // failure.
12975
7.49k
      std::string_view buffer = host_view.substr(0, location);
12976
7.49k
      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
7.47k
      if constexpr (override_hostname) {
12983
3.73k
        return false;
12984
3.73k
      }
12985
12986
      // Let host be the result of host parsing buffer with url is not special.
12987
0
      bool succeeded = parse_host(buffer);
12988
7.47k
      if (!succeeded) {
12989
383
        host = std::move(previous_host);
12990
383
        update_base_port(previous_port);
12991
383
        return false;
12992
383
      }
12993
12994
      // Set url's host to host, buffer to the empty string, and state to port
12995
      // state.
12996
7.08k
      std::string_view port_buffer = new_host.substr(location + 1);
12997
7.08k
      if (!port_buffer.empty()) {
12998
2.89k
        set_port(port_buffer);
12999
2.89k
      }
13000
7.08k
      return true;
13001
7.47k
    }
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
9.03k
    else {
13006
      // If url is special and host_view is the empty string, host-missing
13007
      // validation error, return failure.
13008
9.03k
      if (host_view.empty() && is_special()) {
13009
1.55k
        return false;
13010
1.55k
      }
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
7.47k
      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
7.47k
      if (host_view.empty() && !is_special()) {
13022
0
        host = "";
13023
0
        return true;
13024
0
      }
13025
13026
7.47k
      bool succeeded = parse_host(host_view);
13027
7.47k
      if (!succeeded) {
13028
3.33k
        host = std::move(previous_host);
13029
3.33k
        update_base_port(previous_port);
13030
3.33k
        return false;
13031
3.33k
      }
13032
4.14k
      return true;
13033
7.47k
    }
13034
16.5k
  }
13035
13036
1.47k
  size_t location = new_host.find_first_of("/\\?");
13037
1.47k
  if (location != std::string_view::npos) {
13038
1.34k
    new_host.remove_suffix(new_host.length() - location);
13039
1.34k
  }
13040
13041
1.47k
  if (new_host.empty()) {
13042
    // Set url's host to the empty string.
13043
0
    host = "";
13044
1.47k
  } else {
13045
    // Let host be the result of host parsing buffer with url is not special.
13046
1.47k
    if (!parse_host(new_host)) {
13047
1.46k
      host = std::move(previous_host);
13048
1.46k
      update_base_port(previous_port);
13049
1.46k
      return false;
13050
1.46k
    }
13051
13052
    // If host is "localhost", then set host to the empty string.
13053
6
    if (host == "localhost") {
13054
0
      host = "";
13055
0
    }
13056
6
  }
13057
6
  return true;
13058
1.47k
}
bool ada::url::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
12947
9.00k
bool url::set_host_or_hostname(const std::string_view input) {
12948
9.00k
  if (has_opaque_path) {
12949
0
    return false;
12950
0
  }
12951
12952
9.00k
  std::optional<std::string> previous_host = host;
12953
9.00k
  std::optional<uint16_t> previous_port = port;
12954
12955
9.00k
  size_t host_end_pos = input.find('#');
12956
9.00k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
12957
9.00k
                                      ? host_end_pos
12958
9.00k
                                      : input.size());
12959
9.00k
  helpers::remove_ascii_tab_or_newline(_host);
12960
9.00k
  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
9.00k
  if (type != ada::scheme::type::FILE) {
12965
8.26k
    std::string_view host_view(_host.data(), _host.length());
12966
8.26k
    auto [location, found_colon] =
12967
8.26k
        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
8.26k
    if (found_colon) {
12973
      // If buffer is the empty string, host-missing validation error, return
12974
      // failure.
12975
3.74k
      std::string_view buffer = host_view.substr(0, location);
12976
3.74k
      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.73k
      bool succeeded = parse_host(buffer);
12988
3.73k
      if (!succeeded) {
12989
383
        host = std::move(previous_host);
12990
383
        update_base_port(previous_port);
12991
383
        return false;
12992
383
      }
12993
12994
      // Set url's host to host, buffer to the empty string, and state to port
12995
      // state.
12996
3.35k
      std::string_view port_buffer = new_host.substr(location + 1);
12997
3.35k
      if (!port_buffer.empty()) {
12998
2.89k
        set_port(port_buffer);
12999
2.89k
      }
13000
3.35k
      return true;
13001
3.73k
    }
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.51k
    else {
13006
      // If url is special and host_view is the empty string, host-missing
13007
      // validation error, return failure.
13008
4.51k
      if (host_view.empty() && is_special()) {
13009
779
        return false;
13010
779
      }
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.73k
      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.73k
      if (host_view.empty() && !is_special()) {
13022
0
        host = "";
13023
0
        return true;
13024
0
      }
13025
13026
3.73k
      bool succeeded = parse_host(host_view);
13027
3.73k
      if (!succeeded) {
13028
1.66k
        host = std::move(previous_host);
13029
1.66k
        update_base_port(previous_port);
13030
1.66k
        return false;
13031
1.66k
      }
13032
2.07k
      return true;
13033
3.73k
    }
13034
8.26k
  }
13035
13036
736
  size_t location = new_host.find_first_of("/\\?");
13037
736
  if (location != std::string_view::npos) {
13038
673
    new_host.remove_suffix(new_host.length() - location);
13039
673
  }
13040
13041
736
  if (new_host.empty()) {
13042
    // Set url's host to the empty string.
13043
0
    host = "";
13044
736
  } else {
13045
    // Let host be the result of host parsing buffer with url is not special.
13046
736
    if (!parse_host(new_host)) {
13047
733
      host = std::move(previous_host);
13048
733
      update_base_port(previous_port);
13049
733
      return false;
13050
733
    }
13051
13052
    // If host is "localhost", then set host to the empty string.
13053
3
    if (host == "localhost") {
13054
0
      host = "";
13055
0
    }
13056
3
  }
13057
3
  return true;
13058
736
}
bool ada::url::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
12947
9.00k
bool url::set_host_or_hostname(const std::string_view input) {
12948
9.00k
  if (has_opaque_path) {
12949
0
    return false;
12950
0
  }
12951
12952
9.00k
  std::optional<std::string> previous_host = host;
12953
9.00k
  std::optional<uint16_t> previous_port = port;
12954
12955
9.00k
  size_t host_end_pos = input.find('#');
12956
9.00k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
12957
9.00k
                                      ? host_end_pos
12958
9.00k
                                      : input.size());
12959
9.00k
  helpers::remove_ascii_tab_or_newline(_host);
12960
9.00k
  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
9.00k
  if (type != ada::scheme::type::FILE) {
12965
8.26k
    std::string_view host_view(_host.data(), _host.length());
12966
8.26k
    auto [location, found_colon] =
12967
8.26k
        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
8.26k
    if (found_colon) {
12973
      // If buffer is the empty string, host-missing validation error, return
12974
      // failure.
12975
3.74k
      std::string_view buffer = host_view.substr(0, location);
12976
3.74k
      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.73k
      if constexpr (override_hostname) {
12983
3.73k
        return false;
12984
3.73k
      }
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.73k
      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.73k
      std::string_view port_buffer = new_host.substr(location + 1);
12997
3.73k
      if (!port_buffer.empty()) {
12998
0
        set_port(port_buffer);
12999
0
      }
13000
3.73k
      return true;
13001
3.73k
    }
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.51k
    else {
13006
      // If url is special and host_view is the empty string, host-missing
13007
      // validation error, return failure.
13008
4.51k
      if (host_view.empty() && is_special()) {
13009
779
        return false;
13010
779
      }
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.73k
      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.73k
      if (host_view.empty() && !is_special()) {
13022
0
        host = "";
13023
0
        return true;
13024
0
      }
13025
13026
3.73k
      bool succeeded = parse_host(host_view);
13027
3.73k
      if (!succeeded) {
13028
1.66k
        host = std::move(previous_host);
13029
1.66k
        update_base_port(previous_port);
13030
1.66k
        return false;
13031
1.66k
      }
13032
2.07k
      return true;
13033
3.73k
    }
13034
8.26k
  }
13035
13036
736
  size_t location = new_host.find_first_of("/\\?");
13037
736
  if (location != std::string_view::npos) {
13038
673
    new_host.remove_suffix(new_host.length() - location);
13039
673
  }
13040
13041
736
  if (new_host.empty()) {
13042
    // Set url's host to the empty string.
13043
0
    host = "";
13044
736
  } else {
13045
    // Let host be the result of host parsing buffer with url is not special.
13046
736
    if (!parse_host(new_host)) {
13047
733
      host = std::move(previous_host);
13048
733
      update_base_port(previous_port);
13049
733
      return false;
13050
733
    }
13051
13052
    // If host is "localhost", then set host to the empty string.
13053
3
    if (host == "localhost") {
13054
0
      host = "";
13055
0
    }
13056
3
  }
13057
3
  return true;
13058
736
}
13059
13060
9.00k
bool url::set_host(const std::string_view input) {
13061
9.00k
  return set_host_or_hostname<false>(input);
13062
9.00k
}
13063
13064
9.00k
bool url::set_hostname(const std::string_view input) {
13065
9.00k
  return set_host_or_hostname<true>(input);
13066
9.00k
}
13067
13068
9.00k
bool url::set_username(const std::string_view input) {
13069
9.00k
  if (cannot_have_credentials_or_port()) {
13070
736
    return false;
13071
736
  }
13072
8.26k
  username = ada::unicode::percent_encode(
13073
8.26k
      input, character_sets::USERINFO_PERCENT_ENCODE);
13074
8.26k
  return true;
13075
9.00k
}
13076
13077
9.00k
bool url::set_password(const std::string_view input) {
13078
9.00k
  if (cannot_have_credentials_or_port()) {
13079
736
    return false;
13080
736
  }
13081
8.26k
  password = ada::unicode::percent_encode(
13082
8.26k
      input, character_sets::USERINFO_PERCENT_ENCODE);
13083
8.26k
  return true;
13084
9.00k
}
13085
13086
11.8k
bool url::set_port(const std::string_view input) {
13087
11.8k
  if (cannot_have_credentials_or_port()) {
13088
736
    return false;
13089
736
  }
13090
13091
11.1k
  if (input.empty()) {
13092
2
    port = std::nullopt;
13093
2
    return true;
13094
2
  }
13095
13096
11.1k
  std::string trimmed(input);
13097
11.1k
  helpers::remove_ascii_tab_or_newline(trimmed);
13098
13099
11.1k
  if (trimmed.empty()) {
13100
32
    return true;
13101
32
  }
13102
13103
  // Input should not start with a non-digit character.
13104
11.1k
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
13105
9.42k
    return false;
13106
9.42k
  }
13107
13108
  // Find the first non-digit character to determine the length of digits
13109
1.70k
  auto first_non_digit =
13110
1.70k
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
13111
1.70k
  std::string_view digits_to_parse =
13112
1.70k
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
13113
13114
  // Revert changes if parse_port fails.
13115
1.70k
  std::optional<uint16_t> previous_port = port;
13116
1.70k
  parse_port(digits_to_parse);
13117
1.70k
  if (is_valid) {
13118
1.19k
    return true;
13119
1.19k
  }
13120
511
  port = std::move(previous_port);
13121
511
  is_valid = true;
13122
511
  return false;
13123
1.70k
}
13124
13125
9.00k
void url::set_hash(const std::string_view input) {
13126
9.00k
  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.99k
  std::string new_value;
13133
8.99k
  new_value = input[0] == '#' ? input.substr(1) : input;
13134
8.99k
  helpers::remove_ascii_tab_or_newline(new_value);
13135
8.99k
  hash = unicode::percent_encode(new_value,
13136
8.99k
                                 ada::character_sets::FRAGMENT_PERCENT_ENCODE);
13137
8.99k
}
13138
13139
9.00k
void url::set_search(const std::string_view input) {
13140
9.00k
  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.99k
  std::string new_value;
13147
8.99k
  new_value = input[0] == '?' ? input.substr(1) : input;
13148
8.99k
  helpers::remove_ascii_tab_or_newline(new_value);
13149
13150
8.99k
  auto query_percent_encode_set =
13151
8.99k
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13152
8.99k
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
13153
13154
8.99k
  query = ada::unicode::percent_encode(new_value, query_percent_encode_set);
13155
8.99k
}
13156
13157
9.00k
bool url::set_pathname(const std::string_view input) {
13158
9.00k
  if (has_opaque_path) {
13159
0
    return false;
13160
0
  }
13161
9.00k
  path.clear();
13162
9.00k
  parse_path(input);
13163
9.00k
  return true;
13164
9.00k
}
13165
13166
9.00k
bool url::set_protocol(const std::string_view input) {
13167
9.00k
  std::string view(input);
13168
9.00k
  helpers::remove_ascii_tab_or_newline(view);
13169
9.00k
  if (view.empty()) {
13170
34
    return true;
13171
34
  }
13172
13173
  // Schemes should start with alpha values.
13174
8.96k
  if (!checkers::is_alpha(view[0])) {
13175
4.33k
    return false;
13176
4.33k
  }
13177
13178
4.63k
  view.append(":");
13179
13180
4.63k
  std::string::iterator pointer =
13181
4.63k
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
13182
13183
4.63k
  if (pointer != view.end() && *pointer == ':') {
13184
4.03k
    return parse_scheme<true>(
13185
4.03k
        std::string_view(view.data(), pointer - view.begin()));
13186
4.03k
  }
13187
597
  return false;
13188
4.63k
}
13189
13190
3.05k
bool url::set_href(const std::string_view input) {
13191
3.05k
  ada::result<ada::url> out = ada::parse<ada::url>(input);
13192
13193
3.05k
  if (out) {
13194
3.05k
    *this = *out;
13195
3.05k
  }
13196
13197
3.05k
  return out.has_value();
13198
3.05k
}
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
43.0k
                           const result_type* base_url) {
13213
  // We can specialize the implementation per type.
13214
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
13215
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
13216
  // something else } is free (at runtime). This means that ada::url_aggregator
13217
  // and ada::url **do not have to support the exact same API**.
13218
43.0k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13219
43.0k
  constexpr bool result_type_is_ada_url_aggregator =
13220
43.0k
      std::is_same_v<url_aggregator, result_type>;
13221
43.0k
  static_assert(result_type_is_ada_url ||
13222
43.0k
                result_type_is_ada_url_aggregator);  // We don't support
13223
                                                     // anything else for now.
13224
13225
43.0k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13226
43.0k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13227
43.0k
          ")");
13228
13229
43.0k
  state state = state::SCHEME_START;
13230
43.0k
  result_type url{};
13231
13232
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
13233
  // surely the result of a bug or are otherwise a security concern.
13234
43.0k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) [[unlikely]] {
13235
0
    url.is_valid = false;
13236
0
  }
13237
  // Going forward, user_input.size() is in [0,
13238
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
13239
  // base, or the optional_url was invalid, we must return.
13240
43.0k
  if (base_url != nullptr) {
13241
0
    url.is_valid &= base_url->is_valid;
13242
0
  }
13243
43.0k
  if (!url.is_valid) {
13244
0
    return url;
13245
0
  }
13246
43.0k
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
13247
    // Most of the time, we just need user_input.size().
13248
    // In some instances, we may need a bit more.
13249
    ///////////////////////////
13250
    // This is *very* important. This line should *not* be removed
13251
    // hastily. There are principled reasons why reserve is important
13252
    // for performance. If you have a benchmark with small inputs,
13253
    // it may not matter, but in other instances, it could.
13254
    ////
13255
    // This rounds up to the next power of two.
13256
    // We know that user_input.size() is in [0,
13257
    // std::numeric_limits<uint32_t>::max).
13258
21.5k
    uint32_t reserve_capacity =
13259
21.5k
        (0xFFFFFFFF >>
13260
21.5k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13261
21.5k
        1;
13262
21.5k
    url.reserve(reserve_capacity);
13263
21.5k
  }
13264
43.0k
  std::string tmp_buffer;
13265
43.0k
  std::string_view url_data;
13266
43.0k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13267
396
    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
396
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13271
396
    url_data = tmp_buffer;
13272
42.6k
  } else [[likely]] {
13273
42.6k
    url_data = user_input;
13274
42.6k
  }
13275
13276
  // Leading and trailing control characters are uncommon and easy to deal with
13277
  // (no performance concern).
13278
43.0k
  helpers::trim_c0_whitespace(url_data);
13279
13280
  // Optimization opportunity. Most websites do not have fragment.
13281
43.0k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13282
  // We add it last so that an implementation like ada::url_aggregator
13283
  // can append it last to its internal buffer, thus improving performance.
13284
13285
  // Here url_data no longer has its fragment.
13286
  // We are going to access the data from url_data (it is immutable).
13287
  // At any given time, we are pointing at byte 'input_position' in url_data.
13288
  // The input_position variable should range from 0 to input_size.
13289
  // It is illegal to access url_data at input_size.
13290
43.0k
  size_t input_position = 0;
13291
43.0k
  const size_t input_size = url_data.size();
13292
  // Keep running the following state machine by switching on state.
13293
  // If after a run pointer points to the EOF code point, go to the next step.
13294
  // Otherwise, increase pointer by 1 and continue with the state machine.
13295
  // We never decrement input_position.
13296
210k
  while (input_position <= input_size) {
13297
202k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13298
202k
            " in state ", ada::to_string(state));
13299
202k
    switch (state) {
13300
43.0k
      case state::SCHEME_START: {
13301
43.0k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13302
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13303
        // state to scheme state.
13304
43.0k
        if ((input_position != input_size) &&
13305
42.9k
            checkers::is_alpha(url_data[input_position])) {
13306
34.3k
          state = state::SCHEME;
13307
34.3k
          input_position++;
13308
34.3k
        } else {
13309
          // Otherwise, if state override is not given, set state to no scheme
13310
          // state and decrease pointer by 1.
13311
8.68k
          state = state::NO_SCHEME;
13312
8.68k
        }
13313
43.0k
        break;
13314
0
      }
13315
34.3k
      case state::SCHEME: {
13316
34.3k
        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
179k
        while ((input_position != input_size) &&
13320
178k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13321
144k
          input_position++;
13322
144k
        }
13323
        // Otherwise, if c is U+003A (:), then:
13324
34.3k
        if ((input_position != input_size) &&
13325
33.6k
            (url_data[input_position] == ':')) {
13326
32.4k
          ada_log("SCHEME the scheme should be ",
13327
32.4k
                  url_data.substr(0, input_position));
13328
32.4k
          if constexpr (result_type_is_ada_url) {
13329
16.2k
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13330
0
              return url;
13331
0
            }
13332
16.2k
          } else {
13333
            // we pass the colon along instead of painfully adding it back.
13334
16.2k
            if (!url.parse_scheme_with_colon(
13335
16.2k
                    url_data.substr(0, input_position + 1))) {
13336
0
              return url;
13337
0
            }
13338
16.2k
          }
13339
32.4k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13340
13341
          // If url's scheme is "file", then:
13342
32.4k
          if (url.type == scheme::type::FILE) {
13343
            // Set state to file state.
13344
2.92k
            state = state::FILE;
13345
2.92k
          }
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
29.4k
          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
29.4k
          else if (url.is_special()) {
13357
23.5k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13358
23.5k
          }
13359
          // Otherwise, if remaining starts with an U+002F (/), set state to
13360
          // path or authority state and increase pointer by 1.
13361
5.95k
          else if (input_position + 1 < input_size &&
13362
5.18k
                   url_data[input_position + 1] == '/') {
13363
2.55k
            state = state::PATH_OR_AUTHORITY;
13364
2.55k
            input_position++;
13365
2.55k
          }
13366
          // Otherwise, set url's path to the empty string and set state to
13367
          // opaque path state.
13368
3.40k
          else {
13369
3.40k
            state = state::OPAQUE_PATH;
13370
3.40k
          }
13371
32.4k
        }
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.95k
        else {
13376
1.95k
          state = state::NO_SCHEME;
13377
1.95k
          input_position = 0;
13378
1.95k
          break;
13379
1.95k
        }
13380
32.4k
        input_position++;
13381
32.4k
        break;
13382
34.3k
      }
13383
10.6k
      case state::NO_SCHEME: {
13384
10.6k
        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
10.6k
        if (base_url == nullptr ||
13388
10.6k
            (base_url->has_opaque_path && !fragment.has_value())) {
13389
10.6k
          ada_log("NO_SCHEME validation error");
13390
10.6k
          url.is_valid = false;
13391
10.6k
          return url;
13392
10.6k
        }
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
10.6k
      }
13425
24.3k
      case state::AUTHORITY: {
13426
24.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
24.3k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13438
22.9k
          state = state::HOST;
13439
22.9k
          break;
13440
22.9k
        }
13441
1.37k
        bool at_sign_seen{false};
13442
1.37k
        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
18.3k
        do {
13449
18.3k
          std::string_view view = url_data.substr(input_position);
13450
          // The delimiters are @, /, ? \\.
13451
18.3k
          size_t location =
13452
18.3k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13453
18.3k
                               : helpers::find_authority_delimiter(view);
13454
18.3k
          std::string_view authority_view = view.substr(0, location);
13455
18.3k
          size_t end_of_authority = input_position + authority_view.size();
13456
          // If c is U+0040 (@), then:
13457
18.3k
          if ((end_of_authority != input_size) &&
13458
17.1k
              (url_data[end_of_authority] == '@')) {
13459
            // If atSignSeen is true, then prepend "%40" to buffer.
13460
16.9k
            if (at_sign_seen) {
13461
15.6k
              if (password_token_seen) {
13462
5.62k
                if constexpr (result_type_is_ada_url) {
13463
2.81k
                  url.password += "%40";
13464
2.81k
                } else {
13465
2.81k
                  url.append_base_password("%40");
13466
2.81k
                }
13467
10.0k
              } else {
13468
10.0k
                if constexpr (result_type_is_ada_url) {
13469
5.02k
                  url.username += "%40";
13470
5.02k
                } else {
13471
5.02k
                  url.append_base_username("%40");
13472
5.02k
                }
13473
10.0k
              }
13474
15.6k
            }
13475
13476
16.9k
            at_sign_seen = true;
13477
13478
16.9k
            if (!password_token_seen) {
13479
11.3k
              size_t password_token_location = authority_view.find(':');
13480
11.3k
              password_token_seen =
13481
11.3k
                  password_token_location != std::string_view::npos;
13482
13483
11.3k
              if constexpr (store_values) {
13484
11.3k
                if (!password_token_seen) {
13485
10.7k
                  if constexpr (result_type_is_ada_url) {
13486
5.38k
                    url.username += unicode::percent_encode(
13487
5.38k
                        authority_view,
13488
5.38k
                        character_sets::USERINFO_PERCENT_ENCODE);
13489
5.38k
                  } else {
13490
5.38k
                    url.append_base_username(unicode::percent_encode(
13491
5.38k
                        authority_view,
13492
5.38k
                        character_sets::USERINFO_PERCENT_ENCODE));
13493
5.38k
                  }
13494
10.7k
                } else {
13495
576
                  if constexpr (result_type_is_ada_url) {
13496
288
                    url.username += unicode::percent_encode(
13497
288
                        authority_view.substr(0, password_token_location),
13498
288
                        character_sets::USERINFO_PERCENT_ENCODE);
13499
288
                    url.password += unicode::percent_encode(
13500
288
                        authority_view.substr(password_token_location + 1),
13501
288
                        character_sets::USERINFO_PERCENT_ENCODE);
13502
288
                  } else {
13503
288
                    url.append_base_username(unicode::percent_encode(
13504
288
                        authority_view.substr(0, password_token_location),
13505
288
                        character_sets::USERINFO_PERCENT_ENCODE));
13506
288
                    url.append_base_password(unicode::percent_encode(
13507
288
                        authority_view.substr(password_token_location + 1),
13508
288
                        character_sets::USERINFO_PERCENT_ENCODE));
13509
288
                  }
13510
576
                }
13511
11.3k
              }
13512
11.3k
            } else if constexpr (store_values) {
13513
5.62k
              if constexpr (result_type_is_ada_url) {
13514
2.81k
                url.password += unicode::percent_encode(
13515
2.81k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13516
2.81k
              } else {
13517
2.81k
                url.append_base_password(unicode::percent_encode(
13518
2.81k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13519
2.81k
              }
13520
5.62k
            }
13521
16.9k
          }
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.37k
          else if (end_of_authority == input_size ||
13526
144
                   url_data[end_of_authority] == '/' ||
13527
42
                   url_data[end_of_authority] == '?' ||
13528
1.37k
                   (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.37k
            if (at_sign_seen && authority_view.empty()) {
13532
174
              url.is_valid = false;
13533
174
              return url;
13534
174
            }
13535
1.19k
            state = state::HOST;
13536
1.19k
            break;
13537
1.37k
          }
13538
16.9k
          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
16.9k
          input_position = end_of_authority + 1;
13547
16.9k
        } while (true);
13548
13549
1.19k
        break;
13550
1.37k
      }
13551
1.19k
      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.37k
      }
13569
2.55k
      case state::PATH_OR_AUTHORITY: {
13570
2.55k
        ada_log("PATH_OR_AUTHORITY ",
13571
2.55k
                helpers::substring(url_data, input_position));
13572
13573
        // If c is U+002F (/), then set state to authority state.
13574
2.55k
        if ((input_position != input_size) &&
13575
2.53k
            (url_data[input_position] == '/')) {
13576
792
          state = state::AUTHORITY;
13577
792
          input_position++;
13578
1.75k
        } else {
13579
          // Otherwise, set state to path state, and decrease pointer by 1.
13580
1.75k
          state = state::PATH;
13581
1.75k
        }
13582
13583
2.55k
        break;
13584
1.37k
      }
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
23.5k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13705
23.5k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13706
23.5k
                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
23.5k
        if (url_data.substr(input_position, 2) == "//") {
13712
18.0k
          input_position += 2;
13713
18.0k
        }
13714
13715
23.5k
        [[fallthrough]];
13716
23.5k
      }
13717
23.5k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13718
23.5k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13719
23.5k
                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
24.7k
        while ((input_position != input_size) &&
13724
24.7k
               ((url_data[input_position] == '/') ||
13725
23.9k
                (url_data[input_position] == '\\'))) {
13726
1.25k
          input_position++;
13727
1.25k
        }
13728
23.5k
        state = state::AUTHORITY;
13729
13730
23.5k
        break;
13731
23.5k
      }
13732
634
      case state::QUERY: {
13733
634
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13734
634
        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
634
          const uint8_t* query_percent_encode_set =
13738
634
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13739
634
                               : 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
634
          url.update_base_search(url_data.substr(input_position),
13744
634
                                 query_percent_encode_set);
13745
634
          ada_log("QUERY update_base_search completed ");
13746
634
          if (fragment.has_value()) {
13747
33
            url.update_unencoded_base_hash(*fragment);
13748
33
          }
13749
634
        }
13750
634
        return url;
13751
23.5k
      }
13752
24.1k
      case state::HOST: {
13753
24.1k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13754
13755
24.1k
        std::string_view host_view = url_data.substr(input_position);
13756
24.1k
        auto [location, found_colon] =
13757
24.1k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13758
24.1k
        input_position = (location != std::string_view::npos)
13759
24.1k
                             ? input_position + location
13760
24.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
24.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
1.47k
          ada_log("HOST parsing ", host_view);
13769
1.47k
          if (!url.parse_host(host_view)) {
13770
197
            return url;
13771
197
          }
13772
1.27k
          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.27k
          state = state::PORT;
13776
1.27k
          input_position++;
13777
1.27k
        }
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
22.6k
        else {
13784
          // If url is special and host_view is the empty string, validation
13785
          // error, return failure.
13786
22.6k
          if (host_view.empty() && url.is_special()) {
13787
22
            url.is_valid = false;
13788
22
            return url;
13789
22
          }
13790
22.6k
          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
22.6k
          if (host_view.empty()) {
13794
98
            url.update_base_hostname("");
13795
22.5k
          } else if (!url.parse_host(host_view)) {
13796
698
            return url;
13797
698
          }
13798
21.9k
          ada_log("HOST parsing results in ", url.get_hostname(),
13799
21.9k
                  " href=", url.get_href());
13800
13801
          // Set url's host to host, and state to path start state.
13802
21.9k
          state = state::PATH_START;
13803
21.9k
        }
13804
13805
23.2k
        break;
13806
24.1k
      }
13807
23.2k
      case state::OPAQUE_PATH: {
13808
3.40k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13809
3.40k
        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.40k
        size_t location = view.find('?');
13813
3.40k
        if (location != std::string_view::npos) {
13814
304
          view.remove_suffix(view.size() - location);
13815
304
          state = state::QUERY;
13816
304
          input_position += location + 1;
13817
3.10k
        } else {
13818
3.10k
          input_position = input_size + 1;
13819
3.10k
        }
13820
3.40k
        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.40k
        if (view.ends_with(' ')) {
13825
144
          std::string modified_view =
13826
144
              std::string(view.substr(0, view.size() - 1)) + "%20";
13827
144
          url.update_base_pathname(unicode::percent_encode(
13828
144
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13829
3.26k
        } else {
13830
3.26k
          url.update_base_pathname(unicode::percent_encode(
13831
3.26k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13832
3.26k
        }
13833
3.40k
        break;
13834
24.1k
      }
13835
1.27k
      case state::PORT: {
13836
1.27k
        ada_log("PORT ", helpers::substring(url_data, input_position));
13837
1.27k
        std::string_view port_view = url_data.substr(input_position);
13838
1.27k
        input_position += url.parse_port(port_view, true);
13839
1.27k
        if (!url.is_valid) {
13840
230
          return url;
13841
230
        }
13842
1.04k
        state = state::PATH_START;
13843
1.04k
        [[fallthrough]];
13844
1.04k
      }
13845
24.0k
      case state::PATH_START: {
13846
24.0k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13847
13848
        // If url is special, then:
13849
24.0k
        if (url.is_special()) {
13850
          // Set state to path state.
13851
23.4k
          state = state::PATH;
13852
13853
          // Optimization: Avoiding going into PATH state improves the
13854
          // performance of urls ending with /.
13855
23.4k
          if (input_position == input_size) {
13856
21.8k
            if constexpr (store_values) {
13857
21.8k
              url.update_base_pathname("/");
13858
21.8k
              if (fragment.has_value()) {
13859
123
                url.update_unencoded_base_hash(*fragment);
13860
123
              }
13861
21.8k
            }
13862
21.8k
            return url;
13863
21.8k
          }
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.65k
          if ((url_data[input_position] != '/') &&
13868
203
              (url_data[input_position] != '\\')) {
13869
170
            break;
13870
170
          }
13871
1.65k
        }
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
532
        else if ((input_position != input_size) &&
13875
110
                 (url_data[input_position] == '?')) {
13876
12
          state = state::QUERY;
13877
12
        }
13878
        // Otherwise, if c is not the EOF code point:
13879
520
        else if (input_position != input_size) {
13880
          // Set state to path state.
13881
98
          state = state::PATH;
13882
13883
          // If c is not U+002F (/), then decrease pointer by 1.
13884
98
          if (url_data[input_position] != '/') {
13885
0
            break;
13886
0
          }
13887
98
        }
13888
13889
2.02k
        input_position++;
13890
2.02k
        break;
13891
24.0k
      }
13892
5.17k
      case state::PATH: {
13893
5.17k
        ada_log("PATH ", helpers::substring(url_data, input_position));
13894
5.17k
        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
5.17k
        size_t locofquestionmark = view.find('?');
13899
5.17k
        if (locofquestionmark != std::string_view::npos) {
13900
318
          state = state::QUERY;
13901
318
          view.remove_suffix(view.size() - locofquestionmark);
13902
318
          input_position += locofquestionmark + 1;
13903
4.85k
        } else {
13904
4.85k
          input_position = input_size + 1;
13905
4.85k
        }
13906
5.17k
        if constexpr (store_values) {
13907
5.17k
          if constexpr (result_type_is_ada_url) {
13908
2.64k
            helpers::parse_prepared_path(view, url.type, url.path);
13909
2.64k
          } else {
13910
2.53k
            url.consume_prepared_path(view);
13911
2.53k
            ADA_ASSERT_TRUE(url.validate());
13912
2.53k
          }
13913
5.17k
        }
13914
5.17k
        break;
13915
24.0k
      }
13916
1.69k
      case state::FILE_SLASH: {
13917
1.69k
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13918
13919
        // If c is U+002F (/) or U+005C (\), then:
13920
1.69k
        if ((input_position != input_size) &&
13921
1.68k
            (url_data[input_position] == '/' ||
13922
1.28k
             url_data[input_position] == '\\')) {
13923
1.28k
          ada_log("FILE_SLASH c is U+002F or U+005C");
13924
          // Set state to file host state.
13925
1.28k
          state = state::FILE_HOST;
13926
1.28k
          input_position++;
13927
1.28k
        } else {
13928
412
          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
412
          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
412
          state = state::PATH;
13968
412
        }
13969
13970
1.69k
        break;
13971
24.0k
      }
13972
1.28k
      case state::FILE_HOST: {
13973
1.28k
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13974
1.28k
        std::string_view view = url_data.substr(input_position);
13975
13976
1.28k
        size_t location = view.find_first_of("/\\?");
13977
1.28k
        std::string_view file_host_buffer(
13978
1.28k
            view.data(),
13979
1.28k
            (location != std::string_view::npos) ? location : view.size());
13980
13981
1.28k
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13982
14
          state = state::PATH;
13983
1.26k
        } 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.21k
        } else {
13993
1.21k
          size_t consumed_bytes = file_host_buffer.size();
13994
1.21k
          input_position += consumed_bytes;
13995
          // Let host be the result of host parsing buffer with url is not
13996
          // special.
13997
1.21k
          if (!url.parse_host(file_host_buffer)) {
13998
262
            return url;
13999
262
          }
14000
14001
950
          if constexpr (result_type_is_ada_url) {
14002
            // If host is "localhost", then set host to the empty string.
14003
484
            if (url.host.has_value() && url.host.value() == "localhost") {
14004
3
              url.host = "";
14005
3
            }
14006
484
          } else {
14007
466
            if (url.get_hostname() == "localhost") {
14008
3
              url.update_base_hostname("");
14009
3
            }
14010
466
          }
14011
14012
          // Set buffer to the empty string and state to path start state.
14013
950
          state = state::PATH_START;
14014
950
        }
14015
14016
1.02k
        break;
14017
1.28k
      }
14018
2.92k
      case state::FILE: {
14019
2.92k
        ada_log("FILE ", helpers::substring(url_data, input_position));
14020
2.92k
        std::string_view file_view = url_data.substr(input_position);
14021
14022
2.92k
        url.set_protocol_as_file();
14023
2.92k
        if constexpr (result_type_is_ada_url) {
14024
          // Set url's host to the empty string.
14025
1.46k
          url.host = "";
14026
1.46k
        } else {
14027
1.46k
          url.update_base_hostname("");
14028
1.46k
        }
14029
        // If c is U+002F (/) or U+005C (\), then:
14030
2.92k
        if (input_position != input_size &&
14031
2.90k
            (url_data[input_position] == '/' ||
14032
1.69k
             url_data[input_position] == '\\')) {
14033
1.69k
          ada_log("FILE c is U+002F or U+005C");
14034
          // Set state to file slash state.
14035
1.69k
          state = state::FILE_SLASH;
14036
1.69k
        }
14037
        // Otherwise, if base is non-null and base's scheme is "file":
14038
1.23k
        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.23k
        else {
14088
1.23k
          ada_log("FILE go to path");
14089
1.23k
          state = state::PATH;
14090
1.23k
          break;
14091
1.23k
        }
14092
14093
1.69k
        input_position++;
14094
1.69k
        break;
14095
2.92k
      }
14096
0
      default:
14097
0
        unreachable();
14098
202k
    }
14099
202k
  }
14100
8.38k
  if constexpr (store_values) {
14101
8.38k
    if (fragment.has_value()) {
14102
349
      url.update_unencoded_base_hash(*fragment);
14103
349
    }
14104
8.38k
  }
14105
8.38k
  return url;
14106
43.0k
}
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
21.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
21.5k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13219
21.5k
  constexpr bool result_type_is_ada_url_aggregator =
13220
21.5k
      std::is_same_v<url_aggregator, result_type>;
13221
21.5k
  static_assert(result_type_is_ada_url ||
13222
21.5k
                result_type_is_ada_url_aggregator);  // We don't support
13223
                                                     // anything else for now.
13224
13225
21.5k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13226
21.5k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13227
21.5k
          ")");
13228
13229
21.5k
  state state = state::SCHEME_START;
13230
21.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
21.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
21.5k
  if (base_url != nullptr) {
13241
0
    url.is_valid &= base_url->is_valid;
13242
0
  }
13243
21.5k
  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
21.5k
  std::string tmp_buffer;
13265
21.5k
  std::string_view url_data;
13266
21.5k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13267
198
    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
198
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13271
198
    url_data = tmp_buffer;
13272
21.3k
  } else [[likely]] {
13273
21.3k
    url_data = user_input;
13274
21.3k
  }
13275
13276
  // Leading and trailing control characters are uncommon and easy to deal with
13277
  // (no performance concern).
13278
21.5k
  helpers::trim_c0_whitespace(url_data);
13279
13280
  // Optimization opportunity. Most websites do not have fragment.
13281
21.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
21.5k
  size_t input_position = 0;
13291
21.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
105k
  while (input_position <= input_size) {
13297
101k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13298
101k
            " in state ", ada::to_string(state));
13299
101k
    switch (state) {
13300
21.5k
      case state::SCHEME_START: {
13301
21.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
21.5k
        if ((input_position != input_size) &&
13305
21.4k
            checkers::is_alpha(url_data[input_position])) {
13306
17.1k
          state = state::SCHEME;
13307
17.1k
          input_position++;
13308
17.1k
        } else {
13309
          // Otherwise, if state override is not given, set state to no scheme
13310
          // state and decrease pointer by 1.
13311
4.34k
          state = state::NO_SCHEME;
13312
4.34k
        }
13313
21.5k
        break;
13314
0
      }
13315
17.1k
      case state::SCHEME: {
13316
17.1k
        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
89.6k
        while ((input_position != input_size) &&
13320
89.2k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13321
72.4k
          input_position++;
13322
72.4k
        }
13323
        // Otherwise, if c is U+003A (:), then:
13324
17.1k
        if ((input_position != input_size) &&
13325
16.8k
            (url_data[input_position] == ':')) {
13326
16.2k
          ada_log("SCHEME the scheme should be ",
13327
16.2k
                  url_data.substr(0, input_position));
13328
16.2k
          if constexpr (result_type_is_ada_url) {
13329
16.2k
            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
16.2k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13340
13341
          // If url's scheme is "file", then:
13342
16.2k
          if (url.type == scheme::type::FILE) {
13343
            // Set state to file state.
13344
1.46k
            state = state::FILE;
13345
1.46k
          }
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
14.7k
          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
14.7k
          else if (url.is_special()) {
13357
11.7k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13358
11.7k
          }
13359
          // Otherwise, if remaining starts with an U+002F (/), set state to
13360
          // path or authority state and increase pointer by 1.
13361
2.97k
          else if (input_position + 1 < input_size &&
13362
2.59k
                   url_data[input_position + 1] == '/') {
13363
1.27k
            state = state::PATH_OR_AUTHORITY;
13364
1.27k
            input_position++;
13365
1.27k
          }
13366
          // Otherwise, set url's path to the empty string and set state to
13367
          // opaque path state.
13368
1.70k
          else {
13369
1.70k
            state = state::OPAQUE_PATH;
13370
1.70k
          }
13371
16.2k
        }
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
979
        else {
13376
979
          state = state::NO_SCHEME;
13377
979
          input_position = 0;
13378
979
          break;
13379
979
        }
13380
16.2k
        input_position++;
13381
16.2k
        break;
13382
17.1k
      }
13383
5.32k
      case state::NO_SCHEME: {
13384
5.32k
        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
5.32k
        if (base_url == nullptr ||
13388
5.32k
            (base_url->has_opaque_path && !fragment.has_value())) {
13389
5.32k
          ada_log("NO_SCHEME validation error");
13390
5.32k
          url.is_valid = false;
13391
5.32k
          return url;
13392
5.32k
        }
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
5.32k
      }
13425
12.1k
      case state::AUTHORITY: {
13426
12.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
12.1k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13438
11.4k
          state = state::HOST;
13439
11.4k
          break;
13440
11.4k
        }
13441
686
        bool at_sign_seen{false};
13442
686
        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
9.16k
        do {
13449
9.16k
          std::string_view view = url_data.substr(input_position);
13450
          // The delimiters are @, /, ? \\.
13451
9.16k
          size_t location =
13452
9.16k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13453
9.16k
                               : helpers::find_authority_delimiter(view);
13454
9.16k
          std::string_view authority_view = view.substr(0, location);
13455
9.16k
          size_t end_of_authority = input_position + authority_view.size();
13456
          // If c is U+0040 (@), then:
13457
9.16k
          if ((end_of_authority != input_size) &&
13458
8.55k
              (url_data[end_of_authority] == '@')) {
13459
            // If atSignSeen is true, then prepend "%40" to buffer.
13460
8.47k
            if (at_sign_seen) {
13461
7.83k
              if (password_token_seen) {
13462
2.81k
                if constexpr (result_type_is_ada_url) {
13463
2.81k
                  url.password += "%40";
13464
                } else {
13465
                  url.append_base_password("%40");
13466
                }
13467
5.02k
              } else {
13468
5.02k
                if constexpr (result_type_is_ada_url) {
13469
5.02k
                  url.username += "%40";
13470
                } else {
13471
                  url.append_base_username("%40");
13472
                }
13473
5.02k
              }
13474
7.83k
            }
13475
13476
8.47k
            at_sign_seen = true;
13477
13478
8.47k
            if (!password_token_seen) {
13479
5.66k
              size_t password_token_location = authority_view.find(':');
13480
5.66k
              password_token_seen =
13481
5.66k
                  password_token_location != std::string_view::npos;
13482
13483
5.66k
              if constexpr (store_values) {
13484
5.66k
                if (!password_token_seen) {
13485
5.38k
                  if constexpr (result_type_is_ada_url) {
13486
5.38k
                    url.username += unicode::percent_encode(
13487
5.38k
                        authority_view,
13488
5.38k
                        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
5.38k
                } else {
13495
288
                  if constexpr (result_type_is_ada_url) {
13496
288
                    url.username += unicode::percent_encode(
13497
288
                        authority_view.substr(0, password_token_location),
13498
288
                        character_sets::USERINFO_PERCENT_ENCODE);
13499
288
                    url.password += unicode::percent_encode(
13500
288
                        authority_view.substr(password_token_location + 1),
13501
288
                        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
288
                }
13511
5.66k
              }
13512
5.66k
            } else if constexpr (store_values) {
13513
2.81k
              if constexpr (result_type_is_ada_url) {
13514
2.81k
                url.password += unicode::percent_encode(
13515
2.81k
                    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.81k
            }
13521
8.47k
          }
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
686
          else if (end_of_authority == input_size ||
13526
72
                   url_data[end_of_authority] == '/' ||
13527
21
                   url_data[end_of_authority] == '?' ||
13528
686
                   (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
686
            if (at_sign_seen && authority_view.empty()) {
13532
87
              url.is_valid = false;
13533
87
              return url;
13534
87
            }
13535
599
            state = state::HOST;
13536
599
            break;
13537
686
          }
13538
8.47k
          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
8.47k
          input_position = end_of_authority + 1;
13547
8.47k
        } while (true);
13548
13549
599
        break;
13550
686
      }
13551
599
      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
686
      }
13569
1.27k
      case state::PATH_OR_AUTHORITY: {
13570
1.27k
        ada_log("PATH_OR_AUTHORITY ",
13571
1.27k
                helpers::substring(url_data, input_position));
13572
13573
        // If c is U+002F (/), then set state to authority state.
13574
1.27k
        if ((input_position != input_size) &&
13575
1.26k
            (url_data[input_position] == '/')) {
13576
396
          state = state::AUTHORITY;
13577
396
          input_position++;
13578
879
        } else {
13579
          // Otherwise, set state to path state, and decrease pointer by 1.
13580
879
          state = state::PATH;
13581
879
        }
13582
13583
1.27k
        break;
13584
686
      }
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
11.7k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13705
11.7k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13706
11.7k
                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
11.7k
        if (url_data.substr(input_position, 2) == "//") {
13712
9.02k
          input_position += 2;
13713
9.02k
        }
13714
13715
11.7k
        [[fallthrough]];
13716
11.7k
      }
13717
11.7k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13718
11.7k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13719
11.7k
                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
12.3k
        while ((input_position != input_size) &&
13724
12.3k
               ((url_data[input_position] == '/') ||
13725
11.9k
                (url_data[input_position] == '\\'))) {
13726
627
          input_position++;
13727
627
        }
13728
11.7k
        state = state::AUTHORITY;
13729
13730
11.7k
        break;
13731
11.7k
      }
13732
320
      case state::QUERY: {
13733
320
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13734
320
        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
320
          const uint8_t* query_percent_encode_set =
13738
320
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13739
320
                               : 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
320
          url.update_base_search(url_data.substr(input_position),
13744
320
                                 query_percent_encode_set);
13745
320
          ada_log("QUERY update_base_search completed ");
13746
320
          if (fragment.has_value()) {
13747
17
            url.update_unencoded_base_hash(*fragment);
13748
17
          }
13749
320
        }
13750
320
        return url;
13751
11.7k
      }
13752
12.0k
      case state::HOST: {
13753
12.0k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13754
13755
12.0k
        std::string_view host_view = url_data.substr(input_position);
13756
12.0k
        auto [location, found_colon] =
13757
12.0k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13758
12.0k
        input_position = (location != std::string_view::npos)
13759
12.0k
                             ? input_position + location
13760
12.0k
                             : 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
12.0k
        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
736
          ada_log("HOST parsing ", host_view);
13769
736
          if (!url.parse_host(host_view)) {
13770
91
            return url;
13771
91
          }
13772
645
          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
645
          state = state::PORT;
13776
645
          input_position++;
13777
645
        }
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
11.3k
        else {
13784
          // If url is special and host_view is the empty string, validation
13785
          // error, return failure.
13786
11.3k
          if (host_view.empty() && url.is_special()) {
13787
11
            url.is_valid = false;
13788
11
            return url;
13789
11
          }
13790
11.3k
          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
11.3k
          if (host_view.empty()) {
13794
49
            url.update_base_hostname("");
13795
11.2k
          } else if (!url.parse_host(host_view)) {
13796
297
            return url;
13797
297
          }
13798
11.0k
          ada_log("HOST parsing results in ", url.get_hostname(),
13799
11.0k
                  " href=", url.get_href());
13800
13801
          // Set url's host to host, and state to path start state.
13802
11.0k
          state = state::PATH_START;
13803
11.0k
        }
13804
13805
11.6k
        break;
13806
12.0k
      }
13807
11.6k
      case state::OPAQUE_PATH: {
13808
1.70k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13809
1.70k
        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.70k
        size_t location = view.find('?');
13813
1.70k
        if (location != std::string_view::npos) {
13814
152
          view.remove_suffix(view.size() - location);
13815
152
          state = state::QUERY;
13816
152
          input_position += location + 1;
13817
1.55k
        } else {
13818
1.55k
          input_position = input_size + 1;
13819
1.55k
        }
13820
1.70k
        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.70k
        if (view.ends_with(' ')) {
13825
72
          std::string modified_view =
13826
72
              std::string(view.substr(0, view.size() - 1)) + "%20";
13827
72
          url.update_base_pathname(unicode::percent_encode(
13828
72
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13829
1.63k
        } else {
13830
1.63k
          url.update_base_pathname(unicode::percent_encode(
13831
1.63k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13832
1.63k
        }
13833
1.70k
        break;
13834
12.0k
      }
13835
645
      case state::PORT: {
13836
645
        ada_log("PORT ", helpers::substring(url_data, input_position));
13837
645
        std::string_view port_view = url_data.substr(input_position);
13838
645
        input_position += url.parse_port(port_view, true);
13839
645
        if (!url.is_valid) {
13840
117
          return url;
13841
117
        }
13842
528
        state = state::PATH_START;
13843
528
        [[fallthrough]];
13844
528
      }
13845
12.0k
      case state::PATH_START: {
13846
12.0k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13847
13848
        // If url is special, then:
13849
12.0k
        if (url.is_special()) {
13850
          // Set state to path state.
13851
11.8k
          state = state::PATH;
13852
13853
          // Optimization: Avoiding going into PATH state improves the
13854
          // performance of urls ending with /.
13855
11.8k
          if (input_position == input_size) {
13856
10.9k
            if constexpr (store_values) {
13857
10.9k
              url.update_base_pathname("/");
13858
10.9k
              if (fragment.has_value()) {
13859
63
                url.update_unencoded_base_hash(*fragment);
13860
63
              }
13861
10.9k
            }
13862
10.9k
            return url;
13863
10.9k
          }
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
882
          if ((url_data[input_position] != '/') &&
13868
105
              (url_data[input_position] != '\\')) {
13869
88
            break;
13870
88
          }
13871
882
        }
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
266
        else if ((input_position != input_size) &&
13875
55
                 (url_data[input_position] == '?')) {
13876
6
          state = state::QUERY;
13877
6
        }
13878
        // Otherwise, if c is not the EOF code point:
13879
260
        else if (input_position != input_size) {
13880
          // Set state to path state.
13881
49
          state = state::PATH;
13882
13883
          // If c is not U+002F (/), then decrease pointer by 1.
13884
49
          if (url_data[input_position] != '/') {
13885
0
            break;
13886
0
          }
13887
49
        }
13888
13889
1.06k
        input_position++;
13890
1.06k
        break;
13891
12.0k
      }
13892
2.64k
      case state::PATH: {
13893
2.64k
        ada_log("PATH ", helpers::substring(url_data, input_position));
13894
2.64k
        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.64k
        size_t locofquestionmark = view.find('?');
13899
2.64k
        if (locofquestionmark != std::string_view::npos) {
13900
162
          state = state::QUERY;
13901
162
          view.remove_suffix(view.size() - locofquestionmark);
13902
162
          input_position += locofquestionmark + 1;
13903
2.47k
        } else {
13904
2.47k
          input_position = input_size + 1;
13905
2.47k
        }
13906
2.64k
        if constexpr (store_values) {
13907
2.64k
          if constexpr (result_type_is_ada_url) {
13908
2.64k
            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.64k
        }
13914
2.64k
        break;
13915
12.0k
      }
13916
847
      case state::FILE_SLASH: {
13917
847
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13918
13919
        // If c is U+002F (/) or U+005C (\), then:
13920
847
        if ((input_position != input_size) &&
13921
842
            (url_data[input_position] == '/' ||
13922
641
             url_data[input_position] == '\\')) {
13923
641
          ada_log("FILE_SLASH c is U+002F or U+005C");
13924
          // Set state to file host state.
13925
641
          state = state::FILE_HOST;
13926
641
          input_position++;
13927
641
        } else {
13928
206
          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
206
          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
206
          state = state::PATH;
13968
206
        }
13969
13970
847
        break;
13971
12.0k
      }
13972
641
      case state::FILE_HOST: {
13973
641
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13974
641
        std::string_view view = url_data.substr(input_position);
13975
13976
641
        size_t location = view.find_first_of("/\\?");
13977
641
        std::string_view file_host_buffer(
13978
641
            view.data(),
13979
641
            (location != std::string_view::npos) ? location : view.size());
13980
13981
641
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13982
7
          state = state::PATH;
13983
634
        } 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
606
        } else {
13993
606
          size_t consumed_bytes = file_host_buffer.size();
13994
606
          input_position += consumed_bytes;
13995
          // Let host be the result of host parsing buffer with url is not
13996
          // special.
13997
606
          if (!url.parse_host(file_host_buffer)) {
13998
122
            return url;
13999
122
          }
14000
14001
484
          if constexpr (result_type_is_ada_url) {
14002
            // If host is "localhost", then set host to the empty string.
14003
484
            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
484
          state = state::PATH_START;
14014
484
        }
14015
14016
519
        break;
14017
641
      }
14018
1.46k
      case state::FILE: {
14019
1.46k
        ada_log("FILE ", helpers::substring(url_data, input_position));
14020
1.46k
        std::string_view file_view = url_data.substr(input_position);
14021
14022
1.46k
        url.set_protocol_as_file();
14023
1.46k
        if constexpr (result_type_is_ada_url) {
14024
          // Set url's host to the empty string.
14025
1.46k
          url.host = "";
14026
        } else {
14027
          url.update_base_hostname("");
14028
        }
14029
        // If c is U+002F (/) or U+005C (\), then:
14030
1.46k
        if (input_position != input_size &&
14031
1.45k
            (url_data[input_position] == '/' ||
14032
847
             url_data[input_position] == '\\')) {
14033
847
          ada_log("FILE c is U+002F or U+005C");
14034
          // Set state to file slash state.
14035
847
          state = state::FILE_SLASH;
14036
847
        }
14037
        // Otherwise, if base is non-null and base's scheme is "file":
14038
617
        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
617
        else {
14088
617
          ada_log("FILE go to path");
14089
617
          state = state::PATH;
14090
617
          break;
14091
617
        }
14092
14093
847
        input_position++;
14094
847
        break;
14095
1.46k
      }
14096
0
      default:
14097
0
        unreachable();
14098
101k
    }
14099
101k
  }
14100
4.24k
  if constexpr (store_values) {
14101
4.24k
    if (fragment.has_value()) {
14102
175
      url.update_unencoded_base_hash(*fragment);
14103
175
    }
14104
4.24k
  }
14105
4.24k
  return url;
14106
21.5k
}
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
21.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
21.5k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13219
21.5k
  constexpr bool result_type_is_ada_url_aggregator =
13220
21.5k
      std::is_same_v<url_aggregator, result_type>;
13221
21.5k
  static_assert(result_type_is_ada_url ||
13222
21.5k
                result_type_is_ada_url_aggregator);  // We don't support
13223
                                                     // anything else for now.
13224
13225
21.5k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13226
21.5k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13227
21.5k
          ")");
13228
13229
21.5k
  state state = state::SCHEME_START;
13230
21.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
21.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
21.5k
  if (base_url != nullptr) {
13241
0
    url.is_valid &= base_url->is_valid;
13242
0
  }
13243
21.5k
  if (!url.is_valid) {
13244
0
    return url;
13245
0
  }
13246
21.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
21.5k
    uint32_t reserve_capacity =
13259
21.5k
        (0xFFFFFFFF >>
13260
21.5k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13261
21.5k
        1;
13262
21.5k
    url.reserve(reserve_capacity);
13263
21.5k
  }
13264
21.5k
  std::string tmp_buffer;
13265
21.5k
  std::string_view url_data;
13266
21.5k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13267
198
    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
198
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13271
198
    url_data = tmp_buffer;
13272
21.3k
  } else [[likely]] {
13273
21.3k
    url_data = user_input;
13274
21.3k
  }
13275
13276
  // Leading and trailing control characters are uncommon and easy to deal with
13277
  // (no performance concern).
13278
21.5k
  helpers::trim_c0_whitespace(url_data);
13279
13280
  // Optimization opportunity. Most websites do not have fragment.
13281
21.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
21.5k
  size_t input_position = 0;
13291
21.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
105k
  while (input_position <= input_size) {
13297
100k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13298
100k
            " in state ", ada::to_string(state));
13299
100k
    switch (state) {
13300
21.5k
      case state::SCHEME_START: {
13301
21.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
21.5k
        if ((input_position != input_size) &&
13305
21.4k
            checkers::is_alpha(url_data[input_position])) {
13306
17.1k
          state = state::SCHEME;
13307
17.1k
          input_position++;
13308
17.1k
        } else {
13309
          // Otherwise, if state override is not given, set state to no scheme
13310
          // state and decrease pointer by 1.
13311
4.34k
          state = state::NO_SCHEME;
13312
4.34k
        }
13313
21.5k
        break;
13314
0
      }
13315
17.1k
      case state::SCHEME: {
13316
17.1k
        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
89.6k
        while ((input_position != input_size) &&
13320
89.2k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13321
72.4k
          input_position++;
13322
72.4k
        }
13323
        // Otherwise, if c is U+003A (:), then:
13324
17.1k
        if ((input_position != input_size) &&
13325
16.8k
            (url_data[input_position] == ':')) {
13326
16.2k
          ada_log("SCHEME the scheme should be ",
13327
16.2k
                  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
16.2k
          } else {
13333
            // we pass the colon along instead of painfully adding it back.
13334
16.2k
            if (!url.parse_scheme_with_colon(
13335
16.2k
                    url_data.substr(0, input_position + 1))) {
13336
0
              return url;
13337
0
            }
13338
16.2k
          }
13339
16.2k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13340
13341
          // If url's scheme is "file", then:
13342
16.2k
          if (url.type == scheme::type::FILE) {
13343
            // Set state to file state.
13344
1.46k
            state = state::FILE;
13345
1.46k
          }
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
14.7k
          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
14.7k
          else if (url.is_special()) {
13357
11.7k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13358
11.7k
          }
13359
          // Otherwise, if remaining starts with an U+002F (/), set state to
13360
          // path or authority state and increase pointer by 1.
13361
2.97k
          else if (input_position + 1 < input_size &&
13362
2.59k
                   url_data[input_position + 1] == '/') {
13363
1.27k
            state = state::PATH_OR_AUTHORITY;
13364
1.27k
            input_position++;
13365
1.27k
          }
13366
          // Otherwise, set url's path to the empty string and set state to
13367
          // opaque path state.
13368
1.70k
          else {
13369
1.70k
            state = state::OPAQUE_PATH;
13370
1.70k
          }
13371
16.2k
        }
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
979
        else {
13376
979
          state = state::NO_SCHEME;
13377
979
          input_position = 0;
13378
979
          break;
13379
979
        }
13380
16.2k
        input_position++;
13381
16.2k
        break;
13382
17.1k
      }
13383
5.32k
      case state::NO_SCHEME: {
13384
5.32k
        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
5.32k
        if (base_url == nullptr ||
13388
5.32k
            (base_url->has_opaque_path && !fragment.has_value())) {
13389
5.32k
          ada_log("NO_SCHEME validation error");
13390
5.32k
          url.is_valid = false;
13391
5.32k
          return url;
13392
5.32k
        }
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
5.32k
      }
13425
12.1k
      case state::AUTHORITY: {
13426
12.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
12.1k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13438
11.4k
          state = state::HOST;
13439
11.4k
          break;
13440
11.4k
        }
13441
686
        bool at_sign_seen{false};
13442
686
        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
9.16k
        do {
13449
9.16k
          std::string_view view = url_data.substr(input_position);
13450
          // The delimiters are @, /, ? \\.
13451
9.16k
          size_t location =
13452
9.16k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13453
9.16k
                               : helpers::find_authority_delimiter(view);
13454
9.16k
          std::string_view authority_view = view.substr(0, location);
13455
9.16k
          size_t end_of_authority = input_position + authority_view.size();
13456
          // If c is U+0040 (@), then:
13457
9.16k
          if ((end_of_authority != input_size) &&
13458
8.55k
              (url_data[end_of_authority] == '@')) {
13459
            // If atSignSeen is true, then prepend "%40" to buffer.
13460
8.47k
            if (at_sign_seen) {
13461
7.83k
              if (password_token_seen) {
13462
                if constexpr (result_type_is_ada_url) {
13463
                  url.password += "%40";
13464
2.81k
                } else {
13465
2.81k
                  url.append_base_password("%40");
13466
2.81k
                }
13467
5.02k
              } else {
13468
                if constexpr (result_type_is_ada_url) {
13469
                  url.username += "%40";
13470
5.02k
                } else {
13471
5.02k
                  url.append_base_username("%40");
13472
5.02k
                }
13473
5.02k
              }
13474
7.83k
            }
13475
13476
8.47k
            at_sign_seen = true;
13477
13478
8.47k
            if (!password_token_seen) {
13479
5.66k
              size_t password_token_location = authority_view.find(':');
13480
5.66k
              password_token_seen =
13481
5.66k
                  password_token_location != std::string_view::npos;
13482
13483
5.66k
              if constexpr (store_values) {
13484
5.66k
                if (!password_token_seen) {
13485
                  if constexpr (result_type_is_ada_url) {
13486
                    url.username += unicode::percent_encode(
13487
                        authority_view,
13488
                        character_sets::USERINFO_PERCENT_ENCODE);
13489
5.38k
                  } else {
13490
5.38k
                    url.append_base_username(unicode::percent_encode(
13491
5.38k
                        authority_view,
13492
5.38k
                        character_sets::USERINFO_PERCENT_ENCODE));
13493
5.38k
                  }
13494
5.38k
                } 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
288
                  } else {
13503
288
                    url.append_base_username(unicode::percent_encode(
13504
288
                        authority_view.substr(0, password_token_location),
13505
288
                        character_sets::USERINFO_PERCENT_ENCODE));
13506
288
                    url.append_base_password(unicode::percent_encode(
13507
288
                        authority_view.substr(password_token_location + 1),
13508
288
                        character_sets::USERINFO_PERCENT_ENCODE));
13509
288
                  }
13510
288
                }
13511
5.66k
              }
13512
5.66k
            } 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.81k
              } else {
13517
2.81k
                url.append_base_password(unicode::percent_encode(
13518
2.81k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13519
2.81k
              }
13520
2.81k
            }
13521
8.47k
          }
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
686
          else if (end_of_authority == input_size ||
13526
72
                   url_data[end_of_authority] == '/' ||
13527
21
                   url_data[end_of_authority] == '?' ||
13528
686
                   (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
686
            if (at_sign_seen && authority_view.empty()) {
13532
87
              url.is_valid = false;
13533
87
              return url;
13534
87
            }
13535
599
            state = state::HOST;
13536
599
            break;
13537
686
          }
13538
8.47k
          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
8.47k
          input_position = end_of_authority + 1;
13547
8.47k
        } while (true);
13548
13549
599
        break;
13550
686
      }
13551
599
      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
686
      }
13569
1.27k
      case state::PATH_OR_AUTHORITY: {
13570
1.27k
        ada_log("PATH_OR_AUTHORITY ",
13571
1.27k
                helpers::substring(url_data, input_position));
13572
13573
        // If c is U+002F (/), then set state to authority state.
13574
1.27k
        if ((input_position != input_size) &&
13575
1.26k
            (url_data[input_position] == '/')) {
13576
396
          state = state::AUTHORITY;
13577
396
          input_position++;
13578
879
        } else {
13579
          // Otherwise, set state to path state, and decrease pointer by 1.
13580
879
          state = state::PATH;
13581
879
        }
13582
13583
1.27k
        break;
13584
686
      }
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
11.7k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13705
11.7k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13706
11.7k
                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
11.7k
        if (url_data.substr(input_position, 2) == "//") {
13712
9.02k
          input_position += 2;
13713
9.02k
        }
13714
13715
11.7k
        [[fallthrough]];
13716
11.7k
      }
13717
11.7k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13718
11.7k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13719
11.7k
                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
12.3k
        while ((input_position != input_size) &&
13724
12.3k
               ((url_data[input_position] == '/') ||
13725
11.9k
                (url_data[input_position] == '\\'))) {
13726
627
          input_position++;
13727
627
        }
13728
11.7k
        state = state::AUTHORITY;
13729
13730
11.7k
        break;
13731
11.7k
      }
13732
314
      case state::QUERY: {
13733
314
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13734
314
        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
314
          const uint8_t* query_percent_encode_set =
13738
314
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13739
314
                               : 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
314
          url.update_base_search(url_data.substr(input_position),
13744
314
                                 query_percent_encode_set);
13745
314
          ada_log("QUERY update_base_search completed ");
13746
314
          if (fragment.has_value()) {
13747
16
            url.update_unencoded_base_hash(*fragment);
13748
16
          }
13749
314
        }
13750
314
        return url;
13751
11.7k
      }
13752
12.0k
      case state::HOST: {
13753
12.0k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13754
13755
12.0k
        std::string_view host_view = url_data.substr(input_position);
13756
12.0k
        auto [location, found_colon] =
13757
12.0k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13758
12.0k
        input_position = (location != std::string_view::npos)
13759
12.0k
                             ? input_position + location
13760
12.0k
                             : 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
12.0k
        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
736
          ada_log("HOST parsing ", host_view);
13769
736
          if (!url.parse_host(host_view)) {
13770
106
            return url;
13771
106
          }
13772
630
          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
630
          state = state::PORT;
13776
630
          input_position++;
13777
630
        }
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
11.3k
        else {
13784
          // If url is special and host_view is the empty string, validation
13785
          // error, return failure.
13786
11.3k
          if (host_view.empty() && url.is_special()) {
13787
11
            url.is_valid = false;
13788
11
            return url;
13789
11
          }
13790
11.3k
          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
11.3k
          if (host_view.empty()) {
13794
49
            url.update_base_hostname("");
13795
11.2k
          } else if (!url.parse_host(host_view)) {
13796
401
            return url;
13797
401
          }
13798
10.9k
          ada_log("HOST parsing results in ", url.get_hostname(),
13799
10.9k
                  " href=", url.get_href());
13800
13801
          // Set url's host to host, and state to path start state.
13802
10.9k
          state = state::PATH_START;
13803
10.9k
        }
13804
13805
11.5k
        break;
13806
12.0k
      }
13807
11.5k
      case state::OPAQUE_PATH: {
13808
1.70k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13809
1.70k
        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.70k
        size_t location = view.find('?');
13813
1.70k
        if (location != std::string_view::npos) {
13814
152
          view.remove_suffix(view.size() - location);
13815
152
          state = state::QUERY;
13816
152
          input_position += location + 1;
13817
1.55k
        } else {
13818
1.55k
          input_position = input_size + 1;
13819
1.55k
        }
13820
1.70k
        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.70k
        if (view.ends_with(' ')) {
13825
72
          std::string modified_view =
13826
72
              std::string(view.substr(0, view.size() - 1)) + "%20";
13827
72
          url.update_base_pathname(unicode::percent_encode(
13828
72
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13829
1.63k
        } else {
13830
1.63k
          url.update_base_pathname(unicode::percent_encode(
13831
1.63k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13832
1.63k
        }
13833
1.70k
        break;
13834
12.0k
      }
13835
630
      case state::PORT: {
13836
630
        ada_log("PORT ", helpers::substring(url_data, input_position));
13837
630
        std::string_view port_view = url_data.substr(input_position);
13838
630
        input_position += url.parse_port(port_view, true);
13839
630
        if (!url.is_valid) {
13840
113
          return url;
13841
113
        }
13842
517
        state = state::PATH_START;
13843
517
        [[fallthrough]];
13844
517
      }
13845
11.9k
      case state::PATH_START: {
13846
11.9k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13847
13848
        // If url is special, then:
13849
11.9k
        if (url.is_special()) {
13850
          // Set state to path state.
13851
11.6k
          state = state::PATH;
13852
13853
          // Optimization: Avoiding going into PATH state improves the
13854
          // performance of urls ending with /.
13855
11.6k
          if (input_position == input_size) {
13856
10.8k
            if constexpr (store_values) {
13857
10.8k
              url.update_base_pathname("/");
13858
10.8k
              if (fragment.has_value()) {
13859
60
                url.update_unencoded_base_hash(*fragment);
13860
60
              }
13861
10.8k
            }
13862
10.8k
            return url;
13863
10.8k
          }
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
776
          if ((url_data[input_position] != '/') &&
13868
98
              (url_data[input_position] != '\\')) {
13869
82
            break;
13870
82
          }
13871
776
        }
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
266
        else if ((input_position != input_size) &&
13875
55
                 (url_data[input_position] == '?')) {
13876
6
          state = state::QUERY;
13877
6
        }
13878
        // Otherwise, if c is not the EOF code point:
13879
260
        else if (input_position != input_size) {
13880
          // Set state to path state.
13881
49
          state = state::PATH;
13882
13883
          // If c is not U+002F (/), then decrease pointer by 1.
13884
49
          if (url_data[input_position] != '/') {
13885
0
            break;
13886
0
          }
13887
49
        }
13888
13889
960
        input_position++;
13890
960
        break;
13891
11.9k
      }
13892
2.53k
      case state::PATH: {
13893
2.53k
        ada_log("PATH ", helpers::substring(url_data, input_position));
13894
2.53k
        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.53k
        size_t locofquestionmark = view.find('?');
13899
2.53k
        if (locofquestionmark != std::string_view::npos) {
13900
156
          state = state::QUERY;
13901
156
          view.remove_suffix(view.size() - locofquestionmark);
13902
156
          input_position += locofquestionmark + 1;
13903
2.37k
        } else {
13904
2.37k
          input_position = input_size + 1;
13905
2.37k
        }
13906
2.53k
        if constexpr (store_values) {
13907
          if constexpr (result_type_is_ada_url) {
13908
            helpers::parse_prepared_path(view, url.type, url.path);
13909
2.53k
          } else {
13910
2.53k
            url.consume_prepared_path(view);
13911
2.53k
            ADA_ASSERT_TRUE(url.validate());
13912
2.53k
          }
13913
2.53k
        }
13914
2.53k
        break;
13915
11.9k
      }
13916
847
      case state::FILE_SLASH: {
13917
847
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13918
13919
        // If c is U+002F (/) or U+005C (\), then:
13920
847
        if ((input_position != input_size) &&
13921
842
            (url_data[input_position] == '/' ||
13922
641
             url_data[input_position] == '\\')) {
13923
641
          ada_log("FILE_SLASH c is U+002F or U+005C");
13924
          // Set state to file host state.
13925
641
          state = state::FILE_HOST;
13926
641
          input_position++;
13927
641
        } else {
13928
206
          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
206
          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
206
          state = state::PATH;
13968
206
        }
13969
13970
847
        break;
13971
11.9k
      }
13972
641
      case state::FILE_HOST: {
13973
641
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13974
641
        std::string_view view = url_data.substr(input_position);
13975
13976
641
        size_t location = view.find_first_of("/\\?");
13977
641
        std::string_view file_host_buffer(
13978
641
            view.data(),
13979
641
            (location != std::string_view::npos) ? location : view.size());
13980
13981
641
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13982
7
          state = state::PATH;
13983
634
        } 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
606
        } else {
13993
606
          size_t consumed_bytes = file_host_buffer.size();
13994
606
          input_position += consumed_bytes;
13995
          // Let host be the result of host parsing buffer with url is not
13996
          // special.
13997
606
          if (!url.parse_host(file_host_buffer)) {
13998
140
            return url;
13999
140
          }
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
466
          } else {
14007
466
            if (url.get_hostname() == "localhost") {
14008
3
              url.update_base_hostname("");
14009
3
            }
14010
466
          }
14011
14012
          // Set buffer to the empty string and state to path start state.
14013
466
          state = state::PATH_START;
14014
466
        }
14015
14016
501
        break;
14017
641
      }
14018
1.46k
      case state::FILE: {
14019
1.46k
        ada_log("FILE ", helpers::substring(url_data, input_position));
14020
1.46k
        std::string_view file_view = url_data.substr(input_position);
14021
14022
1.46k
        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.46k
        } else {
14027
1.46k
          url.update_base_hostname("");
14028
1.46k
        }
14029
        // If c is U+002F (/) or U+005C (\), then:
14030
1.46k
        if (input_position != input_size &&
14031
1.45k
            (url_data[input_position] == '/' ||
14032
847
             url_data[input_position] == '\\')) {
14033
847
          ada_log("FILE c is U+002F or U+005C");
14034
          // Set state to file slash state.
14035
847
          state = state::FILE_SLASH;
14036
847
        }
14037
        // Otherwise, if base is non-null and base's scheme is "file":
14038
617
        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
617
        else {
14088
617
          ada_log("FILE go to path");
14089
617
          state = state::PATH;
14090
617
          break;
14091
617
        }
14092
14093
847
        input_position++;
14094
847
        break;
14095
1.46k
      }
14096
0
      default:
14097
0
        unreachable();
14098
100k
    }
14099
100k
  }
14100
4.14k
  if constexpr (store_values) {
14101
4.14k
    if (fragment.has_value()) {
14102
174
      url.update_unencoded_base_hash(*fragment);
14103
174
    }
14104
4.14k
  }
14105
4.14k
  return url;
14106
21.5k
}
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
20.2k
    const std::string_view input_with_colon) {
14186
20.2k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14187
20.2k
  ADA_ASSERT_TRUE(validate());
14188
20.2k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14189
20.2k
  std::string_view input{input_with_colon};
14190
20.2k
  input.remove_suffix(1);
14191
20.2k
  auto parsed_type = ada::scheme::get_scheme_type(input);
14192
20.2k
  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
20.2k
  if (is_input_special) {  // fast path!!!
14198
13.6k
    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.59k
      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.59k
      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.59k
      if (type == ada::scheme::type::FILE &&
14215
0
          components.host_start == components.host_end) {
14216
0
        return false;
14217
0
      }
14218
1.59k
    }
14219
14220
1.59k
    type = parsed_type;
14221
13.6k
    set_scheme_from_view_with_colon(input_with_colon);
14222
14223
13.6k
    if constexpr (has_state_override) {
14224
      // This is uncommon.
14225
1.59k
      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.59k
      if (components.port == urls_scheme_port) {
14230
0
        clear_port();
14231
0
      }
14232
1.59k
    }
14233
13.6k
  } else {  // slow path
14234
6.59k
    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
6.59k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14239
14240
6.59k
    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.44k
      if (is_special() != ada::scheme::is_special(_buffer)) {
14245
1.78k
        return true;
14246
1.78k
      }
14247
14248
      // If url includes credentials or has a non-null port, and buffer is
14249
      // "file", then return.
14250
657
      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
657
      if (type == ada::scheme::type::FILE &&
14258
0
          components.host_start == components.host_end) {
14259
0
        return true;
14260
0
      }
14261
657
    }
14262
14263
657
    set_scheme(_buffer);
14264
14265
6.59k
    if constexpr (has_state_override) {
14266
      // This is uncommon.
14267
2.44k
      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.44k
      if (components.port == urls_scheme_port) {
14272
0
        clear_port();
14273
0
      }
14274
2.44k
    }
14275
6.59k
  }
14276
0
  ADA_ASSERT_TRUE(validate());
14277
20.2k
  return true;
14278
20.2k
}
bool ada::url_aggregator::parse_scheme_with_colon<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14185
16.2k
    const std::string_view input_with_colon) {
14186
16.2k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14187
16.2k
  ADA_ASSERT_TRUE(validate());
14188
16.2k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14189
16.2k
  std::string_view input{input_with_colon};
14190
16.2k
  input.remove_suffix(1);
14191
16.2k
  auto parsed_type = ada::scheme::get_scheme_type(input);
14192
16.2k
  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
16.2k
  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
12.0k
    type = parsed_type;
14221
12.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
12.0k
  } else {  // slow path
14234
4.15k
    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
4.15k
    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
4.15k
    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
4.15k
  }
14276
16.2k
  ADA_ASSERT_TRUE(validate());
14277
16.2k
  return true;
14278
16.2k
}
bool ada::url_aggregator::parse_scheme_with_colon<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14185
4.03k
    const std::string_view input_with_colon) {
14186
4.03k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14187
4.03k
  ADA_ASSERT_TRUE(validate());
14188
4.03k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14189
4.03k
  std::string_view input{input_with_colon};
14190
4.03k
  input.remove_suffix(1);
14191
4.03k
  auto parsed_type = ada::scheme::get_scheme_type(input);
14192
4.03k
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
14193
  /**
14194
   * In the common case, we will immediately recognize a special scheme (e.g.,
14195
   *http, https), in which case, we can go really fast.
14196
   **/
14197
4.03k
  if (is_input_special) {  // fast path!!!
14198
1.59k
    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.59k
      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.59k
      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.59k
      if (type == ada::scheme::type::FILE &&
14215
0
          components.host_start == components.host_end) {
14216
0
        return false;
14217
0
      }
14218
1.59k
    }
14219
14220
1.59k
    type = parsed_type;
14221
1.59k
    set_scheme_from_view_with_colon(input_with_colon);
14222
14223
1.59k
    if constexpr (has_state_override) {
14224
      // This is uncommon.
14225
1.59k
      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.59k
      if (components.port == urls_scheme_port) {
14230
0
        clear_port();
14231
0
      }
14232
1.59k
    }
14233
2.44k
  } else {  // slow path
14234
2.44k
    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.44k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14239
14240
2.44k
    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.44k
      if (is_special() != ada::scheme::is_special(_buffer)) {
14245
1.78k
        return true;
14246
1.78k
      }
14247
14248
      // If url includes credentials or has a non-null port, and buffer is
14249
      // "file", then return.
14250
657
      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
657
      if (type == ada::scheme::type::FILE &&
14258
0
          components.host_start == components.host_end) {
14259
0
        return true;
14260
0
      }
14261
657
    }
14262
14263
657
    set_scheme(_buffer);
14264
14265
2.44k
    if constexpr (has_state_override) {
14266
      // This is uncommon.
14267
2.44k
      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.44k
      if (components.port == urls_scheme_port) {
14272
0
        clear_port();
14273
0
      }
14274
2.44k
    }
14275
2.44k
  }
14276
0
  ADA_ASSERT_TRUE(validate());
14277
4.03k
  return true;
14278
4.03k
}
14279
14280
0
inline void url_aggregator::copy_scheme(const url_aggregator& u) {
14281
0
  ada_log("url_aggregator::copy_scheme ", u.buffer);
14282
0
  ADA_ASSERT_TRUE(validate());
14283
  // next line could overflow but unsigned arithmetic has well-defined
14284
  // overflows.
14285
0
  uint32_t new_difference = u.components.protocol_end - components.protocol_end;
14286
0
  type = u.type;
14287
0
  buffer.erase(0, components.protocol_end);
14288
0
  buffer.insert(0, u.get_protocol());
14289
0
  components.protocol_end = u.components.protocol_end;
14290
14291
  // No need to update the components
14292
0
  if (new_difference == 0) {
14293
0
    return;
14294
0
  }
14295
14296
  // Update the rest of the components.
14297
0
  components.username_end += new_difference;
14298
0
  components.host_start += new_difference;
14299
0
  components.host_end += new_difference;
14300
0
  components.pathname_start += new_difference;
14301
0
  if (components.search_start != url_components::omitted) {
14302
0
    components.search_start += new_difference;
14303
0
  }
14304
0
  if (components.hash_start != url_components::omitted) {
14305
0
    components.hash_start += new_difference;
14306
0
  }
14307
0
  ADA_ASSERT_TRUE(validate());
14308
0
}
14309
14310
inline void url_aggregator::set_scheme_from_view_with_colon(
14311
13.6k
    std::string_view new_scheme_with_colon) {
14312
13.6k
  ada_log("url_aggregator::set_scheme_from_view_with_colon ",
14313
13.6k
          new_scheme_with_colon);
14314
13.6k
  ADA_ASSERT_TRUE(validate());
14315
13.6k
  ADA_ASSERT_TRUE(!new_scheme_with_colon.empty() &&
14316
13.6k
                  new_scheme_with_colon.back() == ':');
14317
  // next line could overflow but unsigned arithmetic has well-defined
14318
  // overflows.
14319
13.6k
  uint32_t new_difference =
14320
13.6k
      uint32_t(new_scheme_with_colon.size()) - components.protocol_end;
14321
14322
13.6k
  if (buffer.empty()) {
14323
12.0k
    buffer.append(new_scheme_with_colon);
14324
12.0k
  } else {
14325
1.59k
    buffer.erase(0, components.protocol_end);
14326
1.59k
    buffer.insert(0, new_scheme_with_colon);
14327
1.59k
  }
14328
13.6k
  components.protocol_end += new_difference;
14329
14330
  // Update the rest of the components.
14331
13.6k
  components.username_end += new_difference;
14332
13.6k
  components.host_start += new_difference;
14333
13.6k
  components.host_end += new_difference;
14334
13.6k
  components.pathname_start += new_difference;
14335
13.6k
  if (components.search_start != url_components::omitted) {
14336
0
    components.search_start += new_difference;
14337
0
  }
14338
13.6k
  if (components.hash_start != url_components::omitted) {
14339
0
    components.hash_start += new_difference;
14340
0
  }
14341
13.6k
  ADA_ASSERT_TRUE(validate());
14342
13.6k
}
14343
14344
4.80k
inline void url_aggregator::set_scheme(std::string_view new_scheme) {
14345
4.80k
  ada_log("url_aggregator::set_scheme ", new_scheme);
14346
4.80k
  ADA_ASSERT_TRUE(validate());
14347
4.80k
  ADA_ASSERT_TRUE(new_scheme.empty() || new_scheme.back() != ':');
14348
  // next line could overflow but unsigned arithmetic has well-defined
14349
  // overflows.
14350
4.80k
  uint32_t new_difference =
14351
4.80k
      uint32_t(new_scheme.size()) - components.protocol_end + 1;
14352
14353
4.80k
  type = ada::scheme::get_scheme_type(new_scheme);
14354
4.80k
  if (buffer.empty()) {
14355
4.15k
    buffer.append(helpers::concat(new_scheme, ":"));
14356
4.15k
  } else {
14357
657
    buffer.erase(0, components.protocol_end);
14358
657
    buffer.insert(0, helpers::concat(new_scheme, ":"));
14359
657
  }
14360
4.80k
  components.protocol_end = uint32_t(new_scheme.size() + 1);
14361
14362
  // Update the rest of the components.
14363
4.80k
  components.username_end += new_difference;
14364
4.80k
  components.host_start += new_difference;
14365
4.80k
  components.host_end += new_difference;
14366
4.80k
  components.pathname_start += new_difference;
14367
4.80k
  if (components.search_start != url_components::omitted) {
14368
0
    components.search_start += new_difference;
14369
0
  }
14370
4.80k
  if (components.hash_start != url_components::omitted) {
14371
0
    components.hash_start += new_difference;
14372
0
  }
14373
4.80k
  ADA_ASSERT_TRUE(validate());
14374
4.80k
}
14375
14376
9.00k
bool url_aggregator::set_protocol(const std::string_view input) {
14377
9.00k
  ada_log("url_aggregator::set_protocol ", input);
14378
9.00k
  ADA_ASSERT_TRUE(validate());
14379
9.00k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14380
9.00k
  std::string view(input);
14381
9.00k
  helpers::remove_ascii_tab_or_newline(view);
14382
9.00k
  if (view.empty()) {
14383
34
    return true;
14384
34
  }
14385
14386
  // Schemes should start with alpha values.
14387
8.96k
  if (!checkers::is_alpha(view[0])) {
14388
4.33k
    return false;
14389
4.33k
  }
14390
14391
4.63k
  view.append(":");
14392
14393
4.63k
  std::string::iterator pointer =
14394
4.63k
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
14395
14396
4.63k
  if (pointer != view.end() && *pointer == ':') {
14397
4.03k
    return parse_scheme_with_colon<true>(
14398
4.03k
        view.substr(0, pointer - view.begin() + 1));
14399
4.03k
  }
14400
597
  return false;
14401
4.63k
}
14402
14403
9.00k
bool url_aggregator::set_username(const std::string_view input) {
14404
9.00k
  ada_log("url_aggregator::set_username '", input, "' ");
14405
9.00k
  ADA_ASSERT_TRUE(validate());
14406
9.00k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14407
9.00k
  if (cannot_have_credentials_or_port()) {
14408
736
    return false;
14409
736
  }
14410
8.26k
  size_t idx = ada::unicode::percent_encode_index(
14411
8.26k
      input, character_sets::USERINFO_PERCENT_ENCODE);
14412
8.26k
  if (idx == input.size()) {
14413
1.06k
    update_base_username(input);
14414
7.19k
  } else {
14415
    // We only create a temporary string if we have to!
14416
7.19k
    update_base_username(ada::unicode::percent_encode(
14417
7.19k
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14418
7.19k
  }
14419
8.26k
  ADA_ASSERT_TRUE(validate());
14420
8.26k
  return true;
14421
9.00k
}
14422
14423
9.00k
bool url_aggregator::set_password(const std::string_view input) {
14424
9.00k
  ada_log("url_aggregator::set_password '", input, "'");
14425
9.00k
  ADA_ASSERT_TRUE(validate());
14426
9.00k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14427
9.00k
  if (cannot_have_credentials_or_port()) {
14428
736
    return false;
14429
736
  }
14430
8.26k
  size_t idx = ada::unicode::percent_encode_index(
14431
8.26k
      input, character_sets::USERINFO_PERCENT_ENCODE);
14432
8.26k
  if (idx == input.size()) {
14433
1.06k
    update_base_password(input);
14434
7.19k
  } else {
14435
    // We only create a temporary string if we have to!
14436
7.19k
    update_base_password(ada::unicode::percent_encode(
14437
7.19k
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14438
7.19k
  }
14439
8.26k
  ADA_ASSERT_TRUE(validate());
14440
8.26k
  return true;
14441
9.00k
}
14442
14443
11.8k
bool url_aggregator::set_port(const std::string_view input) {
14444
11.8k
  ada_log("url_aggregator::set_port ", input);
14445
11.8k
  ADA_ASSERT_TRUE(validate());
14446
11.8k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14447
11.8k
  if (cannot_have_credentials_or_port()) {
14448
736
    return false;
14449
736
  }
14450
14451
11.1k
  if (input.empty()) {
14452
2
    clear_port();
14453
2
    return true;
14454
2
  }
14455
14456
11.1k
  std::string trimmed(input);
14457
11.1k
  helpers::remove_ascii_tab_or_newline(trimmed);
14458
14459
11.1k
  if (trimmed.empty()) {
14460
32
    return true;
14461
32
  }
14462
14463
  // Input should not start with a non-digit character.
14464
11.1k
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
14465
9.42k
    return false;
14466
9.42k
  }
14467
14468
  // Find the first non-digit character to determine the length of digits
14469
1.68k
  auto first_non_digit =
14470
1.68k
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
14471
1.68k
  std::string_view digits_to_parse =
14472
1.68k
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
14473
14474
  // Revert changes if parse_port fails.
14475
1.68k
  uint32_t previous_port = components.port;
14476
1.68k
  parse_port(digits_to_parse);
14477
1.68k
  if (is_valid) {
14478
1.16k
    return true;
14479
1.16k
  }
14480
517
  update_base_port(previous_port);
14481
517
  is_valid = true;
14482
517
  ADA_ASSERT_TRUE(validate());
14483
517
  return false;
14484
1.68k
}
14485
14486
9.00k
bool url_aggregator::set_pathname(const std::string_view input) {
14487
9.00k
  ada_log("url_aggregator::set_pathname ", input);
14488
9.00k
  ADA_ASSERT_TRUE(validate());
14489
9.00k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14490
9.00k
  if (has_opaque_path) {
14491
0
    return false;
14492
0
  }
14493
9.00k
  clear_pathname();
14494
9.00k
  parse_path(input);
14495
9.00k
  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
9.00k
  ADA_ASSERT_TRUE(validate());
14506
9.00k
  return true;
14507
9.00k
}
14508
14509
9.00k
ada_really_inline void url_aggregator::parse_path(std::string_view input) {
14510
9.00k
  ada_log("url_aggregator::parse_path ", input);
14511
9.00k
  ADA_ASSERT_TRUE(validate());
14512
9.00k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14513
9.00k
  std::string tmp_buffer;
14514
9.00k
  std::string_view internal_input;
14515
9.00k
  if (unicode::has_tabs_or_newline(input)) {
14516
157
    tmp_buffer = input;
14517
    // Optimization opportunity: Instead of copying and then pruning, we could
14518
    // just directly build the string from user_input.
14519
157
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
14520
157
    internal_input = tmp_buffer;
14521
8.84k
  } else {
14522
8.84k
    internal_input = input;
14523
8.84k
  }
14524
14525
  // If url is special, then:
14526
9.00k
  if (is_special()) {
14527
9.00k
    if (internal_input.empty()) {
14528
34
      update_base_pathname("/");
14529
8.96k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
14530
713
      consume_prepared_path(internal_input.substr(1));
14531
8.25k
    } else {
14532
8.25k
      consume_prepared_path(internal_input);
14533
8.25k
    }
14534
9.00k
  } 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
9.00k
  ADA_ASSERT_TRUE(validate());
14548
9.00k
}
14549
14550
9.00k
void url_aggregator::set_search(const std::string_view input) {
14551
9.00k
  ada_log("url_aggregator::set_search ", input);
14552
9.00k
  ADA_ASSERT_TRUE(validate());
14553
9.00k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14554
9.00k
  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.99k
  std::string new_value;
14561
8.99k
  new_value = input[0] == '?' ? input.substr(1) : input;
14562
8.99k
  helpers::remove_ascii_tab_or_newline(new_value);
14563
14564
8.99k
  auto query_percent_encode_set =
14565
8.99k
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
14566
8.99k
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
14567
14568
8.99k
  update_base_search(new_value, query_percent_encode_set);
14569
8.99k
  ADA_ASSERT_TRUE(validate());
14570
8.99k
}
14571
14572
9.00k
void url_aggregator::set_hash(const std::string_view input) {
14573
9.00k
  ada_log("url_aggregator::set_hash ", input);
14574
9.00k
  ADA_ASSERT_TRUE(validate());
14575
9.00k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14576
9.00k
  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.99k
  std::string new_value;
14586
8.99k
  new_value = input[0] == '#' ? input.substr(1) : input;
14587
8.99k
  helpers::remove_ascii_tab_or_newline(new_value);
14588
8.99k
  update_unencoded_base_hash(new_value);
14589
8.99k
  ADA_ASSERT_TRUE(validate());
14590
8.99k
}
14591
14592
3.05k
bool url_aggregator::set_href(const std::string_view input) {
14593
3.05k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14594
3.05k
  ada_log("url_aggregator::set_href ", input, " [", input.size(), " bytes]");
14595
3.05k
  ada::result<url_aggregator> out = ada::parse<url_aggregator>(input);
14596
3.05k
  ada_log("url_aggregator::set_href, success :", out.has_value());
14597
14598
3.05k
  if (out) {
14599
3.05k
    ada_log("url_aggregator::set_href, parsed ", out->to_string());
14600
    // TODO: Figure out why the following line puts test to never finish.
14601
3.05k
    *this = *out;
14602
3.05k
  }
14603
14604
3.05k
  return out.has_value();
14605
3.05k
}
14606
14607
25.3k
ada_really_inline bool url_aggregator::parse_host(std::string_view input) {
14608
25.3k
  ada_log("url_aggregator:parse_host \"", input, "\" [", input.size(),
14609
25.3k
          " bytes]");
14610
25.3k
  ADA_ASSERT_TRUE(validate());
14611
25.3k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14612
25.3k
  if (input.empty()) {
14613
9
    return is_valid = false;
14614
9
  }  // technically unnecessary.
14615
  // If input starts with U+005B ([), then:
14616
25.2k
  if (input[0] == '[') {
14617
    // If input does not end with U+005D (]), validation error, return failure.
14618
654
    if (input.back() != ']') {
14619
234
      return is_valid = false;
14620
234
    }
14621
420
    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
420
    input.remove_prefix(1);
14626
420
    input.remove_suffix(1);
14627
420
    return parse_ipv6(input);
14628
654
  }
14629
14630
  // If isNotSpecial is true, then return the result of opaque-host parsing
14631
  // input.
14632
24.6k
  if (!is_special()) {
14633
268
    return parse_opaque_host(input);
14634
268
  }
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
24.3k
  const uint64_t fast_result = checkers::try_parse_ipv4_fast(input);
14647
24.3k
  if (fast_result < checkers::ipv4_fast_fail) {
14648
    // Fast path succeeded - input is pure decimal IPv4
14649
49
    if (!input.empty() && input.back() == '.') {
14650
19
      update_base_hostname(input.substr(0, input.size() - 1));
14651
30
    } else {
14652
30
      update_base_hostname(input);
14653
30
    }
14654
49
    host_type = IPV4;
14655
49
    ada_log("parse_host fast path decimal ipv4");
14656
49
    ADA_ASSERT_TRUE(validate());
14657
49
    return true;
14658
49
  }
14659
24.3k
  uint8_t is_forbidden_or_upper =
14660
24.3k
      unicode::contains_forbidden_domain_code_point_or_upper(input.data(),
14661
24.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
24.3k
  if (is_forbidden_or_upper == 0 &&
14669
14.9k
      input.find("xn-") == std::string_view::npos) {
14670
    // fast path
14671
14.7k
    update_base_hostname(input);
14672
14673
    // Check for other IPv4 formats (hex, octal, etc.)
14674
14.7k
    if (checkers::is_ipv4(get_hostname())) {
14675
1.65k
      ada_log("parse_host fast path ipv4");
14676
1.65k
      return parse_ipv4(get_hostname(), true);
14677
1.65k
    }
14678
13.0k
    ada_log("parse_host fast path ", get_hostname());
14679
13.0k
    return true;
14680
14.7k
  }
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
9.60k
  ada_log("parse_host calling to_ascii");
14686
9.60k
  std::optional<std::string> host = std::string(get_hostname());
14687
9.60k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
14688
9.60k
  if (!is_valid) {
14689
4.62k
    ada_log("parse_host to_ascii returns false");
14690
4.62k
    return is_valid = false;
14691
4.62k
  }
14692
4.97k
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
14693
4.97k
          " bytes]");
14694
14695
4.97k
  if (std::ranges::any_of(host.value(),
14696
4.97k
                          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.97k
  if (checkers::is_ipv4(host.value())) {
14703
626
    ada_log("parse_host got ipv4 ", *host);
14704
626
    return parse_ipv4(host.value(), false);
14705
626
  }
14706
14707
4.35k
  update_base_hostname(host.value());
14708
4.35k
  ADA_ASSERT_TRUE(validate());
14709
4.35k
  return true;
14710
4.97k
}
14711
14712
template <bool override_hostname>
14713
18.0k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14714
18.0k
  ada_log("url_aggregator::set_host_or_hostname ", input);
14715
18.0k
  ADA_ASSERT_TRUE(validate());
14716
18.0k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14717
18.0k
  if (has_opaque_path) {
14718
0
    return false;
14719
0
  }
14720
14721
18.0k
  std::string previous_host(get_hostname());
14722
18.0k
  uint32_t previous_port = components.port;
14723
14724
18.0k
  size_t host_end_pos = input.find('#');
14725
18.0k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14726
18.0k
                                      ? host_end_pos
14727
18.0k
                                      : input.size());
14728
18.0k
  helpers::remove_ascii_tab_or_newline(_host);
14729
18.0k
  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
18.0k
  if (type != ada::scheme::type::FILE) {
14734
16.5k
    std::string_view host_view(_host.data(), _host.length());
14735
16.5k
    auto [location, found_colon] =
14736
16.5k
        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
16.5k
    if (found_colon) {
14742
      // If buffer is the empty string, host-missing validation error, return
14743
      // failure.
14744
7.49k
      std::string_view host_buffer = host_view.substr(0, location);
14745
7.49k
      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
7.47k
      if constexpr (override_hostname) {
14752
3.73k
        return false;
14753
3.73k
      }
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
7.47k
      if (!succeeded) {
14758
410
        update_base_hostname(previous_host);
14759
410
        update_base_port(previous_port);
14760
410
        return false;
14761
410
      }
14762
14763
      // Set url's host to host, buffer to the empty string, and state to port
14764
      // state.
14765
7.06k
      std::string_view port_buffer = new_host.substr(location + 1);
14766
7.06k
      if (!port_buffer.empty()) {
14767
2.87k
        set_port(port_buffer);
14768
2.87k
      }
14769
7.06k
      return true;
14770
7.47k
    }
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
9.03k
    else {
14775
      // If url is special and host_view is the empty string, host-missing
14776
      // validation error, return failure.
14777
9.03k
      if (host_view.empty() && is_special()) {
14778
1.55k
        return false;
14779
1.55k
      }
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
7.47k
      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
7.47k
      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
7.47k
      bool succeeded = parse_host(host_view);
14801
7.47k
      if (!succeeded) {
14802
3.35k
        update_base_hostname(previous_host);
14803
3.35k
        update_base_port(previous_port);
14804
3.35k
        return false;
14805
4.12k
      } else if (has_dash_dot()) {
14806
        // Should remove dash_dot from pathname
14807
0
        delete_dash_dot();
14808
0
      }
14809
4.12k
      return true;
14810
7.47k
    }
14811
16.5k
  }
14812
14813
1.47k
  size_t location = new_host.find_first_of("/\\?");
14814
1.47k
  if (location != std::string_view::npos) {
14815
1.34k
    new_host.remove_suffix(new_host.length() - location);
14816
1.34k
  }
14817
14818
1.47k
  if (new_host.empty()) {
14819
    // Set url's host to the empty string.
14820
0
    clear_hostname();
14821
1.47k
  } else {
14822
    // Let host be the result of host parsing buffer with url is not special.
14823
1.47k
    if (!parse_host(new_host)) {
14824
1.46k
      update_base_hostname(previous_host);
14825
1.46k
      update_base_port(previous_port);
14826
1.46k
      return false;
14827
1.46k
    }
14828
14829
    // If host is "localhost", then set host to the empty string.
14830
6
    if (helpers::substring(buffer, components.host_start,
14831
6
                           components.host_end) == "localhost") {
14832
0
      clear_hostname();
14833
0
    }
14834
6
  }
14835
6
  ADA_ASSERT_TRUE(validate());
14836
6
  return true;
14837
1.47k
}
bool ada::url_aggregator::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14713
9.00k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14714
9.00k
  ada_log("url_aggregator::set_host_or_hostname ", input);
14715
9.00k
  ADA_ASSERT_TRUE(validate());
14716
9.00k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14717
9.00k
  if (has_opaque_path) {
14718
0
    return false;
14719
0
  }
14720
14721
9.00k
  std::string previous_host(get_hostname());
14722
9.00k
  uint32_t previous_port = components.port;
14723
14724
9.00k
  size_t host_end_pos = input.find('#');
14725
9.00k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14726
9.00k
                                      ? host_end_pos
14727
9.00k
                                      : input.size());
14728
9.00k
  helpers::remove_ascii_tab_or_newline(_host);
14729
9.00k
  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
9.00k
  if (type != ada::scheme::type::FILE) {
14734
8.26k
    std::string_view host_view(_host.data(), _host.length());
14735
8.26k
    auto [location, found_colon] =
14736
8.26k
        helpers::get_host_delimiter_location(is_special(), host_view);
14737
14738
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14739
    // Note: the 'found_colon' value is true if and only if a colon was
14740
    // encountered while not inside brackets.
14741
8.26k
    if (found_colon) {
14742
      // If buffer is the empty string, host-missing validation error, return
14743
      // failure.
14744
3.74k
      std::string_view host_buffer = host_view.substr(0, location);
14745
3.74k
      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.73k
      bool succeeded = parse_host(host_buffer);
14757
3.73k
      if (!succeeded) {
14758
410
        update_base_hostname(previous_host);
14759
410
        update_base_port(previous_port);
14760
410
        return false;
14761
410
      }
14762
14763
      // Set url's host to host, buffer to the empty string, and state to port
14764
      // state.
14765
3.32k
      std::string_view port_buffer = new_host.substr(location + 1);
14766
3.32k
      if (!port_buffer.empty()) {
14767
2.87k
        set_port(port_buffer);
14768
2.87k
      }
14769
3.32k
      return true;
14770
3.73k
    }
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.51k
    else {
14775
      // If url is special and host_view is the empty string, host-missing
14776
      // validation error, return failure.
14777
4.51k
      if (host_view.empty() && is_special()) {
14778
779
        return false;
14779
779
      }
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.73k
      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.73k
      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.73k
      bool succeeded = parse_host(host_view);
14801
3.73k
      if (!succeeded) {
14802
1.67k
        update_base_hostname(previous_host);
14803
1.67k
        update_base_port(previous_port);
14804
1.67k
        return false;
14805
2.06k
      } else if (has_dash_dot()) {
14806
        // Should remove dash_dot from pathname
14807
0
        delete_dash_dot();
14808
0
      }
14809
2.06k
      return true;
14810
3.73k
    }
14811
8.26k
  }
14812
14813
736
  size_t location = new_host.find_first_of("/\\?");
14814
736
  if (location != std::string_view::npos) {
14815
673
    new_host.remove_suffix(new_host.length() - location);
14816
673
  }
14817
14818
736
  if (new_host.empty()) {
14819
    // Set url's host to the empty string.
14820
0
    clear_hostname();
14821
736
  } else {
14822
    // Let host be the result of host parsing buffer with url is not special.
14823
736
    if (!parse_host(new_host)) {
14824
733
      update_base_hostname(previous_host);
14825
733
      update_base_port(previous_port);
14826
733
      return false;
14827
733
    }
14828
14829
    // If host is "localhost", then set host to the empty string.
14830
3
    if (helpers::substring(buffer, components.host_start,
14831
3
                           components.host_end) == "localhost") {
14832
0
      clear_hostname();
14833
0
    }
14834
3
  }
14835
3
  ADA_ASSERT_TRUE(validate());
14836
3
  return true;
14837
736
}
bool ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14713
9.00k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14714
9.00k
  ada_log("url_aggregator::set_host_or_hostname ", input);
14715
9.00k
  ADA_ASSERT_TRUE(validate());
14716
9.00k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14717
9.00k
  if (has_opaque_path) {
14718
0
    return false;
14719
0
  }
14720
14721
9.00k
  std::string previous_host(get_hostname());
14722
9.00k
  uint32_t previous_port = components.port;
14723
14724
9.00k
  size_t host_end_pos = input.find('#');
14725
9.00k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14726
9.00k
                                      ? host_end_pos
14727
9.00k
                                      : input.size());
14728
9.00k
  helpers::remove_ascii_tab_or_newline(_host);
14729
9.00k
  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
9.00k
  if (type != ada::scheme::type::FILE) {
14734
8.26k
    std::string_view host_view(_host.data(), _host.length());
14735
8.26k
    auto [location, found_colon] =
14736
8.26k
        helpers::get_host_delimiter_location(is_special(), host_view);
14737
14738
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14739
    // Note: the 'found_colon' value is true if and only if a colon was
14740
    // encountered while not inside brackets.
14741
8.26k
    if (found_colon) {
14742
      // If buffer is the empty string, host-missing validation error, return
14743
      // failure.
14744
3.74k
      std::string_view host_buffer = host_view.substr(0, location);
14745
3.74k
      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.73k
      if constexpr (override_hostname) {
14752
3.73k
        return false;
14753
3.73k
      }
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.73k
      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.73k
      std::string_view port_buffer = new_host.substr(location + 1);
14766
3.73k
      if (!port_buffer.empty()) {
14767
0
        set_port(port_buffer);
14768
0
      }
14769
3.73k
      return true;
14770
3.73k
    }
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.51k
    else {
14775
      // If url is special and host_view is the empty string, host-missing
14776
      // validation error, return failure.
14777
4.51k
      if (host_view.empty() && is_special()) {
14778
779
        return false;
14779
779
      }
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.73k
      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.73k
      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.73k
      bool succeeded = parse_host(host_view);
14801
3.73k
      if (!succeeded) {
14802
1.67k
        update_base_hostname(previous_host);
14803
1.67k
        update_base_port(previous_port);
14804
1.67k
        return false;
14805
2.06k
      } else if (has_dash_dot()) {
14806
        // Should remove dash_dot from pathname
14807
0
        delete_dash_dot();
14808
0
      }
14809
2.06k
      return true;
14810
3.73k
    }
14811
8.26k
  }
14812
14813
736
  size_t location = new_host.find_first_of("/\\?");
14814
736
  if (location != std::string_view::npos) {
14815
673
    new_host.remove_suffix(new_host.length() - location);
14816
673
  }
14817
14818
736
  if (new_host.empty()) {
14819
    // Set url's host to the empty string.
14820
0
    clear_hostname();
14821
736
  } else {
14822
    // Let host be the result of host parsing buffer with url is not special.
14823
736
    if (!parse_host(new_host)) {
14824
733
      update_base_hostname(previous_host);
14825
733
      update_base_port(previous_port);
14826
733
      return false;
14827
733
    }
14828
14829
    // If host is "localhost", then set host to the empty string.
14830
3
    if (helpers::substring(buffer, components.host_start,
14831
3
                           components.host_end) == "localhost") {
14832
0
      clear_hostname();
14833
0
    }
14834
3
  }
14835
3
  ADA_ASSERT_TRUE(validate());
14836
3
  return true;
14837
736
}
14838
14839
9.00k
bool url_aggregator::set_host(const std::string_view input) {
14840
9.00k
  ada_log("url_aggregator::set_host '", input, "'");
14841
9.00k
  ADA_ASSERT_TRUE(validate());
14842
9.00k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14843
9.00k
  return set_host_or_hostname<false>(input);
14844
9.00k
}
14845
14846
9.00k
bool url_aggregator::set_hostname(const std::string_view input) {
14847
9.00k
  ada_log("url_aggregator::set_hostname '", input, "'");
14848
9.00k
  ADA_ASSERT_TRUE(validate());
14849
9.00k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14850
9.00k
  return set_host_or_hostname<true>(input);
14851
9.00k
}
14852
14853
12.0k
[[nodiscard]] std::string url_aggregator::get_origin() const {
14854
12.0k
  ada_log("url_aggregator::get_origin");
14855
12.0k
  if (is_special()) {
14856
    // Return a new opaque origin.
14857
10.6k
    if (type == scheme::FILE) {
14858
1.35k
      return "null";
14859
1.35k
    }
14860
14861
9.32k
    return helpers::concat(get_protocol(), "//", get_host());
14862
10.6k
  }
14863
14864
1.37k
  if (get_protocol() == "blob:") {
14865
481
    std::string_view path = get_pathname();
14866
481
    if (!path.empty()) {
14867
472
      auto out = ada::parse<ada::url_aggregator>(path);
14868
472
      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
20
        return helpers::concat(out->get_protocol(), "//", out->get_host());
14872
20
      }
14873
472
    }
14874
481
  }
14875
14876
  // Return a new opaque origin.
14877
1.35k
  return "null";
14878
1.37k
}
14879
14880
[[nodiscard]] std::string_view url_aggregator::get_username() const
14881
15.5k
    ada_lifetime_bound {
14882
15.5k
  ada_log("url_aggregator::get_username");
14883
15.5k
  if (has_non_empty_username()) {
14884
14.8k
    return helpers::substring(buffer, components.protocol_end + 2,
14885
14.8k
                              components.username_end);
14886
14.8k
  }
14887
738
  return "";
14888
15.5k
}
14889
14890
[[nodiscard]] std::string_view url_aggregator::get_password() const
14891
15.5k
    ada_lifetime_bound {
14892
15.5k
  ada_log("url_aggregator::get_password");
14893
15.5k
  if (has_non_empty_password()) {
14894
14.8k
    return helpers::substring(buffer, components.username_end + 1,
14895
14.8k
                              components.host_start);
14896
14.8k
  }
14897
738
  return "";
14898
15.5k
}
14899
14900
[[nodiscard]] std::string_view url_aggregator::get_port() const
14901
9.00k
    ada_lifetime_bound {
14902
9.00k
  ada_log("url_aggregator::get_port");
14903
9.00k
  if (components.port == url_components::omitted) {
14904
7.95k
    return "";
14905
7.95k
  }
14906
1.04k
  return helpers::substring(buffer, components.host_end + 1,
14907
1.04k
                            components.pathname_start);
14908
9.00k
}
14909
14910
[[nodiscard]] std::string_view url_aggregator::get_hash() const
14911
15.5k
    ada_lifetime_bound {
14912
15.5k
  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
15.5k
  if (components.hash_start == url_components::omitted) {
14916
2
    return "";
14917
2
  }
14918
15.5k
  if (buffer.size() - components.hash_start <= 1) {
14919
70
    return "";
14920
70
  }
14921
15.5k
  return helpers::substring(buffer, components.hash_start);
14922
15.5k
}
14923
14924
[[nodiscard]] std::string_view url_aggregator::get_host() const
14925
24.9k
    ada_lifetime_bound {
14926
24.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
24.9k
  size_t start = components.host_start;
14931
24.9k
  if (components.host_end > components.host_start &&
14932
24.9k
      buffer[components.host_start] == '@') {
14933
23.3k
    start++;
14934
23.3k
  }
14935
  // if we have an empty host, then the space between components.host_end and
14936
  // components.pathname_start may be occupied by /.
14937
24.9k
  if (start == components.host_end) {
14938
0
    return {};
14939
0
  }
14940
24.9k
  return helpers::substring(buffer, start, components.pathname_start);
14941
24.9k
}
14942
14943
[[nodiscard]] std::string_view url_aggregator::get_hostname() const
14944
53.4k
    ada_lifetime_bound {
14945
53.4k
  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
53.4k
  size_t start = components.host_start;
14950
  // So host_start is not where the host begins.
14951
53.4k
  if (components.host_end > components.host_start &&
14952
51.9k
      buffer[components.host_start] == '@') {
14953
37.2k
    start++;
14954
37.2k
  }
14955
53.4k
  return helpers::substring(buffer, start, components.host_end);
14956
53.4k
}
14957
14958
[[nodiscard]] std::string_view url_aggregator::get_search() const
14959
15.5k
    ada_lifetime_bound {
14960
15.5k
  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
15.5k
  if (components.search_start == url_components::omitted) {
14964
2
    return "";
14965
2
  }
14966
15.5k
  auto ending_index = uint32_t(buffer.size());
14967
15.5k
  if (components.hash_start != url_components::omitted) {
14968
15.5k
    ending_index = components.hash_start;
14969
15.5k
  }
14970
15.5k
  if (ending_index - components.search_start <= 1) {
14971
68
    return "";
14972
68
  }
14973
15.5k
  return helpers::substring(buffer, components.search_start, ending_index);
14974
15.5k
}
14975
14976
[[nodiscard]] std::string_view url_aggregator::get_protocol() const
14977
29.3k
    ada_lifetime_bound {
14978
29.3k
  ada_log("url_aggregator::get_protocol");
14979
29.3k
  return helpers::substring(buffer, 0, components.protocol_end);
14980
29.3k
}
14981
14982
9.00k
[[nodiscard]] std::string ada::url_aggregator::to_string() const {
14983
9.00k
  ada_log("url_aggregator::to_string buffer:", buffer, " [", buffer.size(),
14984
9.00k
          " bytes]");
14985
9.00k
  if (!is_valid) {
14986
2.41k
    return "null";
14987
2.41k
  }
14988
14989
6.58k
  std::string answer;
14990
6.58k
  auto back = std::back_insert_iterator(answer);
14991
6.58k
  answer.append("{\n");
14992
14993
6.58k
  answer.append("\t\"buffer\":\"");
14994
6.58k
  helpers::encode_json(buffer, back);
14995
6.58k
  answer.append("\",\n");
14996
14997
6.58k
  answer.append("\t\"protocol\":\"");
14998
6.58k
  helpers::encode_json(get_protocol(), back);
14999
6.58k
  answer.append("\",\n");
15000
15001
6.58k
  if (has_credentials()) {
15002
6.58k
    answer.append("\t\"username\":\"");
15003
6.58k
    helpers::encode_json(get_username(), back);
15004
6.58k
    answer.append("\",\n");
15005
6.58k
    answer.append("\t\"password\":\"");
15006
6.58k
    helpers::encode_json(get_password(), back);
15007
6.58k
    answer.append("\",\n");
15008
6.58k
  }
15009
15010
6.58k
  answer.append("\t\"host\":\"");
15011
6.58k
  helpers::encode_json(get_host(), back);
15012
6.58k
  answer.append("\",\n");
15013
15014
6.58k
  answer.append("\t\"path\":\"");
15015
6.58k
  helpers::encode_json(get_pathname(), back);
15016
6.58k
  answer.append("\",\n");
15017
6.58k
  answer.append("\t\"opaque path\":");
15018
6.58k
  answer.append((has_opaque_path ? "true" : "false"));
15019
6.58k
  answer.append(",\n");
15020
15021
6.58k
  if (components.search_start != url_components::omitted) {
15022
6.58k
    answer.append("\t\"query\":\"");
15023
6.58k
    helpers::encode_json(get_search(), back);
15024
6.58k
    answer.append("\",\n");
15025
6.58k
  }
15026
6.58k
  if (components.hash_start != url_components::omitted) {
15027
6.58k
    answer.append("\t\"fragment\":\"");
15028
6.58k
    helpers::encode_json(get_hash(), back);
15029
6.58k
    answer.append("\",\n");
15030
6.58k
  }
15031
15032
52.7k
  auto convert_offset_to_string = [](uint32_t offset) -> std::string {
15033
52.7k
    if (offset == url_components::omitted) {
15034
5.54k
      return "null";
15035
47.1k
    } else {
15036
47.1k
      return std::to_string(offset);
15037
47.1k
    }
15038
52.7k
  };
15039
15040
6.58k
  answer.append("\t\"protocol_end\":");
15041
6.58k
  answer.append(convert_offset_to_string(components.protocol_end));
15042
6.58k
  answer.append(",\n");
15043
15044
6.58k
  answer.append("\t\"username_end\":");
15045
6.58k
  answer.append(convert_offset_to_string(components.username_end));
15046
6.58k
  answer.append(",\n");
15047
15048
6.58k
  answer.append("\t\"host_start\":");
15049
6.58k
  answer.append(convert_offset_to_string(components.host_start));
15050
6.58k
  answer.append(",\n");
15051
15052
6.58k
  answer.append("\t\"host_end\":");
15053
6.58k
  answer.append(convert_offset_to_string(components.host_end));
15054
6.58k
  answer.append(",\n");
15055
15056
6.58k
  answer.append("\t\"port\":");
15057
6.58k
  answer.append(convert_offset_to_string(components.port));
15058
6.58k
  answer.append(",\n");
15059
15060
6.58k
  answer.append("\t\"pathname_start\":");
15061
6.58k
  answer.append(convert_offset_to_string(components.pathname_start));
15062
6.58k
  answer.append(",\n");
15063
15064
6.58k
  answer.append("\t\"search_start\":");
15065
6.58k
  answer.append(convert_offset_to_string(components.search_start));
15066
6.58k
  answer.append(",\n");
15067
15068
6.58k
  answer.append("\t\"hash_start\":");
15069
6.58k
  answer.append(convert_offset_to_string(components.hash_start));
15070
6.58k
  answer.append("\n}");
15071
15072
6.58k
  return answer;
15073
9.00k
}
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.27k
bool url_aggregator::parse_ipv4(std::string_view input, bool in_place) {
15083
2.27k
  ada_log("parse_ipv4 ", input, " [", input.size(),
15084
2.27k
          " bytes], overlaps with buffer: ",
15085
2.27k
          helpers::overlaps(input, buffer) ? "yes" : "no");
15086
2.27k
  ADA_ASSERT_TRUE(validate());
15087
2.27k
  const bool trailing_dot = (input.back() == '.');
15088
2.27k
  if (trailing_dot) {
15089
55
    input.remove_suffix(1);
15090
55
  }
15091
2.27k
  size_t digit_count{0};
15092
2.27k
  int pure_decimal_count = 0;  // entries that are decimal
15093
2.27k
  uint64_t ipv4{0};
15094
  // we could unroll for better performance?
15095
2.73k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
15096
2.71k
    uint32_t
15097
2.71k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
15098
2.71k
    bool is_hex = checkers::has_hex_prefix(input);
15099
2.71k
    if (is_hex && ((input.length() == 2) ||
15100
883
                   ((input.length() > 2) && (input[2] == '.')))) {
15101
      // special case
15102
56
      segment_result = 0;
15103
56
      input.remove_prefix(2);
15104
2.66k
    } else {
15105
2.66k
      std::from_chars_result r{};
15106
2.66k
      if (is_hex) {
15107
863
        ada_log("parse_ipv4 trying to parse hex number");
15108
863
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
15109
863
                            segment_result, 16);
15110
1.79k
      } else if ((input.length() >= 2) && input[0] == '0' &&
15111
516
                 checkers::is_digit(input[1])) {
15112
412
        ada_log("parse_ipv4 trying to parse octal number");
15113
412
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
15114
412
                            segment_result, 8);
15115
1.38k
      } else {
15116
1.38k
        ada_log("parse_ipv4 trying to parse decimal number");
15117
1.38k
        pure_decimal_count++;
15118
1.38k
        r = std::from_chars(input.data(), input.data() + input.size(),
15119
1.38k
                            segment_result, 10);
15120
1.38k
      }
15121
2.66k
      if (r.ec != std::errc()) {
15122
420
        ada_log("parse_ipv4 parsing failed");
15123
420
        return is_valid = false;
15124
420
      }
15125
2.24k
      ada_log("parse_ipv4 parsed ", segment_result);
15126
2.24k
      input.remove_prefix(r.ptr - input.data());
15127
2.24k
    }
15128
2.29k
    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.64k
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
15133
55
        return is_valid = false;
15134
55
      }
15135
1.58k
      ipv4 <<= (32 - digit_count * 8);
15136
1.58k
      ipv4 |= segment_result;
15137
1.58k
      goto final;
15138
1.64k
    } else {
15139
      // There is more, so that the value must no be larger than 255
15140
      // and we must have a '.'.
15141
654
      if ((segment_result > 255) || (input[0] != '.')) {
15142
192
        return is_valid = false;
15143
192
      }
15144
462
      ipv4 <<= 8;
15145
462
      ipv4 |= segment_result;
15146
462
      input.remove_prefix(1);  // remove '.'
15147
462
    }
15148
2.29k
  }
15149
20
  if ((digit_count != 4) || (!input.empty())) {
15150
20
    ada_log("parse_ipv4 found invalid (more than 4 numbers or empty) ");
15151
20
    return is_valid = false;
15152
20
  }
15153
1.58k
final:
15154
1.58k
  ada_log("url_aggregator::parse_ipv4 completed ", get_href(),
15155
1.58k
          " host: ", get_host());
15156
15157
  // We could also check r.ptr to see where the parsing ended.
15158
1.58k
  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.58k
  } else {
15165
1.58k
    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.58k
    update_base_hostname(
15171
1.58k
        ada::serializers::ipv4(ipv4));  // We have to reserialize the address.
15172
1.58k
  }
15173
1.58k
  host_type = IPV4;
15174
1.58k
  ADA_ASSERT_TRUE(validate());
15175
1.58k
  return true;
15176
20
}
15177
15178
420
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
420
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
15184
420
  ADA_ASSERT_TRUE(validate());
15185
420
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15186
420
  if (input.empty()) {
15187
25
    return is_valid = false;
15188
25
  }
15189
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
15190
395
  std::array<uint16_t, 8> address{};
15191
15192
  // Let pieceIndex be 0.
15193
395
  int piece_index = 0;
15194
15195
  // Let compress be null.
15196
395
  std::optional<int> compress{};
15197
15198
  // Let pointer be a pointer for input.
15199
395
  std::string_view::iterator pointer = input.begin();
15200
15201
  // If c is U+003A (:), then:
15202
395
  if (input[0] == ':') {
15203
    // If remaining does not start with U+003A (:), validation error, return
15204
    // failure.
15205
91
    if (input.size() == 1 || input[1] != ':') {
15206
18
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
15207
18
      return is_valid = false;
15208
18
    }
15209
15210
    // Increase pointer by 2.
15211
73
    pointer += 2;
15212
15213
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
15214
73
    compress = ++piece_index;
15215
73
  }
15216
15217
  // While c is not the EOF code point:
15218
907
  while (pointer != input.end()) {
15219
    // If pieceIndex is 8, validation error, return failure.
15220
726
    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
721
    if (*pointer == ':') {
15227
      // If compress is non-null, validation error, return failure.
15228
66
      if (compress.has_value()) {
15229
5
        ada_log("parse_ipv6 compress is non-null");
15230
5
        return is_valid = false;
15231
5
      }
15232
15233
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
15234
      // then continue.
15235
61
      pointer++;
15236
61
      compress = ++piece_index;
15237
61
      continue;
15238
66
    }
15239
15240
    // Let value and length be 0.
15241
655
    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.68k
    while (length < 4 && pointer != input.end() &&
15247
1.49k
           unicode::is_ascii_hex_digit(*pointer)) {
15248
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
15249
1.03k
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
15250
1.03k
      pointer++;
15251
1.03k
      length++;
15252
1.03k
    }
15253
15254
    // If c is U+002E (.), then:
15255
655
    if (pointer != input.end() && *pointer == '.') {
15256
      // If length is 0, validation error, return failure.
15257
78
      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
75
      pointer -= length;
15264
15265
      // If pieceIndex is greater than 6, validation error, return failure.
15266
75
      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
72
      int numbers_seen = 0;
15273
15274
      // While c is not the EOF code point:
15275
174
      while (pointer != input.end()) {
15276
        // Let ipv4Piece be null.
15277
158
        std::optional<uint16_t> ipv4_piece{};
15278
15279
        // If numbersSeen is greater than 0, then:
15280
158
        if (numbers_seen > 0) {
15281
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
15282
          // pointer by 1.
15283
86
          if (*pointer == '.' && numbers_seen < 4) {
15284
76
            pointer++;
15285
76
          } else {
15286
            // Otherwise, validation error, return failure.
15287
10
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
15288
10
            return is_valid = false;
15289
10
          }
15290
86
        }
15291
15292
        // If c is not an ASCII digit, validation error, return failure.
15293
148
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
15294
29
          ada_log(
15295
29
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
15296
29
              "failure");
15297
29
          return is_valid = false;
15298
29
        }
15299
15300
        // While c is an ASCII digit:
15301
316
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
15302
          // Let number be c interpreted as decimal number.
15303
214
          int number = *pointer - '0';
15304
15305
          // If ipv4Piece is null, then set ipv4Piece to number.
15306
214
          if (!ipv4_piece.has_value()) {
15307
119
            ipv4_piece = number;
15308
119
          }
15309
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
15310
95
          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
92
          else {
15316
92
            ipv4_piece = *ipv4_piece * 10 + number;
15317
92
          }
15318
15319
          // If ipv4Piece is greater than 255, validation error, return failure.
15320
211
          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
197
          pointer++;
15327
197
        }
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
102
        address[piece_index] =
15333
102
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
15334
15335
        // Increase numbersSeen by 1.
15336
102
        numbers_seen++;
15337
15338
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
15339
102
        if (numbers_seen == 2 || numbers_seen == 4) {
15340
36
          piece_index++;
15341
36
        }
15342
102
      }
15343
15344
      // If numbersSeen is not 4, validation error, return failure.
15345
16
      if (numbers_seen != 4) {
15346
13
        return is_valid = false;
15347
13
      }
15348
15349
      // Break.
15350
3
      break;
15351
16
    }
15352
    // Otherwise, if c is U+003A (:):
15353
577
    else if ((pointer != input.end()) && (*pointer == ':')) {
15354
      // Increase pointer by 1.
15355
347
      pointer++;
15356
15357
      // If c is the EOF code point, validation error, return failure.
15358
347
      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
347
    }
15365
    // Otherwise, if c is not the EOF code point, validation error, return
15366
    // failure.
15367
230
    else if (pointer != input.end()) {
15368
105
      ada_log(
15369
105
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
15370
105
          "error, return failure");
15371
105
      return is_valid = false;
15372
105
    }
15373
15374
    // Set address[pieceIndex] to value.
15375
469
    address[piece_index] = value;
15376
15377
    // Increase pieceIndex by 1.
15378
469
    piece_index++;
15379
469
  }
15380
15381
  // If compress is non-null, then:
15382
184
  if (compress.has_value()) {
15383
    // Let swaps be pieceIndex - compress.
15384
123
    int swaps = piece_index - *compress;
15385
15386
    // Set pieceIndex to 7.
15387
123
    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
249
    while (piece_index != 0 && swaps > 0) {
15393
126
      std::swap(address[piece_index], address[*compress + swaps - 1]);
15394
126
      piece_index--;
15395
126
      swaps--;
15396
126
    }
15397
123
  }
15398
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
15399
  // return failure.
15400
61
  else if (piece_index != 8) {
15401
52
    ada_log(
15402
52
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
15403
52
        "error, return failure");
15404
52
    return is_valid = false;
15405
52
  }
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
132
  update_base_hostname(ada::serializers::ipv6(address));
15410
132
  ada_log("parse_ipv6 ", get_hostname());
15411
132
  ADA_ASSERT_TRUE(validate());
15412
132
  host_type = IPV6;
15413
132
  return true;
15414
184
}
15415
15416
268
bool url_aggregator::parse_opaque_host(std::string_view input) {
15417
268
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
15418
268
  ADA_ASSERT_TRUE(validate());
15419
268
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15420
268
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
15421
28
    return is_valid = false;
15422
28
  }
15423
15424
  // Return the result of running UTF-8 percent-encode on input using the C0
15425
  // control percent-encode set.
15426
240
  size_t idx = ada::unicode::percent_encode_index(
15427
240
      input, character_sets::C0_CONTROL_PERCENT_ENCODE);
15428
240
  if (idx == input.size()) {
15429
138
    update_base_hostname(input);
15430
138
  } else {
15431
    // We only create a temporary string if we need to.
15432
102
    update_base_hostname(ada::unicode::percent_encode(
15433
102
        input, character_sets::C0_CONTROL_PERCENT_ENCODE, idx));
15434
102
  }
15435
240
  ADA_ASSERT_TRUE(validate());
15436
240
  return true;
15437
268
}
15438
15439
9.00k
[[nodiscard]] std::string url_aggregator::to_diagram() const {
15440
9.00k
  if (!is_valid) {
15441
2.41k
    return "invalid";
15442
2.41k
  }
15443
6.58k
  std::string answer;
15444
6.58k
  answer.append(buffer);
15445
6.58k
  answer.append(" [");
15446
6.58k
  answer.append(std::to_string(buffer.size()));
15447
6.58k
  answer.append(" bytes]");
15448
6.58k
  answer.append("\n");
15449
  // first line
15450
6.58k
  std::string line1;
15451
6.58k
  line1.resize(buffer.size(), ' ');
15452
6.58k
  if (components.hash_start != url_components::omitted) {
15453
6.58k
    line1[components.hash_start] = '|';
15454
6.58k
  }
15455
6.58k
  if (components.search_start != url_components::omitted) {
15456
6.58k
    line1[components.search_start] = '|';
15457
6.58k
  }
15458
6.58k
  if (components.pathname_start != buffer.size()) {
15459
6.58k
    line1[components.pathname_start] = '|';
15460
6.58k
  }
15461
6.58k
  if (components.host_end != buffer.size()) {
15462
6.58k
    line1[components.host_end] = '|';
15463
6.58k
  }
15464
6.58k
  if (components.host_start != buffer.size()) {
15465
6.58k
    line1[components.host_start] = '|';
15466
6.58k
  }
15467
6.58k
  if (components.username_end != buffer.size()) {
15468
6.58k
    line1[components.username_end] = '|';
15469
6.58k
  }
15470
6.58k
  if (components.protocol_end != buffer.size()) {
15471
6.58k
    line1[components.protocol_end] = '|';
15472
6.58k
  }
15473
6.58k
  answer.append(line1);
15474
6.58k
  answer.append("\n");
15475
15476
6.58k
  std::string line2 = line1;
15477
6.58k
  if (components.hash_start != url_components::omitted) {
15478
6.58k
    line2[components.hash_start] = '`';
15479
6.58k
    line1[components.hash_start] = ' ';
15480
15481
435k
    for (size_t i = components.hash_start + 1; i < line2.size(); i++) {
15482
428k
      line2[i] = '-';
15483
428k
    }
15484
6.58k
    line2.append(" hash_start");
15485
6.58k
    answer.append(line2);
15486
6.58k
    answer.append("\n");
15487
6.58k
  }
15488
15489
6.58k
  std::string line3 = line1;
15490
6.58k
  if (components.search_start != url_components::omitted) {
15491
6.58k
    line3[components.search_start] = '`';
15492
6.58k
    line1[components.search_start] = ' ';
15493
15494
872k
    for (size_t i = components.search_start + 1; i < line3.size(); i++) {
15495
865k
      line3[i] = '-';
15496
865k
    }
15497
6.58k
    line3.append(" search_start ");
15498
6.58k
    line3.append(std::to_string(components.search_start));
15499
6.58k
    answer.append(line3);
15500
6.58k
    answer.append("\n");
15501
6.58k
  }
15502
15503
6.58k
  std::string line4 = line1;
15504
6.58k
  if (components.pathname_start != buffer.size()) {
15505
6.58k
    line4[components.pathname_start] = '`';
15506
6.58k
    line1[components.pathname_start] = ' ';
15507
1.27M
    for (size_t i = components.pathname_start + 1; i < line4.size(); i++) {
15508
1.26M
      line4[i] = '-';
15509
1.26M
    }
15510
6.58k
    line4.append(" pathname_start ");
15511
6.58k
    line4.append(std::to_string(components.pathname_start));
15512
6.58k
    answer.append(line4);
15513
6.58k
    answer.append("\n");
15514
6.58k
  }
15515
15516
6.58k
  std::string line5 = line1;
15517
6.58k
  if (components.host_end != buffer.size()) {
15518
6.58k
    line5[components.host_end] = '`';
15519
6.58k
    line1[components.host_end] = ' ';
15520
15521
1.27M
    for (size_t i = components.host_end + 1; i < line5.size(); i++) {
15522
1.26M
      line5[i] = '-';
15523
1.26M
    }
15524
6.58k
    line5.append(" host_end ");
15525
6.58k
    line5.append(std::to_string(components.host_end));
15526
6.58k
    answer.append(line5);
15527
6.58k
    answer.append("\n");
15528
6.58k
  }
15529
15530
6.58k
  std::string line6 = line1;
15531
6.58k
  if (components.host_start != buffer.size()) {
15532
6.58k
    line6[components.host_start] = '`';
15533
6.58k
    line1[components.host_start] = ' ';
15534
15535
1.47M
    for (size_t i = components.host_start + 1; i < line6.size(); i++) {
15536
1.46M
      line6[i] = '-';
15537
1.46M
    }
15538
6.58k
    line6.append(" host_start ");
15539
6.58k
    line6.append(std::to_string(components.host_start));
15540
6.58k
    answer.append(line6);
15541
6.58k
    answer.append("\n");
15542
6.58k
  }
15543
15544
6.58k
  std::string line7 = line1;
15545
6.58k
  if (components.username_end != buffer.size()) {
15546
6.58k
    line7[components.username_end] = '`';
15547
6.58k
    line1[components.username_end] = ' ';
15548
15549
1.98M
    for (size_t i = components.username_end + 1; i < line7.size(); i++) {
15550
1.98M
      line7[i] = '-';
15551
1.98M
    }
15552
6.58k
    line7.append(" username_end ");
15553
6.58k
    line7.append(std::to_string(components.username_end));
15554
6.58k
    answer.append(line7);
15555
6.58k
    answer.append("\n");
15556
6.58k
  }
15557
15558
6.58k
  std::string line8 = line1;
15559
6.58k
  if (components.protocol_end != buffer.size()) {
15560
6.58k
    line8[components.protocol_end] = '`';
15561
6.58k
    line1[components.protocol_end] = ' ';
15562
15563
2.51M
    for (size_t i = components.protocol_end + 1; i < line8.size(); i++) {
15564
2.50M
      line8[i] = '-';
15565
2.50M
    }
15566
6.58k
    line8.append(" protocol_end ");
15567
6.58k
    line8.append(std::to_string(components.protocol_end));
15568
6.58k
    answer.append(line8);
15569
6.58k
    answer.append("\n");
15570
6.58k
  }
15571
15572
6.58k
  if (components.hash_start == url_components::omitted) {
15573
2
    answer.append("note: hash omitted\n");
15574
2
  }
15575
6.58k
  if (components.search_start == url_components::omitted) {
15576
2
    answer.append("note: search omitted\n");
15577
2
  }
15578
6.58k
  if (components.protocol_end > buffer.size()) {
15579
0
    answer.append("warning: protocol_end overflows\n");
15580
0
  }
15581
6.58k
  if (components.username_end > buffer.size()) {
15582
0
    answer.append("warning: username_end overflows\n");
15583
0
  }
15584
6.58k
  if (components.host_start > buffer.size()) {
15585
0
    answer.append("warning: host_start overflows\n");
15586
0
  }
15587
6.58k
  if (components.host_end > buffer.size()) {
15588
0
    answer.append("warning: host_end overflows\n");
15589
0
  }
15590
6.58k
  if (components.pathname_start > buffer.size()) {
15591
0
    answer.append("warning: pathname_start overflows\n");
15592
0
  }
15593
6.58k
  return answer;
15594
9.00k
}
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
11.5k
inline void url_aggregator::consume_prepared_path(std::string_view input) {
15613
11.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
11.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
11.5k
  constexpr uint8_t need_encoding = 1;
15629
11.5k
  constexpr uint8_t backslash_char = 2;
15630
11.5k
  constexpr uint8_t dot_char = 4;
15631
11.5k
  constexpr uint8_t percent_char = 8;
15632
11.5k
  bool special = type != ada::scheme::NOT_SPECIAL;
15633
11.5k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
15634
1.61k
                                      checkers::is_windows_drive_letter(input));
15635
11.5k
  bool trivial_path =
15636
11.5k
      (special ? (accumulator == 0)
15637
11.5k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
15638
928
                  0)) &&
15639
2.13k
      (!may_need_slow_file_handling);
15640
11.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.46k
    if (input[0] != '.') {
15649
1.78k
      size_t slashdot = 0;
15650
1.78k
      bool dot_is_file = true;
15651
8.61k
      for (;;) {
15652
8.61k
        slashdot = input.find("/.", slashdot);
15653
8.61k
        if (slashdot == std::string_view::npos) {  // common case
15654
1.78k
          break;
15655
6.82k
        } else {  // uncommon
15656
          // only three cases matter: /./, /.. or a final /
15657
6.82k
          slashdot += 2;
15658
6.82k
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
15659
1.35k
                           input[slashdot] == '/');
15660
6.82k
        }
15661
8.61k
      }
15662
1.78k
      trivial_path = dot_is_file;
15663
1.78k
    }
15664
2.46k
  }
15665
11.5k
  if (trivial_path && is_at_path()) {
15666
2.78k
    ada_log("parse_path trivial");
15667
2.78k
    buffer += '/';
15668
2.78k
    buffer += input;
15669
2.78k
    return;
15670
2.78k
  }
15671
8.71k
  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
8.71k
  bool fast_path =
15677
8.71k
      (special &&
15678
7.88k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
15679
1.65k
      (type != ada::scheme::type::FILE);
15680
8.71k
  if (fast_path) {
15681
1.28k
    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.28k
    size_t previous_location = 0;  // We start at 0.
15687
16.8k
    do {
15688
16.8k
      size_t new_location = input.find('/', previous_location);
15689
      // std::string_view path_view = input;
15690
      //  We process the last segment separately:
15691
16.8k
      if (new_location == std::string_view::npos) {
15692
1.28k
        std::string_view path_view = input.substr(previous_location);
15693
1.28k
        if (path_view == "..") {  // The path ends with ..
15694
          // e.g., if you receive ".." with an empty path, you go to "/".
15695
172
          if (path.empty()) {
15696
67
            path = '/';
15697
67
            update_base_pathname(path);
15698
67
            return;
15699
67
          }
15700
          // Fast case where we have nothing to do:
15701
105
          if (path.back() == '/') {
15702
40
            update_base_pathname(path);
15703
40
            return;
15704
40
          }
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
105
        }
15711
1.11k
        path += '/';
15712
1.11k
        if (path_view != ".") {
15713
870
          path.append(path_view);
15714
870
        }
15715
1.11k
        update_base_pathname(path);
15716
1.11k
        return;
15717
15.6k
      } else {
15718
        // This is a non-final segment.
15719
15.6k
        std::string_view path_view =
15720
15.6k
            input.substr(previous_location, new_location - previous_location);
15721
15.6k
        previous_location = new_location + 1;
15722
15.6k
        if (path_view == "..") {
15723
3.77k
          size_t last_delimiter = path.rfind('/');
15724
3.77k
          if (last_delimiter != std::string::npos) {
15725
1.82k
            path.erase(last_delimiter);
15726
1.82k
          }
15727
11.8k
        } else if (path_view != ".") {
15728
10.1k
          path += '/';
15729
10.1k
          path.append(path_view);
15730
10.1k
        }
15731
15.6k
      }
15732
16.8k
    } while (true);
15733
7.43k
  } else {
15734
7.43k
    ada_log("parse_path slow");
15735
    // we have reached the general case
15736
7.43k
    bool needs_percent_encoding = (accumulator & 1);
15737
7.43k
    std::string path_buffer_tmp;
15738
42.4k
    do {
15739
42.4k
      size_t location = (special && (accumulator & 2))
15740
42.4k
                            ? input.find_first_of("/\\")
15741
42.4k
                            : input.find('/');
15742
42.4k
      std::string_view path_view = input;
15743
42.4k
      if (location != std::string_view::npos) {
15744
34.9k
        path_view.remove_suffix(path_view.size() - location);
15745
34.9k
        input.remove_prefix(location + 1);
15746
34.9k
      }
15747
      // path_buffer is either path_view or it might point at a percent encoded
15748
      // temporary string.
15749
42.4k
      std::string_view path_buffer =
15750
42.4k
          (needs_percent_encoding &&
15751
27.9k
           ada::unicode::percent_encode<false>(
15752
27.9k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
15753
42.4k
              ? path_buffer_tmp
15754
42.4k
              : path_view;
15755
42.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
833
          path += '/';
15759
833
        }
15760
32.3k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
15761
1.89k
                 (location == std::string_view::npos)) {
15762
159
        path += '/';
15763
159
      }
15764
      // Otherwise, if path_buffer is not a single-dot path segment, then:
15765
32.1k
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
15766
        // If url's scheme is "file", url's path is empty, and path_buffer is a
15767
        // Windows drive letter, then replace the second code point in
15768
        // path_buffer with U+003A (:).
15769
30.4k
        if (type == ada::scheme::type::FILE && path.empty() &&
15770
4.07k
            checkers::is_windows_drive_letter(path_buffer)) {
15771
156
          path += '/';
15772
156
          path += path_buffer[0];
15773
156
          path += ':';
15774
156
          path_buffer.remove_prefix(2);
15775
156
          path.append(path_buffer);
15776
30.2k
        } else {
15777
          // Append path_buffer to url's path.
15778
30.2k
          path += '/';
15779
30.2k
          path.append(path_buffer);
15780
30.2k
        }
15781
30.4k
      }
15782
42.4k
      if (location == std::string_view::npos) {
15783
7.43k
        update_base_pathname(path);
15784
7.43k
        return;
15785
7.43k
      }
15786
42.4k
    } while (true);
15787
7.43k
  }
15788
8.71k
}
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 */