Coverage Report

Created: 2026-01-09 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ada-url/build/singleheader/ada.cpp
Line
Count
Source
1
/* auto-generated on 2026-01-08 10:25:21 -0500. Do not edit! */
2
/* begin file src/ada.cpp */
3
#include "ada.h"
4
/* begin file src/checkers.cpp */
5
6
#include <algorithm>
7
#include <array>
8
#include <string_view>
9
10
namespace ada::checkers {
11
12
40.8k
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
40.8k
  if (view.ends_with('.')) {
21
1.60k
    view.remove_suffix(1);
22
1.60k
    if (view.empty()) {
23
676
      return false;
24
676
    }
25
1.60k
  }
26
40.1k
  char last_char = view.back();
27
40.1k
  bool possible_ipv4 = (last_char >= '0' && last_char <= '9') ||
28
36.1k
                       (last_char >= 'a' && last_char <= 'f') ||
29
28.8k
                       last_char == 'x';
30
40.1k
  if (!possible_ipv4) {
31
28.1k
    return false;
32
28.1k
  }
33
  // From the last character, find the last dot.
34
12.0k
  size_t last_dot = view.rfind('.');
35
12.0k
  if (last_dot != std::string_view::npos) {
36
    // We have at least one dot.
37
3.11k
    view = view.substr(last_dot + 1);
38
3.11k
  }
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
12.0k
  if (std::ranges::all_of(view, ada::checkers::is_digit)) {
43
2.79k
    return true;
44
2.79k
  }
45
  // It could be hex (0x), but not if there is a single character.
46
9.23k
  if (view.size() == 1) {
47
1.42k
    return false;
48
1.42k
  }
49
  // It must start with 0x.
50
7.81k
  if (!view.starts_with("0x")) {
51
5.75k
    return false;
52
5.75k
  }
53
  // We must allow "0x".
54
2.05k
  if (view.size() == 2) {
55
96
    return true;
56
96
  }
57
  // We have 0x followed by some characters, we need to check that they are
58
  // hexadecimals.
59
1.96k
  view.remove_prefix(2);
60
1.96k
  return std::ranges::all_of(view, ada::unicode::is_lowercase_hex);
61
2.05k
}
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
33.2k
    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
33.2k
  size_t i = 0;
94
33.2k
  uint8_t accumulator{};
95
157k
  for (; i + 7 < input.size(); i += 8) {
96
123k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])] |
97
123k
                           path_signature_table[uint8_t(input[i + 1])] |
98
123k
                           path_signature_table[uint8_t(input[i + 2])] |
99
123k
                           path_signature_table[uint8_t(input[i + 3])] |
100
123k
                           path_signature_table[uint8_t(input[i + 4])] |
101
123k
                           path_signature_table[uint8_t(input[i + 5])] |
102
123k
                           path_signature_table[uint8_t(input[i + 6])] |
103
123k
                           path_signature_table[uint8_t(input[i + 7])]);
104
123k
  }
105
147k
  for (; i < input.size(); i++) {
106
113k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])]);
107
113k
  }
108
33.2k
  return accumulator;
109
33.2k
}
110
111
ada_really_inline constexpr bool verify_dns_length(
112
9.27k
    std::string_view input) noexcept {
113
9.27k
  if (input.back() == '.') {
114
964
    if (input.size() > 254) return false;
115
8.30k
  } else if (input.size() > 253)
116
45
    return false;
117
118
9.22k
  size_t start = 0;
119
28.8k
  while (start < input.size()) {
120
21.6k
    auto dot_location = input.find('.', start);
121
    // If not found, it's likely the end of the domain
122
21.6k
    if (dot_location == std::string_view::npos) dot_location = input.size();
123
124
21.6k
    auto label_size = dot_location - start;
125
21.6k
    if (label_size > 63 || label_size == 0) return false;
126
127
19.6k
    start = dot_location + 1;
128
19.6k
  }
129
130
7.17k
  return true;
131
9.22k
}
132
}  // namespace ada::checkers
133
/* end file src/checkers.cpp */
134
/* begin file src/unicode.cpp */
135
136
137
ADA_PUSH_DISABLE_ALL_WARNINGS
138
/* begin file src/ada_idna.cpp */
139
/* auto-generated on 2025-06-26 23:04:30 -0300. Do not edit! */
140
/* begin file src/idna.cpp */
141
/* begin file src/unicode_transcoding.cpp */
142
143
#include <algorithm>
144
#include <cstdint>
145
#include <cstring>
146
147
namespace ada::idna {
148
149
11.2k
size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) {
150
11.2k
  const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
151
11.2k
  size_t pos = 0;
152
11.2k
  const char32_t* start{utf32_output};
153
164k
  while (pos < len) {
154
    // try to convert the next block of 16 ASCII bytes
155
155k
    if (pos + 16 <= len) {  // if it is safe to read 16 more
156
                            // bytes, check that they are ascii
157
108k
      uint64_t v1;
158
108k
      std::memcpy(&v1, data + pos, sizeof(uint64_t));
159
108k
      uint64_t v2;
160
108k
      std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
161
108k
      uint64_t v{v1 | v2};
162
108k
      if ((v & 0x8080808080808080) == 0) {
163
2.00k
        size_t final_pos = pos + 16;
164
34.0k
        while (pos < final_pos) {
165
32.0k
          *utf32_output++ = char32_t(buf[pos]);
166
32.0k
          pos++;
167
32.0k
        }
168
2.00k
        continue;
169
2.00k
      }
170
108k
    }
171
153k
    uint8_t leading_byte = data[pos];  // leading byte
172
153k
    if (leading_byte < 0b10000000) {
173
      // converting one ASCII byte !!!
174
64.6k
      *utf32_output++ = char32_t(leading_byte);
175
64.6k
      pos++;
176
88.7k
    } else if ((leading_byte & 0b11100000) == 0b11000000) {
177
      // We have a two-byte UTF-8
178
10.4k
      if (pos + 1 >= len) {
179
208
        return 0;
180
208
      }  // minimal bound checking
181
10.1k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
182
216
        return 0;
183
216
      }
184
      // range check
185
9.98k
      uint32_t code_point =
186
9.98k
          (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
187
9.98k
      if (code_point < 0x80 || 0x7ff < code_point) {
188
14
        return 0;
189
14
      }
190
9.96k
      *utf32_output++ = char32_t(code_point);
191
9.96k
      pos += 2;
192
78.3k
    } else if ((leading_byte & 0b11110000) == 0b11100000) {
193
      // We have a three-byte UTF-8
194
75.5k
      if (pos + 2 >= len) {
195
78
        return 0;
196
78
      }  // minimal bound checking
197
198
75.4k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
199
94
        return 0;
200
94
      }
201
75.3k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
202
30
        return 0;
203
30
      }
204
      // range check
205
75.3k
      uint32_t code_point = (leading_byte & 0b00001111) << 12 |
206
75.3k
                            (data[pos + 1] & 0b00111111) << 6 |
207
75.3k
                            (data[pos + 2] & 0b00111111);
208
75.3k
      if (code_point < 0x800 || 0xffff < code_point ||
209
75.3k
          (0xd7ff < code_point && code_point < 0xe000)) {
210
32
        return 0;
211
32
      }
212
75.2k
      *utf32_output++ = char32_t(code_point);
213
75.2k
      pos += 3;
214
75.2k
    } else if ((leading_byte & 0b11111000) == 0b11110000) {  // 0b11110000
215
      // we have a 4-byte UTF-8 word.
216
1.30k
      if (pos + 3 >= len) {
217
86
        return 0;
218
86
      }  // minimal bound checking
219
1.21k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
220
40
        return 0;
221
40
      }
222
1.17k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
223
26
        return 0;
224
26
      }
225
1.15k
      if ((data[pos + 3] & 0b11000000) != 0b10000000) {
226
34
        return 0;
227
34
      }
228
229
      // range check
230
1.11k
      uint32_t code_point = (leading_byte & 0b00000111) << 18 |
231
1.11k
                            (data[pos + 1] & 0b00111111) << 12 |
232
1.11k
                            (data[pos + 2] & 0b00111111) << 6 |
233
1.11k
                            (data[pos + 3] & 0b00111111);
234
1.11k
      if (code_point <= 0xffff || 0x10ffff < code_point) {
235
40
        return 0;
236
40
      }
237
1.07k
      *utf32_output++ = char32_t(code_point);
238
1.07k
      pos += 4;
239
1.50k
    } else {
240
1.50k
      return 0;
241
1.50k
    }
242
153k
  }
243
8.89k
  return utf32_output - start;
244
11.2k
}
245
246
0
size_t utf8_length_from_utf32(const char32_t* buf, size_t len) {
247
  // We are not BOM aware.
248
0
  const uint32_t* p = reinterpret_cast<const uint32_t*>(buf);
249
0
  size_t counter{0};
250
0
  for (size_t i = 0; i != len; ++i) {
251
0
    ++counter;                                      // ASCII
252
0
    counter += static_cast<size_t>(p[i] > 0x7F);    // two-byte
253
0
    counter += static_cast<size_t>(p[i] > 0x7FF);   // three-byte
254
0
    counter += static_cast<size_t>(p[i] > 0xFFFF);  // four-bytes
255
0
  }
256
0
  return counter;
257
0
}
258
259
11.2k
size_t utf32_length_from_utf8(const char* buf, size_t len) {
260
11.2k
  const int8_t* p = reinterpret_cast<const int8_t*>(buf);
261
404k
  return std::count_if(p, std::next(p, len), [](int8_t c) {
262
    // -65 is 0b10111111, anything larger in two-complement's
263
    // should start a new code point.
264
404k
    return c > -65;
265
404k
  });
266
11.2k
}
267
268
0
size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) {
269
0
  const uint32_t* data = reinterpret_cast<const uint32_t*>(buf);
270
0
  size_t pos = 0;
271
0
  const char* start{utf8_output};
272
0
  while (pos < len) {
273
    // try to convert the next block of 2 ASCII characters
274
0
    if (pos + 2 <= len) {  // if it is safe to read 8 more
275
                           // bytes, check that they are ascii
276
0
      uint64_t v;
277
0
      std::memcpy(&v, data + pos, sizeof(uint64_t));
278
0
      if ((v & 0xFFFFFF80FFFFFF80) == 0) {
279
0
        *utf8_output++ = char(buf[pos]);
280
0
        *utf8_output++ = char(buf[pos + 1]);
281
0
        pos += 2;
282
0
        continue;
283
0
      }
284
0
    }
285
0
    uint32_t word = data[pos];
286
0
    if ((word & 0xFFFFFF80) == 0) {
287
      // will generate one UTF-8 bytes
288
0
      *utf8_output++ = char(word);
289
0
      pos++;
290
0
    } else if ((word & 0xFFFFF800) == 0) {
291
      // will generate two UTF-8 bytes
292
      // we have 0b110XXXXX 0b10XXXXXX
293
0
      *utf8_output++ = char((word >> 6) | 0b11000000);
294
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
295
0
      pos++;
296
0
    } else if ((word & 0xFFFF0000) == 0) {
297
      // will generate three UTF-8 bytes
298
      // we have 0b1110XXXX 0b10XXXXXX 0b10XXXXXX
299
0
      if (word >= 0xD800 && word <= 0xDFFF) {
300
0
        return 0;
301
0
      }
302
0
      *utf8_output++ = char((word >> 12) | 0b11100000);
303
0
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
304
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
305
0
      pos++;
306
0
    } else {
307
      // will generate four UTF-8 bytes
308
      // we have 0b11110XXX 0b10XXXXXX 0b10XXXXXX
309
      // 0b10XXXXXX
310
0
      if (word > 0x10FFFF) {
311
0
        return 0;
312
0
      }
313
0
      *utf8_output++ = char((word >> 18) | 0b11110000);
314
0
      *utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
315
0
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
316
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
317
0
      pos++;
318
0
    }
319
0
  }
320
0
  return utf8_output - start;
321
0
}
322
}  // namespace ada::idna
323
/* end file src/unicode_transcoding.cpp */
324
/* begin file src/mapping.cpp */
325
326
#include <algorithm>
327
#include <array>
328
#include <string>
329
330
/* begin file src/mapping_tables.cpp */
331
// IDNA  16.0.0
332
333
// clang-format off
334
#ifndef ADA_IDNA_TABLES_H
335
#define ADA_IDNA_TABLES_H
336
#include <cstdint>
337
338
namespace ada::idna {
339
340
const uint32_t mappings[5236] =
341
{
342
  97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
343
  114, 115, 116, 117, 118, 119, 120, 121, 122, 32, 32, 776, 32, 772, 50, 51, 32, 769,
344
  956, 32, 807, 49, 49, 8260, 52, 49, 8260, 50, 51, 8260, 52, 224, 225, 226, 227,
345
  228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
346
  244, 245, 246, 248, 249, 250, 251, 252, 253, 254, 257, 259, 261, 263, 265, 267,
347
  269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299,
348
  301, 303, 105, 775, 309, 311, 314, 316, 318, 108, 183, 322, 324, 326, 328, 700,
349
  110, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359,
350
  361, 363, 365, 367, 369, 371, 373, 375, 255, 378, 380, 382, 595, 387, 389, 596,
351
  392, 598, 599, 396, 477, 601, 603, 402, 608, 611, 617, 616, 409, 623, 626, 629,
352
  417, 419, 421, 640, 424, 643, 429, 648, 432, 650, 651, 436, 438, 658, 441, 445,
353
  100, 382, 108, 106, 110, 106, 462, 464, 466, 468, 470, 472, 474, 476, 479, 481,
354
  483, 485, 487, 489, 491, 493, 495, 100, 122, 501, 405, 447, 505, 507, 509, 511,
355
  513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535, 537, 539, 541, 543,
356
  414, 547, 549, 551, 553, 555, 557, 559, 561, 563, 11365, 572, 410, 11366, 578, 384,
357
  649, 652, 583, 585, 587, 589, 591, 614, 633, 635, 641, 32, 774, 32, 775, 32, 778,
358
  32, 808, 32, 771, 32, 779, 661, 768, 787, 776, 769, 953, 881, 883, 697, 887, 32,
359
  953, 59, 1011, 32, 776, 769, 940, 941, 942, 943, 972, 973, 974, 945, 946, 947, 948,
360
  949, 950, 951, 952, 954, 955, 957, 958, 959, 960, 961, 963, 964, 965, 966, 967,
361
  968, 969, 970, 971, 983, 985, 987, 989, 991, 993, 995, 997, 999, 1001, 1003, 1005,
362
  1007, 1016, 1019, 891, 892, 893, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111,
363
  1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1072, 1073, 1074, 1075, 1076, 1077,
364
  1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091,
365
  1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1121, 1123,
366
  1125, 1127, 1129, 1131, 1133, 1135, 1137, 1139, 1141, 1143, 1145, 1147, 1149, 1151,
367
  1153, 1163, 1165, 1167, 1169, 1171, 1173, 1175, 1177, 1179, 1181, 1183, 1185, 1187,
368
  1189, 1191, 1193, 1195, 1197, 1199, 1201, 1203, 1205, 1207, 1209, 1211, 1213, 1215,
369
  1231, 1218, 1220, 1222, 1224, 1226, 1228, 1230, 1233, 1235, 1237, 1239, 1241, 1243,
370
  1245, 1247, 1249, 1251, 1253, 1255, 1257, 1259, 1261, 1263, 1265, 1267, 1269, 1271,
371
  1273, 1275, 1277, 1279, 1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, 1297, 1299,
372
  1301, 1303, 1305, 1307, 1309, 1311, 1313, 1315, 1317, 1319, 1321, 1323, 1325, 1327,
373
  1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390,
374
  1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404,
375
  1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1381, 1410, 1575, 1652,
376
  1608, 1652, 1735, 1652, 1610, 1652, 2325, 2364, 2326, 2364, 2327, 2364, 2332, 2364,
377
  2337, 2364, 2338, 2364, 2347, 2364, 2351, 2364, 2465, 2492, 2466, 2492, 2479, 2492,
378
  2610, 2620, 2616, 2620, 2582, 2620, 2583, 2620, 2588, 2620, 2603, 2620, 2849, 2876,
379
  2850, 2876, 3661, 3634, 3789, 3762, 3755, 3737, 3755, 3745, 3851, 3906, 4023, 3916,
380
  4023, 3921, 4023, 3926, 4023, 3931, 4023, 3904, 4021, 3953, 3954, 3953, 3956, 4018,
381
  3968, 4018, 3953, 3968, 4019, 3968, 4019, 3953, 3968, 3986, 4023, 3996, 4023, 4001,
382
  4023, 4006, 4023, 4011, 4023, 3984, 4021, 11520, 11521, 11522, 11523, 11524, 11525,
383
  11526, 11527, 11528, 11529, 11530, 11531, 11532, 11533, 11534, 11535, 11536, 11537,
384
  11538, 11539, 11540, 11541, 11542, 11543, 11544, 11545, 11546, 11547, 11548, 11549,
385
  11550, 11551, 11552, 11553, 11554, 11555, 11556, 11557, 11559, 11565, 4316, 5104,
386
  5105, 5106, 5107, 5108, 5109, 42571, 7306, 4304, 4305, 4306, 4307, 4308, 4309, 4310,
387
  4311, 4312, 4313, 4314, 4315, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325,
388
  4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339,
389
  4340, 4341, 4342, 4343, 4344, 4345, 4346, 4349, 4350, 4351, 592, 593, 7426, 604,
390
  7446, 7447, 7453, 7461, 594, 597, 607, 609, 613, 618, 7547, 669, 621, 7557, 671,
391
  625, 624, 627, 628, 632, 642, 427, 7452, 656, 657, 7681, 7683, 7685, 7687, 7689,
392
  7691, 7693, 7695, 7697, 7699, 7701, 7703, 7705, 7707, 7709, 7711, 7713, 7715, 7717,
393
  7719, 7721, 7723, 7725, 7727, 7729, 7731, 7733, 7735, 7737, 7739, 7741, 7743, 7745,
394
  7747, 7749, 7751, 7753, 7755, 7757, 7759, 7761, 7763, 7765, 7767, 7769, 7771, 7773,
395
  7775, 7777, 7779, 7781, 7783, 7785, 7787, 7789, 7791, 7793, 7795, 7797, 7799, 7801,
396
  7803, 7805, 7807, 7809, 7811, 7813, 7815, 7817, 7819, 7821, 7823, 7825, 7827, 7829,
397
  97, 702, 223, 7841, 7843, 7845, 7847, 7849, 7851, 7853, 7855, 7857, 7859, 7861,
398
  7863, 7865, 7867, 7869, 7871, 7873, 7875, 7877, 7879, 7881, 7883, 7885, 7887, 7889,
399
  7891, 7893, 7895, 7897, 7899, 7901, 7903, 7905, 7907, 7909, 7911, 7913, 7915, 7917,
400
  7919, 7921, 7923, 7925, 7927, 7929, 7931, 7933, 7935, 7936, 7937, 7938, 7939, 7940,
401
  7941, 7942, 7943, 7952, 7953, 7954, 7955, 7956, 7957, 7968, 7969, 7970, 7971, 7972,
402
  7973, 7974, 7975, 7984, 7985, 7986, 7987, 7988, 7989, 7990, 7991, 8000, 8001, 8002,
403
  8003, 8004, 8005, 8017, 8019, 8021, 8023, 8032, 8033, 8034, 8035, 8036, 8037, 8038,
404
  8039, 7936, 953, 7937, 953, 7938, 953, 7939, 953, 7940, 953, 7941, 953, 7942, 953,
405
  7943, 953, 7968, 953, 7969, 953, 7970, 953, 7971, 953, 7972, 953, 7973, 953, 7974,
406
  953, 7975, 953, 8032, 953, 8033, 953, 8034, 953, 8035, 953, 8036, 953, 8037, 953,
407
  8038, 953, 8039, 953, 8048, 953, 945, 953, 940, 953, 8118, 953, 8112, 8113, 32,
408
  787, 32, 834, 32, 776, 834, 8052, 953, 951, 953, 942, 953, 8134, 953, 8050, 32,
409
  787, 768, 32, 787, 769, 32, 787, 834, 912, 8144, 8145, 8054, 32, 788, 768, 32, 788,
410
  769, 32, 788, 834, 944, 8160, 8161, 8058, 8165, 32, 776, 768, 96, 8060, 953, 969,
411
  953, 974, 953, 8182, 953, 8056, 8208, 32, 819, 8242, 8242, 8242, 8242, 8242, 8245,
412
  8245, 8245, 8245, 8245, 33, 33, 32, 773, 63, 63, 63, 33, 33, 63, 48, 53, 54, 55,
413
  56, 57, 43, 8722, 61, 40, 41, 97, 47, 99, 97, 47, 115, 176, 99, 99, 47, 111, 99,
414
  47, 117, 176, 102, 115, 109, 116, 101, 108, 116, 109, 8526, 1488, 1489, 1490, 1491,
415
  102, 97, 120, 8721, 49, 8260, 55, 49, 8260, 57, 49, 8260, 49, 48, 49, 8260, 51,
416
  50, 8260, 51, 49, 8260, 53, 50, 8260, 53, 51, 8260, 53, 52, 8260, 53, 49, 8260,
417
  54, 53, 8260, 54, 49, 8260, 56, 51, 8260, 56, 53, 8260, 56, 55, 8260, 56, 105, 105,
418
  105, 105, 105, 105, 118, 118, 105, 118, 105, 105, 118, 105, 105, 105, 105, 120,
419
  120, 105, 120, 105, 105, 8580, 48, 8260, 51, 8747, 8747, 8747, 8747, 8747, 8750,
420
  8750, 8750, 8750, 8750, 12296, 12297, 49, 50, 49, 51, 49, 52, 49, 53, 49, 54, 49,
421
  55, 49, 56, 49, 57, 50, 48, 40, 49, 41, 40, 50, 41, 40, 51, 41, 40, 52, 41, 40,
422
  53, 41, 40, 54, 41, 40, 55, 41, 40, 56, 41, 40, 57, 41, 40, 49, 48, 41, 40, 49,
423
  49, 41, 40, 49, 50, 41, 40, 49, 51, 41, 40, 49, 52, 41, 40, 49, 53, 41, 40, 49,
424
  54, 41, 40, 49, 55, 41, 40, 49, 56, 41, 40, 49, 57, 41, 40, 50, 48, 41, 40, 97,
425
  41, 40, 98, 41, 40, 99, 41, 40, 100, 41, 40, 101, 41, 40, 102, 41, 40, 103, 41,
426
  40, 104, 41, 40, 105, 41, 40, 106, 41, 40, 107, 41, 40, 108, 41, 40, 109, 41, 40,
427
  110, 41, 40, 111, 41, 40, 112, 41, 40, 113, 41, 40, 114, 41, 40, 115, 41, 40, 116,
428
  41, 40, 117, 41, 40, 118, 41, 40, 119, 41, 40, 120, 41, 40, 121, 41, 40, 122, 41,
429
  58, 58, 61, 61, 61, 10973, 824, 11312, 11313, 11314, 11315, 11316, 11317, 11318,
430
  11319, 11320, 11321, 11322, 11323, 11324, 11325, 11326, 11327, 11328, 11329, 11330,
431
  11331, 11332, 11333, 11334, 11335, 11336, 11337, 11338, 11339, 11340, 11341, 11342,
432
  11343, 11344, 11345, 11346, 11347, 11348, 11349, 11350, 11351, 11352, 11353, 11354,
433
  11355, 11356, 11357, 11358, 11359, 11361, 619, 7549, 637, 11368, 11370, 11372, 11379,
434
  11382, 575, 576, 11393, 11395, 11397, 11399, 11401, 11403, 11405, 11407, 11409,
435
  11411, 11413, 11415, 11417, 11419, 11421, 11423, 11425, 11427, 11429, 11431, 11433,
436
  11435, 11437, 11439, 11441, 11443, 11445, 11447, 11449, 11451, 11453, 11455, 11457,
437
  11459, 11461, 11463, 11465, 11467, 11469, 11471, 11473, 11475, 11477, 11479, 11481,
438
  11483, 11485, 11487, 11489, 11491, 11500, 11502, 11507, 11617, 27597, 40863, 19968,
439
  20008, 20022, 20031, 20057, 20101, 20108, 20128, 20154, 20799, 20837, 20843, 20866,
440
  20886, 20907, 20960, 20981, 20992, 21147, 21241, 21269, 21274, 21304, 21313, 21340,
441
  21353, 21378, 21430, 21448, 21475, 22231, 22303, 22763, 22786, 22794, 22805, 22823,
442
  22899, 23376, 23424, 23544, 23567, 23586, 23608, 23662, 23665, 24027, 24037, 24049,
443
  24062, 24178, 24186, 24191, 24308, 24318, 24331, 24339, 24400, 24417, 24435, 24515,
444
  25096, 25142, 25163, 25903, 25908, 25991, 26007, 26020, 26041, 26080, 26085, 26352,
445
  26376, 26408, 27424, 27490, 27513, 27571, 27595, 27604, 27611, 27663, 27668, 27700,
446
  28779, 29226, 29238, 29243, 29247, 29255, 29273, 29275, 29356, 29572, 29577, 29916,
447
  29926, 29976, 29983, 29992, 30000, 30091, 30098, 30326, 30333, 30382, 30399, 30446,
448
  30683, 30690, 30707, 31034, 31160, 31166, 31348, 31435, 31481, 31859, 31992, 32566,
449
  32593, 32650, 32701, 32769, 32780, 32786, 32819, 32895, 32905, 33251, 33258, 33267,
450
  33276, 33292, 33307, 33311, 33390, 33394, 33400, 34381, 34411, 34880, 34892, 34915,
451
  35198, 35211, 35282, 35328, 35895, 35910, 35925, 35960, 35997, 36196, 36208, 36275,
452
  36523, 36554, 36763, 36784, 36789, 37009, 37193, 37318, 37324, 37329, 38263, 38272,
453
  38428, 38582, 38585, 38632, 38737, 38750, 38754, 38761, 38859, 38893, 38899, 38913,
454
  39080, 39131, 39135, 39318, 39321, 39340, 39592, 39640, 39647, 39717, 39727, 39730,
455
  39740, 39770, 40165, 40565, 40575, 40613, 40635, 40643, 40653, 40657, 40697, 40701,
456
  40718, 40723, 40736, 40763, 40778, 40786, 40845, 40860, 40864, 46, 12306, 21316,
457
  21317, 32, 12441, 32, 12442, 12424, 12426, 12467, 12488, 4352, 4353, 4522, 4354,
458
  4524, 4525, 4355, 4356, 4357, 4528, 4529, 4530, 4531, 4532, 4533, 4378, 4358, 4359,
459
  4360, 4385, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4449, 4450,
460
  4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464,
461
  4465, 4466, 4467, 4468, 4469, 4372, 4373, 4551, 4552, 4556, 4558, 4563, 4567, 4569,
462
  4380, 4573, 4575, 4381, 4382, 4384, 4386, 4387, 4391, 4393, 4395, 4396, 4397, 4398,
463
  4399, 4402, 4406, 4416, 4423, 4428, 4593, 4594, 4439, 4440, 4441, 4484, 4485, 4488,
464
  4497, 4498, 4500, 4510, 4513, 19977, 22235, 19978, 20013, 19979, 30002, 19993, 19969,
465
  22825, 22320, 40, 4352, 41, 40, 4354, 41, 40, 4355, 41, 40, 4357, 41, 40, 4358,
466
  41, 40, 4359, 41, 40, 4361, 41, 40, 4363, 41, 40, 4364, 41, 40, 4366, 41, 40, 4367,
467
  41, 40, 4368, 41, 40, 4369, 41, 40, 4370, 41, 40, 44032, 41, 40, 45208, 41, 40,
468
  45796, 41, 40, 46972, 41, 40, 47560, 41, 40, 48148, 41, 40, 49324, 41, 40, 50500,
469
  41, 40, 51088, 41, 40, 52264, 41, 40, 52852, 41, 40, 53440, 41, 40, 54028, 41, 40,
470
  54616, 41, 40, 51452, 41, 40, 50724, 51204, 41, 40, 50724, 54980, 41, 40, 19968,
471
  41, 40, 20108, 41, 40, 19977, 41, 40, 22235, 41, 40, 20116, 41, 40, 20845, 41, 40,
472
  19971, 41, 40, 20843, 41, 40, 20061, 41, 40, 21313, 41, 40, 26376, 41, 40, 28779,
473
  41, 40, 27700, 41, 40, 26408, 41, 40, 37329, 41, 40, 22303, 41, 40, 26085, 41, 40,
474
  26666, 41, 40, 26377, 41, 40, 31038, 41, 40, 21517, 41, 40, 29305, 41, 40, 36001,
475
  41, 40, 31069, 41, 40, 21172, 41, 40, 20195, 41, 40, 21628, 41, 40, 23398, 41, 40,
476
  30435, 41, 40, 20225, 41, 40, 36039, 41, 40, 21332, 41, 40, 31085, 41, 40, 20241,
477
  41, 40, 33258, 41, 40, 33267, 41, 21839, 24188, 31631, 112, 116, 101, 50, 50, 50,
478
  52, 50, 53, 50, 54, 50, 55, 50, 56, 50, 57, 51, 48, 51, 51, 51, 52, 51, 53, 52280,
479
  44256, 51452, 51032, 50864, 31192, 30007, 36969, 20778, 21360, 27880, 38917, 20889,
480
  27491, 24038, 21491, 21307, 23447, 22812, 51, 54, 51, 55, 51, 56, 51, 57, 52, 48,
481
  52, 52, 52, 53, 52, 54, 52, 55, 52, 56, 52, 57, 53, 48, 49, 26376, 50, 26376, 51,
482
  26376, 52, 26376, 53, 26376, 54, 26376, 55, 26376, 56, 26376, 57, 26376, 49, 48,
483
  26376, 49, 49, 26376, 49, 50, 26376, 104, 103, 101, 114, 103, 101, 118, 108, 116,
484
  100, 12450, 12452, 12454, 12456, 12458, 12459, 12461, 12463, 12465, 12469, 12471,
485
  12473, 12475, 12477, 12479, 12481, 12484, 12486, 12490, 12491, 12492, 12493, 12494,
486
  12495, 12498, 12501, 12504, 12507, 12510, 12511, 12512, 12513, 12514, 12516, 12518,
487
  12520, 12521, 12522, 12523, 12524, 12525, 12527, 12528, 12529, 12530, 20196, 21644,
488
  12450, 12497, 12540, 12488, 12450, 12523, 12501, 12449, 12450, 12531, 12506, 12450,
489
  12450, 12540, 12523, 12452, 12491, 12531, 12464, 12452, 12531, 12481, 12454, 12457,
490
  12531, 12456, 12473, 12463, 12540, 12489, 12456, 12540, 12459, 12540, 12458, 12531,
491
  12473, 12458, 12540, 12512, 12459, 12452, 12522, 12459, 12521, 12483, 12488, 12459,
492
  12525, 12522, 12540, 12460, 12525, 12531, 12460, 12531, 12510, 12462, 12460, 12462,
493
  12491, 12540, 12461, 12517, 12522, 12540, 12462, 12523, 12480, 12540, 12461, 12525,
494
  12461, 12525, 12464, 12521, 12512, 12461, 12525, 12513, 12540, 12488, 12523, 12461,
495
  12525, 12527, 12483, 12488, 12464, 12521, 12512, 12488, 12531, 12463, 12523, 12476,
496
  12452, 12525, 12463, 12525, 12540, 12493, 12465, 12540, 12473, 12467, 12523, 12490,
497
  12467, 12540, 12509, 12469, 12452, 12463, 12523, 12469, 12531, 12481, 12540, 12512,
498
  12471, 12522, 12531, 12464, 12475, 12531, 12481, 12475, 12531, 12488, 12480, 12540,
499
  12473, 12487, 12471, 12489, 12523, 12490, 12494, 12494, 12483, 12488, 12495, 12452,
500
  12484, 12497, 12540, 12475, 12531, 12488, 12497, 12540, 12484, 12496, 12540, 12524,
501
  12523, 12500, 12450, 12473, 12488, 12523, 12500, 12463, 12523, 12500, 12467, 12499,
502
  12523, 12501, 12449, 12521, 12483, 12489, 12501, 12451, 12540, 12488, 12502, 12483,
503
  12471, 12455, 12523, 12501, 12521, 12531, 12504, 12463, 12479, 12540, 12523, 12506,
504
  12477, 12506, 12491, 12498, 12504, 12523, 12484, 12506, 12531, 12473, 12506, 12540,
505
  12472, 12505, 12540, 12479, 12509, 12452, 12531, 12488, 12508, 12523, 12488, 12507,
506
  12531, 12509, 12531, 12489, 12507, 12540, 12523, 12507, 12540, 12531, 12510, 12452,
507
  12463, 12525, 12510, 12452, 12523, 12510, 12483, 12495, 12510, 12523, 12463, 12510,
508
  12531, 12471, 12519, 12531, 12511, 12463, 12525, 12531, 12511, 12522, 12511, 12522,
509
  12496, 12540, 12523, 12513, 12460, 12513, 12460, 12488, 12531, 12516, 12540, 12489,
510
  12516, 12540, 12523, 12518, 12450, 12531, 12522, 12483, 12488, 12523, 12522, 12521,
511
  12523, 12500, 12540, 12523, 12540, 12502, 12523, 12524, 12512, 12524, 12531, 12488,
512
  12466, 12531, 48, 28857, 49, 28857, 50, 28857, 51, 28857, 52, 28857, 53, 28857,
513
  54, 28857, 55, 28857, 56, 28857, 57, 28857, 49, 48, 28857, 49, 49, 28857, 49, 50,
514
  28857, 49, 51, 28857, 49, 52, 28857, 49, 53, 28857, 49, 54, 28857, 49, 55, 28857,
515
  49, 56, 28857, 49, 57, 28857, 50, 48, 28857, 50, 49, 28857, 50, 50, 28857, 50, 51,
516
  28857, 50, 52, 28857, 104, 112, 97, 100, 97, 97, 117, 98, 97, 114, 111, 118, 112,
517
  99, 100, 109, 100, 109, 50, 100, 109, 51, 105, 117, 24179, 25104, 26157, 21644,
518
  22823, 27491, 26126, 27835, 26666, 24335, 20250, 31038, 110, 97, 956, 97, 109, 97,
519
  107, 97, 107, 98, 109, 98, 103, 98, 99, 97, 108, 107, 99, 97, 108, 112, 102, 110,
520
  102, 956, 102, 956, 103, 109, 103, 107, 103, 104, 122, 107, 104, 122, 109, 104,
521
  122, 116, 104, 122, 956, 108, 109, 108, 100, 108, 102, 109, 110, 109, 956, 109,
522
  109, 109, 99, 109, 107, 109, 109, 109, 50, 99, 109, 50, 107, 109, 50, 109, 109,
523
  51, 99, 109, 51, 107, 109, 51, 109, 8725, 115, 109, 8725, 115, 50, 107, 112, 97,
524
  109, 112, 97, 103, 112, 97, 114, 97, 100, 114, 97, 100, 8725, 115, 114, 97, 100,
525
  8725, 115, 50, 112, 115, 110, 115, 956, 115, 109, 115, 112, 118, 110, 118, 956,
526
  118, 109, 118, 107, 118, 112, 119, 110, 119, 956, 119, 109, 119, 107, 119, 107,
527
  969, 109, 969, 98, 113, 99, 8725, 107, 103, 100, 98, 103, 121, 104, 97, 105, 110,
528
  107, 107, 107, 116, 108, 110, 108, 111, 103, 108, 120, 109, 105, 108, 109, 111,
529
  108, 112, 104, 112, 112, 109, 112, 114, 115, 118, 119, 98, 118, 8725, 109, 97, 8725,
530
  109, 49, 26085, 50, 26085, 51, 26085, 52, 26085, 53, 26085, 54, 26085, 55, 26085,
531
  56, 26085, 57, 26085, 49, 48, 26085, 49, 49, 26085, 49, 50, 26085, 49, 51, 26085,
532
  49, 52, 26085, 49, 53, 26085, 49, 54, 26085, 49, 55, 26085, 49, 56, 26085, 49, 57,
533
  26085, 50, 48, 26085, 50, 49, 26085, 50, 50, 26085, 50, 51, 26085, 50, 52, 26085,
534
  50, 53, 26085, 50, 54, 26085, 50, 55, 26085, 50, 56, 26085, 50, 57, 26085, 51, 48,
535
  26085, 51, 49, 26085, 103, 97, 108, 42561, 42563, 42565, 42567, 42569, 42573, 42575,
536
  42577, 42579, 42581, 42583, 42585, 42587, 42589, 42591, 42593, 42595, 42597, 42599,
537
  42601, 42603, 42605, 42625, 42627, 42629, 42631, 42633, 42635, 42637, 42639, 42641,
538
  42643, 42645, 42647, 42649, 42651, 42787, 42789, 42791, 42793, 42795, 42797, 42799,
539
  42803, 42805, 42807, 42809, 42811, 42813, 42815, 42817, 42819, 42821, 42823, 42825,
540
  42827, 42829, 42831, 42833, 42835, 42837, 42839, 42841, 42843, 42845, 42847, 42849,
541
  42851, 42853, 42855, 42857, 42859, 42861, 42863, 42874, 42876, 7545, 42879, 42881,
542
  42883, 42885, 42887, 42892, 42897, 42899, 42903, 42905, 42907, 42909, 42911, 42913,
543
  42915, 42917, 42919, 42921, 620, 670, 647, 43859, 42933, 42935, 42937, 42939, 42941,
544
  42943, 42945, 42947, 42900, 7566, 42952, 42954, 612, 42957, 42961, 42967, 42969,
545
  42971, 411, 42998, 43831, 43858, 653, 5024, 5025, 5026, 5027, 5028, 5029, 5030,
546
  5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044,
547
  5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058,
548
  5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072,
549
  5073, 5074, 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086,
550
  5087, 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100,
551
  5101, 5102, 5103, 35912, 26356, 36040, 28369, 20018, 21477, 22865, 21895, 22856,
552
  25078, 30313, 32645, 34367, 34746, 35064, 37007, 27138, 27931, 28889, 29662, 33853,
553
  37226, 39409, 20098, 21365, 27396, 29211, 34349, 40478, 23888, 28651, 34253, 35172,
554
  25289, 33240, 34847, 24266, 26391, 28010, 29436, 37070, 20358, 20919, 21214, 25796,
555
  27347, 29200, 30439, 34310, 34396, 36335, 38706, 39791, 40442, 30860, 31103, 32160,
556
  33737, 37636, 35542, 22751, 24324, 31840, 32894, 29282, 30922, 36034, 38647, 22744,
557
  23650, 27155, 28122, 28431, 32047, 32311, 38475, 21202, 32907, 20956, 20940, 31260,
558
  32190, 33777, 38517, 35712, 25295, 35582, 20025, 23527, 24594, 29575, 30064, 21271,
559
  30971, 20415, 24489, 19981, 27852, 25976, 32034, 21443, 22622, 30465, 33865, 35498,
560
  27578, 27784, 25342, 33509, 25504, 30053, 20142, 20841, 20937, 26753, 31975, 33391,
561
  35538, 37327, 21237, 21570, 24300, 26053, 28670, 31018, 38317, 39530, 40599, 40654,
562
  26310, 27511, 36706, 24180, 24976, 25088, 25754, 28451, 29001, 29833, 31178, 32244,
563
  32879, 36646, 34030, 36899, 37706, 21015, 21155, 21693, 28872, 35010, 24265, 24565,
564
  25467, 27566, 31806, 29557, 22265, 23994, 24604, 29618, 29801, 32666, 32838, 37428,
565
  38646, 38728, 38936, 20363, 31150, 37300, 38584, 24801, 20102, 20698, 23534, 23615,
566
  26009, 29134, 30274, 34044, 36988, 26248, 38446, 21129, 26491, 26611, 27969, 28316,
567
  29705, 30041, 30827, 32016, 39006, 25134, 38520, 20523, 23833, 28138, 36650, 24459,
568
  24900, 26647, 38534, 21033, 21519, 23653, 26131, 26446, 26792, 27877, 29702, 30178,
569
  32633, 35023, 35041, 38626, 21311, 28346, 21533, 29136, 29848, 34298, 38563, 40023,
570
  40607, 26519, 28107, 33256, 31520, 31890, 29376, 28825, 35672, 20160, 33590, 21050,
571
  20999, 24230, 25299, 31958, 23429, 27934, 26292, 36667, 38477, 24275, 20800, 21952,
572
  22618, 26228, 20958, 29482, 30410, 31036, 31070, 31077, 31119, 38742, 31934, 34322,
573
  35576, 36920, 37117, 39151, 39164, 39208, 40372, 37086, 38583, 20398, 20711, 20813,
574
  21193, 21220, 21329, 21917, 22022, 22120, 22592, 22696, 23652, 24724, 24936, 24974,
575
  25074, 25935, 26082, 26257, 26757, 28023, 28186, 28450, 29038, 29227, 29730, 30865,
576
  31049, 31048, 31056, 31062, 31117, 31118, 31296, 31361, 31680, 32265, 32321, 32626,
577
  32773, 33261, 33401, 33879, 35088, 35222, 35585, 35641, 36051, 36104, 36790, 38627,
578
  38911, 38971, 24693, 148206, 33304, 20006, 20917, 20840, 20352, 20805, 20864, 21191,
579
  21242, 21845, 21913, 21986, 22707, 22852, 22868, 23138, 23336, 24274, 24281, 24425,
580
  24493, 24792, 24910, 24840, 24928, 25140, 25540, 25628, 25682, 25942, 26395, 26454,
581
  28379, 28363, 28702, 30631, 29237, 29359, 29809, 29958, 30011, 30237, 30239, 30427,
582
  30452, 30538, 30528, 30924, 31409, 31867, 32091, 32574, 33618, 33775, 34681, 35137,
583
  35206, 35519, 35531, 35565, 35722, 36664, 36978, 37273, 37494, 38524, 38875, 38923,
584
  39698, 141386, 141380, 144341, 15261, 16408, 16441, 152137, 154832, 163539, 40771,
585
  40846, 102, 102, 102, 105, 102, 108, 102, 102, 108, 1396, 1398, 1396, 1381, 1396,
586
  1387, 1406, 1398, 1396, 1389, 1497, 1460, 1522, 1463, 1506, 1492, 1499, 1500, 1501,
587
  1512, 1514, 1513, 1473, 1513, 1474, 1513, 1468, 1473, 1513, 1468, 1474, 1488, 1463,
588
  1488, 1464, 1488, 1468, 1489, 1468, 1490, 1468, 1491, 1468, 1492, 1468, 1493, 1468,
589
  1494, 1468, 1496, 1468, 1497, 1468, 1498, 1468, 1499, 1468, 1500, 1468, 1502, 1468,
590
  1504, 1468, 1505, 1468, 1507, 1468, 1508, 1468, 1510, 1468, 1511, 1468, 1512, 1468,
591
  1514, 1468, 1493, 1465, 1489, 1471, 1499, 1471, 1508, 1471, 1488, 1500, 1649, 1659,
592
  1662, 1664, 1658, 1663, 1657, 1700, 1702, 1668, 1667, 1670, 1671, 1677, 1676, 1678,
593
  1672, 1688, 1681, 1705, 1711, 1715, 1713, 1722, 1723, 1728, 1729, 1726, 1746, 1747,
594
  1709, 1734, 1736, 1739, 1733, 1737, 1744, 1609, 1574, 1575, 1574, 1749, 1574, 1608,
595
  1574, 1735, 1574, 1734, 1574, 1736, 1574, 1744, 1574, 1609, 1740, 1574, 1580, 1574,
596
  1581, 1574, 1605, 1574, 1610, 1576, 1580, 1576, 1581, 1576, 1582, 1576, 1605, 1576,
597
  1609, 1576, 1610, 1578, 1580, 1578, 1581, 1578, 1582, 1578, 1605, 1578, 1609, 1578,
598
  1610, 1579, 1580, 1579, 1605, 1579, 1609, 1579, 1610, 1580, 1581, 1580, 1605, 1581,
599
  1605, 1582, 1580, 1582, 1581, 1582, 1605, 1587, 1580, 1587, 1581, 1587, 1582, 1587,
600
  1605, 1589, 1581, 1589, 1605, 1590, 1580, 1590, 1581, 1590, 1582, 1590, 1605, 1591,
601
  1581, 1591, 1605, 1592, 1605, 1593, 1580, 1593, 1605, 1594, 1580, 1594, 1605, 1601,
602
  1580, 1601, 1581, 1601, 1582, 1601, 1605, 1601, 1609, 1601, 1610, 1602, 1581, 1602,
603
  1605, 1602, 1609, 1602, 1610, 1603, 1575, 1603, 1580, 1603, 1581, 1603, 1582, 1603,
604
  1604, 1603, 1605, 1603, 1609, 1603, 1610, 1604, 1580, 1604, 1581, 1604, 1582, 1604,
605
  1605, 1604, 1609, 1604, 1610, 1605, 1580, 1605, 1605, 1605, 1609, 1605, 1610, 1606,
606
  1580, 1606, 1581, 1606, 1582, 1606, 1605, 1606, 1609, 1606, 1610, 1607, 1580, 1607,
607
  1605, 1607, 1609, 1607, 1610, 1610, 1581, 1610, 1582, 1610, 1609, 1584, 1648, 1585,
608
  1648, 1609, 1648, 32, 1612, 1617, 32, 1613, 1617, 32, 1614, 1617, 32, 1615, 1617,
609
  32, 1616, 1617, 32, 1617, 1648, 1574, 1585, 1574, 1586, 1574, 1606, 1576, 1585,
610
  1576, 1586, 1576, 1606, 1578, 1585, 1578, 1586, 1578, 1606, 1579, 1585, 1579, 1586,
611
  1579, 1606, 1605, 1575, 1606, 1585, 1606, 1586, 1606, 1606, 1610, 1585, 1610, 1586,
612
  1574, 1582, 1574, 1607, 1576, 1607, 1578, 1607, 1589, 1582, 1604, 1607, 1606, 1607,
613
  1607, 1648, 1579, 1607, 1587, 1607, 1588, 1605, 1588, 1607, 1600, 1614, 1617, 1600,
614
  1615, 1617, 1600, 1616, 1617, 1591, 1609, 1591, 1610, 1593, 1609, 1593, 1610, 1594,
615
  1609, 1594, 1610, 1587, 1609, 1587, 1610, 1588, 1609, 1588, 1610, 1581, 1609, 1580,
616
  1609, 1580, 1610, 1582, 1609, 1589, 1609, 1589, 1610, 1590, 1609, 1590, 1610, 1588,
617
  1580, 1588, 1581, 1588, 1582, 1588, 1585, 1587, 1585, 1589, 1585, 1590, 1585, 1575,
618
  1611, 1578, 1580, 1605, 1578, 1581, 1580, 1578, 1581, 1605, 1578, 1582, 1605, 1578,
619
  1605, 1580, 1578, 1605, 1581, 1578, 1605, 1582, 1581, 1605, 1610, 1581, 1605, 1609,
620
  1587, 1581, 1580, 1587, 1580, 1581, 1587, 1580, 1609, 1587, 1605, 1581, 1587, 1605,
621
  1580, 1587, 1605, 1605, 1589, 1581, 1581, 1589, 1605, 1605, 1588, 1581, 1605, 1588,
622
  1580, 1610, 1588, 1605, 1582, 1588, 1605, 1605, 1590, 1581, 1609, 1590, 1582, 1605,
623
  1591, 1605, 1581, 1591, 1605, 1605, 1591, 1605, 1610, 1593, 1580, 1605, 1593, 1605,
624
  1605, 1593, 1605, 1609, 1594, 1605, 1605, 1594, 1605, 1610, 1594, 1605, 1609, 1601,
625
  1582, 1605, 1602, 1605, 1581, 1602, 1605, 1605, 1604, 1581, 1605, 1604, 1581, 1610,
626
  1604, 1581, 1609, 1604, 1580, 1580, 1604, 1582, 1605, 1604, 1605, 1581, 1605, 1581,
627
  1580, 1605, 1581, 1610, 1605, 1580, 1581, 1605, 1582, 1605, 1605, 1580, 1582, 1607,
628
  1605, 1580, 1607, 1605, 1605, 1606, 1581, 1605, 1606, 1581, 1609, 1606, 1580, 1605,
629
  1606, 1580, 1609, 1606, 1605, 1610, 1606, 1605, 1609, 1610, 1605, 1605, 1576, 1582,
630
  1610, 1578, 1580, 1610, 1578, 1580, 1609, 1578, 1582, 1610, 1578, 1582, 1609, 1578,
631
  1605, 1610, 1578, 1605, 1609, 1580, 1605, 1610, 1580, 1581, 1609, 1580, 1605, 1609,
632
  1587, 1582, 1609, 1589, 1581, 1610, 1588, 1581, 1610, 1590, 1581, 1610, 1604, 1580,
633
  1610, 1604, 1605, 1610, 1610, 1580, 1610, 1610, 1605, 1610, 1605, 1605, 1610, 1602,
634
  1605, 1610, 1606, 1581, 1610, 1593, 1605, 1610, 1603, 1605, 1610, 1606, 1580, 1581,
635
  1605, 1582, 1610, 1604, 1580, 1605, 1603, 1605, 1605, 1580, 1581, 1610, 1581, 1580,
636
  1610, 1605, 1580, 1610, 1601, 1605, 1610, 1576, 1581, 1610, 1587, 1582, 1610, 1606,
637
  1580, 1610, 1589, 1604, 1746, 1602, 1604, 1746, 1575, 1604, 1604, 1607, 1575, 1603,
638
  1576, 1585, 1605, 1581, 1605, 1583, 1589, 1604, 1593, 1605, 1585, 1587, 1608, 1604,
639
  1593, 1604, 1610, 1607, 1608, 1587, 1604, 1605, 1589, 1604, 1609, 1589, 1604, 1609,
640
  32, 1575, 1604, 1604, 1607, 32, 1593, 1604, 1610, 1607, 32, 1608, 1587, 1604, 1605,
641
  1580, 1604, 32, 1580, 1604, 1575, 1604, 1607, 1585, 1740, 1575, 1604, 44, 12289,
642
  12310, 12311, 8212, 8211, 95, 123, 125, 12308, 12309, 12304, 12305, 12298, 12299,
643
  12300, 12301, 12302, 12303, 91, 93, 35, 38, 42, 45, 60, 62, 92, 36, 37, 64, 32,
644
  1611, 1600, 1611, 1600, 1617, 32, 1618, 1600, 1618, 1569, 1570, 1571, 1572, 1573,
645
  1577, 1604, 1570, 1604, 1571, 1604, 1573, 34, 39, 94, 124, 126, 10629, 10630, 12539,
646
  12453, 12515, 162, 163, 172, 166, 165, 8361, 9474, 8592, 8593, 8594, 8595, 9632,
647
  9675, 66600, 66601, 66602, 66603, 66604, 66605, 66606, 66607, 66608, 66609, 66610,
648
  66611, 66612, 66613, 66614, 66615, 66616, 66617, 66618, 66619, 66620, 66621, 66622,
649
  66623, 66624, 66625, 66626, 66627, 66628, 66629, 66630, 66631, 66632, 66633, 66634,
650
  66635, 66636, 66637, 66638, 66639, 66776, 66777, 66778, 66779, 66780, 66781, 66782,
651
  66783, 66784, 66785, 66786, 66787, 66788, 66789, 66790, 66791, 66792, 66793, 66794,
652
  66795, 66796, 66797, 66798, 66799, 66800, 66801, 66802, 66803, 66804, 66805, 66806,
653
  66807, 66808, 66809, 66810, 66811, 66967, 66968, 66969, 66970, 66971, 66972, 66973,
654
  66974, 66975, 66976, 66977, 66979, 66980, 66981, 66982, 66983, 66984, 66985, 66986,
655
  66987, 66988, 66989, 66990, 66991, 66992, 66993, 66995, 66996, 66997, 66998, 66999,
656
  67000, 67001, 67003, 67004, 720, 721, 665, 675, 43878, 677, 676, 7569, 600, 606,
657
  681, 610, 667, 668, 615, 644, 682, 683, 122628, 42894, 622, 122629, 654, 122630,
658
  630, 631, 634, 122632, 638, 680, 678, 43879, 679, 11377, 655, 673, 674, 664, 448,
659
  449, 450, 122634, 122654, 68800, 68801, 68802, 68803, 68804, 68805, 68806, 68807,
660
  68808, 68809, 68810, 68811, 68812, 68813, 68814, 68815, 68816, 68817, 68818, 68819,
661
  68820, 68821, 68822, 68823, 68824, 68825, 68826, 68827, 68828, 68829, 68830, 68831,
662
  68832, 68833, 68834, 68835, 68836, 68837, 68838, 68839, 68840, 68841, 68842, 68843,
663
  68844, 68845, 68846, 68847, 68848, 68849, 68850, 68976, 68977, 68978, 68979, 68980,
664
  68981, 68982, 68983, 68984, 68985, 68986, 68987, 68988, 68989, 68990, 68991, 68992,
665
  68993, 68994, 68995, 68996, 68997, 71872, 71873, 71874, 71875, 71876, 71877, 71878,
666
  71879, 71880, 71881, 71882, 71883, 71884, 71885, 71886, 71887, 71888, 71889, 71890,
667
  71891, 71892, 71893, 71894, 71895, 71896, 71897, 71898, 71899, 71900, 71901, 71902,
668
  71903, 93792, 93793, 93794, 93795, 93796, 93797, 93798, 93799, 93800, 93801, 93802,
669
  93803, 93804, 93805, 93806, 93807, 93808, 93809, 93810, 93811, 93812, 93813, 93814,
670
  93815, 93816, 93817, 93818, 93819, 93820, 93821, 93822, 93823, 119127, 119141, 119128,
671
  119141, 119128, 119141, 119150, 119128, 119141, 119151, 119128, 119141, 119152,
672
  119128, 119141, 119153, 119128, 119141, 119154, 119225, 119141, 119226, 119141,
673
  119225, 119141, 119150, 119226, 119141, 119150, 119225, 119141, 119151, 119226,
674
  119141, 119151, 305, 567, 8711, 8706, 125218, 125219, 125220, 125221, 125222, 125223,
675
  125224, 125225, 125226, 125227, 125228, 125229, 125230, 125231, 125232, 125233,
676
  125234, 125235, 125236, 125237, 125238, 125239, 125240, 125241, 125242, 125243,
677
  125244, 125245, 125246, 125247, 125248, 125249, 125250, 125251, 1646, 1697, 1647,
678
  48, 44, 49, 44, 50, 44, 51, 44, 52, 44, 53, 44, 54, 44, 55, 44, 56, 44, 57, 44,
679
  12308, 115, 12309, 119, 122, 104, 118, 115, 100, 115, 115, 112, 112, 118, 119, 99,
680
  109, 114, 100, 106, 12411, 12363, 12467, 12467, 23383, 21452, 22810, 35299, 20132,
681
  26144, 28961, 21069, 24460, 20877, 26032, 21021, 32066, 36009, 22768, 21561, 28436,
682
  25237, 25429, 36938, 25351, 25171, 31105, 31354, 21512, 28288, 30003, 21106, 21942,
683
  37197, 12308, 26412, 12309, 12308, 19977, 12309, 12308, 20108, 12309, 12308, 23433,
684
  12309, 12308, 28857, 12309, 12308, 25171, 12309, 12308, 30423, 12309, 12308, 21213,
685
  12309, 12308, 25943, 12309, 24471, 21487, 20029, 20024, 20033, 131362, 20320, 20411,
686
  20482, 20602, 20633, 20687, 13470, 132666, 20820, 20836, 20855, 132380, 13497, 20839,
687
  132427, 20887, 20900, 20172, 20908, 168415, 20995, 13535, 21051, 21062, 21111, 13589,
688
  21253, 21254, 21321, 21338, 21363, 21373, 21375, 133676, 28784, 21450, 21471, 133987,
689
  21483, 21489, 21510, 21662, 21560, 21576, 21608, 21666, 21750, 21776, 21843, 21859,
690
  21892, 21931, 21939, 21954, 22294, 22295, 22097, 22132, 22766, 22478, 22516, 22541,
691
  22411, 22578, 22577, 22700, 136420, 22770, 22775, 22790, 22818, 22882, 136872, 136938,
692
  23020, 23067, 23079, 23000, 23142, 14062, 14076, 23304, 23358, 137672, 23491, 23512,
693
  23539, 138008, 23551, 23558, 24403, 14209, 23648, 23744, 23693, 138724, 23875, 138726,
694
  23918, 23915, 23932, 24033, 24034, 14383, 24061, 24104, 24125, 24169, 14434, 139651,
695
  14460, 24240, 24243, 24246, 172946, 140081, 33281, 24354, 14535, 144056, 156122,
696
  24418, 24427, 14563, 24474, 24525, 24535, 24569, 24705, 14650, 14620, 141012, 24775,
697
  24904, 24908, 24954, 25010, 24996, 25007, 25054, 25115, 25181, 25265, 25300, 25424,
698
  142092, 25405, 25340, 25448, 25475, 25572, 142321, 25634, 25541, 25513, 14894, 25705,
699
  25726, 25757, 25719, 14956, 25964, 143370, 26083, 26360, 26185, 15129, 15112, 15076,
700
  20882, 20885, 26368, 26268, 32941, 17369, 26401, 26462, 26451, 144323, 15177, 26618,
701
  26501, 26706, 144493, 26766, 26655, 26900, 26946, 27043, 27114, 27304, 145059, 27355,
702
  15384, 27425, 145575, 27476, 15438, 27506, 27551, 27579, 146061, 138507, 146170,
703
  27726, 146620, 27839, 27853, 27751, 27926, 27966, 28009, 28024, 28037, 146718, 27956,
704
  28207, 28270, 15667, 28359, 147153, 28153, 28526, 147294, 147342, 28614, 28729,
705
  28699, 15766, 28746, 28797, 28791, 28845, 132389, 28997, 148067, 29084, 148395,
706
  29224, 29264, 149000, 29312, 29333, 149301, 149524, 29562, 29579, 16044, 29605,
707
  16056, 29767, 29788, 29829, 29898, 16155, 29988, 150582, 30014, 150674, 139679,
708
  30224, 151457, 151480, 151620, 16380, 16392, 151795, 151794, 151833, 151859, 30494,
709
  30495, 30603, 16454, 16534, 152605, 30798, 16611, 153126, 153242, 153285, 31211,
710
  16687, 31306, 31311, 153980, 154279, 31470, 16898, 154539, 31686, 31689, 16935,
711
  154752, 31954, 17056, 31976, 31971, 32000, 155526, 32099, 17153, 32199, 32258, 32325,
712
  17204, 156200, 156231, 17241, 156377, 32634, 156478, 32661, 32762, 156890, 156963,
713
  32864, 157096, 32880, 144223, 17365, 32946, 33027, 17419, 33086, 23221, 157607,
714
  157621, 144275, 144284, 33284, 36766, 17515, 33425, 33419, 33437, 21171, 33457,
715
  33459, 33469, 33510, 158524, 33565, 33635, 33709, 33571, 33725, 33767, 33619, 33738,
716
  33740, 33756, 158774, 159083, 158933, 17707, 34033, 34035, 34070, 160714, 34148,
717
  159532, 17757, 17761, 159665, 159954, 17771, 34384, 34407, 34409, 34473, 34440,
718
  34574, 34530, 34600, 34667, 34694, 17879, 34785, 34817, 17913, 34912, 161383, 35031,
719
  35038, 17973, 35066, 13499, 161966, 162150, 18110, 18119, 35488, 162984, 36011,
720
  36033, 36123, 36215, 163631, 133124, 36299, 36284, 36336, 133342, 36564, 165330,
721
  165357, 37012, 37105, 37137, 165678, 37147, 37432, 37591, 37592, 37500, 37881, 37909,
722
  166906, 38283, 18837, 38327, 167287, 18918, 38595, 23986, 38691, 168261, 168474,
723
  19054, 19062, 38880, 168970, 19122, 169110, 38953, 169398, 39138, 19251, 39209,
724
  39335, 39362, 39422, 19406, 170800, 40000, 40189, 19662, 19693, 40295, 172238, 19704,
725
  172293, 172558, 172689, 19798, 40702, 40709, 40719, 40726, 173568,
726
727
};
728
const uint32_t table[8150][2] =
729
{
730
  {0, 1}, {65, 16777219}, {66, 16777475}, {67, 16777731},
731
  {68, 16777987}, {69, 16778243}, {70, 16778499}, {71, 16778755},
732
  {72, 16779011}, {73, 16779267}, {74, 16779523}, {75, 16779779},
733
  {76, 16780035}, {77, 16780291}, {78, 16780547}, {79, 16780803},
734
  {80, 16781059}, {81, 16781315}, {82, 16781571}, {83, 16781827},
735
  {84, 16782083}, {85, 16782339}, {86, 16782595}, {87, 16782851},
736
  {88, 16783107}, {89, 16783363}, {90, 16783619}, {91, 1},
737
  {128, 2}, {160, 16783875}, {161, 1}, {168, 33561347},
738
  {169, 1}, {170, 16777219}, {171, 1}, {173, 0},
739
  {174, 1}, {175, 33561859}, {176, 1}, {178, 16785155},
740
  {179, 16785411}, {180, 33562883}, {181, 16786179}, {182, 1},
741
  {184, 33563651}, {185, 16786947}, {186, 16780803}, {187, 1},
742
  {188, 50341635}, {189, 50342403}, {190, 50343171}, {191, 1},
743
  {192, 16789507}, {193, 16789763}, {194, 16790019}, {195, 16790275},
744
  {196, 16790531}, {197, 16790787}, {198, 16791043}, {199, 16791299},
745
  {200, 16791555}, {201, 16791811}, {202, 16792067}, {203, 16792323},
746
  {204, 16792579}, {205, 16792835}, {206, 16793091}, {207, 16793347},
747
  {208, 16793603}, {209, 16793859}, {210, 16794115}, {211, 16794371},
748
  {212, 16794627}, {213, 16794883}, {214, 16795139}, {215, 1},
749
  {216, 16795395}, {217, 16795651}, {218, 16795907}, {219, 16796163},
750
  {220, 16796419}, {221, 16796675}, {222, 16796931}, {223, 1},
751
  {256, 16797187}, {257, 1}, {258, 16797443}, {259, 1},
752
  {260, 16797699}, {261, 1}, {262, 16797955}, {263, 1},
753
  {264, 16798211}, {265, 1}, {266, 16798467}, {267, 1},
754
  {268, 16798723}, {269, 1}, {270, 16798979}, {271, 1},
755
  {272, 16799235}, {273, 1}, {274, 16799491}, {275, 1},
756
  {276, 16799747}, {277, 1}, {278, 16800003}, {279, 1},
757
  {280, 16800259}, {281, 1}, {282, 16800515}, {283, 1},
758
  {284, 16800771}, {285, 1}, {286, 16801027}, {287, 1},
759
  {288, 16801283}, {289, 1}, {290, 16801539}, {291, 1},
760
  {292, 16801795}, {293, 1}, {294, 16802051}, {295, 1},
761
  {296, 16802307}, {297, 1}, {298, 16802563}, {299, 1},
762
  {300, 16802819}, {301, 1}, {302, 16803075}, {303, 1},
763
  {304, 33580547}, {305, 1}, {306, 33556483}, {308, 16803843},
764
  {309, 1}, {310, 16804099}, {311, 1}, {313, 16804355},
765
  {314, 1}, {315, 16804611}, {316, 1}, {317, 16804867},
766
  {318, 1}, {319, 33582339}, {321, 16805635}, {322, 1},
767
  {323, 16805891}, {324, 1}, {325, 16806147}, {326, 1},
768
  {327, 16806403}, {328, 1}, {329, 33583875}, {330, 16807171},
769
  {331, 1}, {332, 16807427}, {333, 1}, {334, 16807683},
770
  {335, 1}, {336, 16807939}, {337, 1}, {338, 16808195},
771
  {339, 1}, {340, 16808451}, {341, 1}, {342, 16808707},
772
  {343, 1}, {344, 16808963}, {345, 1}, {346, 16809219},
773
  {347, 1}, {348, 16809475}, {349, 1}, {350, 16809731},
774
  {351, 1}, {352, 16809987}, {353, 1}, {354, 16810243},
775
  {355, 1}, {356, 16810499}, {357, 1}, {358, 16810755},
776
  {359, 1}, {360, 16811011}, {361, 1}, {362, 16811267},
777
  {363, 1}, {364, 16811523}, {365, 1}, {366, 16811779},
778
  {367, 1}, {368, 16812035}, {369, 1}, {370, 16812291},
779
  {371, 1}, {372, 16812547}, {373, 1}, {374, 16812803},
780
  {375, 1}, {376, 16813059}, {377, 16813315}, {378, 1},
781
  {379, 16813571}, {380, 1}, {381, 16813827}, {382, 1},
782
  {383, 16781827}, {384, 1}, {385, 16814083}, {386, 16814339},
783
  {387, 1}, {388, 16814595}, {389, 1}, {390, 16814851},
784
  {391, 16815107}, {392, 1}, {393, 16815363}, {394, 16815619},
785
  {395, 16815875}, {396, 1}, {398, 16816131}, {399, 16816387},
786
  {400, 16816643}, {401, 16816899}, {402, 1}, {403, 16817155},
787
  {404, 16817411}, {405, 1}, {406, 16817667}, {407, 16817923},
788
  {408, 16818179}, {409, 1}, {412, 16818435}, {413, 16818691},
789
  {414, 1}, {415, 16818947}, {416, 16819203}, {417, 1},
790
  {418, 16819459}, {419, 1}, {420, 16819715}, {421, 1},
791
  {422, 16819971}, {423, 16820227}, {424, 1}, {425, 16820483},
792
  {426, 1}, {428, 16820739}, {429, 1}, {430, 16820995},
793
  {431, 16821251}, {432, 1}, {433, 16821507}, {434, 16821763},
794
  {435, 16822019}, {436, 1}, {437, 16822275}, {438, 1},
795
  {439, 16822531}, {440, 16822787}, {441, 1}, {444, 16823043},
796
  {445, 1}, {452, 33600515}, {455, 33601027}, {458, 33601539},
797
  {461, 16824835}, {462, 1}, {463, 16825091}, {464, 1},
798
  {465, 16825347}, {466, 1}, {467, 16825603}, {468, 1},
799
  {469, 16825859}, {470, 1}, {471, 16826115}, {472, 1},
800
  {473, 16826371}, {474, 1}, {475, 16826627}, {476, 1},
801
  {478, 16826883}, {479, 1}, {480, 16827139}, {481, 1},
802
  {482, 16827395}, {483, 1}, {484, 16827651}, {485, 1},
803
  {486, 16827907}, {487, 1}, {488, 16828163}, {489, 1},
804
  {490, 16828419}, {491, 1}, {492, 16828675}, {493, 1},
805
  {494, 16828931}, {495, 1}, {497, 33606403}, {500, 16829699},
806
  {501, 1}, {502, 16829955}, {503, 16830211}, {504, 16830467},
807
  {505, 1}, {506, 16830723}, {507, 1}, {508, 16830979},
808
  {509, 1}, {510, 16831235}, {511, 1}, {512, 16831491},
809
  {513, 1}, {514, 16831747}, {515, 1}, {516, 16832003},
810
  {517, 1}, {518, 16832259}, {519, 1}, {520, 16832515},
811
  {521, 1}, {522, 16832771}, {523, 1}, {524, 16833027},
812
  {525, 1}, {526, 16833283}, {527, 1}, {528, 16833539},
813
  {529, 1}, {530, 16833795}, {531, 1}, {532, 16834051},
814
  {533, 1}, {534, 16834307}, {535, 1}, {536, 16834563},
815
  {537, 1}, {538, 16834819}, {539, 1}, {540, 16835075},
816
  {541, 1}, {542, 16835331}, {543, 1}, {544, 16835587},
817
  {545, 1}, {546, 16835843}, {547, 1}, {548, 16836099},
818
  {549, 1}, {550, 16836355}, {551, 1}, {552, 16836611},
819
  {553, 1}, {554, 16836867}, {555, 1}, {556, 16837123},
820
  {557, 1}, {558, 16837379}, {559, 1}, {560, 16837635},
821
  {561, 1}, {562, 16837891}, {563, 1}, {570, 16838147},
822
  {571, 16838403}, {572, 1}, {573, 16838659}, {574, 16838915},
823
  {575, 1}, {577, 16839171}, {578, 1}, {579, 16839427},
824
  {580, 16839683}, {581, 16839939}, {582, 16840195}, {583, 1},
825
  {584, 16840451}, {585, 1}, {586, 16840707}, {587, 1},
826
  {588, 16840963}, {589, 1}, {590, 16841219}, {591, 1},
827
  {688, 16779011}, {689, 16841475}, {690, 16779523}, {691, 16781571},
828
  {692, 16841731}, {693, 16841987}, {694, 16842243}, {695, 16782851},
829
  {696, 16783363}, {697, 1}, {728, 33619715}, {729, 33620227},
830
  {730, 33620739}, {731, 33621251}, {732, 33621763}, {733, 33622275},
831
  {734, 1}, {736, 16817411}, {737, 16780035}, {738, 16781827},
832
  {739, 16783107}, {740, 16845571}, {741, 1}, {832, 16845827},
833
  {833, 16785923}, {834, 1}, {835, 16846083}, {836, 33623555},
834
  {837, 16846851}, {838, 1}, {847, 0}, {848, 1},
835
  {880, 16847107}, {881, 1}, {882, 16847363}, {883, 1},
836
  {884, 16847619}, {885, 1}, {886, 16847875}, {887, 1},
837
  {888, 2}, {890, 33625347}, {891, 1}, {894, 16848643},
838
  {895, 16848899}, {896, 2}, {900, 33562883}, {901, 50403587},
839
  {902, 16849923}, {903, 16805379}, {904, 16850179}, {905, 16850435},
840
  {906, 16850691}, {907, 2}, {908, 16850947}, {909, 2},
841
  {910, 16851203}, {911, 16851459}, {912, 1}, {913, 16851715},
842
  {914, 16851971}, {915, 16852227}, {916, 16852483}, {917, 16852739},
843
  {918, 16852995}, {919, 16853251}, {920, 16853507}, {921, 16846851},
844
  {922, 16853763}, {923, 16854019}, {924, 16786179}, {925, 16854275},
845
  {926, 16854531}, {927, 16854787}, {928, 16855043}, {929, 16855299},
846
  {930, 2}, {931, 16855555}, {932, 16855811}, {933, 16856067},
847
  {934, 16856323}, {935, 16856579}, {936, 16856835}, {937, 16857091},
848
  {938, 16857347}, {939, 16857603}, {940, 1}, {975, 16857859},
849
  {976, 16851971}, {977, 16853507}, {978, 16856067}, {979, 16851203},
850
  {980, 16857603}, {981, 16856323}, {982, 16855043}, {983, 1},
851
  {984, 16858115}, {985, 1}, {986, 16858371}, {987, 1},
852
  {988, 16858627}, {989, 1}, {990, 16858883}, {991, 1},
853
  {992, 16859139}, {993, 1}, {994, 16859395}, {995, 1},
854
  {996, 16859651}, {997, 1}, {998, 16859907}, {999, 1},
855
  {1000, 16860163}, {1001, 1}, {1002, 16860419}, {1003, 1},
856
  {1004, 16860675}, {1005, 1}, {1006, 16860931}, {1007, 1},
857
  {1008, 16853763}, {1009, 16855299}, {1010, 16855555}, {1011, 1},
858
  {1012, 16853507}, {1013, 16852739}, {1014, 1}, {1015, 16861187},
859
  {1016, 1}, {1017, 16855555}, {1018, 16861443}, {1019, 1},
860
  {1021, 16861699}, {1022, 16861955}, {1023, 16862211}, {1024, 16862467},
861
  {1025, 16862723}, {1026, 16862979}, {1027, 16863235}, {1028, 16863491},
862
  {1029, 16863747}, {1030, 16864003}, {1031, 16864259}, {1032, 16864515},
863
  {1033, 16864771}, {1034, 16865027}, {1035, 16865283}, {1036, 16865539},
864
  {1037, 16865795}, {1038, 16866051}, {1039, 16866307}, {1040, 16866563},
865
  {1041, 16866819}, {1042, 16867075}, {1043, 16867331}, {1044, 16867587},
866
  {1045, 16867843}, {1046, 16868099}, {1047, 16868355}, {1048, 16868611},
867
  {1049, 16868867}, {1050, 16869123}, {1051, 16869379}, {1052, 16869635},
868
  {1053, 16869891}, {1054, 16870147}, {1055, 16870403}, {1056, 16870659},
869
  {1057, 16870915}, {1058, 16871171}, {1059, 16871427}, {1060, 16871683},
870
  {1061, 16871939}, {1062, 16872195}, {1063, 16872451}, {1064, 16872707},
871
  {1065, 16872963}, {1066, 16873219}, {1067, 16873475}, {1068, 16873731},
872
  {1069, 16873987}, {1070, 16874243}, {1071, 16874499}, {1072, 1},
873
  {1120, 16874755}, {1121, 1}, {1122, 16875011}, {1123, 1},
874
  {1124, 16875267}, {1125, 1}, {1126, 16875523}, {1127, 1},
875
  {1128, 16875779}, {1129, 1}, {1130, 16876035}, {1131, 1},
876
  {1132, 16876291}, {1133, 1}, {1134, 16876547}, {1135, 1},
877
  {1136, 16876803}, {1137, 1}, {1138, 16877059}, {1139, 1},
878
  {1140, 16877315}, {1141, 1}, {1142, 16877571}, {1143, 1},
879
  {1144, 16877827}, {1145, 1}, {1146, 16878083}, {1147, 1},
880
  {1148, 16878339}, {1149, 1}, {1150, 16878595}, {1151, 1},
881
  {1152, 16878851}, {1153, 1}, {1162, 16879107}, {1163, 1},
882
  {1164, 16879363}, {1165, 1}, {1166, 16879619}, {1167, 1},
883
  {1168, 16879875}, {1169, 1}, {1170, 16880131}, {1171, 1},
884
  {1172, 16880387}, {1173, 1}, {1174, 16880643}, {1175, 1},
885
  {1176, 16880899}, {1177, 1}, {1178, 16881155}, {1179, 1},
886
  {1180, 16881411}, {1181, 1}, {1182, 16881667}, {1183, 1},
887
  {1184, 16881923}, {1185, 1}, {1186, 16882179}, {1187, 1},
888
  {1188, 16882435}, {1189, 1}, {1190, 16882691}, {1191, 1},
889
  {1192, 16882947}, {1193, 1}, {1194, 16883203}, {1195, 1},
890
  {1196, 16883459}, {1197, 1}, {1198, 16883715}, {1199, 1},
891
  {1200, 16883971}, {1201, 1}, {1202, 16884227}, {1203, 1},
892
  {1204, 16884483}, {1205, 1}, {1206, 16884739}, {1207, 1},
893
  {1208, 16884995}, {1209, 1}, {1210, 16885251}, {1211, 1},
894
  {1212, 16885507}, {1213, 1}, {1214, 16885763}, {1215, 1},
895
  {1216, 16886019}, {1217, 16886275}, {1218, 1}, {1219, 16886531},
896
  {1220, 1}, {1221, 16886787}, {1222, 1}, {1223, 16887043},
897
  {1224, 1}, {1225, 16887299}, {1226, 1}, {1227, 16887555},
898
  {1228, 1}, {1229, 16887811}, {1230, 1}, {1232, 16888067},
899
  {1233, 1}, {1234, 16888323}, {1235, 1}, {1236, 16888579},
900
  {1237, 1}, {1238, 16888835}, {1239, 1}, {1240, 16889091},
901
  {1241, 1}, {1242, 16889347}, {1243, 1}, {1244, 16889603},
902
  {1245, 1}, {1246, 16889859}, {1247, 1}, {1248, 16890115},
903
  {1249, 1}, {1250, 16890371}, {1251, 1}, {1252, 16890627},
904
  {1253, 1}, {1254, 16890883}, {1255, 1}, {1256, 16891139},
905
  {1257, 1}, {1258, 16891395}, {1259, 1}, {1260, 16891651},
906
  {1261, 1}, {1262, 16891907}, {1263, 1}, {1264, 16892163},
907
  {1265, 1}, {1266, 16892419}, {1267, 1}, {1268, 16892675},
908
  {1269, 1}, {1270, 16892931}, {1271, 1}, {1272, 16893187},
909
  {1273, 1}, {1274, 16893443}, {1275, 1}, {1276, 16893699},
910
  {1277, 1}, {1278, 16893955}, {1279, 1}, {1280, 16894211},
911
  {1281, 1}, {1282, 16894467}, {1283, 1}, {1284, 16894723},
912
  {1285, 1}, {1286, 16894979}, {1287, 1}, {1288, 16895235},
913
  {1289, 1}, {1290, 16895491}, {1291, 1}, {1292, 16895747},
914
  {1293, 1}, {1294, 16896003}, {1295, 1}, {1296, 16896259},
915
  {1297, 1}, {1298, 16896515}, {1299, 1}, {1300, 16896771},
916
  {1301, 1}, {1302, 16897027}, {1303, 1}, {1304, 16897283},
917
  {1305, 1}, {1306, 16897539}, {1307, 1}, {1308, 16897795},
918
  {1309, 1}, {1310, 16898051}, {1311, 1}, {1312, 16898307},
919
  {1313, 1}, {1314, 16898563}, {1315, 1}, {1316, 16898819},
920
  {1317, 1}, {1318, 16899075}, {1319, 1}, {1320, 16899331},
921
  {1321, 1}, {1322, 16899587}, {1323, 1}, {1324, 16899843},
922
  {1325, 1}, {1326, 16900099}, {1327, 1}, {1328, 2},
923
  {1329, 16900355}, {1330, 16900611}, {1331, 16900867}, {1332, 16901123},
924
  {1333, 16901379}, {1334, 16901635}, {1335, 16901891}, {1336, 16902147},
925
  {1337, 16902403}, {1338, 16902659}, {1339, 16902915}, {1340, 16903171},
926
  {1341, 16903427}, {1342, 16903683}, {1343, 16903939}, {1344, 16904195},
927
  {1345, 16904451}, {1346, 16904707}, {1347, 16904963}, {1348, 16905219},
928
  {1349, 16905475}, {1350, 16905731}, {1351, 16905987}, {1352, 16906243},
929
  {1353, 16906499}, {1354, 16906755}, {1355, 16907011}, {1356, 16907267},
930
  {1357, 16907523}, {1358, 16907779}, {1359, 16908035}, {1360, 16908291},
931
  {1361, 16908547}, {1362, 16908803}, {1363, 16909059}, {1364, 16909315},
932
  {1365, 16909571}, {1366, 16909827}, {1367, 2}, {1369, 1},
933
  {1415, 33687299}, {1416, 1}, {1419, 2}, {1421, 1},
934
  {1424, 2}, {1425, 1}, {1480, 2}, {1488, 1},
935
  {1515, 2}, {1519, 1}, {1525, 2}, {1542, 1},
936
  {1564, 2}, {1565, 1}, {1653, 33687811}, {1654, 33688323},
937
  {1655, 33688835}, {1656, 33689347}, {1657, 1}, {1757, 2},
938
  {1758, 1}, {1806, 2}, {1808, 1}, {1867, 2},
939
  {1869, 1}, {1970, 2}, {1984, 1}, {2043, 2},
940
  {2045, 1}, {2094, 2}, {2096, 1}, {2111, 2},
941
  {2112, 1}, {2140, 2}, {2142, 1}, {2143, 2},
942
  {2144, 1}, {2155, 2}, {2160, 1}, {2191, 2},
943
  {2199, 1}, {2274, 2}, {2275, 1}, {2392, 33689859},
944
  {2393, 33690371}, {2394, 33690883}, {2395, 33691395}, {2396, 33691907},
945
  {2397, 33692419}, {2398, 33692931}, {2399, 33693443}, {2400, 1},
946
  {2436, 2}, {2437, 1}, {2445, 2}, {2447, 1},
947
  {2449, 2}, {2451, 1}, {2473, 2}, {2474, 1},
948
  {2481, 2}, {2482, 1}, {2483, 2}, {2486, 1},
949
  {2490, 2}, {2492, 1}, {2501, 2}, {2503, 1},
950
  {2505, 2}, {2507, 1}, {2511, 2}, {2519, 1},
951
  {2520, 2}, {2524, 33693955}, {2525, 33694467}, {2526, 2},
952
  {2527, 33694979}, {2528, 1}, {2532, 2}, {2534, 1},
953
  {2559, 2}, {2561, 1}, {2564, 2}, {2565, 1},
954
  {2571, 2}, {2575, 1}, {2577, 2}, {2579, 1},
955
  {2601, 2}, {2602, 1}, {2609, 2}, {2610, 1},
956
  {2611, 33695491}, {2612, 2}, {2613, 1}, {2614, 33696003},
957
  {2615, 2}, {2616, 1}, {2618, 2}, {2620, 1},
958
  {2621, 2}, {2622, 1}, {2627, 2}, {2631, 1},
959
  {2633, 2}, {2635, 1}, {2638, 2}, {2641, 1},
960
  {2642, 2}, {2649, 33696515}, {2650, 33697027}, {2651, 33697539},
961
  {2652, 1}, {2653, 2}, {2654, 33698051}, {2655, 2},
962
  {2662, 1}, {2679, 2}, {2689, 1}, {2692, 2},
963
  {2693, 1}, {2702, 2}, {2703, 1}, {2706, 2},
964
  {2707, 1}, {2729, 2}, {2730, 1}, {2737, 2},
965
  {2738, 1}, {2740, 2}, {2741, 1}, {2746, 2},
966
  {2748, 1}, {2758, 2}, {2759, 1}, {2762, 2},
967
  {2763, 1}, {2766, 2}, {2768, 1}, {2769, 2},
968
  {2784, 1}, {2788, 2}, {2790, 1}, {2802, 2},
969
  {2809, 1}, {2816, 2}, {2817, 1}, {2820, 2},
970
  {2821, 1}, {2829, 2}, {2831, 1}, {2833, 2},
971
  {2835, 1}, {2857, 2}, {2858, 1}, {2865, 2},
972
  {2866, 1}, {2868, 2}, {2869, 1}, {2874, 2},
973
  {2876, 1}, {2885, 2}, {2887, 1}, {2889, 2},
974
  {2891, 1}, {2894, 2}, {2901, 1}, {2904, 2},
975
  {2908, 33698563}, {2909, 33699075}, {2910, 2}, {2911, 1},
976
  {2916, 2}, {2918, 1}, {2936, 2}, {2946, 1},
977
  {2948, 2}, {2949, 1}, {2955, 2}, {2958, 1},
978
  {2961, 2}, {2962, 1}, {2966, 2}, {2969, 1},
979
  {2971, 2}, {2972, 1}, {2973, 2}, {2974, 1},
980
  {2976, 2}, {2979, 1}, {2981, 2}, {2984, 1},
981
  {2987, 2}, {2990, 1}, {3002, 2}, {3006, 1},
982
  {3011, 2}, {3014, 1}, {3017, 2}, {3018, 1},
983
  {3022, 2}, {3024, 1}, {3025, 2}, {3031, 1},
984
  {3032, 2}, {3046, 1}, {3067, 2}, {3072, 1},
985
  {3085, 2}, {3086, 1}, {3089, 2}, {3090, 1},
986
  {3113, 2}, {3114, 1}, {3130, 2}, {3132, 1},
987
  {3141, 2}, {3142, 1}, {3145, 2}, {3146, 1},
988
  {3150, 2}, {3157, 1}, {3159, 2}, {3160, 1},
989
  {3163, 2}, {3165, 1}, {3166, 2}, {3168, 1},
990
  {3172, 2}, {3174, 1}, {3184, 2}, {3191, 1},
991
  {3213, 2}, {3214, 1}, {3217, 2}, {3218, 1},
992
  {3241, 2}, {3242, 1}, {3252, 2}, {3253, 1},
993
  {3258, 2}, {3260, 1}, {3269, 2}, {3270, 1},
994
  {3273, 2}, {3274, 1}, {3278, 2}, {3285, 1},
995
  {3287, 2}, {3293, 1}, {3295, 2}, {3296, 1},
996
  {3300, 2}, {3302, 1}, {3312, 2}, {3313, 1},
997
  {3316, 2}, {3328, 1}, {3341, 2}, {3342, 1},
998
  {3345, 2}, {3346, 1}, {3397, 2}, {3398, 1},
999
  {3401, 2}, {3402, 1}, {3408, 2}, {3412, 1},
1000
  {3428, 2}, {3430, 1}, {3456, 2}, {3457, 1},
1001
  {3460, 2}, {3461, 1}, {3479, 2}, {3482, 1},
1002
  {3506, 2}, {3507, 1}, {3516, 2}, {3517, 1},
1003
  {3518, 2}, {3520, 1}, {3527, 2}, {3530, 1},
1004
  {3531, 2}, {3535, 1}, {3541, 2}, {3542, 1},
1005
  {3543, 2}, {3544, 1}, {3552, 2}, {3558, 1},
1006
  {3568, 2}, {3570, 1}, {3573, 2}, {3585, 1},
1007
  {3635, 33699587}, {3636, 1}, {3643, 2}, {3647, 1},
1008
  {3676, 2}, {3713, 1}, {3715, 2}, {3716, 1},
1009
  {3717, 2}, {3718, 1}, {3723, 2}, {3724, 1},
1010
  {3748, 2}, {3749, 1}, {3750, 2}, {3751, 1},
1011
  {3763, 33700099}, {3764, 1}, {3774, 2}, {3776, 1},
1012
  {3781, 2}, {3782, 1}, {3783, 2}, {3784, 1},
1013
  {3791, 2}, {3792, 1}, {3802, 2}, {3804, 33700611},
1014
  {3805, 33701123}, {3806, 1}, {3808, 2}, {3840, 1},
1015
  {3852, 16924419}, {3853, 1}, {3907, 33701891}, {3908, 1},
1016
  {3912, 2}, {3913, 1}, {3917, 33702403}, {3918, 1},
1017
  {3922, 33702915}, {3923, 1}, {3927, 33703427}, {3928, 1},
1018
  {3932, 33703939}, {3933, 1}, {3945, 33704451}, {3946, 1},
1019
  {3949, 2}, {3953, 1}, {3955, 33704963}, {3956, 1},
1020
  {3957, 33705475}, {3958, 33705987}, {3959, 50483715}, {3960, 33707267},
1021
  {3961, 50484995}, {3962, 1}, {3969, 33706755}, {3970, 1},
1022
  {3987, 33708547}, {3988, 1}, {3992, 2}, {3993, 1},
1023
  {3997, 33709059}, {3998, 1}, {4002, 33709571}, {4003, 1},
1024
  {4007, 33710083}, {4008, 1}, {4012, 33710595}, {4013, 1},
1025
  {4025, 33711107}, {4026, 1}, {4029, 2}, {4030, 1},
1026
  {4045, 2}, {4046, 1}, {4059, 2}, {4096, 1},
1027
  {4256, 16934403}, {4257, 16934659}, {4258, 16934915}, {4259, 16935171},
1028
  {4260, 16935427}, {4261, 16935683}, {4262, 16935939}, {4263, 16936195},
1029
  {4264, 16936451}, {4265, 16936707}, {4266, 16936963}, {4267, 16937219},
1030
  {4268, 16937475}, {4269, 16937731}, {4270, 16937987}, {4271, 16938243},
1031
  {4272, 16938499}, {4273, 16938755}, {4274, 16939011}, {4275, 16939267},
1032
  {4276, 16939523}, {4277, 16939779}, {4278, 16940035}, {4279, 16940291},
1033
  {4280, 16940547}, {4281, 16940803}, {4282, 16941059}, {4283, 16941315},
1034
  {4284, 16941571}, {4285, 16941827}, {4286, 16942083}, {4287, 16942339},
1035
  {4288, 16942595}, {4289, 16942851}, {4290, 16943107}, {4291, 16943363},
1036
  {4292, 16943619}, {4293, 16943875}, {4294, 2}, {4295, 16944131},
1037
  {4296, 2}, {4301, 16944387}, {4302, 2}, {4304, 1},
1038
  {4348, 16944643}, {4349, 1}, {4447, 0}, {4449, 1},
1039
  {4681, 2}, {4682, 1}, {4686, 2}, {4688, 1},
1040
  {4695, 2}, {4696, 1}, {4697, 2}, {4698, 1},
1041
  {4702, 2}, {4704, 1}, {4745, 2}, {4746, 1},
1042
  {4750, 2}, {4752, 1}, {4785, 2}, {4786, 1},
1043
  {4790, 2}, {4792, 1}, {4799, 2}, {4800, 1},
1044
  {4801, 2}, {4802, 1}, {4806, 2}, {4808, 1},
1045
  {4823, 2}, {4824, 1}, {4881, 2}, {4882, 1},
1046
  {4886, 2}, {4888, 1}, {4955, 2}, {4957, 1},
1047
  {4989, 2}, {4992, 1}, {5018, 2}, {5024, 1},
1048
  {5110, 2}, {5112, 16944899}, {5113, 16945155}, {5114, 16945411},
1049
  {5115, 16945667}, {5116, 16945923}, {5117, 16946179}, {5118, 2},
1050
  {5120, 1}, {5760, 2}, {5761, 1}, {5789, 2},
1051
  {5792, 1}, {5881, 2}, {5888, 1}, {5910, 2},
1052
  {5919, 1}, {5943, 2}, {5952, 1}, {5972, 2},
1053
  {5984, 1}, {5997, 2}, {5998, 1}, {6001, 2},
1054
  {6002, 1}, {6004, 2}, {6016, 1}, {6068, 0},
1055
  {6070, 1}, {6110, 2}, {6112, 1}, {6122, 2},
1056
  {6128, 1}, {6138, 2}, {6144, 1}, {6155, 0},
1057
  {6160, 1}, {6170, 2}, {6176, 1}, {6265, 2},
1058
  {6272, 1}, {6315, 2}, {6320, 1}, {6390, 2},
1059
  {6400, 1}, {6431, 2}, {6432, 1}, {6444, 2},
1060
  {6448, 1}, {6460, 2}, {6464, 1}, {6465, 2},
1061
  {6468, 1}, {6510, 2}, {6512, 1}, {6517, 2},
1062
  {6528, 1}, {6572, 2}, {6576, 1}, {6602, 2},
1063
  {6608, 1}, {6619, 2}, {6622, 1}, {6684, 2},
1064
  {6686, 1}, {6751, 2}, {6752, 1}, {6781, 2},
1065
  {6783, 1}, {6794, 2}, {6800, 1}, {6810, 2},
1066
  {6816, 1}, {6830, 2}, {6832, 1}, {6863, 2},
1067
  {6912, 1}, {6989, 2}, {6990, 1}, {7156, 2},
1068
  {7164, 1}, {7224, 2}, {7227, 1}, {7242, 2},
1069
  {7245, 1}, {7296, 16867075}, {7297, 16867587}, {7298, 16870147},
1070
  {7299, 16870915}, {7300, 16871171}, {7302, 16873219}, {7303, 16875011},
1071
  {7304, 16946435}, {7305, 16946691}, {7306, 1}, {7307, 2},
1072
  {7312, 16946947}, {7313, 16947203}, {7314, 16947459}, {7315, 16947715},
1073
  {7316, 16947971}, {7317, 16948227}, {7318, 16948483}, {7319, 16948739},
1074
  {7320, 16948995}, {7321, 16949251}, {7322, 16949507}, {7323, 16949763},
1075
  {7324, 16944643}, {7325, 16950019}, {7326, 16950275}, {7327, 16950531},
1076
  {7328, 16950787}, {7329, 16951043}, {7330, 16951299}, {7331, 16951555},
1077
  {7332, 16951811}, {7333, 16952067}, {7334, 16952323}, {7335, 16952579},
1078
  {7336, 16952835}, {7337, 16953091}, {7338, 16953347}, {7339, 16953603},
1079
  {7340, 16953859}, {7341, 16954115}, {7342, 16954371}, {7343, 16954627},
1080
  {7344, 16954883}, {7345, 16955139}, {7346, 16955395}, {7347, 16955651},
1081
  {7348, 16955907}, {7349, 16956163}, {7350, 16956419}, {7351, 16956675},
1082
  {7352, 16956931}, {7353, 16957187}, {7354, 16957443}, {7355, 2},
1083
  {7357, 16957699}, {7358, 16957955}, {7359, 16958211}, {7360, 1},
1084
  {7368, 2}, {7376, 1}, {7419, 2}, {7424, 1},
1085
  {7468, 16777219}, {7469, 16791043}, {7470, 16777475}, {7471, 1},
1086
  {7472, 16777987}, {7473, 16778243}, {7474, 16816131}, {7475, 16778755},
1087
  {7476, 16779011}, {7477, 16779267}, {7478, 16779523}, {7479, 16779779},
1088
  {7480, 16780035}, {7481, 16780291}, {7482, 16780547}, {7483, 1},
1089
  {7484, 16780803}, {7485, 16835843}, {7486, 16781059}, {7487, 16781571},
1090
  {7488, 16782083}, {7489, 16782339}, {7490, 16782851}, {7491, 16777219},
1091
  {7492, 16958467}, {7493, 16958723}, {7494, 16958979}, {7495, 16777475},
1092
  {7496, 16777987}, {7497, 16778243}, {7498, 16816387}, {7499, 16816643},
1093
  {7500, 16959235}, {7501, 16778755}, {7502, 1}, {7503, 16779779},
1094
  {7504, 16780291}, {7505, 16807171}, {7506, 16780803}, {7507, 16814851},
1095
  {7508, 16959491}, {7509, 16959747}, {7510, 16781059}, {7511, 16782083},
1096
  {7512, 16782339}, {7513, 16960003}, {7514, 16818435}, {7515, 16782595},
1097
  {7516, 16960259}, {7517, 16851971}, {7518, 16852227}, {7519, 16852483},
1098
  {7520, 16856323}, {7521, 16856579}, {7522, 16779267}, {7523, 16781571},
1099
  {7524, 16782339}, {7525, 16782595}, {7526, 16851971}, {7527, 16852227},
1100
  {7528, 16855299}, {7529, 16856323}, {7530, 16856579}, {7531, 1},
1101
  {7544, 16869891}, {7545, 1}, {7579, 16960515}, {7580, 16777731},
1102
  {7581, 16960771}, {7582, 16793603}, {7583, 16959235}, {7584, 16778499},
1103
  {7585, 16961027}, {7586, 16961283}, {7587, 16961539}, {7588, 16817923},
1104
  {7589, 16817667}, {7590, 16961795}, {7591, 16962051}, {7592, 16962307},
1105
  {7593, 16962563}, {7594, 16962819}, {7595, 16963075}, {7596, 16963331},
1106
  {7597, 16963587}, {7598, 16818691}, {7599, 16963843}, {7600, 16964099},
1107
  {7601, 16818947}, {7602, 16964355}, {7603, 16964611}, {7604, 16820483},
1108
  {7605, 16964867}, {7606, 16839683}, {7607, 16821507}, {7608, 16965123},
1109
  {7609, 16821763}, {7610, 16839939}, {7611, 16783619}, {7612, 16965379},
1110
  {7613, 16965635}, {7614, 16822531}, {7615, 16853507}, {7616, 1},
1111
  {7680, 16965891}, {7681, 1}, {7682, 16966147}, {7683, 1},
1112
  {7684, 16966403}, {7685, 1}, {7686, 16966659}, {7687, 1},
1113
  {7688, 16966915}, {7689, 1}, {7690, 16967171}, {7691, 1},
1114
  {7692, 16967427}, {7693, 1}, {7694, 16967683}, {7695, 1},
1115
  {7696, 16967939}, {7697, 1}, {7698, 16968195}, {7699, 1},
1116
  {7700, 16968451}, {7701, 1}, {7702, 16968707}, {7703, 1},
1117
  {7704, 16968963}, {7705, 1}, {7706, 16969219}, {7707, 1},
1118
  {7708, 16969475}, {7709, 1}, {7710, 16969731}, {7711, 1},
1119
  {7712, 16969987}, {7713, 1}, {7714, 16970243}, {7715, 1},
1120
  {7716, 16970499}, {7717, 1}, {7718, 16970755}, {7719, 1},
1121
  {7720, 16971011}, {7721, 1}, {7722, 16971267}, {7723, 1},
1122
  {7724, 16971523}, {7725, 1}, {7726, 16971779}, {7727, 1},
1123
  {7728, 16972035}, {7729, 1}, {7730, 16972291}, {7731, 1},
1124
  {7732, 16972547}, {7733, 1}, {7734, 16972803}, {7735, 1},
1125
  {7736, 16973059}, {7737, 1}, {7738, 16973315}, {7739, 1},
1126
  {7740, 16973571}, {7741, 1}, {7742, 16973827}, {7743, 1},
1127
  {7744, 16974083}, {7745, 1}, {7746, 16974339}, {7747, 1},
1128
  {7748, 16974595}, {7749, 1}, {7750, 16974851}, {7751, 1},
1129
  {7752, 16975107}, {7753, 1}, {7754, 16975363}, {7755, 1},
1130
  {7756, 16975619}, {7757, 1}, {7758, 16975875}, {7759, 1},
1131
  {7760, 16976131}, {7761, 1}, {7762, 16976387}, {7763, 1},
1132
  {7764, 16976643}, {7765, 1}, {7766, 16976899}, {7767, 1},
1133
  {7768, 16977155}, {7769, 1}, {7770, 16977411}, {7771, 1},
1134
  {7772, 16977667}, {7773, 1}, {7774, 16977923}, {7775, 1},
1135
  {7776, 16978179}, {7777, 1}, {7778, 16978435}, {7779, 1},
1136
  {7780, 16978691}, {7781, 1}, {7782, 16978947}, {7783, 1},
1137
  {7784, 16979203}, {7785, 1}, {7786, 16979459}, {7787, 1},
1138
  {7788, 16979715}, {7789, 1}, {7790, 16979971}, {7791, 1},
1139
  {7792, 16980227}, {7793, 1}, {7794, 16980483}, {7795, 1},
1140
  {7796, 16980739}, {7797, 1}, {7798, 16980995}, {7799, 1},
1141
  {7800, 16981251}, {7801, 1}, {7802, 16981507}, {7803, 1},
1142
  {7804, 16981763}, {7805, 1}, {7806, 16982019}, {7807, 1},
1143
  {7808, 16982275}, {7809, 1}, {7810, 16982531}, {7811, 1},
1144
  {7812, 16982787}, {7813, 1}, {7814, 16983043}, {7815, 1},
1145
  {7816, 16983299}, {7817, 1}, {7818, 16983555}, {7819, 1},
1146
  {7820, 16983811}, {7821, 1}, {7822, 16984067}, {7823, 1},
1147
  {7824, 16984323}, {7825, 1}, {7826, 16984579}, {7827, 1},
1148
  {7828, 16984835}, {7829, 1}, {7834, 33762307}, {7835, 16978179},
1149
  {7836, 1}, {7838, 16985603}, {7839, 1}, {7840, 16985859},
1150
  {7841, 1}, {7842, 16986115}, {7843, 1}, {7844, 16986371},
1151
  {7845, 1}, {7846, 16986627}, {7847, 1}, {7848, 16986883},
1152
  {7849, 1}, {7850, 16987139}, {7851, 1}, {7852, 16987395},
1153
  {7853, 1}, {7854, 16987651}, {7855, 1}, {7856, 16987907},
1154
  {7857, 1}, {7858, 16988163}, {7859, 1}, {7860, 16988419},
1155
  {7861, 1}, {7862, 16988675}, {7863, 1}, {7864, 16988931},
1156
  {7865, 1}, {7866, 16989187}, {7867, 1}, {7868, 16989443},
1157
  {7869, 1}, {7870, 16989699}, {7871, 1}, {7872, 16989955},
1158
  {7873, 1}, {7874, 16990211}, {7875, 1}, {7876, 16990467},
1159
  {7877, 1}, {7878, 16990723}, {7879, 1}, {7880, 16990979},
1160
  {7881, 1}, {7882, 16991235}, {7883, 1}, {7884, 16991491},
1161
  {7885, 1}, {7886, 16991747}, {7887, 1}, {7888, 16992003},
1162
  {7889, 1}, {7890, 16992259}, {7891, 1}, {7892, 16992515},
1163
  {7893, 1}, {7894, 16992771}, {7895, 1}, {7896, 16993027},
1164
  {7897, 1}, {7898, 16993283}, {7899, 1}, {7900, 16993539},
1165
  {7901, 1}, {7902, 16993795}, {7903, 1}, {7904, 16994051},
1166
  {7905, 1}, {7906, 16994307}, {7907, 1}, {7908, 16994563},
1167
  {7909, 1}, {7910, 16994819}, {7911, 1}, {7912, 16995075},
1168
  {7913, 1}, {7914, 16995331}, {7915, 1}, {7916, 16995587},
1169
  {7917, 1}, {7918, 16995843}, {7919, 1}, {7920, 16996099},
1170
  {7921, 1}, {7922, 16996355}, {7923, 1}, {7924, 16996611},
1171
  {7925, 1}, {7926, 16996867}, {7927, 1}, {7928, 16997123},
1172
  {7929, 1}, {7930, 16997379}, {7931, 1}, {7932, 16997635},
1173
  {7933, 1}, {7934, 16997891}, {7935, 1}, {7944, 16998147},
1174
  {7945, 16998403}, {7946, 16998659}, {7947, 16998915}, {7948, 16999171},
1175
  {7949, 16999427}, {7950, 16999683}, {7951, 16999939}, {7952, 1},
1176
  {7958, 2}, {7960, 17000195}, {7961, 17000451}, {7962, 17000707},
1177
  {7963, 17000963}, {7964, 17001219}, {7965, 17001475}, {7966, 2},
1178
  {7968, 1}, {7976, 17001731}, {7977, 17001987}, {7978, 17002243},
1179
  {7979, 17002499}, {7980, 17002755}, {7981, 17003011}, {7982, 17003267},
1180
  {7983, 17003523}, {7984, 1}, {7992, 17003779}, {7993, 17004035},
1181
  {7994, 17004291}, {7995, 17004547}, {7996, 17004803}, {7997, 17005059},
1182
  {7998, 17005315}, {7999, 17005571}, {8000, 1}, {8006, 2},
1183
  {8008, 17005827}, {8009, 17006083}, {8010, 17006339}, {8011, 17006595},
1184
  {8012, 17006851}, {8013, 17007107}, {8014, 2}, {8016, 1},
1185
  {8024, 2}, {8025, 17007363}, {8026, 2}, {8027, 17007619},
1186
  {8028, 2}, {8029, 17007875}, {8030, 2}, {8031, 17008131},
1187
  {8032, 1}, {8040, 17008387}, {8041, 17008643}, {8042, 17008899},
1188
  {8043, 17009155}, {8044, 17009411}, {8045, 17009667}, {8046, 17009923},
1189
  {8047, 17010179}, {8048, 1}, {8049, 16849923}, {8050, 1},
1190
  {8051, 16850179}, {8052, 1}, {8053, 16850435}, {8054, 1},
1191
  {8055, 16850691}, {8056, 1}, {8057, 16850947}, {8058, 1},
1192
  {8059, 16851203}, {8060, 1}, {8061, 16851459}, {8062, 2},
1193
  {8064, 33787651}, {8065, 33788163}, {8066, 33788675}, {8067, 33789187},
1194
  {8068, 33789699}, {8069, 33790211}, {8070, 33790723}, {8071, 33791235},
1195
  {8072, 33787651}, {8073, 33788163}, {8074, 33788675}, {8075, 33789187},
1196
  {8076, 33789699}, {8077, 33790211}, {8078, 33790723}, {8079, 33791235},
1197
  {8080, 33791747}, {8081, 33792259}, {8082, 33792771}, {8083, 33793283},
1198
  {8084, 33793795}, {8085, 33794307}, {8086, 33794819}, {8087, 33795331},
1199
  {8088, 33791747}, {8089, 33792259}, {8090, 33792771}, {8091, 33793283},
1200
  {8092, 33793795}, {8093, 33794307}, {8094, 33794819}, {8095, 33795331},
1201
  {8096, 33795843}, {8097, 33796355}, {8098, 33796867}, {8099, 33797379},
1202
  {8100, 33797891}, {8101, 33798403}, {8102, 33798915}, {8103, 33799427},
1203
  {8104, 33795843}, {8105, 33796355}, {8106, 33796867}, {8107, 33797379},
1204
  {8108, 33797891}, {8109, 33798403}, {8110, 33798915}, {8111, 33799427},
1205
  {8112, 1}, {8114, 33799939}, {8115, 33800451}, {8116, 33800963},
1206
  {8117, 2}, {8118, 1}, {8119, 33801475}, {8120, 17024771},
1207
  {8121, 17025027}, {8122, 17022723}, {8123, 16849923}, {8124, 33800451},
1208
  {8125, 33802499}, {8126, 16846851}, {8127, 33802499}, {8128, 33803011},
1209
  {8129, 50580739}, {8130, 33804291}, {8131, 33804803}, {8132, 33805315},
1210
  {8133, 2}, {8134, 1}, {8135, 33805827}, {8136, 17029123},
1211
  {8137, 16850179}, {8138, 17027075}, {8139, 16850435}, {8140, 33804803},
1212
  {8141, 50583811}, {8142, 50584579}, {8143, 50585347}, {8144, 1},
1213
  {8147, 17031683}, {8148, 2}, {8150, 1}, {8152, 17031939},
1214
  {8153, 17032195}, {8154, 17032451}, {8155, 16850691}, {8156, 2},
1215
  {8157, 50587139}, {8158, 50587907}, {8159, 50588675}, {8160, 1},
1216
  {8163, 17035011}, {8164, 1}, {8168, 17035267}, {8169, 17035523},
1217
  {8170, 17035779}, {8171, 16851203}, {8172, 17036035}, {8173, 50590723},
1218
  {8174, 50403587}, {8175, 17037059}, {8176, 2}, {8178, 33814531},
1219
  {8179, 33815043}, {8180, 33815555}, {8181, 2}, {8182, 1},
1220
  {8183, 33816067}, {8184, 17039363}, {8185, 16850947}, {8186, 17037315},
1221
  {8187, 16851459}, {8188, 33815043}, {8189, 33562883}, {8190, 33809923},
1222
  {8191, 2}, {8192, 16783875}, {8203, 0}, {8204, 1},
1223
  {8206, 2}, {8208, 1}, {8209, 17039619}, {8210, 1},
1224
  {8215, 33817091}, {8216, 1}, {8228, 2}, {8231, 1},
1225
  {8232, 2}, {8239, 16783875}, {8240, 1}, {8243, 33817603},
1226
  {8244, 50595331}, {8245, 1}, {8246, 33818883}, {8247, 50596611},
1227
  {8248, 1}, {8252, 33820163}, {8253, 1}, {8254, 33820675},
1228
  {8255, 1}, {8263, 33821187}, {8264, 33821699}, {8265, 33822211},
1229
  {8266, 1}, {8279, 67372035}, {8280, 1}, {8287, 16783875},
1230
  {8288, 0}, {8293, 2}, {8298, 0}, {8304, 17045507},
1231
  {8305, 16779267}, {8306, 2}, {8308, 16787715}, {8309, 17045763},
1232
  {8310, 17046019}, {8311, 17046275}, {8312, 17046531}, {8313, 17046787},
1233
  {8314, 17047043}, {8315, 17047299}, {8316, 17047555}, {8317, 17047811},
1234
  {8318, 17048067}, {8319, 16780547}, {8320, 17045507}, {8321, 16786947},
1235
  {8322, 16785155}, {8323, 16785411}, {8324, 16787715}, {8325, 17045763},
1236
  {8326, 17046019}, {8327, 17046275}, {8328, 17046531}, {8329, 17046787},
1237
  {8330, 17047043}, {8331, 17047299}, {8332, 17047555}, {8333, 17047811},
1238
  {8334, 17048067}, {8335, 2}, {8336, 16777219}, {8337, 16778243},
1239
  {8338, 16780803}, {8339, 16783107}, {8340, 16816387}, {8341, 16779011},
1240
  {8342, 16779779}, {8343, 16780035}, {8344, 16780291}, {8345, 16780547},
1241
  {8346, 16781059}, {8347, 16781827}, {8348, 16782083}, {8349, 2},
1242
  {8352, 1}, {8360, 33558787}, {8361, 1}, {8385, 2},
1243
  {8400, 1}, {8433, 2}, {8448, 50602755}, {8449, 50603523},
1244
  {8450, 16777731}, {8451, 33827075}, {8452, 1}, {8453, 50604803},
1245
  {8454, 50605571}, {8455, 16816643}, {8456, 1}, {8457, 33829123},
1246
  {8458, 16778755}, {8459, 16779011}, {8463, 16802051}, {8464, 16779267},
1247
  {8466, 16780035}, {8468, 1}, {8469, 16780547}, {8470, 33557763},
1248
  {8471, 1}, {8473, 16781059}, {8474, 16781315}, {8475, 16781571},
1249
  {8478, 1}, {8480, 33829635}, {8481, 50607363}, {8482, 33830915},
1250
  {8483, 1}, {8484, 16783619}, {8485, 1}, {8486, 16857091},
1251
  {8487, 1}, {8488, 16783619}, {8489, 1}, {8490, 16779779},
1252
  {8491, 16790787}, {8492, 16777475}, {8493, 16777731}, {8494, 1},
1253
  {8495, 16778243}, {8497, 16778499}, {8498, 17054211}, {8499, 16780291},
1254
  {8500, 16780803}, {8501, 17054467}, {8502, 17054723}, {8503, 17054979},
1255
  {8504, 17055235}, {8505, 16779267}, {8506, 1}, {8507, 50609923},
1256
  {8508, 16855043}, {8509, 16852227}, {8511, 16855043}, {8512, 17056259},
1257
  {8513, 1}, {8517, 16777987}, {8519, 16778243}, {8520, 16779267},
1258
  {8521, 16779523}, {8522, 1}, {8528, 50610947}, {8529, 50611715},
1259
  {8530, 67389699}, {8531, 50613507}, {8532, 50614275}, {8533, 50615043},
1260
  {8534, 50615811}, {8535, 50616579}, {8536, 50617347}, {8537, 50618115},
1261
  {8538, 50618883}, {8539, 50619651}, {8540, 50620419}, {8541, 50621187},
1262
  {8542, 50621955}, {8543, 33564419}, {8544, 16779267}, {8545, 33845507},
1263
  {8546, 50623235}, {8547, 33846787}, {8548, 16782595}, {8549, 33847299},
1264
  {8550, 50625027}, {8551, 67403011}, {8552, 33849603}, {8553, 16783107},
1265
  {8554, 33850115}, {8555, 50627843}, {8556, 16780035}, {8557, 16777731},
1266
  {8558, 16777987}, {8559, 16780291}, {8560, 16779267}, {8561, 33845507},
1267
  {8562, 50622723}, {8563, 33846787}, {8564, 16782595}, {8565, 33847299},
1268
  {8566, 50625027}, {8567, 67403011}, {8568, 33849603}, {8569, 16783107},
1269
  {8570, 33850115}, {8571, 50627843}, {8572, 16780035}, {8573, 16777731},
1270
  {8574, 16777987}, {8575, 16780291}, {8576, 1}, {8579, 17074179},
1271
  {8580, 1}, {8585, 50628867}, {8586, 1}, {8588, 2},
1272
  {8592, 1}, {8748, 33852419}, {8749, 50630147}, {8750, 1},
1273
  {8751, 33853699}, {8752, 50631427}, {8753, 1}, {9001, 17077763},
1274
  {9002, 17078019}, {9003, 1}, {9258, 2}, {9280, 1},
1275
  {9291, 2}, {9312, 16786947}, {9313, 16785155}, {9314, 16785411},
1276
  {9315, 16787715}, {9316, 17045763}, {9317, 17046019}, {9318, 17046275},
1277
  {9319, 17046531}, {9320, 17046787}, {9321, 33835779}, {9322, 33564163},
1278
  {9323, 33855491}, {9324, 33856003}, {9325, 33856515}, {9326, 33857027},
1279
  {9327, 33857539}, {9328, 33858051}, {9329, 33858563}, {9330, 33859075},
1280
  {9331, 33859587}, {9332, 50637315}, {9333, 50638083}, {9334, 50638851},
1281
  {9335, 50639619}, {9336, 50640387}, {9337, 50641155}, {9338, 50641923},
1282
  {9339, 50642691}, {9340, 50643459}, {9341, 67421443}, {9342, 67422467},
1283
  {9343, 67423491}, {9344, 67424515}, {9345, 67425539}, {9346, 67426563},
1284
  {9347, 67427587}, {9348, 67428611}, {9349, 67429635}, {9350, 67430659},
1285
  {9351, 67431683}, {9352, 2}, {9372, 50655491}, {9373, 50656259},
1286
  {9374, 50657027}, {9375, 50657795}, {9376, 50658563}, {9377, 50659331},
1287
  {9378, 50660099}, {9379, 50660867}, {9380, 50661635}, {9381, 50662403},
1288
  {9382, 50663171}, {9383, 50663939}, {9384, 50664707}, {9385, 50665475},
1289
  {9386, 50666243}, {9387, 50667011}, {9388, 50667779}, {9389, 50668547},
1290
  {9390, 50669315}, {9391, 50670083}, {9392, 50670851}, {9393, 50671619},
1291
  {9394, 50672387}, {9395, 50673155}, {9396, 50673923}, {9397, 50674691},
1292
  {9398, 16777219}, {9399, 16777475}, {9400, 16777731}, {9401, 16777987},
1293
  {9402, 16778243}, {9403, 16778499}, {9404, 16778755}, {9405, 16779011},
1294
  {9406, 16779267}, {9407, 16779523}, {9408, 16779779}, {9409, 16780035},
1295
  {9410, 16780291}, {9411, 16780547}, {9412, 16780803}, {9413, 16781059},
1296
  {9414, 16781315}, {9415, 16781571}, {9416, 16781827}, {9417, 16782083},
1297
  {9418, 16782339}, {9419, 16782595}, {9420, 16782851}, {9421, 16783107},
1298
  {9422, 16783363}, {9423, 16783619}, {9424, 16777219}, {9425, 16777475},
1299
  {9426, 16777731}, {9427, 16777987}, {9428, 16778243}, {9429, 16778499},
1300
  {9430, 16778755}, {9431, 16779011}, {9432, 16779267}, {9433, 16779523},
1301
  {9434, 16779779}, {9435, 16780035}, {9436, 16780291}, {9437, 16780547},
1302
  {9438, 16780803}, {9439, 16781059}, {9440, 16781315}, {9441, 16781571},
1303
  {9442, 16781827}, {9443, 16782083}, {9444, 16782339}, {9445, 16782595},
1304
  {9446, 16782851}, {9447, 16783107}, {9448, 16783363}, {9449, 16783619},
1305
  {9450, 17045507}, {9451, 1}, {10764, 67406851}, {10765, 1},
1306
  {10868, 50675459}, {10869, 33899011}, {10870, 50675971}, {10871, 1},
1307
  {10972, 33899523}, {10973, 1}, {11124, 2}, {11126, 1},
1308
  {11158, 2}, {11159, 1}, {11264, 17122819}, {11265, 17123075},
1309
  {11266, 17123331}, {11267, 17123587}, {11268, 17123843}, {11269, 17124099},
1310
  {11270, 17124355}, {11271, 17124611}, {11272, 17124867}, {11273, 17125123},
1311
  {11274, 17125379}, {11275, 17125635}, {11276, 17125891}, {11277, 17126147},
1312
  {11278, 17126403}, {11279, 17126659}, {11280, 17126915}, {11281, 17127171},
1313
  {11282, 17127427}, {11283, 17127683}, {11284, 17127939}, {11285, 17128195},
1314
  {11286, 17128451}, {11287, 17128707}, {11288, 17128963}, {11289, 17129219},
1315
  {11290, 17129475}, {11291, 17129731}, {11292, 17129987}, {11293, 17130243},
1316
  {11294, 17130499}, {11295, 17130755}, {11296, 17131011}, {11297, 17131267},
1317
  {11298, 17131523}, {11299, 17131779}, {11300, 17132035}, {11301, 17132291},
1318
  {11302, 17132547}, {11303, 17132803}, {11304, 17133059}, {11305, 17133315},
1319
  {11306, 17133571}, {11307, 17133827}, {11308, 17134083}, {11309, 17134339},
1320
  {11310, 17134595}, {11311, 17134851}, {11312, 1}, {11360, 17135107},
1321
  {11361, 1}, {11362, 17135363}, {11363, 17135619}, {11364, 17135875},
1322
  {11365, 1}, {11367, 17136131}, {11368, 1}, {11369, 17136387},
1323
  {11370, 1}, {11371, 17136643}, {11372, 1}, {11373, 16958723},
1324
  {11374, 16963331}, {11375, 16958467}, {11376, 16960515}, {11377, 1},
1325
  {11378, 17136899}, {11379, 1}, {11381, 17137155}, {11382, 1},
1326
  {11388, 16779523}, {11389, 16782595}, {11390, 17137411}, {11391, 17137667},
1327
  {11392, 17137923}, {11393, 1}, {11394, 17138179}, {11395, 1},
1328
  {11396, 17138435}, {11397, 1}, {11398, 17138691}, {11399, 1},
1329
  {11400, 17138947}, {11401, 1}, {11402, 17139203}, {11403, 1},
1330
  {11404, 17139459}, {11405, 1}, {11406, 17139715}, {11407, 1},
1331
  {11408, 17139971}, {11409, 1}, {11410, 17140227}, {11411, 1},
1332
  {11412, 17140483}, {11413, 1}, {11414, 17140739}, {11415, 1},
1333
  {11416, 17140995}, {11417, 1}, {11418, 17141251}, {11419, 1},
1334
  {11420, 17141507}, {11421, 1}, {11422, 17141763}, {11423, 1},
1335
  {11424, 17142019}, {11425, 1}, {11426, 17142275}, {11427, 1},
1336
  {11428, 17142531}, {11429, 1}, {11430, 17142787}, {11431, 1},
1337
  {11432, 17143043}, {11433, 1}, {11434, 17143299}, {11435, 1},
1338
  {11436, 17143555}, {11437, 1}, {11438, 17143811}, {11439, 1},
1339
  {11440, 17144067}, {11441, 1}, {11442, 17144323}, {11443, 1},
1340
  {11444, 17144579}, {11445, 1}, {11446, 17144835}, {11447, 1},
1341
  {11448, 17145091}, {11449, 1}, {11450, 17145347}, {11451, 1},
1342
  {11452, 17145603}, {11453, 1}, {11454, 17145859}, {11455, 1},
1343
  {11456, 17146115}, {11457, 1}, {11458, 17146371}, {11459, 1},
1344
  {11460, 17146627}, {11461, 1}, {11462, 17146883}, {11463, 1},
1345
  {11464, 17147139}, {11465, 1}, {11466, 17147395}, {11467, 1},
1346
  {11468, 17147651}, {11469, 1}, {11470, 17147907}, {11471, 1},
1347
  {11472, 17148163}, {11473, 1}, {11474, 17148419}, {11475, 1},
1348
  {11476, 17148675}, {11477, 1}, {11478, 17148931}, {11479, 1},
1349
  {11480, 17149187}, {11481, 1}, {11482, 17149443}, {11483, 1},
1350
  {11484, 17149699}, {11485, 1}, {11486, 17149955}, {11487, 1},
1351
  {11488, 17150211}, {11489, 1}, {11490, 17150467}, {11491, 1},
1352
  {11499, 17150723}, {11500, 1}, {11501, 17150979}, {11502, 1},
1353
  {11506, 17151235}, {11507, 1}, {11508, 2}, {11513, 1},
1354
  {11558, 2}, {11559, 1}, {11560, 2}, {11565, 1},
1355
  {11566, 2}, {11568, 1}, {11624, 2}, {11631, 17151491},
1356
  {11632, 1}, {11633, 2}, {11647, 1}, {11671, 2},
1357
  {11680, 1}, {11687, 2}, {11688, 1}, {11695, 2},
1358
  {11696, 1}, {11703, 2}, {11704, 1}, {11711, 2},
1359
  {11712, 1}, {11719, 2}, {11720, 1}, {11727, 2},
1360
  {11728, 1}, {11735, 2}, {11736, 1}, {11743, 2},
1361
  {11744, 1}, {11870, 2}, {11904, 1}, {11930, 2},
1362
  {11931, 1}, {11935, 17151747}, {11936, 1}, {12019, 17152003},
1363
  {12020, 2}, {12032, 17152259}, {12033, 17152515}, {12034, 17152771},
1364
  {12035, 17153027}, {12036, 17153283}, {12037, 17153539}, {12038, 17153795},
1365
  {12039, 17154051}, {12040, 17154307}, {12041, 17154563}, {12042, 17154819},
1366
  {12043, 17155075}, {12044, 17155331}, {12045, 17155587}, {12046, 17155843},
1367
  {12047, 17156099}, {12048, 17156355}, {12049, 17156611}, {12050, 17156867},
1368
  {12051, 17157123}, {12052, 17157379}, {12053, 17157635}, {12054, 17157891},
1369
  {12055, 17158147}, {12056, 17158403}, {12057, 17158659}, {12058, 17158915},
1370
  {12059, 17159171}, {12060, 17159427}, {12061, 17159683}, {12062, 17159939},
1371
  {12063, 17160195}, {12064, 17160451}, {12065, 17160707}, {12066, 17160963},
1372
  {12067, 17161219}, {12068, 17161475}, {12069, 17161731}, {12070, 17161987},
1373
  {12071, 17162243}, {12072, 17162499}, {12073, 17162755}, {12074, 17163011},
1374
  {12075, 17163267}, {12076, 17163523}, {12077, 17163779}, {12078, 17164035},
1375
  {12079, 17164291}, {12080, 17164547}, {12081, 17164803}, {12082, 17165059},
1376
  {12083, 17165315}, {12084, 17165571}, {12085, 17165827}, {12086, 17166083},
1377
  {12087, 17166339}, {12088, 17166595}, {12089, 17166851}, {12090, 17167107},
1378
  {12091, 17167363}, {12092, 17167619}, {12093, 17167875}, {12094, 17168131},
1379
  {12095, 17168387}, {12096, 17168643}, {12097, 17168899}, {12098, 17169155},
1380
  {12099, 17169411}, {12100, 17169667}, {12101, 17169923}, {12102, 17170179},
1381
  {12103, 17170435}, {12104, 17170691}, {12105, 17170947}, {12106, 17171203},
1382
  {12107, 17171459}, {12108, 17171715}, {12109, 17171971}, {12110, 17172227},
1383
  {12111, 17172483}, {12112, 17172739}, {12113, 17172995}, {12114, 17173251},
1384
  {12115, 17173507}, {12116, 17173763}, {12117, 17174019}, {12118, 17174275},
1385
  {12119, 17174531}, {12120, 17174787}, {12121, 17175043}, {12122, 17175299},
1386
  {12123, 17175555}, {12124, 17175811}, {12125, 17176067}, {12126, 17176323},
1387
  {12127, 17176579}, {12128, 17176835}, {12129, 17177091}, {12130, 17177347},
1388
  {12131, 17177603}, {12132, 17177859}, {12133, 17178115}, {12134, 17178371},
1389
  {12135, 17178627}, {12136, 17178883}, {12137, 17179139}, {12138, 17179395},
1390
  {12139, 17179651}, {12140, 17179907}, {12141, 17180163}, {12142, 17180419},
1391
  {12143, 17180675}, {12144, 17180931}, {12145, 17181187}, {12146, 17181443},
1392
  {12147, 17181699}, {12148, 17181955}, {12149, 17182211}, {12150, 17182467},
1393
  {12151, 17182723}, {12152, 17182979}, {12153, 17183235}, {12154, 17183491},
1394
  {12155, 17183747}, {12156, 17184003}, {12157, 17184259}, {12158, 17184515},
1395
  {12159, 17184771}, {12160, 17185027}, {12161, 17185283}, {12162, 17185539},
1396
  {12163, 17185795}, {12164, 17186051}, {12165, 17186307}, {12166, 17186563},
1397
  {12167, 17186819}, {12168, 17187075}, {12169, 17187331}, {12170, 17187587},
1398
  {12171, 17187843}, {12172, 17188099}, {12173, 17188355}, {12174, 17188611},
1399
  {12175, 17188867}, {12176, 17189123}, {12177, 17189379}, {12178, 17189635},
1400
  {12179, 17189891}, {12180, 17190147}, {12181, 17190403}, {12182, 17190659},
1401
  {12183, 17190915}, {12184, 17191171}, {12185, 17191427}, {12186, 17191683},
1402
  {12187, 17191939}, {12188, 17192195}, {12189, 17192451}, {12190, 17192707},
1403
  {12191, 17192963}, {12192, 17193219}, {12193, 17193475}, {12194, 17193731},
1404
  {12195, 17193987}, {12196, 17194243}, {12197, 17194499}, {12198, 17194755},
1405
  {12199, 17195011}, {12200, 17195267}, {12201, 17195523}, {12202, 17195779},
1406
  {12203, 17196035}, {12204, 17196291}, {12205, 17196547}, {12206, 17196803},
1407
  {12207, 17197059}, {12208, 17197315}, {12209, 17197571}, {12210, 17197827},
1408
  {12211, 17198083}, {12212, 17198339}, {12213, 17198595}, {12214, 17198851},
1409
  {12215, 17199107}, {12216, 17199363}, {12217, 17199619}, {12218, 17199875},
1410
  {12219, 17200131}, {12220, 17200387}, {12221, 17200643}, {12222, 17200899},
1411
  {12223, 17201155}, {12224, 17201411}, {12225, 17201667}, {12226, 17201923},
1412
  {12227, 17202179}, {12228, 17202435}, {12229, 17202691}, {12230, 17202947},
1413
  {12231, 17203203}, {12232, 17203459}, {12233, 17203715}, {12234, 17203971},
1414
  {12235, 17204227}, {12236, 17204483}, {12237, 17204739}, {12238, 17204995},
1415
  {12239, 17205251}, {12240, 17205507}, {12241, 17205763}, {12242, 17206019},
1416
  {12243, 17206275}, {12244, 17206531}, {12245, 17206787}, {12246, 2},
1417
  {12288, 16783875}, {12289, 1}, {12290, 17207043}, {12291, 1},
1418
  {12342, 17207299}, {12343, 1}, {12344, 17158147}, {12345, 17207555},
1419
  {12346, 17207811}, {12347, 1}, {12352, 2}, {12353, 1},
1420
  {12439, 2}, {12441, 1}, {12443, 33985283}, {12444, 33985795},
1421
  {12445, 1}, {12447, 33986307}, {12448, 1}, {12543, 33986819},
1422
  {12544, 2}, {12549, 1}, {12592, 2}, {12593, 17210115},
1423
  {12594, 17210371}, {12595, 17210627}, {12596, 17210883}, {12597, 17211139},
1424
  {12598, 17211395}, {12599, 17211651}, {12600, 17211907}, {12601, 17212163},
1425
  {12602, 17212419}, {12603, 17212675}, {12604, 17212931}, {12605, 17213187},
1426
  {12606, 17213443}, {12607, 17213699}, {12608, 17213955}, {12609, 17214211},
1427
  {12610, 17214467}, {12611, 17214723}, {12612, 17214979}, {12613, 17215235},
1428
  {12614, 17215491}, {12615, 17215747}, {12616, 17216003}, {12617, 17216259},
1429
  {12618, 17216515}, {12619, 17216771}, {12620, 17217027}, {12621, 17217283},
1430
  {12622, 17217539}, {12623, 17217795}, {12624, 17218051}, {12625, 17218307},
1431
  {12626, 17218563}, {12627, 17218819}, {12628, 17219075}, {12629, 17219331},
1432
  {12630, 17219587}, {12631, 17219843}, {12632, 17220099}, {12633, 17220355},
1433
  {12634, 17220611}, {12635, 17220867}, {12636, 17221123}, {12637, 17221379},
1434
  {12638, 17221635}, {12639, 17221891}, {12640, 17222147}, {12641, 17222403},
1435
  {12642, 17222659}, {12643, 17222915}, {12644, 0}, {12645, 17223171},
1436
  {12646, 17223427}, {12647, 17223683}, {12648, 17223939}, {12649, 17224195},
1437
  {12650, 17224451}, {12651, 17224707}, {12652, 17224963}, {12653, 17225219},
1438
  {12654, 17225475}, {12655, 17225731}, {12656, 17225987}, {12657, 17226243},
1439
  {12658, 17226499}, {12659, 17226755}, {12660, 17227011}, {12661, 17227267},
1440
  {12662, 17227523}, {12663, 17227779}, {12664, 17228035}, {12665, 17228291},
1441
  {12666, 17228547}, {12667, 17228803}, {12668, 17229059}, {12669, 17229315},
1442
  {12670, 17229571}, {12671, 17229827}, {12672, 17230083}, {12673, 17230339},
1443
  {12674, 17230595}, {12675, 17230851}, {12676, 17231107}, {12677, 17231363},
1444
  {12678, 17231619}, {12679, 17231875}, {12680, 17232131}, {12681, 17232387},
1445
  {12682, 17232643}, {12683, 17232899}, {12684, 17233155}, {12685, 17233411},
1446
  {12686, 17233667}, {12687, 2}, {12688, 1}, {12690, 17152259},
1447
  {12691, 17153795}, {12692, 17233923}, {12693, 17234179}, {12694, 17234435},
1448
  {12695, 17234691}, {12696, 17234947}, {12697, 17235203}, {12698, 17153283},
1449
  {12699, 17235459}, {12700, 17235715}, {12701, 17235971}, {12702, 17236227},
1450
  {12703, 17154307}, {12704, 1}, {12774, 2}, {12784, 1},
1451
  {12800, 50790915}, {12801, 50791683}, {12802, 50792451}, {12803, 50793219},
1452
  {12804, 50793987}, {12805, 50794755}, {12806, 50795523}, {12807, 50796291},
1453
  {12808, 50797059}, {12809, 50797827}, {12810, 50798595}, {12811, 50799363},
1454
  {12812, 50800131}, {12813, 50800899}, {12814, 50801667}, {12815, 50802435},
1455
  {12816, 50803203}, {12817, 50803971}, {12818, 50804739}, {12819, 50805507},
1456
  {12820, 50806275}, {12821, 50807043}, {12822, 50807811}, {12823, 50808579},
1457
  {12824, 50809347}, {12825, 50810115}, {12826, 50810883}, {12827, 50811651},
1458
  {12828, 50812419}, {12829, 67590403}, {12830, 67591427}, {12831, 2},
1459
  {12832, 50815235}, {12833, 50816003}, {12834, 50816771}, {12835, 50817539},
1460
  {12836, 50818307}, {12837, 50819075}, {12838, 50819843}, {12839, 50820611},
1461
  {12840, 50821379}, {12841, 50822147}, {12842, 50822915}, {12843, 50823683},
1462
  {12844, 50824451}, {12845, 50825219}, {12846, 50825987}, {12847, 50826755},
1463
  {12848, 50827523}, {12849, 50828291}, {12850, 50829059}, {12851, 50829827},
1464
  {12852, 50830595}, {12853, 50831363}, {12854, 50832131}, {12855, 50832899},
1465
  {12856, 50833667}, {12857, 50834435}, {12858, 50835203}, {12859, 50835971},
1466
  {12860, 50836739}, {12861, 50837507}, {12862, 50838275}, {12863, 50839043},
1467
  {12864, 50839811}, {12865, 50840579}, {12866, 50841347}, {12867, 50842115},
1468
  {12868, 17288451}, {12869, 17288707}, {12870, 17169155}, {12871, 17288963},
1469
  {12872, 1}, {12880, 50843651}, {12881, 33855747}, {12882, 34067203},
1470
  {12883, 33562371}, {12884, 34067715}, {12885, 34068227}, {12886, 34068739},
1471
  {12887, 34069251}, {12888, 34069763}, {12889, 34070275}, {12890, 34070787},
1472
  {12891, 33837571}, {12892, 33836803}, {12893, 34071299}, {12894, 34071811},
1473
  {12895, 34072323}, {12896, 17210115}, {12897, 17210883}, {12898, 17211651},
1474
  {12899, 17212163}, {12900, 17214211}, {12901, 17214467}, {12902, 17215235},
1475
  {12903, 17215747}, {12904, 17216003}, {12905, 17216515}, {12906, 17216771},
1476
  {12907, 17217027}, {12908, 17217283}, {12909, 17217539}, {12910, 17247491},
1477
  {12911, 17248259}, {12912, 17249027}, {12913, 17249795}, {12914, 17250563},
1478
  {12915, 17251331}, {12916, 17252099}, {12917, 17252867}, {12918, 17253635},
1479
  {12919, 17254403}, {12920, 17255171}, {12921, 17255939}, {12922, 17256707},
1480
  {12923, 17257475}, {12924, 34072835}, {12925, 34073347}, {12926, 17296643},
1481
  {12927, 1}, {12928, 17152259}, {12929, 17153795}, {12930, 17233923},
1482
  {12931, 17234179}, {12932, 17264131}, {12933, 17264899}, {12934, 17265667},
1483
  {12935, 17155075}, {12936, 17267203}, {12937, 17158147}, {12938, 17170947},
1484
  {12939, 17174019}, {12940, 17173763}, {12941, 17171203}, {12942, 17194755},
1485
  {12943, 17160195}, {12944, 17170435}, {12945, 17274115}, {12946, 17274883},
1486
  {12947, 17275651}, {12948, 17276419}, {12949, 17277187}, {12950, 17277955},
1487
  {12951, 17278723}, {12952, 17279491}, {12953, 17296899}, {12954, 17297155},
1488
  {12955, 17161731}, {12956, 17297411}, {12957, 17297667}, {12958, 17297923},
1489
  {12959, 17298179}, {12960, 17298435}, {12961, 17286403}, {12962, 17298691},
1490
  {12963, 17298947}, {12964, 17234435}, {12965, 17234691}, {12966, 17234947},
1491
  {12967, 17299203}, {12968, 17299459}, {12969, 17299715}, {12970, 17299971},
1492
  {12971, 17281795}, {12972, 17282563}, {12973, 17283331}, {12974, 17284099},
1493
  {12975, 17284867}, {12976, 17300227}, {12977, 34077699}, {12978, 34078211},
1494
  {12979, 34078723}, {12980, 34079235}, {12981, 34079747}, {12982, 33564931},
1495
  {12983, 34067971}, {12984, 34072067}, {12985, 34080259}, {12986, 34080771},
1496
  {12987, 34081283}, {12988, 34081795}, {12989, 34082307}, {12990, 34082819},
1497
  {12991, 34083331}, {12992, 34083843}, {12993, 34084355}, {12994, 34084867},
1498
  {12995, 34085379}, {12996, 34085891}, {12997, 34086403}, {12998, 34086915},
1499
  {12999, 34087427}, {13000, 34087939}, {13001, 50865667}, {13002, 50866435},
1500
  {13003, 50867203}, {13004, 34090755}, {13005, 50868483}, {13006, 34092035},
1501
  {13007, 50869763}, {13008, 17316099}, {13009, 17316355}, {13010, 17316611},
1502
  {13011, 17316867}, {13012, 17317123}, {13013, 17317379}, {13014, 17317635},
1503
  {13015, 17317891}, {13016, 17318147}, {13017, 17209603}, {13018, 17318403},
1504
  {13019, 17318659}, {13020, 17318915}, {13021, 17319171}, {13022, 17319427},
1505
  {13023, 17319683}, {13024, 17319939}, {13025, 17320195}, {13026, 17320451},
1506
  {13027, 17209859}, {13028, 17320707}, {13029, 17320963}, {13030, 17321219},
1507
  {13031, 17321475}, {13032, 17321731}, {13033, 17321987}, {13034, 17322243},
1508
  {13035, 17322499}, {13036, 17322755}, {13037, 17323011}, {13038, 17323267},
1509
  {13039, 17323523}, {13040, 17323779}, {13041, 17324035}, {13042, 17324291},
1510
  {13043, 17324547}, {13044, 17324803}, {13045, 17325059}, {13046, 17325315},
1511
  {13047, 17325571}, {13048, 17325827}, {13049, 17326083}, {13050, 17326339},
1512
  {13051, 17326595}, {13052, 17326851}, {13053, 17327107}, {13054, 17327363},
1513
  {13055, 34104835}, {13056, 67659779}, {13057, 67660803}, {13058, 67661827},
1514
  {13059, 50885635}, {13060, 67663619}, {13061, 50887427}, {13062, 50888195},
1515
  {13063, 84443395}, {13064, 67667459}, {13065, 50891267}, {13066, 50892035},
1516
  {13067, 50892803}, {13068, 67670787}, {13069, 67671811}, {13070, 50895619},
1517
  {13071, 50896387}, {13072, 34119939}, {13073, 50897667}, {13074, 67675651},
1518
  {13075, 67676675}, {13076, 34123267}, {13077, 84455427}, {13078, 101233923},
1519
  {13079, 84458243}, {13080, 50901507}, {13081, 84459523}, {13082, 84460803},
1520
  {13083, 67684867}, {13084, 50908675}, {13085, 50909443}, {13086, 50910211},
1521
  {13087, 67688195}, {13088, 84466435}, {13089, 67690499}, {13090, 50914307},
1522
  {13091, 50915075}, {13092, 50915843}, {13093, 34139395}, {13094, 34139907},
1523
  {13095, 34128643}, {13096, 34140419}, {13097, 50918147}, {13098, 50918915},
1524
  {13099, 84474115}, {13100, 50920963}, {13101, 67698947}, {13102, 84477187},
1525
  {13103, 50924035}, {13104, 34147587}, {13105, 34148099}, {13106, 84480259},
1526
  {13107, 67704323}, {13108, 84482563}, {13109, 50929411}, {13110, 84484611},
1527
  {13111, 34154243}, {13112, 50931971}, {13113, 50932739}, {13114, 50933507},
1528
  {13115, 50934275}, {13116, 50935043}, {13117, 67713027}, {13118, 50936835},
1529
  {13119, 34160387}, {13120, 50938115}, {13121, 50938883}, {13122, 50939651},
1530
  {13123, 67717635}, {13124, 50941443}, {13125, 50942211}, {13126, 50942979},
1531
  {13127, 84498179}, {13128, 67722243}, {13129, 34168835}, {13130, 84500995},
1532
  {13131, 34170627}, {13132, 67725571}, {13133, 67680003}, {13134, 50949379},
1533
  {13135, 50950147}, {13136, 50950915}, {13137, 67728899}, {13138, 34175491},
1534
  {13139, 50953219}, {13140, 67731203}, {13141, 34177795}, {13142, 84509955},
1535
  {13143, 50904323}, {13144, 34179587}, {13145, 34180099}, {13146, 34180611},
1536
  {13147, 34181123}, {13148, 34181635}, {13149, 34182147}, {13150, 34182659},
1537
  {13151, 34183171}, {13152, 34183683}, {13153, 34184195}, {13154, 50961923},
1538
  {13155, 50962691}, {13156, 50963459}, {13157, 50964227}, {13158, 50964995},
1539
  {13159, 50965763}, {13160, 50966531}, {13161, 50967299}, {13162, 50968067},
1540
  {13163, 50968835}, {13164, 50969603}, {13165, 50970371}, {13166, 50971139},
1541
  {13167, 50971907}, {13168, 50972675}, {13169, 50973443}, {13170, 34196995},
1542
  {13171, 34197507}, {13172, 50975235}, {13173, 34198787}, {13174, 34199299},
1543
  {13175, 34199811}, {13176, 50977539}, {13177, 50978307}, {13178, 34201859},
1544
  {13179, 34202371}, {13180, 34202883}, {13181, 34203395}, {13182, 34203907},
1545
  {13183, 67758851}, {13184, 34196483}, {13185, 34205443}, {13186, 34205955},
1546
  {13187, 34206467}, {13188, 34206979}, {13189, 34207491}, {13190, 34208003},
1547
  {13191, 34208515}, {13192, 50986243}, {13193, 67764227}, {13194, 34210819},
1548
  {13195, 34211331}, {13196, 34211843}, {13197, 34212355}, {13198, 34212867},
1549
  {13199, 34213379}, {13200, 34213891}, {13201, 50991619}, {13202, 50992387},
1550
  {13203, 50990851}, {13204, 50993155}, {13205, 34216707}, {13206, 34217219},
1551
  {13207, 34217731}, {13208, 33556995}, {13209, 34218243}, {13210, 34218755},
1552
  {13211, 34219267}, {13212, 34219779}, {13213, 34220291}, {13214, 34220803},
1553
  {13215, 50998531}, {13216, 50999299}, {13217, 34200579}, {13218, 51000067},
1554
  {13219, 51000835}, {13220, 51001603}, {13221, 34201347}, {13222, 51002371},
1555
  {13223, 51003139}, {13224, 67781123}, {13225, 34196483}, {13226, 51004931},
1556
  {13227, 51005699}, {13228, 51006467}, {13229, 51007235}, {13230, 84562435},
1557
  {13231, 101340931}, {13232, 34233603}, {13233, 34234115}, {13234, 34234627},
1558
  {13235, 34235139}, {13236, 34235651}, {13237, 34236163}, {13238, 34236675},
1559
  {13239, 34237187}, {13240, 34237699}, {13241, 34237187}, {13242, 34238211},
1560
  {13243, 34238723}, {13244, 34239235}, {13245, 34239747}, {13246, 34240259},
1561
  {13247, 34239747}, {13248, 34240771}, {13249, 34241283}, {13250, 2},
1562
  {13251, 34241795}, {13252, 33827331}, {13253, 33554947}, {13254, 67796739},
1563
  {13255, 2}, {13256, 34243331}, {13257, 34243843}, {13258, 34244355},
1564
  {13259, 34196227}, {13260, 34244867}, {13261, 34245379}, {13262, 34220803},
1565
  {13263, 34245891}, {13264, 33557251}, {13265, 34246403}, {13266, 51024131},
1566
  {13267, 34247683}, {13268, 34208003}, {13269, 51025411}, {13270, 51026179},
1567
  {13271, 34249731}, {13272, 2}, {13273, 51027459}, {13274, 34251011},
1568
  {13275, 34231811}, {13276, 34251523}, {13277, 34252035}, {13278, 51029763},
1569
  {13279, 51030531}, {13280, 34254083}, {13281, 34254595}, {13282, 34255107},
1570
  {13283, 34255619}, {13284, 34256131}, {13285, 34256643}, {13286, 34257155},
1571
  {13287, 34257667}, {13288, 34258179}, {13289, 51035907}, {13290, 51036675},
1572
  {13291, 51037443}, {13292, 51038211}, {13293, 51038979}, {13294, 51039747},
1573
  {13295, 51040515}, {13296, 51041283}, {13297, 51042051}, {13298, 51042819},
1574
  {13299, 51043587}, {13300, 51044355}, {13301, 51045123}, {13302, 51045891},
1575
  {13303, 51046659}, {13304, 51047427}, {13305, 51048195}, {13306, 51048963},
1576
  {13307, 51049731}, {13308, 51050499}, {13309, 51051267}, {13310, 51052035},
1577
  {13311, 51052803}, {13312, 1}, {42125, 2}, {42128, 1},
1578
  {42183, 2}, {42192, 1}, {42540, 2}, {42560, 17499139},
1579
  {42561, 1}, {42562, 17499395}, {42563, 1}, {42564, 17499651},
1580
  {42565, 1}, {42566, 17499907}, {42567, 1}, {42568, 17500163},
1581
  {42569, 1}, {42570, 16946435}, {42571, 1}, {42572, 17500419},
1582
  {42573, 1}, {42574, 17500675}, {42575, 1}, {42576, 17500931},
1583
  {42577, 1}, {42578, 17501187}, {42579, 1}, {42580, 17501443},
1584
  {42581, 1}, {42582, 17501699}, {42583, 1}, {42584, 17501955},
1585
  {42585, 1}, {42586, 17502211}, {42587, 1}, {42588, 17502467},
1586
  {42589, 1}, {42590, 17502723}, {42591, 1}, {42592, 17502979},
1587
  {42593, 1}, {42594, 17503235}, {42595, 1}, {42596, 17503491},
1588
  {42597, 1}, {42598, 17503747}, {42599, 1}, {42600, 17504003},
1589
  {42601, 1}, {42602, 17504259}, {42603, 1}, {42604, 17504515},
1590
  {42605, 1}, {42624, 17504771}, {42625, 1}, {42626, 17505027},
1591
  {42627, 1}, {42628, 17505283}, {42629, 1}, {42630, 17505539},
1592
  {42631, 1}, {42632, 17505795}, {42633, 1}, {42634, 17506051},
1593
  {42635, 1}, {42636, 17506307}, {42637, 1}, {42638, 17506563},
1594
  {42639, 1}, {42640, 17506819}, {42641, 1}, {42642, 17507075},
1595
  {42643, 1}, {42644, 17507331}, {42645, 1}, {42646, 17507587},
1596
  {42647, 1}, {42648, 17507843}, {42649, 1}, {42650, 17508099},
1597
  {42651, 1}, {42652, 16873219}, {42653, 16873731}, {42654, 1},
1598
  {42744, 2}, {42752, 1}, {42786, 17508355}, {42787, 1},
1599
  {42788, 17508611}, {42789, 1}, {42790, 17508867}, {42791, 1},
1600
  {42792, 17509123}, {42793, 1}, {42794, 17509379}, {42795, 1},
1601
  {42796, 17509635}, {42797, 1}, {42798, 17509891}, {42799, 1},
1602
  {42802, 17510147}, {42803, 1}, {42804, 17510403}, {42805, 1},
1603
  {42806, 17510659}, {42807, 1}, {42808, 17510915}, {42809, 1},
1604
  {42810, 17511171}, {42811, 1}, {42812, 17511427}, {42813, 1},
1605
  {42814, 17511683}, {42815, 1}, {42816, 17511939}, {42817, 1},
1606
  {42818, 17512195}, {42819, 1}, {42820, 17512451}, {42821, 1},
1607
  {42822, 17512707}, {42823, 1}, {42824, 17512963}, {42825, 1},
1608
  {42826, 17513219}, {42827, 1}, {42828, 17513475}, {42829, 1},
1609
  {42830, 17513731}, {42831, 1}, {42832, 17513987}, {42833, 1},
1610
  {42834, 17514243}, {42835, 1}, {42836, 17514499}, {42837, 1},
1611
  {42838, 17514755}, {42839, 1}, {42840, 17515011}, {42841, 1},
1612
  {42842, 17515267}, {42843, 1}, {42844, 17515523}, {42845, 1},
1613
  {42846, 17515779}, {42847, 1}, {42848, 17516035}, {42849, 1},
1614
  {42850, 17516291}, {42851, 1}, {42852, 17516547}, {42853, 1},
1615
  {42854, 17516803}, {42855, 1}, {42856, 17517059}, {42857, 1},
1616
  {42858, 17517315}, {42859, 1}, {42860, 17517571}, {42861, 1},
1617
  {42862, 17517827}, {42863, 1}, {42864, 17517827}, {42865, 1},
1618
  {42873, 17518083}, {42874, 1}, {42875, 17518339}, {42876, 1},
1619
  {42877, 17518595}, {42878, 17518851}, {42879, 1}, {42880, 17519107},
1620
  {42881, 1}, {42882, 17519363}, {42883, 1}, {42884, 17519619},
1621
  {42885, 1}, {42886, 17519875}, {42887, 1}, {42891, 17520131},
1622
  {42892, 1}, {42893, 16961539}, {42894, 1}, {42896, 17520387},
1623
  {42897, 1}, {42898, 17520643}, {42899, 1}, {42902, 17520899},
1624
  {42903, 1}, {42904, 17521155}, {42905, 1}, {42906, 17521411},
1625
  {42907, 1}, {42908, 17521667}, {42909, 1}, {42910, 17521923},
1626
  {42911, 1}, {42912, 17522179}, {42913, 1}, {42914, 17522435},
1627
  {42915, 1}, {42916, 17522691}, {42917, 1}, {42918, 17522947},
1628
  {42919, 1}, {42920, 17523203}, {42921, 1}, {42922, 16841475},
1629
  {42923, 16959235}, {42924, 16961283}, {42925, 17523459}, {42926, 16961795},
1630
  {42927, 1}, {42928, 17523715}, {42929, 17523971}, {42930, 16962307},
1631
  {42931, 17524227}, {42932, 17524483}, {42933, 1}, {42934, 17524739},
1632
  {42935, 1}, {42936, 17524995}, {42937, 1}, {42938, 17525251},
1633
  {42939, 1}, {42940, 17525507}, {42941, 1}, {42942, 17525763},
1634
  {42943, 1}, {42944, 17526019}, {42945, 1}, {42946, 17526275},
1635
  {42947, 1}, {42948, 17526531}, {42949, 16964611}, {42950, 17526787},
1636
  {42951, 17527043}, {42952, 1}, {42953, 17527299}, {42954, 1},
1637
  {42955, 17527555}, {42956, 17527811}, {42957, 1}, {42958, 2},
1638
  {42960, 17528067}, {42961, 1}, {42962, 2}, {42963, 1},
1639
  {42964, 2}, {42965, 1}, {42966, 17528323}, {42967, 1},
1640
  {42968, 17528579}, {42969, 1}, {42970, 17528835}, {42971, 1},
1641
  {42972, 17529091}, {42973, 2}, {42994, 16777731}, {42995, 16778499},
1642
  {42996, 16781315}, {42997, 17529347}, {42998, 1}, {43000, 16802051},
1643
  {43001, 16808195}, {43002, 1}, {43053, 2}, {43056, 1},
1644
  {43066, 2}, {43072, 1}, {43128, 2}, {43136, 1},
1645
  {43206, 2}, {43214, 1}, {43226, 2}, {43232, 1},
1646
  {43348, 2}, {43359, 1}, {43389, 2}, {43392, 1},
1647
  {43470, 2}, {43471, 1}, {43482, 2}, {43486, 1},
1648
  {43519, 2}, {43520, 1}, {43575, 2}, {43584, 1},
1649
  {43598, 2}, {43600, 1}, {43610, 2}, {43612, 1},
1650
  {43715, 2}, {43739, 1}, {43767, 2}, {43777, 1},
1651
  {43783, 2}, {43785, 1}, {43791, 2}, {43793, 1},
1652
  {43799, 2}, {43808, 1}, {43815, 2}, {43816, 1},
1653
  {43823, 2}, {43824, 1}, {43868, 17508867}, {43869, 17529603},
1654
  {43870, 17135363}, {43871, 17529859}, {43872, 1}, {43881, 17530115},
1655
  {43882, 1}, {43884, 2}, {43888, 17530371}, {43889, 17530627},
1656
  {43890, 17530883}, {43891, 17531139}, {43892, 17531395}, {43893, 17531651},
1657
  {43894, 17531907}, {43895, 17532163}, {43896, 17532419}, {43897, 17532675},
1658
  {43898, 17532931}, {43899, 17533187}, {43900, 17533443}, {43901, 17533699},
1659
  {43902, 17533955}, {43903, 17534211}, {43904, 17534467}, {43905, 17534723},
1660
  {43906, 17534979}, {43907, 17535235}, {43908, 17535491}, {43909, 17535747},
1661
  {43910, 17536003}, {43911, 17536259}, {43912, 17536515}, {43913, 17536771},
1662
  {43914, 17537027}, {43915, 17537283}, {43916, 17537539}, {43917, 17537795},
1663
  {43918, 17538051}, {43919, 17538307}, {43920, 17538563}, {43921, 17538819},
1664
  {43922, 17539075}, {43923, 17539331}, {43924, 17539587}, {43925, 17539843},
1665
  {43926, 17540099}, {43927, 17540355}, {43928, 17540611}, {43929, 17540867},
1666
  {43930, 17541123}, {43931, 17541379}, {43932, 17541635}, {43933, 17541891},
1667
  {43934, 17542147}, {43935, 17542403}, {43936, 17542659}, {43937, 17542915},
1668
  {43938, 17543171}, {43939, 17543427}, {43940, 17543683}, {43941, 17543939},
1669
  {43942, 17544195}, {43943, 17544451}, {43944, 17544707}, {43945, 17544963},
1670
  {43946, 17545219}, {43947, 17545475}, {43948, 17545731}, {43949, 17545987},
1671
  {43950, 17546243}, {43951, 17546499}, {43952, 17546755}, {43953, 17547011},
1672
  {43954, 17547267}, {43955, 17547523}, {43956, 17547779}, {43957, 17548035},
1673
  {43958, 17548291}, {43959, 17548547}, {43960, 17548803}, {43961, 17549059},
1674
  {43962, 17549315}, {43963, 17549571}, {43964, 17549827}, {43965, 17550083},
1675
  {43966, 17550339}, {43967, 17550595}, {43968, 1}, {44014, 2},
1676
  {44016, 1}, {44026, 2}, {44032, 1}, {55204, 2},
1677
  {55216, 1}, {55239, 2}, {55243, 1}, {55292, 2},
1678
  {63744, 17550851}, {63745, 17551107}, {63746, 17192707}, {63747, 17551363},
1679
  {63748, 17551619}, {63749, 17551875}, {63750, 17552131}, {63751, 17206531},
1680
  {63753, 17552387}, {63754, 17194755}, {63755, 17552643}, {63756, 17552899},
1681
  {63757, 17553155}, {63758, 17553411}, {63759, 17553667}, {63760, 17553923},
1682
  {63761, 17554179}, {63762, 17554435}, {63763, 17554691}, {63764, 17554947},
1683
  {63765, 17555203}, {63766, 17555459}, {63767, 17555715}, {63768, 17555971},
1684
  {63769, 17556227}, {63770, 17556483}, {63771, 17556739}, {63772, 17556995},
1685
  {63773, 17557251}, {63774, 17557507}, {63775, 17557763}, {63776, 17558019},
1686
  {63777, 17558275}, {63778, 17558531}, {63779, 17558787}, {63780, 17559043},
1687
  {63781, 17559299}, {63782, 17559555}, {63783, 17559811}, {63784, 17560067},
1688
  {63785, 17560323}, {63786, 17560579}, {63787, 17560835}, {63788, 17561091},
1689
  {63789, 17561347}, {63790, 17561603}, {63791, 17561859}, {63792, 17562115},
1690
  {63793, 17562371}, {63794, 17562627}, {63795, 17562883}, {63796, 17184003},
1691
  {63797, 17563139}, {63798, 17563395}, {63799, 17563651}, {63800, 17563907},
1692
  {63801, 17564163}, {63802, 17564419}, {63803, 17564675}, {63804, 17564931},
1693
  {63805, 17565187}, {63806, 17565443}, {63807, 17565699}, {63808, 17202691},
1694
  {63809, 17565955}, {63810, 17566211}, {63811, 17566467}, {63812, 17566723},
1695
  {63813, 17566979}, {63814, 17567235}, {63815, 17567491}, {63816, 17567747},
1696
  {63817, 17568003}, {63818, 17568259}, {63819, 17568515}, {63820, 17568771},
1697
  {63821, 17569027}, {63822, 17569283}, {63823, 17569539}, {63824, 17569795},
1698
  {63825, 17570051}, {63826, 17570307}, {63827, 17570563}, {63828, 17570819},
1699
  {63829, 17571075}, {63830, 17571331}, {63831, 17571587}, {63832, 17571843},
1700
  {63833, 17572099}, {63834, 17572355}, {63835, 17572611}, {63836, 17554947},
1701
  {63837, 17572867}, {63838, 17573123}, {63839, 17573379}, {63840, 17573635},
1702
  {63841, 17573891}, {63842, 17574147}, {63843, 17574403}, {63844, 17574659},
1703
  {63845, 17574915}, {63846, 17575171}, {63847, 17575427}, {63848, 17575683},
1704
  {63849, 17575939}, {63850, 17576195}, {63851, 17576451}, {63852, 17576707},
1705
  {63853, 17576963}, {63854, 17577219}, {63855, 17577475}, {63856, 17577731},
1706
  {63857, 17193219}, {63858, 17577987}, {63859, 17578243}, {63860, 17578499},
1707
  {63861, 17578755}, {63862, 17579011}, {63863, 17579267}, {63864, 17579523},
1708
  {63865, 17579779}, {63866, 17580035}, {63867, 17580291}, {63868, 17580547},
1709
  {63869, 17580803}, {63870, 17581059}, {63871, 17581315}, {63872, 17581571},
1710
  {63873, 17161731}, {63874, 17581827}, {63875, 17582083}, {63876, 17582339},
1711
  {63877, 17582595}, {63878, 17582851}, {63879, 17583107}, {63880, 17583363},
1712
  {63881, 17583619}, {63882, 17156867}, {63883, 17583875}, {63884, 17584131},
1713
  {63885, 17584387}, {63886, 17584643}, {63887, 17584899}, {63888, 17585155},
1714
  {63889, 17585411}, {63890, 17585667}, {63891, 17585923}, {63892, 17586179},
1715
  {63893, 17586435}, {63894, 17586691}, {63895, 17586947}, {63896, 17587203},
1716
  {63897, 17587459}, {63898, 17587715}, {63899, 17587971}, {63900, 17588227},
1717
  {63901, 17588483}, {63902, 17588739}, {63903, 17588995}, {63904, 17589251},
1718
  {63905, 17577475}, {63906, 17589507}, {63907, 17589763}, {63908, 17590019},
1719
  {63909, 17590275}, {63910, 17590531}, {63911, 17590787}, {63912, 17327619},
1720
  {63913, 17591043}, {63914, 17573379}, {63915, 17591299}, {63916, 17591555},
1721
  {63917, 17591811}, {63918, 17592067}, {63919, 17592323}, {63920, 17592579},
1722
  {63921, 17592835}, {63922, 17593091}, {63923, 17593347}, {63924, 17593603},
1723
  {63925, 17593859}, {63926, 17594115}, {63927, 17594371}, {63928, 17594627},
1724
  {63929, 17594883}, {63930, 17595139}, {63931, 17595395}, {63932, 17595651},
1725
  {63933, 17595907}, {63934, 17596163}, {63935, 17554947}, {63936, 17596419},
1726
  {63937, 17596675}, {63938, 17596931}, {63939, 17597187}, {63940, 17206275},
1727
  {63941, 17597443}, {63942, 17597699}, {63943, 17597955}, {63944, 17598211},
1728
  {63945, 17598467}, {63946, 17598723}, {63947, 17598979}, {63948, 17599235},
1729
  {63949, 17599491}, {63950, 17599747}, {63951, 17600003}, {63952, 17600259},
1730
  {63953, 17264899}, {63954, 17600515}, {63955, 17600771}, {63956, 17601027},
1731
  {63957, 17601283}, {63958, 17601539}, {63959, 17601795}, {63960, 17602051},
1732
  {63961, 17602307}, {63962, 17602563}, {63963, 17573891}, {63964, 17602819},
1733
  {63965, 17603075}, {63966, 17603331}, {63967, 17603587}, {63968, 17603843},
1734
  {63969, 17604099}, {63970, 17604355}, {63971, 17604611}, {63972, 17604867},
1735
  {63973, 17605123}, {63974, 17605379}, {63975, 17605635}, {63976, 17605891},
1736
  {63977, 17194499}, {63978, 17606147}, {63979, 17606403}, {63980, 17606659},
1737
  {63981, 17606915}, {63982, 17607171}, {63983, 17607427}, {63984, 17607683},
1738
  {63985, 17607939}, {63986, 17608195}, {63987, 17608451}, {63988, 17608707},
1739
  {63989, 17608963}, {63990, 17609219}, {63991, 17181955}, {63992, 17609475},
1740
  {63993, 17609731}, {63994, 17609987}, {63995, 17610243}, {63996, 17610499},
1741
  {63997, 17610755}, {63998, 17611011}, {63999, 17611267}, {64000, 17611523},
1742
  {64001, 17611779}, {64002, 17612035}, {64003, 17612291}, {64004, 17612547},
1743
  {64005, 17612803}, {64006, 17613059}, {64007, 17613315}, {64008, 17188867},
1744
  {64009, 17613571}, {64010, 17189635}, {64011, 17613827}, {64012, 17614083},
1745
  {64013, 17614339}, {64014, 1}, {64016, 17614595}, {64017, 1},
1746
  {64018, 17614851}, {64019, 1}, {64021, 17615107}, {64022, 17615363},
1747
  {64023, 17615619}, {64024, 17615875}, {64025, 17616131}, {64026, 17616387},
1748
  {64027, 17616643}, {64028, 17616899}, {64029, 17617155}, {64030, 17183747},
1749
  {64031, 1}, {64032, 17617411}, {64033, 1}, {64034, 17617667},
1750
  {64035, 1}, {64037, 17617923}, {64038, 17618179}, {64039, 1},
1751
  {64042, 17618435}, {64043, 17618691}, {64044, 17618947}, {64045, 17619203},
1752
  {64046, 17619459}, {64047, 17619715}, {64048, 17619971}, {64049, 17620227},
1753
  {64050, 17620483}, {64051, 17620739}, {64052, 17620995}, {64053, 17621251},
1754
  {64054, 17621507}, {64055, 17621763}, {64056, 17622019}, {64057, 17622275},
1755
  {64058, 17622531}, {64059, 17622787}, {64060, 17163523}, {64061, 17623043},
1756
  {64062, 17623299}, {64063, 17623555}, {64064, 17623811}, {64065, 17624067},
1757
  {64066, 17624323}, {64067, 17624579}, {64068, 17624835}, {64069, 17625091},
1758
  {64070, 17625347}, {64071, 17625603}, {64072, 17625859}, {64073, 17626115},
1759
  {64074, 17626371}, {64075, 17626627}, {64076, 17275651}, {64077, 17626883},
1760
  {64078, 17627139}, {64079, 17627395}, {64080, 17627651}, {64081, 17278723},
1761
  {64082, 17627907}, {64083, 17628163}, {64084, 17628419}, {64085, 17628675},
1762
  {64086, 17628931}, {64087, 17586691}, {64088, 17629187}, {64089, 17629443},
1763
  {64090, 17629699}, {64091, 17629955}, {64092, 17630211}, {64093, 17630467},
1764
  {64095, 17630723}, {64096, 17630979}, {64097, 17631235}, {64098, 17631491},
1765
  {64099, 17631747}, {64100, 17632003}, {64101, 17632259}, {64102, 17632515},
1766
  {64103, 17617923}, {64104, 17632771}, {64105, 17633027}, {64106, 17633283},
1767
  {64107, 17633539}, {64108, 17633795}, {64109, 17634051}, {64110, 2},
1768
  {64112, 17634307}, {64113, 17634563}, {64114, 17634819}, {64115, 17635075},
1769
  {64116, 17635331}, {64117, 17635587}, {64118, 17635843}, {64119, 17636099},
1770
  {64120, 17621507}, {64121, 17636355}, {64122, 17636611}, {64123, 17636867},
1771
  {64124, 17614595}, {64125, 17637123}, {64126, 17637379}, {64127, 17637635},
1772
  {64128, 17637891}, {64129, 17638147}, {64130, 17638403}, {64131, 17638659},
1773
  {64132, 17638915}, {64133, 17639171}, {64134, 17639427}, {64135, 17639683},
1774
  {64136, 17639939}, {64137, 17623555}, {64138, 17640195}, {64139, 17623811},
1775
  {64140, 17640451}, {64141, 17640707}, {64142, 17640963}, {64143, 17641219},
1776
  {64144, 17641475}, {64145, 17614851}, {64146, 17560323}, {64147, 17641731},
1777
  {64148, 17641987}, {64149, 17171971}, {64150, 17577731}, {64151, 17598723},
1778
  {64152, 17642243}, {64153, 17642499}, {64154, 17625603}, {64155, 17642755},
1779
  {64156, 17625859}, {64157, 17643011}, {64158, 17643267}, {64159, 17643523},
1780
  {64160, 17615363}, {64161, 17643779}, {64162, 17644035}, {64163, 17644291},
1781
  {64164, 17644547}, {64165, 17644803}, {64166, 17615619}, {64167, 17645059},
1782
  {64168, 17645315}, {64169, 17645571}, {64170, 17645827}, {64171, 17646083},
1783
  {64172, 17646339}, {64173, 17628931}, {64174, 17646595}, {64175, 17646851},
1784
  {64176, 17586691}, {64177, 17647107}, {64178, 17629955}, {64179, 17647363},
1785
  {64180, 17647619}, {64181, 17647875}, {64182, 17648131}, {64183, 17648387},
1786
  {64184, 17631235}, {64185, 17648643}, {64186, 17617667}, {64187, 17648899},
1787
  {64188, 17631491}, {64189, 17572867}, {64190, 17649155}, {64191, 17631747},
1788
  {64192, 17649411}, {64193, 17632259}, {64194, 17649667}, {64195, 17649923},
1789
  {64196, 17650179}, {64197, 17650435}, {64198, 17650691}, {64199, 17632771},
1790
  {64200, 17616899}, {64201, 17650947}, {64202, 17633027}, {64203, 17651203},
1791
  {64204, 17633283}, {64205, 17651459}, {64206, 17206531}, {64207, 17651715},
1792
  {64208, 17651971}, {64209, 17652227}, {64210, 17652483}, {64211, 17652739},
1793
  {64212, 17652995}, {64213, 17653251}, {64214, 17653507}, {64215, 17653763},
1794
  {64216, 17654019}, {64217, 17654275}, {64218, 2}, {64256, 34431747},
1795
  {64257, 34432259}, {64258, 34432771}, {64259, 51209219}, {64260, 51210499},
1796
  {64261, 33559043}, {64263, 2}, {64275, 34434051}, {64276, 34434563},
1797
  {64277, 34435075}, {64278, 34435587}, {64279, 34436099}, {64280, 2},
1798
  {64285, 34436611}, {64286, 1}, {64287, 34437123}, {64288, 17660419},
1799
  {64289, 17054467}, {64290, 17055235}, {64291, 17660675}, {64292, 17660931},
1800
  {64293, 17661187}, {64294, 17661443}, {64295, 17661699}, {64296, 17661955},
1801
  {64297, 17047043}, {64298, 34439427}, {64299, 34439939}, {64300, 51217667},
1802
  {64301, 51218435}, {64302, 34441987}, {64303, 34442499}, {64304, 34443011},
1803
  {64305, 34443523}, {64306, 34444035}, {64307, 34444547}, {64308, 34445059},
1804
  {64309, 34445571}, {64310, 34446083}, {64311, 2}, {64312, 34446595},
1805
  {64313, 34447107}, {64314, 34447619}, {64315, 34448131}, {64316, 34448643},
1806
  {64317, 2}, {64318, 34449155}, {64319, 2}, {64320, 34449667},
1807
  {64321, 34450179}, {64322, 2}, {64323, 34450691}, {64324, 34451203},
1808
  {64325, 2}, {64326, 34451715}, {64327, 34452227}, {64328, 34452739},
1809
  {64329, 34440451}, {64330, 34453251}, {64331, 34453763}, {64332, 34454275},
1810
  {64333, 34454787}, {64334, 34455299}, {64335, 34455811}, {64336, 17679107},
1811
  {64338, 17679363}, {64342, 17679619}, {64346, 17679875}, {64350, 17680131},
1812
  {64354, 17680387}, {64358, 17680643}, {64362, 17680899}, {64366, 17681155},
1813
  {64370, 17681411}, {64374, 17681667}, {64378, 17681923}, {64382, 17682179},
1814
  {64386, 17682435}, {64388, 17682691}, {64390, 17682947}, {64392, 17683203},
1815
  {64394, 17683459}, {64396, 17683715}, {64398, 17683971}, {64402, 17684227},
1816
  {64406, 17684483}, {64410, 17684739}, {64414, 17684995}, {64416, 17685251},
1817
  {64420, 17685507}, {64422, 17685763}, {64426, 17686019}, {64430, 17686275},
1818
  {64432, 17686531}, {64434, 1}, {64451, 2}, {64467, 17686787},
1819
  {64471, 16911619}, {64473, 17687043}, {64475, 17687299}, {64477, 33688835},
1820
  {64478, 17687555}, {64480, 17687811}, {64482, 17688067}, {64484, 17688323},
1821
  {64488, 17688579}, {64490, 34466051}, {64492, 34466563}, {64494, 34467075},
1822
  {64496, 34467587}, {64498, 34468099}, {64500, 34468611}, {64502, 34469123},
1823
  {64505, 34469635}, {64508, 17692931}, {64512, 34470403}, {64513, 34470915},
1824
  {64514, 34471427}, {64515, 34469635}, {64516, 34471939}, {64517, 34472451},
1825
  {64518, 34472963}, {64519, 34473475}, {64520, 34473987}, {64521, 34474499},
1826
  {64522, 34475011}, {64523, 34475523}, {64524, 34476035}, {64525, 34476547},
1827
  {64526, 34477059}, {64527, 34477571}, {64528, 34478083}, {64529, 34478595},
1828
  {64530, 34479107}, {64531, 34479619}, {64532, 34480131}, {64533, 34480643},
1829
  {64534, 34481155}, {64535, 34480899}, {64536, 34481667}, {64537, 34482179},
1830
  {64538, 34482691}, {64539, 34483203}, {64540, 34483715}, {64541, 34484227},
1831
  {64542, 34484739}, {64543, 34485251}, {64544, 34485763}, {64545, 34486275},
1832
  {64546, 34486787}, {64547, 34487299}, {64548, 34487811}, {64549, 34488323},
1833
  {64550, 34488835}, {64551, 34489347}, {64552, 34489859}, {64553, 34490371},
1834
  {64554, 34490883}, {64555, 34491395}, {64556, 34491907}, {64557, 34492419},
1835
  {64558, 34492931}, {64559, 34493443}, {64560, 34493955}, {64561, 34494467},
1836
  {64562, 34494979}, {64563, 34495491}, {64564, 34496003}, {64565, 34496515},
1837
  {64566, 34497027}, {64567, 34497539}, {64568, 34498051}, {64569, 34498563},
1838
  {64570, 34499075}, {64571, 34499587}, {64572, 34500099}, {64573, 34500611},
1839
  {64574, 34501123}, {64575, 34501635}, {64576, 34502147}, {64577, 34502659},
1840
  {64578, 34503171}, {64579, 34503683}, {64580, 34504195}, {64581, 34504707},
1841
  {64582, 34481411}, {64583, 34481923}, {64584, 34505219}, {64585, 34505731},
1842
  {64586, 34506243}, {64587, 34506755}, {64588, 34507267}, {64589, 34507779},
1843
  {64590, 34508291}, {64591, 34508803}, {64592, 34509315}, {64593, 34509827},
1844
  {64594, 34510339}, {64595, 34510851}, {64596, 34511363}, {64597, 34480387},
1845
  {64598, 34511875}, {64599, 34512387}, {64600, 34504451}, {64601, 34512899},
1846
  {64602, 34511619}, {64603, 34513411}, {64604, 34513923}, {64605, 34514435},
1847
  {64606, 51292163}, {64607, 51292931}, {64608, 51293699}, {64609, 51294467},
1848
  {64610, 51295235}, {64611, 51296003}, {64612, 34519555}, {64613, 34520067},
1849
  {64614, 34471427}, {64615, 34520579}, {64616, 34469635}, {64617, 34471939},
1850
  {64618, 34521091}, {64619, 34521603}, {64620, 34473987}, {64621, 34522115},
1851
  {64622, 34474499}, {64623, 34475011}, {64624, 34522627}, {64625, 34523139},
1852
  {64626, 34477059}, {64627, 34523651}, {64628, 34477571}, {64629, 34478083},
1853
  {64630, 34524163}, {64631, 34524675}, {64632, 34479107}, {64633, 34525187},
1854
  {64634, 34479619}, {64635, 34480131}, {64636, 34494467}, {64637, 34494979},
1855
  {64638, 34496515}, {64639, 34497027}, {64640, 34497539}, {64641, 34499587},
1856
  {64642, 34500099}, {64643, 34500611}, {64644, 34501123}, {64645, 34503171},
1857
  {64646, 34503683}, {64647, 34504195}, {64648, 34525699}, {64649, 34505219},
1858
  {64650, 34526211}, {64651, 34526723}, {64652, 34508291}, {64653, 34527235},
1859
  {64654, 34508803}, {64655, 34509315}, {64656, 34514435}, {64657, 34527747},
1860
  {64658, 34528259}, {64659, 34504451}, {64660, 34506499}, {64661, 34512899},
1861
  {64662, 34511619}, {64663, 34470403}, {64664, 34470915}, {64665, 34528771},
1862
  {64666, 34471427}, {64667, 34529283}, {64668, 34472451}, {64669, 34472963},
1863
  {64670, 34473475}, {64671, 34473987}, {64672, 34529795}, {64673, 34475523},
1864
  {64674, 34476035}, {64675, 34476547}, {64676, 34477059}, {64677, 34530307},
1865
  {64678, 34479107}, {64679, 34480643}, {64680, 34481155}, {64681, 34480899},
1866
  {64682, 34481667}, {64683, 34482179}, {64684, 34483203}, {64685, 34483715},
1867
  {64686, 34484227}, {64687, 34484739}, {64688, 34485251}, {64689, 34485763},
1868
  {64690, 34530819}, {64691, 34486275}, {64692, 34486787}, {64693, 34487299},
1869
  {64694, 34487811}, {64695, 34488323}, {64696, 34488835}, {64697, 34489859},
1870
  {64698, 34490371}, {64699, 34490883}, {64700, 34491395}, {64701, 34491907},
1871
  {64702, 34492419}, {64703, 34492931}, {64704, 34493443}, {64705, 34493955},
1872
  {64706, 34495491}, {64707, 34496003}, {64708, 34498051}, {64709, 34498563},
1873
  {64710, 34499075}, {64711, 34499587}, {64712, 34500099}, {64713, 34501635},
1874
  {64714, 34502147}, {64715, 34502659}, {64716, 34503171}, {64717, 34531331},
1875
  {64718, 34504707}, {64719, 34481411}, {64720, 34481923}, {64721, 34505219},
1876
  {64722, 34506755}, {64723, 34507267}, {64724, 34507779}, {64725, 34508291},
1877
  {64726, 34531843}, {64727, 34509827}, {64728, 34510339}, {64729, 34532355},
1878
  {64730, 34480387}, {64731, 34511875}, {64732, 34512387}, {64733, 34504451},
1879
  {64734, 34509571}, {64735, 34471427}, {64736, 34529283}, {64737, 34473987},
1880
  {64738, 34529795}, {64739, 34477059}, {64740, 34530307}, {64741, 34479107},
1881
  {64742, 34532867}, {64743, 34485251}, {64744, 34533379}, {64745, 34533891},
1882
  {64746, 34534403}, {64747, 34499587}, {64748, 34500099}, {64749, 34503171},
1883
  {64750, 34508291}, {64751, 34531843}, {64752, 34504451}, {64753, 34509571},
1884
  {64754, 51312131}, {64755, 51312899}, {64756, 51313667}, {64757, 34537219},
1885
  {64758, 34537731}, {64759, 34538243}, {64760, 34538755}, {64761, 34539267},
1886
  {64762, 34539779}, {64763, 34540291}, {64764, 34540803}, {64765, 34541315},
1887
  {64766, 34541827}, {64767, 34542339}, {64768, 34512131}, {64769, 34542851},
1888
  {64770, 34543363}, {64771, 34543875}, {64772, 34512643}, {64773, 34544387},
1889
  {64774, 34544899}, {64775, 34545411}, {64776, 34545923}, {64777, 34546435},
1890
  {64778, 34546947}, {64779, 34547459}, {64780, 34533891}, {64781, 34547971},
1891
  {64782, 34548483}, {64783, 34548995}, {64784, 34549507}, {64785, 34537219},
1892
  {64786, 34537731}, {64787, 34538243}, {64788, 34538755}, {64789, 34539267},
1893
  {64790, 34539779}, {64791, 34540291}, {64792, 34540803}, {64793, 34541315},
1894
  {64794, 34541827}, {64795, 34542339}, {64796, 34512131}, {64797, 34542851},
1895
  {64798, 34543363}, {64799, 34543875}, {64800, 34512643}, {64801, 34544387},
1896
  {64802, 34544899}, {64803, 34545411}, {64804, 34545923}, {64805, 34546435},
1897
  {64806, 34546947}, {64807, 34547459}, {64808, 34533891}, {64809, 34547971},
1898
  {64810, 34548483}, {64811, 34548995}, {64812, 34549507}, {64813, 34546435},
1899
  {64814, 34546947}, {64815, 34547459}, {64816, 34533891}, {64817, 34533379},
1900
  {64818, 34534403}, {64819, 34489347}, {64820, 34483715}, {64821, 34484227},
1901
  {64822, 34484739}, {64823, 34546435}, {64824, 34546947}, {64825, 34547459},
1902
  {64826, 34489347}, {64827, 34489859}, {64828, 34550019}, {64830, 1},
1903
  {64848, 51327747}, {64849, 51328515}, {64851, 51329283}, {64852, 51330051},
1904
  {64853, 51330819}, {64854, 51331587}, {64855, 51332355}, {64856, 51258371},
1905
  {64858, 51333123}, {64859, 51333891}, {64860, 51334659}, {64861, 51335427},
1906
  {64862, 51336195}, {64863, 51336963}, {64865, 51337731}, {64866, 51338499},
1907
  {64868, 51339267}, {64870, 51340035}, {64871, 51340803}, {64873, 51341571},
1908
  {64874, 51342339}, {64876, 51343107}, {64878, 51343875}, {64879, 51344643},
1909
  {64881, 51345411}, {64883, 51346179}, {64884, 51346947}, {64885, 51347715},
1910
  {64886, 51348483}, {64888, 51349251}, {64889, 51350019}, {64890, 51350787},
1911
  {64891, 51351555}, {64892, 51352323}, {64894, 51353091}, {64895, 51353859},
1912
  {64896, 51354627}, {64897, 51355395}, {64898, 51356163}, {64899, 51356931},
1913
  {64901, 51357699}, {64903, 51358467}, {64905, 51359235}, {64906, 51258627},
1914
  {64907, 51360003}, {64908, 51360771}, {64909, 51281923}, {64910, 51259139},
1915
  {64911, 51361539}, {64912, 2}, {64914, 51362307}, {64915, 51363075},
1916
  {64916, 51363843}, {64917, 51364611}, {64918, 51365379}, {64919, 51366147},
1917
  {64921, 51366915}, {64922, 51367683}, {64923, 51368451}, {64924, 51369219},
1918
  {64926, 51369987}, {64927, 51370755}, {64928, 51371523}, {64929, 51372291},
1919
  {64930, 51373059}, {64931, 51373827}, {64932, 51374595}, {64933, 51375363},
1920
  {64934, 51376131}, {64935, 51376899}, {64936, 51377667}, {64937, 51378435},
1921
  {64938, 51379203}, {64939, 51379971}, {64940, 51380739}, {64941, 51381507},
1922
  {64942, 51289091}, {64943, 51382275}, {64944, 51383043}, {64945, 51383811},
1923
  {64946, 51384579}, {64947, 51385347}, {64948, 51353091}, {64949, 51354627},
1924
  {64950, 51386115}, {64951, 51386883}, {64952, 51387651}, {64953, 51388419},
1925
  {64954, 51389187}, {64955, 51389955}, {64956, 51389187}, {64957, 51387651},
1926
  {64958, 51390723}, {64959, 51391491}, {64960, 51392259}, {64961, 51393027},
1927
  {64962, 51393795}, {64963, 51389955}, {64964, 51347715}, {64965, 51340035},
1928
  {64966, 51394563}, {64967, 51395331}, {64968, 2}, {64975, 1},
1929
  {64976, 2}, {65008, 51396099}, {65009, 51396867}, {65010, 68174851},
1930
  {65011, 68175875}, {65012, 68176899}, {65013, 68177923}, {65014, 68178947},
1931
  {65015, 68179971}, {65016, 68180995}, {65017, 51404803}, {65018, 303063811},
1932
  {65019, 135296259}, {65020, 68189443}, {65021, 1}, {65024, 0},
1933
  {65040, 17858819}, {65041, 17859075}, {65042, 2}, {65043, 17121027},
1934
  {65044, 16848643}, {65045, 17042947}, {65046, 17043971}, {65047, 17859331},
1935
  {65048, 17859587}, {65049, 2}, {65056, 1}, {65072, 2},
1936
  {65073, 17859843}, {65074, 17860099}, {65075, 17860355}, {65077, 17047811},
1937
  {65078, 17048067}, {65079, 17860611}, {65080, 17860867}, {65081, 17861123},
1938
  {65082, 17861379}, {65083, 17861635}, {65084, 17861891}, {65085, 17862147},
1939
  {65086, 17862403}, {65087, 17077763}, {65088, 17078019}, {65089, 17862659},
1940
  {65090, 17862915}, {65091, 17863171}, {65092, 17863427}, {65093, 1},
1941
  {65095, 17863683}, {65096, 17863939}, {65097, 33820675}, {65101, 17860355},
1942
  {65104, 17858819}, {65105, 17859075}, {65106, 2}, {65108, 16848643},
1943
  {65109, 17121027}, {65110, 17043971}, {65111, 17042947}, {65112, 17859843},
1944
  {65113, 17047811}, {65114, 17048067}, {65115, 17860611}, {65116, 17860867},
1945
  {65117, 17861123}, {65118, 17861379}, {65119, 17864195}, {65120, 17864451},
1946
  {65121, 17864707}, {65122, 17047043}, {65123, 17864963}, {65124, 17865219},
1947
  {65125, 17865475}, {65126, 17047555}, {65127, 2}, {65128, 17865731},
1948
  {65129, 17865987}, {65130, 17866243}, {65131, 17866499}, {65132, 2},
1949
  {65136, 34643971}, {65137, 34644483}, {65138, 34514947}, {65139, 1},
1950
  {65140, 34515715}, {65141, 2}, {65142, 34516483}, {65143, 34534915},
1951
  {65144, 34517251}, {65145, 34535683}, {65146, 34518019}, {65147, 34536451},
1952
  {65148, 34518787}, {65149, 34644995}, {65150, 34645507}, {65151, 34646019},
1953
  {65152, 17869315}, {65153, 17869571}, {65155, 17869827}, {65157, 17870083},
1954
  {65159, 17870339}, {65161, 17688835}, {65165, 16910595}, {65167, 17695235},
1955
  {65171, 17870595}, {65173, 17698307}, {65177, 17701379}, {65181, 17693443},
1956
  {65185, 17693955}, {65189, 17696515}, {65193, 17846019}, {65195, 17736195},
1957
  {65197, 17736707}, {65199, 17743107}, {65201, 17706499}, {65205, 17756675},
1958
  {65209, 17708547}, {65213, 17709571}, {65217, 17711619}, {65221, 17712643},
1959
  {65225, 17713155}, {65229, 17714179}, {65233, 17715203}, {65237, 17718275},
1960
  {65241, 17720323}, {65245, 17722627}, {65249, 17694467}, {65253, 17729539},
1961
  {65257, 17732611}, {65261, 16911107}, {65263, 17688579}, {65265, 16912131},
1962
  {65269, 34648067}, {65271, 34648579}, {65273, 34649091}, {65275, 34633987},
1963
  {65277, 2}, {65279, 0}, {65280, 2}, {65281, 17042947},
1964
  {65282, 17872387}, {65283, 17864195}, {65284, 17865987}, {65285, 17866243},
1965
  {65286, 17864451}, {65287, 17872643}, {65288, 17047811}, {65289, 17048067},
1966
  {65290, 17864707}, {65291, 17047043}, {65292, 17858819}, {65293, 17864963},
1967
  {65294, 17207043}, {65295, 17048579}, {65296, 17045507}, {65297, 16786947},
1968
  {65298, 16785155}, {65299, 16785411}, {65300, 16787715}, {65301, 17045763},
1969
  {65302, 17046019}, {65303, 17046275}, {65304, 17046531}, {65305, 17046787},
1970
  {65306, 17121027}, {65307, 16848643}, {65308, 17865219}, {65309, 17047555},
1971
  {65310, 17865475}, {65311, 17043971}, {65312, 17866499}, {65313, 16777219},
1972
  {65314, 16777475}, {65315, 16777731}, {65316, 16777987}, {65317, 16778243},
1973
  {65318, 16778499}, {65319, 16778755}, {65320, 16779011}, {65321, 16779267},
1974
  {65322, 16779523}, {65323, 16779779}, {65324, 16780035}, {65325, 16780291},
1975
  {65326, 16780547}, {65327, 16780803}, {65328, 16781059}, {65329, 16781315},
1976
  {65330, 16781571}, {65331, 16781827}, {65332, 16782083}, {65333, 16782339},
1977
  {65334, 16782595}, {65335, 16782851}, {65336, 16783107}, {65337, 16783363},
1978
  {65338, 16783619}, {65339, 17863683}, {65340, 17865731}, {65341, 17863939},
1979
  {65342, 17872899}, {65343, 17860355}, {65344, 17037059}, {65345, 16777219},
1980
  {65346, 16777475}, {65347, 16777731}, {65348, 16777987}, {65349, 16778243},
1981
  {65350, 16778499}, {65351, 16778755}, {65352, 16779011}, {65353, 16779267},
1982
  {65354, 16779523}, {65355, 16779779}, {65356, 16780035}, {65357, 16780291},
1983
  {65358, 16780547}, {65359, 16780803}, {65360, 16781059}, {65361, 16781315},
1984
  {65362, 16781571}, {65363, 16781827}, {65364, 16782083}, {65365, 16782339},
1985
  {65366, 16782595}, {65367, 16782851}, {65368, 16783107}, {65369, 16783363},
1986
  {65370, 16783619}, {65371, 17860611}, {65372, 17873155}, {65373, 17860867},
1987
  {65374, 17873411}, {65375, 17873667}, {65376, 17873923}, {65377, 17207043},
1988
  {65378, 17862659}, {65379, 17862915}, {65380, 17859075}, {65381, 17874179},
1989
  {65382, 17327363}, {65383, 17329923}, {65384, 17372931}, {65385, 17874435},
1990
  {65386, 17374467}, {65387, 17334019}, {65388, 17874691}, {65389, 17344259},
1991
  {65390, 17390083}, {65391, 17339651}, {65392, 17328643}, {65393, 17316099},
1992
  {65394, 17316355}, {65395, 17316611}, {65396, 17316867}, {65397, 17317123},
1993
  {65398, 17317379}, {65399, 17317635}, {65400, 17317891}, {65401, 17318147},
1994
  {65402, 17209603}, {65403, 17318403}, {65404, 17318659}, {65405, 17318915},
1995
  {65406, 17319171}, {65407, 17319427}, {65408, 17319683}, {65409, 17319939},
1996
  {65410, 17320195}, {65411, 17320451}, {65412, 17209859}, {65413, 17320707},
1997
  {65414, 17320963}, {65415, 17321219}, {65416, 17321475}, {65417, 17321731},
1998
  {65418, 17321987}, {65419, 17322243}, {65420, 17322499}, {65421, 17322755},
1999
  {65422, 17323011}, {65423, 17323267}, {65424, 17323523}, {65425, 17323779},
2000
  {65426, 17324035}, {65427, 17324291}, {65428, 17324547}, {65429, 17324803},
2001
  {65430, 17325059}, {65431, 17325315}, {65432, 17325571}, {65433, 17325827},
2002
  {65434, 17326083}, {65435, 17326339}, {65436, 17326595}, {65437, 17330435},
2003
  {65438, 17208323}, {65439, 17208835}, {65440, 0}, {65441, 17210115},
2004
  {65442, 17210371}, {65443, 17210627}, {65444, 17210883}, {65445, 17211139},
2005
  {65446, 17211395}, {65447, 17211651}, {65448, 17211907}, {65449, 17212163},
2006
  {65450, 17212419}, {65451, 17212675}, {65452, 17212931}, {65453, 17213187},
2007
  {65454, 17213443}, {65455, 17213699}, {65456, 17213955}, {65457, 17214211},
2008
  {65458, 17214467}, {65459, 17214723}, {65460, 17214979}, {65461, 17215235},
2009
  {65462, 17215491}, {65463, 17215747}, {65464, 17216003}, {65465, 17216259},
2010
  {65466, 17216515}, {65467, 17216771}, {65468, 17217027}, {65469, 17217283},
2011
  {65470, 17217539}, {65471, 2}, {65474, 17217795}, {65475, 17218051},
2012
  {65476, 17218307}, {65477, 17218563}, {65478, 17218819}, {65479, 17219075},
2013
  {65480, 2}, {65482, 17219331}, {65483, 17219587}, {65484, 17219843},
2014
  {65485, 17220099}, {65486, 17220355}, {65487, 17220611}, {65488, 2},
2015
  {65490, 17220867}, {65491, 17221123}, {65492, 17221379}, {65493, 17221635},
2016
  {65494, 17221891}, {65495, 17222147}, {65496, 2}, {65498, 17222403},
2017
  {65499, 17222659}, {65500, 17222915}, {65501, 2}, {65504, 17874947},
2018
  {65505, 17875203}, {65506, 17875459}, {65507, 33561859}, {65508, 17875715},
2019
  {65509, 17875971}, {65510, 17876227}, {65511, 2}, {65512, 17876483},
2020
  {65513, 17876739}, {65514, 17876995}, {65515, 17877251}, {65516, 17877507},
2021
  {65517, 17877763}, {65518, 17878019}, {65519, 2}, {65536, 1},
2022
  {65548, 2}, {65549, 1}, {65575, 2}, {65576, 1},
2023
  {65595, 2}, {65596, 1}, {65598, 2}, {65599, 1},
2024
  {65614, 2}, {65616, 1}, {65630, 2}, {65664, 1},
2025
  {65787, 2}, {65792, 1}, {65795, 2}, {65799, 1},
2026
  {65844, 2}, {65847, 1}, {65935, 2}, {65936, 1},
2027
  {65949, 2}, {65952, 1}, {65953, 2}, {66000, 1},
2028
  {66046, 2}, {66176, 1}, {66205, 2}, {66208, 1},
2029
  {66257, 2}, {66272, 1}, {66300, 2}, {66304, 1},
2030
  {66340, 2}, {66349, 1}, {66379, 2}, {66384, 1},
2031
  {66427, 2}, {66432, 1}, {66462, 2}, {66463, 1},
2032
  {66500, 2}, {66504, 1}, {66518, 2}, {66560, 17878275},
2033
  {66561, 17878531}, {66562, 17878787}, {66563, 17879043}, {66564, 17879299},
2034
  {66565, 17879555}, {66566, 17879811}, {66567, 17880067}, {66568, 17880323},
2035
  {66569, 17880579}, {66570, 17880835}, {66571, 17881091}, {66572, 17881347},
2036
  {66573, 17881603}, {66574, 17881859}, {66575, 17882115}, {66576, 17882371},
2037
  {66577, 17882627}, {66578, 17882883}, {66579, 17883139}, {66580, 17883395},
2038
  {66581, 17883651}, {66582, 17883907}, {66583, 17884163}, {66584, 17884419},
2039
  {66585, 17884675}, {66586, 17884931}, {66587, 17885187}, {66588, 17885443},
2040
  {66589, 17885699}, {66590, 17885955}, {66591, 17886211}, {66592, 17886467},
2041
  {66593, 17886723}, {66594, 17886979}, {66595, 17887235}, {66596, 17887491},
2042
  {66597, 17887747}, {66598, 17888003}, {66599, 17888259}, {66600, 1},
2043
  {66718, 2}, {66720, 1}, {66730, 2}, {66736, 17888515},
2044
  {66737, 17888771}, {66738, 17889027}, {66739, 17889283}, {66740, 17889539},
2045
  {66741, 17889795}, {66742, 17890051}, {66743, 17890307}, {66744, 17890563},
2046
  {66745, 17890819}, {66746, 17891075}, {66747, 17891331}, {66748, 17891587},
2047
  {66749, 17891843}, {66750, 17892099}, {66751, 17892355}, {66752, 17892611},
2048
  {66753, 17892867}, {66754, 17893123}, {66755, 17893379}, {66756, 17893635},
2049
  {66757, 17893891}, {66758, 17894147}, {66759, 17894403}, {66760, 17894659},
2050
  {66761, 17894915}, {66762, 17895171}, {66763, 17895427}, {66764, 17895683},
2051
  {66765, 17895939}, {66766, 17896195}, {66767, 17896451}, {66768, 17896707},
2052
  {66769, 17896963}, {66770, 17897219}, {66771, 17897475}, {66772, 2},
2053
  {66776, 1}, {66812, 2}, {66816, 1}, {66856, 2},
2054
  {66864, 1}, {66916, 2}, {66927, 1}, {66928, 17897731},
2055
  {66929, 17897987}, {66930, 17898243}, {66931, 17898499}, {66932, 17898755},
2056
  {66933, 17899011}, {66934, 17899267}, {66935, 17899523}, {66936, 17899779},
2057
  {66937, 17900035}, {66938, 17900291}, {66939, 2}, {66940, 17900547},
2058
  {66941, 17900803}, {66942, 17901059}, {66943, 17901315}, {66944, 17901571},
2059
  {66945, 17901827}, {66946, 17902083}, {66947, 17902339}, {66948, 17902595},
2060
  {66949, 17902851}, {66950, 17903107}, {66951, 17903363}, {66952, 17903619},
2061
  {66953, 17903875}, {66954, 17904131}, {66955, 2}, {66956, 17904387},
2062
  {66957, 17904643}, {66958, 17904899}, {66959, 17905155}, {66960, 17905411},
2063
  {66961, 17905667}, {66962, 17905923}, {66963, 2}, {66964, 17906179},
2064
  {66965, 17906435}, {66966, 2}, {66967, 1}, {66978, 2},
2065
  {66979, 1}, {66994, 2}, {66995, 1}, {67002, 2},
2066
  {67003, 1}, {67005, 2}, {67008, 1}, {67060, 2},
2067
  {67072, 1}, {67383, 2}, {67392, 1}, {67414, 2},
2068
  {67424, 1}, {67432, 2}, {67456, 1}, {67457, 17906691},
2069
  {67458, 17906947}, {67459, 16791043}, {67460, 17907203}, {67461, 16814083},
2070
  {67462, 2}, {67463, 17907459}, {67464, 17907715}, {67465, 17907971},
2071
  {67466, 17908227}, {67467, 16815363}, {67468, 16815619}, {67469, 17908483},
2072
  {67470, 17908739}, {67471, 17908995}, {67472, 17909251}, {67473, 17527555},
2073
  {67474, 17909507}, {67475, 16817155}, {67476, 17909763}, {67477, 16802051},
2074
  {67478, 17910019}, {67479, 17910275}, {67480, 17910531}, {67481, 17910787},
2075
  {67482, 17911043}, {67483, 17523459}, {67484, 17911299}, {67485, 17911555},
2076
  {67486, 17911811}, {67487, 17912067}, {67488, 17912323}, {67489, 17912579},
2077
  {67490, 16795395}, {67491, 17912835}, {67492, 17913091}, {67493, 16781315},
2078
  {67494, 17913347}, {67495, 17913603}, {67496, 17135875}, {67497, 17913859},
2079
  {67498, 16819971}, {67499, 17914115}, {67500, 17914371}, {67501, 17914627},
2080
  {67502, 17914883}, {67503, 16820995}, {67504, 17915139}, {67505, 2},
2081
  {67506, 17915395}, {67507, 17915651}, {67508, 17915907}, {67509, 17916163},
2082
  {67510, 17916419}, {67511, 17916675}, {67512, 17916931}, {67513, 17917187},
2083
  {67514, 17917443}, {67515, 2}, {67584, 1}, {67590, 2},
2084
  {67592, 1}, {67593, 2}, {67594, 1}, {67638, 2},
2085
  {67639, 1}, {67641, 2}, {67644, 1}, {67645, 2},
2086
  {67647, 1}, {67670, 2}, {67671, 1}, {67743, 2},
2087
  {67751, 1}, {67760, 2}, {67808, 1}, {67827, 2},
2088
  {67828, 1}, {67830, 2}, {67835, 1}, {67868, 2},
2089
  {67871, 1}, {67898, 2}, {67903, 1}, {67904, 2},
2090
  {67968, 1}, {68024, 2}, {68028, 1}, {68048, 2},
2091
  {68050, 1}, {68100, 2}, {68101, 1}, {68103, 2},
2092
  {68108, 1}, {68116, 2}, {68117, 1}, {68120, 2},
2093
  {68121, 1}, {68150, 2}, {68152, 1}, {68155, 2},
2094
  {68159, 1}, {68169, 2}, {68176, 1}, {68185, 2},
2095
  {68192, 1}, {68256, 2}, {68288, 1}, {68327, 2},
2096
  {68331, 1}, {68343, 2}, {68352, 1}, {68406, 2},
2097
  {68409, 1}, {68438, 2}, {68440, 1}, {68467, 2},
2098
  {68472, 1}, {68498, 2}, {68505, 1}, {68509, 2},
2099
  {68521, 1}, {68528, 2}, {68608, 1}, {68681, 2},
2100
  {68736, 17917699}, {68737, 17917955}, {68738, 17918211}, {68739, 17918467},
2101
  {68740, 17918723}, {68741, 17918979}, {68742, 17919235}, {68743, 17919491},
2102
  {68744, 17919747}, {68745, 17920003}, {68746, 17920259}, {68747, 17920515},
2103
  {68748, 17920771}, {68749, 17921027}, {68750, 17921283}, {68751, 17921539},
2104
  {68752, 17921795}, {68753, 17922051}, {68754, 17922307}, {68755, 17922563},
2105
  {68756, 17922819}, {68757, 17923075}, {68758, 17923331}, {68759, 17923587},
2106
  {68760, 17923843}, {68761, 17924099}, {68762, 17924355}, {68763, 17924611},
2107
  {68764, 17924867}, {68765, 17925123}, {68766, 17925379}, {68767, 17925635},
2108
  {68768, 17925891}, {68769, 17926147}, {68770, 17926403}, {68771, 17926659},
2109
  {68772, 17926915}, {68773, 17927171}, {68774, 17927427}, {68775, 17927683},
2110
  {68776, 17927939}, {68777, 17928195}, {68778, 17928451}, {68779, 17928707},
2111
  {68780, 17928963}, {68781, 17929219}, {68782, 17929475}, {68783, 17929731},
2112
  {68784, 17929987}, {68785, 17930243}, {68786, 17930499}, {68787, 2},
2113
  {68800, 1}, {68851, 2}, {68858, 1}, {68904, 2},
2114
  {68912, 1}, {68922, 2}, {68928, 1}, {68944, 17930755},
2115
  {68945, 17931011}, {68946, 17931267}, {68947, 17931523}, {68948, 17931779},
2116
  {68949, 17932035}, {68950, 17932291}, {68951, 17932547}, {68952, 17932803},
2117
  {68953, 17933059}, {68954, 17933315}, {68955, 17933571}, {68956, 17933827},
2118
  {68957, 17934083}, {68958, 17934339}, {68959, 17934595}, {68960, 17934851},
2119
  {68961, 17935107}, {68962, 17935363}, {68963, 17935619}, {68964, 17935875},
2120
  {68965, 17936131}, {68966, 2}, {68969, 1}, {68998, 2},
2121
  {69006, 1}, {69008, 2}, {69216, 1}, {69247, 2},
2122
  {69248, 1}, {69290, 2}, {69291, 1}, {69294, 2},
2123
  {69296, 1}, {69298, 2}, {69314, 1}, {69317, 2},
2124
  {69372, 1}, {69416, 2}, {69424, 1}, {69466, 2},
2125
  {69488, 1}, {69514, 2}, {69552, 1}, {69580, 2},
2126
  {69600, 1}, {69623, 2}, {69632, 1}, {69710, 2},
2127
  {69714, 1}, {69750, 2}, {69759, 1}, {69821, 2},
2128
  {69822, 1}, {69827, 2}, {69840, 1}, {69865, 2},
2129
  {69872, 1}, {69882, 2}, {69888, 1}, {69941, 2},
2130
  {69942, 1}, {69960, 2}, {69968, 1}, {70007, 2},
2131
  {70016, 1}, {70112, 2}, {70113, 1}, {70133, 2},
2132
  {70144, 1}, {70162, 2}, {70163, 1}, {70210, 2},
2133
  {70272, 1}, {70279, 2}, {70280, 1}, {70281, 2},
2134
  {70282, 1}, {70286, 2}, {70287, 1}, {70302, 2},
2135
  {70303, 1}, {70314, 2}, {70320, 1}, {70379, 2},
2136
  {70384, 1}, {70394, 2}, {70400, 1}, {70404, 2},
2137
  {70405, 1}, {70413, 2}, {70415, 1}, {70417, 2},
2138
  {70419, 1}, {70441, 2}, {70442, 1}, {70449, 2},
2139
  {70450, 1}, {70452, 2}, {70453, 1}, {70458, 2},
2140
  {70459, 1}, {70469, 2}, {70471, 1}, {70473, 2},
2141
  {70475, 1}, {70478, 2}, {70480, 1}, {70481, 2},
2142
  {70487, 1}, {70488, 2}, {70493, 1}, {70500, 2},
2143
  {70502, 1}, {70509, 2}, {70512, 1}, {70517, 2},
2144
  {70528, 1}, {70538, 2}, {70539, 1}, {70540, 2},
2145
  {70542, 1}, {70543, 2}, {70544, 1}, {70582, 2},
2146
  {70583, 1}, {70593, 2}, {70594, 1}, {70595, 2},
2147
  {70597, 1}, {70598, 2}, {70599, 1}, {70603, 2},
2148
  {70604, 1}, {70614, 2}, {70615, 1}, {70617, 2},
2149
  {70625, 1}, {70627, 2}, {70656, 1}, {70748, 2},
2150
  {70749, 1}, {70754, 2}, {70784, 1}, {70856, 2},
2151
  {70864, 1}, {70874, 2}, {71040, 1}, {71094, 2},
2152
  {71096, 1}, {71134, 2}, {71168, 1}, {71237, 2},
2153
  {71248, 1}, {71258, 2}, {71264, 1}, {71277, 2},
2154
  {71296, 1}, {71354, 2}, {71360, 1}, {71370, 2},
2155
  {71376, 1}, {71396, 2}, {71424, 1}, {71451, 2},
2156
  {71453, 1}, {71468, 2}, {71472, 1}, {71495, 2},
2157
  {71680, 1}, {71740, 2}, {71840, 17936387}, {71841, 17936643},
2158
  {71842, 17936899}, {71843, 17937155}, {71844, 17937411}, {71845, 17937667},
2159
  {71846, 17937923}, {71847, 17938179}, {71848, 17938435}, {71849, 17938691},
2160
  {71850, 17938947}, {71851, 17939203}, {71852, 17939459}, {71853, 17939715},
2161
  {71854, 17939971}, {71855, 17940227}, {71856, 17940483}, {71857, 17940739},
2162
  {71858, 17940995}, {71859, 17941251}, {71860, 17941507}, {71861, 17941763},
2163
  {71862, 17942019}, {71863, 17942275}, {71864, 17942531}, {71865, 17942787},
2164
  {71866, 17943043}, {71867, 17943299}, {71868, 17943555}, {71869, 17943811},
2165
  {71870, 17944067}, {71871, 17944323}, {71872, 1}, {71923, 2},
2166
  {71935, 1}, {71943, 2}, {71945, 1}, {71946, 2},
2167
  {71948, 1}, {71956, 2}, {71957, 1}, {71959, 2},
2168
  {71960, 1}, {71990, 2}, {71991, 1}, {71993, 2},
2169
  {71995, 1}, {72007, 2}, {72016, 1}, {72026, 2},
2170
  {72096, 1}, {72104, 2}, {72106, 1}, {72152, 2},
2171
  {72154, 1}, {72165, 2}, {72192, 1}, {72264, 2},
2172
  {72272, 1}, {72355, 2}, {72368, 1}, {72441, 2},
2173
  {72448, 1}, {72458, 2}, {72640, 1}, {72674, 2},
2174
  {72688, 1}, {72698, 2}, {72704, 1}, {72713, 2},
2175
  {72714, 1}, {72759, 2}, {72760, 1}, {72774, 2},
2176
  {72784, 1}, {72813, 2}, {72816, 1}, {72848, 2},
2177
  {72850, 1}, {72872, 2}, {72873, 1}, {72887, 2},
2178
  {72960, 1}, {72967, 2}, {72968, 1}, {72970, 2},
2179
  {72971, 1}, {73015, 2}, {73018, 1}, {73019, 2},
2180
  {73020, 1}, {73022, 2}, {73023, 1}, {73032, 2},
2181
  {73040, 1}, {73050, 2}, {73056, 1}, {73062, 2},
2182
  {73063, 1}, {73065, 2}, {73066, 1}, {73103, 2},
2183
  {73104, 1}, {73106, 2}, {73107, 1}, {73113, 2},
2184
  {73120, 1}, {73130, 2}, {73440, 1}, {73465, 2},
2185
  {73472, 1}, {73489, 2}, {73490, 1}, {73531, 2},
2186
  {73534, 1}, {73563, 2}, {73648, 1}, {73649, 2},
2187
  {73664, 1}, {73714, 2}, {73727, 1}, {74650, 2},
2188
  {74752, 1}, {74863, 2}, {74864, 1}, {74869, 2},
2189
  {74880, 1}, {75076, 2}, {77712, 1}, {77811, 2},
2190
  {77824, 1}, {78896, 2}, {78912, 1}, {78934, 2},
2191
  {78944, 1}, {82939, 2}, {82944, 1}, {83527, 2},
2192
  {90368, 1}, {90426, 2}, {92160, 1}, {92729, 2},
2193
  {92736, 1}, {92767, 2}, {92768, 1}, {92778, 2},
2194
  {92782, 1}, {92863, 2}, {92864, 1}, {92874, 2},
2195
  {92880, 1}, {92910, 2}, {92912, 1}, {92918, 2},
2196
  {92928, 1}, {92998, 2}, {93008, 1}, {93018, 2},
2197
  {93019, 1}, {93026, 2}, {93027, 1}, {93048, 2},
2198
  {93053, 1}, {93072, 2}, {93504, 1}, {93562, 2},
2199
  {93760, 17944579}, {93761, 17944835}, {93762, 17945091}, {93763, 17945347},
2200
  {93764, 17945603}, {93765, 17945859}, {93766, 17946115}, {93767, 17946371},
2201
  {93768, 17946627}, {93769, 17946883}, {93770, 17947139}, {93771, 17947395},
2202
  {93772, 17947651}, {93773, 17947907}, {93774, 17948163}, {93775, 17948419},
2203
  {93776, 17948675}, {93777, 17948931}, {93778, 17949187}, {93779, 17949443},
2204
  {93780, 17949699}, {93781, 17949955}, {93782, 17950211}, {93783, 17950467},
2205
  {93784, 17950723}, {93785, 17950979}, {93786, 17951235}, {93787, 17951491},
2206
  {93788, 17951747}, {93789, 17952003}, {93790, 17952259}, {93791, 17952515},
2207
  {93792, 1}, {93851, 2}, {93952, 1}, {94027, 2},
2208
  {94031, 1}, {94088, 2}, {94095, 1}, {94112, 2},
2209
  {94176, 1}, {94181, 2}, {94192, 1}, {94194, 2},
2210
  {94208, 1}, {100344, 2}, {100352, 1}, {101590, 2},
2211
  {101631, 1}, {101641, 2}, {110576, 1}, {110580, 2},
2212
  {110581, 1}, {110588, 2}, {110589, 1}, {110591, 2},
2213
  {110592, 1}, {110883, 2}, {110898, 1}, {110899, 2},
2214
  {110928, 1}, {110931, 2}, {110933, 1}, {110934, 2},
2215
  {110948, 1}, {110952, 2}, {110960, 1}, {111356, 2},
2216
  {113664, 1}, {113771, 2}, {113776, 1}, {113789, 2},
2217
  {113792, 1}, {113801, 2}, {113808, 1}, {113818, 2},
2218
  {113820, 1}, {113824, 0}, {113828, 2}, {117760, 1},
2219
  {117974, 16777219}, {117975, 16777475}, {117976, 16777731}, {117977, 16777987},
2220
  {117978, 16778243}, {117979, 16778499}, {117980, 16778755}, {117981, 16779011},
2221
  {117982, 16779267}, {117983, 16779523}, {117984, 16779779}, {117985, 16780035},
2222
  {117986, 16780291}, {117987, 16780547}, {117988, 16780803}, {117989, 16781059},
2223
  {117990, 16781315}, {117991, 16781571}, {117992, 16781827}, {117993, 16782083},
2224
  {117994, 16782339}, {117995, 16782595}, {117996, 16782851}, {117997, 16783107},
2225
  {117998, 16783363}, {117999, 16783619}, {118000, 17045507}, {118001, 16786947},
2226
  {118002, 16785155}, {118003, 16785411}, {118004, 16787715}, {118005, 17045763},
2227
  {118006, 17046019}, {118007, 17046275}, {118008, 17046531}, {118009, 17046787},
2228
  {118010, 2}, {118016, 1}, {118452, 2}, {118528, 1},
2229
  {118574, 2}, {118576, 1}, {118599, 2}, {118608, 1},
2230
  {118724, 2}, {118784, 1}, {119030, 2}, {119040, 1},
2231
  {119079, 2}, {119081, 1}, {119134, 34729987}, {119135, 34730499},
2232
  {119136, 51508227}, {119137, 51508995}, {119138, 51509763}, {119139, 51510531},
2233
  {119140, 51511299}, {119141, 1}, {119155, 0}, {119163, 1},
2234
  {119227, 34734851}, {119228, 34735363}, {119229, 51513091}, {119230, 51513859},
2235
  {119231, 51514627}, {119232, 51515395}, {119233, 1}, {119275, 2},
2236
  {119296, 1}, {119366, 2}, {119488, 1}, {119508, 2},
2237
  {119520, 1}, {119540, 2}, {119552, 1}, {119639, 2},
2238
  {119648, 1}, {119673, 2}, {119808, 16777219}, {119809, 16777475},
2239
  {119810, 16777731}, {119811, 16777987}, {119812, 16778243}, {119813, 16778499},
2240
  {119814, 16778755}, {119815, 16779011}, {119816, 16779267}, {119817, 16779523},
2241
  {119818, 16779779}, {119819, 16780035}, {119820, 16780291}, {119821, 16780547},
2242
  {119822, 16780803}, {119823, 16781059}, {119824, 16781315}, {119825, 16781571},
2243
  {119826, 16781827}, {119827, 16782083}, {119828, 16782339}, {119829, 16782595},
2244
  {119830, 16782851}, {119831, 16783107}, {119832, 16783363}, {119833, 16783619},
2245
  {119834, 16777219}, {119835, 16777475}, {119836, 16777731}, {119837, 16777987},
2246
  {119838, 16778243}, {119839, 16778499}, {119840, 16778755}, {119841, 16779011},
2247
  {119842, 16779267}, {119843, 16779523}, {119844, 16779779}, {119845, 16780035},
2248
  {119846, 16780291}, {119847, 16780547}, {119848, 16780803}, {119849, 16781059},
2249
  {119850, 16781315}, {119851, 16781571}, {119852, 16781827}, {119853, 16782083},
2250
  {119854, 16782339}, {119855, 16782595}, {119856, 16782851}, {119857, 16783107},
2251
  {119858, 16783363}, {119859, 16783619}, {119860, 16777219}, {119861, 16777475},
2252
  {119862, 16777731}, {119863, 16777987}, {119864, 16778243}, {119865, 16778499},
2253
  {119866, 16778755}, {119867, 16779011}, {119868, 16779267}, {119869, 16779523},
2254
  {119870, 16779779}, {119871, 16780035}, {119872, 16780291}, {119873, 16780547},
2255
  {119874, 16780803}, {119875, 16781059}, {119876, 16781315}, {119877, 16781571},
2256
  {119878, 16781827}, {119879, 16782083}, {119880, 16782339}, {119881, 16782595},
2257
  {119882, 16782851}, {119883, 16783107}, {119884, 16783363}, {119885, 16783619},
2258
  {119886, 16777219}, {119887, 16777475}, {119888, 16777731}, {119889, 16777987},
2259
  {119890, 16778243}, {119891, 16778499}, {119892, 16778755}, {119893, 2},
2260
  {119894, 16779267}, {119895, 16779523}, {119896, 16779779}, {119897, 16780035},
2261
  {119898, 16780291}, {119899, 16780547}, {119900, 16780803}, {119901, 16781059},
2262
  {119902, 16781315}, {119903, 16781571}, {119904, 16781827}, {119905, 16782083},
2263
  {119906, 16782339}, {119907, 16782595}, {119908, 16782851}, {119909, 16783107},
2264
  {119910, 16783363}, {119911, 16783619}, {119912, 16777219}, {119913, 16777475},
2265
  {119914, 16777731}, {119915, 16777987}, {119916, 16778243}, {119917, 16778499},
2266
  {119918, 16778755}, {119919, 16779011}, {119920, 16779267}, {119921, 16779523},
2267
  {119922, 16779779}, {119923, 16780035}, {119924, 16780291}, {119925, 16780547},
2268
  {119926, 16780803}, {119927, 16781059}, {119928, 16781315}, {119929, 16781571},
2269
  {119930, 16781827}, {119931, 16782083}, {119932, 16782339}, {119933, 16782595},
2270
  {119934, 16782851}, {119935, 16783107}, {119936, 16783363}, {119937, 16783619},
2271
  {119938, 16777219}, {119939, 16777475}, {119940, 16777731}, {119941, 16777987},
2272
  {119942, 16778243}, {119943, 16778499}, {119944, 16778755}, {119945, 16779011},
2273
  {119946, 16779267}, {119947, 16779523}, {119948, 16779779}, {119949, 16780035},
2274
  {119950, 16780291}, {119951, 16780547}, {119952, 16780803}, {119953, 16781059},
2275
  {119954, 16781315}, {119955, 16781571}, {119956, 16781827}, {119957, 16782083},
2276
  {119958, 16782339}, {119959, 16782595}, {119960, 16782851}, {119961, 16783107},
2277
  {119962, 16783363}, {119963, 16783619}, {119964, 16777219}, {119965, 2},
2278
  {119966, 16777731}, {119967, 16777987}, {119968, 2}, {119970, 16778755},
2279
  {119971, 2}, {119973, 16779523}, {119974, 16779779}, {119975, 2},
2280
  {119977, 16780547}, {119978, 16780803}, {119979, 16781059}, {119980, 16781315},
2281
  {119981, 2}, {119982, 16781827}, {119983, 16782083}, {119984, 16782339},
2282
  {119985, 16782595}, {119986, 16782851}, {119987, 16783107}, {119988, 16783363},
2283
  {119989, 16783619}, {119990, 16777219}, {119991, 16777475}, {119992, 16777731},
2284
  {119993, 16777987}, {119994, 2}, {119995, 16778499}, {119996, 2},
2285
  {119997, 16779011}, {119998, 16779267}, {119999, 16779523}, {120000, 16779779},
2286
  {120001, 16780035}, {120002, 16780291}, {120003, 16780547}, {120004, 2},
2287
  {120005, 16781059}, {120006, 16781315}, {120007, 16781571}, {120008, 16781827},
2288
  {120009, 16782083}, {120010, 16782339}, {120011, 16782595}, {120012, 16782851},
2289
  {120013, 16783107}, {120014, 16783363}, {120015, 16783619}, {120016, 16777219},
2290
  {120017, 16777475}, {120018, 16777731}, {120019, 16777987}, {120020, 16778243},
2291
  {120021, 16778499}, {120022, 16778755}, {120023, 16779011}, {120024, 16779267},
2292
  {120025, 16779523}, {120026, 16779779}, {120027, 16780035}, {120028, 16780291},
2293
  {120029, 16780547}, {120030, 16780803}, {120031, 16781059}, {120032, 16781315},
2294
  {120033, 16781571}, {120034, 16781827}, {120035, 16782083}, {120036, 16782339},
2295
  {120037, 16782595}, {120038, 16782851}, {120039, 16783107}, {120040, 16783363},
2296
  {120041, 16783619}, {120042, 16777219}, {120043, 16777475}, {120044, 16777731},
2297
  {120045, 16777987}, {120046, 16778243}, {120047, 16778499}, {120048, 16778755},
2298
  {120049, 16779011}, {120050, 16779267}, {120051, 16779523}, {120052, 16779779},
2299
  {120053, 16780035}, {120054, 16780291}, {120055, 16780547}, {120056, 16780803},
2300
  {120057, 16781059}, {120058, 16781315}, {120059, 16781571}, {120060, 16781827},
2301
  {120061, 16782083}, {120062, 16782339}, {120063, 16782595}, {120064, 16782851},
2302
  {120065, 16783107}, {120066, 16783363}, {120067, 16783619}, {120068, 16777219},
2303
  {120069, 16777475}, {120070, 2}, {120071, 16777987}, {120072, 16778243},
2304
  {120073, 16778499}, {120074, 16778755}, {120075, 2}, {120077, 16779523},
2305
  {120078, 16779779}, {120079, 16780035}, {120080, 16780291}, {120081, 16780547},
2306
  {120082, 16780803}, {120083, 16781059}, {120084, 16781315}, {120085, 2},
2307
  {120086, 16781827}, {120087, 16782083}, {120088, 16782339}, {120089, 16782595},
2308
  {120090, 16782851}, {120091, 16783107}, {120092, 16783363}, {120093, 2},
2309
  {120094, 16777219}, {120095, 16777475}, {120096, 16777731}, {120097, 16777987},
2310
  {120098, 16778243}, {120099, 16778499}, {120100, 16778755}, {120101, 16779011},
2311
  {120102, 16779267}, {120103, 16779523}, {120104, 16779779}, {120105, 16780035},
2312
  {120106, 16780291}, {120107, 16780547}, {120108, 16780803}, {120109, 16781059},
2313
  {120110, 16781315}, {120111, 16781571}, {120112, 16781827}, {120113, 16782083},
2314
  {120114, 16782339}, {120115, 16782595}, {120116, 16782851}, {120117, 16783107},
2315
  {120118, 16783363}, {120119, 16783619}, {120120, 16777219}, {120121, 16777475},
2316
  {120122, 2}, {120123, 16777987}, {120124, 16778243}, {120125, 16778499},
2317
  {120126, 16778755}, {120127, 2}, {120128, 16779267}, {120129, 16779523},
2318
  {120130, 16779779}, {120131, 16780035}, {120132, 16780291}, {120133, 2},
2319
  {120134, 16780803}, {120135, 2}, {120138, 16781827}, {120139, 16782083},
2320
  {120140, 16782339}, {120141, 16782595}, {120142, 16782851}, {120143, 16783107},
2321
  {120144, 16783363}, {120145, 2}, {120146, 16777219}, {120147, 16777475},
2322
  {120148, 16777731}, {120149, 16777987}, {120150, 16778243}, {120151, 16778499},
2323
  {120152, 16778755}, {120153, 16779011}, {120154, 16779267}, {120155, 16779523},
2324
  {120156, 16779779}, {120157, 16780035}, {120158, 16780291}, {120159, 16780547},
2325
  {120160, 16780803}, {120161, 16781059}, {120162, 16781315}, {120163, 16781571},
2326
  {120164, 16781827}, {120165, 16782083}, {120166, 16782339}, {120167, 16782595},
2327
  {120168, 16782851}, {120169, 16783107}, {120170, 16783363}, {120171, 16783619},
2328
  {120172, 16777219}, {120173, 16777475}, {120174, 16777731}, {120175, 16777987},
2329
  {120176, 16778243}, {120177, 16778499}, {120178, 16778755}, {120179, 16779011},
2330
  {120180, 16779267}, {120181, 16779523}, {120182, 16779779}, {120183, 16780035},
2331
  {120184, 16780291}, {120185, 16780547}, {120186, 16780803}, {120187, 16781059},
2332
  {120188, 16781315}, {120189, 16781571}, {120190, 16781827}, {120191, 16782083},
2333
  {120192, 16782339}, {120193, 16782595}, {120194, 16782851}, {120195, 16783107},
2334
  {120196, 16783363}, {120197, 16783619}, {120198, 16777219}, {120199, 16777475},
2335
  {120200, 16777731}, {120201, 16777987}, {120202, 16778243}, {120203, 16778499},
2336
  {120204, 16778755}, {120205, 16779011}, {120206, 16779267}, {120207, 16779523},
2337
  {120208, 16779779}, {120209, 16780035}, {120210, 16780291}, {120211, 16780547},
2338
  {120212, 16780803}, {120213, 16781059}, {120214, 16781315}, {120215, 16781571},
2339
  {120216, 16781827}, {120217, 16782083}, {120218, 16782339}, {120219, 16782595},
2340
  {120220, 16782851}, {120221, 16783107}, {120222, 16783363}, {120223, 16783619},
2341
  {120224, 16777219}, {120225, 16777475}, {120226, 16777731}, {120227, 16777987},
2342
  {120228, 16778243}, {120229, 16778499}, {120230, 16778755}, {120231, 16779011},
2343
  {120232, 16779267}, {120233, 16779523}, {120234, 16779779}, {120235, 16780035},
2344
  {120236, 16780291}, {120237, 16780547}, {120238, 16780803}, {120239, 16781059},
2345
  {120240, 16781315}, {120241, 16781571}, {120242, 16781827}, {120243, 16782083},
2346
  {120244, 16782339}, {120245, 16782595}, {120246, 16782851}, {120247, 16783107},
2347
  {120248, 16783363}, {120249, 16783619}, {120250, 16777219}, {120251, 16777475},
2348
  {120252, 16777731}, {120253, 16777987}, {120254, 16778243}, {120255, 16778499},
2349
  {120256, 16778755}, {120257, 16779011}, {120258, 16779267}, {120259, 16779523},
2350
  {120260, 16779779}, {120261, 16780035}, {120262, 16780291}, {120263, 16780547},
2351
  {120264, 16780803}, {120265, 16781059}, {120266, 16781315}, {120267, 16781571},
2352
  {120268, 16781827}, {120269, 16782083}, {120270, 16782339}, {120271, 16782595},
2353
  {120272, 16782851}, {120273, 16783107}, {120274, 16783363}, {120275, 16783619},
2354
  {120276, 16777219}, {120277, 16777475}, {120278, 16777731}, {120279, 16777987},
2355
  {120280, 16778243}, {120281, 16778499}, {120282, 16778755}, {120283, 16779011},
2356
  {120284, 16779267}, {120285, 16779523}, {120286, 16779779}, {120287, 16780035},
2357
  {120288, 16780291}, {120289, 16780547}, {120290, 16780803}, {120291, 16781059},
2358
  {120292, 16781315}, {120293, 16781571}, {120294, 16781827}, {120295, 16782083},
2359
  {120296, 16782339}, {120297, 16782595}, {120298, 16782851}, {120299, 16783107},
2360
  {120300, 16783363}, {120301, 16783619}, {120302, 16777219}, {120303, 16777475},
2361
  {120304, 16777731}, {120305, 16777987}, {120306, 16778243}, {120307, 16778499},
2362
  {120308, 16778755}, {120309, 16779011}, {120310, 16779267}, {120311, 16779523},
2363
  {120312, 16779779}, {120313, 16780035}, {120314, 16780291}, {120315, 16780547},
2364
  {120316, 16780803}, {120317, 16781059}, {120318, 16781315}, {120319, 16781571},
2365
  {120320, 16781827}, {120321, 16782083}, {120322, 16782339}, {120323, 16782595},
2366
  {120324, 16782851}, {120325, 16783107}, {120326, 16783363}, {120327, 16783619},
2367
  {120328, 16777219}, {120329, 16777475}, {120330, 16777731}, {120331, 16777987},
2368
  {120332, 16778243}, {120333, 16778499}, {120334, 16778755}, {120335, 16779011},
2369
  {120336, 16779267}, {120337, 16779523}, {120338, 16779779}, {120339, 16780035},
2370
  {120340, 16780291}, {120341, 16780547}, {120342, 16780803}, {120343, 16781059},
2371
  {120344, 16781315}, {120345, 16781571}, {120346, 16781827}, {120347, 16782083},
2372
  {120348, 16782339}, {120349, 16782595}, {120350, 16782851}, {120351, 16783107},
2373
  {120352, 16783363}, {120353, 16783619}, {120354, 16777219}, {120355, 16777475},
2374
  {120356, 16777731}, {120357, 16777987}, {120358, 16778243}, {120359, 16778499},
2375
  {120360, 16778755}, {120361, 16779011}, {120362, 16779267}, {120363, 16779523},
2376
  {120364, 16779779}, {120365, 16780035}, {120366, 16780291}, {120367, 16780547},
2377
  {120368, 16780803}, {120369, 16781059}, {120370, 16781315}, {120371, 16781571},
2378
  {120372, 16781827}, {120373, 16782083}, {120374, 16782339}, {120375, 16782595},
2379
  {120376, 16782851}, {120377, 16783107}, {120378, 16783363}, {120379, 16783619},
2380
  {120380, 16777219}, {120381, 16777475}, {120382, 16777731}, {120383, 16777987},
2381
  {120384, 16778243}, {120385, 16778499}, {120386, 16778755}, {120387, 16779011},
2382
  {120388, 16779267}, {120389, 16779523}, {120390, 16779779}, {120391, 16780035},
2383
  {120392, 16780291}, {120393, 16780547}, {120394, 16780803}, {120395, 16781059},
2384
  {120396, 16781315}, {120397, 16781571}, {120398, 16781827}, {120399, 16782083},
2385
  {120400, 16782339}, {120401, 16782595}, {120402, 16782851}, {120403, 16783107},
2386
  {120404, 16783363}, {120405, 16783619}, {120406, 16777219}, {120407, 16777475},
2387
  {120408, 16777731}, {120409, 16777987}, {120410, 16778243}, {120411, 16778499},
2388
  {120412, 16778755}, {120413, 16779011}, {120414, 16779267}, {120415, 16779523},
2389
  {120416, 16779779}, {120417, 16780035}, {120418, 16780291}, {120419, 16780547},
2390
  {120420, 16780803}, {120421, 16781059}, {120422, 16781315}, {120423, 16781571},
2391
  {120424, 16781827}, {120425, 16782083}, {120426, 16782339}, {120427, 16782595},
2392
  {120428, 16782851}, {120429, 16783107}, {120430, 16783363}, {120431, 16783619},
2393
  {120432, 16777219}, {120433, 16777475}, {120434, 16777731}, {120435, 16777987},
2394
  {120436, 16778243}, {120437, 16778499}, {120438, 16778755}, {120439, 16779011},
2395
  {120440, 16779267}, {120441, 16779523}, {120442, 16779779}, {120443, 16780035},
2396
  {120444, 16780291}, {120445, 16780547}, {120446, 16780803}, {120447, 16781059},
2397
  {120448, 16781315}, {120449, 16781571}, {120450, 16781827}, {120451, 16782083},
2398
  {120452, 16782339}, {120453, 16782595}, {120454, 16782851}, {120455, 16783107},
2399
  {120456, 16783363}, {120457, 16783619}, {120458, 16777219}, {120459, 16777475},
2400
  {120460, 16777731}, {120461, 16777987}, {120462, 16778243}, {120463, 16778499},
2401
  {120464, 16778755}, {120465, 16779011}, {120466, 16779267}, {120467, 16779523},
2402
  {120468, 16779779}, {120469, 16780035}, {120470, 16780291}, {120471, 16780547},
2403
  {120472, 16780803}, {120473, 16781059}, {120474, 16781315}, {120475, 16781571},
2404
  {120476, 16781827}, {120477, 16782083}, {120478, 16782339}, {120479, 16782595},
2405
  {120480, 16782851}, {120481, 16783107}, {120482, 16783363}, {120483, 16783619},
2406
  {120484, 17961731}, {120485, 17961987}, {120486, 2}, {120488, 16851715},
2407
  {120489, 16851971}, {120490, 16852227}, {120491, 16852483}, {120492, 16852739},
2408
  {120493, 16852995}, {120494, 16853251}, {120495, 16853507}, {120496, 16846851},
2409
  {120497, 16853763}, {120498, 16854019}, {120499, 16786179}, {120500, 16854275},
2410
  {120501, 16854531}, {120502, 16854787}, {120503, 16855043}, {120504, 16855299},
2411
  {120505, 16853507}, {120506, 16855555}, {120507, 16855811}, {120508, 16856067},
2412
  {120509, 16856323}, {120510, 16856579}, {120511, 16856835}, {120512, 16857091},
2413
  {120513, 17962243}, {120514, 16851715}, {120515, 16851971}, {120516, 16852227},
2414
  {120517, 16852483}, {120518, 16852739}, {120519, 16852995}, {120520, 16853251},
2415
  {120521, 16853507}, {120522, 16846851}, {120523, 16853763}, {120524, 16854019},
2416
  {120525, 16786179}, {120526, 16854275}, {120527, 16854531}, {120528, 16854787},
2417
  {120529, 16855043}, {120530, 16855299}, {120531, 16855555}, {120533, 16855811},
2418
  {120534, 16856067}, {120535, 16856323}, {120536, 16856579}, {120537, 16856835},
2419
  {120538, 16857091}, {120539, 17962499}, {120540, 16852739}, {120541, 16853507},
2420
  {120542, 16853763}, {120543, 16856323}, {120544, 16855299}, {120545, 16855043},
2421
  {120546, 16851715}, {120547, 16851971}, {120548, 16852227}, {120549, 16852483},
2422
  {120550, 16852739}, {120551, 16852995}, {120552, 16853251}, {120553, 16853507},
2423
  {120554, 16846851}, {120555, 16853763}, {120556, 16854019}, {120557, 16786179},
2424
  {120558, 16854275}, {120559, 16854531}, {120560, 16854787}, {120561, 16855043},
2425
  {120562, 16855299}, {120563, 16853507}, {120564, 16855555}, {120565, 16855811},
2426
  {120566, 16856067}, {120567, 16856323}, {120568, 16856579}, {120569, 16856835},
2427
  {120570, 16857091}, {120571, 17962243}, {120572, 16851715}, {120573, 16851971},
2428
  {120574, 16852227}, {120575, 16852483}, {120576, 16852739}, {120577, 16852995},
2429
  {120578, 16853251}, {120579, 16853507}, {120580, 16846851}, {120581, 16853763},
2430
  {120582, 16854019}, {120583, 16786179}, {120584, 16854275}, {120585, 16854531},
2431
  {120586, 16854787}, {120587, 16855043}, {120588, 16855299}, {120589, 16855555},
2432
  {120591, 16855811}, {120592, 16856067}, {120593, 16856323}, {120594, 16856579},
2433
  {120595, 16856835}, {120596, 16857091}, {120597, 17962499}, {120598, 16852739},
2434
  {120599, 16853507}, {120600, 16853763}, {120601, 16856323}, {120602, 16855299},
2435
  {120603, 16855043}, {120604, 16851715}, {120605, 16851971}, {120606, 16852227},
2436
  {120607, 16852483}, {120608, 16852739}, {120609, 16852995}, {120610, 16853251},
2437
  {120611, 16853507}, {120612, 16846851}, {120613, 16853763}, {120614, 16854019},
2438
  {120615, 16786179}, {120616, 16854275}, {120617, 16854531}, {120618, 16854787},
2439
  {120619, 16855043}, {120620, 16855299}, {120621, 16853507}, {120622, 16855555},
2440
  {120623, 16855811}, {120624, 16856067}, {120625, 16856323}, {120626, 16856579},
2441
  {120627, 16856835}, {120628, 16857091}, {120629, 17962243}, {120630, 16851715},
2442
  {120631, 16851971}, {120632, 16852227}, {120633, 16852483}, {120634, 16852739},
2443
  {120635, 16852995}, {120636, 16853251}, {120637, 16853507}, {120638, 16846851},
2444
  {120639, 16853763}, {120640, 16854019}, {120641, 16786179}, {120642, 16854275},
2445
  {120643, 16854531}, {120644, 16854787}, {120645, 16855043}, {120646, 16855299},
2446
  {120647, 16855555}, {120649, 16855811}, {120650, 16856067}, {120651, 16856323},
2447
  {120652, 16856579}, {120653, 16856835}, {120654, 16857091}, {120655, 17962499},
2448
  {120656, 16852739}, {120657, 16853507}, {120658, 16853763}, {120659, 16856323},
2449
  {120660, 16855299}, {120661, 16855043}, {120662, 16851715}, {120663, 16851971},
2450
  {120664, 16852227}, {120665, 16852483}, {120666, 16852739}, {120667, 16852995},
2451
  {120668, 16853251}, {120669, 16853507}, {120670, 16846851}, {120671, 16853763},
2452
  {120672, 16854019}, {120673, 16786179}, {120674, 16854275}, {120675, 16854531},
2453
  {120676, 16854787}, {120677, 16855043}, {120678, 16855299}, {120679, 16853507},
2454
  {120680, 16855555}, {120681, 16855811}, {120682, 16856067}, {120683, 16856323},
2455
  {120684, 16856579}, {120685, 16856835}, {120686, 16857091}, {120687, 17962243},
2456
  {120688, 16851715}, {120689, 16851971}, {120690, 16852227}, {120691, 16852483},
2457
  {120692, 16852739}, {120693, 16852995}, {120694, 16853251}, {120695, 16853507},
2458
  {120696, 16846851}, {120697, 16853763}, {120698, 16854019}, {120699, 16786179},
2459
  {120700, 16854275}, {120701, 16854531}, {120702, 16854787}, {120703, 16855043},
2460
  {120704, 16855299}, {120705, 16855555}, {120707, 16855811}, {120708, 16856067},
2461
  {120709, 16856323}, {120710, 16856579}, {120711, 16856835}, {120712, 16857091},
2462
  {120713, 17962499}, {120714, 16852739}, {120715, 16853507}, {120716, 16853763},
2463
  {120717, 16856323}, {120718, 16855299}, {120719, 16855043}, {120720, 16851715},
2464
  {120721, 16851971}, {120722, 16852227}, {120723, 16852483}, {120724, 16852739},
2465
  {120725, 16852995}, {120726, 16853251}, {120727, 16853507}, {120728, 16846851},
2466
  {120729, 16853763}, {120730, 16854019}, {120731, 16786179}, {120732, 16854275},
2467
  {120733, 16854531}, {120734, 16854787}, {120735, 16855043}, {120736, 16855299},
2468
  {120737, 16853507}, {120738, 16855555}, {120739, 16855811}, {120740, 16856067},
2469
  {120741, 16856323}, {120742, 16856579}, {120743, 16856835}, {120744, 16857091},
2470
  {120745, 17962243}, {120746, 16851715}, {120747, 16851971}, {120748, 16852227},
2471
  {120749, 16852483}, {120750, 16852739}, {120751, 16852995}, {120752, 16853251},
2472
  {120753, 16853507}, {120754, 16846851}, {120755, 16853763}, {120756, 16854019},
2473
  {120757, 16786179}, {120758, 16854275}, {120759, 16854531}, {120760, 16854787},
2474
  {120761, 16855043}, {120762, 16855299}, {120763, 16855555}, {120765, 16855811},
2475
  {120766, 16856067}, {120767, 16856323}, {120768, 16856579}, {120769, 16856835},
2476
  {120770, 16857091}, {120771, 17962499}, {120772, 16852739}, {120773, 16853507},
2477
  {120774, 16853763}, {120775, 16856323}, {120776, 16855299}, {120777, 16855043},
2478
  {120778, 16858627}, {120780, 2}, {120782, 17045507}, {120783, 16786947},
2479
  {120784, 16785155}, {120785, 16785411}, {120786, 16787715}, {120787, 17045763},
2480
  {120788, 17046019}, {120789, 17046275}, {120790, 17046531}, {120791, 17046787},
2481
  {120792, 17045507}, {120793, 16786947}, {120794, 16785155}, {120795, 16785411},
2482
  {120796, 16787715}, {120797, 17045763}, {120798, 17046019}, {120799, 17046275},
2483
  {120800, 17046531}, {120801, 17046787}, {120802, 17045507}, {120803, 16786947},
2484
  {120804, 16785155}, {120805, 16785411}, {120806, 16787715}, {120807, 17045763},
2485
  {120808, 17046019}, {120809, 17046275}, {120810, 17046531}, {120811, 17046787},
2486
  {120812, 17045507}, {120813, 16786947}, {120814, 16785155}, {120815, 16785411},
2487
  {120816, 16787715}, {120817, 17045763}, {120818, 17046019}, {120819, 17046275},
2488
  {120820, 17046531}, {120821, 17046787}, {120822, 17045507}, {120823, 16786947},
2489
  {120824, 16785155}, {120825, 16785411}, {120826, 16787715}, {120827, 17045763},
2490
  {120828, 17046019}, {120829, 17046275}, {120830, 17046531}, {120831, 17046787},
2491
  {120832, 1}, {121484, 2}, {121499, 1}, {121504, 2},
2492
  {121505, 1}, {121520, 2}, {122624, 1}, {122655, 2},
2493
  {122661, 1}, {122667, 2}, {122880, 1}, {122887, 2},
2494
  {122888, 1}, {122905, 2}, {122907, 1}, {122914, 2},
2495
  {122915, 1}, {122917, 2}, {122918, 1}, {122923, 2},
2496
  {122928, 16866563}, {122929, 16866819}, {122930, 16867075}, {122931, 16867331},
2497
  {122932, 16867587}, {122933, 16867843}, {122934, 16868099}, {122935, 16868355},
2498
  {122936, 16868611}, {122937, 16869123}, {122938, 16869379}, {122939, 16869635},
2499
  {122940, 16870147}, {122941, 16870403}, {122942, 16870659}, {122943, 16870915},
2500
  {122944, 16871171}, {122945, 16871427}, {122946, 16871683}, {122947, 16871939},
2501
  {122948, 16872195}, {122949, 16872451}, {122950, 16872707}, {122951, 16873475},
2502
  {122952, 16873987}, {122953, 16874243}, {122954, 17505795}, {122955, 16889091},
2503
  {122956, 16864003}, {122957, 16864515}, {122958, 16891139}, {122959, 16883715},
2504
  {122960, 16886019}, {122961, 16866563}, {122962, 16866819}, {122963, 16867075},
2505
  {122964, 16867331}, {122965, 16867587}, {122966, 16867843}, {122967, 16868099},
2506
  {122968, 16868355}, {122969, 16868611}, {122970, 16869123}, {122971, 16869379},
2507
  {122972, 16870147}, {122973, 16870403}, {122974, 16870915}, {122975, 16871427},
2508
  {122976, 16871683}, {122977, 16871939}, {122978, 16872195}, {122979, 16872451},
2509
  {122980, 16872707}, {122981, 16873219}, {122982, 16873475}, {122983, 16879875},
2510
  {122984, 16864003}, {122985, 16863747}, {122986, 16866307}, {122987, 16883203},
2511
  {122988, 17500931}, {122989, 16883971}, {122990, 2}, {123023, 1},
2512
  {123024, 2}, {123136, 1}, {123181, 2}, {123184, 1},
2513
  {123198, 2}, {123200, 1}, {123210, 2}, {123214, 1},
2514
  {123216, 2}, {123536, 1}, {123567, 2}, {123584, 1},
2515
  {123642, 2}, {123647, 1}, {123648, 2}, {124112, 1},
2516
  {124154, 2}, {124368, 1}, {124411, 2}, {124415, 1},
2517
  {124416, 2}, {124896, 1}, {124903, 2}, {124904, 1},
2518
  {124908, 2}, {124909, 1}, {124911, 2}, {124912, 1},
2519
  {124927, 2}, {124928, 1}, {125125, 2}, {125127, 1},
2520
  {125143, 2}, {125184, 17962755}, {125185, 17963011}, {125186, 17963267},
2521
  {125187, 17963523}, {125188, 17963779}, {125189, 17964035}, {125190, 17964291},
2522
  {125191, 17964547}, {125192, 17964803}, {125193, 17965059}, {125194, 17965315},
2523
  {125195, 17965571}, {125196, 17965827}, {125197, 17966083}, {125198, 17966339},
2524
  {125199, 17966595}, {125200, 17966851}, {125201, 17967107}, {125202, 17967363},
2525
  {125203, 17967619}, {125204, 17967875}, {125205, 17968131}, {125206, 17968387},
2526
  {125207, 17968643}, {125208, 17968899}, {125209, 17969155}, {125210, 17969411},
2527
  {125211, 17969667}, {125212, 17969923}, {125213, 17970179}, {125214, 17970435},
2528
  {125215, 17970691}, {125216, 17970947}, {125217, 17971203}, {125218, 1},
2529
  {125260, 2}, {125264, 1}, {125274, 2}, {125278, 1},
2530
  {125280, 2}, {126065, 1}, {126133, 2}, {126209, 1},
2531
  {126270, 2}, {126464, 16910595}, {126465, 17695235}, {126466, 17693443},
2532
  {126467, 17846019}, {126468, 2}, {126469, 16911107}, {126470, 17743107},
2533
  {126471, 17693955}, {126472, 17711619}, {126473, 16912131}, {126474, 17720323},
2534
  {126475, 17722627}, {126476, 17694467}, {126477, 17729539}, {126478, 17706499},
2535
  {126479, 17713155}, {126480, 17715203}, {126481, 17708547}, {126482, 17718275},
2536
  {126483, 17736707}, {126484, 17756675}, {126485, 17698307}, {126486, 17701379},
2537
  {126487, 17696515}, {126488, 17736195}, {126489, 17709571}, {126490, 17712643},
2538
  {126491, 17714179}, {126492, 17971459}, {126493, 17684995}, {126494, 17971715},
2539
  {126495, 17971971}, {126496, 2}, {126497, 17695235}, {126498, 17693443},
2540
  {126499, 2}, {126500, 17732611}, {126501, 2}, {126503, 17693955},
2541
  {126504, 2}, {126505, 16912131}, {126506, 17720323}, {126507, 17722627},
2542
  {126508, 17694467}, {126509, 17729539}, {126510, 17706499}, {126511, 17713155},
2543
  {126512, 17715203}, {126513, 17708547}, {126514, 17718275}, {126515, 2},
2544
  {126516, 17756675}, {126517, 17698307}, {126518, 17701379}, {126519, 17696515},
2545
  {126520, 2}, {126521, 17709571}, {126522, 2}, {126523, 17714179},
2546
  {126524, 2}, {126530, 17693443}, {126531, 2}, {126535, 17693955},
2547
  {126536, 2}, {126537, 16912131}, {126538, 2}, {126539, 17722627},
2548
  {126540, 2}, {126541, 17729539}, {126542, 17706499}, {126543, 17713155},
2549
  {126544, 2}, {126545, 17708547}, {126546, 17718275}, {126547, 2},
2550
  {126548, 17756675}, {126549, 2}, {126551, 17696515}, {126552, 2},
2551
  {126553, 17709571}, {126554, 2}, {126555, 17714179}, {126556, 2},
2552
  {126557, 17684995}, {126558, 2}, {126559, 17971971}, {126560, 2},
2553
  {126561, 17695235}, {126562, 17693443}, {126563, 2}, {126564, 17732611},
2554
  {126565, 2}, {126567, 17693955}, {126568, 17711619}, {126569, 16912131},
2555
  {126570, 17720323}, {126571, 2}, {126572, 17694467}, {126573, 17729539},
2556
  {126574, 17706499}, {126575, 17713155}, {126576, 17715203}, {126577, 17708547},
2557
  {126578, 17718275}, {126579, 2}, {126580, 17756675}, {126581, 17698307},
2558
  {126582, 17701379}, {126583, 17696515}, {126584, 2}, {126585, 17709571},
2559
  {126586, 17712643}, {126587, 17714179}, {126588, 17971459}, {126589, 2},
2560
  {126590, 17971715}, {126591, 2}, {126592, 16910595}, {126593, 17695235},
2561
  {126594, 17693443}, {126595, 17846019}, {126596, 17732611}, {126597, 16911107},
2562
  {126598, 17743107}, {126599, 17693955}, {126600, 17711619}, {126601, 16912131},
2563
  {126602, 2}, {126603, 17722627}, {126604, 17694467}, {126605, 17729539},
2564
  {126606, 17706499}, {126607, 17713155}, {126608, 17715203}, {126609, 17708547},
2565
  {126610, 17718275}, {126611, 17736707}, {126612, 17756675}, {126613, 17698307},
2566
  {126614, 17701379}, {126615, 17696515}, {126616, 17736195}, {126617, 17709571},
2567
  {126618, 17712643}, {126619, 17714179}, {126620, 2}, {126625, 17695235},
2568
  {126626, 17693443}, {126627, 17846019}, {126628, 2}, {126629, 16911107},
2569
  {126630, 17743107}, {126631, 17693955}, {126632, 17711619}, {126633, 16912131},
2570
  {126634, 2}, {126635, 17722627}, {126636, 17694467}, {126637, 17729539},
2571
  {126638, 17706499}, {126639, 17713155}, {126640, 17715203}, {126641, 17708547},
2572
  {126642, 17718275}, {126643, 17736707}, {126644, 17756675}, {126645, 17698307},
2573
  {126646, 17701379}, {126647, 17696515}, {126648, 17736195}, {126649, 17709571},
2574
  {126650, 17712643}, {126651, 17714179}, {126652, 2}, {126704, 1},
2575
  {126706, 2}, {126976, 1}, {127020, 2}, {127024, 1},
2576
  {127124, 2}, {127136, 1}, {127151, 2}, {127153, 1},
2577
  {127168, 2}, {127169, 1}, {127184, 2}, {127185, 1},
2578
  {127222, 2}, {127233, 34749443}, {127234, 34749955}, {127235, 34750467},
2579
  {127236, 34750979}, {127237, 34751491}, {127238, 34752003}, {127239, 34752515},
2580
  {127240, 34753027}, {127241, 34753539}, {127242, 34754051}, {127243, 1},
2581
  {127248, 50655491}, {127249, 50656259}, {127250, 50657027}, {127251, 50657795},
2582
  {127252, 50658563}, {127253, 50659331}, {127254, 50660099}, {127255, 50660867},
2583
  {127256, 50661635}, {127257, 50662403}, {127258, 50663171}, {127259, 50663939},
2584
  {127260, 50664707}, {127261, 50665475}, {127262, 50666243}, {127263, 50667011},
2585
  {127264, 50667779}, {127265, 50668547}, {127266, 50669315}, {127267, 50670083},
2586
  {127268, 50670851}, {127269, 50671619}, {127270, 50672387}, {127271, 50673155},
2587
  {127272, 50673923}, {127273, 50674691}, {127274, 51531779}, {127275, 16777731},
2588
  {127276, 16781571}, {127277, 33554947}, {127278, 34755331}, {127279, 1},
2589
  {127280, 16777219}, {127281, 16777475}, {127282, 16777731}, {127283, 16777987},
2590
  {127284, 16778243}, {127285, 16778499}, {127286, 16778755}, {127287, 16779011},
2591
  {127288, 16779267}, {127289, 16779523}, {127290, 16779779}, {127291, 16780035},
2592
  {127292, 16780291}, {127293, 16780547}, {127294, 16780803}, {127295, 16781059},
2593
  {127296, 16781315}, {127297, 16781571}, {127298, 16781827}, {127299, 16782083},
2594
  {127300, 16782339}, {127301, 16782595}, {127302, 16782851}, {127303, 16783107},
2595
  {127304, 16783363}, {127305, 16783619}, {127306, 34755843}, {127307, 34237187},
2596
  {127308, 34756355}, {127309, 34756867}, {127310, 51534595}, {127311, 34758147},
2597
  {127312, 1}, {127338, 34220035}, {127339, 34200067}, {127340, 34758659},
2598
  {127341, 1}, {127376, 34759171}, {127377, 1}, {127406, 2},
2599
  {127462, 1}, {127488, 34759683}, {127489, 34760195}, {127490, 17318403},
2600
  {127491, 2}, {127504, 17168387}, {127505, 17983491}, {127506, 17983747},
2601
  {127507, 17362179}, {127508, 17153795}, {127509, 17984003}, {127510, 17984259},
2602
  {127511, 17235971}, {127512, 17984515}, {127513, 17984771}, {127514, 17985027},
2603
  {127515, 17596163}, {127516, 17985283}, {127517, 17985539}, {127518, 17985795},
2604
  {127519, 17986051}, {127520, 17986307}, {127521, 17986563}, {127522, 17177603},
2605
  {127523, 17986819}, {127524, 17987075}, {127525, 17987331}, {127526, 17987587},
2606
  {127527, 17987843}, {127528, 17988099}, {127529, 17152259}, {127530, 17233923},
2607
  {127531, 17988355}, {127532, 17299203}, {127533, 17234691}, {127534, 17299459},
2608
  {127535, 17988611}, {127536, 17191939}, {127537, 17988867}, {127538, 17989123},
2609
  {127539, 17989379}, {127540, 17989635}, {127541, 17989891}, {127542, 17274883},
2610
  {127543, 17170947}, {127544, 17990147}, {127545, 17990403}, {127546, 17990659},
2611
  {127547, 17990915}, {127548, 2}, {127552, 51545603}, {127553, 51546371},
2612
  {127554, 51547139}, {127555, 51547907}, {127556, 51548675}, {127557, 51549443},
2613
  {127558, 51550211}, {127559, 51550979}, {127560, 51551747}, {127561, 2},
2614
  {127568, 17998083}, {127569, 17998339}, {127570, 2}, {127584, 1},
2615
  {127590, 2}, {127744, 1}, {128728, 2}, {128732, 1},
2616
  {128749, 2}, {128752, 1}, {128765, 2}, {128768, 1},
2617
  {128887, 2}, {128891, 1}, {128986, 2}, {128992, 1},
2618
  {129004, 2}, {129008, 1}, {129009, 2}, {129024, 1},
2619
  {129036, 2}, {129040, 1}, {129096, 2}, {129104, 1},
2620
  {129114, 2}, {129120, 1}, {129160, 2}, {129168, 1},
2621
  {129198, 2}, {129200, 1}, {129212, 2}, {129216, 1},
2622
  {129218, 2}, {129280, 1}, {129620, 2}, {129632, 1},
2623
  {129646, 2}, {129648, 1}, {129661, 2}, {129664, 1},
2624
  {129674, 2}, {129679, 1}, {129735, 2}, {129742, 1},
2625
  {129757, 2}, {129759, 1}, {129770, 2}, {129776, 1},
2626
  {129785, 2}, {129792, 1}, {129939, 2}, {129940, 1},
2627
  {130032, 17045507}, {130033, 16786947}, {130034, 16785155}, {130035, 16785411},
2628
  {130036, 16787715}, {130037, 17045763}, {130038, 17046019}, {130039, 17046275},
2629
  {130040, 17046531}, {130041, 17046787}, {130042, 2}, {131072, 1},
2630
  {173792, 2}, {173824, 1}, {177978, 2}, {177984, 1},
2631
  {178206, 2}, {178208, 1}, {183970, 2}, {183984, 1},
2632
  {191457, 2}, {191472, 1}, {192094, 2}, {194560, 17998595},
2633
  {194561, 17998851}, {194562, 17999107}, {194563, 17999363}, {194564, 17999619},
2634
  {194565, 17619971}, {194566, 17999875}, {194567, 18000131}, {194568, 18000387},
2635
  {194569, 18000643}, {194570, 17620227}, {194571, 18000899}, {194572, 18001155},
2636
  {194573, 18001411}, {194574, 17620483}, {194575, 18001667}, {194576, 18001923},
2637
  {194577, 18002179}, {194578, 18002435}, {194579, 18002691}, {194580, 18002947},
2638
  {194581, 17985795}, {194582, 18003203}, {194583, 18003459}, {194584, 18003715},
2639
  {194585, 18003971}, {194586, 18004227}, {194587, 17634563}, {194588, 18004483},
2640
  {194589, 17156355}, {194590, 18004739}, {194591, 18004995}, {194592, 18005251},
2641
  {194593, 18005507}, {194594, 17990403}, {194595, 18005763}, {194596, 18006019},
2642
  {194597, 17635843}, {194598, 17620739}, {194599, 17620995}, {194600, 17636099},
2643
  {194601, 18006275}, {194602, 18006531}, {194603, 17574403}, {194604, 18006787},
2644
  {194605, 17621251}, {194606, 18007043}, {194607, 18007299}, {194608, 18007555},
2645
  {194609, 18007811}, {194612, 18008067}, {194613, 18008323}, {194614, 18008579},
2646
  {194615, 18008835}, {194616, 18009091}, {194617, 18009347}, {194618, 18009603},
2647
  {194619, 18009859}, {194620, 18010115}, {194621, 18010371}, {194622, 18010627},
2648
  {194623, 18010883}, {194624, 18011139}, {194625, 18011395}, {194626, 18011651},
2649
  {194627, 18011907}, {194628, 18012163}, {194629, 18012419}, {194631, 17636611},
2650
  {194632, 18012675}, {194633, 18012931}, {194634, 18013187}, {194635, 18013443},
2651
  {194636, 17621763}, {194637, 18013699}, {194638, 18013955}, {194639, 18014211},
2652
  {194640, 17611523}, {194641, 18014467}, {194642, 18014723}, {194643, 18014979},
2653
  {194644, 18015235}, {194645, 18015491}, {194646, 18015747}, {194647, 18016003},
2654
  {194648, 18016259}, {194649, 18016515}, {194650, 18016771}, {194651, 18017027},
2655
  {194652, 18017283}, {194653, 17984003}, {194654, 18017539}, {194655, 18017795},
2656
  {194656, 18018051}, {194657, 18018307}, {194658, 18018563}, {194659, 18018819},
2657
  {194660, 18019075}, {194661, 18019331}, {194662, 18019587}, {194663, 18019843},
2658
  {194664, 18020099}, {194665, 18020355}, {194666, 18020611}, {194668, 18020867},
2659
  {194669, 18021123}, {194670, 18021379}, {194671, 17573379}, {194672, 18021635},
2660
  {194673, 18021891}, {194674, 18022147}, {194675, 18022403}, {194676, 18022659},
2661
  {194677, 17163011}, {194678, 18022915}, {194679, 18023171}, {194680, 17163523},
2662
  {194681, 18023427}, {194682, 18023683}, {194683, 18023939}, {194684, 18024195},
2663
  {194685, 18024451}, {194686, 18024707}, {194687, 18024963}, {194688, 18025219},
2664
  {194689, 18025475}, {194690, 18025731}, {194691, 18025987}, {194692, 18026243},
2665
  {194693, 18026499}, {194694, 18026755}, {194695, 18027011}, {194696, 18027267},
2666
  {194697, 18027523}, {194698, 18027779}, {194699, 18028035}, {194700, 18028291},
2667
  {194701, 18028547}, {194702, 17560067}, {194703, 18028803}, {194704, 17166083},
2668
  {194705, 18029059}, {194707, 18029315}, {194708, 18029571}, {194710, 18029827},
2669
  {194711, 18030083}, {194712, 18030339}, {194713, 18030595}, {194714, 18030851},
2670
  {194715, 18031107}, {194716, 18031363}, {194717, 18031619}, {194718, 18031875},
2671
  {194719, 18032131}, {194720, 18032387}, {194721, 18032643}, {194722, 18032899},
2672
  {194723, 17623043}, {194724, 18033155}, {194725, 18033411}, {194726, 18033667},
2673
  {194727, 18033923}, {194728, 17639683}, {194729, 18033923}, {194730, 18034179},
2674
  {194731, 17623555}, {194732, 18034435}, {194733, 18034691}, {194734, 18034947},
2675
  {194735, 18035203}, {194736, 17623811}, {194737, 17553155}, {194738, 17425411},
2676
  {194739, 18035459}, {194740, 18035715}, {194741, 18035971}, {194742, 18036227},
2677
  {194743, 18036483}, {194744, 18036739}, {194745, 18036995}, {194746, 18037251},
2678
  {194747, 18037507}, {194748, 18037763}, {194749, 18038019}, {194750, 18038275},
2679
  {194751, 18038531}, {194752, 18038787}, {194753, 18039043}, {194754, 18039299},
2680
  {194755, 18039555}, {194756, 18039811}, {194757, 18040067}, {194758, 18040323},
2681
  {194759, 18040579}, {194760, 17624067}, {194761, 18040835}, {194762, 18041091},
2682
  {194763, 18041347}, {194764, 18041603}, {194765, 18041859}, {194766, 18042115},
2683
  {194767, 17624579}, {194768, 18042371}, {194769, 18042627}, {194770, 18042883},
2684
  {194771, 18043139}, {194772, 18043395}, {194773, 18043651}, {194774, 18043907},
2685
  {194775, 18044163}, {194776, 17560323}, {194777, 17641731}, {194778, 18044419},
2686
  {194779, 18044675}, {194780, 18044931}, {194781, 18045187}, {194782, 18045443},
2687
  {194783, 18045699}, {194784, 18045955}, {194785, 18046211}, {194786, 17624835},
2688
  {194787, 18046467}, {194788, 18046723}, {194789, 18046979}, {194790, 18047235},
2689
  {194791, 17652483}, {194792, 18047491}, {194793, 18047747}, {194794, 18048003},
2690
  {194795, 18048259}, {194796, 18048515}, {194797, 18048771}, {194798, 18049027},
2691
  {194799, 18049283}, {194800, 18049539}, {194801, 18049795}, {194802, 18050051},
2692
  {194803, 18050307}, {194804, 18050563}, {194805, 17577731}, {194806, 18050819},
2693
  {194807, 18051075}, {194808, 18051331}, {194809, 18051587}, {194810, 18051843},
2694
  {194811, 18052099}, {194812, 18052355}, {194813, 18052611}, {194814, 18052867},
2695
  {194815, 18053123}, {194816, 18053379}, {194817, 17625091}, {194818, 17598723},
2696
  {194819, 18053635}, {194820, 18053891}, {194821, 18054147}, {194822, 18054403},
2697
  {194823, 18054659}, {194824, 18054915}, {194825, 18055171}, {194826, 18055427},
2698
  {194827, 17642499}, {194828, 18055683}, {194829, 18055939}, {194830, 18056195},
2699
  {194831, 18056451}, {194832, 18056707}, {194833, 18056963}, {194834, 18057219},
2700
  {194835, 18057475}, {194836, 17642755}, {194837, 18057731}, {194838, 18057987},
2701
  {194839, 18058243}, {194840, 18058499}, {194841, 18058755}, {194842, 18059011},
2702
  {194843, 18059267}, {194844, 18059523}, {194845, 18059779}, {194846, 18060035},
2703
  {194847, 18060291}, {194848, 18060547}, {194849, 17643267}, {194850, 18060803},
2704
  {194851, 18061059}, {194852, 18061315}, {194853, 18061571}, {194854, 18061827},
2705
  {194855, 18062083}, {194856, 18062339}, {194857, 18062595}, {194858, 18062851},
2706
  {194859, 18063107}, {194860, 18063363}, {194862, 18063619}, {194863, 18063875},
2707
  {194864, 17643779}, {194865, 18064131}, {194866, 18064387}, {194867, 18064643},
2708
  {194868, 18064899}, {194869, 18065155}, {194870, 18065411}, {194871, 18065667},
2709
  {194872, 17574147}, {194873, 18065923}, {194874, 18066179}, {194875, 18066435},
2710
  {194876, 18066691}, {194877, 18066947}, {194878, 18067203}, {194879, 18067459},
2711
  {194880, 17645315}, {194881, 18067715}, {194882, 18067971}, {194883, 18068227},
2712
  {194884, 18068483}, {194885, 18068739}, {194886, 18068995}, {194888, 17645571},
2713
  {194889, 17652995}, {194890, 18069251}, {194891, 18069507}, {194892, 18069763},
2714
  {194893, 18070019}, {194894, 18070275}, {194895, 17564675}, {194896, 17646083},
2715
  {194897, 18070531}, {194898, 18070787}, {194899, 17627651}, {194900, 18071043},
2716
  {194901, 18071299}, {194902, 17616643}, {194903, 18071555}, {194904, 18071811},
2717
  {194905, 17628419}, {194906, 18072067}, {194907, 18072323}, {194908, 18072579},
2718
  {194909, 18072835}, {194911, 18073091}, {194912, 18073347}, {194913, 18073603},
2719
  {194914, 18073859}, {194915, 18074115}, {194916, 18074371}, {194917, 18074627},
2720
  {194918, 18074883}, {194919, 18075139}, {194920, 18075395}, {194921, 18075651},
2721
  {194922, 18075907}, {194923, 18076163}, {194924, 18076419}, {194925, 18076675},
2722
  {194926, 18076931}, {194927, 18077187}, {194928, 18077443}, {194929, 18077699},
2723
  {194930, 18077955}, {194931, 18078211}, {194932, 18078467}, {194933, 18078723},
2724
  {194934, 18078979}, {194935, 18079235}, {194936, 18079491}, {194937, 18079747},
2725
  {194938, 17629955}, {194939, 18080003}, {194940, 18080259}, {194941, 18080515},
2726
  {194942, 18080771}, {194943, 18081027}, {194944, 18081283}, {194945, 18081539},
2727
  {194946, 18081795}, {194947, 18082051}, {194948, 18082307}, {194949, 18082563},
2728
  {194950, 18082819}, {194951, 18083075}, {194952, 18083331}, {194953, 18083587},
2729
  {194954, 18083843}, {194955, 18029315}, {194956, 18084099}, {194957, 18084355},
2730
  {194958, 18084611}, {194959, 18084867}, {194960, 18085123}, {194961, 18085379},
2731
  {194962, 18085635}, {194963, 18085891}, {194964, 18086147}, {194965, 18086403},
2732
  {194966, 18086659}, {194967, 18086915}, {194968, 17578499}, {194969, 18087171},
2733
  {194970, 18087427}, {194971, 18087683}, {194972, 18087939}, {194973, 18088195},
2734
  {194974, 18088451}, {194975, 17630723}, {194976, 18088707}, {194977, 18088963},
2735
  {194978, 18089219}, {194979, 18089475}, {194980, 18089731}, {194981, 18089987},
2736
  {194982, 18090243}, {194983, 18090499}, {194984, 18090755}, {194985, 18091011},
2737
  {194986, 18091267}, {194987, 18091523}, {194988, 18091779}, {194989, 18092035},
2738
  {194990, 18092291}, {194991, 18092547}, {194992, 18092803}, {194993, 18093059},
2739
  {194994, 18093315}, {194995, 18093571}, {194996, 17563395}, {194997, 18093827},
2740
  {194998, 18094083}, {194999, 18094339}, {195000, 18094595}, {195001, 18094851},
2741
  {195002, 18095107}, {195003, 17647875}, {195004, 18095363}, {195005, 18095619},
2742
  {195006, 18095875}, {195007, 18096131}, {195008, 18096387}, {195009, 18096643},
2743
  {195010, 18096899}, {195011, 18097155}, {195012, 17189123}, {195013, 18097411},
2744
  {195014, 18097667}, {195015, 18097923}, {195016, 18098179}, {195017, 18098435},
2745
  {195018, 18098691}, {195019, 18098947}, {195020, 18099203}, {195021, 18099459},
2746
  {195022, 18099715}, {195023, 18099971}, {195024, 17649155}, {195025, 17649411},
2747
  {195026, 17190915}, {195027, 18100227}, {195028, 18100483}, {195029, 18100739},
2748
  {195030, 18100995}, {195031, 18101251}, {195032, 18101507}, {195033, 18101763},
2749
  {195034, 18102019}, {195035, 18102275}, {195036, 18102531}, {195037, 18102787},
2750
  {195038, 18103043}, {195039, 17649667}, {195040, 18103299}, {195041, 18103555},
2751
  {195042, 18103811}, {195043, 18104067}, {195044, 18104323}, {195045, 18104579},
2752
  {195046, 18104835}, {195047, 18105091}, {195048, 18105347}, {195049, 18105603},
2753
  {195050, 18105859}, {195051, 18106115}, {195052, 18106371}, {195053, 18106627},
2754
  {195054, 18106883}, {195055, 18107139}, {195056, 18107395}, {195057, 18107651},
2755
  {195058, 18107907}, {195059, 18108163}, {195060, 18108419}, {195061, 18108675},
2756
  {195062, 18108931}, {195063, 18109187}, {195064, 18109443}, {195065, 18109699},
2757
  {195066, 18109955}, {195067, 18110211}, {195068, 18110467}, {195069, 18110723},
2758
  {195070, 17651203}, {195072, 18110979}, {195073, 18111235}, {195074, 18111491},
2759
  {195075, 18111747}, {195076, 18112003}, {195077, 18112259}, {195078, 18112515},
2760
  {195079, 18112771}, {195080, 18113027}, {195081, 18113283}, {195082, 17651459},
2761
  {195083, 18113539}, {195084, 18113795}, {195085, 18114051}, {195086, 18114307},
2762
  {195087, 18114563}, {195088, 18114819}, {195089, 18115075}, {195090, 18115331},
2763
  {195091, 18115587}, {195092, 18115843}, {195093, 17203203}, {195094, 18116099},
2764
  {195095, 17204227}, {195096, 18116355}, {195097, 18116611}, {195098, 18116867},
2765
  {195099, 18117123}, {195100, 17205507}, {195101, 18117379}, {195102, 2},
2766
  {196608, 1}, {201547, 2}, {201552, 1}, {205744, 2},
2767
  {917760, 0}, {918000, 2}
2768
};
2769
2770
2771
} // namespace ada::idna
2772
#endif // ADA_IDNA_TABLES_H
2773
/* end file src/mapping_tables.cpp */
2774
2775
namespace ada::idna {
2776
2777
// This can be greatly accelerated. For now we just use a simply
2778
// binary search. In practice, you should *not* do that.
2779
213k
uint32_t find_range_index(uint32_t key) {
2780
  ////////////////
2781
  // This could be implemented with std::lower_bound, but we roll our own
2782
  // because we want to allow further optimizations in the future.
2783
  ////////////////
2784
213k
  uint32_t len = std::size(table);
2785
213k
  uint32_t low = 0;
2786
213k
  uint32_t high = len - 1;
2787
2.86M
  while (low <= high) {
2788
2.74M
    uint32_t middle_index = (low + high) >> 1;  // cannot overflow
2789
2.74M
    uint32_t middle_value = table[middle_index][0];
2790
2.74M
    if (middle_value < key) {
2791
898k
      low = middle_index + 1;
2792
1.84M
    } else if (middle_value > key) {
2793
1.75M
      high = middle_index - 1;
2794
1.75M
    } else {
2795
95.2k
      return middle_index;  // perfect match
2796
95.2k
    }
2797
2.74M
  }
2798
118k
  return low == 0 ? 0 : low - 1;
2799
213k
}
2800
2801
6.80k
void ascii_map(char* input, size_t length) {
2802
20.4k
  auto broadcast = [](uint8_t v) -> uint64_t {
2803
20.4k
    return 0x101010101010101ull * v;
2804
20.4k
  };
2805
6.80k
  uint64_t broadcast_80 = broadcast(0x80);
2806
6.80k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
2807
6.80k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2808
6.80k
  size_t i = 0;
2809
2810
17.4k
  for (; i + 7 < length; i += 8) {
2811
10.6k
    uint64_t word{};
2812
10.6k
    memcpy(&word, input + i, sizeof(word));
2813
10.6k
    word ^=
2814
10.6k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2815
10.6k
    memcpy(input + i, &word, sizeof(word));
2816
10.6k
  }
2817
6.80k
  if (i < length) {
2818
6.29k
    uint64_t word{};
2819
6.29k
    memcpy(&word, input + i, length - i);
2820
6.29k
    word ^=
2821
6.29k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2822
6.29k
    memcpy(input + i, &word, length - i);
2823
6.29k
  }
2824
6.80k
}
2825
2826
// Map the characters according to IDNA, returning the empty string on error.
2827
14.0k
std::u32string map(std::u32string_view input) {
2828
  //  [Map](https://www.unicode.org/reports/tr46/#ProcessingStepMap).
2829
  //  For each code point in the domain_name string, look up the status
2830
  //  value in Section 5, [IDNA Mapping
2831
  //  Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table),
2832
  //  and take the following actions:
2833
  //    * disallowed: Leave the code point unchanged in the string, and
2834
  //    record that there was an error.
2835
  //    * ignored: Remove the code point from the string. This is
2836
  //    equivalent to mapping the code point to an empty string.
2837
  //    * mapped: Replace the code point in the string by the value for
2838
  //    the mapping in Section 5, [IDNA Mapping
2839
  //    Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table).
2840
  //    * valid: Leave the code point unchanged in the string.
2841
14.0k
  static std::u32string error = U"";
2842
14.0k
  std::u32string answer;
2843
14.0k
  answer.reserve(input.size());
2844
213k
  for (char32_t x : input) {
2845
213k
    size_t index = find_range_index(x);
2846
213k
    uint32_t descriptor = table[index][1];
2847
213k
    uint8_t code = uint8_t(descriptor);
2848
213k
    switch (code) {
2849
586
      case 0:
2850
586
        break;  // nothing to do, ignored
2851
123k
      case 1:
2852
123k
        answer.push_back(x);  // valid, we just copy it to output
2853
123k
        break;
2854
434
      case 2:
2855
434
        return error;  // disallowed
2856
      // case 3 :
2857
88.7k
      default:
2858
        // We have a mapping
2859
88.7k
        {
2860
88.7k
          size_t char_count = (descriptor >> 24);
2861
88.7k
          uint16_t char_index = uint16_t(descriptor >> 8);
2862
625k
          for (size_t idx = char_index; idx < char_index + char_count; idx++) {
2863
536k
            answer.push_back(mappings[idx]);
2864
536k
          }
2865
88.7k
        }
2866
213k
    }
2867
213k
  }
2868
13.5k
  return answer;
2869
14.0k
}
2870
}  // namespace ada::idna
2871
/* end file src/mapping.cpp */
2872
/* begin file src/normalization.cpp */
2873
/* begin file src/normalization_tables.cpp */
2874
// IDNA  15.0.0
2875
2876
// clang-format off
2877
#ifndef ADA_IDNA_NORMALIZATION_TABLES_H
2878
#define ADA_IDNA_NORMALIZATION_TABLES_H
2879
#include <cstdint>
2880
2881
/**
2882
 * Unicode Standard Annex #15
2883
 *
2884
 * UNICODE NORMALIZATION FORMS
2885
 * https://www.unicode.org/reports/tr15/
2886
 *
2887
 * See https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/data/data_norm.h for reference.
2888
 */
2889
2890
namespace ada::idna {
2891
2892
const uint8_t decomposition_index[4352] = {
2893
    0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  9,  10, 11, 12, 13, 14, 15, 7,  7,
2894
    7,  7,  7,  7,  7,  7,  7,  7,  16, 7,  17, 18, 19, 20, 21, 22, 23, 24, 7,
2895
    7,  7,  7,  7,  25, 7,  26, 27, 28, 29, 30, 31, 32, 33, 7,  7,  7,  7,  7,
2896
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2897
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2898
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2899
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2900
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2901
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  34, 35, 7,  7,  7,
2902
    36, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2903
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2904
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2905
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2906
    7,  7,  37, 38, 39, 40, 41, 42, 43, 7,  7,  7,  7,  7,  7,  7,  44, 7,  7,
2907
    7,  7,  7,  7,  7,  7,  45, 46, 7,  47, 48, 49, 7,  7,  7,  50, 7,  7,  7,
2908
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2909
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2910
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2911
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2912
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2913
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2914
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2915
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2916
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2917
    7,  7,  7,  7,  7,  7,  7,  7,  7,  51, 7,  52, 53, 54, 55, 56, 7,  7,  7,
2918
    7,  7,  7,  7,  7,  57, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  58,
2919
    59, 7,  60, 61, 62, 7,  7,  7,  7,  7,  7,  7,  7,  63, 7,  7,  7,  7,  7,
2920
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2921
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2922
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2923
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2924
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2925
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2926
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2927
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2928
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2929
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2930
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2931
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2932
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2933
    64, 65, 66, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2934
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2935
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2936
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2937
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2938
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2939
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2940
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2941
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2942
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2943
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2944
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2945
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2946
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2947
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2948
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2949
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2950
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2951
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2952
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2953
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2954
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2955
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2956
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2957
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2958
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2959
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2960
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2961
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2962
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2963
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2964
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2965
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2966
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2967
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2968
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2969
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2970
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2971
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2972
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2973
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2974
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2975
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2976
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2977
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2978
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2979
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2980
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2981
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2982
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2983
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2984
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2985
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2986
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2987
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2988
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2989
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2990
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2991
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2992
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2993
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2994
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2995
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2996
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2997
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2998
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2999
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3000
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3001
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3002
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3003
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3004
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3005
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3006
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3007
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3008
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3009
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3010
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3011
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3012
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3013
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3014
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3015
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3016
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3017
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3018
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3019
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3020
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3021
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3022
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3023
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3024
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3025
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3026
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3027
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3028
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3029
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3030
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3031
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3032
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3033
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3034
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3035
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3036
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3037
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3038
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3039
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3040
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3041
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3042
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3043
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3044
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3045
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3046
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3047
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3048
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3049
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3050
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3051
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3052
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3053
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3054
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3055
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3056
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3057
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3058
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3059
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3060
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3061
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3062
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3063
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3064
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3065
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3066
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3067
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3068
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3069
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3070
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3071
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3072
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3073
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3074
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3075
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3076
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3077
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3078
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3079
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3080
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3081
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3082
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3083
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3084
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3085
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3086
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3087
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3088
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3089
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3090
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3091
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3092
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3093
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3094
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3095
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3096
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3097
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3098
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3099
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3100
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3101
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3102
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3103
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3104
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3105
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3106
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3107
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3108
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3109
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3110
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3111
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3112
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3113
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3114
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3115
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3116
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3117
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3118
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3119
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3120
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3121
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3122
    7};
3123
3124
const uint16_t decomposition_block[67][257] = {
3125
    {4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3126
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3127
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3128
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3129
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3130
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3131
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3132
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3133
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3134
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3135
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   5,   8,   8,   8,   8,
3136
     8,   8,   8,   9,   16,  17,  20,  20,  20,  20,  21,  28,  28,  29,  33,
3137
     37,  45,  48,  48,  49,  57,  61,  64,  65,  77,  89,  100, 100, 108, 116,
3138
     124, 132, 140, 148, 148, 156, 164, 172, 180, 188, 196, 204, 212, 220, 220,
3139
     228, 236, 244, 252, 260, 268, 268, 268, 276, 284, 292, 300, 308, 308, 308,
3140
     316, 324, 332, 340, 348, 356, 356, 364, 372, 380, 388, 396, 404, 412, 420,
3141
     428, 428, 436, 444, 452, 460, 468, 476, 476, 476, 484, 492, 500, 508, 516,
3142
     516, 524},
3143
    {524,  532,  540,  548,  556,  564,  572,  580,  588,  596,  604,  612,
3144
     620,  628,  636,  644,  652,  652,  652,  660,  668,  676,  684,  692,
3145
     700,  708,  716,  724,  732,  740,  748,  756,  764,  772,  780,  788,
3146
     796,  804,  812,  812,  812,  820,  828,  836,  844,  852,  860,  868,
3147
     876,  884,  885,  893,  900,  908,  916,  924,  932,  932,  940,  948,
3148
     956,  964,  972,  981,  989,  996,  996,  996,  1004, 1012, 1020, 1028,
3149
     1036, 1045, 1052, 1052, 1052, 1060, 1068, 1076, 1084, 1092, 1100, 1100,
3150
     1100, 1108, 1116, 1124, 1132, 1140, 1148, 1156, 1164, 1172, 1180, 1188,
3151
     1196, 1204, 1212, 1220, 1228, 1236, 1244, 1244, 1244, 1252, 1260, 1268,
3152
     1276, 1284, 1292, 1300, 1308, 1316, 1324, 1332, 1340, 1348, 1356, 1364,
3153
     1372, 1380, 1388, 1396, 1404, 1412, 1420, 1429, 1432, 1432, 1432, 1432,
3154
     1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3155
     1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3156
     1432, 1432, 1432, 1432, 1432, 1440, 1448, 1448, 1448, 1448, 1448, 1448,
3157
     1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1456, 1464, 1464, 1464,
3158
     1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464,
3159
     1464, 1464, 1464, 1464, 1465, 1477, 1489, 1501, 1509, 1517, 1525, 1533,
3160
     1541, 1548, 1556, 1564, 1572, 1580, 1588, 1596, 1604, 1612, 1624, 1636,
3161
     1648, 1660, 1672, 1684, 1696, 1708, 1708, 1720, 1732, 1744, 1756, 1764,
3162
     1772, 1772, 1772, 1780, 1788, 1796, 1804, 1812, 1820, 1832, 1844, 1852,
3163
     1860, 1869, 1877, 1885, 1892, 1900, 1908, 1908, 1908, 1916, 1924, 1936,
3164
     1948, 1956, 1964, 1972, 1980},
3165
    {1980, 1988, 1996, 2004, 2012, 2020, 2028, 2036, 2044, 2052, 2060, 2068,
3166
     2076, 2084, 2092, 2100, 2108, 2116, 2124, 2132, 2140, 2148, 2156, 2164,
3167
     2172, 2180, 2188, 2196, 2204, 2204, 2204, 2212, 2220, 2220, 2220, 2220,
3168
     2220, 2220, 2220, 2228, 2236, 2244, 2252, 2264, 2276, 2288, 2300, 2308,
3169
     2316, 2328, 2340, 2348, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3170
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3171
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3172
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3173
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3174
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3175
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3176
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3177
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3178
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3179
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2357, 2361, 2365, 2369,
3180
     2373, 2377, 2381, 2385, 2389, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3181
     2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3182
     2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3183
     2393, 2401, 2409, 2417, 2425, 2433, 2440, 2440, 2441, 2445, 2449, 2453,
3184
     2457, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3185
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3186
     2460, 2460, 2460, 2460, 2460},
3187
    {2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3188
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3189
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3190
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3191
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3192
     2460, 2460, 2460, 2460, 2460, 2464, 2468, 2468, 2472, 2480, 2480, 2480,
3193
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3194
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3195
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3196
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2484, 2484, 2484,
3197
     2484, 2484, 2485, 2492, 2492, 2492, 2492, 2496, 2496, 2496, 2496, 2496,
3198
     2497, 2506, 2512, 2520, 2524, 2532, 2540, 2548, 2548, 2556, 2556, 2564,
3199
     2572, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3200
     2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3201
     2584, 2584, 2584, 2592, 2600, 2608, 2616, 2624, 2632, 2644, 2644, 2644,
3202
     2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644,
3203
     2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2652,
3204
     2660, 2668, 2676, 2684, 2685, 2689, 2693, 2698, 2706, 2713, 2717, 2720,
3205
     2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3206
     2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3207
     2721, 2725, 2729, 2732, 2733, 2737, 2740, 2740, 2740, 2741, 2744, 2744,
3208
     2744, 2744, 2744, 2744, 2744},
3209
    {2744, 2752, 2760, 2760, 2768, 2768, 2768, 2768, 2776, 2776, 2776, 2776,
3210
     2776, 2784, 2792, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800,
3211
     2800, 2800, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3212
     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3213
     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2816, 2816,
3214
     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816,
3215
     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2824, 2832, 2832,
3216
     2840, 2840, 2840, 2840, 2848, 2848, 2848, 2848, 2848, 2856, 2864, 2872,
3217
     2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872,
3218
     2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2880,
3219
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3220
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3221
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3222
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3223
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3224
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3225
     2888, 2888, 2896, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904,
3226
     2904, 2904, 2904, 2904, 2904, 2912, 2920, 2928, 2936, 2936, 2936, 2944,
3227
     2952, 2952, 2952, 2960, 2968, 2976, 2984, 2992, 3000, 3000, 3000, 3008,
3228
     3016, 3024, 3032, 3040, 3048, 3048, 3048, 3056, 3064, 3072, 3080, 3088,
3229
     3096, 3104, 3112, 3120, 3128, 3136, 3144, 3144, 3144, 3152, 3160, 3160,
3230
     3160, 3160, 3160, 3160, 3160},
3231
    {3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3232
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3233
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3234
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3235
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3236
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3237
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3238
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3239
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3240
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3241
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3242
     3160, 3160, 3160, 3161, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3243
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3244
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3245
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3246
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3247
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3248
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3249
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3250
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3251
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3252
     3168, 3168, 3168, 3168, 3168},
3253
    {3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3254
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3255
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3176,
3256
     3184, 3192, 3200, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3257
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3258
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3259
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3260
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3261
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3262
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3209, 3217, 3225,
3263
     3233, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3264
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3265
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3266
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3267
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3268
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3269
     3240, 3248, 3248, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256,
3270
     3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3264, 3264, 3264, 3264,
3271
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3272
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3273
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3274
     3264, 3264, 3264, 3264, 3264},
3275
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3276
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3277
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3278
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3279
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3280
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3281
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3282
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3283
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3284
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3285
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
3286
    {3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3287
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3288
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3289
     3264, 3264, 3264, 3264, 3264, 3264, 3272, 3272, 3272, 3272, 3272, 3272,
3290
     3272, 3272, 3280, 3280, 3280, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3291
     3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3292
     3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3293
     3288, 3288, 3288, 3288, 3288, 3296, 3304, 3312, 3320, 3328, 3336, 3344,
3294
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3295
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3296
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3297
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3298
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3299
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3300
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3301
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3302
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3303
     3360, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368,
3304
     3368, 3368, 3368, 3368, 3368, 3376, 3384, 3384, 3392, 3392, 3392, 3392,
3305
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3306
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3307
     3392, 3392, 3392, 3392, 3392},
3308
    {3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3309
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3310
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3311
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3312
     3392, 3392, 3392, 3392, 3400, 3400, 3400, 3408, 3408, 3408, 3408, 3408,
3313
     3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3314
     3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3315
     3408, 3408, 3408, 3408, 3408, 3408, 3416, 3424, 3432, 3432, 3432, 3440,
3316
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3317
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3318
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3319
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3320
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3321
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3322
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3323
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3324
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3325
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3326
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3327
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3328
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3329
     3440, 3440, 3440, 3440, 3440},
3330
    {3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3331
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3332
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3333
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3334
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3335
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3336
     3440, 3448, 3448, 3448, 3456, 3464, 3464, 3464, 3464, 3464, 3464, 3464,
3337
     3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3472, 3480, 3480,
3338
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3339
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3340
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3341
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3342
     3480, 3480, 3480, 3480, 3480, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3343
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3344
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3345
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3346
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3496,
3347
     3504, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3348
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3349
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3350
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3351
     3512, 3512, 3512, 3512, 3512},
3352
    {3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3353
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3354
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3355
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3356
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3357
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3358
     3512, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3359
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3360
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3361
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3362
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3363
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3364
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3365
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3366
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3367
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3368
     3520, 3528, 3528, 3528, 3528, 3528, 3528, 3528, 3536, 3544, 3544, 3552,
3369
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3370
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3371
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3372
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3373
     3564, 3564, 3564, 3564, 3564},
3374
    {3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3375
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3376
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3377
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3378
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3379
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3380
     3564, 3564, 3564, 3572, 3580, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3381
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3382
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3383
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3384
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3385
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3386
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3387
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3388
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3389
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3390
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3391
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3392
     3588, 3588, 3588, 3596, 3596, 3604, 3616, 3624, 3624, 3624, 3624, 3624,
3393
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3394
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3395
     3624, 3624, 3624, 3624, 3624},
3396
    {3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3397
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3398
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3399
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3400
     3624, 3624, 3624, 3625, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3401
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3402
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3403
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3404
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3405
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3406
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3407
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3408
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3409
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3410
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3633,
3411
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3412
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3413
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3414
     3640, 3640, 3640, 3640, 3641, 3649, 3656, 3656, 3656, 3656, 3656, 3656,
3415
     3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3416
     3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3417
     3656, 3656, 3656, 3656, 3656},
3418
    {3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3419
     3657, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3420
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3421
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3422
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3423
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3668, 3668, 3668, 3668,
3424
     3668, 3668, 3668, 3668, 3668, 3668, 3676, 3676, 3676, 3676, 3676, 3684,
3425
     3684, 3684, 3684, 3684, 3692, 3692, 3692, 3692, 3692, 3700, 3700, 3700,
3426
     3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3708, 3708,
3427
     3708, 3708, 3708, 3708, 3708, 3708, 3708, 3708, 3716, 3716, 3724, 3733,
3428
     3744, 3753, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3772, 3772,
3429
     3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772,
3430
     3772, 3772, 3772, 3772, 3780, 3780, 3780, 3780, 3780, 3780, 3780, 3780,
3431
     3780, 3780, 3788, 3788, 3788, 3788, 3788, 3796, 3796, 3796, 3796, 3796,
3432
     3804, 3804, 3804, 3804, 3804, 3812, 3812, 3812, 3812, 3812, 3812, 3812,
3433
     3812, 3812, 3812, 3812, 3812, 3812, 3820, 3820, 3820, 3820, 3820, 3820,
3434
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3435
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3436
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3437
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3438
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3439
     3820, 3820, 3820, 3820, 3820},
3440
    {3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3441
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3442
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3443
     3820, 3820, 3820, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3444
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3445
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3446
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3447
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3448
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3449
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3450
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3451
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3452
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3453
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3454
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3455
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3456
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3457
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3458
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3459
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3460
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3461
     3829, 3832, 3832, 3832, 3832},
3462
    {3832, 3832, 3832, 3832, 3832, 3832, 3832, 3840, 3840, 3848, 3848, 3856,
3463
     3856, 3864, 3864, 3872, 3872, 3872, 3872, 3880, 3880, 3880, 3880, 3880,
3464
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3465
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3466
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3467
     3888, 3888, 3896, 3896, 3896, 3904, 3912, 3912, 3920, 3920, 3920, 3920,
3468
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3469
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3470
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3471
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3472
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3473
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3474
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3475
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3476
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3477
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3478
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3479
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3480
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3481
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3482
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3483
     3920, 3920, 3920, 3920, 3920},
3484
    {3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3485
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3486
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3487
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3921, 3925, 3929, 3932,
3488
     3933, 3937, 3941, 3945, 3949, 3953, 3957, 3961, 3965, 3969, 3973, 3976,
3489
     3977, 3981, 3985, 3989, 3993, 3997, 4001, 4005, 4009, 4013, 4017, 4021,
3490
     4025, 4029, 4033, 4037, 4041, 4045, 4048, 4049, 4053, 4057, 4061, 4065,
3491
     4069, 4073, 4077, 4081, 4085, 4089, 4093, 4097, 4101, 4105, 4109, 4113,
3492
     4117, 4121, 4125, 4129, 4133, 4137, 4141, 4145, 4149, 4153, 4157, 4160,
3493
     4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160,
3494
     4161, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3495
     4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3496
     4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4165,
3497
     4169, 4173, 4177, 4181, 4185, 4189, 4193, 4197, 4201, 4205, 4209, 4213,
3498
     4217, 4221, 4225, 4229, 4233, 4237, 4241, 4245, 4249, 4253, 4257, 4261,
3499
     4265, 4269, 4273, 4277, 4281, 4285, 4289, 4293, 4297, 4301, 4305, 4309,
3500
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3501
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3502
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3503
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3504
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3505
     4312, 4312, 4312, 4312, 4312},
3506
    {4312, 4320, 4328, 4336, 4344, 4352, 4360, 4368, 4376, 4388, 4400, 4408,
3507
     4416, 4424, 4432, 4440, 4448, 4456, 4464, 4472, 4480, 4492, 4504, 4516,
3508
     4528, 4536, 4544, 4552, 4560, 4572, 4584, 4592, 4600, 4608, 4616, 4624,
3509
     4632, 4640, 4648, 4656, 4664, 4672, 4680, 4688, 4696, 4704, 4712, 4724,
3510
     4736, 4744, 4752, 4760, 4768, 4776, 4784, 4792, 4800, 4812, 4824, 4832,
3511
     4840, 4848, 4856, 4864, 4872, 4880, 4888, 4896, 4904, 4912, 4920, 4928,
3512
     4936, 4944, 4952, 4960, 4968, 4980, 4992, 5004, 5016, 5028, 5040, 5052,
3513
     5064, 5072, 5080, 5088, 5096, 5104, 5112, 5120, 5128, 5140, 5152, 5160,
3514
     5168, 5176, 5184, 5192, 5200, 5212, 5224, 5236, 5248, 5260, 5272, 5280,
3515
     5288, 5296, 5304, 5312, 5320, 5328, 5336, 5344, 5352, 5360, 5368, 5376,
3516
     5384, 5396, 5408, 5420, 5432, 5440, 5448, 5456, 5464, 5472, 5480, 5488,
3517
     5496, 5504, 5512, 5520, 5528, 5536, 5544, 5552, 5560, 5568, 5576, 5584,
3518
     5592, 5600, 5608, 5616, 5624, 5632, 5640, 5648, 5656, 5664, 5673, 5682,
3519
     5688, 5688, 5688, 5688, 5688, 5696, 5704, 5712, 5720, 5732, 5744, 5756,
3520
     5768, 5780, 5792, 5804, 5816, 5828, 5840, 5852, 5864, 5876, 5888, 5900,
3521
     5912, 5924, 5936, 5948, 5960, 5968, 5976, 5984, 5992, 6000, 6008, 6020,
3522
     6032, 6044, 6056, 6068, 6080, 6092, 6104, 6116, 6128, 6136, 6144, 6152,
3523
     6160, 6168, 6176, 6184, 6192, 6204, 6216, 6228, 6240, 6252, 6264, 6276,
3524
     6288, 6300, 6312, 6324, 6336, 6348, 6360, 6372, 6384, 6396, 6408, 6420,
3525
     6432, 6440, 6448, 6456, 6464, 6476, 6488, 6500, 6512, 6524, 6536, 6548,
3526
     6560, 6572, 6584, 6592, 6600, 6608, 6616, 6624, 6632, 6640, 6648, 6648,
3527
     6648, 6648, 6648, 6648, 6648},
3528
    {6648, 6656, 6664, 6676, 6688, 6700, 6712, 6724, 6736, 6744, 6752, 6764,
3529
     6776, 6788, 6800, 6812, 6824, 6832, 6840, 6852, 6864, 6876, 6888, 6888,
3530
     6888, 6896, 6904, 6916, 6928, 6940, 6952, 6952, 6952, 6960, 6968, 6980,
3531
     6992, 7004, 7016, 7028, 7040, 7048, 7056, 7068, 7080, 7092, 7104, 7116,
3532
     7128, 7136, 7144, 7156, 7168, 7180, 7192, 7204, 7216, 7224, 7232, 7244,
3533
     7256, 7268, 7280, 7292, 7304, 7312, 7320, 7332, 7344, 7356, 7368, 7368,
3534
     7368, 7376, 7384, 7396, 7408, 7420, 7432, 7432, 7432, 7440, 7448, 7460,
3535
     7472, 7484, 7496, 7508, 7520, 7520, 7528, 7528, 7540, 7540, 7552, 7552,
3536
     7564, 7572, 7580, 7592, 7604, 7616, 7628, 7640, 7652, 7660, 7668, 7680,
3537
     7692, 7704, 7716, 7728, 7740, 7748, 7756, 7764, 7772, 7780, 7788, 7796,
3538
     7804, 7812, 7820, 7828, 7836, 7844, 7852, 7852, 7852, 7864, 7876, 7892,
3539
     7908, 7924, 7940, 7956, 7972, 7984, 7996, 8012, 8028, 8044, 8060, 8076,
3540
     8092, 8104, 8116, 8132, 8148, 8164, 8180, 8196, 8212, 8224, 8236, 8252,
3541
     8268, 8284, 8300, 8316, 8332, 8344, 8356, 8372, 8388, 8404, 8420, 8436,
3542
     8452, 8464, 8476, 8492, 8508, 8524, 8540, 8556, 8572, 8580, 8588, 8600,
3543
     8608, 8620, 8620, 8628, 8640, 8648, 8656, 8664, 8672, 8681, 8688, 8693,
3544
     8701, 8710, 8716, 8728, 8736, 8748, 8748, 8756, 8768, 8776, 8784, 8792,
3545
     8800, 8810, 8818, 8826, 8832, 8840, 8848, 8860, 8872, 8872, 8872, 8880,
3546
     8892, 8900, 8908, 8916, 8924, 8926, 8934, 8942, 8948, 8956, 8964, 8976,
3547
     8988, 8996, 9004, 9012, 9024, 9032, 9040, 9048, 9056, 9066, 9074, 9080,
3548
     9084, 9084, 9084, 9096, 9104, 9116, 9116, 9124, 9136, 9144, 9152, 9160,
3549
     9168, 9178, 9181, 9188, 9190},
3550
    {9190, 9194, 9197, 9201, 9205, 9209, 9213, 9217, 9221, 9225, 9229, 9232,
3551
     9232, 9232, 9232, 9232, 9232, 9233, 9236, 9236, 9236, 9236, 9236, 9237,
3552
     9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244,
3553
     9245, 9249, 9257, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9269,
3554
     9272, 9272, 9272, 9273, 9281, 9292, 9293, 9301, 9312, 9312, 9312, 9312,
3555
     9313, 9320, 9321, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9329,
3556
     9337, 9345, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352,
3557
     9352, 9352, 9352, 9353, 9368, 9368, 9368, 9368, 9368, 9368, 9368, 9369,
3558
     9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372,
3559
     9372, 9372, 9372, 9372, 9373, 9377, 9380, 9380, 9381, 9385, 9389, 9393,
3560
     9397, 9401, 9405, 9409, 9413, 9417, 9421, 9425, 9429, 9433, 9437, 9441,
3561
     9445, 9449, 9453, 9457, 9461, 9465, 9469, 9473, 9477, 9481, 9485, 9488,
3562
     9489, 9493, 9497, 9501, 9505, 9509, 9513, 9517, 9521, 9525, 9529, 9533,
3563
     9537, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540,
3564
     9541, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3565
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3566
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3567
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3568
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3569
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3570
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3571
     9548, 9548, 9548, 9548, 9549},
3572
    {9549,  9561,  9573,  9577,  9584,  9585,  9597,  9609,  9612,  9613,
3573
     9621,  9625,  9629,  9633,  9637,  9641,  9645,  9649,  9653,  9657,
3574
     9660,  9661,  9665,  9672,  9672,  9673,  9677,  9681,  9685,  9689,
3575
     9692,  9692,  9693,  9701,  9713,  9720,  9721,  9724,  9724,  9728,
3576
     9729,  9732,  9732,  9736,  9745,  9749,  9752,  9753,  9757,  9761,
3577
     9764,  9765,  9769,  9773,  9777,  9781,  9785,  9789,  9792,  9793,
3578
     9805,  9809,  9813,  9817,  9821,  9824,  9824,  9824,  9824,  9825,
3579
     9829,  9833,  9837,  9841,  9844,  9844,  9844,  9844,  9844,  9844,
3580
     9845,  9857,  9869,  9885,  9897,  9909,  9921,  9933,  9945,  9957,
3581
     9969,  9981,  9993,  10005, 10017, 10029, 10037, 10041, 10049, 10061,
3582
     10069, 10073, 10081, 10093, 10109, 10117, 10121, 10129, 10141, 10145,
3583
     10149, 10153, 10157, 10161, 10169, 10181, 10189, 10193, 10201, 10213,
3584
     10229, 10237, 10241, 10249, 10261, 10265, 10269, 10273, 10276, 10276,
3585
     10276, 10276, 10276, 10276, 10276, 10276, 10276, 10277, 10288, 10288,
3586
     10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288,
3587
     10288, 10288, 10288, 10288, 10288, 10296, 10304, 10304, 10304, 10304,
3588
     10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304,
3589
     10304, 10304, 10304, 10304, 10304, 10312, 10312, 10312, 10312, 10312,
3590
     10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3591
     10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3592
     10312, 10312, 10312, 10312, 10312, 10312, 10320, 10328, 10336, 10336,
3593
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3594
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3595
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3596
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3597
     10336, 10336, 10336, 10336, 10336, 10336, 10336},
3598
    {10336, 10336, 10336, 10336, 10336, 10344, 10344, 10344, 10344, 10344,
3599
     10352, 10352, 10352, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3600
     10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3601
     10360, 10360, 10360, 10360, 10360, 10360, 10360, 10368, 10368, 10376,
3602
     10376, 10376, 10376, 10376, 10377, 10385, 10396, 10397, 10405, 10416,
3603
     10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416,
3604
     10416, 10416, 10416, 10416, 10416, 10416, 10424, 10424, 10424, 10432,
3605
     10432, 10432, 10440, 10440, 10448, 10448, 10448, 10448, 10448, 10448,
3606
     10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448,
3607
     10448, 10448, 10448, 10448, 10448, 10448, 10448, 10456, 10456, 10464,
3608
     10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464,
3609
     10472, 10480, 10488, 10496, 10504, 10504, 10504, 10512, 10520, 10520,
3610
     10520, 10528, 10536, 10536, 10536, 10536, 10536, 10536, 10536, 10544,
3611
     10552, 10552, 10552, 10560, 10568, 10568, 10568, 10576, 10584, 10584,
3612
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3613
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3614
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3615
     10584, 10584, 10584, 10592, 10600, 10608, 10616, 10616, 10616, 10616,
3616
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3617
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3618
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3619
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3620
     10616, 10616, 10616, 10616, 10616, 10624, 10632, 10640, 10648, 10648,
3621
     10648, 10648, 10648, 10648, 10648, 10656, 10664, 10672, 10680, 10680,
3622
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3623
     10680, 10680, 10680, 10680, 10680, 10680, 10680},
3624
    {10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3625
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3626
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3627
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3628
     10680, 10680, 10684, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3629
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3630
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3631
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3632
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3633
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3634
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3635
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3636
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3637
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3638
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3639
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3640
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3641
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3642
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3643
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3644
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3645
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3646
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3647
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3648
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3649
     10688, 10688, 10688, 10688, 10688, 10688, 10688},
3650
    {10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3651
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3652
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3653
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3654
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3655
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3656
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3657
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3658
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3659
     10688, 10688, 10688, 10688, 10688, 10688, 10689, 10693, 10697, 10701,
3660
     10705, 10709, 10713, 10717, 10721, 10725, 10733, 10741, 10749, 10757,
3661
     10765, 10773, 10781, 10789, 10797, 10805, 10813, 10825, 10837, 10849,
3662
     10861, 10873, 10885, 10897, 10909, 10921, 10937, 10953, 10969, 10985,
3663
     11001, 11017, 11033, 11049, 11065, 11081, 11097, 11105, 11113, 11121,
3664
     11129, 11137, 11145, 11153, 11161, 11169, 11181, 11193, 11205, 11217,
3665
     11229, 11241, 11253, 11265, 11277, 11289, 11301, 11313, 11325, 11337,
3666
     11349, 11361, 11373, 11385, 11397, 11409, 11421, 11433, 11445, 11457,
3667
     11469, 11481, 11493, 11505, 11517, 11529, 11541, 11553, 11565, 11577,
3668
     11589, 11601, 11613, 11617, 11621, 11625, 11629, 11633, 11637, 11641,
3669
     11645, 11649, 11653, 11657, 11661, 11665, 11669, 11673, 11677, 11681,
3670
     11685, 11689, 11693, 11697, 11701, 11705, 11709, 11713, 11717, 11721,
3671
     11725, 11729, 11733, 11737, 11741, 11745, 11749, 11753, 11757, 11761,
3672
     11765, 11769, 11773, 11777, 11781, 11785, 11789, 11793, 11797, 11801,
3673
     11805, 11809, 11813, 11817, 11821, 11824, 11824, 11824, 11824, 11824,
3674
     11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3675
     11824, 11824, 11824, 11824, 11824, 11824, 11824},
3676
    {11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3677
     11824, 11824, 11825, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3678
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3679
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3680
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3681
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3682
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3683
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3684
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3685
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3686
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3687
     11840, 11840, 11840, 11840, 11840, 11840, 11841, 11853, 11861, 11872,
3688
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3689
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3690
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3691
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3692
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3693
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3694
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3695
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3696
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3697
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3698
     11872, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3699
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3700
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3701
     11880, 11880, 11880, 11880, 11880, 11880, 11880},
3702
    {11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3703
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3704
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3705
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3706
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3707
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3708
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3709
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3710
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3711
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3712
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3713
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3714
     11880, 11880, 11880, 11880, 11881, 11885, 11888, 11888, 11888, 11888,
3715
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3716
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3717
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3718
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3719
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3720
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3721
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3722
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3723
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3724
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3725
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3726
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3727
     11888, 11888, 11888, 11888, 11888, 11888, 11888},
3728
    {11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3729
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3730
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3731
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3732
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3733
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3734
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3735
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3736
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3737
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3738
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3739
     11888, 11889, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3740
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3741
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3742
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3743
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3744
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3745
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3746
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3747
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3748
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3749
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3750
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3751
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3752
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3753
     11892, 11892, 11892, 11892, 11892, 11892, 11892},
3754
    {11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3755
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3756
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3757
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3758
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3759
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3760
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3761
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3762
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3763
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3764
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3765
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3766
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3767
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3768
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3769
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11893,
3770
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3771
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3772
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3773
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3774
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3775
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3776
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3777
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3778
     11896, 11896, 11896, 11897, 11900, 11900, 11900, 11900, 11900, 11900,
3779
     11900, 11900, 11900, 11900, 11900, 11900, 11901},
3780
    {11901, 11905, 11909, 11913, 11917, 11921, 11925, 11929, 11933, 11937,
3781
     11941, 11945, 11949, 11953, 11957, 11961, 11965, 11969, 11973, 11977,
3782
     11981, 11985, 11989, 11993, 11997, 12001, 12005, 12009, 12013, 12017,
3783
     12021, 12025, 12029, 12033, 12037, 12041, 12045, 12049, 12053, 12057,
3784
     12061, 12065, 12069, 12073, 12077, 12081, 12085, 12089, 12093, 12097,
3785
     12101, 12105, 12109, 12113, 12117, 12121, 12125, 12129, 12133, 12137,
3786
     12141, 12145, 12149, 12153, 12157, 12161, 12165, 12169, 12173, 12177,
3787
     12181, 12185, 12189, 12193, 12197, 12201, 12205, 12209, 12213, 12217,
3788
     12221, 12225, 12229, 12233, 12237, 12241, 12245, 12249, 12253, 12257,
3789
     12261, 12265, 12269, 12273, 12277, 12281, 12285, 12289, 12293, 12297,
3790
     12301, 12305, 12309, 12313, 12317, 12321, 12325, 12329, 12333, 12337,
3791
     12341, 12345, 12349, 12353, 12357, 12361, 12365, 12369, 12373, 12377,
3792
     12381, 12385, 12389, 12393, 12397, 12401, 12405, 12409, 12413, 12417,
3793
     12421, 12425, 12429, 12433, 12437, 12441, 12445, 12449, 12453, 12457,
3794
     12461, 12465, 12469, 12473, 12477, 12481, 12485, 12489, 12493, 12497,
3795
     12501, 12505, 12509, 12513, 12517, 12521, 12525, 12529, 12533, 12537,
3796
     12541, 12545, 12549, 12553, 12557, 12561, 12565, 12569, 12573, 12577,
3797
     12581, 12585, 12589, 12593, 12597, 12601, 12605, 12609, 12613, 12617,
3798
     12621, 12625, 12629, 12633, 12637, 12641, 12645, 12649, 12653, 12657,
3799
     12661, 12665, 12669, 12673, 12677, 12681, 12685, 12689, 12693, 12697,
3800
     12701, 12705, 12709, 12713, 12717, 12721, 12725, 12729, 12733, 12737,
3801
     12741, 12745, 12749, 12753, 12756, 12756, 12756, 12756, 12756, 12756,
3802
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3803
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3804
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3805
     12756, 12756, 12756, 12756, 12756, 12756, 12757},
3806
    {12757, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3807
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3808
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3809
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3810
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3811
     12760, 12760, 12760, 12760, 12761, 12764, 12765, 12769, 12773, 12776,
3812
     12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776,
3813
     12776, 12776, 12776, 12776, 12776, 12776, 12776, 12784, 12784, 12792,
3814
     12792, 12800, 12800, 12808, 12808, 12816, 12816, 12824, 12824, 12832,
3815
     12832, 12840, 12840, 12848, 12848, 12856, 12856, 12864, 12864, 12872,
3816
     12872, 12872, 12880, 12880, 12888, 12888, 12896, 12896, 12896, 12896,
3817
     12896, 12896, 12896, 12904, 12912, 12912, 12920, 12928, 12928, 12936,
3818
     12944, 12944, 12952, 12960, 12960, 12968, 12976, 12976, 12976, 12976,
3819
     12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976,
3820
     12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12984,
3821
     12984, 12984, 12984, 12984, 12984, 12985, 12993, 13000, 13000, 13009,
3822
     13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016,
3823
     13016, 13016, 13016, 13024, 13024, 13032, 13032, 13040, 13040, 13048,
3824
     13048, 13056, 13056, 13064, 13064, 13072, 13072, 13080, 13080, 13088,
3825
     13088, 13096, 13096, 13104, 13104, 13112, 13112, 13112, 13120, 13120,
3826
     13128, 13128, 13136, 13136, 13136, 13136, 13136, 13136, 13136, 13144,
3827
     13152, 13152, 13160, 13168, 13168, 13176, 13184, 13184, 13192, 13200,
3828
     13200, 13208, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3829
     13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3830
     13216, 13216, 13216, 13216, 13216, 13224, 13224, 13224, 13232, 13240,
3831
     13248, 13256, 13256, 13256, 13256, 13265, 13272},
3832
    {13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3833
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3834
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3835
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3836
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13273,
3837
     13277, 13281, 13285, 13289, 13293, 13297, 13301, 13305, 13309, 13313,
3838
     13317, 13321, 13325, 13329, 13333, 13337, 13341, 13345, 13349, 13353,
3839
     13357, 13361, 13365, 13369, 13373, 13377, 13381, 13385, 13389, 13393,
3840
     13397, 13401, 13405, 13409, 13413, 13417, 13421, 13425, 13429, 13433,
3841
     13437, 13441, 13445, 13449, 13453, 13457, 13461, 13465, 13469, 13473,
3842
     13477, 13481, 13485, 13489, 13493, 13497, 13501, 13505, 13509, 13513,
3843
     13517, 13521, 13525, 13529, 13533, 13537, 13541, 13545, 13549, 13553,
3844
     13557, 13561, 13565, 13569, 13573, 13577, 13581, 13585, 13589, 13593,
3845
     13597, 13601, 13605, 13609, 13613, 13617, 13621, 13625, 13629, 13633,
3846
     13637, 13641, 13645, 13648, 13648, 13648, 13649, 13653, 13657, 13661,
3847
     13665, 13669, 13673, 13677, 13681, 13685, 13689, 13693, 13697, 13701,
3848
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3849
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3850
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3851
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3852
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3853
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3854
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3855
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3856
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3857
     13704, 13704, 13704, 13704, 13704, 13704, 13705},
3858
    {13705, 13717, 13729, 13741, 13753, 13765, 13777, 13789, 13801, 13813,
3859
     13825, 13837, 13849, 13861, 13873, 13889, 13905, 13921, 13937, 13953,
3860
     13969, 13985, 14001, 14017, 14033, 14049, 14065, 14081, 14097, 14113,
3861
     14141, 14164, 14165, 14177, 14189, 14201, 14213, 14225, 14237, 14249,
3862
     14261, 14273, 14285, 14297, 14309, 14321, 14333, 14345, 14357, 14369,
3863
     14381, 14393, 14405, 14417, 14429, 14441, 14453, 14465, 14477, 14489,
3864
     14501, 14513, 14525, 14537, 14549, 14561, 14573, 14585, 14597, 14601,
3865
     14605, 14609, 14612, 14612, 14612, 14612, 14612, 14612, 14612, 14612,
3866
     14613, 14625, 14633, 14641, 14649, 14657, 14665, 14673, 14681, 14689,
3867
     14697, 14705, 14713, 14721, 14729, 14737, 14745, 14749, 14753, 14757,
3868
     14761, 14765, 14769, 14773, 14777, 14781, 14785, 14789, 14793, 14797,
3869
     14801, 14809, 14817, 14825, 14833, 14841, 14849, 14857, 14865, 14873,
3870
     14881, 14889, 14897, 14905, 14913, 14933, 14949, 14956, 14957, 14961,
3871
     14965, 14969, 14973, 14977, 14981, 14985, 14989, 14993, 14997, 15001,
3872
     15005, 15009, 15013, 15017, 15021, 15025, 15029, 15033, 15037, 15041,
3873
     15045, 15049, 15053, 15057, 15061, 15065, 15069, 15073, 15077, 15081,
3874
     15085, 15089, 15093, 15097, 15101, 15105, 15109, 15113, 15117, 15121,
3875
     15125, 15129, 15133, 15137, 15141, 15145, 15149, 15153, 15161, 15169,
3876
     15177, 15185, 15193, 15201, 15209, 15217, 15225, 15233, 15241, 15249,
3877
     15257, 15265, 15273, 15281, 15289, 15297, 15305, 15313, 15321, 15329,
3878
     15337, 15345, 15357, 15369, 15381, 15389, 15401, 15409, 15421, 15425,
3879
     15429, 15433, 15437, 15441, 15445, 15449, 15453, 15457, 15461, 15465,
3880
     15469, 15473, 15477, 15481, 15485, 15489, 15493, 15497, 15501, 15505,
3881
     15509, 15513, 15517, 15521, 15525, 15529, 15533, 15537, 15541, 15545,
3882
     15549, 15553, 15557, 15561, 15565, 15569, 15573, 15577, 15581, 15585,
3883
     15589, 15593, 15597, 15601, 15605, 15609, 15617},
3884
    {15617, 15637, 15653, 15673, 15685, 15705, 15717, 15729, 15753, 15769,
3885
     15781, 15793, 15805, 15821, 15837, 15853, 15869, 15885, 15901, 15917,
3886
     15941, 15949, 15973, 15997, 16017, 16033, 16057, 16081, 16097, 16109,
3887
     16121, 16137, 16153, 16173, 16193, 16205, 16217, 16233, 16245, 16257,
3888
     16265, 16273, 16285, 16297, 16321, 16337, 16357, 16381, 16397, 16409,
3889
     16421, 16445, 16461, 16485, 16497, 16517, 16529, 16545, 16557, 16573,
3890
     16593, 16609, 16629, 16645, 16653, 16673, 16685, 16697, 16713, 16725,
3891
     16737, 16749, 16769, 16785, 16793, 16817, 16829, 16849, 16865, 16881,
3892
     16893, 16905, 16921, 16929, 16945, 16965, 16973, 16997, 17009, 17017,
3893
     17025, 17033, 17041, 17049, 17057, 17065, 17073, 17081, 17089, 17101,
3894
     17113, 17125, 17137, 17149, 17161, 17173, 17185, 17197, 17209, 17221,
3895
     17233, 17245, 17257, 17269, 17281, 17289, 17297, 17309, 17317, 17325,
3896
     17333, 17345, 17357, 17365, 17373, 17381, 17389, 17397, 17413, 17421,
3897
     17429, 17437, 17445, 17453, 17461, 17469, 17477, 17489, 17505, 17513,
3898
     17521, 17529, 17537, 17545, 17553, 17561, 17573, 17585, 17597, 17609,
3899
     17617, 17625, 17633, 17641, 17649, 17657, 17665, 17673, 17681, 17689,
3900
     17701, 17713, 17721, 17733, 17745, 17757, 17765, 17777, 17789, 17805,
3901
     17813, 17825, 17837, 17849, 17861, 17881, 17905, 17913, 17921, 17929,
3902
     17937, 17945, 17953, 17961, 17969, 17977, 17985, 17993, 18001, 18009,
3903
     18017, 18025, 18033, 18041, 18049, 18065, 18073, 18081, 18089, 18105,
3904
     18117, 18125, 18133, 18141, 18149, 18157, 18165, 18173, 18181, 18189,
3905
     18197, 18209, 18217, 18225, 18237, 18249, 18257, 18273, 18285, 18293,
3906
     18301, 18309, 18317, 18329, 18341, 18349, 18357, 18365, 18373, 18381,
3907
     18389, 18397, 18405, 18413, 18425, 18437, 18449, 18461, 18473, 18485,
3908
     18497, 18509, 18521, 18533, 18545, 18557, 18569, 18581, 18593, 18605,
3909
     18617, 18629, 18641, 18653, 18665, 18677, 18688},
3910
    {18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3911
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3912
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3913
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3914
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3915
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3916
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3917
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3918
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3919
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3920
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3921
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3922
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3923
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3924
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3925
     18688, 18688, 18688, 18688, 18688, 18688, 18689, 18693, 18696, 18696,
3926
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3927
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3928
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3929
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3930
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3931
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3932
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3933
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3934
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3935
     18696, 18696, 18696, 18696, 18696, 18696, 18696},
3936
    {18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3937
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3938
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3939
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3940
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3941
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3942
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3943
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3944
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3945
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3946
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3947
     18696, 18696, 18697, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3948
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3949
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3950
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3951
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3952
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3953
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3954
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3955
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3956
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3957
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3958
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3959
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3960
     18700, 18700, 18701, 18705, 18709, 18712, 18712, 18712, 18713, 18717,
3961
     18720, 18720, 18720, 18720, 18720, 18720, 18720},
3962
    {18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3963
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3964
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3965
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3966
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3967
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3968
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3969
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3970
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3971
     18720, 18720, 18721, 18725, 18729, 18733, 18736, 18736, 18736, 18736,
3972
     18736, 18736, 18736, 18736, 18736, 18737, 18740, 18740, 18740, 18740,
3973
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3974
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3975
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3976
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3977
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3978
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3979
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3980
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3981
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3982
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3983
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3984
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3985
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3986
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3987
     18740, 18740, 18740, 18740, 18740, 18740, 18740},
3988
    {18740, 18744, 18748, 18752, 18756, 18760, 18764, 18768, 18772, 18776,
3989
     18780, 18784, 18788, 18792, 18796, 18800, 18804, 18808, 18812, 18816,
3990
     18820, 18824, 18828, 18832, 18836, 18840, 18844, 18848, 18852, 18856,
3991
     18860, 18864, 18868, 18872, 18876, 18880, 18884, 18888, 18892, 18896,
3992
     18900, 18904, 18908, 18912, 18916, 18920, 18924, 18928, 18932, 18936,
3993
     18940, 18944, 18948, 18952, 18956, 18960, 18964, 18968, 18972, 18976,
3994
     18980, 18984, 18988, 18992, 18996, 19000, 19004, 19008, 19012, 19016,
3995
     19020, 19024, 19028, 19032, 19036, 19040, 19044, 19048, 19052, 19056,
3996
     19060, 19064, 19068, 19072, 19076, 19080, 19084, 19088, 19092, 19096,
3997
     19100, 19104, 19108, 19112, 19116, 19120, 19124, 19128, 19132, 19136,
3998
     19140, 19144, 19148, 19152, 19156, 19160, 19164, 19168, 19172, 19176,
3999
     19180, 19184, 19188, 19192, 19196, 19200, 19204, 19208, 19212, 19216,
4000
     19220, 19224, 19228, 19232, 19236, 19240, 19244, 19248, 19252, 19256,
4001
     19260, 19264, 19268, 19272, 19276, 19280, 19284, 19288, 19292, 19296,
4002
     19300, 19304, 19308, 19312, 19316, 19320, 19324, 19328, 19332, 19336,
4003
     19340, 19344, 19348, 19352, 19356, 19360, 19364, 19368, 19372, 19376,
4004
     19380, 19384, 19388, 19392, 19396, 19400, 19404, 19408, 19412, 19416,
4005
     19420, 19424, 19428, 19432, 19436, 19440, 19444, 19448, 19452, 19456,
4006
     19460, 19464, 19468, 19472, 19476, 19480, 19484, 19488, 19492, 19496,
4007
     19500, 19504, 19508, 19512, 19516, 19520, 19524, 19528, 19532, 19536,
4008
     19540, 19544, 19548, 19552, 19556, 19560, 19564, 19568, 19572, 19576,
4009
     19580, 19584, 19588, 19592, 19596, 19600, 19604, 19608, 19612, 19616,
4010
     19620, 19624, 19628, 19632, 19636, 19640, 19644, 19648, 19652, 19656,
4011
     19660, 19664, 19668, 19672, 19676, 19680, 19684, 19688, 19692, 19696,
4012
     19700, 19704, 19708, 19712, 19716, 19720, 19724, 19728, 19732, 19736,
4013
     19740, 19744, 19748, 19752, 19756, 19760, 19764},
4014
    {19764, 19768, 19772, 19776, 19780, 19784, 19788, 19792, 19796, 19800,
4015
     19804, 19808, 19812, 19816, 19820, 19820, 19820, 19824, 19824, 19828,
4016
     19828, 19828, 19832, 19836, 19840, 19844, 19848, 19852, 19856, 19860,
4017
     19864, 19868, 19868, 19872, 19872, 19876, 19876, 19876, 19880, 19884,
4018
     19884, 19884, 19884, 19888, 19892, 19896, 19900, 19904, 19908, 19912,
4019
     19916, 19920, 19924, 19928, 19932, 19936, 19940, 19944, 19948, 19952,
4020
     19956, 19960, 19964, 19968, 19972, 19976, 19980, 19984, 19988, 19992,
4021
     19996, 20000, 20004, 20008, 20012, 20016, 20020, 20024, 20028, 20032,
4022
     20036, 20040, 20044, 20048, 20052, 20056, 20060, 20064, 20068, 20072,
4023
     20076, 20080, 20084, 20088, 20092, 20096, 20100, 20104, 20108, 20112,
4024
     20116, 20120, 20124, 20128, 20132, 20136, 20140, 20144, 20148, 20152,
4025
     20156, 20156, 20156, 20160, 20164, 20168, 20172, 20176, 20180, 20184,
4026
     20188, 20192, 20196, 20200, 20204, 20208, 20212, 20216, 20220, 20224,
4027
     20228, 20232, 20236, 20240, 20244, 20248, 20252, 20256, 20260, 20264,
4028
     20268, 20272, 20276, 20280, 20284, 20288, 20292, 20296, 20300, 20304,
4029
     20308, 20312, 20316, 20320, 20324, 20328, 20332, 20336, 20340, 20344,
4030
     20348, 20352, 20356, 20360, 20364, 20368, 20372, 20376, 20380, 20384,
4031
     20388, 20392, 20396, 20400, 20404, 20408, 20412, 20416, 20420, 20424,
4032
     20428, 20432, 20436, 20440, 20444, 20448, 20452, 20456, 20460, 20464,
4033
     20468, 20472, 20476, 20480, 20484, 20488, 20492, 20496, 20500, 20504,
4034
     20508, 20512, 20516, 20520, 20524, 20528, 20532, 20536, 20540, 20544,
4035
     20548, 20552, 20556, 20560, 20564, 20568, 20572, 20576, 20580, 20580,
4036
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4037
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4038
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4039
     20580, 20580, 20580, 20580, 20580, 20580, 20581},
4040
    {20581, 20589, 20597, 20605, 20617, 20629, 20637, 20644, 20644, 20644,
4041
     20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20645,
4042
     20653, 20661, 20669, 20677, 20684, 20684, 20684, 20684, 20684, 20684,
4043
     20692, 20692, 20701, 20705, 20709, 20713, 20717, 20721, 20725, 20729,
4044
     20733, 20737, 20740, 20748, 20756, 20768, 20780, 20788, 20796, 20804,
4045
     20812, 20820, 20828, 20836, 20844, 20852, 20852, 20860, 20868, 20876,
4046
     20884, 20892, 20892, 20900, 20900, 20908, 20916, 20916, 20924, 20932,
4047
     20932, 20940, 20948, 20956, 20964, 20972, 20980, 20988, 20996, 21005,
4048
     21013, 21017, 21021, 21025, 21029, 21033, 21037, 21041, 21045, 21049,
4049
     21053, 21057, 21061, 21065, 21069, 21073, 21077, 21081, 21085, 21089,
4050
     21093, 21097, 21101, 21105, 21109, 21113, 21117, 21121, 21125, 21129,
4051
     21133, 21137, 21141, 21145, 21149, 21153, 21157, 21161, 21165, 21169,
4052
     21173, 21177, 21181, 21185, 21189, 21193, 21197, 21201, 21205, 21209,
4053
     21213, 21217, 21221, 21225, 21229, 21233, 21237, 21241, 21245, 21249,
4054
     21253, 21257, 21261, 21265, 21269, 21273, 21277, 21281, 21285, 21289,
4055
     21293, 21297, 21301, 21305, 21309, 21313, 21317, 21321, 21325, 21329,
4056
     21333, 21337, 21341, 21345, 21349, 21357, 21365, 21369, 21373, 21377,
4057
     21381, 21385, 21389, 21393, 21397, 21401, 21405, 21413, 21420, 21420,
4058
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4059
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4060
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4061
     21420, 21421, 21425, 21429, 21433, 21437, 21441, 21445, 21449, 21453,
4062
     21457, 21461, 21469, 21473, 21477, 21481, 21485, 21489, 21493, 21497,
4063
     21501, 21505, 21509, 21513, 21517, 21529, 21541, 21553, 21565, 21577,
4064
     21589, 21601, 21613, 21625, 21637, 21649, 21661, 21673, 21685, 21697,
4065
     21709, 21721, 21733, 21737, 21741, 21745, 21749},
4066
    {21749, 21761, 21773, 21785, 21797, 21809, 21817, 21825, 21833, 21841,
4067
     21849, 21857, 21865, 21873, 21881, 21889, 21897, 21905, 21913, 21921,
4068
     21929, 21937, 21945, 21953, 21961, 21969, 21977, 21985, 21993, 22001,
4069
     22009, 22017, 22025, 22033, 22041, 22049, 22057, 22065, 22073, 22081,
4070
     22089, 22097, 22105, 22113, 22121, 22129, 22137, 22145, 22153, 22161,
4071
     22169, 22177, 22185, 22193, 22201, 22209, 22217, 22225, 22233, 22241,
4072
     22249, 22257, 22265, 22273, 22281, 22289, 22297, 22305, 22313, 22321,
4073
     22329, 22337, 22345, 22353, 22361, 22369, 22377, 22385, 22393, 22401,
4074
     22409, 22417, 22425, 22433, 22441, 22449, 22457, 22465, 22473, 22481,
4075
     22489, 22497, 22505, 22513, 22521, 22533, 22545, 22557, 22569, 22581,
4076
     22593, 22605, 22617, 22629, 22641, 22653, 22665, 22673, 22681, 22689,
4077
     22697, 22705, 22713, 22721, 22729, 22737, 22745, 22753, 22761, 22769,
4078
     22777, 22785, 22793, 22801, 22809, 22817, 22825, 22833, 22841, 22849,
4079
     22857, 22865, 22873, 22881, 22889, 22897, 22905, 22913, 22921, 22929,
4080
     22937, 22945, 22953, 22961, 22969, 22977, 22985, 22993, 23001, 23009,
4081
     23017, 23025, 23037, 23049, 23061, 23073, 23085, 23093, 23101, 23109,
4082
     23117, 23125, 23133, 23141, 23149, 23157, 23165, 23173, 23181, 23189,
4083
     23197, 23205, 23213, 23221, 23229, 23237, 23245, 23253, 23261, 23269,
4084
     23277, 23285, 23293, 23301, 23309, 23317, 23325, 23333, 23341, 23349,
4085
     23357, 23365, 23373, 23381, 23389, 23397, 23405, 23413, 23421, 23429,
4086
     23437, 23445, 23453, 23461, 23469, 23477, 23485, 23493, 23501, 23509,
4087
     23517, 23525, 23533, 23541, 23549, 23557, 23565, 23573, 23581, 23589,
4088
     23597, 23605, 23613, 23621, 23633, 23645, 23653, 23661, 23669, 23677,
4089
     23685, 23693, 23701, 23709, 23717, 23725, 23733, 23741, 23749, 23757,
4090
     23765, 23773, 23781, 23793, 23805, 23817, 23825, 23833, 23841, 23849,
4091
     23857, 23865, 23873, 23881, 23889, 23897, 23905},
4092
    {23905, 23913, 23921, 23929, 23937, 23945, 23953, 23961, 23969, 23977,
4093
     23985, 23993, 24001, 24009, 24017, 24025, 24033, 24041, 24049, 24057,
4094
     24065, 24073, 24081, 24089, 24097, 24105, 24113, 24121, 24129, 24137,
4095
     24145, 24153, 24161, 24169, 24177, 24185, 24193, 24201, 24209, 24217,
4096
     24225, 24233, 24241, 24249, 24257, 24265, 24273, 24281, 24289, 24297,
4097
     24305, 24313, 24321, 24329, 24337, 24345, 24353, 24361, 24369, 24377,
4098
     24385, 24393, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4099
     24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4100
     24401, 24413, 24425, 24437, 24449, 24461, 24473, 24485, 24497, 24509,
4101
     24521, 24533, 24545, 24557, 24569, 24581, 24593, 24605, 24617, 24629,
4102
     24641, 24653, 24665, 24677, 24689, 24701, 24713, 24725, 24737, 24749,
4103
     24761, 24773, 24785, 24797, 24809, 24821, 24833, 24845, 24857, 24869,
4104
     24881, 24893, 24905, 24917, 24929, 24941, 24953, 24965, 24977, 24989,
4105
     25001, 25013, 25025, 25037, 25049, 25061, 25073, 25085, 25097, 25109,
4106
     25121, 25133, 25145, 25157, 25168, 25168, 25169, 25181, 25193, 25205,
4107
     25217, 25229, 25241, 25253, 25265, 25277, 25289, 25301, 25313, 25325,
4108
     25337, 25349, 25361, 25373, 25385, 25397, 25409, 25421, 25433, 25445,
4109
     25457, 25469, 25481, 25493, 25505, 25517, 25529, 25541, 25553, 25565,
4110
     25577, 25589, 25601, 25613, 25625, 25637, 25649, 25661, 25673, 25685,
4111
     25697, 25709, 25721, 25733, 25745, 25757, 25769, 25781, 25793, 25805,
4112
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4113
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4114
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4115
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4116
     25817, 25829, 25841, 25857, 25873, 25889, 25905, 25921, 25937, 25953,
4117
     25965, 26037, 26069, 26084, 26084, 26084, 26084},
4118
    {26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084,
4119
     26084, 26084, 26084, 26084, 26084, 26084, 26085, 26089, 26093, 26097,
4120
     26101, 26105, 26109, 26113, 26117, 26121, 26132, 26132, 26132, 26132,
4121
     26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132,
4122
     26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26133, 26141,
4123
     26145, 26149, 26153, 26157, 26161, 26165, 26169, 26173, 26177, 26181,
4124
     26185, 26189, 26193, 26197, 26201, 26205, 26209, 26213, 26217, 26220,
4125
     26220, 26221, 26225, 26229, 26237, 26245, 26253, 26261, 26265, 26269,
4126
     26273, 26277, 26281, 26284, 26285, 26289, 26293, 26297, 26301, 26305,
4127
     26309, 26313, 26317, 26321, 26325, 26329, 26333, 26337, 26341, 26345,
4128
     26349, 26353, 26357, 26360, 26361, 26365, 26369, 26373, 26376, 26376,
4129
     26376, 26376, 26377, 26385, 26393, 26400, 26401, 26408, 26409, 26417,
4130
     26425, 26433, 26441, 26449, 26457, 26465, 26473, 26481, 26489, 26493,
4131
     26501, 26509, 26517, 26525, 26533, 26541, 26549, 26557, 26565, 26573,
4132
     26581, 26589, 26593, 26597, 26601, 26605, 26609, 26613, 26617, 26621,
4133
     26625, 26629, 26633, 26637, 26641, 26645, 26649, 26653, 26657, 26661,
4134
     26665, 26669, 26673, 26677, 26681, 26685, 26689, 26693, 26697, 26701,
4135
     26705, 26709, 26713, 26717, 26721, 26725, 26729, 26733, 26737, 26741,
4136
     26745, 26749, 26753, 26757, 26761, 26765, 26769, 26773, 26777, 26781,
4137
     26785, 26789, 26793, 26797, 26801, 26805, 26809, 26813, 26817, 26821,
4138
     26825, 26829, 26833, 26837, 26841, 26845, 26849, 26853, 26857, 26861,
4139
     26865, 26869, 26873, 26877, 26881, 26885, 26889, 26893, 26897, 26901,
4140
     26905, 26909, 26913, 26917, 26921, 26925, 26929, 26933, 26937, 26941,
4141
     26945, 26949, 26953, 26957, 26961, 26965, 26969, 26973, 26977, 26981,
4142
     26985, 26989, 26993, 26997, 27001, 27005, 27017, 27029, 27041, 27053,
4143
     27065, 27077, 27085, 27092, 27092, 27092, 27092},
4144
    {27092, 27093, 27097, 27101, 27105, 27109, 27113, 27117, 27121, 27125,
4145
     27129, 27133, 27137, 27141, 27145, 27149, 27153, 27157, 27161, 27165,
4146
     27169, 27173, 27177, 27181, 27185, 27189, 27193, 27197, 27201, 27205,
4147
     27209, 27213, 27217, 27221, 27225, 27229, 27233, 27237, 27241, 27245,
4148
     27249, 27253, 27257, 27261, 27265, 27269, 27273, 27277, 27281, 27285,
4149
     27289, 27293, 27297, 27301, 27305, 27309, 27313, 27317, 27321, 27325,
4150
     27329, 27333, 27337, 27341, 27345, 27349, 27353, 27357, 27361, 27365,
4151
     27369, 27373, 27377, 27381, 27385, 27389, 27393, 27397, 27401, 27405,
4152
     27409, 27413, 27417, 27421, 27425, 27429, 27433, 27437, 27441, 27445,
4153
     27449, 27453, 27457, 27461, 27465, 27469, 27473, 27477, 27481, 27485,
4154
     27489, 27493, 27497, 27501, 27505, 27509, 27513, 27517, 27521, 27525,
4155
     27529, 27533, 27537, 27541, 27545, 27549, 27553, 27557, 27561, 27565,
4156
     27569, 27573, 27577, 27581, 27585, 27589, 27593, 27597, 27601, 27605,
4157
     27609, 27613, 27617, 27621, 27625, 27629, 27633, 27637, 27641, 27645,
4158
     27649, 27653, 27657, 27661, 27665, 27669, 27673, 27677, 27681, 27685,
4159
     27689, 27693, 27697, 27701, 27705, 27709, 27713, 27717, 27721, 27725,
4160
     27729, 27733, 27737, 27741, 27745, 27749, 27753, 27757, 27761, 27765,
4161
     27769, 27773, 27777, 27781, 27785, 27789, 27793, 27797, 27801, 27805,
4162
     27809, 27813, 27817, 27821, 27825, 27829, 27833, 27837, 27841, 27845,
4163
     27849, 27852, 27852, 27852, 27853, 27857, 27861, 27865, 27869, 27873,
4164
     27876, 27876, 27877, 27881, 27885, 27889, 27893, 27897, 27900, 27900,
4165
     27901, 27905, 27909, 27913, 27917, 27921, 27924, 27924, 27925, 27929,
4166
     27933, 27936, 27936, 27936, 27937, 27941, 27945, 27949, 27957, 27961,
4167
     27965, 27968, 27969, 27973, 27977, 27981, 27985, 27989, 27993, 27996,
4168
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4169
     27996, 27996, 27996, 27996, 27996, 27996, 27996},
4170
    {27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4171
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4172
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4173
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4174
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4175
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4176
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4177
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4178
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4179
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4180
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4181
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4182
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27997,
4183
     28001, 28005, 28009, 28013, 28016, 28017, 28021, 28025, 28029, 28033,
4184
     28037, 28041, 28045, 28049, 28053, 28057, 28061, 28065, 28069, 28073,
4185
     28077, 28081, 28085, 28089, 28093, 28097, 28101, 28105, 28109, 28113,
4186
     28117, 28121, 28125, 28129, 28133, 28137, 28141, 28145, 28149, 28153,
4187
     28157, 28161, 28165, 28169, 28173, 28177, 28181, 28184, 28185, 28189,
4188
     28193, 28197, 28201, 28205, 28209, 28213, 28217, 28220, 28220, 28220,
4189
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4190
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4191
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4192
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4193
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4194
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4195
     28220, 28220, 28220, 28220, 28220, 28220, 28220},
4196
    {28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4197
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4198
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4199
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4200
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4201
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4202
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4203
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4204
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4205
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4206
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4207
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4208
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4209
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4210
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4211
     28220, 28220, 28220, 28220, 28220, 28228, 28228, 28236, 28236, 28236,
4212
     28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236,
4213
     28236, 28236, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4214
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4215
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4216
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4217
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4218
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4219
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4220
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4221
     28244, 28244, 28244, 28244, 28244, 28244, 28244},
4222
    {28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4223
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4224
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4225
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4226
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28252, 28260, 28260,
4227
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4228
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4229
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4230
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4231
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4232
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4233
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4234
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4235
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4236
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4237
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4238
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4239
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4240
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4241
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4242
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4243
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4244
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4245
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4246
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4247
     28260, 28260, 28260, 28260, 28260, 28260, 28260},
4248
    {28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4249
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4250
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4251
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4252
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4253
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4254
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4255
     28260, 28260, 28260, 28260, 28260, 28260, 28268, 28276, 28276, 28276,
4256
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4257
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4258
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4259
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4260
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4261
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4262
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4263
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4264
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4265
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4266
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4267
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4268
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4269
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4270
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4271
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4272
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4273
     28276, 28276, 28276, 28276, 28276, 28276, 28276},
4274
    {28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4275
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4276
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4277
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4278
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4279
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4280
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4281
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4282
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4283
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4284
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4285
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4286
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4287
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4288
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4289
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4290
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4291
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4292
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28284, 28292,
4293
     28292, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4294
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4295
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4296
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4297
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4298
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4299
     28300, 28300, 28300, 28300, 28300, 28300, 28300},
4300
    {28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4301
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4302
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4303
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4304
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4305
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4306
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4307
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4308
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4309
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4310
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4311
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4312
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4313
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4314
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4315
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4316
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4317
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4318
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28308, 28316, 28316,
4319
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4320
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4321
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4322
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4323
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4324
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4325
     28316, 28316, 28316, 28316, 28316, 28316, 28316},
4326
    {28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4327
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4328
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4329
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4330
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4331
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28324, 28324, 28324,
4332
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4333
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4334
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4335
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4336
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4337
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4338
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4339
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4340
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4341
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4342
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4343
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4344
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4345
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4346
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4347
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4348
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4349
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4350
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4351
     28324, 28324, 28324, 28324, 28324, 28324, 28324},
4352
    {28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4353
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4354
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4355
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4356
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4357
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4358
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4359
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4360
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4361
     28324, 28324, 28324, 28324, 28324, 28332, 28340, 28352, 28364, 28376,
4362
     28388, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4363
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4364
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4365
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4366
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4367
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4368
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4369
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4370
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28408, 28416,
4371
     28428, 28440, 28452, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4372
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4373
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4374
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4375
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4376
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4377
     28464, 28464, 28464, 28464, 28464, 28464, 28464},
4378
    {28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4379
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4380
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4381
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4382
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4383
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4384
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4385
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4386
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4387
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4388
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4389
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4390
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4391
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4392
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4393
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4394
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4395
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4396
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4397
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4398
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4399
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4400
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4401
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4402
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4403
     28464, 28464, 28464, 28464, 28464, 28464, 28465},
4404
    {28465, 28469, 28473, 28477, 28481, 28485, 28489, 28493, 28497, 28501,
4405
     28505, 28509, 28513, 28517, 28521, 28525, 28529, 28533, 28537, 28541,
4406
     28545, 28549, 28553, 28557, 28561, 28565, 28569, 28573, 28577, 28581,
4407
     28585, 28589, 28593, 28597, 28601, 28605, 28609, 28613, 28617, 28621,
4408
     28625, 28629, 28633, 28637, 28641, 28645, 28649, 28653, 28657, 28661,
4409
     28665, 28669, 28673, 28677, 28681, 28685, 28689, 28693, 28697, 28701,
4410
     28705, 28709, 28713, 28717, 28721, 28725, 28729, 28733, 28737, 28741,
4411
     28745, 28749, 28753, 28757, 28761, 28765, 28769, 28773, 28777, 28781,
4412
     28785, 28789, 28793, 28797, 28801, 28804, 28805, 28809, 28813, 28817,
4413
     28821, 28825, 28829, 28833, 28837, 28841, 28845, 28849, 28853, 28857,
4414
     28861, 28865, 28869, 28873, 28877, 28881, 28885, 28889, 28893, 28897,
4415
     28901, 28905, 28909, 28913, 28917, 28921, 28925, 28929, 28933, 28937,
4416
     28941, 28945, 28949, 28953, 28957, 28961, 28965, 28969, 28973, 28977,
4417
     28981, 28985, 28989, 28993, 28997, 29001, 29005, 29009, 29013, 29017,
4418
     29021, 29025, 29029, 29033, 29037, 29041, 29045, 29049, 29053, 29057,
4419
     29061, 29065, 29069, 29073, 29077, 29081, 29085, 29088, 29089, 29093,
4420
     29096, 29096, 29097, 29100, 29100, 29101, 29105, 29108, 29108, 29109,
4421
     29113, 29117, 29121, 29124, 29125, 29129, 29133, 29137, 29141, 29145,
4422
     29149, 29153, 29157, 29161, 29165, 29169, 29172, 29173, 29176, 29177,
4423
     29181, 29185, 29189, 29193, 29197, 29201, 29204, 29205, 29209, 29213,
4424
     29217, 29221, 29225, 29229, 29233, 29237, 29241, 29245, 29249, 29253,
4425
     29257, 29261, 29265, 29269, 29273, 29277, 29281, 29285, 29289, 29293,
4426
     29297, 29301, 29305, 29309, 29313, 29317, 29321, 29325, 29329, 29333,
4427
     29337, 29341, 29345, 29349, 29353, 29357, 29361, 29365, 29369, 29373,
4428
     29377, 29381, 29385, 29389, 29393, 29397, 29401, 29405, 29409, 29413,
4429
     29417, 29421, 29425, 29429, 29433, 29437, 29441},
4430
    {29441, 29445, 29449, 29453, 29457, 29461, 29464, 29465, 29469, 29473,
4431
     29477, 29480, 29480, 29481, 29485, 29489, 29493, 29497, 29501, 29505,
4432
     29509, 29512, 29513, 29517, 29521, 29525, 29529, 29533, 29537, 29540,
4433
     29541, 29545, 29549, 29553, 29557, 29561, 29565, 29569, 29573, 29577,
4434
     29581, 29585, 29589, 29593, 29597, 29601, 29605, 29609, 29613, 29617,
4435
     29621, 29625, 29629, 29633, 29637, 29641, 29645, 29649, 29652, 29653,
4436
     29657, 29661, 29665, 29668, 29669, 29673, 29677, 29681, 29685, 29688,
4437
     29689, 29692, 29692, 29692, 29693, 29697, 29701, 29705, 29709, 29713,
4438
     29717, 29720, 29721, 29725, 29729, 29733, 29737, 29741, 29745, 29749,
4439
     29753, 29757, 29761, 29765, 29769, 29773, 29777, 29781, 29785, 29789,
4440
     29793, 29797, 29801, 29805, 29809, 29813, 29817, 29821, 29825, 29829,
4441
     29833, 29837, 29841, 29845, 29849, 29853, 29857, 29861, 29865, 29869,
4442
     29873, 29877, 29881, 29885, 29889, 29893, 29897, 29901, 29905, 29909,
4443
     29913, 29917, 29921, 29925, 29929, 29933, 29937, 29941, 29945, 29949,
4444
     29953, 29957, 29961, 29965, 29969, 29973, 29977, 29981, 29985, 29989,
4445
     29993, 29997, 30001, 30005, 30009, 30013, 30017, 30021, 30025, 30029,
4446
     30033, 30037, 30041, 30045, 30049, 30053, 30057, 30061, 30065, 30069,
4447
     30073, 30077, 30081, 30085, 30089, 30093, 30097, 30101, 30105, 30109,
4448
     30113, 30117, 30121, 30125, 30129, 30133, 30137, 30141, 30145, 30149,
4449
     30153, 30157, 30161, 30165, 30169, 30173, 30177, 30181, 30185, 30189,
4450
     30193, 30197, 30201, 30205, 30209, 30213, 30217, 30221, 30225, 30229,
4451
     30233, 30237, 30241, 30245, 30249, 30253, 30257, 30261, 30265, 30269,
4452
     30273, 30277, 30281, 30285, 30289, 30293, 30297, 30301, 30305, 30309,
4453
     30313, 30317, 30321, 30325, 30329, 30333, 30337, 30341, 30345, 30349,
4454
     30353, 30357, 30361, 30365, 30369, 30373, 30377, 30381, 30385, 30389,
4455
     30393, 30397, 30401, 30405, 30409, 30413, 30417},
4456
    {30417, 30421, 30425, 30429, 30433, 30437, 30441, 30445, 30449, 30453,
4457
     30457, 30461, 30465, 30469, 30473, 30477, 30481, 30485, 30489, 30493,
4458
     30497, 30501, 30505, 30509, 30513, 30517, 30521, 30525, 30529, 30533,
4459
     30537, 30541, 30545, 30549, 30553, 30557, 30561, 30565, 30569, 30573,
4460
     30577, 30581, 30585, 30589, 30593, 30597, 30601, 30605, 30609, 30613,
4461
     30617, 30621, 30625, 30629, 30633, 30637, 30641, 30645, 30649, 30653,
4462
     30657, 30661, 30665, 30669, 30673, 30677, 30681, 30685, 30689, 30693,
4463
     30697, 30701, 30705, 30709, 30713, 30717, 30721, 30725, 30729, 30733,
4464
     30737, 30741, 30745, 30749, 30753, 30757, 30761, 30765, 30769, 30773,
4465
     30777, 30781, 30785, 30789, 30793, 30797, 30801, 30805, 30809, 30813,
4466
     30817, 30821, 30825, 30829, 30833, 30837, 30841, 30845, 30849, 30853,
4467
     30857, 30861, 30865, 30869, 30873, 30877, 30881, 30885, 30889, 30893,
4468
     30897, 30901, 30905, 30909, 30913, 30917, 30921, 30925, 30929, 30933,
4469
     30937, 30941, 30945, 30949, 30953, 30957, 30961, 30965, 30969, 30973,
4470
     30977, 30981, 30985, 30989, 30993, 30997, 31001, 31005, 31009, 31013,
4471
     31017, 31021, 31025, 31029, 31033, 31037, 31041, 31045, 31049, 31053,
4472
     31057, 31061, 31065, 31069, 31073, 31077, 31080, 31080, 31081, 31085,
4473
     31089, 31093, 31097, 31101, 31105, 31109, 31113, 31117, 31121, 31125,
4474
     31129, 31133, 31137, 31141, 31145, 31149, 31153, 31157, 31161, 31165,
4475
     31169, 31173, 31177, 31181, 31185, 31189, 31193, 31197, 31201, 31205,
4476
     31209, 31213, 31217, 31221, 31225, 31229, 31233, 31237, 31241, 31245,
4477
     31249, 31253, 31257, 31261, 31265, 31269, 31273, 31277, 31281, 31285,
4478
     31289, 31293, 31297, 31301, 31305, 31309, 31313, 31317, 31321, 31325,
4479
     31329, 31333, 31337, 31341, 31345, 31349, 31353, 31357, 31361, 31365,
4480
     31369, 31373, 31377, 31381, 31385, 31389, 31393, 31397, 31401, 31405,
4481
     31409, 31413, 31417, 31421, 31425, 31429, 31433},
4482
    {31433, 31437, 31441, 31445, 31449, 31453, 31457, 31461, 31465, 31469,
4483
     31473, 31477, 31481, 31485, 31489, 31493, 31497, 31501, 31505, 31509,
4484
     31513, 31517, 31521, 31525, 31529, 31533, 31537, 31541, 31545, 31549,
4485
     31553, 31557, 31561, 31565, 31569, 31573, 31577, 31581, 31585, 31589,
4486
     31593, 31597, 31601, 31605, 31609, 31613, 31617, 31621, 31625, 31629,
4487
     31633, 31637, 31641, 31645, 31649, 31653, 31657, 31661, 31665, 31669,
4488
     31673, 31677, 31681, 31685, 31689, 31693, 31697, 31701, 31705, 31709,
4489
     31713, 31717, 31721, 31725, 31729, 31733, 31737, 31741, 31745, 31749,
4490
     31753, 31757, 31761, 31765, 31769, 31773, 31777, 31781, 31785, 31789,
4491
     31793, 31797, 31801, 31805, 31809, 31813, 31817, 31821, 31825, 31829,
4492
     31833, 31837, 31841, 31845, 31849, 31853, 31857, 31861, 31865, 31869,
4493
     31873, 31877, 31881, 31885, 31889, 31893, 31897, 31901, 31905, 31909,
4494
     31913, 31917, 31921, 31925, 31929, 31933, 31937, 31941, 31945, 31949,
4495
     31953, 31957, 31961, 31965, 31969, 31973, 31977, 31981, 31985, 31989,
4496
     31993, 31997, 32001, 32005, 32009, 32013, 32017, 32021, 32025, 32029,
4497
     32033, 32037, 32041, 32045, 32049, 32053, 32057, 32061, 32065, 32069,
4498
     32073, 32077, 32081, 32085, 32089, 32093, 32097, 32101, 32105, 32109,
4499
     32113, 32117, 32121, 32125, 32129, 32133, 32137, 32141, 32145, 32149,
4500
     32153, 32157, 32161, 32165, 32169, 32173, 32177, 32181, 32185, 32189,
4501
     32193, 32197, 32201, 32205, 32209, 32213, 32217, 32221, 32225, 32229,
4502
     32233, 32237, 32241, 32245, 32248, 32248, 32249, 32253, 32257, 32261,
4503
     32265, 32269, 32273, 32277, 32281, 32285, 32289, 32293, 32297, 32301,
4504
     32305, 32309, 32313, 32317, 32321, 32325, 32329, 32333, 32337, 32341,
4505
     32345, 32349, 32353, 32357, 32361, 32365, 32369, 32373, 32377, 32381,
4506
     32385, 32389, 32393, 32397, 32401, 32405, 32409, 32413, 32417, 32421,
4507
     32425, 32429, 32433, 32437, 32441, 32445, 32448},
4508
    {32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4509
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4510
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4511
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4512
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32449, 32453,
4513
     32457, 32461, 32465, 32469, 32473, 32477, 32481, 32485, 32489, 32493,
4514
     32497, 32501, 32505, 32509, 32513, 32517, 32521, 32525, 32529, 32533,
4515
     32537, 32541, 32545, 32549, 32553, 32557, 32561, 32565, 32569, 32573,
4516
     32577, 32581, 32585, 32589, 32593, 32597, 32601, 32605, 32609, 32613,
4517
     32617, 32621, 32625, 32629, 32633, 32637, 32641, 32645, 32649, 32653,
4518
     32657, 32661, 32665, 32669, 32673, 32677, 32681, 32685, 32689, 32693,
4519
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4520
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4521
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4522
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4523
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4524
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4525
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4526
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4527
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4528
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4529
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4530
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4531
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4532
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4533
     32696, 32696, 32696, 32696, 32696, 32696, 32696},
4534
    {32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4535
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4536
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4537
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4538
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4539
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4540
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4541
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4542
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4543
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4544
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4545
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4546
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4547
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4548
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4549
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4550
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4551
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4552
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4553
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4554
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4555
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4556
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4557
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4558
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4559
     32696, 32696, 32696, 32696, 32696, 32696, 32697},
4560
    {32697, 32701, 32705, 32709, 32712, 32713, 32717, 32721, 32725, 32729,
4561
     32733, 32737, 32741, 32745, 32749, 32753, 32757, 32761, 32765, 32769,
4562
     32773, 32777, 32781, 32785, 32789, 32793, 32797, 32801, 32805, 32809,
4563
     32813, 32817, 32820, 32821, 32825, 32828, 32829, 32832, 32832, 32833,
4564
     32836, 32837, 32841, 32845, 32849, 32853, 32857, 32861, 32865, 32869,
4565
     32873, 32876, 32877, 32881, 32885, 32889, 32892, 32893, 32896, 32897,
4566
     32900, 32900, 32900, 32900, 32900, 32900, 32901, 32904, 32904, 32904,
4567
     32904, 32905, 32908, 32909, 32912, 32913, 32916, 32917, 32921, 32925,
4568
     32928, 32929, 32933, 32936, 32937, 32940, 32940, 32941, 32944, 32945,
4569
     32948, 32949, 32952, 32953, 32956, 32957, 32960, 32961, 32965, 32968,
4570
     32969, 32972, 32972, 32973, 32977, 32981, 32985, 32988, 32989, 32993,
4571
     32997, 33001, 33005, 33009, 33013, 33016, 33017, 33021, 33025, 33029,
4572
     33032, 33033, 33037, 33041, 33045, 33048, 33049, 33052, 33053, 33057,
4573
     33061, 33065, 33069, 33073, 33077, 33081, 33085, 33089, 33092, 33093,
4574
     33097, 33101, 33105, 33109, 33113, 33117, 33121, 33125, 33129, 33133,
4575
     33137, 33141, 33145, 33149, 33153, 33157, 33160, 33160, 33160, 33160,
4576
     33160, 33161, 33165, 33169, 33172, 33173, 33177, 33181, 33185, 33189,
4577
     33192, 33193, 33197, 33201, 33205, 33209, 33213, 33217, 33221, 33225,
4578
     33229, 33233, 33237, 33241, 33245, 33249, 33253, 33257, 33260, 33260,
4579
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4580
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4581
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4582
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4583
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4584
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4585
     33260, 33260, 33260, 33260, 33260, 33260, 33260},
4586
    {33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4587
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4588
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4589
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4590
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4591
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4592
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4593
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4594
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4595
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4596
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4597
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4598
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4599
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4600
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4601
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4602
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4603
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4604
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4605
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4606
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4607
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4608
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4609
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4610
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4611
     33260, 33260, 33260, 33260, 33260, 33260, 33261},
4612
    {33261, 33269, 33277, 33285, 33293, 33301, 33309, 33317, 33325, 33333,
4613
     33341, 33348, 33348, 33348, 33348, 33348, 33349, 33361, 33373, 33385,
4614
     33397, 33409, 33421, 33433, 33445, 33457, 33469, 33481, 33493, 33505,
4615
     33517, 33529, 33541, 33553, 33565, 33577, 33589, 33601, 33613, 33625,
4616
     33637, 33649, 33661, 33673, 33677, 33681, 33689, 33696, 33697, 33701,
4617
     33705, 33709, 33713, 33717, 33721, 33725, 33729, 33733, 33737, 33741,
4618
     33745, 33749, 33753, 33757, 33761, 33765, 33769, 33773, 33777, 33781,
4619
     33785, 33789, 33793, 33797, 33801, 33809, 33817, 33825, 33833, 33845,
4620
     33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4621
     33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4622
     33852, 33852, 33852, 33852, 33852, 33852, 33853, 33861, 33869, 33876,
4623
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4624
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4625
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4626
     33876, 33876, 33876, 33876, 33877, 33884, 33884, 33884, 33884, 33884,
4627
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4628
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4629
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4630
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4631
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4632
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4633
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4634
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4635
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4636
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4637
     33884, 33884, 33884, 33884, 33884, 33884, 33885},
4638
    {33885, 33893, 33901, 33904, 33904, 33904, 33904, 33904, 33904, 33904,
4639
     33904, 33904, 33904, 33904, 33904, 33904, 33905, 33909, 33913, 33917,
4640
     33925, 33929, 33933, 33937, 33941, 33945, 33949, 33953, 33957, 33961,
4641
     33965, 33969, 33973, 33977, 33981, 33985, 33989, 33993, 33997, 34001,
4642
     34005, 34009, 34013, 34017, 34021, 34025, 34029, 34033, 34037, 34041,
4643
     34045, 34049, 34053, 34057, 34061, 34065, 34069, 34073, 34077, 34081,
4644
     34084, 34084, 34084, 34084, 34085, 34097, 34109, 34121, 34133, 34145,
4645
     34157, 34169, 34181, 34192, 34192, 34192, 34192, 34192, 34192, 34192,
4646
     34193, 34197, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4647
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4648
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4649
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4650
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4651
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4652
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4653
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4654
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4655
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4656
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4657
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4658
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4659
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4660
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4661
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4662
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4663
     34200, 34200, 34200, 34200, 34200, 34200, 34200},
4664
    {34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4665
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4666
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4667
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4668
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4669
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4670
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4671
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4672
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4673
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4674
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4675
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4676
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4677
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4678
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4679
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4680
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4681
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4682
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4683
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4684
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4685
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4686
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4687
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4688
     34201, 34205, 34209, 34213, 34217, 34221, 34225, 34229, 34233, 34237,
4689
     34240, 34240, 34240, 34240, 34240, 34240, 34240},
4690
    {34240, 34244, 34248, 34252, 34256, 34260, 34264, 34268, 34272, 34276,
4691
     34280, 34284, 34288, 34292, 34296, 34300, 34304, 34308, 34312, 34316,
4692
     34320, 34324, 34328, 34332, 34336, 34340, 34344, 34348, 34352, 34356,
4693
     34360, 34364, 34368, 34372, 34376, 34380, 34384, 34388, 34392, 34396,
4694
     34400, 34404, 34408, 34412, 34416, 34420, 34424, 34428, 34432, 34436,
4695
     34440, 34444, 34448, 34452, 34456, 34460, 34464, 34468, 34472, 34476,
4696
     34480, 34484, 34488, 34492, 34496, 34500, 34504, 34508, 34512, 34516,
4697
     34520, 34524, 34528, 34532, 34536, 34540, 34544, 34548, 34552, 34556,
4698
     34560, 34564, 34568, 34572, 34576, 34580, 34584, 34588, 34592, 34596,
4699
     34600, 34604, 34608, 34612, 34616, 34620, 34624, 34628, 34632, 34636,
4700
     34640, 34644, 34648, 34652, 34656, 34660, 34664, 34668, 34672, 34676,
4701
     34680, 34684, 34688, 34692, 34696, 34700, 34704, 34708, 34712, 34716,
4702
     34720, 34724, 34728, 34732, 34736, 34740, 34744, 34748, 34752, 34756,
4703
     34760, 34764, 34768, 34772, 34776, 34780, 34784, 34788, 34792, 34796,
4704
     34800, 34804, 34808, 34812, 34816, 34820, 34824, 34828, 34832, 34836,
4705
     34840, 34844, 34848, 34852, 34856, 34860, 34864, 34868, 34872, 34876,
4706
     34880, 34884, 34888, 34892, 34896, 34900, 34904, 34908, 34912, 34916,
4707
     34920, 34924, 34928, 34932, 34936, 34940, 34944, 34948, 34952, 34956,
4708
     34960, 34964, 34968, 34972, 34976, 34980, 34984, 34988, 34992, 34996,
4709
     35000, 35004, 35008, 35012, 35016, 35020, 35024, 35028, 35032, 35036,
4710
     35040, 35044, 35048, 35052, 35056, 35060, 35064, 35068, 35072, 35076,
4711
     35080, 35084, 35088, 35092, 35096, 35100, 35104, 35108, 35112, 35116,
4712
     35120, 35124, 35128, 35132, 35136, 35140, 35144, 35148, 35152, 35156,
4713
     35160, 35164, 35168, 35172, 35176, 35180, 35184, 35188, 35192, 35196,
4714
     35200, 35204, 35208, 35212, 35216, 35220, 35224, 35228, 35232, 35236,
4715
     35240, 35244, 35248, 35252, 35256, 35260, 35264},
4716
    {35264, 35268, 35272, 35276, 35280, 35284, 35288, 35292, 35296, 35300,
4717
     35304, 35308, 35312, 35316, 35320, 35324, 35328, 35332, 35336, 35340,
4718
     35344, 35348, 35352, 35356, 35360, 35364, 35368, 35372, 35376, 35380,
4719
     35384, 35388, 35392, 35396, 35400, 35404, 35408, 35412, 35416, 35420,
4720
     35424, 35428, 35432, 35436, 35440, 35444, 35448, 35452, 35456, 35460,
4721
     35464, 35468, 35472, 35476, 35480, 35484, 35488, 35492, 35496, 35500,
4722
     35504, 35508, 35512, 35516, 35520, 35524, 35528, 35532, 35536, 35540,
4723
     35544, 35548, 35552, 35556, 35560, 35564, 35568, 35572, 35576, 35580,
4724
     35584, 35588, 35592, 35596, 35600, 35604, 35608, 35612, 35616, 35620,
4725
     35624, 35628, 35632, 35636, 35640, 35644, 35648, 35652, 35656, 35660,
4726
     35664, 35668, 35672, 35676, 35680, 35684, 35688, 35692, 35696, 35700,
4727
     35704, 35708, 35712, 35716, 35720, 35724, 35728, 35732, 35736, 35740,
4728
     35744, 35748, 35752, 35756, 35760, 35764, 35768, 35772, 35776, 35780,
4729
     35784, 35788, 35792, 35796, 35800, 35804, 35808, 35812, 35816, 35820,
4730
     35824, 35828, 35832, 35836, 35840, 35844, 35848, 35852, 35856, 35860,
4731
     35864, 35868, 35872, 35876, 35880, 35884, 35888, 35892, 35896, 35900,
4732
     35904, 35908, 35912, 35916, 35920, 35924, 35928, 35932, 35936, 35940,
4733
     35944, 35948, 35952, 35956, 35960, 35964, 35968, 35972, 35976, 35980,
4734
     35984, 35988, 35992, 35996, 36000, 36004, 36008, 36012, 36016, 36020,
4735
     36024, 36028, 36032, 36036, 36040, 36044, 36048, 36052, 36056, 36060,
4736
     36064, 36068, 36072, 36076, 36080, 36084, 36088, 36092, 36096, 36100,
4737
     36104, 36108, 36112, 36116, 36120, 36124, 36128, 36132, 36136, 36140,
4738
     36144, 36148, 36152, 36156, 36160, 36164, 36168, 36172, 36176, 36180,
4739
     36184, 36188, 36192, 36196, 36200, 36204, 36208, 36212, 36216, 36220,
4740
     36224, 36228, 36232, 36236, 36240, 36244, 36248, 36252, 36256, 36260,
4741
     36264, 36268, 36272, 36276, 36280, 36284, 36288},
4742
    {36288, 36292, 36296, 36300, 36304, 36308, 36312, 36316, 36320, 36324,
4743
     36328, 36332, 36336, 36340, 36344, 36348, 36352, 36356, 36360, 36364,
4744
     36368, 36372, 36376, 36380, 36384, 36388, 36392, 36396, 36400, 36404,
4745
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4746
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4747
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4748
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4749
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4750
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4751
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4752
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4753
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4754
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4755
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4756
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4757
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4758
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4759
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4760
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4761
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4762
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4763
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4764
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4765
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4766
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4767
     36408, 36408, 36408, 36408, 36408, 36408, 36408}};
4768
const char32_t decomposition_data[9102] = {
4769
    0,      32,     32,     776,    97,     32,     772,    50,     51,
4770
    32,     769,    956,    32,     807,    49,     111,    49,     8260,
4771
    52,     49,     8260,   50,     51,     8260,   52,     65,     768,
4772
    65,     769,    65,     770,    65,     771,    65,     776,    65,
4773
    778,    67,     807,    69,     768,    69,     769,    69,     770,
4774
    69,     776,    73,     768,    73,     769,    73,     770,    73,
4775
    776,    78,     771,    79,     768,    79,     769,    79,     770,
4776
    79,     771,    79,     776,    85,     768,    85,     769,    85,
4777
    770,    85,     776,    89,     769,    97,     768,    97,     769,
4778
    97,     770,    97,     771,    97,     776,    97,     778,    99,
4779
    807,    101,    768,    101,    769,    101,    770,    101,    776,
4780
    105,    768,    105,    769,    105,    770,    105,    776,    110,
4781
    771,    111,    768,    111,    769,    111,    770,    111,    771,
4782
    111,    776,    117,    768,    117,    769,    117,    770,    117,
4783
    776,    121,    769,    121,    776,    65,     772,    97,     772,
4784
    65,     774,    97,     774,    65,     808,    97,     808,    67,
4785
    769,    99,     769,    67,     770,    99,     770,    67,     775,
4786
    99,     775,    67,     780,    99,     780,    68,     780,    100,
4787
    780,    69,     772,    101,    772,    69,     774,    101,    774,
4788
    69,     775,    101,    775,    69,     808,    101,    808,    69,
4789
    780,    101,    780,    71,     770,    103,    770,    71,     774,
4790
    103,    774,    71,     775,    103,    775,    71,     807,    103,
4791
    807,    72,     770,    104,    770,    73,     771,    105,    771,
4792
    73,     772,    105,    772,    73,     774,    105,    774,    73,
4793
    808,    105,    808,    73,     775,    73,     74,     105,    106,
4794
    74,     770,    106,    770,    75,     807,    107,    807,    76,
4795
    769,    108,    769,    76,     807,    108,    807,    76,     780,
4796
    108,    780,    76,     183,    108,    183,    78,     769,    110,
4797
    769,    78,     807,    110,    807,    78,     780,    110,    780,
4798
    700,    110,    79,     772,    111,    772,    79,     774,    111,
4799
    774,    79,     779,    111,    779,    82,     769,    114,    769,
4800
    82,     807,    114,    807,    82,     780,    114,    780,    83,
4801
    769,    115,    769,    83,     770,    115,    770,    83,     807,
4802
    115,    807,    83,     780,    115,    780,    84,     807,    116,
4803
    807,    84,     780,    116,    780,    85,     771,    117,    771,
4804
    85,     772,    117,    772,    85,     774,    117,    774,    85,
4805
    778,    117,    778,    85,     779,    117,    779,    85,     808,
4806
    117,    808,    87,     770,    119,    770,    89,     770,    121,
4807
    770,    89,     776,    90,     769,    122,    769,    90,     775,
4808
    122,    775,    90,     780,    122,    780,    115,    79,     795,
4809
    111,    795,    85,     795,    117,    795,    68,     90,     780,
4810
    68,     122,    780,    100,    122,    780,    76,     74,     76,
4811
    106,    108,    106,    78,     74,     78,     106,    110,    106,
4812
    65,     780,    97,     780,    73,     780,    105,    780,    79,
4813
    780,    111,    780,    85,     780,    117,    780,    85,     776,
4814
    772,    117,    776,    772,    85,     776,    769,    117,    776,
4815
    769,    85,     776,    780,    117,    776,    780,    85,     776,
4816
    768,    117,    776,    768,    65,     776,    772,    97,     776,
4817
    772,    65,     775,    772,    97,     775,    772,    198,    772,
4818
    230,    772,    71,     780,    103,    780,    75,     780,    107,
4819
    780,    79,     808,    111,    808,    79,     808,    772,    111,
4820
    808,    772,    439,    780,    658,    780,    106,    780,    68,
4821
    90,     68,     122,    100,    122,    71,     769,    103,    769,
4822
    78,     768,    110,    768,    65,     778,    769,    97,     778,
4823
    769,    198,    769,    230,    769,    216,    769,    248,    769,
4824
    65,     783,    97,     783,    65,     785,    97,     785,    69,
4825
    783,    101,    783,    69,     785,    101,    785,    73,     783,
4826
    105,    783,    73,     785,    105,    785,    79,     783,    111,
4827
    783,    79,     785,    111,    785,    82,     783,    114,    783,
4828
    82,     785,    114,    785,    85,     783,    117,    783,    85,
4829
    785,    117,    785,    83,     806,    115,    806,    84,     806,
4830
    116,    806,    72,     780,    104,    780,    65,     775,    97,
4831
    775,    69,     807,    101,    807,    79,     776,    772,    111,
4832
    776,    772,    79,     771,    772,    111,    771,    772,    79,
4833
    775,    111,    775,    79,     775,    772,    111,    775,    772,
4834
    89,     772,    121,    772,    104,    614,    106,    114,    633,
4835
    635,    641,    119,    121,    32,     774,    32,     775,    32,
4836
    778,    32,     808,    32,     771,    32,     779,    611,    108,
4837
    115,    120,    661,    768,    769,    787,    776,    769,    697,
4838
    32,     837,    59,     32,     769,    168,    769,    913,    769,
4839
    183,    917,    769,    919,    769,    921,    769,    927,    769,
4840
    933,    769,    937,    769,    953,    776,    769,    921,    776,
4841
    933,    776,    945,    769,    949,    769,    951,    769,    953,
4842
    769,    965,    776,    769,    953,    776,    965,    776,    959,
4843
    769,    965,    769,    969,    769,    946,    952,    933,    978,
4844
    769,    978,    776,    966,    960,    954,    961,    962,    920,
4845
    949,    931,    1045,   768,    1045,   776,    1043,   769,    1030,
4846
    776,    1050,   769,    1048,   768,    1059,   774,    1048,   774,
4847
    1080,   774,    1077,   768,    1077,   776,    1075,   769,    1110,
4848
    776,    1082,   769,    1080,   768,    1091,   774,    1140,   783,
4849
    1141,   783,    1046,   774,    1078,   774,    1040,   774,    1072,
4850
    774,    1040,   776,    1072,   776,    1045,   774,    1077,   774,
4851
    1240,   776,    1241,   776,    1046,   776,    1078,   776,    1047,
4852
    776,    1079,   776,    1048,   772,    1080,   772,    1048,   776,
4853
    1080,   776,    1054,   776,    1086,   776,    1256,   776,    1257,
4854
    776,    1069,   776,    1101,   776,    1059,   772,    1091,   772,
4855
    1059,   776,    1091,   776,    1059,   779,    1091,   779,    1063,
4856
    776,    1095,   776,    1067,   776,    1099,   776,    1381,   1410,
4857
    1575,   1619,   1575,   1620,   1608,   1620,   1575,   1621,   1610,
4858
    1620,   1575,   1652,   1608,   1652,   1735,   1652,   1610,   1652,
4859
    1749,   1620,   1729,   1620,   1746,   1620,   2344,   2364,   2352,
4860
    2364,   2355,   2364,   2325,   2364,   2326,   2364,   2327,   2364,
4861
    2332,   2364,   2337,   2364,   2338,   2364,   2347,   2364,   2351,
4862
    2364,   2503,   2494,   2503,   2519,   2465,   2492,   2466,   2492,
4863
    2479,   2492,   2610,   2620,   2616,   2620,   2582,   2620,   2583,
4864
    2620,   2588,   2620,   2603,   2620,   2887,   2902,   2887,   2878,
4865
    2887,   2903,   2849,   2876,   2850,   2876,   2962,   3031,   3014,
4866
    3006,   3015,   3006,   3014,   3031,   3142,   3158,   3263,   3285,
4867
    3270,   3285,   3270,   3286,   3270,   3266,   3270,   3266,   3285,
4868
    3398,   3390,   3399,   3390,   3398,   3415,   3545,   3530,   3545,
4869
    3535,   3545,   3535,   3530,   3545,   3551,   3661,   3634,   3789,
4870
    3762,   3755,   3737,   3755,   3745,   3851,   3906,   4023,   3916,
4871
    4023,   3921,   4023,   3926,   4023,   3931,   4023,   3904,   4021,
4872
    3953,   3954,   3953,   3956,   4018,   3968,   4018,   3953,   3968,
4873
    4019,   3968,   4019,   3953,   3968,   3953,   3968,   3986,   4023,
4874
    3996,   4023,   4001,   4023,   4006,   4023,   4011,   4023,   3984,
4875
    4021,   4133,   4142,   4316,   6917,   6965,   6919,   6965,   6921,
4876
    6965,   6923,   6965,   6925,   6965,   6929,   6965,   6970,   6965,
4877
    6972,   6965,   6974,   6965,   6975,   6965,   6978,   6965,   65,
4878
    198,    66,     68,     69,     398,    71,     72,     73,     74,
4879
    75,     76,     77,     78,     79,     546,    80,     82,     84,
4880
    85,     87,     97,     592,    593,    7426,   98,     100,    101,
4881
    601,    603,    604,    103,    107,    109,    331,    111,    596,
4882
    7446,   7447,   112,    116,    117,    7453,   623,    118,    7461,
4883
    946,    947,    948,    966,    967,    105,    114,    117,    118,
4884
    946,    947,    961,    966,    967,    1085,   594,    99,     597,
4885
    240,    604,    102,    607,    609,    613,    616,    617,    618,
4886
    7547,   669,    621,    7557,   671,    625,    624,    626,    627,
4887
    628,    629,    632,    642,    643,    427,    649,    650,    7452,
4888
    651,    652,    122,    656,    657,    658,    952,    65,     805,
4889
    97,     805,    66,     775,    98,     775,    66,     803,    98,
4890
    803,    66,     817,    98,     817,    67,     807,    769,    99,
4891
    807,    769,    68,     775,    100,    775,    68,     803,    100,
4892
    803,    68,     817,    100,    817,    68,     807,    100,    807,
4893
    68,     813,    100,    813,    69,     772,    768,    101,    772,
4894
    768,    69,     772,    769,    101,    772,    769,    69,     813,
4895
    101,    813,    69,     816,    101,    816,    69,     807,    774,
4896
    101,    807,    774,    70,     775,    102,    775,    71,     772,
4897
    103,    772,    72,     775,    104,    775,    72,     803,    104,
4898
    803,    72,     776,    104,    776,    72,     807,    104,    807,
4899
    72,     814,    104,    814,    73,     816,    105,    816,    73,
4900
    776,    769,    105,    776,    769,    75,     769,    107,    769,
4901
    75,     803,    107,    803,    75,     817,    107,    817,    76,
4902
    803,    108,    803,    76,     803,    772,    108,    803,    772,
4903
    76,     817,    108,    817,    76,     813,    108,    813,    77,
4904
    769,    109,    769,    77,     775,    109,    775,    77,     803,
4905
    109,    803,    78,     775,    110,    775,    78,     803,    110,
4906
    803,    78,     817,    110,    817,    78,     813,    110,    813,
4907
    79,     771,    769,    111,    771,    769,    79,     771,    776,
4908
    111,    771,    776,    79,     772,    768,    111,    772,    768,
4909
    79,     772,    769,    111,    772,    769,    80,     769,    112,
4910
    769,    80,     775,    112,    775,    82,     775,    114,    775,
4911
    82,     803,    114,    803,    82,     803,    772,    114,    803,
4912
    772,    82,     817,    114,    817,    83,     775,    115,    775,
4913
    83,     803,    115,    803,    83,     769,    775,    115,    769,
4914
    775,    83,     780,    775,    115,    780,    775,    83,     803,
4915
    775,    115,    803,    775,    84,     775,    116,    775,    84,
4916
    803,    116,    803,    84,     817,    116,    817,    84,     813,
4917
    116,    813,    85,     804,    117,    804,    85,     816,    117,
4918
    816,    85,     813,    117,    813,    85,     771,    769,    117,
4919
    771,    769,    85,     772,    776,    117,    772,    776,    86,
4920
    771,    118,    771,    86,     803,    118,    803,    87,     768,
4921
    119,    768,    87,     769,    119,    769,    87,     776,    119,
4922
    776,    87,     775,    119,    775,    87,     803,    119,    803,
4923
    88,     775,    120,    775,    88,     776,    120,    776,    89,
4924
    775,    121,    775,    90,     770,    122,    770,    90,     803,
4925
    122,    803,    90,     817,    122,    817,    104,    817,    116,
4926
    776,    119,    778,    121,    778,    97,     702,    383,    775,
4927
    65,     803,    97,     803,    65,     777,    97,     777,    65,
4928
    770,    769,    97,     770,    769,    65,     770,    768,    97,
4929
    770,    768,    65,     770,    777,    97,     770,    777,    65,
4930
    770,    771,    97,     770,    771,    65,     803,    770,    97,
4931
    803,    770,    65,     774,    769,    97,     774,    769,    65,
4932
    774,    768,    97,     774,    768,    65,     774,    777,    97,
4933
    774,    777,    65,     774,    771,    97,     774,    771,    65,
4934
    803,    774,    97,     803,    774,    69,     803,    101,    803,
4935
    69,     777,    101,    777,    69,     771,    101,    771,    69,
4936
    770,    769,    101,    770,    769,    69,     770,    768,    101,
4937
    770,    768,    69,     770,    777,    101,    770,    777,    69,
4938
    770,    771,    101,    770,    771,    69,     803,    770,    101,
4939
    803,    770,    73,     777,    105,    777,    73,     803,    105,
4940
    803,    79,     803,    111,    803,    79,     777,    111,    777,
4941
    79,     770,    769,    111,    770,    769,    79,     770,    768,
4942
    111,    770,    768,    79,     770,    777,    111,    770,    777,
4943
    79,     770,    771,    111,    770,    771,    79,     803,    770,
4944
    111,    803,    770,    79,     795,    769,    111,    795,    769,
4945
    79,     795,    768,    111,    795,    768,    79,     795,    777,
4946
    111,    795,    777,    79,     795,    771,    111,    795,    771,
4947
    79,     795,    803,    111,    795,    803,    85,     803,    117,
4948
    803,    85,     777,    117,    777,    85,     795,    769,    117,
4949
    795,    769,    85,     795,    768,    117,    795,    768,    85,
4950
    795,    777,    117,    795,    777,    85,     795,    771,    117,
4951
    795,    771,    85,     795,    803,    117,    795,    803,    89,
4952
    768,    121,    768,    89,     803,    121,    803,    89,     777,
4953
    121,    777,    89,     771,    121,    771,    945,    787,    945,
4954
    788,    945,    787,    768,    945,    788,    768,    945,    787,
4955
    769,    945,    788,    769,    945,    787,    834,    945,    788,
4956
    834,    913,    787,    913,    788,    913,    787,    768,    913,
4957
    788,    768,    913,    787,    769,    913,    788,    769,    913,
4958
    787,    834,    913,    788,    834,    949,    787,    949,    788,
4959
    949,    787,    768,    949,    788,    768,    949,    787,    769,
4960
    949,    788,    769,    917,    787,    917,    788,    917,    787,
4961
    768,    917,    788,    768,    917,    787,    769,    917,    788,
4962
    769,    951,    787,    951,    788,    951,    787,    768,    951,
4963
    788,    768,    951,    787,    769,    951,    788,    769,    951,
4964
    787,    834,    951,    788,    834,    919,    787,    919,    788,
4965
    919,    787,    768,    919,    788,    768,    919,    787,    769,
4966
    919,    788,    769,    919,    787,    834,    919,    788,    834,
4967
    953,    787,    953,    788,    953,    787,    768,    953,    788,
4968
    768,    953,    787,    769,    953,    788,    769,    953,    787,
4969
    834,    953,    788,    834,    921,    787,    921,    788,    921,
4970
    787,    768,    921,    788,    768,    921,    787,    769,    921,
4971
    788,    769,    921,    787,    834,    921,    788,    834,    959,
4972
    787,    959,    788,    959,    787,    768,    959,    788,    768,
4973
    959,    787,    769,    959,    788,    769,    927,    787,    927,
4974
    788,    927,    787,    768,    927,    788,    768,    927,    787,
4975
    769,    927,    788,    769,    965,    787,    965,    788,    965,
4976
    787,    768,    965,    788,    768,    965,    787,    769,    965,
4977
    788,    769,    965,    787,    834,    965,    788,    834,    933,
4978
    788,    933,    788,    768,    933,    788,    769,    933,    788,
4979
    834,    969,    787,    969,    788,    969,    787,    768,    969,
4980
    788,    768,    969,    787,    769,    969,    788,    769,    969,
4981
    787,    834,    969,    788,    834,    937,    787,    937,    788,
4982
    937,    787,    768,    937,    788,    768,    937,    787,    769,
4983
    937,    788,    769,    937,    787,    834,    937,    788,    834,
4984
    945,    768,    945,    769,    949,    768,    949,    769,    951,
4985
    768,    951,    769,    953,    768,    953,    769,    959,    768,
4986
    959,    769,    965,    768,    965,    769,    969,    768,    969,
4987
    769,    945,    787,    837,    945,    788,    837,    945,    787,
4988
    768,    837,    945,    788,    768,    837,    945,    787,    769,
4989
    837,    945,    788,    769,    837,    945,    787,    834,    837,
4990
    945,    788,    834,    837,    913,    787,    837,    913,    788,
4991
    837,    913,    787,    768,    837,    913,    788,    768,    837,
4992
    913,    787,    769,    837,    913,    788,    769,    837,    913,
4993
    787,    834,    837,    913,    788,    834,    837,    951,    787,
4994
    837,    951,    788,    837,    951,    787,    768,    837,    951,
4995
    788,    768,    837,    951,    787,    769,    837,    951,    788,
4996
    769,    837,    951,    787,    834,    837,    951,    788,    834,
4997
    837,    919,    787,    837,    919,    788,    837,    919,    787,
4998
    768,    837,    919,    788,    768,    837,    919,    787,    769,
4999
    837,    919,    788,    769,    837,    919,    787,    834,    837,
5000
    919,    788,    834,    837,    969,    787,    837,    969,    788,
5001
    837,    969,    787,    768,    837,    969,    788,    768,    837,
5002
    969,    787,    769,    837,    969,    788,    769,    837,    969,
5003
    787,    834,    837,    969,    788,    834,    837,    937,    787,
5004
    837,    937,    788,    837,    937,    787,    768,    837,    937,
5005
    788,    768,    837,    937,    787,    769,    837,    937,    788,
5006
    769,    837,    937,    787,    834,    837,    937,    788,    834,
5007
    837,    945,    774,    945,    772,    945,    768,    837,    945,
5008
    837,    945,    769,    837,    945,    834,    945,    834,    837,
5009
    913,    774,    913,    772,    913,    768,    913,    769,    913,
5010
    837,    32,     787,    953,    32,     787,    32,     834,    168,
5011
    834,    951,    768,    837,    951,    837,    951,    769,    837,
5012
    951,    834,    951,    834,    837,    917,    768,    917,    769,
5013
    919,    768,    919,    769,    919,    837,    8127,   768,    8127,
5014
    769,    8127,   834,    953,    774,    953,    772,    953,    776,
5015
    768,    953,    776,    769,    953,    834,    953,    776,    834,
5016
    921,    774,    921,    772,    921,    768,    921,    769,    8190,
5017
    768,    8190,   769,    8190,   834,    965,    774,    965,    772,
5018
    965,    776,    768,    965,    776,    769,    961,    787,    961,
5019
    788,    965,    834,    965,    776,    834,    933,    774,    933,
5020
    772,    933,    768,    933,    769,    929,    788,    168,    768,
5021
    168,    769,    96,     969,    768,    837,    969,    837,    969,
5022
    769,    837,    969,    834,    969,    834,    837,    927,    768,
5023
    927,    769,    937,    768,    937,    769,    937,    837,    180,
5024
    32,     788,    8194,   8195,   32,     32,     32,     32,     32,
5025
    32,     32,     32,     32,     8208,   32,     819,    46,     46,
5026
    46,     46,     46,     46,     32,     8242,   8242,   8242,   8242,
5027
    8242,   8245,   8245,   8245,   8245,   8245,   33,     33,     32,
5028
    773,    63,     63,     63,     33,     33,     63,     8242,   8242,
5029
    8242,   8242,   32,     48,     105,    52,     53,     54,     55,
5030
    56,     57,     43,     8722,   61,     40,     41,     110,    48,
5031
    49,     50,     51,     52,     53,     54,     55,     56,     57,
5032
    43,     8722,   61,     40,     41,     97,     101,    111,    120,
5033
    601,    104,    107,    108,    109,    110,    112,    115,    116,
5034
    82,     115,    97,     47,     99,     97,     47,     115,    67,
5035
    176,    67,     99,     47,     111,    99,     47,     117,    400,
5036
    176,    70,     103,    72,     72,     72,     104,    295,    73,
5037
    73,     76,     108,    78,     78,     111,    80,     81,     82,
5038
    82,     82,     83,     77,     84,     69,     76,     84,     77,
5039
    90,     937,    90,     75,     65,     778,    66,     67,     101,
5040
    69,     70,     77,     111,    1488,   1489,   1490,   1491,   105,
5041
    70,     65,     88,     960,    947,    915,    928,    8721,   68,
5042
    100,    101,    105,    106,    49,     8260,   55,     49,     8260,
5043
    57,     49,     8260,   49,     48,     49,     8260,   51,     50,
5044
    8260,   51,     49,     8260,   53,     50,     8260,   53,     51,
5045
    8260,   53,     52,     8260,   53,     49,     8260,   54,     53,
5046
    8260,   54,     49,     8260,   56,     51,     8260,   56,     53,
5047
    8260,   56,     55,     8260,   56,     49,     8260,   73,     73,
5048
    73,     73,     73,     73,     73,     86,     86,     86,     73,
5049
    86,     73,     73,     86,     73,     73,     73,     73,     88,
5050
    88,     88,     73,     88,     73,     73,     76,     67,     68,
5051
    77,     105,    105,    105,    105,    105,    105,    105,    118,
5052
    118,    118,    105,    118,    105,    105,    118,    105,    105,
5053
    105,    105,    120,    120,    120,    105,    120,    105,    105,
5054
    108,    99,     100,    109,    48,     8260,   51,     8592,   824,
5055
    8594,   824,    8596,   824,    8656,   824,    8660,   824,    8658,
5056
    824,    8707,   824,    8712,   824,    8715,   824,    8739,   824,
5057
    8741,   824,    8747,   8747,   8747,   8747,   8747,   8750,   8750,
5058
    8750,   8750,   8750,   8764,   824,    8771,   824,    8773,   824,
5059
    8776,   824,    61,     824,    8801,   824,    8781,   824,    60,
5060
    824,    62,     824,    8804,   824,    8805,   824,    8818,   824,
5061
    8819,   824,    8822,   824,    8823,   824,    8826,   824,    8827,
5062
    824,    8834,   824,    8835,   824,    8838,   824,    8839,   824,
5063
    8866,   824,    8872,   824,    8873,   824,    8875,   824,    8828,
5064
    824,    8829,   824,    8849,   824,    8850,   824,    8882,   824,
5065
    8883,   824,    8884,   824,    8885,   824,    12296,  12297,  49,
5066
    50,     51,     52,     53,     54,     55,     56,     57,     49,
5067
    48,     49,     49,     49,     50,     49,     51,     49,     52,
5068
    49,     53,     49,     54,     49,     55,     49,     56,     49,
5069
    57,     50,     48,     40,     49,     41,     40,     50,     41,
5070
    40,     51,     41,     40,     52,     41,     40,     53,     41,
5071
    40,     54,     41,     40,     55,     41,     40,     56,     41,
5072
    40,     57,     41,     40,     49,     48,     41,     40,     49,
5073
    49,     41,     40,     49,     50,     41,     40,     49,     51,
5074
    41,     40,     49,     52,     41,     40,     49,     53,     41,
5075
    40,     49,     54,     41,     40,     49,     55,     41,     40,
5076
    49,     56,     41,     40,     49,     57,     41,     40,     50,
5077
    48,     41,     49,     46,     50,     46,     51,     46,     52,
5078
    46,     53,     46,     54,     46,     55,     46,     56,     46,
5079
    57,     46,     49,     48,     46,     49,     49,     46,     49,
5080
    50,     46,     49,     51,     46,     49,     52,     46,     49,
5081
    53,     46,     49,     54,     46,     49,     55,     46,     49,
5082
    56,     46,     49,     57,     46,     50,     48,     46,     40,
5083
    97,     41,     40,     98,     41,     40,     99,     41,     40,
5084
    100,    41,     40,     101,    41,     40,     102,    41,     40,
5085
    103,    41,     40,     104,    41,     40,     105,    41,     40,
5086
    106,    41,     40,     107,    41,     40,     108,    41,     40,
5087
    109,    41,     40,     110,    41,     40,     111,    41,     40,
5088
    112,    41,     40,     113,    41,     40,     114,    41,     40,
5089
    115,    41,     40,     116,    41,     40,     117,    41,     40,
5090
    118,    41,     40,     119,    41,     40,     120,    41,     40,
5091
    121,    41,     40,     122,    41,     65,     66,     67,     68,
5092
    69,     70,     71,     72,     73,     74,     75,     76,     77,
5093
    78,     79,     80,     81,     82,     83,     84,     85,     86,
5094
    87,     88,     89,     90,     97,     98,     99,     100,    101,
5095
    102,    103,    104,    105,    106,    107,    108,    109,    110,
5096
    111,    112,    113,    114,    115,    116,    117,    118,    119,
5097
    120,    121,    122,    48,     8747,   8747,   8747,   8747,   58,
5098
    58,     61,     61,     61,     61,     61,     61,     10973,  824,
5099
    106,    86,     11617,  27597,  40863,  19968,  20008,  20022,  20031,
5100
    20057,  20101,  20108,  20128,  20154,  20799,  20837,  20843,  20866,
5101
    20886,  20907,  20960,  20981,  20992,  21147,  21241,  21269,  21274,
5102
    21304,  21313,  21340,  21353,  21378,  21430,  21448,  21475,  22231,
5103
    22303,  22763,  22786,  22794,  22805,  22823,  22899,  23376,  23424,
5104
    23544,  23567,  23586,  23608,  23662,  23665,  24027,  24037,  24049,
5105
    24062,  24178,  24186,  24191,  24308,  24318,  24331,  24339,  24400,
5106
    24417,  24435,  24515,  25096,  25142,  25163,  25903,  25908,  25991,
5107
    26007,  26020,  26041,  26080,  26085,  26352,  26376,  26408,  27424,
5108
    27490,  27513,  27571,  27595,  27604,  27611,  27663,  27668,  27700,
5109
    28779,  29226,  29238,  29243,  29247,  29255,  29273,  29275,  29356,
5110
    29572,  29577,  29916,  29926,  29976,  29983,  29992,  30000,  30091,
5111
    30098,  30326,  30333,  30382,  30399,  30446,  30683,  30690,  30707,
5112
    31034,  31160,  31166,  31348,  31435,  31481,  31859,  31992,  32566,
5113
    32593,  32650,  32701,  32769,  32780,  32786,  32819,  32895,  32905,
5114
    33251,  33258,  33267,  33276,  33292,  33307,  33311,  33390,  33394,
5115
    33400,  34381,  34411,  34880,  34892,  34915,  35198,  35211,  35282,
5116
    35328,  35895,  35910,  35925,  35960,  35997,  36196,  36208,  36275,
5117
    36523,  36554,  36763,  36784,  36789,  37009,  37193,  37318,  37324,
5118
    37329,  38263,  38272,  38428,  38582,  38585,  38632,  38737,  38750,
5119
    38754,  38761,  38859,  38893,  38899,  38913,  39080,  39131,  39135,
5120
    39318,  39321,  39340,  39592,  39640,  39647,  39717,  39727,  39730,
5121
    39740,  39770,  40165,  40565,  40575,  40613,  40635,  40643,  40653,
5122
    40657,  40697,  40701,  40718,  40723,  40736,  40763,  40778,  40786,
5123
    40845,  40860,  40864,  32,     12306,  21313,  21316,  21317,  12363,
5124
    12441,  12365,  12441,  12367,  12441,  12369,  12441,  12371,  12441,
5125
    12373,  12441,  12375,  12441,  12377,  12441,  12379,  12441,  12381,
5126
    12441,  12383,  12441,  12385,  12441,  12388,  12441,  12390,  12441,
5127
    12392,  12441,  12399,  12441,  12399,  12442,  12402,  12441,  12402,
5128
    12442,  12405,  12441,  12405,  12442,  12408,  12441,  12408,  12442,
5129
    12411,  12441,  12411,  12442,  12358,  12441,  32,     12441,  32,
5130
    12442,  12445,  12441,  12424,  12426,  12459,  12441,  12461,  12441,
5131
    12463,  12441,  12465,  12441,  12467,  12441,  12469,  12441,  12471,
5132
    12441,  12473,  12441,  12475,  12441,  12477,  12441,  12479,  12441,
5133
    12481,  12441,  12484,  12441,  12486,  12441,  12488,  12441,  12495,
5134
    12441,  12495,  12442,  12498,  12441,  12498,  12442,  12501,  12441,
5135
    12501,  12442,  12504,  12441,  12504,  12442,  12507,  12441,  12507,
5136
    12442,  12454,  12441,  12527,  12441,  12528,  12441,  12529,  12441,
5137
    12530,  12441,  12541,  12441,  12467,  12488,  4352,   4353,   4522,
5138
    4354,   4524,   4525,   4355,   4356,   4357,   4528,   4529,   4530,
5139
    4531,   4532,   4533,   4378,   4358,   4359,   4360,   4385,   4361,
5140
    4362,   4363,   4364,   4365,   4366,   4367,   4368,   4369,   4370,
5141
    4449,   4450,   4451,   4452,   4453,   4454,   4455,   4456,   4457,
5142
    4458,   4459,   4460,   4461,   4462,   4463,   4464,   4465,   4466,
5143
    4467,   4468,   4469,   4448,   4372,   4373,   4551,   4552,   4556,
5144
    4558,   4563,   4567,   4569,   4380,   4573,   4575,   4381,   4382,
5145
    4384,   4386,   4387,   4391,   4393,   4395,   4396,   4397,   4398,
5146
    4399,   4402,   4406,   4416,   4423,   4428,   4593,   4594,   4439,
5147
    4440,   4441,   4484,   4485,   4488,   4497,   4498,   4500,   4510,
5148
    4513,   19968,  20108,  19977,  22235,  19978,  20013,  19979,  30002,
5149
    20057,  19993,  19969,  22825,  22320,  20154,  40,     4352,   41,
5150
    40,     4354,   41,     40,     4355,   41,     40,     4357,   41,
5151
    40,     4358,   41,     40,     4359,   41,     40,     4361,   41,
5152
    40,     4363,   41,     40,     4364,   41,     40,     4366,   41,
5153
    40,     4367,   41,     40,     4368,   41,     40,     4369,   41,
5154
    40,     4370,   41,     40,     4352,   4449,   41,     40,     4354,
5155
    4449,   41,     40,     4355,   4449,   41,     40,     4357,   4449,
5156
    41,     40,     4358,   4449,   41,     40,     4359,   4449,   41,
5157
    40,     4361,   4449,   41,     40,     4363,   4449,   41,     40,
5158
    4364,   4449,   41,     40,     4366,   4449,   41,     40,     4367,
5159
    4449,   41,     40,     4368,   4449,   41,     40,     4369,   4449,
5160
    41,     40,     4370,   4449,   41,     40,     4364,   4462,   41,
5161
    40,     4363,   4457,   4364,   4453,   4523,   41,     40,     4363,
5162
    4457,   4370,   4462,   41,     40,     19968,  41,     40,     20108,
5163
    41,     40,     19977,  41,     40,     22235,  41,     40,     20116,
5164
    41,     40,     20845,  41,     40,     19971,  41,     40,     20843,
5165
    41,     40,     20061,  41,     40,     21313,  41,     40,     26376,
5166
    41,     40,     28779,  41,     40,     27700,  41,     40,     26408,
5167
    41,     40,     37329,  41,     40,     22303,  41,     40,     26085,
5168
    41,     40,     26666,  41,     40,     26377,  41,     40,     31038,
5169
    41,     40,     21517,  41,     40,     29305,  41,     40,     36001,
5170
    41,     40,     31069,  41,     40,     21172,  41,     40,     20195,
5171
    41,     40,     21628,  41,     40,     23398,  41,     40,     30435,
5172
    41,     40,     20225,  41,     40,     36039,  41,     40,     21332,
5173
    41,     40,     31085,  41,     40,     20241,  41,     40,     33258,
5174
    41,     40,     33267,  41,     21839,  24188,  25991,  31631,  80,
5175
    84,     69,     50,     49,     50,     50,     50,     51,     50,
5176
    52,     50,     53,     50,     54,     50,     55,     50,     56,
5177
    50,     57,     51,     48,     51,     49,     51,     50,     51,
5178
    51,     51,     52,     51,     53,     4352,   4354,   4355,   4357,
5179
    4358,   4359,   4361,   4363,   4364,   4366,   4367,   4368,   4369,
5180
    4370,   4352,   4449,   4354,   4449,   4355,   4449,   4357,   4449,
5181
    4358,   4449,   4359,   4449,   4361,   4449,   4363,   4449,   4364,
5182
    4449,   4366,   4449,   4367,   4449,   4368,   4449,   4369,   4449,
5183
    4370,   4449,   4366,   4449,   4535,   4352,   4457,   4364,   4462,
5184
    4363,   4468,   4363,   4462,   19968,  20108,  19977,  22235,  20116,
5185
    20845,  19971,  20843,  20061,  21313,  26376,  28779,  27700,  26408,
5186
    37329,  22303,  26085,  26666,  26377,  31038,  21517,  29305,  36001,
5187
    31069,  21172,  31192,  30007,  22899,  36969,  20778,  21360,  27880,
5188
    38917,  20241,  20889,  27491,  19978,  20013,  19979,  24038,  21491,
5189
    21307,  23447,  23398,  30435,  20225,  36039,  21332,  22812,  51,
5190
    54,     51,     55,     51,     56,     51,     57,     52,     48,
5191
    52,     49,     52,     50,     52,     51,     52,     52,     52,
5192
    53,     52,     54,     52,     55,     52,     56,     52,     57,
5193
    53,     48,     49,     26376,  50,     26376,  51,     26376,  52,
5194
    26376,  53,     26376,  54,     26376,  55,     26376,  56,     26376,
5195
    57,     26376,  49,     48,     26376,  49,     49,     26376,  49,
5196
    50,     26376,  72,     103,    101,    114,    103,    101,    86,
5197
    76,     84,     68,     12450,  12452,  12454,  12456,  12458,  12459,
5198
    12461,  12463,  12465,  12467,  12469,  12471,  12473,  12475,  12477,
5199
    12479,  12481,  12484,  12486,  12488,  12490,  12491,  12492,  12493,
5200
    12494,  12495,  12498,  12501,  12504,  12507,  12510,  12511,  12512,
5201
    12513,  12514,  12516,  12518,  12520,  12521,  12522,  12523,  12524,
5202
    12525,  12527,  12528,  12529,  12530,  20196,  21644,  12450,  12495,
5203
    12442,  12540,  12488,  12450,  12523,  12501,  12449,  12450,  12531,
5204
    12504,  12442,  12450,  12450,  12540,  12523,  12452,  12491,  12531,
5205
    12463,  12441,  12452,  12531,  12481,  12454,  12457,  12531,  12456,
5206
    12473,  12463,  12540,  12488,  12441,  12456,  12540,  12459,  12540,
5207
    12458,  12531,  12473,  12458,  12540,  12512,  12459,  12452,  12522,
5208
    12459,  12521,  12483,  12488,  12459,  12525,  12522,  12540,  12459,
5209
    12441,  12525,  12531,  12459,  12441,  12531,  12510,  12461,  12441,
5210
    12459,  12441,  12461,  12441,  12491,  12540,  12461,  12517,  12522,
5211
    12540,  12461,  12441,  12523,  12479,  12441,  12540,  12461,  12525,
5212
    12461,  12525,  12463,  12441,  12521,  12512,  12461,  12525,  12513,
5213
    12540,  12488,  12523,  12461,  12525,  12527,  12483,  12488,  12463,
5214
    12441,  12521,  12512,  12463,  12441,  12521,  12512,  12488,  12531,
5215
    12463,  12523,  12475,  12441,  12452,  12525,  12463,  12525,  12540,
5216
    12493,  12465,  12540,  12473,  12467,  12523,  12490,  12467,  12540,
5217
    12507,  12442,  12469,  12452,  12463,  12523,  12469,  12531,  12481,
5218
    12540,  12512,  12471,  12522,  12531,  12463,  12441,  12475,  12531,
5219
    12481,  12475,  12531,  12488,  12479,  12441,  12540,  12473,  12486,
5220
    12441,  12471,  12488,  12441,  12523,  12488,  12531,  12490,  12494,
5221
    12494,  12483,  12488,  12495,  12452,  12484,  12495,  12442,  12540,
5222
    12475,  12531,  12488,  12495,  12442,  12540,  12484,  12495,  12441,
5223
    12540,  12524,  12523,  12498,  12442,  12450,  12473,  12488,  12523,
5224
    12498,  12442,  12463,  12523,  12498,  12442,  12467,  12498,  12441,
5225
    12523,  12501,  12449,  12521,  12483,  12488,  12441,  12501,  12451,
5226
    12540,  12488,  12501,  12441,  12483,  12471,  12455,  12523,  12501,
5227
    12521,  12531,  12504,  12463,  12479,  12540,  12523,  12504,  12442,
5228
    12477,  12504,  12442,  12491,  12498,  12504,  12523,  12484,  12504,
5229
    12442,  12531,  12473,  12504,  12442,  12540,  12471,  12441,  12504,
5230
    12441,  12540,  12479,  12507,  12442,  12452,  12531,  12488,  12507,
5231
    12441,  12523,  12488,  12507,  12531,  12507,  12442,  12531,  12488,
5232
    12441,  12507,  12540,  12523,  12507,  12540,  12531,  12510,  12452,
5233
    12463,  12525,  12510,  12452,  12523,  12510,  12483,  12495,  12510,
5234
    12523,  12463,  12510,  12531,  12471,  12519,  12531,  12511,  12463,
5235
    12525,  12531,  12511,  12522,  12511,  12522,  12495,  12441,  12540,
5236
    12523,  12513,  12459,  12441,  12513,  12459,  12441,  12488,  12531,
5237
    12513,  12540,  12488,  12523,  12516,  12540,  12488,  12441,  12516,
5238
    12540,  12523,  12518,  12450,  12531,  12522,  12483,  12488,  12523,
5239
    12522,  12521,  12523,  12498,  12442,  12540,  12523,  12540,  12501,
5240
    12441,  12523,  12524,  12512,  12524,  12531,  12488,  12465,  12441,
5241
    12531,  12527,  12483,  12488,  48,     28857,  49,     28857,  50,
5242
    28857,  51,     28857,  52,     28857,  53,     28857,  54,     28857,
5243
    55,     28857,  56,     28857,  57,     28857,  49,     48,     28857,
5244
    49,     49,     28857,  49,     50,     28857,  49,     51,     28857,
5245
    49,     52,     28857,  49,     53,     28857,  49,     54,     28857,
5246
    49,     55,     28857,  49,     56,     28857,  49,     57,     28857,
5247
    50,     48,     28857,  50,     49,     28857,  50,     50,     28857,
5248
    50,     51,     28857,  50,     52,     28857,  104,    80,     97,
5249
    100,    97,     65,     85,     98,     97,     114,    111,    86,
5250
    112,    99,     100,    109,    100,    109,    50,     100,    109,
5251
    51,     73,     85,     24179,  25104,  26157,  21644,  22823,  27491,
5252
    26126,  27835,  26666,  24335,  20250,  31038,  112,    65,     110,
5253
    65,     956,    65,     109,    65,     107,    65,     75,     66,
5254
    77,     66,     71,     66,     99,     97,     108,    107,    99,
5255
    97,     108,    112,    70,     110,    70,     956,    70,     956,
5256
    103,    109,    103,    107,    103,    72,     122,    107,    72,
5257
    122,    77,     72,     122,    71,     72,     122,    84,     72,
5258
    122,    956,    108,    109,    108,    100,    108,    107,    108,
5259
    102,    109,    110,    109,    956,    109,    109,    109,    99,
5260
    109,    107,    109,    109,    109,    50,     99,     109,    50,
5261
    109,    50,     107,    109,    50,     109,    109,    51,     99,
5262
    109,    51,     109,    51,     107,    109,    51,     109,    8725,
5263
    115,    109,    8725,   115,    50,     80,     97,     107,    80,
5264
    97,     77,     80,     97,     71,     80,     97,     114,    97,
5265
    100,    114,    97,     100,    8725,   115,    114,    97,     100,
5266
    8725,   115,    50,     112,    115,    110,    115,    956,    115,
5267
    109,    115,    112,    86,     110,    86,     956,    86,     109,
5268
    86,     107,    86,     77,     86,     112,    87,     110,    87,
5269
    956,    87,     109,    87,     107,    87,     77,     87,     107,
5270
    937,    77,     937,    97,     46,     109,    46,     66,     113,
5271
    99,     99,     99,     100,    67,     8725,   107,    103,    67,
5272
    111,    46,     100,    66,     71,     121,    104,    97,     72,
5273
    80,     105,    110,    75,     75,     75,     77,     107,    116,
5274
    108,    109,    108,    110,    108,    111,    103,    108,    120,
5275
    109,    98,     109,    105,    108,    109,    111,    108,    80,
5276
    72,     112,    46,     109,    46,     80,     80,     77,     80,
5277
    82,     115,    114,    83,     118,    87,     98,     86,     8725,
5278
    109,    65,     8725,   109,    49,     26085,  50,     26085,  51,
5279
    26085,  52,     26085,  53,     26085,  54,     26085,  55,     26085,
5280
    56,     26085,  57,     26085,  49,     48,     26085,  49,     49,
5281
    26085,  49,     50,     26085,  49,     51,     26085,  49,     52,
5282
    26085,  49,     53,     26085,  49,     54,     26085,  49,     55,
5283
    26085,  49,     56,     26085,  49,     57,     26085,  50,     48,
5284
    26085,  50,     49,     26085,  50,     50,     26085,  50,     51,
5285
    26085,  50,     52,     26085,  50,     53,     26085,  50,     54,
5286
    26085,  50,     55,     26085,  50,     56,     26085,  50,     57,
5287
    26085,  51,     48,     26085,  51,     49,     26085,  103,    97,
5288
    108,    1098,   1100,   42863,  67,     70,     81,     294,    339,
5289
    42791,  43831,  619,    43858,  653,    35912,  26356,  36554,  36040,
5290
    28369,  20018,  21477,  40860,  40860,  22865,  37329,  21895,  22856,
5291
    25078,  30313,  32645,  34367,  34746,  35064,  37007,  27138,  27931,
5292
    28889,  29662,  33853,  37226,  39409,  20098,  21365,  27396,  29211,
5293
    34349,  40478,  23888,  28651,  34253,  35172,  25289,  33240,  34847,
5294
    24266,  26391,  28010,  29436,  37070,  20358,  20919,  21214,  25796,
5295
    27347,  29200,  30439,  32769,  34310,  34396,  36335,  38706,  39791,
5296
    40442,  30860,  31103,  32160,  33737,  37636,  40575,  35542,  22751,
5297
    24324,  31840,  32894,  29282,  30922,  36034,  38647,  22744,  23650,
5298
    27155,  28122,  28431,  32047,  32311,  38475,  21202,  32907,  20956,
5299
    20940,  31260,  32190,  33777,  38517,  35712,  25295,  27138,  35582,
5300
    20025,  23527,  24594,  29575,  30064,  21271,  30971,  20415,  24489,
5301
    19981,  27852,  25976,  32034,  21443,  22622,  30465,  33865,  35498,
5302
    27578,  36784,  27784,  25342,  33509,  25504,  30053,  20142,  20841,
5303
    20937,  26753,  31975,  33391,  35538,  37327,  21237,  21570,  22899,
5304
    24300,  26053,  28670,  31018,  38317,  39530,  40599,  40654,  21147,
5305
    26310,  27511,  36706,  24180,  24976,  25088,  25754,  28451,  29001,
5306
    29833,  31178,  32244,  32879,  36646,  34030,  36899,  37706,  21015,
5307
    21155,  21693,  28872,  35010,  35498,  24265,  24565,  25467,  27566,
5308
    31806,  29557,  20196,  22265,  23527,  23994,  24604,  29618,  29801,
5309
    32666,  32838,  37428,  38646,  38728,  38936,  20363,  31150,  37300,
5310
    38584,  24801,  20102,  20698,  23534,  23615,  26009,  27138,  29134,
5311
    30274,  34044,  36988,  40845,  26248,  38446,  21129,  26491,  26611,
5312
    27969,  28316,  29705,  30041,  30827,  32016,  39006,  20845,  25134,
5313
    38520,  20523,  23833,  28138,  36650,  24459,  24900,  26647,  29575,
5314
    38534,  21033,  21519,  23653,  26131,  26446,  26792,  27877,  29702,
5315
    30178,  32633,  35023,  35041,  37324,  38626,  21311,  28346,  21533,
5316
    29136,  29848,  34298,  38563,  40023,  40607,  26519,  28107,  33256,
5317
    31435,  31520,  31890,  29376,  28825,  35672,  20160,  33590,  21050,
5318
    20999,  24230,  25299,  31958,  23429,  27934,  26292,  36667,  34892,
5319
    38477,  35211,  24275,  20800,  21952,  22618,  26228,  20958,  29482,
5320
    30410,  31036,  31070,  31077,  31119,  38742,  31934,  32701,  34322,
5321
    35576,  36920,  37117,  39151,  39164,  39208,  40372,  37086,  38583,
5322
    20398,  20711,  20813,  21193,  21220,  21329,  21917,  22022,  22120,
5323
    22592,  22696,  23652,  23662,  24724,  24936,  24974,  25074,  25935,
5324
    26082,  26257,  26757,  28023,  28186,  28450,  29038,  29227,  29730,
5325
    30865,  31038,  31049,  31048,  31056,  31062,  31069,  31117,  31118,
5326
    31296,  31361,  31680,  32244,  32265,  32321,  32626,  32773,  33261,
5327
    33401,  33401,  33879,  35088,  35222,  35585,  35641,  36051,  36104,
5328
    36790,  36920,  38627,  38911,  38971,  24693,  148206, 33304,  20006,
5329
    20917,  20840,  20352,  20805,  20864,  21191,  21242,  21917,  21845,
5330
    21913,  21986,  22618,  22707,  22852,  22868,  23138,  23336,  24274,
5331
    24281,  24425,  24493,  24792,  24910,  24840,  24974,  24928,  25074,
5332
    25140,  25540,  25628,  25682,  25942,  26228,  26391,  26395,  26454,
5333
    27513,  27578,  27969,  28379,  28363,  28450,  28702,  29038,  30631,
5334
    29237,  29359,  29482,  29809,  29958,  30011,  30237,  30239,  30410,
5335
    30427,  30452,  30538,  30528,  30924,  31409,  31680,  31867,  32091,
5336
    32244,  32574,  32773,  33618,  33775,  34681,  35137,  35206,  35222,
5337
    35519,  35576,  35531,  35585,  35582,  35565,  35641,  35722,  36104,
5338
    36664,  36978,  37273,  37494,  38524,  38627,  38742,  38875,  38911,
5339
    38923,  38971,  39698,  40860,  141386, 141380, 144341, 15261,  16408,
5340
    16441,  152137, 154832, 163539, 40771,  40846,  102,    102,    102,
5341
    105,    102,    108,    102,    102,    105,    102,    102,    108,
5342
    115,    116,    115,    116,    1396,   1398,   1396,   1381,   1396,
5343
    1387,   1406,   1398,   1396,   1389,   1497,   1460,   1522,   1463,
5344
    1506,   1488,   1491,   1492,   1499,   1500,   1501,   1512,   1514,
5345
    43,     1513,   1473,   1513,   1474,   1513,   1468,   1473,   1513,
5346
    1468,   1474,   1488,   1463,   1488,   1464,   1488,   1468,   1489,
5347
    1468,   1490,   1468,   1491,   1468,   1492,   1468,   1493,   1468,
5348
    1494,   1468,   1496,   1468,   1497,   1468,   1498,   1468,   1499,
5349
    1468,   1500,   1468,   1502,   1468,   1504,   1468,   1505,   1468,
5350
    1507,   1468,   1508,   1468,   1510,   1468,   1511,   1468,   1512,
5351
    1468,   1513,   1468,   1514,   1468,   1493,   1465,   1489,   1471,
5352
    1499,   1471,   1508,   1471,   1488,   1500,   1649,   1649,   1659,
5353
    1659,   1659,   1659,   1662,   1662,   1662,   1662,   1664,   1664,
5354
    1664,   1664,   1658,   1658,   1658,   1658,   1663,   1663,   1663,
5355
    1663,   1657,   1657,   1657,   1657,   1700,   1700,   1700,   1700,
5356
    1702,   1702,   1702,   1702,   1668,   1668,   1668,   1668,   1667,
5357
    1667,   1667,   1667,   1670,   1670,   1670,   1670,   1671,   1671,
5358
    1671,   1671,   1677,   1677,   1676,   1676,   1678,   1678,   1672,
5359
    1672,   1688,   1688,   1681,   1681,   1705,   1705,   1705,   1705,
5360
    1711,   1711,   1711,   1711,   1715,   1715,   1715,   1715,   1713,
5361
    1713,   1713,   1713,   1722,   1722,   1723,   1723,   1723,   1723,
5362
    1749,   1620,   1749,   1620,   1729,   1729,   1729,   1729,   1726,
5363
    1726,   1726,   1726,   1746,   1746,   1746,   1620,   1746,   1620,
5364
    1709,   1709,   1709,   1709,   1735,   1735,   1734,   1734,   1736,
5365
    1736,   1735,   1652,   1739,   1739,   1733,   1733,   1737,   1737,
5366
    1744,   1744,   1744,   1744,   1609,   1609,   1610,   1620,   1575,
5367
    1610,   1620,   1575,   1610,   1620,   1749,   1610,   1620,   1749,
5368
    1610,   1620,   1608,   1610,   1620,   1608,   1610,   1620,   1735,
5369
    1610,   1620,   1735,   1610,   1620,   1734,   1610,   1620,   1734,
5370
    1610,   1620,   1736,   1610,   1620,   1736,   1610,   1620,   1744,
5371
    1610,   1620,   1744,   1610,   1620,   1744,   1610,   1620,   1609,
5372
    1610,   1620,   1609,   1610,   1620,   1609,   1740,   1740,   1740,
5373
    1740,   1610,   1620,   1580,   1610,   1620,   1581,   1610,   1620,
5374
    1605,   1610,   1620,   1609,   1610,   1620,   1610,   1576,   1580,
5375
    1576,   1581,   1576,   1582,   1576,   1605,   1576,   1609,   1576,
5376
    1610,   1578,   1580,   1578,   1581,   1578,   1582,   1578,   1605,
5377
    1578,   1609,   1578,   1610,   1579,   1580,   1579,   1605,   1579,
5378
    1609,   1579,   1610,   1580,   1581,   1580,   1605,   1581,   1580,
5379
    1581,   1605,   1582,   1580,   1582,   1581,   1582,   1605,   1587,
5380
    1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,   1581,
5381
    1589,   1605,   1590,   1580,   1590,   1581,   1590,   1582,   1590,
5382
    1605,   1591,   1581,   1591,   1605,   1592,   1605,   1593,   1580,
5383
    1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,   1601,
5384
    1581,   1601,   1582,   1601,   1605,   1601,   1609,   1601,   1610,
5385
    1602,   1581,   1602,   1605,   1602,   1609,   1602,   1610,   1603,
5386
    1575,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5387
    1603,   1605,   1603,   1609,   1603,   1610,   1604,   1580,   1604,
5388
    1581,   1604,   1582,   1604,   1605,   1604,   1609,   1604,   1610,
5389
    1605,   1580,   1605,   1581,   1605,   1582,   1605,   1605,   1605,
5390
    1609,   1605,   1610,   1606,   1580,   1606,   1581,   1606,   1582,
5391
    1606,   1605,   1606,   1609,   1606,   1610,   1607,   1580,   1607,
5392
    1605,   1607,   1609,   1607,   1610,   1610,   1580,   1610,   1581,
5393
    1610,   1582,   1610,   1605,   1610,   1609,   1610,   1610,   1584,
5394
    1648,   1585,   1648,   1609,   1648,   32,     1612,   1617,   32,
5395
    1613,   1617,   32,     1614,   1617,   32,     1615,   1617,   32,
5396
    1616,   1617,   32,     1617,   1648,   1610,   1620,   1585,   1610,
5397
    1620,   1586,   1610,   1620,   1605,   1610,   1620,   1606,   1610,
5398
    1620,   1609,   1610,   1620,   1610,   1576,   1585,   1576,   1586,
5399
    1576,   1605,   1576,   1606,   1576,   1609,   1576,   1610,   1578,
5400
    1585,   1578,   1586,   1578,   1605,   1578,   1606,   1578,   1609,
5401
    1578,   1610,   1579,   1585,   1579,   1586,   1579,   1605,   1579,
5402
    1606,   1579,   1609,   1579,   1610,   1601,   1609,   1601,   1610,
5403
    1602,   1609,   1602,   1610,   1603,   1575,   1603,   1604,   1603,
5404
    1605,   1603,   1609,   1603,   1610,   1604,   1605,   1604,   1609,
5405
    1604,   1610,   1605,   1575,   1605,   1605,   1606,   1585,   1606,
5406
    1586,   1606,   1605,   1606,   1606,   1606,   1609,   1606,   1610,
5407
    1609,   1648,   1610,   1585,   1610,   1586,   1610,   1605,   1610,
5408
    1606,   1610,   1609,   1610,   1610,   1610,   1620,   1580,   1610,
5409
    1620,   1581,   1610,   1620,   1582,   1610,   1620,   1605,   1610,
5410
    1620,   1607,   1576,   1580,   1576,   1581,   1576,   1582,   1576,
5411
    1605,   1576,   1607,   1578,   1580,   1578,   1581,   1578,   1582,
5412
    1578,   1605,   1578,   1607,   1579,   1605,   1580,   1581,   1580,
5413
    1605,   1581,   1580,   1581,   1605,   1582,   1580,   1582,   1605,
5414
    1587,   1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,
5415
    1581,   1589,   1582,   1589,   1605,   1590,   1580,   1590,   1581,
5416
    1590,   1582,   1590,   1605,   1591,   1581,   1592,   1605,   1593,
5417
    1580,   1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,
5418
    1601,   1581,   1601,   1582,   1601,   1605,   1602,   1581,   1602,
5419
    1605,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5420
    1603,   1605,   1604,   1580,   1604,   1581,   1604,   1582,   1604,
5421
    1605,   1604,   1607,   1605,   1580,   1605,   1581,   1605,   1582,
5422
    1605,   1605,   1606,   1580,   1606,   1581,   1606,   1582,   1606,
5423
    1605,   1606,   1607,   1607,   1580,   1607,   1605,   1607,   1648,
5424
    1610,   1580,   1610,   1581,   1610,   1582,   1610,   1605,   1610,
5425
    1607,   1610,   1620,   1605,   1610,   1620,   1607,   1576,   1605,
5426
    1576,   1607,   1578,   1605,   1578,   1607,   1579,   1605,   1579,
5427
    1607,   1587,   1605,   1587,   1607,   1588,   1605,   1588,   1607,
5428
    1603,   1604,   1603,   1605,   1604,   1605,   1606,   1605,   1606,
5429
    1607,   1610,   1605,   1610,   1607,   1600,   1614,   1617,   1600,
5430
    1615,   1617,   1600,   1616,   1617,   1591,   1609,   1591,   1610,
5431
    1593,   1609,   1593,   1610,   1594,   1609,   1594,   1610,   1587,
5432
    1609,   1587,   1610,   1588,   1609,   1588,   1610,   1581,   1609,
5433
    1581,   1610,   1580,   1609,   1580,   1610,   1582,   1609,   1582,
5434
    1610,   1589,   1609,   1589,   1610,   1590,   1609,   1590,   1610,
5435
    1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1588,
5436
    1585,   1587,   1585,   1589,   1585,   1590,   1585,   1591,   1609,
5437
    1591,   1610,   1593,   1609,   1593,   1610,   1594,   1609,   1594,
5438
    1610,   1587,   1609,   1587,   1610,   1588,   1609,   1588,   1610,
5439
    1581,   1609,   1581,   1610,   1580,   1609,   1580,   1610,   1582,
5440
    1609,   1582,   1610,   1589,   1609,   1589,   1610,   1590,   1609,
5441
    1590,   1610,   1588,   1580,   1588,   1581,   1588,   1582,   1588,
5442
    1605,   1588,   1585,   1587,   1585,   1589,   1585,   1590,   1585,
5443
    1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1587,
5444
    1607,   1588,   1607,   1591,   1605,   1587,   1580,   1587,   1581,
5445
    1587,   1582,   1588,   1580,   1588,   1581,   1588,   1582,   1591,
5446
    1605,   1592,   1605,   1575,   1611,   1575,   1611,   1578,   1580,
5447
    1605,   1578,   1581,   1580,   1578,   1581,   1580,   1578,   1581,
5448
    1605,   1578,   1582,   1605,   1578,   1605,   1580,   1578,   1605,
5449
    1581,   1578,   1605,   1582,   1580,   1605,   1581,   1580,   1605,
5450
    1581,   1581,   1605,   1610,   1581,   1605,   1609,   1587,   1581,
5451
    1580,   1587,   1580,   1581,   1587,   1580,   1609,   1587,   1605,
5452
    1581,   1587,   1605,   1581,   1587,   1605,   1580,   1587,   1605,
5453
    1605,   1587,   1605,   1605,   1589,   1581,   1581,   1589,   1581,
5454
    1581,   1589,   1605,   1605,   1588,   1581,   1605,   1588,   1581,
5455
    1605,   1588,   1580,   1610,   1588,   1605,   1582,   1588,   1605,
5456
    1582,   1588,   1605,   1605,   1588,   1605,   1605,   1590,   1581,
5457
    1609,   1590,   1582,   1605,   1590,   1582,   1605,   1591,   1605,
5458
    1581,   1591,   1605,   1581,   1591,   1605,   1605,   1591,   1605,
5459
    1610,   1593,   1580,   1605,   1593,   1605,   1605,   1593,   1605,
5460
    1605,   1593,   1605,   1609,   1594,   1605,   1605,   1594,   1605,
5461
    1610,   1594,   1605,   1609,   1601,   1582,   1605,   1601,   1582,
5462
    1605,   1602,   1605,   1581,   1602,   1605,   1605,   1604,   1581,
5463
    1605,   1604,   1581,   1610,   1604,   1581,   1609,   1604,   1580,
5464
    1580,   1604,   1580,   1580,   1604,   1582,   1605,   1604,   1582,
5465
    1605,   1604,   1605,   1581,   1604,   1605,   1581,   1605,   1581,
5466
    1580,   1605,   1581,   1605,   1605,   1581,   1610,   1605,   1580,
5467
    1581,   1605,   1580,   1605,   1605,   1582,   1580,   1605,   1582,
5468
    1605,   1605,   1580,   1582,   1607,   1605,   1580,   1607,   1605,
5469
    1605,   1606,   1581,   1605,   1606,   1581,   1609,   1606,   1580,
5470
    1605,   1606,   1580,   1605,   1606,   1580,   1609,   1606,   1605,
5471
    1610,   1606,   1605,   1609,   1610,   1605,   1605,   1610,   1605,
5472
    1605,   1576,   1582,   1610,   1578,   1580,   1610,   1578,   1580,
5473
    1609,   1578,   1582,   1610,   1578,   1582,   1609,   1578,   1605,
5474
    1610,   1578,   1605,   1609,   1580,   1605,   1610,   1580,   1581,
5475
    1609,   1580,   1605,   1609,   1587,   1582,   1609,   1589,   1581,
5476
    1610,   1588,   1581,   1610,   1590,   1581,   1610,   1604,   1580,
5477
    1610,   1604,   1605,   1610,   1610,   1581,   1610,   1610,   1580,
5478
    1610,   1610,   1605,   1610,   1605,   1605,   1610,   1602,   1605,
5479
    1610,   1606,   1581,   1610,   1602,   1605,   1581,   1604,   1581,
5480
    1605,   1593,   1605,   1610,   1603,   1605,   1610,   1606,   1580,
5481
    1581,   1605,   1582,   1610,   1604,   1580,   1605,   1603,   1605,
5482
    1605,   1604,   1580,   1605,   1606,   1580,   1581,   1580,   1581,
5483
    1610,   1581,   1580,   1610,   1605,   1580,   1610,   1601,   1605,
5484
    1610,   1576,   1581,   1610,   1603,   1605,   1605,   1593,   1580,
5485
    1605,   1589,   1605,   1605,   1587,   1582,   1610,   1606,   1580,
5486
    1610,   1589,   1604,   1746,   1602,   1604,   1746,   1575,   1604,
5487
    1604,   1607,   1575,   1603,   1576,   1585,   1605,   1581,   1605,
5488
    1583,   1589,   1604,   1593,   1605,   1585,   1587,   1608,   1604,
5489
    1593,   1604,   1610,   1607,   1608,   1587,   1604,   1605,   1589,
5490
    1604,   1609,   1589,   1604,   1609,   32,     1575,   1604,   1604,
5491
    1607,   32,     1593,   1604,   1610,   1607,   32,     1608,   1587,
5492
    1604,   1605,   1580,   1604,   32,     1580,   1604,   1575,   1604,
5493
    1607,   1585,   1740,   1575,   1604,   44,     12289,  12290,  58,
5494
    59,     33,     63,     12310,  12311,  46,     46,     46,     46,
5495
    46,     8212,   8211,   95,     95,     40,     41,     123,    125,
5496
    12308,  12309,  12304,  12305,  12298,  12299,  12296,  12297,  12300,
5497
    12301,  12302,  12303,  91,     93,     32,     773,    32,     773,
5498
    32,     773,    32,     773,    95,     95,     95,     44,     12289,
5499
    46,     59,     58,     63,     33,     8212,   40,     41,     123,
5500
    125,    12308,  12309,  35,     38,     42,     43,     45,     60,
5501
    62,     61,     92,     36,     37,     64,     32,     1611,   1600,
5502
    1611,   32,     1612,   32,     1613,   32,     1614,   1600,   1614,
5503
    32,     1615,   1600,   1615,   32,     1616,   1600,   1616,   32,
5504
    1617,   1600,   1617,   32,     1618,   1600,   1618,   1569,   1575,
5505
    1619,   1575,   1619,   1575,   1620,   1575,   1620,   1608,   1620,
5506
    1608,   1620,   1575,   1621,   1575,   1621,   1610,   1620,   1610,
5507
    1620,   1610,   1620,   1610,   1620,   1575,   1575,   1576,   1576,
5508
    1576,   1576,   1577,   1577,   1578,   1578,   1578,   1578,   1579,
5509
    1579,   1579,   1579,   1580,   1580,   1580,   1580,   1581,   1581,
5510
    1581,   1581,   1582,   1582,   1582,   1582,   1583,   1583,   1584,
5511
    1584,   1585,   1585,   1586,   1586,   1587,   1587,   1587,   1587,
5512
    1588,   1588,   1588,   1588,   1589,   1589,   1589,   1589,   1590,
5513
    1590,   1590,   1590,   1591,   1591,   1591,   1591,   1592,   1592,
5514
    1592,   1592,   1593,   1593,   1593,   1593,   1594,   1594,   1594,
5515
    1594,   1601,   1601,   1601,   1601,   1602,   1602,   1602,   1602,
5516
    1603,   1603,   1603,   1603,   1604,   1604,   1604,   1604,   1605,
5517
    1605,   1605,   1605,   1606,   1606,   1606,   1606,   1607,   1607,
5518
    1607,   1607,   1608,   1608,   1609,   1609,   1610,   1610,   1610,
5519
    1610,   1604,   1575,   1619,   1604,   1575,   1619,   1604,   1575,
5520
    1620,   1604,   1575,   1620,   1604,   1575,   1621,   1604,   1575,
5521
    1621,   1604,   1575,   1604,   1575,   33,     34,     35,     36,
5522
    37,     38,     39,     40,     41,     42,     43,     44,     45,
5523
    46,     47,     48,     49,     50,     51,     52,     53,     54,
5524
    55,     56,     57,     58,     59,     60,     61,     62,     63,
5525
    64,     65,     66,     67,     68,     69,     70,     71,     72,
5526
    73,     74,     75,     76,     77,     78,     79,     80,     81,
5527
    82,     83,     84,     85,     86,     87,     88,     89,     90,
5528
    91,     92,     93,     94,     95,     96,     97,     98,     99,
5529
    100,    101,    102,    103,    104,    105,    106,    107,    108,
5530
    109,    110,    111,    112,    113,    114,    115,    116,    117,
5531
    118,    119,    120,    121,    122,    123,    124,    125,    126,
5532
    10629,  10630,  12290,  12300,  12301,  12289,  12539,  12530,  12449,
5533
    12451,  12453,  12455,  12457,  12515,  12517,  12519,  12483,  12540,
5534
    12450,  12452,  12454,  12456,  12458,  12459,  12461,  12463,  12465,
5535
    12467,  12469,  12471,  12473,  12475,  12477,  12479,  12481,  12484,
5536
    12486,  12488,  12490,  12491,  12492,  12493,  12494,  12495,  12498,
5537
    12501,  12504,  12507,  12510,  12511,  12512,  12513,  12514,  12516,
5538
    12518,  12520,  12521,  12522,  12523,  12524,  12525,  12527,  12531,
5539
    12441,  12442,  4448,   4352,   4353,   4522,   4354,   4524,   4525,
5540
    4355,   4356,   4357,   4528,   4529,   4530,   4531,   4532,   4533,
5541
    4378,   4358,   4359,   4360,   4385,   4361,   4362,   4363,   4364,
5542
    4365,   4366,   4367,   4368,   4369,   4370,   4449,   4450,   4451,
5543
    4452,   4453,   4454,   4455,   4456,   4457,   4458,   4459,   4460,
5544
    4461,   4462,   4463,   4464,   4465,   4466,   4467,   4468,   4469,
5545
    162,    163,    172,    32,     772,    166,    165,    8361,   9474,
5546
    8592,   8593,   8594,   8595,   9632,   9675,   720,    721,    230,
5547
    665,    595,    675,    43878,  677,    676,    598,    599,    7569,
5548
    600,    606,    681,    612,    610,    608,    667,    295,    668,
5549
    615,    644,    682,    683,    620,    122628, 42894,  622,    122629,
5550
    654,    122630, 248,    630,    631,    113,    634,    122632, 637,
5551
    638,    640,    680,    678,    43879,  679,    648,    11377,  655,
5552
    673,    674,    664,    448,    449,    450,    122634, 122654, 69785,
5553
    69818,  69787,  69818,  69797,  69818,  69937,  69927,  69938,  69927,
5554
    70471,  70462,  70471,  70487,  70841,  70842,  70841,  70832,  70841,
5555
    70845,  71096,  71087,  71097,  71087,  71989,  71984,  119127, 119141,
5556
    119128, 119141, 119128, 119141, 119150, 119128, 119141, 119151, 119128,
5557
    119141, 119152, 119128, 119141, 119153, 119128, 119141, 119154, 119225,
5558
    119141, 119226, 119141, 119225, 119141, 119150, 119226, 119141, 119150,
5559
    119225, 119141, 119151, 119226, 119141, 119151, 65,     66,     67,
5560
    68,     69,     70,     71,     72,     73,     74,     75,     76,
5561
    77,     78,     79,     80,     81,     82,     83,     84,     85,
5562
    86,     87,     88,     89,     90,     97,     98,     99,     100,
5563
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5564
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5565
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5566
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5567
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5568
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5569
    103,    105,    106,    107,    108,    109,    110,    111,    112,
5570
    113,    114,    115,    116,    117,    118,    119,    120,    121,
5571
    122,    65,     66,     67,     68,     69,     70,     71,     72,
5572
    73,     74,     75,     76,     77,     78,     79,     80,     81,
5573
    82,     83,     84,     85,     86,     87,     88,     89,     90,
5574
    97,     98,     99,     100,    101,    102,    103,    104,    105,
5575
    106,    107,    108,    109,    110,    111,    112,    113,    114,
5576
    115,    116,    117,    118,    119,    120,    121,    122,    65,
5577
    67,     68,     71,     74,     75,     78,     79,     80,     81,
5578
    83,     84,     85,     86,     87,     88,     89,     90,     97,
5579
    98,     99,     100,    102,    104,    105,    106,    107,    108,
5580
    109,    110,    112,    113,    114,    115,    116,    117,    118,
5581
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5582
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5583
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5584
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5585
    103,    104,    105,    106,    107,    108,    109,    110,    111,
5586
    112,    113,    114,    115,    116,    117,    118,    119,    120,
5587
    121,    122,    65,     66,     68,     69,     70,     71,     74,
5588
    75,     76,     77,     78,     79,     80,     81,     83,     84,
5589
    85,     86,     87,     88,     89,     97,     98,     99,     100,
5590
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5591
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5592
    119,    120,    121,    122,    65,     66,     68,     69,     70,
5593
    71,     73,     74,     75,     76,     77,     79,     83,     84,
5594
    85,     86,     87,     88,     89,     97,     98,     99,     100,
5595
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5596
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5597
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5598
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5599
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5600
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5601
    103,    104,    105,    106,    107,    108,    109,    110,    111,
5602
    112,    113,    114,    115,    116,    117,    118,    119,    120,
5603
    121,    122,    65,     66,     67,     68,     69,     70,     71,
5604
    72,     73,     74,     75,     76,     77,     78,     79,     80,
5605
    81,     82,     83,     84,     85,     86,     87,     88,     89,
5606
    90,     97,     98,     99,     100,    101,    102,    103,    104,
5607
    105,    106,    107,    108,    109,    110,    111,    112,    113,
5608
    114,    115,    116,    117,    118,    119,    120,    121,    122,
5609
    65,     66,     67,     68,     69,     70,     71,     72,     73,
5610
    74,     75,     76,     77,     78,     79,     80,     81,     82,
5611
    83,     84,     85,     86,     87,     88,     89,     90,     97,
5612
    98,     99,     100,    101,    102,    103,    104,    105,    106,
5613
    107,    108,    109,    110,    111,    112,    113,    114,    115,
5614
    116,    117,    118,    119,    120,    121,    122,    65,     66,
5615
    67,     68,     69,     70,     71,     72,     73,     74,     75,
5616
    76,     77,     78,     79,     80,     81,     82,     83,     84,
5617
    85,     86,     87,     88,     89,     90,     97,     98,     99,
5618
    100,    101,    102,    103,    104,    105,    106,    107,    108,
5619
    109,    110,    111,    112,    113,    114,    115,    116,    117,
5620
    118,    119,    120,    121,    122,    65,     66,     67,     68,
5621
    69,     70,     71,     72,     73,     74,     75,     76,     77,
5622
    78,     79,     80,     81,     82,     83,     84,     85,     86,
5623
    87,     88,     89,     90,     97,     98,     99,     100,    101,
5624
    102,    103,    104,    105,    106,    107,    108,    109,    110,
5625
    111,    112,    113,    114,    115,    116,    117,    118,    119,
5626
    120,    121,    122,    65,     66,     67,     68,     69,     70,
5627
    71,     72,     73,     74,     75,     76,     77,     78,     79,
5628
    80,     81,     82,     83,     84,     85,     86,     87,     88,
5629
    89,     90,     97,     98,     99,     100,    101,    102,    103,
5630
    104,    105,    106,    107,    108,    109,    110,    111,    112,
5631
    113,    114,    115,    116,    117,    118,    119,    120,    121,
5632
    122,    305,    567,    913,    914,    915,    916,    917,    918,
5633
    919,    920,    921,    922,    923,    924,    925,    926,    927,
5634
    928,    929,    920,    931,    932,    933,    934,    935,    936,
5635
    937,    8711,   945,    946,    947,    948,    949,    950,    951,
5636
    952,    953,    954,    955,    956,    957,    958,    959,    960,
5637
    961,    962,    963,    964,    965,    966,    967,    968,    969,
5638
    8706,   949,    952,    954,    966,    961,    960,    913,    914,
5639
    915,    916,    917,    918,    919,    920,    921,    922,    923,
5640
    924,    925,    926,    927,    928,    929,    920,    931,    932,
5641
    933,    934,    935,    936,    937,    8711,   945,    946,    947,
5642
    948,    949,    950,    951,    952,    953,    954,    955,    956,
5643
    957,    958,    959,    960,    961,    962,    963,    964,    965,
5644
    966,    967,    968,    969,    8706,   949,    952,    954,    966,
5645
    961,    960,    913,    914,    915,    916,    917,    918,    919,
5646
    920,    921,    922,    923,    924,    925,    926,    927,    928,
5647
    929,    920,    931,    932,    933,    934,    935,    936,    937,
5648
    8711,   945,    946,    947,    948,    949,    950,    951,    952,
5649
    953,    954,    955,    956,    957,    958,    959,    960,    961,
5650
    962,    963,    964,    965,    966,    967,    968,    969,    8706,
5651
    949,    952,    954,    966,    961,    960,    913,    914,    915,
5652
    916,    917,    918,    919,    920,    921,    922,    923,    924,
5653
    925,    926,    927,    928,    929,    920,    931,    932,    933,
5654
    934,    935,    936,    937,    8711,   945,    946,    947,    948,
5655
    949,    950,    951,    952,    953,    954,    955,    956,    957,
5656
    958,    959,    960,    961,    962,    963,    964,    965,    966,
5657
    967,    968,    969,    8706,   949,    952,    954,    966,    961,
5658
    960,    913,    914,    915,    916,    917,    918,    919,    920,
5659
    921,    922,    923,    924,    925,    926,    927,    928,    929,
5660
    920,    931,    932,    933,    934,    935,    936,    937,    8711,
5661
    945,    946,    947,    948,    949,    950,    951,    952,    953,
5662
    954,    955,    956,    957,    958,    959,    960,    961,    962,
5663
    963,    964,    965,    966,    967,    968,    969,    8706,   949,
5664
    952,    954,    966,    961,    960,    988,    989,    48,     49,
5665
    50,     51,     52,     53,     54,     55,     56,     57,     48,
5666
    49,     50,     51,     52,     53,     54,     55,     56,     57,
5667
    48,     49,     50,     51,     52,     53,     54,     55,     56,
5668
    57,     48,     49,     50,     51,     52,     53,     54,     55,
5669
    56,     57,     48,     49,     50,     51,     52,     53,     54,
5670
    55,     56,     57,     1072,   1073,   1074,   1075,   1076,   1077,
5671
    1078,   1079,   1080,   1082,   1083,   1084,   1086,   1087,   1088,
5672
    1089,   1090,   1091,   1092,   1093,   1094,   1095,   1096,   1099,
5673
    1101,   1102,   42633,  1241,   1110,   1112,   1257,   1199,   1231,
5674
    1072,   1073,   1074,   1075,   1076,   1077,   1078,   1079,   1080,
5675
    1082,   1083,   1086,   1087,   1089,   1091,   1092,   1093,   1094,
5676
    1095,   1096,   1098,   1099,   1169,   1110,   1109,   1119,   1195,
5677
    42577,  1201,   1575,   1576,   1580,   1583,   1608,   1586,   1581,
5678
    1591,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5679
    1589,   1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,
5680
    1592,   1594,   1646,   1722,   1697,   1647,   1576,   1580,   1607,
5681
    1581,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5682
    1589,   1602,   1588,   1578,   1579,   1582,   1590,   1594,   1580,
5683
    1581,   1610,   1604,   1606,   1587,   1593,   1589,   1602,   1588,
5684
    1582,   1590,   1594,   1722,   1647,   1576,   1580,   1607,   1581,
5685
    1591,   1610,   1603,   1605,   1606,   1587,   1593,   1601,   1589,
5686
    1602,   1588,   1578,   1579,   1582,   1590,   1592,   1594,   1646,
5687
    1697,   1575,   1576,   1580,   1583,   1607,   1608,   1586,   1581,
5688
    1591,   1610,   1604,   1605,   1606,   1587,   1593,   1601,   1589,
5689
    1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,   1592,
5690
    1594,   1576,   1580,   1583,   1608,   1586,   1581,   1591,   1610,
5691
    1604,   1605,   1606,   1587,   1593,   1601,   1589,   1602,   1585,
5692
    1588,   1578,   1579,   1582,   1584,   1590,   1592,   1594,   48,
5693
    46,     48,     44,     49,     44,     50,     44,     51,     44,
5694
    52,     44,     53,     44,     54,     44,     55,     44,     56,
5695
    44,     57,     44,     40,     65,     41,     40,     66,     41,
5696
    40,     67,     41,     40,     68,     41,     40,     69,     41,
5697
    40,     70,     41,     40,     71,     41,     40,     72,     41,
5698
    40,     73,     41,     40,     74,     41,     40,     75,     41,
5699
    40,     76,     41,     40,     77,     41,     40,     78,     41,
5700
    40,     79,     41,     40,     80,     41,     40,     81,     41,
5701
    40,     82,     41,     40,     83,     41,     40,     84,     41,
5702
    40,     85,     41,     40,     86,     41,     40,     87,     41,
5703
    40,     88,     41,     40,     89,     41,     40,     90,     41,
5704
    12308,  83,     12309,  67,     82,     67,     68,     87,     90,
5705
    65,     66,     67,     68,     69,     70,     71,     72,     73,
5706
    74,     75,     76,     77,     78,     79,     80,     81,     82,
5707
    83,     84,     85,     86,     87,     88,     89,     90,     72,
5708
    86,     77,     86,     83,     68,     83,     83,     80,     80,
5709
    86,     87,     67,     77,     67,     77,     68,     77,     82,
5710
    68,     74,     12411,  12363,  12467,  12467,  12469,  25163,  23383,
5711
    21452,  12486,  12441,  20108,  22810,  35299,  22825,  20132,  26144,
5712
    28961,  26009,  21069,  24460,  20877,  26032,  21021,  32066,  29983,
5713
    36009,  22768,  21561,  28436,  25237,  25429,  19968,  19977,  36938,
5714
    24038,  20013,  21491,  25351,  36208,  25171,  31105,  31354,  21512,
5715
    28288,  26377,  26376,  30003,  21106,  21942,  37197,  12308,  26412,
5716
    12309,  12308,  19977,  12309,  12308,  20108,  12309,  12308,  23433,
5717
    12309,  12308,  28857,  12309,  12308,  25171,  12309,  12308,  30423,
5718
    12309,  12308,  21213,  12309,  12308,  25943,  12309,  24471,  21487,
5719
    48,     49,     50,     51,     52,     53,     54,     55,     56,
5720
    57,     20029,  20024,  20033,  131362, 20320,  20398,  20411,  20482,
5721
    20602,  20633,  20711,  20687,  13470,  132666, 20813,  20820,  20836,
5722
    20855,  132380, 13497,  20839,  20877,  132427, 20887,  20900,  20172,
5723
    20908,  20917,  168415, 20981,  20995,  13535,  21051,  21062,  21106,
5724
    21111,  13589,  21191,  21193,  21220,  21242,  21253,  21254,  21271,
5725
    21321,  21329,  21338,  21363,  21373,  21375,  21375,  21375,  133676,
5726
    28784,  21450,  21471,  133987, 21483,  21489,  21510,  21662,  21560,
5727
    21576,  21608,  21666,  21750,  21776,  21843,  21859,  21892,  21892,
5728
    21913,  21931,  21939,  21954,  22294,  22022,  22295,  22097,  22132,
5729
    20999,  22766,  22478,  22516,  22541,  22411,  22578,  22577,  22700,
5730
    136420, 22770,  22775,  22790,  22810,  22818,  22882,  136872, 136938,
5731
    23020,  23067,  23079,  23000,  23142,  14062,  14076,  23304,  23358,
5732
    23358,  137672, 23491,  23512,  23527,  23539,  138008, 23551,  23558,
5733
    24403,  23586,  14209,  23648,  23662,  23744,  23693,  138724, 23875,
5734
    138726, 23918,  23915,  23932,  24033,  24034,  14383,  24061,  24104,
5735
    24125,  24169,  14434,  139651, 14460,  24240,  24243,  24246,  24266,
5736
    172946, 24318,  140081, 140081, 33281,  24354,  24354,  14535,  144056,
5737
    156122, 24418,  24427,  14563,  24474,  24525,  24535,  24569,  24705,
5738
    14650,  14620,  24724,  141012, 24775,  24904,  24908,  24910,  24908,
5739
    24954,  24974,  25010,  24996,  25007,  25054,  25074,  25078,  25104,
5740
    25115,  25181,  25265,  25300,  25424,  142092, 25405,  25340,  25448,
5741
    25475,  25572,  142321, 25634,  25541,  25513,  14894,  25705,  25726,
5742
    25757,  25719,  14956,  25935,  25964,  143370, 26083,  26360,  26185,
5743
    15129,  26257,  15112,  15076,  20882,  20885,  26368,  26268,  32941,
5744
    17369,  26391,  26395,  26401,  26462,  26451,  144323, 15177,  26618,
5745
    26501,  26706,  26757,  144493, 26766,  26655,  26900,  15261,  26946,
5746
    27043,  27114,  27304,  145059, 27355,  15384,  27425,  145575, 27476,
5747
    15438,  27506,  27551,  27578,  27579,  146061, 138507, 146170, 27726,
5748
    146620, 27839,  27853,  27751,  27926,  27966,  28023,  27969,  28009,
5749
    28024,  28037,  146718, 27956,  28207,  28270,  15667,  28363,  28359,
5750
    147153, 28153,  28526,  147294, 147342, 28614,  28729,  28702,  28699,
5751
    15766,  28746,  28797,  28791,  28845,  132389, 28997,  148067, 29084,
5752
    148395, 29224,  29237,  29264,  149000, 29312,  29333,  149301, 149524,
5753
    29562,  29579,  16044,  29605,  16056,  16056,  29767,  29788,  29809,
5754
    29829,  29898,  16155,  29988,  150582, 30014,  150674, 30064,  139679,
5755
    30224,  151457, 151480, 151620, 16380,  16392,  30452,  151795, 151794,
5756
    151833, 151859, 30494,  30495,  30495,  30538,  16441,  30603,  16454,
5757
    16534,  152605, 30798,  30860,  30924,  16611,  153126, 31062,  153242,
5758
    153285, 31119,  31211,  16687,  31296,  31306,  31311,  153980, 154279,
5759
    154279, 31470,  16898,  154539, 31686,  31689,  16935,  154752, 31954,
5760
    17056,  31976,  31971,  32000,  155526, 32099,  17153,  32199,  32258,
5761
    32325,  17204,  156200, 156231, 17241,  156377, 32634,  156478, 32661,
5762
    32762,  32773,  156890, 156963, 32864,  157096, 32880,  144223, 17365,
5763
    32946,  33027,  17419,  33086,  23221,  157607, 157621, 144275, 144284,
5764
    33281,  33284,  36766,  17515,  33425,  33419,  33437,  21171,  33457,
5765
    33459,  33469,  33510,  158524, 33509,  33565,  33635,  33709,  33571,
5766
    33725,  33767,  33879,  33619,  33738,  33740,  33756,  158774, 159083,
5767
    158933, 17707,  34033,  34035,  34070,  160714, 34148,  159532, 17757,
5768
    17761,  159665, 159954, 17771,  34384,  34396,  34407,  34409,  34473,
5769
    34440,  34574,  34530,  34681,  34600,  34667,  34694,  17879,  34785,
5770
    34817,  17913,  34912,  34915,  161383, 35031,  35038,  17973,  35066,
5771
    13499,  161966, 162150, 18110,  18119,  35488,  35565,  35722,  35925,
5772
    162984, 36011,  36033,  36123,  36215,  163631, 133124, 36299,  36284,
5773
    36336,  133342, 36564,  36664,  165330, 165357, 37012,  37105,  37137,
5774
    165678, 37147,  37432,  37591,  37592,  37500,  37881,  37909,  166906,
5775
    38283,  18837,  38327,  167287, 18918,  38595,  23986,  38691,  168261,
5776
    168474, 19054,  19062,  38880,  168970, 19122,  169110, 38923,  38923,
5777
    38953,  169398, 39138,  19251,  39209,  39335,  39362,  39422,  19406,
5778
    170800, 39698,  40000,  40189,  19662,  19693,  40295,  172238, 19704,
5779
    172293, 172558, 172689, 40635,  19798,  40697,  40702,  40709,  40719,
5780
    40726,  40763,  173568};
5781
5782
const uint8_t canonical_combining_class_index[4352] = {
5783
    0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 0,  0,
5784
    15, 0,  0,  0,  16, 17, 18, 19, 20, 21, 22, 0,  0,  23, 0,  0,  0,  0,  0,
5785
    0,  0,  0,  0,  0,  0,  24, 25, 0,  0,  26, 0,  0,  0,  0,  0,  0,  0,  0,
5786
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5787
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5788
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5789
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5790
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5791
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  27, 0,  28, 29, 30,
5792
    31, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5793
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5794
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5795
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5796
    0,  0,  0,  0,  32, 0,  0,  33, 0,  0,  34, 35, 36, 0,  0,  0,  0,  0,  0,
5797
    37, 0,  0,  38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,  52,
5798
    53, 0,  54, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5799
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5800
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5801
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5802
    0,  55, 56, 0,  0,  0,  57, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5803
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5804
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5805
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5806
    0,  0,  0,  0,  0,  0,  0,  58, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5807
    0,  0,  0,  0,  0,  0,  0,  0,  0,  59, 60, 0,  0,  0,  0,  0,  0,  0,  0,
5808
    0,  0,  0,  0,  0,  61, 56, 62, 0,  63, 0,  0,  0,  64, 65, 0,  0,  0,  0,
5809
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5810
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5811
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5812
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5813
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5814
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5815
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5816
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5817
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5818
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5819
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5820
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5821
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5822
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5823
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5824
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5825
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5826
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5827
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5828
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5829
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5830
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5831
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5832
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5833
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5834
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5835
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5836
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5837
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5838
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5839
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5840
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5841
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5842
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5843
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5844
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5845
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5846
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5847
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5848
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5849
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5850
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5851
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5852
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5853
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5854
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5855
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5856
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5857
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5858
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5859
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5860
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5861
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5862
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5863
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5864
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5865
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5866
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5867
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5868
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5869
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5870
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5871
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5872
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5873
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5874
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5875
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5876
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5877
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5878
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5879
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5880
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5881
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5882
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5883
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5884
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5885
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5886
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5887
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5888
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5889
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5890
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5891
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5892
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5893
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5894
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5895
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5896
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5897
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5898
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5899
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5900
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5901
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5902
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5903
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5904
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5905
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5906
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5907
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5908
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5909
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5910
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5911
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5912
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5913
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5914
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5915
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5916
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5917
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5918
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5919
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5920
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5921
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5922
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5923
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5924
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5925
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5926
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5927
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5928
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5929
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5930
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5931
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5932
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5933
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5934
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5935
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5936
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5937
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5938
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5939
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5940
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5941
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5942
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5943
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5944
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5945
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5946
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5947
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5948
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5949
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5950
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5951
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5952
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5953
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5954
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5955
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5956
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5957
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5958
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5959
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5960
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5961
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5962
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5963
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5964
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5965
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5966
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5967
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5968
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5969
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5970
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5971
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5972
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5973
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5974
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5975
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5976
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5977
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5978
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5979
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5980
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5981
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5982
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5983
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5984
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5985
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5986
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5987
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5988
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5989
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5990
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5991
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5992
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5993
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5994
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5995
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5996
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5997
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5998
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5999
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6000
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6001
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6002
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6003
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6004
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6005
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6006
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6007
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6008
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6009
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6010
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6011
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6012
    0};
6013
const uint8_t canonical_combining_class_block[67][256] = {
6014
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6015
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6016
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6017
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6018
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6019
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6020
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6021
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6022
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6023
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6024
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6025
    {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6026
     230, 230, 230, 230, 230, 230, 232, 220, 220, 220, 220, 232, 216, 220, 220,
6027
     220, 220, 220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220,
6028
     220, 220, 220, 220, 220, 220, 220, 1,   1,   1,   1,   1,   220, 220, 220,
6029
     220, 230, 230, 230, 230, 230, 230, 230, 230, 240, 230, 220, 220, 220, 230,
6030
     230, 230, 220, 220, 0,   230, 230, 230, 220, 220, 220, 220, 230, 232, 220,
6031
     220, 230, 233, 234, 234, 233, 234, 234, 233, 230, 230, 230, 230, 230, 230,
6032
     230, 230, 230, 230, 230, 230, 230, 0,   0,   0,   0,   0,   0,   0,   0,
6033
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6034
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6035
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6036
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6037
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6038
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6039
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6040
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6041
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6042
     0},
6043
    {0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6044
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6045
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6046
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6047
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6048
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230,
6049
     230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6050
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6051
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6052
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6053
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6054
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6055
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6056
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6057
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6058
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6059
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6060
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6061
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6062
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6063
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6064
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 230, 230, 230, 230,
6065
     220, 230, 230, 230, 222, 220, 230, 230, 230, 230, 230, 230, 220, 220, 220,
6066
     220, 220, 220, 230, 230, 220, 230, 230, 222, 228, 230, 10,  11,  12,  13,
6067
     14,  15,  16,  17,  18,  19,  19,  20,  21,  22,  0,   23,  0,   24,  25,
6068
     0,   230, 220, 0,   18,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6069
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6070
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6071
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6072
     0},
6073
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6074
     0,   230, 230, 230, 230, 230, 230, 230, 230, 30,  31,  32,  0,   0,   0,
6075
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6076
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6077
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6078
     27,  28,  29,  30,  31,  32,  33,  34,  230, 230, 220, 220, 230, 230, 230,
6079
     230, 230, 220, 230, 230, 220, 0,   0,   0,   0,   0,   0,   0,   0,   0,
6080
     0,   0,   0,   0,   0,   0,   0,   35,  0,   0,   0,   0,   0,   0,   0,
6081
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6082
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6083
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6084
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6085
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6086
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6087
     0,   0,   0,   0,   230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230,
6088
     230, 230, 220, 230, 0,   0,   230, 230, 0,   220, 230, 230, 220, 0,   0,
6089
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6090
     0},
6091
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6092
     0,   0,   36,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6093
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6094
     0,   0,   0,   230, 220, 230, 230, 220, 230, 230, 220, 220, 220, 230, 220,
6095
     220, 230, 220, 230, 230, 230, 220, 230, 220, 230, 220, 230, 220, 230, 230,
6096
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6097
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6098
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6099
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6100
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6101
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6102
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6103
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6104
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6105
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6106
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 230,
6107
     230, 230, 220, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 0,
6108
     0},
6109
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6110
     0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 0,   230, 230, 230,
6111
     230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 0,   230, 230, 230, 230,
6112
     230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6113
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6114
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   220,
6115
     220, 220, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6116
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6117
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6118
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6119
     0,   0,   230, 220, 220, 220, 230, 230, 230, 230, 0,   0,   0,   0,   0,
6120
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6121
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6122
     0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 230, 220, 220, 220,
6123
     220, 220, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6124
     230, 0,   220, 230, 230, 220, 230, 230, 220, 230, 230, 230, 220, 220, 220,
6125
     27,  28,  29,  230, 230, 230, 220, 230, 230, 220, 220, 230, 230, 230, 230,
6126
     230},
6127
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6128
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6129
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   7,   0,   0,   0, 0, 0,
6130
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0, 0, 230, 220, 230, 230, 0, 0, 0,
6131
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6132
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6133
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6134
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6135
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6136
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6137
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6138
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0},
6139
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6140
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6141
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6142
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6143
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6144
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6145
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6146
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
6147
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6148
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6149
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6150
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6151
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6152
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6153
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6154
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6155
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6156
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6157
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6158
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6159
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6160
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6161
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6162
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6163
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6164
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 84, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6165
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6166
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6167
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6168
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 7, 0, 0, 0,
6169
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6170
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6171
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0},
6172
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6173
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6174
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6175
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6176
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6177
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6178
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6179
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6180
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6181
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6182
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6183
    {0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6184
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6185
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6186
     0,   0,   103, 103, 9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6187
     107, 107, 107, 107, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6188
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6189
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6190
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6191
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6192
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6193
     0,   0,   0,   0,   118, 118, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6194
     0,   0,   122, 122, 122, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6195
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6196
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6197
     0,   0,   0,   0},
6198
    {0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6199
     0,   0, 0,   0,   0,   0,   0, 0, 0,   220, 220, 0,   0,   0, 0,
6200
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6201
     0,   0, 0,   0,   0,   0,   0, 0, 220, 0,   220, 0,   216, 0, 0,
6202
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6203
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6204
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6205
     0,   0, 0,   0,   0,   0,   0, 0, 129, 130, 0,   132, 0,   0, 0,
6206
     0,   0, 130, 130, 130, 130, 0, 0, 130, 0,   230, 230, 9,   0, 230,
6207
     230, 0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6208
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6209
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6210
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6211
     0,   0, 0,   220, 0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6212
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6213
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6214
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6215
     0},
6216
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6217
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6218
     0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6219
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6220
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6221
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0,
6222
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6223
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6224
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6225
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6226
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6227
    {0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6228
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6229
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6230
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6231
     0, 0, 0, 0, 0, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6232
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6233
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6234
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6235
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6236
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6237
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6238
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0},
6239
    {0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0,
6240
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6241
     0, 0, 0, 0, 9, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6242
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6243
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6244
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6245
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6246
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6247
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6248
     0, 0, 0, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6249
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6250
    {0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6251
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6252
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6253
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6254
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6255
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6256
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6257
     0, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6258
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6259
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6260
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6261
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6262
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6263
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 230, 220, 0, 0, 0, 0, 0, 0,
6264
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6265
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6266
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6267
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6268
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6269
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6270
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6271
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6272
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6273
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6274
     0,   0,   0,   0,   0,   0,   0,   0,   230, 220, 0,   0,   0,   0,   0,
6275
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6276
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6277
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6278
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6279
     0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6280
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230,
6281
     230, 230, 230, 230, 230, 0,   0,   220, 0,   0,   0,   0,   0,   0,   0,
6282
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6283
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6284
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230,
6285
     230, 220, 220, 220, 220, 220, 220, 230, 230, 220, 0,   220, 220, 230, 230,
6286
     220, 220, 230, 230, 230, 230, 230, 220, 230, 230, 230, 230, 0,   0,   0,
6287
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6288
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6289
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6290
     0},
6291
    {0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6292
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6293
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   7,   0,   0,   0,   0,
6294
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0,   0,   0,   0,   0,   0,
6295
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6296
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 230, 230, 230, 230, 230,
6297
     230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6298
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6299
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   9,
6300
     9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6301
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6302
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6303
     0,   0,   7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   9,   9,   0,   0,   0,
6304
     0,   0,   0, 0, 0, 0, 0, 0, 0},
6305
    {0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6306
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6307
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6308
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   7,   0,   0,   0,   0,
6309
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6310
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6311
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6312
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6313
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6314
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6315
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6316
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6317
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6318
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230,
6319
     230, 0, 1, 220, 220, 220, 220, 220, 230, 230, 220, 220, 220, 220, 230,
6320
     0,   1, 1, 1,   1,   1,   1,   1,   0,   0,   0,   0,   220, 0,   0,
6321
     0,   0, 0, 0,   230, 0,   0,   0,   230, 230, 0,   0,   0,   0,   0,
6322
     0},
6323
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6324
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6325
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6326
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6327
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6328
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6329
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6330
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6331
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6332
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6333
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6334
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6335
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 220,
6336
     230, 230, 230, 230, 230, 230, 230, 220, 230, 230, 234, 214, 220, 202, 230,
6337
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6338
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6339
     230, 230, 230, 230, 230, 230, 232, 228, 228, 220, 218, 230, 233, 220, 230,
6340
     220},
6341
    {0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6342
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6343
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6344
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6345
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6346
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6347
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6348
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6349
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6350
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6351
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6352
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6353
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6354
     230, 230, 1, 1, 230, 230, 230, 230, 1,   1,   1, 230, 230, 0,   0,   0,
6355
     0,   230, 0, 0, 0,   1,   1,   230, 220, 230, 1, 1,   220, 220, 220, 220,
6356
     230, 0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0},
6357
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6358
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6359
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6360
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6361
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6362
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6363
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6364
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6365
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6366
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6367
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230,
6368
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6369
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6370
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6371
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6372
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6373
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6374
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6375
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6376
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6377
     0,   0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,
6378
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6379
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6380
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6381
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6382
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6383
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6384
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6385
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6386
     230},
6387
    {0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6388
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6389
     0, 0, 218, 228, 232, 222, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6390
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6391
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6392
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6393
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6394
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0,
6395
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6396
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6397
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6398
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6399
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0},
6400
    {0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6401
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6402
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6403
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6404
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6405
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6406
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6407
     0,   0,   0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,
6408
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6409
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230,
6410
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6411
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6412
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6413
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6414
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6415
     230, 230, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0},
6416
    {0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6417
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6418
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   9,
6419
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6420
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6421
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6422
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6423
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6424
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6425
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6426
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6427
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6428
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6429
     0,   9,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6430
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6431
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6432
     230, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6433
     0},
6434
    {0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6435
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220,
6436
     220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6437
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
6438
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6439
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6440
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6441
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6442
     0,   0,   0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6443
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6444
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6445
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6446
    {0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6447
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6448
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6449
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6450
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6451
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6452
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6453
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6454
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6455
     0,   0,   0, 0,   0, 230, 0, 230, 230, 220, 0, 0, 230, 230, 0, 0, 0, 0, 0,
6456
     230, 230, 0, 230, 0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6457
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6458
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 9,
6459
     0,   0,   0, 0,   0, 0,   0, 0,   0},
6460
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6461
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6462
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6463
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6464
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6465
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6466
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6467
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6468
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6469
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0,
6470
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6471
    {0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6472
     0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6473
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6474
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6475
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6476
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6477
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6478
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6479
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6480
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6481
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0},
6482
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6483
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6484
     0,   0,   230, 230, 230, 230, 230, 230, 230, 220, 220, 220, 220, 220, 220,
6485
     220, 230, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6486
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6487
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6488
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6489
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6490
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6491
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6492
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6493
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6494
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6495
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6496
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6497
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6498
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6499
     0},
6500
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6501
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6502
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6503
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6504
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6505
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6506
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6507
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6508
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6509
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6510
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0},
6511
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6512
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6513
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6514
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6515
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6516
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6517
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6518
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6519
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6520
     0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6521
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0},
6522
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6523
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6524
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6525
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6526
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6527
     0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6528
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6529
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6530
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6531
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6532
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6533
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0},
6534
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 220, 0, 230, 0,   0, 0,   0,
6535
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6536
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   230, 1, 220, 0,
6537
     0, 0, 0, 9, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6538
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6539
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6540
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6541
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6542
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6543
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6544
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6545
     0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 0, 0, 0,   0, 0,   0,   0, 0,   0,
6546
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0},
6547
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6548
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0, 0, 0, 0,
6549
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6550
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6551
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6552
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6553
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6554
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6555
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6556
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6557
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6558
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6559
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6560
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6561
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6562
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6563
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6564
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6565
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6566
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 230, 230, 0, 0, 0,
6567
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6568
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6569
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6570
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220},
6571
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6572
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6573
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6574
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 220, 220,
6575
     230, 230, 230, 220, 230, 220, 220, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6576
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6577
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6578
     0,   0,   0,   0,   230, 220, 230, 220, 0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6579
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6580
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6581
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6582
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6583
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6584
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6585
     0,   0,   0,   0},
6586
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6587
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6588
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,
6589
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6590
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
6591
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6592
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6593
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0,
6594
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6595
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6596
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6597
    {230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6598
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6599
     0,   0,   0,   0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6600
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6601
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6602
     0,   0,   0,   0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6603
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6604
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6605
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6606
     0,   0,   0,   0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6607
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6608
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6609
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6610
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6611
     0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6612
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6613
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6614
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6615
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6616
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6617
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6618
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 0, 0, 0, 0, 0,
6619
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6620
    {0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6621
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6622
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6623
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   7,   7,   0, 0, 0,
6624
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   9, 0, 0,
6625
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6626
     0,   0,   0,   0,   0,   0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0,
6627
     230, 230, 230, 230, 230, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6628
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6629
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6630
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6631
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6632
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6633
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6634
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6635
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0},
6636
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6637
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6638
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 7,   0,
6639
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0,
6640
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6641
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6642
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6643
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6644
     0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6645
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6646
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6647
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6648
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6649
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6650
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6651
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6652
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6653
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6654
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
6655
     7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6656
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6657
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6658
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6659
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6660
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
6661
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6662
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6663
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6664
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6665
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0,
6666
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6667
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6668
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6669
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6670
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
6671
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6672
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6673
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6674
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6675
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6676
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6677
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6678
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6679
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6680
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6681
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6682
     0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6683
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6684
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6685
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6686
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6687
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6688
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6689
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6690
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6691
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6692
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6693
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 7, 0, 0, 0, 0,
6694
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6695
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6696
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6697
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6698
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6699
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6700
     0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6701
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6702
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6703
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6704
     0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
6705
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6706
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6707
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6708
     0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6709
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6710
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6711
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6712
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6713
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6714
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6715
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
6716
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6717
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6718
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6719
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6720
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6721
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6722
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6723
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6724
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6725
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6726
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0,
6727
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6728
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6729
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6730
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6731
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6732
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6733
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6734
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6735
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6736
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6737
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0,
6738
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6739
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6740
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6741
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6742
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6743
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6744
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6745
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6746
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6747
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6748
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6749
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6750
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6751
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6752
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6753
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6754
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6755
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6756
     1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6757
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6758
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6759
     0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0,
6760
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6761
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6762
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6763
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6764
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6765
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6766
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6767
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6768
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6769
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0},
6770
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6771
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6772
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6773
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6774
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6775
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6776
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6777
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6778
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6779
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6780
     6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6781
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6782
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6783
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6784
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6785
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6786
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6787
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6788
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6789
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6790
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6791
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6792
    {0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6793
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6794
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6795
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6796
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6797
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6798
     0,   0,   0,   0, 0, 216, 216, 1,   1,   1,   0,   0,   0,   226, 216, 216,
6799
     216, 216, 216, 0, 0, 0,   0,   0,   0,   0,   0,   220, 220, 220, 220, 220,
6800
     220, 220, 220, 0, 0, 230, 230, 230, 230, 230, 220, 220, 0,   0,   0,   0,
6801
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6802
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   230, 230, 230, 230, 0,   0,
6803
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6804
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6805
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6806
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6807
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0},
6808
    {0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6809
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6810
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6811
     230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6812
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6813
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6814
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6815
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6816
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6817
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6818
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6819
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6820
    {230, 230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 230, 230, 230, 230,
6821
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230, 230,
6822
     230, 230, 230, 230, 0,   230, 230, 0,   230, 230, 230, 230, 230, 0,   0,
6823
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6824
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6825
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6826
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6827
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6828
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6829
     0,   0,   0,   0,   0,   0,   0,   0,   230, 0,   0,   0,   0,   0,   0,
6830
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6831
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6832
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6833
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6834
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6835
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6836
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6837
     0},
6838
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6839
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6840
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6841
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6842
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6843
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6844
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6845
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   230, 0,
6846
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6847
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6848
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0,   0,
6849
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6850
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6851
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6852
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6853
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6854
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6855
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6856
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6857
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6858
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6859
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6860
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 232, 220, 230, 0, 0,
6861
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6862
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6863
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6864
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6865
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6866
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6867
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6868
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6869
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6870
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6871
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6872
     0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 220, 220, 220, 220, 0, 0, 0, 0, 0,
6873
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6874
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0},
6875
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6876
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6877
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6878
     0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 7, 0, 0, 0, 0, 0,
6879
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6880
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6881
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6882
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6883
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6884
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6885
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6886
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6887
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0}};
6888
6889
const uint8_t composition_index[4352] = {
6890
    0, 1, 2, 3, 4,  5,  6, 5, 5,  7,  5, 8,  9,  10, 5, 5, 11, 5,  5, 5, 5, 5,
6891
    5, 5, 5, 5, 5,  12, 5, 5, 13, 14, 5, 15, 16, 5,  5, 5, 5,  5,  5, 5, 5, 5,
6892
    5, 5, 5, 5, 17, 5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6893
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6894
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6895
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6896
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6897
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6898
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6899
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6900
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6901
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6902
    5, 5, 5, 5, 5,  5,  5, 5, 18, 19, 5, 20, 21, 22, 5, 5, 5,  23, 5, 5, 5, 5,
6903
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6904
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6905
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6906
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6907
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6908
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6909
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6910
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6911
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6912
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6913
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6914
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6915
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6916
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6917
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6918
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6919
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6920
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6921
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6922
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6923
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6924
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6925
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6926
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6927
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6928
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6929
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6930
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6931
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6932
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6933
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6934
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6935
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6936
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6937
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6938
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6939
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6940
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6941
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6942
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6943
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6944
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6945
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6946
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6947
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6948
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6949
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6950
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6951
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6952
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6953
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6954
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6955
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6956
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6957
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6958
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6959
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6960
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6961
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6962
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6963
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6964
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6965
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6966
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6967
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6968
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6969
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6970
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6971
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6972
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6973
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6974
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6975
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6976
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6977
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6978
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6979
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6980
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6981
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6982
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6983
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6984
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6985
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6986
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6987
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6988
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6989
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6990
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6991
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6992
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6993
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6994
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6995
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6996
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6997
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6998
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6999
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7000
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7001
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7002
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7003
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7004
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7005
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7006
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7007
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7008
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7009
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7010
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7011
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7012
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7013
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7014
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7015
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7016
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7017
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7018
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7019
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7020
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7021
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7022
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7023
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7024
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7025
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7026
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7027
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7028
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7029
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7030
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7031
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7032
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7033
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7034
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7035
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7036
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7037
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7038
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7039
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7040
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7041
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7042
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7043
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7044
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7045
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7046
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7047
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7048
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7049
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7050
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7051
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7052
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7053
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7054
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7055
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7056
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7057
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7058
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7059
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7060
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7061
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7062
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7063
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7064
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7065
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7066
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7067
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7068
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7069
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7070
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7071
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7072
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7073
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7074
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7075
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7076
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7077
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7078
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7079
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7080
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7081
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7082
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7083
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7084
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7085
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7086
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7087
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5};
7088
const uint16_t composition_block[67][257] = {
7089
    {1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7090
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7091
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7092
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7093
     1,   3,   5,   7,   7,   7,   39,  45,  55,  67,  101, 103, 117, 131, 161,
7094
     163, 173, 185, 191, 209, 241, 245, 245, 261, 275, 289, 327, 331, 343, 347,
7095
     365, 377, 377, 377, 377, 377, 377, 377, 409, 415, 425, 437, 471, 473, 487,
7096
     503, 531, 535, 545, 557, 563, 581, 613, 617, 617, 633, 647, 663, 701, 705,
7097
     719, 723, 743, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7098
     755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7099
     755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7100
     755, 755, 755, 755, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7101
     761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7102
     769, 769, 771, 773, 777, 779, 779, 779, 787, 787, 787, 787, 787, 789, 789,
7103
     789, 789, 789, 797, 803, 805, 805, 807, 807, 807, 807, 815, 815, 815, 815,
7104
     815, 815, 823, 823, 825, 827, 831, 833, 833, 833, 841, 841, 841, 841, 841,
7105
     843, 843, 843, 843, 843, 851, 857, 859, 859, 861, 861, 861, 861, 869, 869,
7106
     869, 869},
7107
    {869, 869, 869, 877, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885,
7108
     885, 885, 885, 885, 889, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7109
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7110
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7111
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7112
     893, 893, 897, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901,
7113
     901, 903, 905, 905, 905, 905, 905, 907, 909, 909, 909, 909, 909, 909, 909,
7114
     911, 913, 915, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917,
7115
     917, 917, 917, 917, 917, 917, 917, 917, 919, 919, 919, 919, 919, 919, 919,
7116
     919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919,
7117
     919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 929, 939, 939, 939,
7118
     939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 949, 959, 959, 959,
7119
     959, 959, 959, 959, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7120
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7121
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7122
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 963, 965, 965, 965, 965,
7123
     965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7124
     965, 965},
7125
    {965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7126
     965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7127
     965, 965, 965, 965, 965, 965, 965, 965, 965, 967, 969, 971, 973, 973, 973,
7128
     973, 973, 975, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7129
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7130
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7131
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7132
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7133
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7134
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 979, 979, 979,
7135
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7136
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7137
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7138
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7139
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7140
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7141
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7142
     979, 979},
7143
    {979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7144
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7145
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7146
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7147
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7148
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7149
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7150
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7151
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7152
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7153
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7154
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7155
     979,  979,  993,  993,  993,  993,  1001, 1001, 1011, 1011, 1025, 1025,
7156
     1025, 1025, 1025, 1025, 1033, 1033, 1035, 1035, 1035, 1035, 1047, 1047,
7157
     1047, 1047, 1057, 1057, 1057, 1059, 1059, 1061, 1061, 1061, 1077, 1077,
7158
     1077, 1077, 1085, 1085, 1097, 1097, 1113, 1113, 1113, 1113, 1113, 1113,
7159
     1121, 1121, 1125, 1125, 1125, 1125, 1141, 1141, 1141, 1141, 1153, 1159,
7160
     1165, 1165, 1165, 1167, 1167, 1167, 1167, 1171, 1171, 1171, 1171, 1171,
7161
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7162
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7163
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7164
     1171, 1171, 1171, 1171, 1171},
7165
    {1171, 1171, 1171, 1171, 1171, 1171, 1171, 1173, 1173, 1173, 1173, 1173,
7166
     1173, 1173, 1173, 1173, 1173, 1177, 1177, 1177, 1179, 1179, 1185, 1189,
7167
     1191, 1199, 1199, 1201, 1201, 1201, 1201, 1203, 1203, 1203, 1203, 1203,
7168
     1211, 1211, 1211, 1211, 1213, 1213, 1213, 1213, 1215, 1215, 1217, 1217,
7169
     1217, 1221, 1221, 1221, 1223, 1223, 1229, 1233, 1235, 1243, 1243, 1245,
7170
     1245, 1245, 1245, 1247, 1247, 1247, 1247, 1247, 1255, 1255, 1255, 1255,
7171
     1257, 1257, 1257, 1257, 1259, 1259, 1261, 1261, 1261, 1261, 1261, 1261,
7172
     1261, 1261, 1261, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7173
     1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7174
     1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1265, 1267, 1267,
7175
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7176
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7177
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7178
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7179
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7180
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7181
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7182
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7183
     1267, 1269, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271,
7184
     1271, 1271, 1271, 1271, 1271, 1273, 1275, 1275, 1275, 1275, 1275, 1275,
7185
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7186
     1275, 1275, 1275, 1275, 1275},
7187
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7188
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7189
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7190
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7191
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7192
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7193
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7194
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7195
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7196
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7197
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
7198
    {1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7199
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7200
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7201
     1275, 1275, 1275, 1275, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7202
     1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7203
     1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7204
     1281, 1283, 1283, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7205
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7206
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7207
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7208
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7209
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7210
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7211
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7212
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7213
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7214
     1285, 1285, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
7215
     1287, 1287, 1287, 1287, 1287, 1287, 1287, 1289, 1289, 1289, 1291, 1291,
7216
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7217
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7218
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7219
     1291, 1291, 1291, 1291, 1291},
7220
    {1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7221
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7222
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7223
     1291, 1291, 1291, 1291, 1291, 1293, 1293, 1293, 1293, 1293, 1293, 1293,
7224
     1293, 1295, 1295, 1295, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7225
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7226
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7227
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7228
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7229
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7230
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7231
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7232
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7233
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7234
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7235
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7236
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1301, 1301, 1301, 1301,
7237
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7238
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7239
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7240
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7241
     1301, 1301, 1301, 1301, 1301},
7242
    {1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7243
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7244
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7245
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7246
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7247
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7248
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7249
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7250
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7251
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7252
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7253
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7254
     1307, 1307, 1307, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7255
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7256
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7257
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7258
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1313, 1315, 1315, 1315, 1315,
7259
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7260
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7261
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7262
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7263
     1315, 1315, 1315, 1315, 1315},
7264
    {1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7265
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7266
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7267
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7268
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7269
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1317,
7270
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7271
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7272
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7273
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7274
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7275
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7276
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7277
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7278
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7279
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7280
     1319, 1319, 1319, 1319, 1319, 1319, 1319, 1325, 1325, 1325, 1325, 1327,
7281
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7282
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7283
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7284
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7285
     1327, 1327, 1327, 1327, 1327},
7286
    {1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7287
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7288
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7289
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7290
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7291
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1331,
7292
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7293
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7294
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7295
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7296
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7297
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7298
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7299
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7300
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7301
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7302
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7303
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7304
     1333, 1333, 1339, 1339, 1339, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7305
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7306
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7307
     1341, 1341, 1341, 1341, 1341},
7308
    {1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7309
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7310
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7311
     1341, 1341, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7312
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7313
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7314
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7315
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7316
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7317
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7318
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7319
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7320
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7321
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7322
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7323
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7324
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7325
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7326
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7327
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7328
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7329
     1343, 1343, 1343, 1343, 1343},
7330
    {1343, 1343, 1343, 1343, 1343, 1343, 1345, 1345, 1347, 1347, 1349, 1349,
7331
     1351, 1351, 1353, 1353, 1353, 1353, 1355, 1355, 1355, 1355, 1355, 1355,
7332
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7333
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7334
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1357,
7335
     1357, 1359, 1359, 1361, 1363, 1363, 1363, 1365, 1365, 1365, 1365, 1365,
7336
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7337
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7338
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7339
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7340
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7341
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7342
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7343
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7344
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7345
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7346
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7347
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7348
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7349
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7350
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7351
     1365, 1365, 1365, 1365, 1365},
7352
    {1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7353
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7354
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7355
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7356
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1367, 1369, 1369, 1369, 1369,
7357
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7358
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7359
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1371, 1373, 1373, 1373, 1373,
7360
     1373, 1373, 1373, 1375, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7361
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7362
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7363
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7364
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7365
     1377, 1377, 1377, 1377, 1377, 1381, 1385, 1385, 1385, 1385, 1385, 1385,
7366
     1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385,
7367
     1385, 1385, 1385, 1385, 1385, 1387, 1389, 1389, 1389, 1389, 1389, 1389,
7368
     1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389,
7369
     1389, 1391, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7370
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7371
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7372
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7373
     1393, 1393, 1393, 1393, 1393},
7374
    {1393, 1401, 1409, 1411, 1413, 1415, 1417, 1419, 1421, 1429, 1437, 1439,
7375
     1441, 1443, 1445, 1447, 1449, 1453, 1457, 1457, 1457, 1457, 1457, 1457,
7376
     1457, 1461, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1473, 1481, 1483,
7377
     1485, 1487, 1489, 1491, 1493, 1501, 1509, 1511, 1513, 1515, 1517, 1519,
7378
     1521, 1527, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1539, 1545, 1545,
7379
     1545, 1545, 1545, 1545, 1545, 1549, 1553, 1553, 1553, 1553, 1553, 1553,
7380
     1553, 1557, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1567, 1573, 1573,
7381
     1573, 1573, 1573, 1573, 1573, 1573, 1579, 1579, 1579, 1579, 1579, 1579,
7382
     1579, 1587, 1595, 1597, 1599, 1601, 1603, 1605, 1607, 1615, 1623, 1625,
7383
     1627, 1629, 1631, 1633, 1635, 1637, 1637, 1637, 1637, 1639, 1639, 1639,
7384
     1639, 1639, 1639, 1639, 1639, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7385
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7386
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7387
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7388
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7389
     1641, 1641, 1641, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643,
7390
     1649, 1649, 1649, 1649, 1649, 1649, 1649, 1651, 1651, 1651, 1651, 1651,
7391
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7392
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7393
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7394
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1653, 1653, 1653, 1653, 1653,
7395
     1653, 1653, 1653, 1659, 1659},
7396
    {1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7397
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7398
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7399
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7400
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7401
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7402
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7403
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7404
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7405
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7406
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7407
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7408
     1659, 1661, 1661, 1663, 1663, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7409
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7410
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7411
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7412
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7413
     1665, 1665, 1665, 1665, 1665, 1667, 1667, 1669, 1669, 1671, 1671, 1671,
7414
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7415
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7416
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7417
     1671, 1671, 1671, 1671, 1671},
7418
    {1671, 1671, 1671, 1671, 1673, 1673, 1673, 1673, 1673, 1675, 1675, 1675,
7419
     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7420
     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7421
     1679, 1679, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7422
     1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7423
     1681, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1685, 1685, 1687, 1687,
7424
     1687, 1689, 1689, 1689, 1689, 1689, 1691, 1691, 1691, 1691, 1691, 1691,
7425
     1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691,
7426
     1691, 1691, 1693, 1693, 1693, 1695, 1697, 1697, 1697, 1697, 1697, 1697,
7427
     1697, 1697, 1697, 1697, 1697, 1697, 1697, 1699, 1701, 1701, 1701, 1703,
7428
     1705, 1705, 1705, 1707, 1709, 1711, 1713, 1713, 1713, 1713, 1713, 1715,
7429
     1717, 1717, 1717, 1719, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
7430
     1721, 1721, 1723, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725,
7431
     1725, 1725, 1725, 1725, 1725, 1725, 1725, 1727, 1727, 1727, 1727, 1727,
7432
     1727, 1729, 1731, 1731, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1735,
7433
     1737, 1739, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7434
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7435
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7436
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7437
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7438
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7439
     1741, 1741, 1741, 1741, 1741},
7440
    {1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7441
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7442
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7443
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7444
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7445
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1743,
7446
     1743, 1743, 1743, 1743, 1745, 1745, 1747, 1747, 1749, 1749, 1751, 1751,
7447
     1753, 1753, 1755, 1755, 1757, 1757, 1759, 1759, 1761, 1761, 1763, 1763,
7448
     1765, 1765, 1767, 1767, 1767, 1769, 1769, 1771, 1771, 1773, 1773, 1773,
7449
     1773, 1773, 1773, 1773, 1777, 1777, 1777, 1781, 1781, 1781, 1785, 1785,
7450
     1785, 1789, 1789, 1789, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7451
     1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7452
     1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7453
     1793, 1793, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1797,
7454
     1797, 1797, 1797, 1797, 1799, 1799, 1801, 1801, 1803, 1803, 1805, 1805,
7455
     1807, 1807, 1809, 1809, 1811, 1811, 1813, 1813, 1815, 1815, 1817, 1817,
7456
     1819, 1819, 1821, 1821, 1821, 1823, 1823, 1825, 1825, 1827, 1827, 1827,
7457
     1827, 1827, 1827, 1827, 1831, 1831, 1831, 1835, 1835, 1835, 1839, 1839,
7458
     1839, 1843, 1843, 1843, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7459
     1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7460
     1849, 1851, 1853, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855,
7461
     1855, 1855, 1857, 1857, 1857},
7462
    {1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7463
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7464
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7465
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7466
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7467
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7468
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7469
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7470
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7471
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7472
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7473
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7474
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1859, 1859,
7475
     1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1863, 1863,
7476
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7477
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7478
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7479
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7480
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7481
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7482
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7483
     1863, 1863, 1863, 1863, 1863},
7484
    {1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7485
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7486
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7487
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7488
     1863, 1863, 1865, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7489
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7490
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7491
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7492
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7493
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7494
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7495
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7496
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7497
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7498
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7499
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7500
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7501
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7502
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7503
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7504
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7505
     1867, 1867, 1867, 1867, 1867},
7506
    {1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7507
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7508
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7509
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7510
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7511
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7512
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7513
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7514
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7515
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7516
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7517
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7518
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7519
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7520
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7521
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7522
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7523
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7524
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7525
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7526
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7527
     1871, 1871, 1871, 1871, 1871},
7528
    {1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7529
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7530
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7531
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7532
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7533
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7534
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7535
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7536
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7537
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7538
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7539
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7540
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7541
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7542
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7543
     1871, 1871, 1871, 1871, 1871, 1871, 1877, 1877, 1877, 1877, 1877, 1877,
7544
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7545
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7546
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7547
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7548
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7549
     1877, 1877, 1877, 1877, 1877},
7550
    {1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7551
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7552
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7553
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7554
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7555
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7556
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7557
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7558
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7559
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7560
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7561
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7562
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7563
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7564
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7565
     1877, 1877, 1877, 1877, 1877, 1879, 1881, 1881, 1881, 1881, 1881, 1881,
7566
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7567
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7568
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7569
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7570
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7571
     1881, 1881, 1881, 1881, 1881},
7572
    {1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7573
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7574
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7575
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7576
     1881, 1881, 1881, 1881, 1881, 1881, 1883, 1883, 1883, 1883, 1883, 1883,
7577
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7578
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7579
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7580
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7581
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7582
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7583
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7584
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7585
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7586
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7587
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7588
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7589
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7590
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7591
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7592
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7593
     1883, 1883, 1883, 1883, 1883}};
7594
const char32_t composition_data[1883] = {
7595
    0,     824,   8814,  824,   8800,  824,   8815,  768,   192,   769,   193,
7596
    770,   194,   771,   195,   772,   256,   774,   258,   775,   550,   776,
7597
    196,   777,   7842,  778,   197,   780,   461,   783,   512,   785,   514,
7598
    803,   7840,  805,   7680,  808,   260,   775,   7682,  803,   7684,  817,
7599
    7686,  769,   262,   770,   264,   775,   266,   780,   268,   807,   199,
7600
    775,   7690,  780,   270,   803,   7692,  807,   7696,  813,   7698,  817,
7601
    7694,  768,   200,   769,   201,   770,   202,   771,   7868,  772,   274,
7602
    774,   276,   775,   278,   776,   203,   777,   7866,  780,   282,   783,
7603
    516,   785,   518,   803,   7864,  807,   552,   808,   280,   813,   7704,
7604
    816,   7706,  775,   7710,  769,   500,   770,   284,   772,   7712,  774,
7605
    286,   775,   288,   780,   486,   807,   290,   770,   292,   775,   7714,
7606
    776,   7718,  780,   542,   803,   7716,  807,   7720,  814,   7722,  768,
7607
    204,   769,   205,   770,   206,   771,   296,   772,   298,   774,   300,
7608
    775,   304,   776,   207,   777,   7880,  780,   463,   783,   520,   785,
7609
    522,   803,   7882,  808,   302,   816,   7724,  770,   308,   769,   7728,
7610
    780,   488,   803,   7730,  807,   310,   817,   7732,  769,   313,   780,
7611
    317,   803,   7734,  807,   315,   813,   7740,  817,   7738,  769,   7742,
7612
    775,   7744,  803,   7746,  768,   504,   769,   323,   771,   209,   775,
7613
    7748,  780,   327,   803,   7750,  807,   325,   813,   7754,  817,   7752,
7614
    768,   210,   769,   211,   770,   212,   771,   213,   772,   332,   774,
7615
    334,   775,   558,   776,   214,   777,   7886,  779,   336,   780,   465,
7616
    783,   524,   785,   526,   795,   416,   803,   7884,  808,   490,   769,
7617
    7764,  775,   7766,  769,   340,   775,   7768,  780,   344,   783,   528,
7618
    785,   530,   803,   7770,  807,   342,   817,   7774,  769,   346,   770,
7619
    348,   775,   7776,  780,   352,   803,   7778,  806,   536,   807,   350,
7620
    775,   7786,  780,   356,   803,   7788,  806,   538,   807,   354,   813,
7621
    7792,  817,   7790,  768,   217,   769,   218,   770,   219,   771,   360,
7622
    772,   362,   774,   364,   776,   220,   777,   7910,  778,   366,   779,
7623
    368,   780,   467,   783,   532,   785,   534,   795,   431,   803,   7908,
7624
    804,   7794,  808,   370,   813,   7798,  816,   7796,  771,   7804,  803,
7625
    7806,  768,   7808,  769,   7810,  770,   372,   775,   7814,  776,   7812,
7626
    803,   7816,  775,   7818,  776,   7820,  768,   7922,  769,   221,   770,
7627
    374,   771,   7928,  772,   562,   775,   7822,  776,   376,   777,   7926,
7628
    803,   7924,  769,   377,   770,   7824,  775,   379,   780,   381,   803,
7629
    7826,  817,   7828,  768,   224,   769,   225,   770,   226,   771,   227,
7630
    772,   257,   774,   259,   775,   551,   776,   228,   777,   7843,  778,
7631
    229,   780,   462,   783,   513,   785,   515,   803,   7841,  805,   7681,
7632
    808,   261,   775,   7683,  803,   7685,  817,   7687,  769,   263,   770,
7633
    265,   775,   267,   780,   269,   807,   231,   775,   7691,  780,   271,
7634
    803,   7693,  807,   7697,  813,   7699,  817,   7695,  768,   232,   769,
7635
    233,   770,   234,   771,   7869,  772,   275,   774,   277,   775,   279,
7636
    776,   235,   777,   7867,  780,   283,   783,   517,   785,   519,   803,
7637
    7865,  807,   553,   808,   281,   813,   7705,  816,   7707,  775,   7711,
7638
    769,   501,   770,   285,   772,   7713,  774,   287,   775,   289,   780,
7639
    487,   807,   291,   770,   293,   775,   7715,  776,   7719,  780,   543,
7640
    803,   7717,  807,   7721,  814,   7723,  817,   7830,  768,   236,   769,
7641
    237,   770,   238,   771,   297,   772,   299,   774,   301,   776,   239,
7642
    777,   7881,  780,   464,   783,   521,   785,   523,   803,   7883,  808,
7643
    303,   816,   7725,  770,   309,   780,   496,   769,   7729,  780,   489,
7644
    803,   7731,  807,   311,   817,   7733,  769,   314,   780,   318,   803,
7645
    7735,  807,   316,   813,   7741,  817,   7739,  769,   7743,  775,   7745,
7646
    803,   7747,  768,   505,   769,   324,   771,   241,   775,   7749,  780,
7647
    328,   803,   7751,  807,   326,   813,   7755,  817,   7753,  768,   242,
7648
    769,   243,   770,   244,   771,   245,   772,   333,   774,   335,   775,
7649
    559,   776,   246,   777,   7887,  779,   337,   780,   466,   783,   525,
7650
    785,   527,   795,   417,   803,   7885,  808,   491,   769,   7765,  775,
7651
    7767,  769,   341,   775,   7769,  780,   345,   783,   529,   785,   531,
7652
    803,   7771,  807,   343,   817,   7775,  769,   347,   770,   349,   775,
7653
    7777,  780,   353,   803,   7779,  806,   537,   807,   351,   775,   7787,
7654
    776,   7831,  780,   357,   803,   7789,  806,   539,   807,   355,   813,
7655
    7793,  817,   7791,  768,   249,   769,   250,   770,   251,   771,   361,
7656
    772,   363,   774,   365,   776,   252,   777,   7911,  778,   367,   779,
7657
    369,   780,   468,   783,   533,   785,   535,   795,   432,   803,   7909,
7658
    804,   7795,  808,   371,   813,   7799,  816,   7797,  771,   7805,  803,
7659
    7807,  768,   7809,  769,   7811,  770,   373,   775,   7815,  776,   7813,
7660
    778,   7832,  803,   7817,  775,   7819,  776,   7821,  768,   7923,  769,
7661
    253,   770,   375,   771,   7929,  772,   563,   775,   7823,  776,   255,
7662
    777,   7927,  778,   7833,  803,   7925,  769,   378,   770,   7825,  775,
7663
    380,   780,   382,   803,   7827,  817,   7829,  768,   8173,  769,   901,
7664
    834,   8129,  768,   7846,  769,   7844,  771,   7850,  777,   7848,  772,
7665
    478,   769,   506,   769,   508,   772,   482,   769,   7688,  768,   7872,
7666
    769,   7870,  771,   7876,  777,   7874,  769,   7726,  768,   7890,  769,
7667
    7888,  771,   7894,  777,   7892,  769,   7756,  772,   556,   776,   7758,
7668
    772,   554,   769,   510,   768,   475,   769,   471,   772,   469,   780,
7669
    473,   768,   7847,  769,   7845,  771,   7851,  777,   7849,  772,   479,
7670
    769,   507,   769,   509,   772,   483,   769,   7689,  768,   7873,  769,
7671
    7871,  771,   7877,  777,   7875,  769,   7727,  768,   7891,  769,   7889,
7672
    771,   7895,  777,   7893,  769,   7757,  772,   557,   776,   7759,  772,
7673
    555,   769,   511,   768,   476,   769,   472,   772,   470,   780,   474,
7674
    768,   7856,  769,   7854,  771,   7860,  777,   7858,  768,   7857,  769,
7675
    7855,  771,   7861,  777,   7859,  768,   7700,  769,   7702,  768,   7701,
7676
    769,   7703,  768,   7760,  769,   7762,  768,   7761,  769,   7763,  775,
7677
    7780,  775,   7781,  775,   7782,  775,   7783,  769,   7800,  769,   7801,
7678
    776,   7802,  776,   7803,  775,   7835,  768,   7900,  769,   7898,  771,
7679
    7904,  777,   7902,  803,   7906,  768,   7901,  769,   7899,  771,   7905,
7680
    777,   7903,  803,   7907,  768,   7914,  769,   7912,  771,   7918,  777,
7681
    7916,  803,   7920,  768,   7915,  769,   7913,  771,   7919,  777,   7917,
7682
    803,   7921,  780,   494,   772,   492,   772,   493,   772,   480,   772,
7683
    481,   774,   7708,  774,   7709,  772,   560,   772,   561,   780,   495,
7684
    768,   8122,  769,   902,   772,   8121,  774,   8120,  787,   7944,  788,
7685
    7945,  837,   8124,  768,   8136,  769,   904,   787,   7960,  788,   7961,
7686
    768,   8138,  769,   905,   787,   7976,  788,   7977,  837,   8140,  768,
7687
    8154,  769,   906,   772,   8153,  774,   8152,  776,   938,   787,   7992,
7688
    788,   7993,  768,   8184,  769,   908,   787,   8008,  788,   8009,  788,
7689
    8172,  768,   8170,  769,   910,   772,   8169,  774,   8168,  776,   939,
7690
    788,   8025,  768,   8186,  769,   911,   787,   8040,  788,   8041,  837,
7691
    8188,  837,   8116,  837,   8132,  768,   8048,  769,   940,   772,   8113,
7692
    774,   8112,  787,   7936,  788,   7937,  834,   8118,  837,   8115,  768,
7693
    8050,  769,   941,   787,   7952,  788,   7953,  768,   8052,  769,   942,
7694
    787,   7968,  788,   7969,  834,   8134,  837,   8131,  768,   8054,  769,
7695
    943,   772,   8145,  774,   8144,  776,   970,   787,   7984,  788,   7985,
7696
    834,   8150,  768,   8056,  769,   972,   787,   8000,  788,   8001,  787,
7697
    8164,  788,   8165,  768,   8058,  769,   973,   772,   8161,  774,   8160,
7698
    776,   971,   787,   8016,  788,   8017,  834,   8166,  768,   8060,  769,
7699
    974,   787,   8032,  788,   8033,  834,   8182,  837,   8179,  768,   8146,
7700
    769,   912,   834,   8151,  768,   8162,  769,   944,   834,   8167,  837,
7701
    8180,  769,   979,   776,   980,   776,   1031,  774,   1232,  776,   1234,
7702
    769,   1027,  768,   1024,  774,   1238,  776,   1025,  774,   1217,  776,
7703
    1244,  776,   1246,  768,   1037,  772,   1250,  774,   1049,  776,   1252,
7704
    769,   1036,  776,   1254,  772,   1262,  774,   1038,  776,   1264,  779,
7705
    1266,  776,   1268,  776,   1272,  776,   1260,  774,   1233,  776,   1235,
7706
    769,   1107,  768,   1104,  774,   1239,  776,   1105,  774,   1218,  776,
7707
    1245,  776,   1247,  768,   1117,  772,   1251,  774,   1081,  776,   1253,
7708
    769,   1116,  776,   1255,  772,   1263,  774,   1118,  776,   1265,  779,
7709
    1267,  776,   1269,  776,   1273,  776,   1261,  776,   1111,  783,   1142,
7710
    783,   1143,  776,   1242,  776,   1243,  776,   1258,  776,   1259,  1619,
7711
    1570,  1620,  1571,  1621,  1573,  1620,  1572,  1620,  1574,  1620,  1730,
7712
    1620,  1747,  1620,  1728,  2364,  2345,  2364,  2353,  2364,  2356,  2494,
7713
    2507,  2519,  2508,  2878,  2891,  2902,  2888,  2903,  2892,  3031,  2964,
7714
    3006,  3018,  3031,  3020,  3006,  3019,  3158,  3144,  3285,  3264,  3266,
7715
    3274,  3285,  3271,  3286,  3272,  3285,  3275,  3390,  3402,  3415,  3404,
7716
    3390,  3403,  3530,  3546,  3535,  3548,  3551,  3550,  3530,  3549,  4142,
7717
    4134,  6965,  6918,  6965,  6920,  6965,  6922,  6965,  6924,  6965,  6926,
7718
    6965,  6930,  6965,  6971,  6965,  6973,  6965,  6976,  6965,  6977,  6965,
7719
    6979,  772,   7736,  772,   7737,  772,   7772,  772,   7773,  775,   7784,
7720
    775,   7785,  770,   7852,  774,   7862,  770,   7853,  774,   7863,  770,
7721
    7878,  770,   7879,  770,   7896,  770,   7897,  768,   7938,  769,   7940,
7722
    834,   7942,  837,   8064,  768,   7939,  769,   7941,  834,   7943,  837,
7723
    8065,  837,   8066,  837,   8067,  837,   8068,  837,   8069,  837,   8070,
7724
    837,   8071,  768,   7946,  769,   7948,  834,   7950,  837,   8072,  768,
7725
    7947,  769,   7949,  834,   7951,  837,   8073,  837,   8074,  837,   8075,
7726
    837,   8076,  837,   8077,  837,   8078,  837,   8079,  768,   7954,  769,
7727
    7956,  768,   7955,  769,   7957,  768,   7962,  769,   7964,  768,   7963,
7728
    769,   7965,  768,   7970,  769,   7972,  834,   7974,  837,   8080,  768,
7729
    7971,  769,   7973,  834,   7975,  837,   8081,  837,   8082,  837,   8083,
7730
    837,   8084,  837,   8085,  837,   8086,  837,   8087,  768,   7978,  769,
7731
    7980,  834,   7982,  837,   8088,  768,   7979,  769,   7981,  834,   7983,
7732
    837,   8089,  837,   8090,  837,   8091,  837,   8092,  837,   8093,  837,
7733
    8094,  837,   8095,  768,   7986,  769,   7988,  834,   7990,  768,   7987,
7734
    769,   7989,  834,   7991,  768,   7994,  769,   7996,  834,   7998,  768,
7735
    7995,  769,   7997,  834,   7999,  768,   8002,  769,   8004,  768,   8003,
7736
    769,   8005,  768,   8010,  769,   8012,  768,   8011,  769,   8013,  768,
7737
    8018,  769,   8020,  834,   8022,  768,   8019,  769,   8021,  834,   8023,
7738
    768,   8027,  769,   8029,  834,   8031,  768,   8034,  769,   8036,  834,
7739
    8038,  837,   8096,  768,   8035,  769,   8037,  834,   8039,  837,   8097,
7740
    837,   8098,  837,   8099,  837,   8100,  837,   8101,  837,   8102,  837,
7741
    8103,  768,   8042,  769,   8044,  834,   8046,  837,   8104,  768,   8043,
7742
    769,   8045,  834,   8047,  837,   8105,  837,   8106,  837,   8107,  837,
7743
    8108,  837,   8109,  837,   8110,  837,   8111,  837,   8114,  837,   8130,
7744
    837,   8178,  837,   8119,  768,   8141,  769,   8142,  834,   8143,  837,
7745
    8135,  837,   8183,  768,   8157,  769,   8158,  834,   8159,  824,   8602,
7746
    824,   8603,  824,   8622,  824,   8653,  824,   8655,  824,   8654,  824,
7747
    8708,  824,   8713,  824,   8716,  824,   8740,  824,   8742,  824,   8769,
7748
    824,   8772,  824,   8775,  824,   8777,  824,   8813,  824,   8802,  824,
7749
    8816,  824,   8817,  824,   8820,  824,   8821,  824,   8824,  824,   8825,
7750
    824,   8832,  824,   8833,  824,   8928,  824,   8929,  824,   8836,  824,
7751
    8837,  824,   8840,  824,   8841,  824,   8930,  824,   8931,  824,   8876,
7752
    824,   8877,  824,   8878,  824,   8879,  824,   8938,  824,   8939,  824,
7753
    8940,  824,   8941,  12441, 12436, 12441, 12364, 12441, 12366, 12441, 12368,
7754
    12441, 12370, 12441, 12372, 12441, 12374, 12441, 12376, 12441, 12378, 12441,
7755
    12380, 12441, 12382, 12441, 12384, 12441, 12386, 12441, 12389, 12441, 12391,
7756
    12441, 12393, 12441, 12400, 12442, 12401, 12441, 12403, 12442, 12404, 12441,
7757
    12406, 12442, 12407, 12441, 12409, 12442, 12410, 12441, 12412, 12442, 12413,
7758
    12441, 12446, 12441, 12532, 12441, 12460, 12441, 12462, 12441, 12464, 12441,
7759
    12466, 12441, 12468, 12441, 12470, 12441, 12472, 12441, 12474, 12441, 12476,
7760
    12441, 12478, 12441, 12480, 12441, 12482, 12441, 12485, 12441, 12487, 12441,
7761
    12489, 12441, 12496, 12442, 12497, 12441, 12499, 12442, 12500, 12441, 12502,
7762
    12442, 12503, 12441, 12505, 12442, 12506, 12441, 12508, 12442, 12509, 12441,
7763
    12535, 12441, 12536, 12441, 12537, 12441, 12538, 12441, 12542, 69818, 69786,
7764
    69818, 69788, 69818, 69803, 69927, 69934, 69927, 69935, 70462, 70475, 70487,
7765
    70476, 70832, 70844, 70842, 70843, 70845, 70846, 71087, 71098, 71087, 71099,
7766
    71984, 71992};
7767
7768
}  // namespace ada::idna
7769
#endif  // ADA_IDNA_NORMALIZATION_TABLES_H
7770
/* end file src/normalization_tables.cpp */
7771
7772
namespace ada::idna {
7773
7774
// See
7775
// https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/impl_norm.h#L467
7776
constexpr char32_t hangul_sbase = 0xAC00;
7777
constexpr char32_t hangul_tbase = 0x11A7;
7778
constexpr char32_t hangul_vbase = 0x1161;
7779
constexpr char32_t hangul_lbase = 0x1100;
7780
constexpr char32_t hangul_lcount = 19;
7781
constexpr char32_t hangul_vcount = 21;
7782
constexpr char32_t hangul_tcount = 28;
7783
constexpr char32_t hangul_ncount = hangul_vcount * hangul_tcount;
7784
constexpr char32_t hangul_scount =
7785
    hangul_lcount * hangul_vcount * hangul_tcount;
7786
7787
std::pair<bool, size_t> compute_decomposition_length(
7788
13.4k
    const std::u32string_view input) noexcept {
7789
13.4k
  bool decomposition_needed{false};
7790
13.4k
  size_t additional_elements{0};
7791
519k
  for (char32_t current_character : input) {
7792
519k
    size_t decomposition_length{0};
7793
7794
519k
    if (current_character >= hangul_sbase &&
7795
24.7k
        current_character < hangul_sbase + hangul_scount) {
7796
21.8k
      decomposition_length = 2;
7797
21.8k
      if ((current_character - hangul_sbase) % hangul_tcount) {
7798
4.40k
        decomposition_length = 3;
7799
4.40k
      }
7800
497k
    } else if (current_character < 0x110000) {
7801
497k
      const uint8_t di = decomposition_index[current_character >> 8];
7802
497k
      const uint16_t* const decomposition =
7803
497k
          decomposition_block[di] + (current_character % 256);
7804
497k
      decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
7805
497k
      if ((decomposition_length > 0) && (decomposition[0] & 1)) {
7806
0
        decomposition_length = 0;
7807
0
      }
7808
497k
    }
7809
519k
    if (decomposition_length != 0) {
7810
26.3k
      decomposition_needed = true;
7811
26.3k
      additional_elements += decomposition_length - 1;
7812
26.3k
    }
7813
519k
  }
7814
13.4k
  return {decomposition_needed, additional_elements};
7815
13.4k
}
7816
7817
4.05k
void decompose(std::u32string& input, size_t additional_elements) {
7818
4.05k
  input.resize(input.size() + additional_elements);
7819
4.05k
  for (size_t descending_idx = input.size(),
7820
4.05k
              input_count = descending_idx - additional_elements;
7821
243k
       input_count--;) {
7822
239k
    if (input[input_count] >= hangul_sbase &&
7823
22.6k
        input[input_count] < hangul_sbase + hangul_scount) {
7824
      // Hangul decomposition.
7825
21.8k
      char32_t s_index = input[input_count] - hangul_sbase;
7826
21.8k
      if (s_index % hangul_tcount != 0) {
7827
4.40k
        input[--descending_idx] = hangul_tbase + s_index % hangul_tcount;
7828
4.40k
      }
7829
21.8k
      input[--descending_idx] =
7830
21.8k
          hangul_vbase + (s_index % hangul_ncount) / hangul_tcount;
7831
21.8k
      input[--descending_idx] = hangul_lbase + s_index / hangul_ncount;
7832
217k
    } else if (input[input_count] < 0x110000) {
7833
      // Check decomposition_data.
7834
217k
      const uint16_t* decomposition =
7835
217k
          decomposition_block[decomposition_index[input[input_count] >> 8]] +
7836
217k
          (input[input_count] % 256);
7837
217k
      uint16_t decomposition_length =
7838
217k
          (decomposition[1] >> 2) - (decomposition[0] >> 2);
7839
217k
      if (decomposition_length > 0 && (decomposition[0] & 1)) {
7840
0
        decomposition_length = 0;
7841
0
      }
7842
217k
      if (decomposition_length > 0) {
7843
        // Non-recursive decomposition.
7844
14.7k
        while (decomposition_length-- > 0) {
7845
10.2k
          input[--descending_idx] = decomposition_data[(decomposition[0] >> 2) +
7846
10.2k
                                                       decomposition_length];
7847
10.2k
        }
7848
212k
      } else {
7849
        // No decomposition.
7850
212k
        input[--descending_idx] = input[input_count];
7851
212k
      }
7852
217k
    } else {
7853
      // Non-Unicode character.
7854
0
      input[--descending_idx] = input[input_count];
7855
0
    }
7856
239k
  }
7857
4.05k
}
7858
7859
1.04M
uint8_t get_ccc(char32_t c) noexcept {
7860
1.04M
  return c < 0x110000 ? canonical_combining_class_block
7861
1.04M
                            [canonical_combining_class_index[c >> 8]][c % 256]
7862
1.04M
                      : 0;
7863
1.04M
}
7864
7865
13.4k
void sort_marks(std::u32string& input) {
7866
551k
  for (size_t idx = 1; idx < input.size(); idx++) {
7867
538k
    uint8_t ccc = get_ccc(input[idx]);
7868
538k
    if (ccc == 0) {
7869
526k
      continue;
7870
526k
    }  // Skip non-combining characters.
7871
12.0k
    auto current_character = input[idx];
7872
12.0k
    size_t back_idx = idx;
7873
13.6k
    while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) {
7874
1.59k
      input[back_idx] = input[back_idx - 1];
7875
1.59k
      back_idx--;
7876
1.59k
    }
7877
12.0k
    input[back_idx] = current_character;
7878
12.0k
  }
7879
13.4k
}
7880
7881
13.4k
void decompose_nfc(std::u32string& input) {
7882
  /**
7883
   * Decompose the domain_name string to Unicode Normalization Form C.
7884
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepDecompose
7885
   */
7886
13.4k
  auto [decomposition_needed, additional_elements] =
7887
13.4k
      compute_decomposition_length(input);
7888
13.4k
  if (decomposition_needed) {
7889
4.05k
    decompose(input, additional_elements);
7890
4.05k
  }
7891
13.4k
  sort_marks(input);
7892
13.4k
}
7893
7894
13.4k
void compose(std::u32string& input) {
7895
  /**
7896
   * Compose the domain_name string to Unicode Normalization Form C.
7897
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepCompose
7898
   */
7899
13.4k
  size_t input_count{0};
7900
13.4k
  size_t composition_count{0};
7901
526k
  for (; input_count < input.size(); input_count++, composition_count++) {
7902
513k
    input[composition_count] = input[input_count];
7903
513k
    if (input[input_count] >= hangul_lbase &&
7904
259k
        input[input_count] < hangul_lbase + hangul_lcount) {
7905
23.5k
      if (input_count + 1 < input.size() &&
7906
23.2k
          input[input_count + 1] >= hangul_vbase &&
7907
22.2k
          input[input_count + 1] < hangul_vbase + hangul_vcount) {
7908
21.8k
        input[composition_count] =
7909
21.8k
            hangul_sbase +
7910
21.8k
            ((input[input_count] - hangul_lbase) * hangul_vcount +
7911
21.8k
             input[input_count + 1] - hangul_vbase) *
7912
21.8k
                hangul_tcount;
7913
21.8k
        input_count++;
7914
21.8k
        if (input_count + 1 < input.size() &&
7915
21.6k
            input[input_count + 1] > hangul_tbase &&
7916
4.72k
            input[input_count + 1] < hangul_tbase + hangul_tcount) {
7917
4.40k
          input[composition_count] += input[++input_count] - hangul_tbase;
7918
4.40k
        }
7919
21.8k
      }
7920
489k
    } else if (input[input_count] >= hangul_sbase &&
7921
2.29k
               input[input_count] < hangul_sbase + hangul_scount) {
7922
0
      if ((input[input_count] - hangul_sbase) % hangul_tcount &&
7923
0
          input_count + 1 < input.size() &&
7924
0
          input[input_count + 1] > hangul_tbase &&
7925
0
          input[input_count + 1] < hangul_tbase + hangul_tcount) {
7926
0
        input[composition_count] += input[++input_count] - hangul_tbase;
7927
0
      }
7928
489k
    } else if (input[input_count] < 0x110000) {
7929
489k
      const uint16_t* composition =
7930
489k
          &composition_block[composition_index[input[input_count] >> 8]]
7931
489k
                            [input[input_count] % 256];
7932
489k
      size_t initial_composition_count = composition_count;
7933
501k
      for (int32_t previous_ccc = -1; input_count + 1 < input.size();
7934
489k
           input_count++) {
7935
489k
        uint8_t ccc = get_ccc(input[input_count + 1]);
7936
7937
489k
        if (composition[1] != composition[0] && previous_ccc < ccc) {
7938
          // Try finding a composition.
7939
102k
          int left = composition[0];
7940
102k
          int right = composition[1];
7941
247k
          while (left + 2 < right) {
7942
            // mean without overflow
7943
144k
            int middle = left + (((right - left) >> 1) & ~1);
7944
144k
            if (composition_data[middle] <= input[input_count + 1]) {
7945
11.8k
              left = middle;
7946
11.8k
            }
7947
144k
            if (composition_data[middle] >= input[input_count + 1]) {
7948
135k
              right = middle;
7949
135k
            }
7950
144k
          }
7951
102k
          if (composition_data[left] == input[input_count + 1]) {
7952
5.84k
            input[initial_composition_count] = composition_data[left + 1];
7953
5.84k
            composition =
7954
5.84k
                &composition_block
7955
5.84k
                    [composition_index[composition_data[left + 1] >> 8]]
7956
5.84k
                    [composition_data[left + 1] % 256];
7957
5.84k
            continue;
7958
5.84k
          }
7959
102k
        }
7960
7961
483k
        if (ccc == 0) {
7962
477k
          break;
7963
477k
        }  // Not a combining character.
7964
6.27k
        previous_ccc = ccc;
7965
6.27k
        input[++composition_count] = input[input_count + 1];
7966
6.27k
      }
7967
489k
    }
7968
513k
  }
7969
7970
13.4k
  if (composition_count < input_count) {
7971
4.08k
    input.resize(composition_count);
7972
4.08k
  }
7973
13.4k
}
7974
7975
13.4k
void normalize(std::u32string& input) {
7976
  /**
7977
   * Normalize the domain_name string to Unicode Normalization Form C.
7978
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepNormalize
7979
   */
7980
13.4k
  decompose_nfc(input);
7981
13.4k
  compose(input);
7982
13.4k
}
7983
7984
}  // namespace ada::idna
7985
/* end file src/normalization.cpp */
7986
/* begin file src/punycode.cpp */
7987
7988
#include <cstdint>
7989
7990
namespace ada::idna {
7991
7992
constexpr int32_t base = 36;
7993
constexpr int32_t tmin = 1;
7994
constexpr int32_t tmax = 26;
7995
constexpr int32_t skew = 38;
7996
constexpr int32_t damp = 700;
7997
constexpr int32_t initial_bias = 72;
7998
constexpr uint32_t initial_n = 128;
7999
8000
57.1k
static constexpr int32_t char_to_digit_value(char value) {
8001
57.1k
  if (value >= 'a' && value <= 'z') return value - 'a';
8002
7.27k
  if (value >= '0' && value <= '9') return value - '0' + 26;
8003
108
  return -1;
8004
7.27k
}
8005
8006
789k
static constexpr char digit_to_char(int32_t digit) {
8007
789k
  return digit < 26 ? char(digit + 97) : char(digit + 22);
8008
789k
}
8009
8010
345k
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
8011
345k
  if (firsttime) {
8012
40.6k
    d = d / damp;
8013
304k
  } else {
8014
304k
    d = d / 2;
8015
304k
  }
8016
345k
  d += d / n;
8017
345k
  int32_t k = 0;
8018
515k
  while (d > ((base - tmin) * tmax) / 2) {
8019
169k
    d /= base - tmin;
8020
169k
    k += base;
8021
169k
  }
8022
345k
  return k + (((base - tmin + 1) * d) / (d + skew));
8023
345k
}
8024
8025
5.78k
bool punycode_to_utf32(std::string_view input, std::u32string &out) {
8026
  // See https://github.com/whatwg/url/issues/803
8027
5.78k
  if (input.starts_with("xn--")) {
8028
6
    return false;
8029
6
  }
8030
5.78k
  int32_t written_out{0};
8031
5.78k
  out.reserve(out.size() + input.size());
8032
5.78k
  uint32_t n = initial_n;
8033
5.78k
  int32_t i = 0;
8034
5.78k
  int32_t bias = initial_bias;
8035
  // grab ascii content
8036
5.78k
  size_t end_of_ascii = input.find_last_of('-');
8037
5.78k
  if (end_of_ascii != std::string_view::npos) {
8038
5.35k
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8039
5.35k
      if (c >= 0x80) {
8040
0
        return false;
8041
0
      }
8042
5.35k
      out.push_back(c);
8043
5.35k
      written_out++;
8044
5.35k
    }
8045
470
    input.remove_prefix(end_of_ascii + 1);
8046
470
  }
8047
48.2k
  while (!input.empty()) {
8048
42.8k
    int32_t oldi = i;
8049
42.8k
    int32_t w = 1;
8050
57.3k
    for (int32_t k = base;; k += base) {
8051
57.3k
      if (input.empty()) {
8052
178
        return false;
8053
178
      }
8054
57.1k
      uint8_t code_point = input.front();
8055
57.1k
      input.remove_prefix(1);
8056
57.1k
      int32_t digit = char_to_digit_value(code_point);
8057
57.1k
      if (digit < 0) {
8058
108
        return false;
8059
108
      }
8060
57.0k
      if (digit > (0x7fffffff - i) / w) {
8061
14
        return false;
8062
14
      }
8063
57.0k
      i = i + digit * w;
8064
57.0k
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8065
57.0k
      if (digit < t) {
8066
42.5k
        break;
8067
42.5k
      }
8068
14.5k
      if (w > 0x7fffffff / (base - t)) {
8069
0
        return false;
8070
0
      }
8071
14.5k
      w = w * (base - t);
8072
14.5k
    }
8073
42.5k
    bias = adapt(i - oldi, written_out + 1, oldi == 0);
8074
42.5k
    if (i / (written_out + 1) > int32_t(0x7fffffff - n)) {
8075
86
      return false;
8076
86
    }
8077
42.4k
    n = n + i / (written_out + 1);
8078
42.4k
    i = i % (written_out + 1);
8079
42.4k
    if (n < 0x80) {
8080
0
      return false;
8081
0
    }
8082
42.4k
    out.insert(out.begin() + i, n);
8083
42.4k
    written_out++;
8084
42.4k
    ++i;
8085
42.4k
  }
8086
5.39k
  return true;
8087
5.78k
}
8088
8089
0
bool verify_punycode(std::string_view input) {
8090
0
  if (input.starts_with("xn--")) {
8091
0
    return false;
8092
0
  }
8093
0
  size_t written_out{0};
8094
0
  uint32_t n = initial_n;
8095
0
  int32_t i = 0;
8096
0
  int32_t bias = initial_bias;
8097
  // grab ascii content
8098
0
  size_t end_of_ascii = input.find_last_of('-');
8099
0
  if (end_of_ascii != std::string_view::npos) {
8100
0
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8101
0
      if (c >= 0x80) {
8102
0
        return false;
8103
0
      }
8104
0
      written_out++;
8105
0
    }
8106
0
    input.remove_prefix(end_of_ascii + 1);
8107
0
  }
8108
0
  while (!input.empty()) {
8109
0
    int32_t oldi = i;
8110
0
    int32_t w = 1;
8111
0
    for (int32_t k = base;; k += base) {
8112
0
      if (input.empty()) {
8113
0
        return false;
8114
0
      }
8115
0
      uint8_t code_point = input.front();
8116
0
      input.remove_prefix(1);
8117
0
      int32_t digit = char_to_digit_value(code_point);
8118
0
      if (digit < 0) {
8119
0
        return false;
8120
0
      }
8121
0
      if (digit > (0x7fffffff - i) / w) {
8122
0
        return false;
8123
0
      }
8124
0
      i = i + digit * w;
8125
0
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8126
0
      if (digit < t) {
8127
0
        break;
8128
0
      }
8129
0
      if (w > 0x7fffffff / (base - t)) {
8130
0
        return false;
8131
0
      }
8132
0
      w = w * (base - t);
8133
0
    }
8134
0
    bias = adapt(i - oldi, int32_t(written_out + 1), oldi == 0);
8135
0
    if (i / (written_out + 1) > 0x7fffffff - n) {
8136
0
      return false;
8137
0
    }
8138
0
    n = n + i / int32_t(written_out + 1);
8139
0
    i = i % int32_t(written_out + 1);
8140
0
    if (n < 0x80) {
8141
0
      return false;
8142
0
    }
8143
0
    written_out++;
8144
0
    ++i;
8145
0
  }
8146
8147
0
  return true;
8148
0
}
8149
8150
35.2k
bool utf32_to_punycode(std::u32string_view input, std::string &out) {
8151
35.2k
  out.reserve(input.size() + out.size());
8152
35.2k
  uint32_t n = initial_n;
8153
35.2k
  int32_t d = 0;
8154
35.2k
  int32_t bias = initial_bias;
8155
35.2k
  size_t h = 0;
8156
  // first push the ascii content
8157
344k
  for (uint32_t c : input) {
8158
344k
    if (c < 0x80) {
8159
42.0k
      ++h;
8160
42.0k
      out.push_back(char(c));
8161
42.0k
    }
8162
344k
    if (c > 0x10ffff || (c >= 0xd800 && c < 0xe000)) {
8163
0
      return false;
8164
0
    }
8165
344k
  }
8166
35.2k
  size_t b = h;
8167
35.2k
  if (b > 0) {
8168
12.8k
    out.push_back('-');
8169
12.8k
  }
8170
241k
  while (h < input.size()) {
8171
206k
    uint32_t m = 0x10FFFF;
8172
3.45M
    for (auto code_point : input) {
8173
3.45M
      if (code_point >= n && code_point < m) m = code_point;
8174
3.45M
    }
8175
8176
206k
    if ((m - n) > (0x7fffffff - d) / (h + 1)) {
8177
0
      return false;
8178
0
    }
8179
206k
    d = d + int32_t((m - n) * (h + 1));
8180
206k
    n = m;
8181
3.45M
    for (auto c : input) {
8182
3.45M
      if (c < n) {
8183
1.81M
        if (d == 0x7fffffff) {
8184
0
          return false;
8185
0
        }
8186
1.81M
        ++d;
8187
1.81M
      }
8188
3.45M
      if (c == n) {
8189
302k
        int32_t q = d;
8190
789k
        for (int32_t k = base;; k += base) {
8191
789k
          int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8192
8193
789k
          if (q < t) {
8194
302k
            break;
8195
302k
          }
8196
487k
          out.push_back(digit_to_char(t + ((q - t) % (base - t))));
8197
487k
          q = (q - t) / (base - t);
8198
487k
        }
8199
302k
        out.push_back(digit_to_char(q));
8200
302k
        bias = adapt(d, int32_t(h + 1), h == b);
8201
302k
        d = 0;
8202
302k
        ++h;
8203
302k
      }
8204
3.45M
    }
8205
206k
    ++d;
8206
206k
    ++n;
8207
206k
  }
8208
35.2k
  return true;
8209
35.2k
}
8210
8211
}  // namespace ada::idna
8212
/* end file src/punycode.cpp */
8213
/* begin file src/validity.cpp */
8214
#include <algorithm>
8215
#include <string_view>
8216
8217
namespace ada::idna {
8218
8219
enum direction : uint8_t {
8220
  NONE,
8221
  BN,
8222
  CS,
8223
  ES,
8224
  ON,
8225
  EN,
8226
  L,
8227
  R,
8228
  NSM,
8229
  AL,
8230
  AN,
8231
  ET,
8232
  WS,
8233
  RLO,
8234
  LRO,
8235
  PDF,
8236
  RLE,
8237
  RLI,
8238
  FSI,
8239
  PDI,
8240
  LRI,
8241
  B,
8242
  S,
8243
  LRE
8244
};
8245
8246
struct directions {
8247
  uint32_t start_code;
8248
  uint32_t final_code;
8249
  direction direct;
8250
};
8251
8252
static directions dir_table[] = {
8253
    {0x0, 0x8, direction::BN},          {0x9, 0x9, direction::S},
8254
    {0xa, 0xa, direction::B},           {0xb, 0xb, direction::S},
8255
    {0xc, 0xc, direction::WS},          {0xd, 0xd, direction::B},
8256
    {0xe, 0x1b, direction::BN},         {0x1c, 0x1e, direction::B},
8257
    {0x1f, 0x1f, direction::S},         {0x20, 0x20, direction::WS},
8258
    {0x21, 0x22, direction::ON},        {0x23, 0x25, direction::ET},
8259
    {0x26, 0x2a, direction::ON},        {0x2b, 0x2b, direction::ES},
8260
    {0x2c, 0x2c, direction::CS},        {0x2d, 0x2d, direction::ES},
8261
    {0x2e, 0x2f, direction::CS},        {0x30, 0x39, direction::EN},
8262
    {0x3a, 0x3a, direction::CS},        {0x3b, 0x40, direction::ON},
8263
    {0x41, 0x5a, direction::L},         {0x5b, 0x60, direction::ON},
8264
    {0x61, 0x7a, direction::L},         {0x7b, 0x7e, direction::ON},
8265
    {0x7f, 0x84, direction::BN},        {0x85, 0x85, direction::B},
8266
    {0x86, 0x9f, direction::BN},        {0xa0, 0xa0, direction::CS},
8267
    {0xa1, 0xa1, direction::ON},        {0xa2, 0xa5, direction::ET},
8268
    {0xa6, 0xa9, direction::ON},        {0xaa, 0xaa, direction::L},
8269
    {0xab, 0xac, direction::ON},        {0xad, 0xad, direction::BN},
8270
    {0xae, 0xaf, direction::ON},        {0xb0, 0xb1, direction::ET},
8271
    {0xb2, 0xb3, direction::EN},        {0xb4, 0xb4, direction::ON},
8272
    {0xb5, 0xb5, direction::L},         {0xb6, 0xb8, direction::ON},
8273
    {0xb9, 0xb9, direction::EN},        {0xba, 0xba, direction::L},
8274
    {0xbb, 0xbf, direction::ON},        {0xc0, 0xd6, direction::L},
8275
    {0xd7, 0xd7, direction::ON},        {0xd8, 0xf6, direction::L},
8276
    {0xf7, 0xf7, direction::ON},        {0xf8, 0x2b8, direction::L},
8277
    {0x2b9, 0x2ba, direction::ON},      {0x2bb, 0x2c1, direction::L},
8278
    {0x2c2, 0x2cf, direction::ON},      {0x2d0, 0x2d1, direction::L},
8279
    {0x2d2, 0x2df, direction::ON},      {0x2e0, 0x2e4, direction::L},
8280
    {0x2e5, 0x2ed, direction::ON},      {0x2ee, 0x2ee, direction::L},
8281
    {0x2ef, 0x2ff, direction::ON},      {0x300, 0x36f, direction::NSM},
8282
    {0x370, 0x373, direction::L},       {0x374, 0x375, direction::ON},
8283
    {0x376, 0x377, direction::L},       {0x37a, 0x37d, direction::L},
8284
    {0x37e, 0x37e, direction::ON},      {0x37f, 0x37f, direction::L},
8285
    {0x384, 0x385, direction::ON},      {0x386, 0x386, direction::L},
8286
    {0x387, 0x387, direction::ON},      {0x388, 0x38a, direction::L},
8287
    {0x38c, 0x38c, direction::L},       {0x38e, 0x3a1, direction::L},
8288
    {0x3a3, 0x3f5, direction::L},       {0x3f6, 0x3f6, direction::ON},
8289
    {0x3f7, 0x482, direction::L},       {0x483, 0x489, direction::NSM},
8290
    {0x48a, 0x52f, direction::L},       {0x531, 0x556, direction::L},
8291
    {0x559, 0x589, direction::L},       {0x58a, 0x58a, direction::ON},
8292
    {0x58d, 0x58e, direction::ON},      {0x58f, 0x58f, direction::ET},
8293
    {0x591, 0x5bd, direction::NSM},     {0x5be, 0x5be, direction::R},
8294
    {0x5bf, 0x5bf, direction::NSM},     {0x5c0, 0x5c0, direction::R},
8295
    {0x5c1, 0x5c2, direction::NSM},     {0x5c3, 0x5c3, direction::R},
8296
    {0x5c4, 0x5c5, direction::NSM},     {0x5c6, 0x5c6, direction::R},
8297
    {0x5c7, 0x5c7, direction::NSM},     {0x5d0, 0x5ea, direction::R},
8298
    {0x5ef, 0x5f4, direction::R},       {0x600, 0x605, direction::AN},
8299
    {0x606, 0x607, direction::ON},      {0x608, 0x608, direction::AL},
8300
    {0x609, 0x60a, direction::ET},      {0x60b, 0x60b, direction::AL},
8301
    {0x60c, 0x60c, direction::CS},      {0x60d, 0x60d, direction::AL},
8302
    {0x60e, 0x60f, direction::ON},      {0x610, 0x61a, direction::NSM},
8303
    {0x61b, 0x61c, direction::AL},      {0x61e, 0x64a, direction::AL},
8304
    {0x64b, 0x65f, direction::NSM},     {0x660, 0x669, direction::AN},
8305
    {0x66a, 0x66a, direction::ET},      {0x66b, 0x66c, direction::AN},
8306
    {0x66d, 0x66f, direction::AL},      {0x670, 0x670, direction::NSM},
8307
    {0x671, 0x6d5, direction::AL},      {0x6d6, 0x6dc, direction::NSM},
8308
    {0x6dd, 0x6dd, direction::AN},      {0x6de, 0x6de, direction::ON},
8309
    {0x6df, 0x6e4, direction::NSM},     {0x6e5, 0x6e6, direction::AL},
8310
    {0x6e7, 0x6e8, direction::NSM},     {0x6e9, 0x6e9, direction::ON},
8311
    {0x6ea, 0x6ed, direction::NSM},     {0x6ee, 0x6ef, direction::AL},
8312
    {0x6f0, 0x6f9, direction::EN},      {0x6fa, 0x70d, direction::AL},
8313
    {0x70f, 0x710, direction::AL},      {0x711, 0x711, direction::NSM},
8314
    {0x712, 0x72f, direction::AL},      {0x730, 0x74a, direction::NSM},
8315
    {0x74d, 0x7a5, direction::AL},      {0x7a6, 0x7b0, direction::NSM},
8316
    {0x7b1, 0x7b1, direction::AL},      {0x7c0, 0x7ea, direction::R},
8317
    {0x7eb, 0x7f3, direction::NSM},     {0x7f4, 0x7f5, direction::R},
8318
    {0x7f6, 0x7f9, direction::ON},      {0x7fa, 0x7fa, direction::R},
8319
    {0x7fd, 0x7fd, direction::NSM},     {0x7fe, 0x815, direction::R},
8320
    {0x816, 0x819, direction::NSM},     {0x81a, 0x81a, direction::R},
8321
    {0x81b, 0x823, direction::NSM},     {0x824, 0x824, direction::R},
8322
    {0x825, 0x827, direction::NSM},     {0x828, 0x828, direction::R},
8323
    {0x829, 0x82d, direction::NSM},     {0x830, 0x83e, direction::R},
8324
    {0x840, 0x858, direction::R},       {0x859, 0x85b, direction::NSM},
8325
    {0x85e, 0x85e, direction::R},       {0x860, 0x86a, direction::AL},
8326
    {0x8a0, 0x8b4, direction::AL},      {0x8b6, 0x8c7, direction::AL},
8327
    {0x8d3, 0x8e1, direction::NSM},     {0x8e2, 0x8e2, direction::AN},
8328
    {0x8e3, 0x902, direction::NSM},     {0x903, 0x939, direction::L},
8329
    {0x93a, 0x93a, direction::NSM},     {0x93b, 0x93b, direction::L},
8330
    {0x93c, 0x93c, direction::NSM},     {0x93d, 0x940, direction::L},
8331
    {0x941, 0x948, direction::NSM},     {0x949, 0x94c, direction::L},
8332
    {0x94d, 0x94d, direction::NSM},     {0x94e, 0x950, direction::L},
8333
    {0x951, 0x957, direction::NSM},     {0x958, 0x961, direction::L},
8334
    {0x962, 0x963, direction::NSM},     {0x964, 0x980, direction::L},
8335
    {0x981, 0x981, direction::NSM},     {0x982, 0x983, direction::L},
8336
    {0x985, 0x98c, direction::L},       {0x98f, 0x990, direction::L},
8337
    {0x993, 0x9a8, direction::L},       {0x9aa, 0x9b0, direction::L},
8338
    {0x9b2, 0x9b2, direction::L},       {0x9b6, 0x9b9, direction::L},
8339
    {0x9bc, 0x9bc, direction::NSM},     {0x9bd, 0x9c0, direction::L},
8340
    {0x9c1, 0x9c4, direction::NSM},     {0x9c7, 0x9c8, direction::L},
8341
    {0x9cb, 0x9cc, direction::L},       {0x9cd, 0x9cd, direction::NSM},
8342
    {0x9ce, 0x9ce, direction::L},       {0x9d7, 0x9d7, direction::L},
8343
    {0x9dc, 0x9dd, direction::L},       {0x9df, 0x9e1, direction::L},
8344
    {0x9e2, 0x9e3, direction::NSM},     {0x9e6, 0x9f1, direction::L},
8345
    {0x9f2, 0x9f3, direction::ET},      {0x9f4, 0x9fa, direction::L},
8346
    {0x9fb, 0x9fb, direction::ET},      {0x9fc, 0x9fd, direction::L},
8347
    {0x9fe, 0x9fe, direction::NSM},     {0xa01, 0xa02, direction::NSM},
8348
    {0xa03, 0xa03, direction::L},       {0xa05, 0xa0a, direction::L},
8349
    {0xa0f, 0xa10, direction::L},       {0xa13, 0xa28, direction::L},
8350
    {0xa2a, 0xa30, direction::L},       {0xa32, 0xa33, direction::L},
8351
    {0xa35, 0xa36, direction::L},       {0xa38, 0xa39, direction::L},
8352
    {0xa3c, 0xa3c, direction::NSM},     {0xa3e, 0xa40, direction::L},
8353
    {0xa41, 0xa42, direction::NSM},     {0xa47, 0xa48, direction::NSM},
8354
    {0xa4b, 0xa4d, direction::NSM},     {0xa51, 0xa51, direction::NSM},
8355
    {0xa59, 0xa5c, direction::L},       {0xa5e, 0xa5e, direction::L},
8356
    {0xa66, 0xa6f, direction::L},       {0xa70, 0xa71, direction::NSM},
8357
    {0xa72, 0xa74, direction::L},       {0xa75, 0xa75, direction::NSM},
8358
    {0xa76, 0xa76, direction::L},       {0xa81, 0xa82, direction::NSM},
8359
    {0xa83, 0xa83, direction::L},       {0xa85, 0xa8d, direction::L},
8360
    {0xa8f, 0xa91, direction::L},       {0xa93, 0xaa8, direction::L},
8361
    {0xaaa, 0xab0, direction::L},       {0xab2, 0xab3, direction::L},
8362
    {0xab5, 0xab9, direction::L},       {0xabc, 0xabc, direction::NSM},
8363
    {0xabd, 0xac0, direction::L},       {0xac1, 0xac5, direction::NSM},
8364
    {0xac7, 0xac8, direction::NSM},     {0xac9, 0xac9, direction::L},
8365
    {0xacb, 0xacc, direction::L},       {0xacd, 0xacd, direction::NSM},
8366
    {0xad0, 0xad0, direction::L},       {0xae0, 0xae1, direction::L},
8367
    {0xae2, 0xae3, direction::NSM},     {0xae6, 0xaf0, direction::L},
8368
    {0xaf1, 0xaf1, direction::ET},      {0xaf9, 0xaf9, direction::L},
8369
    {0xafa, 0xaff, direction::NSM},     {0xb01, 0xb01, direction::NSM},
8370
    {0xb02, 0xb03, direction::L},       {0xb05, 0xb0c, direction::L},
8371
    {0xb0f, 0xb10, direction::L},       {0xb13, 0xb28, direction::L},
8372
    {0xb2a, 0xb30, direction::L},       {0xb32, 0xb33, direction::L},
8373
    {0xb35, 0xb39, direction::L},       {0xb3c, 0xb3c, direction::NSM},
8374
    {0xb3d, 0xb3e, direction::L},       {0xb3f, 0xb3f, direction::NSM},
8375
    {0xb40, 0xb40, direction::L},       {0xb41, 0xb44, direction::NSM},
8376
    {0xb47, 0xb48, direction::L},       {0xb4b, 0xb4c, direction::L},
8377
    {0xb4d, 0xb4d, direction::NSM},     {0xb55, 0xb56, direction::NSM},
8378
    {0xb57, 0xb57, direction::L},       {0xb5c, 0xb5d, direction::L},
8379
    {0xb5f, 0xb61, direction::L},       {0xb62, 0xb63, direction::NSM},
8380
    {0xb66, 0xb77, direction::L},       {0xb82, 0xb82, direction::NSM},
8381
    {0xb83, 0xb83, direction::L},       {0xb85, 0xb8a, direction::L},
8382
    {0xb8e, 0xb90, direction::L},       {0xb92, 0xb95, direction::L},
8383
    {0xb99, 0xb9a, direction::L},       {0xb9c, 0xb9c, direction::L},
8384
    {0xb9e, 0xb9f, direction::L},       {0xba3, 0xba4, direction::L},
8385
    {0xba8, 0xbaa, direction::L},       {0xbae, 0xbb9, direction::L},
8386
    {0xbbe, 0xbbf, direction::L},       {0xbc0, 0xbc0, direction::NSM},
8387
    {0xbc1, 0xbc2, direction::L},       {0xbc6, 0xbc8, direction::L},
8388
    {0xbca, 0xbcc, direction::L},       {0xbcd, 0xbcd, direction::NSM},
8389
    {0xbd0, 0xbd0, direction::L},       {0xbd7, 0xbd7, direction::L},
8390
    {0xbe6, 0xbf2, direction::L},       {0xbf3, 0xbf8, direction::ON},
8391
    {0xbf9, 0xbf9, direction::ET},      {0xbfa, 0xbfa, direction::ON},
8392
    {0xc00, 0xc00, direction::NSM},     {0xc01, 0xc03, direction::L},
8393
    {0xc04, 0xc04, direction::NSM},     {0xc05, 0xc0c, direction::L},
8394
    {0xc0e, 0xc10, direction::L},       {0xc12, 0xc28, direction::L},
8395
    {0xc2a, 0xc39, direction::L},       {0xc3d, 0xc3d, direction::L},
8396
    {0xc3e, 0xc40, direction::NSM},     {0xc41, 0xc44, direction::L},
8397
    {0xc46, 0xc48, direction::NSM},     {0xc4a, 0xc4d, direction::NSM},
8398
    {0xc55, 0xc56, direction::NSM},     {0xc58, 0xc5a, direction::L},
8399
    {0xc60, 0xc61, direction::L},       {0xc62, 0xc63, direction::NSM},
8400
    {0xc66, 0xc6f, direction::L},       {0xc77, 0xc77, direction::L},
8401
    {0xc78, 0xc7e, direction::ON},      {0xc7f, 0xc80, direction::L},
8402
    {0xc81, 0xc81, direction::NSM},     {0xc82, 0xc8c, direction::L},
8403
    {0xc8e, 0xc90, direction::L},       {0xc92, 0xca8, direction::L},
8404
    {0xcaa, 0xcb3, direction::L},       {0xcb5, 0xcb9, direction::L},
8405
    {0xcbc, 0xcbc, direction::NSM},     {0xcbd, 0xcc4, direction::L},
8406
    {0xcc6, 0xcc8, direction::L},       {0xcca, 0xccb, direction::L},
8407
    {0xccc, 0xccd, direction::NSM},     {0xcd5, 0xcd6, direction::L},
8408
    {0xcde, 0xcde, direction::L},       {0xce0, 0xce1, direction::L},
8409
    {0xce2, 0xce3, direction::NSM},     {0xce6, 0xcef, direction::L},
8410
    {0xcf1, 0xcf2, direction::L},       {0xd00, 0xd01, direction::NSM},
8411
    {0xd02, 0xd0c, direction::L},       {0xd0e, 0xd10, direction::L},
8412
    {0xd12, 0xd3a, direction::L},       {0xd3b, 0xd3c, direction::NSM},
8413
    {0xd3d, 0xd40, direction::L},       {0xd41, 0xd44, direction::NSM},
8414
    {0xd46, 0xd48, direction::L},       {0xd4a, 0xd4c, direction::L},
8415
    {0xd4d, 0xd4d, direction::NSM},     {0xd4e, 0xd4f, direction::L},
8416
    {0xd54, 0xd61, direction::L},       {0xd62, 0xd63, direction::NSM},
8417
    {0xd66, 0xd7f, direction::L},       {0xd81, 0xd81, direction::NSM},
8418
    {0xd82, 0xd83, direction::L},       {0xd85, 0xd96, direction::L},
8419
    {0xd9a, 0xdb1, direction::L},       {0xdb3, 0xdbb, direction::L},
8420
    {0xdbd, 0xdbd, direction::L},       {0xdc0, 0xdc6, direction::L},
8421
    {0xdca, 0xdca, direction::NSM},     {0xdcf, 0xdd1, direction::L},
8422
    {0xdd2, 0xdd4, direction::NSM},     {0xdd6, 0xdd6, direction::NSM},
8423
    {0xdd8, 0xddf, direction::L},       {0xde6, 0xdef, direction::L},
8424
    {0xdf2, 0xdf4, direction::L},       {0xe01, 0xe30, direction::L},
8425
    {0xe31, 0xe31, direction::NSM},     {0xe32, 0xe33, direction::L},
8426
    {0xe34, 0xe3a, direction::NSM},     {0xe3f, 0xe3f, direction::ET},
8427
    {0xe40, 0xe46, direction::L},       {0xe47, 0xe4e, direction::NSM},
8428
    {0xe4f, 0xe5b, direction::L},       {0xe81, 0xe82, direction::L},
8429
    {0xe84, 0xe84, direction::L},       {0xe86, 0xe8a, direction::L},
8430
    {0xe8c, 0xea3, direction::L},       {0xea5, 0xea5, direction::L},
8431
    {0xea7, 0xeb0, direction::L},       {0xeb1, 0xeb1, direction::NSM},
8432
    {0xeb2, 0xeb3, direction::L},       {0xeb4, 0xebc, direction::NSM},
8433
    {0xebd, 0xebd, direction::L},       {0xec0, 0xec4, direction::L},
8434
    {0xec6, 0xec6, direction::L},       {0xec8, 0xecd, direction::NSM},
8435
    {0xed0, 0xed9, direction::L},       {0xedc, 0xedf, direction::L},
8436
    {0xf00, 0xf17, direction::L},       {0xf18, 0xf19, direction::NSM},
8437
    {0xf1a, 0xf34, direction::L},       {0xf35, 0xf35, direction::NSM},
8438
    {0xf36, 0xf36, direction::L},       {0xf37, 0xf37, direction::NSM},
8439
    {0xf38, 0xf38, direction::L},       {0xf39, 0xf39, direction::NSM},
8440
    {0xf3a, 0xf3d, direction::ON},      {0xf3e, 0xf47, direction::L},
8441
    {0xf49, 0xf6c, direction::L},       {0xf71, 0xf7e, direction::NSM},
8442
    {0xf7f, 0xf7f, direction::L},       {0xf80, 0xf84, direction::NSM},
8443
    {0xf85, 0xf85, direction::L},       {0xf86, 0xf87, direction::NSM},
8444
    {0xf88, 0xf8c, direction::L},       {0xf8d, 0xf97, direction::NSM},
8445
    {0xf99, 0xfbc, direction::NSM},     {0xfbe, 0xfc5, direction::L},
8446
    {0xfc6, 0xfc6, direction::NSM},     {0xfc7, 0xfcc, direction::L},
8447
    {0xfce, 0xfda, direction::L},       {0x1000, 0x102c, direction::L},
8448
    {0x102d, 0x1030, direction::NSM},   {0x1031, 0x1031, direction::L},
8449
    {0x1032, 0x1037, direction::NSM},   {0x1038, 0x1038, direction::L},
8450
    {0x1039, 0x103a, direction::NSM},   {0x103b, 0x103c, direction::L},
8451
    {0x103d, 0x103e, direction::NSM},   {0x103f, 0x1057, direction::L},
8452
    {0x1058, 0x1059, direction::NSM},   {0x105a, 0x105d, direction::L},
8453
    {0x105e, 0x1060, direction::NSM},   {0x1061, 0x1070, direction::L},
8454
    {0x1071, 0x1074, direction::NSM},   {0x1075, 0x1081, direction::L},
8455
    {0x1082, 0x1082, direction::NSM},   {0x1083, 0x1084, direction::L},
8456
    {0x1085, 0x1086, direction::NSM},   {0x1087, 0x108c, direction::L},
8457
    {0x108d, 0x108d, direction::NSM},   {0x108e, 0x109c, direction::L},
8458
    {0x109d, 0x109d, direction::NSM},   {0x109e, 0x10c5, direction::L},
8459
    {0x10c7, 0x10c7, direction::L},     {0x10cd, 0x10cd, direction::L},
8460
    {0x10d0, 0x1248, direction::L},     {0x124a, 0x124d, direction::L},
8461
    {0x1250, 0x1256, direction::L},     {0x1258, 0x1258, direction::L},
8462
    {0x125a, 0x125d, direction::L},     {0x1260, 0x1288, direction::L},
8463
    {0x128a, 0x128d, direction::L},     {0x1290, 0x12b0, direction::L},
8464
    {0x12b2, 0x12b5, direction::L},     {0x12b8, 0x12be, direction::L},
8465
    {0x12c0, 0x12c0, direction::L},     {0x12c2, 0x12c5, direction::L},
8466
    {0x12c8, 0x12d6, direction::L},     {0x12d8, 0x1310, direction::L},
8467
    {0x1312, 0x1315, direction::L},     {0x1318, 0x135a, direction::L},
8468
    {0x135d, 0x135f, direction::NSM},   {0x1360, 0x137c, direction::L},
8469
    {0x1380, 0x138f, direction::L},     {0x1390, 0x1399, direction::ON},
8470
    {0x13a0, 0x13f5, direction::L},     {0x13f8, 0x13fd, direction::L},
8471
    {0x1400, 0x1400, direction::ON},    {0x1401, 0x167f, direction::L},
8472
    {0x1680, 0x1680, direction::WS},    {0x1681, 0x169a, direction::L},
8473
    {0x169b, 0x169c, direction::ON},    {0x16a0, 0x16f8, direction::L},
8474
    {0x1700, 0x170c, direction::L},     {0x170e, 0x1711, direction::L},
8475
    {0x1712, 0x1714, direction::NSM},   {0x1720, 0x1731, direction::L},
8476
    {0x1732, 0x1734, direction::NSM},   {0x1735, 0x1736, direction::L},
8477
    {0x1740, 0x1751, direction::L},     {0x1752, 0x1753, direction::NSM},
8478
    {0x1760, 0x176c, direction::L},     {0x176e, 0x1770, direction::L},
8479
    {0x1772, 0x1773, direction::NSM},   {0x1780, 0x17b3, direction::L},
8480
    {0x17b4, 0x17b5, direction::NSM},   {0x17b6, 0x17b6, direction::L},
8481
    {0x17b7, 0x17bd, direction::NSM},   {0x17be, 0x17c5, direction::L},
8482
    {0x17c6, 0x17c6, direction::NSM},   {0x17c7, 0x17c8, direction::L},
8483
    {0x17c9, 0x17d3, direction::NSM},   {0x17d4, 0x17da, direction::L},
8484
    {0x17db, 0x17db, direction::ET},    {0x17dc, 0x17dc, direction::L},
8485
    {0x17dd, 0x17dd, direction::NSM},   {0x17e0, 0x17e9, direction::L},
8486
    {0x17f0, 0x17f9, direction::ON},    {0x1800, 0x180a, direction::ON},
8487
    {0x180b, 0x180d, direction::NSM},   {0x180e, 0x180e, direction::BN},
8488
    {0x1810, 0x1819, direction::L},     {0x1820, 0x1878, direction::L},
8489
    {0x1880, 0x1884, direction::L},     {0x1885, 0x1886, direction::NSM},
8490
    {0x1887, 0x18a8, direction::L},     {0x18a9, 0x18a9, direction::NSM},
8491
    {0x18aa, 0x18aa, direction::L},     {0x18b0, 0x18f5, direction::L},
8492
    {0x1900, 0x191e, direction::L},     {0x1920, 0x1922, direction::NSM},
8493
    {0x1923, 0x1926, direction::L},     {0x1927, 0x1928, direction::NSM},
8494
    {0x1929, 0x192b, direction::L},     {0x1930, 0x1931, direction::L},
8495
    {0x1932, 0x1932, direction::NSM},   {0x1933, 0x1938, direction::L},
8496
    {0x1939, 0x193b, direction::NSM},   {0x1940, 0x1940, direction::ON},
8497
    {0x1944, 0x1945, direction::ON},    {0x1946, 0x196d, direction::L},
8498
    {0x1970, 0x1974, direction::L},     {0x1980, 0x19ab, direction::L},
8499
    {0x19b0, 0x19c9, direction::L},     {0x19d0, 0x19da, direction::L},
8500
    {0x19de, 0x19ff, direction::ON},    {0x1a00, 0x1a16, direction::L},
8501
    {0x1a17, 0x1a18, direction::NSM},   {0x1a19, 0x1a1a, direction::L},
8502
    {0x1a1b, 0x1a1b, direction::NSM},   {0x1a1e, 0x1a55, direction::L},
8503
    {0x1a56, 0x1a56, direction::NSM},   {0x1a57, 0x1a57, direction::L},
8504
    {0x1a58, 0x1a5e, direction::NSM},   {0x1a60, 0x1a60, direction::NSM},
8505
    {0x1a61, 0x1a61, direction::L},     {0x1a62, 0x1a62, direction::NSM},
8506
    {0x1a63, 0x1a64, direction::L},     {0x1a65, 0x1a6c, direction::NSM},
8507
    {0x1a6d, 0x1a72, direction::L},     {0x1a73, 0x1a7c, direction::NSM},
8508
    {0x1a7f, 0x1a7f, direction::NSM},   {0x1a80, 0x1a89, direction::L},
8509
    {0x1a90, 0x1a99, direction::L},     {0x1aa0, 0x1aad, direction::L},
8510
    {0x1ab0, 0x1ac0, direction::NSM},   {0x1b00, 0x1b03, direction::NSM},
8511
    {0x1b04, 0x1b33, direction::L},     {0x1b34, 0x1b34, direction::NSM},
8512
    {0x1b35, 0x1b35, direction::L},     {0x1b36, 0x1b3a, direction::NSM},
8513
    {0x1b3b, 0x1b3b, direction::L},     {0x1b3c, 0x1b3c, direction::NSM},
8514
    {0x1b3d, 0x1b41, direction::L},     {0x1b42, 0x1b42, direction::NSM},
8515
    {0x1b43, 0x1b4b, direction::L},     {0x1b50, 0x1b6a, direction::L},
8516
    {0x1b6b, 0x1b73, direction::NSM},   {0x1b74, 0x1b7c, direction::L},
8517
    {0x1b80, 0x1b81, direction::NSM},   {0x1b82, 0x1ba1, direction::L},
8518
    {0x1ba2, 0x1ba5, direction::NSM},   {0x1ba6, 0x1ba7, direction::L},
8519
    {0x1ba8, 0x1ba9, direction::NSM},   {0x1baa, 0x1baa, direction::L},
8520
    {0x1bab, 0x1bad, direction::NSM},   {0x1bae, 0x1be5, direction::L},
8521
    {0x1be6, 0x1be6, direction::NSM},   {0x1be7, 0x1be7, direction::L},
8522
    {0x1be8, 0x1be9, direction::NSM},   {0x1bea, 0x1bec, direction::L},
8523
    {0x1bed, 0x1bed, direction::NSM},   {0x1bee, 0x1bee, direction::L},
8524
    {0x1bef, 0x1bf1, direction::NSM},   {0x1bf2, 0x1bf3, direction::L},
8525
    {0x1bfc, 0x1c2b, direction::L},     {0x1c2c, 0x1c33, direction::NSM},
8526
    {0x1c34, 0x1c35, direction::L},     {0x1c36, 0x1c37, direction::NSM},
8527
    {0x1c3b, 0x1c49, direction::L},     {0x1c4d, 0x1c88, direction::L},
8528
    {0x1c90, 0x1cba, direction::L},     {0x1cbd, 0x1cc7, direction::L},
8529
    {0x1cd0, 0x1cd2, direction::NSM},   {0x1cd3, 0x1cd3, direction::L},
8530
    {0x1cd4, 0x1ce0, direction::NSM},   {0x1ce1, 0x1ce1, direction::L},
8531
    {0x1ce2, 0x1ce8, direction::NSM},   {0x1ce9, 0x1cec, direction::L},
8532
    {0x1ced, 0x1ced, direction::NSM},   {0x1cee, 0x1cf3, direction::L},
8533
    {0x1cf4, 0x1cf4, direction::NSM},   {0x1cf5, 0x1cf7, direction::L},
8534
    {0x1cf8, 0x1cf9, direction::NSM},   {0x1cfa, 0x1cfa, direction::L},
8535
    {0x1d00, 0x1dbf, direction::L},     {0x1dc0, 0x1df9, direction::NSM},
8536
    {0x1dfb, 0x1dff, direction::NSM},   {0x1e00, 0x1f15, direction::L},
8537
    {0x1f18, 0x1f1d, direction::L},     {0x1f20, 0x1f45, direction::L},
8538
    {0x1f48, 0x1f4d, direction::L},     {0x1f50, 0x1f57, direction::L},
8539
    {0x1f59, 0x1f59, direction::L},     {0x1f5b, 0x1f5b, direction::L},
8540
    {0x1f5d, 0x1f5d, direction::L},     {0x1f5f, 0x1f7d, direction::L},
8541
    {0x1f80, 0x1fb4, direction::L},     {0x1fb6, 0x1fbc, direction::L},
8542
    {0x1fbd, 0x1fbd, direction::ON},    {0x1fbe, 0x1fbe, direction::L},
8543
    {0x1fbf, 0x1fc1, direction::ON},    {0x1fc2, 0x1fc4, direction::L},
8544
    {0x1fc6, 0x1fcc, direction::L},     {0x1fcd, 0x1fcf, direction::ON},
8545
    {0x1fd0, 0x1fd3, direction::L},     {0x1fd6, 0x1fdb, direction::L},
8546
    {0x1fdd, 0x1fdf, direction::ON},    {0x1fe0, 0x1fec, direction::L},
8547
    {0x1fed, 0x1fef, direction::ON},    {0x1ff2, 0x1ff4, direction::L},
8548
    {0x1ff6, 0x1ffc, direction::L},     {0x1ffd, 0x1ffe, direction::ON},
8549
    {0x2000, 0x200a, direction::WS},    {0x200b, 0x200d, direction::BN},
8550
    {0x200e, 0x200e, direction::L},     {0x200f, 0x200f, direction::R},
8551
    {0x2010, 0x2027, direction::ON},    {0x2028, 0x2028, direction::WS},
8552
    {0x2029, 0x2029, direction::B},     {0x202a, 0x202a, direction::LRE},
8553
    {0x202b, 0x202b, direction::RLE},   {0x202c, 0x202c, direction::PDF},
8554
    {0x202d, 0x202d, direction::LRO},   {0x202e, 0x202e, direction::RLO},
8555
    {0x202f, 0x202f, direction::CS},    {0x2030, 0x2034, direction::ET},
8556
    {0x2035, 0x2043, direction::ON},    {0x2044, 0x2044, direction::CS},
8557
    {0x2045, 0x205e, direction::ON},    {0x205f, 0x205f, direction::WS},
8558
    {0x2060, 0x2064, direction::BN},    {0x2066, 0x2066, direction::LRI},
8559
    {0x2067, 0x2067, direction::RLI},   {0x2068, 0x2068, direction::FSI},
8560
    {0x2069, 0x2069, direction::PDI},   {0x206a, 0x206f, direction::BN},
8561
    {0x2070, 0x2070, direction::EN},    {0x2071, 0x2071, direction::L},
8562
    {0x2074, 0x2079, direction::EN},    {0x207a, 0x207b, direction::ES},
8563
    {0x207c, 0x207e, direction::ON},    {0x207f, 0x207f, direction::L},
8564
    {0x2080, 0x2089, direction::EN},    {0x208a, 0x208b, direction::ES},
8565
    {0x208c, 0x208e, direction::ON},    {0x2090, 0x209c, direction::L},
8566
    {0x20a0, 0x20bf, direction::ET},    {0x20d0, 0x20f0, direction::NSM},
8567
    {0x2100, 0x2101, direction::ON},    {0x2102, 0x2102, direction::L},
8568
    {0x2103, 0x2106, direction::ON},    {0x2107, 0x2107, direction::L},
8569
    {0x2108, 0x2109, direction::ON},    {0x210a, 0x2113, direction::L},
8570
    {0x2114, 0x2114, direction::ON},    {0x2115, 0x2115, direction::L},
8571
    {0x2116, 0x2118, direction::ON},    {0x2119, 0x211d, direction::L},
8572
    {0x211e, 0x2123, direction::ON},    {0x2124, 0x2124, direction::L},
8573
    {0x2125, 0x2125, direction::ON},    {0x2126, 0x2126, direction::L},
8574
    {0x2127, 0x2127, direction::ON},    {0x2128, 0x2128, direction::L},
8575
    {0x2129, 0x2129, direction::ON},    {0x212a, 0x212d, direction::L},
8576
    {0x212e, 0x212e, direction::ET},    {0x212f, 0x2139, direction::L},
8577
    {0x213a, 0x213b, direction::ON},    {0x213c, 0x213f, direction::L},
8578
    {0x2140, 0x2144, direction::ON},    {0x2145, 0x2149, direction::L},
8579
    {0x214a, 0x214d, direction::ON},    {0x214e, 0x214f, direction::L},
8580
    {0x2150, 0x215f, direction::ON},    {0x2160, 0x2188, direction::L},
8581
    {0x2189, 0x218b, direction::ON},    {0x2190, 0x2211, direction::ON},
8582
    {0x2212, 0x2212, direction::ES},    {0x2213, 0x2213, direction::ET},
8583
    {0x2214, 0x2335, direction::ON},    {0x2336, 0x237a, direction::L},
8584
    {0x237b, 0x2394, direction::ON},    {0x2395, 0x2395, direction::L},
8585
    {0x2396, 0x2426, direction::ON},    {0x2440, 0x244a, direction::ON},
8586
    {0x2460, 0x2487, direction::ON},    {0x2488, 0x249b, direction::EN},
8587
    {0x249c, 0x24e9, direction::L},     {0x24ea, 0x26ab, direction::ON},
8588
    {0x26ac, 0x26ac, direction::L},     {0x26ad, 0x27ff, direction::ON},
8589
    {0x2800, 0x28ff, direction::L},     {0x2900, 0x2b73, direction::ON},
8590
    {0x2b76, 0x2b95, direction::ON},    {0x2b97, 0x2bff, direction::ON},
8591
    {0x2c00, 0x2c2e, direction::L},     {0x2c30, 0x2c5e, direction::L},
8592
    {0x2c60, 0x2ce4, direction::L},     {0x2ce5, 0x2cea, direction::ON},
8593
    {0x2ceb, 0x2cee, direction::L},     {0x2cef, 0x2cf1, direction::NSM},
8594
    {0x2cf2, 0x2cf3, direction::L},     {0x2cf9, 0x2cff, direction::ON},
8595
    {0x2d00, 0x2d25, direction::L},     {0x2d27, 0x2d27, direction::L},
8596
    {0x2d2d, 0x2d2d, direction::L},     {0x2d30, 0x2d67, direction::L},
8597
    {0x2d6f, 0x2d70, direction::L},     {0x2d7f, 0x2d7f, direction::NSM},
8598
    {0x2d80, 0x2d96, direction::L},     {0x2da0, 0x2da6, direction::L},
8599
    {0x2da8, 0x2dae, direction::L},     {0x2db0, 0x2db6, direction::L},
8600
    {0x2db8, 0x2dbe, direction::L},     {0x2dc0, 0x2dc6, direction::L},
8601
    {0x2dc8, 0x2dce, direction::L},     {0x2dd0, 0x2dd6, direction::L},
8602
    {0x2dd8, 0x2dde, direction::L},     {0x2de0, 0x2dff, direction::NSM},
8603
    {0x2e00, 0x2e52, direction::ON},    {0x2e80, 0x2e99, direction::ON},
8604
    {0x2e9b, 0x2ef3, direction::ON},    {0x2f00, 0x2fd5, direction::ON},
8605
    {0x2ff0, 0x2ffb, direction::ON},    {0x3000, 0x3000, direction::WS},
8606
    {0x3001, 0x3004, direction::ON},    {0x3005, 0x3007, direction::L},
8607
    {0x3008, 0x3020, direction::ON},    {0x3021, 0x3029, direction::L},
8608
    {0x302a, 0x302d, direction::NSM},   {0x302e, 0x302f, direction::L},
8609
    {0x3030, 0x3030, direction::ON},    {0x3031, 0x3035, direction::L},
8610
    {0x3036, 0x3037, direction::ON},    {0x3038, 0x303c, direction::L},
8611
    {0x303d, 0x303f, direction::ON},    {0x3041, 0x3096, direction::L},
8612
    {0x3099, 0x309a, direction::NSM},   {0x309b, 0x309c, direction::ON},
8613
    {0x309d, 0x309f, direction::L},     {0x30a0, 0x30a0, direction::ON},
8614
    {0x30a1, 0x30fa, direction::L},     {0x30fb, 0x30fb, direction::ON},
8615
    {0x30fc, 0x30ff, direction::L},     {0x3105, 0x312f, direction::L},
8616
    {0x3131, 0x318e, direction::L},     {0x3190, 0x31bf, direction::L},
8617
    {0x31c0, 0x31e3, direction::ON},    {0x31f0, 0x321c, direction::L},
8618
    {0x321d, 0x321e, direction::ON},    {0x3220, 0x324f, direction::L},
8619
    {0x3250, 0x325f, direction::ON},    {0x3260, 0x327b, direction::L},
8620
    {0x327c, 0x327e, direction::ON},    {0x327f, 0x32b0, direction::L},
8621
    {0x32b1, 0x32bf, direction::ON},    {0x32c0, 0x32cb, direction::L},
8622
    {0x32cc, 0x32cf, direction::ON},    {0x32d0, 0x3376, direction::L},
8623
    {0x3377, 0x337a, direction::ON},    {0x337b, 0x33dd, direction::L},
8624
    {0x33de, 0x33df, direction::ON},    {0x33e0, 0x33fe, direction::L},
8625
    {0x33ff, 0x33ff, direction::ON},    {0x3400, 0x4dbf, direction::L},
8626
    {0x4dc0, 0x4dff, direction::ON},    {0x4e00, 0x9ffc, direction::L},
8627
    {0xa000, 0xa48c, direction::L},     {0xa490, 0xa4c6, direction::ON},
8628
    {0xa4d0, 0xa60c, direction::L},     {0xa60d, 0xa60f, direction::ON},
8629
    {0xa610, 0xa62b, direction::L},     {0xa640, 0xa66e, direction::L},
8630
    {0xa66f, 0xa672, direction::NSM},   {0xa673, 0xa673, direction::ON},
8631
    {0xa674, 0xa67d, direction::NSM},   {0xa67e, 0xa67f, direction::ON},
8632
    {0xa680, 0xa69d, direction::L},     {0xa69e, 0xa69f, direction::NSM},
8633
    {0xa6a0, 0xa6ef, direction::L},     {0xa6f0, 0xa6f1, direction::NSM},
8634
    {0xa6f2, 0xa6f7, direction::L},     {0xa700, 0xa721, direction::ON},
8635
    {0xa722, 0xa787, direction::L},     {0xa788, 0xa788, direction::ON},
8636
    {0xa789, 0xa7bf, direction::L},     {0xa7c2, 0xa7ca, direction::L},
8637
    {0xa7f5, 0xa801, direction::L},     {0xa802, 0xa802, direction::NSM},
8638
    {0xa803, 0xa805, direction::L},     {0xa806, 0xa806, direction::NSM},
8639
    {0xa807, 0xa80a, direction::L},     {0xa80b, 0xa80b, direction::NSM},
8640
    {0xa80c, 0xa824, direction::L},     {0xa825, 0xa826, direction::NSM},
8641
    {0xa827, 0xa827, direction::L},     {0xa828, 0xa82b, direction::ON},
8642
    {0xa82c, 0xa82c, direction::NSM},   {0xa830, 0xa837, direction::L},
8643
    {0xa838, 0xa839, direction::ET},    {0xa840, 0xa873, direction::L},
8644
    {0xa874, 0xa877, direction::ON},    {0xa880, 0xa8c3, direction::L},
8645
    {0xa8c4, 0xa8c5, direction::NSM},   {0xa8ce, 0xa8d9, direction::L},
8646
    {0xa8e0, 0xa8f1, direction::NSM},   {0xa8f2, 0xa8fe, direction::L},
8647
    {0xa8ff, 0xa8ff, direction::NSM},   {0xa900, 0xa925, direction::L},
8648
    {0xa926, 0xa92d, direction::NSM},   {0xa92e, 0xa946, direction::L},
8649
    {0xa947, 0xa951, direction::NSM},   {0xa952, 0xa953, direction::L},
8650
    {0xa95f, 0xa97c, direction::L},     {0xa980, 0xa982, direction::NSM},
8651
    {0xa983, 0xa9b2, direction::L},     {0xa9b3, 0xa9b3, direction::NSM},
8652
    {0xa9b4, 0xa9b5, direction::L},     {0xa9b6, 0xa9b9, direction::NSM},
8653
    {0xa9ba, 0xa9bb, direction::L},     {0xa9bc, 0xa9bd, direction::NSM},
8654
    {0xa9be, 0xa9cd, direction::L},     {0xa9cf, 0xa9d9, direction::L},
8655
    {0xa9de, 0xa9e4, direction::L},     {0xa9e5, 0xa9e5, direction::NSM},
8656
    {0xa9e6, 0xa9fe, direction::L},     {0xaa00, 0xaa28, direction::L},
8657
    {0xaa29, 0xaa2e, direction::NSM},   {0xaa2f, 0xaa30, direction::L},
8658
    {0xaa31, 0xaa32, direction::NSM},   {0xaa33, 0xaa34, direction::L},
8659
    {0xaa35, 0xaa36, direction::NSM},   {0xaa40, 0xaa42, direction::L},
8660
    {0xaa43, 0xaa43, direction::NSM},   {0xaa44, 0xaa4b, direction::L},
8661
    {0xaa4c, 0xaa4c, direction::NSM},   {0xaa4d, 0xaa4d, direction::L},
8662
    {0xaa50, 0xaa59, direction::L},     {0xaa5c, 0xaa7b, direction::L},
8663
    {0xaa7c, 0xaa7c, direction::NSM},   {0xaa7d, 0xaaaf, direction::L},
8664
    {0xaab0, 0xaab0, direction::NSM},   {0xaab1, 0xaab1, direction::L},
8665
    {0xaab2, 0xaab4, direction::NSM},   {0xaab5, 0xaab6, direction::L},
8666
    {0xaab7, 0xaab8, direction::NSM},   {0xaab9, 0xaabd, direction::L},
8667
    {0xaabe, 0xaabf, direction::NSM},   {0xaac0, 0xaac0, direction::L},
8668
    {0xaac1, 0xaac1, direction::NSM},   {0xaac2, 0xaac2, direction::L},
8669
    {0xaadb, 0xaaeb, direction::L},     {0xaaec, 0xaaed, direction::NSM},
8670
    {0xaaee, 0xaaf5, direction::L},     {0xaaf6, 0xaaf6, direction::NSM},
8671
    {0xab01, 0xab06, direction::L},     {0xab09, 0xab0e, direction::L},
8672
    {0xab11, 0xab16, direction::L},     {0xab20, 0xab26, direction::L},
8673
    {0xab28, 0xab2e, direction::L},     {0xab30, 0xab69, direction::L},
8674
    {0xab6a, 0xab6b, direction::ON},    {0xab70, 0xabe4, direction::L},
8675
    {0xabe5, 0xabe5, direction::NSM},   {0xabe6, 0xabe7, direction::L},
8676
    {0xabe8, 0xabe8, direction::NSM},   {0xabe9, 0xabec, direction::L},
8677
    {0xabed, 0xabed, direction::NSM},   {0xabf0, 0xabf9, direction::L},
8678
    {0xac00, 0xd7a3, direction::L},     {0xd7b0, 0xd7c6, direction::L},
8679
    {0xd7cb, 0xd7fb, direction::L},     {0xd800, 0xfa6d, direction::L},
8680
    {0xfa70, 0xfad9, direction::L},     {0xfb00, 0xfb06, direction::L},
8681
    {0xfb13, 0xfb17, direction::L},     {0xfb1d, 0xfb1d, direction::R},
8682
    {0xfb1e, 0xfb1e, direction::NSM},   {0xfb1f, 0xfb28, direction::R},
8683
    {0xfb29, 0xfb29, direction::ES},    {0xfb2a, 0xfb36, direction::R},
8684
    {0xfb38, 0xfb3c, direction::R},     {0xfb3e, 0xfb3e, direction::R},
8685
    {0xfb40, 0xfb41, direction::R},     {0xfb43, 0xfb44, direction::R},
8686
    {0xfb46, 0xfb4f, direction::R},     {0xfb50, 0xfbc1, direction::AL},
8687
    {0xfbd3, 0xfd3d, direction::AL},    {0xfd3e, 0xfd3f, direction::ON},
8688
    {0xfd50, 0xfd8f, direction::AL},    {0xfd92, 0xfdc7, direction::AL},
8689
    {0xfdf0, 0xfdfc, direction::AL},    {0xfdfd, 0xfdfd, direction::ON},
8690
    {0xfe00, 0xfe0f, direction::NSM},   {0xfe10, 0xfe19, direction::ON},
8691
    {0xfe20, 0xfe2f, direction::NSM},   {0xfe30, 0xfe4f, direction::ON},
8692
    {0xfe50, 0xfe50, direction::CS},    {0xfe51, 0xfe51, direction::ON},
8693
    {0xfe52, 0xfe52, direction::CS},    {0xfe54, 0xfe54, direction::ON},
8694
    {0xfe55, 0xfe55, direction::CS},    {0xfe56, 0xfe5e, direction::ON},
8695
    {0xfe5f, 0xfe5f, direction::ET},    {0xfe60, 0xfe61, direction::ON},
8696
    {0xfe62, 0xfe63, direction::ES},    {0xfe64, 0xfe66, direction::ON},
8697
    {0xfe68, 0xfe68, direction::ON},    {0xfe69, 0xfe6a, direction::ET},
8698
    {0xfe6b, 0xfe6b, direction::ON},    {0xfe70, 0xfe74, direction::AL},
8699
    {0xfe76, 0xfefc, direction::AL},    {0xfeff, 0xfeff, direction::BN},
8700
    {0xff01, 0xff02, direction::ON},    {0xff03, 0xff05, direction::ET},
8701
    {0xff06, 0xff0a, direction::ON},    {0xff0b, 0xff0b, direction::ES},
8702
    {0xff0c, 0xff0c, direction::CS},    {0xff0d, 0xff0d, direction::ES},
8703
    {0xff0e, 0xff0f, direction::CS},    {0xff10, 0xff19, direction::EN},
8704
    {0xff1a, 0xff1a, direction::CS},    {0xff1b, 0xff20, direction::ON},
8705
    {0xff21, 0xff3a, direction::L},     {0xff3b, 0xff40, direction::ON},
8706
    {0xff41, 0xff5a, direction::L},     {0xff5b, 0xff65, direction::ON},
8707
    {0xff66, 0xffbe, direction::L},     {0xffc2, 0xffc7, direction::L},
8708
    {0xffca, 0xffcf, direction::L},     {0xffd2, 0xffd7, direction::L},
8709
    {0xffda, 0xffdc, direction::L},     {0xffe0, 0xffe1, direction::ET},
8710
    {0xffe2, 0xffe4, direction::ON},    {0xffe5, 0xffe6, direction::ET},
8711
    {0xffe8, 0xffee, direction::ON},    {0xfff9, 0xfffd, direction::ON},
8712
    {0x10000, 0x1000b, direction::L},   {0x1000d, 0x10026, direction::L},
8713
    {0x10028, 0x1003a, direction::L},   {0x1003c, 0x1003d, direction::L},
8714
    {0x1003f, 0x1004d, direction::L},   {0x10050, 0x1005d, direction::L},
8715
    {0x10080, 0x100fa, direction::L},   {0x10100, 0x10100, direction::L},
8716
    {0x10101, 0x10101, direction::ON},  {0x10102, 0x10102, direction::L},
8717
    {0x10107, 0x10133, direction::L},   {0x10137, 0x1013f, direction::L},
8718
    {0x10140, 0x1018c, direction::ON},  {0x1018d, 0x1018e, direction::L},
8719
    {0x10190, 0x1019c, direction::ON},  {0x101a0, 0x101a0, direction::ON},
8720
    {0x101d0, 0x101fc, direction::L},   {0x101fd, 0x101fd, direction::NSM},
8721
    {0x10280, 0x1029c, direction::L},   {0x102a0, 0x102d0, direction::L},
8722
    {0x102e0, 0x102e0, direction::NSM}, {0x102e1, 0x102fb, direction::EN},
8723
    {0x10300, 0x10323, direction::L},   {0x1032d, 0x1034a, direction::L},
8724
    {0x10350, 0x10375, direction::L},   {0x10376, 0x1037a, direction::NSM},
8725
    {0x10380, 0x1039d, direction::L},   {0x1039f, 0x103c3, direction::L},
8726
    {0x103c8, 0x103d5, direction::L},   {0x10400, 0x1049d, direction::L},
8727
    {0x104a0, 0x104a9, direction::L},   {0x104b0, 0x104d3, direction::L},
8728
    {0x104d8, 0x104fb, direction::L},   {0x10500, 0x10527, direction::L},
8729
    {0x10530, 0x10563, direction::L},   {0x1056f, 0x1056f, direction::L},
8730
    {0x10600, 0x10736, direction::L},   {0x10740, 0x10755, direction::L},
8731
    {0x10760, 0x10767, direction::L},   {0x10800, 0x10805, direction::R},
8732
    {0x10808, 0x10808, direction::R},   {0x1080a, 0x10835, direction::R},
8733
    {0x10837, 0x10838, direction::R},   {0x1083c, 0x1083c, direction::R},
8734
    {0x1083f, 0x10855, direction::R},   {0x10857, 0x1089e, direction::R},
8735
    {0x108a7, 0x108af, direction::R},   {0x108e0, 0x108f2, direction::R},
8736
    {0x108f4, 0x108f5, direction::R},   {0x108fb, 0x1091b, direction::R},
8737
    {0x1091f, 0x1091f, direction::ON},  {0x10920, 0x10939, direction::R},
8738
    {0x1093f, 0x1093f, direction::R},   {0x10980, 0x109b7, direction::R},
8739
    {0x109bc, 0x109cf, direction::R},   {0x109d2, 0x10a00, direction::R},
8740
    {0x10a01, 0x10a03, direction::NSM}, {0x10a05, 0x10a06, direction::NSM},
8741
    {0x10a0c, 0x10a0f, direction::NSM}, {0x10a10, 0x10a13, direction::R},
8742
    {0x10a15, 0x10a17, direction::R},   {0x10a19, 0x10a35, direction::R},
8743
    {0x10a38, 0x10a3a, direction::NSM}, {0x10a3f, 0x10a3f, direction::NSM},
8744
    {0x10a40, 0x10a48, direction::R},   {0x10a50, 0x10a58, direction::R},
8745
    {0x10a60, 0x10a9f, direction::R},   {0x10ac0, 0x10ae4, direction::R},
8746
    {0x10ae5, 0x10ae6, direction::NSM}, {0x10aeb, 0x10af6, direction::R},
8747
    {0x10b00, 0x10b35, direction::R},   {0x10b39, 0x10b3f, direction::ON},
8748
    {0x10b40, 0x10b55, direction::R},   {0x10b58, 0x10b72, direction::R},
8749
    {0x10b78, 0x10b91, direction::R},   {0x10b99, 0x10b9c, direction::R},
8750
    {0x10ba9, 0x10baf, direction::R},   {0x10c00, 0x10c48, direction::R},
8751
    {0x10c80, 0x10cb2, direction::R},   {0x10cc0, 0x10cf2, direction::R},
8752
    {0x10cfa, 0x10cff, direction::R},   {0x10d00, 0x10d23, direction::AL},
8753
    {0x10d24, 0x10d27, direction::NSM}, {0x10d30, 0x10d39, direction::AN},
8754
    {0x10e60, 0x10e7e, direction::AN},  {0x10e80, 0x10ea9, direction::R},
8755
    {0x10eab, 0x10eac, direction::NSM}, {0x10ead, 0x10ead, direction::R},
8756
    {0x10eb0, 0x10eb1, direction::R},   {0x10f00, 0x10f27, direction::R},
8757
    {0x10f30, 0x10f45, direction::AL},  {0x10f46, 0x10f50, direction::NSM},
8758
    {0x10f51, 0x10f59, direction::AL},  {0x10fb0, 0x10fcb, direction::R},
8759
    {0x10fe0, 0x10ff6, direction::R},   {0x11000, 0x11000, direction::L},
8760
    {0x11001, 0x11001, direction::NSM}, {0x11002, 0x11037, direction::L},
8761
    {0x11038, 0x11046, direction::NSM}, {0x11047, 0x1104d, direction::L},
8762
    {0x11052, 0x11065, direction::ON},  {0x11066, 0x1106f, direction::L},
8763
    {0x1107f, 0x11081, direction::NSM}, {0x11082, 0x110b2, direction::L},
8764
    {0x110b3, 0x110b6, direction::NSM}, {0x110b7, 0x110b8, direction::L},
8765
    {0x110b9, 0x110ba, direction::NSM}, {0x110bb, 0x110c1, direction::L},
8766
    {0x110cd, 0x110cd, direction::L},   {0x110d0, 0x110e8, direction::L},
8767
    {0x110f0, 0x110f9, direction::L},   {0x11100, 0x11102, direction::NSM},
8768
    {0x11103, 0x11126, direction::L},   {0x11127, 0x1112b, direction::NSM},
8769
    {0x1112c, 0x1112c, direction::L},   {0x1112d, 0x11134, direction::NSM},
8770
    {0x11136, 0x11147, direction::L},   {0x11150, 0x11172, direction::L},
8771
    {0x11173, 0x11173, direction::NSM}, {0x11174, 0x11176, direction::L},
8772
    {0x11180, 0x11181, direction::NSM}, {0x11182, 0x111b5, direction::L},
8773
    {0x111b6, 0x111be, direction::NSM}, {0x111bf, 0x111c8, direction::L},
8774
    {0x111c9, 0x111cc, direction::NSM}, {0x111cd, 0x111ce, direction::L},
8775
    {0x111cf, 0x111cf, direction::NSM}, {0x111d0, 0x111df, direction::L},
8776
    {0x111e1, 0x111f4, direction::L},   {0x11200, 0x11211, direction::L},
8777
    {0x11213, 0x1122e, direction::L},   {0x1122f, 0x11231, direction::NSM},
8778
    {0x11232, 0x11233, direction::L},   {0x11234, 0x11234, direction::NSM},
8779
    {0x11235, 0x11235, direction::L},   {0x11236, 0x11237, direction::NSM},
8780
    {0x11238, 0x1123d, direction::L},   {0x1123e, 0x1123e, direction::NSM},
8781
    {0x11280, 0x11286, direction::L},   {0x11288, 0x11288, direction::L},
8782
    {0x1128a, 0x1128d, direction::L},   {0x1128f, 0x1129d, direction::L},
8783
    {0x1129f, 0x112a9, direction::L},   {0x112b0, 0x112de, direction::L},
8784
    {0x112df, 0x112df, direction::NSM}, {0x112e0, 0x112e2, direction::L},
8785
    {0x112e3, 0x112ea, direction::NSM}, {0x112f0, 0x112f9, direction::L},
8786
    {0x11300, 0x11301, direction::NSM}, {0x11302, 0x11303, direction::L},
8787
    {0x11305, 0x1130c, direction::L},   {0x1130f, 0x11310, direction::L},
8788
    {0x11313, 0x11328, direction::L},   {0x1132a, 0x11330, direction::L},
8789
    {0x11332, 0x11333, direction::L},   {0x11335, 0x11339, direction::L},
8790
    {0x1133b, 0x1133c, direction::NSM}, {0x1133d, 0x1133f, direction::L},
8791
    {0x11340, 0x11340, direction::NSM}, {0x11341, 0x11344, direction::L},
8792
    {0x11347, 0x11348, direction::L},   {0x1134b, 0x1134d, direction::L},
8793
    {0x11350, 0x11350, direction::L},   {0x11357, 0x11357, direction::L},
8794
    {0x1135d, 0x11363, direction::L},   {0x11366, 0x1136c, direction::NSM},
8795
    {0x11370, 0x11374, direction::NSM}, {0x11400, 0x11437, direction::L},
8796
    {0x11438, 0x1143f, direction::NSM}, {0x11440, 0x11441, direction::L},
8797
    {0x11442, 0x11444, direction::NSM}, {0x11445, 0x11445, direction::L},
8798
    {0x11446, 0x11446, direction::NSM}, {0x11447, 0x1145b, direction::L},
8799
    {0x1145d, 0x1145d, direction::L},   {0x1145e, 0x1145e, direction::NSM},
8800
    {0x1145f, 0x11461, direction::L},   {0x11480, 0x114b2, direction::L},
8801
    {0x114b3, 0x114b8, direction::NSM}, {0x114b9, 0x114b9, direction::L},
8802
    {0x114ba, 0x114ba, direction::NSM}, {0x114bb, 0x114be, direction::L},
8803
    {0x114bf, 0x114c0, direction::NSM}, {0x114c1, 0x114c1, direction::L},
8804
    {0x114c2, 0x114c3, direction::NSM}, {0x114c4, 0x114c7, direction::L},
8805
    {0x114d0, 0x114d9, direction::L},   {0x11580, 0x115b1, direction::L},
8806
    {0x115b2, 0x115b5, direction::NSM}, {0x115b8, 0x115bb, direction::L},
8807
    {0x115bc, 0x115bd, direction::NSM}, {0x115be, 0x115be, direction::L},
8808
    {0x115bf, 0x115c0, direction::NSM}, {0x115c1, 0x115db, direction::L},
8809
    {0x115dc, 0x115dd, direction::NSM}, {0x11600, 0x11632, direction::L},
8810
    {0x11633, 0x1163a, direction::NSM}, {0x1163b, 0x1163c, direction::L},
8811
    {0x1163d, 0x1163d, direction::NSM}, {0x1163e, 0x1163e, direction::L},
8812
    {0x1163f, 0x11640, direction::NSM}, {0x11641, 0x11644, direction::L},
8813
    {0x11650, 0x11659, direction::L},   {0x11660, 0x1166c, direction::ON},
8814
    {0x11680, 0x116aa, direction::L},   {0x116ab, 0x116ab, direction::NSM},
8815
    {0x116ac, 0x116ac, direction::L},   {0x116ad, 0x116ad, direction::NSM},
8816
    {0x116ae, 0x116af, direction::L},   {0x116b0, 0x116b5, direction::NSM},
8817
    {0x116b6, 0x116b6, direction::L},   {0x116b7, 0x116b7, direction::NSM},
8818
    {0x116b8, 0x116b8, direction::L},   {0x116c0, 0x116c9, direction::L},
8819
    {0x11700, 0x1171a, direction::L},   {0x1171d, 0x1171f, direction::NSM},
8820
    {0x11720, 0x11721, direction::L},   {0x11722, 0x11725, direction::NSM},
8821
    {0x11726, 0x11726, direction::L},   {0x11727, 0x1172b, direction::NSM},
8822
    {0x11730, 0x1173f, direction::L},   {0x11800, 0x1182e, direction::L},
8823
    {0x1182f, 0x11837, direction::NSM}, {0x11838, 0x11838, direction::L},
8824
    {0x11839, 0x1183a, direction::NSM}, {0x1183b, 0x1183b, direction::L},
8825
    {0x118a0, 0x118f2, direction::L},   {0x118ff, 0x11906, direction::L},
8826
    {0x11909, 0x11909, direction::L},   {0x1190c, 0x11913, direction::L},
8827
    {0x11915, 0x11916, direction::L},   {0x11918, 0x11935, direction::L},
8828
    {0x11937, 0x11938, direction::L},   {0x1193b, 0x1193c, direction::NSM},
8829
    {0x1193d, 0x1193d, direction::L},   {0x1193e, 0x1193e, direction::NSM},
8830
    {0x1193f, 0x11942, direction::L},   {0x11943, 0x11943, direction::NSM},
8831
    {0x11944, 0x11946, direction::L},   {0x11950, 0x11959, direction::L},
8832
    {0x119a0, 0x119a7, direction::L},   {0x119aa, 0x119d3, direction::L},
8833
    {0x119d4, 0x119d7, direction::NSM}, {0x119da, 0x119db, direction::NSM},
8834
    {0x119dc, 0x119df, direction::L},   {0x119e0, 0x119e0, direction::NSM},
8835
    {0x119e1, 0x119e4, direction::L},   {0x11a00, 0x11a00, direction::L},
8836
    {0x11a01, 0x11a06, direction::NSM}, {0x11a07, 0x11a08, direction::L},
8837
    {0x11a09, 0x11a0a, direction::NSM}, {0x11a0b, 0x11a32, direction::L},
8838
    {0x11a33, 0x11a38, direction::NSM}, {0x11a39, 0x11a3a, direction::L},
8839
    {0x11a3b, 0x11a3e, direction::NSM}, {0x11a3f, 0x11a46, direction::L},
8840
    {0x11a47, 0x11a47, direction::NSM}, {0x11a50, 0x11a50, direction::L},
8841
    {0x11a51, 0x11a56, direction::NSM}, {0x11a57, 0x11a58, direction::L},
8842
    {0x11a59, 0x11a5b, direction::NSM}, {0x11a5c, 0x11a89, direction::L},
8843
    {0x11a8a, 0x11a96, direction::NSM}, {0x11a97, 0x11a97, direction::L},
8844
    {0x11a98, 0x11a99, direction::NSM}, {0x11a9a, 0x11aa2, direction::L},
8845
    {0x11ac0, 0x11af8, direction::L},   {0x11c00, 0x11c08, direction::L},
8846
    {0x11c0a, 0x11c2f, direction::L},   {0x11c30, 0x11c36, direction::NSM},
8847
    {0x11c38, 0x11c3d, direction::NSM}, {0x11c3e, 0x11c45, direction::L},
8848
    {0x11c50, 0x11c6c, direction::L},   {0x11c70, 0x11c8f, direction::L},
8849
    {0x11c92, 0x11ca7, direction::NSM}, {0x11ca9, 0x11ca9, direction::L},
8850
    {0x11caa, 0x11cb0, direction::NSM}, {0x11cb1, 0x11cb1, direction::L},
8851
    {0x11cb2, 0x11cb3, direction::NSM}, {0x11cb4, 0x11cb4, direction::L},
8852
    {0x11cb5, 0x11cb6, direction::NSM}, {0x11d00, 0x11d06, direction::L},
8853
    {0x11d08, 0x11d09, direction::L},   {0x11d0b, 0x11d30, direction::L},
8854
    {0x11d31, 0x11d36, direction::NSM}, {0x11d3a, 0x11d3a, direction::NSM},
8855
    {0x11d3c, 0x11d3d, direction::NSM}, {0x11d3f, 0x11d45, direction::NSM},
8856
    {0x11d46, 0x11d46, direction::L},   {0x11d47, 0x11d47, direction::NSM},
8857
    {0x11d50, 0x11d59, direction::L},   {0x11d60, 0x11d65, direction::L},
8858
    {0x11d67, 0x11d68, direction::L},   {0x11d6a, 0x11d8e, direction::L},
8859
    {0x11d90, 0x11d91, direction::NSM}, {0x11d93, 0x11d94, direction::L},
8860
    {0x11d95, 0x11d95, direction::NSM}, {0x11d96, 0x11d96, direction::L},
8861
    {0x11d97, 0x11d97, direction::NSM}, {0x11d98, 0x11d98, direction::L},
8862
    {0x11da0, 0x11da9, direction::L},   {0x11ee0, 0x11ef2, direction::L},
8863
    {0x11ef3, 0x11ef4, direction::NSM}, {0x11ef5, 0x11ef8, direction::L},
8864
    {0x11fb0, 0x11fb0, direction::L},   {0x11fc0, 0x11fd4, direction::L},
8865
    {0x11fd5, 0x11fdc, direction::ON},  {0x11fdd, 0x11fe0, direction::ET},
8866
    {0x11fe1, 0x11ff1, direction::ON},  {0x11fff, 0x12399, direction::L},
8867
    {0x12400, 0x1246e, direction::L},   {0x12470, 0x12474, direction::L},
8868
    {0x12480, 0x12543, direction::L},   {0x13000, 0x1342e, direction::L},
8869
    {0x13430, 0x13438, direction::L},   {0x14400, 0x14646, direction::L},
8870
    {0x16800, 0x16a38, direction::L},   {0x16a40, 0x16a5e, direction::L},
8871
    {0x16a60, 0x16a69, direction::L},   {0x16a6e, 0x16a6f, direction::L},
8872
    {0x16ad0, 0x16aed, direction::L},   {0x16af0, 0x16af4, direction::NSM},
8873
    {0x16af5, 0x16af5, direction::L},   {0x16b00, 0x16b2f, direction::L},
8874
    {0x16b30, 0x16b36, direction::NSM}, {0x16b37, 0x16b45, direction::L},
8875
    {0x16b50, 0x16b59, direction::L},   {0x16b5b, 0x16b61, direction::L},
8876
    {0x16b63, 0x16b77, direction::L},   {0x16b7d, 0x16b8f, direction::L},
8877
    {0x16e40, 0x16e9a, direction::L},   {0x16f00, 0x16f4a, direction::L},
8878
    {0x16f4f, 0x16f4f, direction::NSM}, {0x16f50, 0x16f87, direction::L},
8879
    {0x16f8f, 0x16f92, direction::NSM}, {0x16f93, 0x16f9f, direction::L},
8880
    {0x16fe0, 0x16fe1, direction::L},   {0x16fe2, 0x16fe2, direction::ON},
8881
    {0x16fe3, 0x16fe3, direction::L},   {0x16fe4, 0x16fe4, direction::NSM},
8882
    {0x16ff0, 0x16ff1, direction::L},   {0x17000, 0x187f7, direction::L},
8883
    {0x18800, 0x18cd5, direction::L},   {0x18d00, 0x18d08, direction::L},
8884
    {0x1b000, 0x1b11e, direction::L},   {0x1b150, 0x1b152, direction::L},
8885
    {0x1b164, 0x1b167, direction::L},   {0x1b170, 0x1b2fb, direction::L},
8886
    {0x1bc00, 0x1bc6a, direction::L},   {0x1bc70, 0x1bc7c, direction::L},
8887
    {0x1bc80, 0x1bc88, direction::L},   {0x1bc90, 0x1bc99, direction::L},
8888
    {0x1bc9c, 0x1bc9c, direction::L},   {0x1bc9d, 0x1bc9e, direction::NSM},
8889
    {0x1bc9f, 0x1bc9f, direction::L},   {0x1bca0, 0x1bca3, direction::BN},
8890
    {0x1d000, 0x1d0f5, direction::L},   {0x1d100, 0x1d126, direction::L},
8891
    {0x1d129, 0x1d166, direction::L},   {0x1d167, 0x1d169, direction::NSM},
8892
    {0x1d16a, 0x1d172, direction::L},   {0x1d173, 0x1d17a, direction::BN},
8893
    {0x1d17b, 0x1d182, direction::NSM}, {0x1d183, 0x1d184, direction::L},
8894
    {0x1d185, 0x1d18b, direction::NSM}, {0x1d18c, 0x1d1a9, direction::L},
8895
    {0x1d1aa, 0x1d1ad, direction::NSM}, {0x1d1ae, 0x1d1e8, direction::L},
8896
    {0x1d200, 0x1d241, direction::ON},  {0x1d242, 0x1d244, direction::NSM},
8897
    {0x1d245, 0x1d245, direction::ON},  {0x1d2e0, 0x1d2f3, direction::L},
8898
    {0x1d300, 0x1d356, direction::ON},  {0x1d360, 0x1d378, direction::L},
8899
    {0x1d400, 0x1d454, direction::L},   {0x1d456, 0x1d49c, direction::L},
8900
    {0x1d49e, 0x1d49f, direction::L},   {0x1d4a2, 0x1d4a2, direction::L},
8901
    {0x1d4a5, 0x1d4a6, direction::L},   {0x1d4a9, 0x1d4ac, direction::L},
8902
    {0x1d4ae, 0x1d4b9, direction::L},   {0x1d4bb, 0x1d4bb, direction::L},
8903
    {0x1d4bd, 0x1d4c3, direction::L},   {0x1d4c5, 0x1d505, direction::L},
8904
    {0x1d507, 0x1d50a, direction::L},   {0x1d50d, 0x1d514, direction::L},
8905
    {0x1d516, 0x1d51c, direction::L},   {0x1d51e, 0x1d539, direction::L},
8906
    {0x1d53b, 0x1d53e, direction::L},   {0x1d540, 0x1d544, direction::L},
8907
    {0x1d546, 0x1d546, direction::L},   {0x1d54a, 0x1d550, direction::L},
8908
    {0x1d552, 0x1d6a5, direction::L},   {0x1d6a8, 0x1d6da, direction::L},
8909
    {0x1d6db, 0x1d6db, direction::ON},  {0x1d6dc, 0x1d714, direction::L},
8910
    {0x1d715, 0x1d715, direction::ON},  {0x1d716, 0x1d74e, direction::L},
8911
    {0x1d74f, 0x1d74f, direction::ON},  {0x1d750, 0x1d788, direction::L},
8912
    {0x1d789, 0x1d789, direction::ON},  {0x1d78a, 0x1d7c2, direction::L},
8913
    {0x1d7c3, 0x1d7c3, direction::ON},  {0x1d7c4, 0x1d7cb, direction::L},
8914
    {0x1d7ce, 0x1d7ff, direction::EN},  {0x1d800, 0x1d9ff, direction::L},
8915
    {0x1da00, 0x1da36, direction::NSM}, {0x1da37, 0x1da3a, direction::L},
8916
    {0x1da3b, 0x1da6c, direction::NSM}, {0x1da6d, 0x1da74, direction::L},
8917
    {0x1da75, 0x1da75, direction::NSM}, {0x1da76, 0x1da83, direction::L},
8918
    {0x1da84, 0x1da84, direction::NSM}, {0x1da85, 0x1da8b, direction::L},
8919
    {0x1da9b, 0x1da9f, direction::NSM}, {0x1daa1, 0x1daaf, direction::NSM},
8920
    {0x1e000, 0x1e006, direction::NSM}, {0x1e008, 0x1e018, direction::NSM},
8921
    {0x1e01b, 0x1e021, direction::NSM}, {0x1e023, 0x1e024, direction::NSM},
8922
    {0x1e026, 0x1e02a, direction::NSM}, {0x1e100, 0x1e12c, direction::L},
8923
    {0x1e130, 0x1e136, direction::NSM}, {0x1e137, 0x1e13d, direction::L},
8924
    {0x1e140, 0x1e149, direction::L},   {0x1e14e, 0x1e14f, direction::L},
8925
    {0x1e2c0, 0x1e2eb, direction::L},   {0x1e2ec, 0x1e2ef, direction::NSM},
8926
    {0x1e2f0, 0x1e2f9, direction::L},   {0x1e2ff, 0x1e2ff, direction::ET},
8927
    {0x1e800, 0x1e8c4, direction::R},   {0x1e8c7, 0x1e8cf, direction::R},
8928
    {0x1e8d0, 0x1e8d6, direction::NSM}, {0x1e900, 0x1e943, direction::R},
8929
    {0x1e944, 0x1e94a, direction::NSM}, {0x1e94b, 0x1e94b, direction::R},
8930
    {0x1e950, 0x1e959, direction::R},   {0x1e95e, 0x1e95f, direction::R},
8931
    {0x1ec71, 0x1ecb4, direction::AL},  {0x1ed01, 0x1ed3d, direction::AL},
8932
    {0x1ee00, 0x1ee03, direction::AL},  {0x1ee05, 0x1ee1f, direction::AL},
8933
    {0x1ee21, 0x1ee22, direction::AL},  {0x1ee24, 0x1ee24, direction::AL},
8934
    {0x1ee27, 0x1ee27, direction::AL},  {0x1ee29, 0x1ee32, direction::AL},
8935
    {0x1ee34, 0x1ee37, direction::AL},  {0x1ee39, 0x1ee39, direction::AL},
8936
    {0x1ee3b, 0x1ee3b, direction::AL},  {0x1ee42, 0x1ee42, direction::AL},
8937
    {0x1ee47, 0x1ee47, direction::AL},  {0x1ee49, 0x1ee49, direction::AL},
8938
    {0x1ee4b, 0x1ee4b, direction::AL},  {0x1ee4d, 0x1ee4f, direction::AL},
8939
    {0x1ee51, 0x1ee52, direction::AL},  {0x1ee54, 0x1ee54, direction::AL},
8940
    {0x1ee57, 0x1ee57, direction::AL},  {0x1ee59, 0x1ee59, direction::AL},
8941
    {0x1ee5b, 0x1ee5b, direction::AL},  {0x1ee5d, 0x1ee5d, direction::AL},
8942
    {0x1ee5f, 0x1ee5f, direction::AL},  {0x1ee61, 0x1ee62, direction::AL},
8943
    {0x1ee64, 0x1ee64, direction::AL},  {0x1ee67, 0x1ee6a, direction::AL},
8944
    {0x1ee6c, 0x1ee72, direction::AL},  {0x1ee74, 0x1ee77, direction::AL},
8945
    {0x1ee79, 0x1ee7c, direction::AL},  {0x1ee7e, 0x1ee7e, direction::AL},
8946
    {0x1ee80, 0x1ee89, direction::AL},  {0x1ee8b, 0x1ee9b, direction::AL},
8947
    {0x1eea1, 0x1eea3, direction::AL},  {0x1eea5, 0x1eea9, direction::AL},
8948
    {0x1eeab, 0x1eebb, direction::AL},  {0x1eef0, 0x1eef1, direction::ON},
8949
    {0x1f000, 0x1f02b, direction::ON},  {0x1f030, 0x1f093, direction::ON},
8950
    {0x1f0a0, 0x1f0ae, direction::ON},  {0x1f0b1, 0x1f0bf, direction::ON},
8951
    {0x1f0c1, 0x1f0cf, direction::ON},  {0x1f0d1, 0x1f0f5, direction::ON},
8952
    {0x1f100, 0x1f10a, direction::EN},  {0x1f10b, 0x1f10f, direction::ON},
8953
    {0x1f110, 0x1f12e, direction::L},   {0x1f12f, 0x1f12f, direction::ON},
8954
    {0x1f130, 0x1f169, direction::L},   {0x1f16a, 0x1f16f, direction::ON},
8955
    {0x1f170, 0x1f1ac, direction::L},   {0x1f1ad, 0x1f1ad, direction::ON},
8956
    {0x1f1e6, 0x1f202, direction::L},   {0x1f210, 0x1f23b, direction::L},
8957
    {0x1f240, 0x1f248, direction::L},   {0x1f250, 0x1f251, direction::L},
8958
    {0x1f260, 0x1f265, direction::ON},  {0x1f300, 0x1f6d7, direction::ON},
8959
    {0x1f6e0, 0x1f6ec, direction::ON},  {0x1f6f0, 0x1f6fc, direction::ON},
8960
    {0x1f700, 0x1f773, direction::ON},  {0x1f780, 0x1f7d8, direction::ON},
8961
    {0x1f7e0, 0x1f7eb, direction::ON},  {0x1f800, 0x1f80b, direction::ON},
8962
    {0x1f810, 0x1f847, direction::ON},  {0x1f850, 0x1f859, direction::ON},
8963
    {0x1f860, 0x1f887, direction::ON},  {0x1f890, 0x1f8ad, direction::ON},
8964
    {0x1f8b0, 0x1f8b1, direction::ON},  {0x1f900, 0x1f978, direction::ON},
8965
    {0x1f97a, 0x1f9cb, direction::ON},  {0x1f9cd, 0x1fa53, direction::ON},
8966
    {0x1fa60, 0x1fa6d, direction::ON},  {0x1fa70, 0x1fa74, direction::ON},
8967
    {0x1fa78, 0x1fa7a, direction::ON},  {0x1fa80, 0x1fa86, direction::ON},
8968
    {0x1fa90, 0x1faa8, direction::ON},  {0x1fab0, 0x1fab6, direction::ON},
8969
    {0x1fac0, 0x1fac2, direction::ON},  {0x1fad0, 0x1fad6, direction::ON},
8970
    {0x1fb00, 0x1fb92, direction::ON},  {0x1fb94, 0x1fbca, direction::ON},
8971
    {0x1fbf0, 0x1fbf9, direction::EN},  {0x20000, 0x2a6dd, direction::L},
8972
    {0x2a700, 0x2b734, direction::L},   {0x2b740, 0x2b81d, direction::L},
8973
    {0x2b820, 0x2cea1, direction::L},   {0x2ceb0, 0x2ebe0, direction::L},
8974
    {0x2f800, 0x2fa1d, direction::L},   {0x30000, 0x3134a, direction::L},
8975
    {0xe0001, 0xe0001, direction::BN},  {0xe0020, 0xe007f, direction::BN},
8976
    {0xe0100, 0xe01ef, direction::NSM}, {0xf0000, 0xffffd, direction::L},
8977
    {0x100000, 0x10fffd, direction::L}};
8978
8979
// CheckJoiners and CheckBidi are true for URL specification.
8980
8981
397k
inline static direction find_direction(uint32_t code_point) noexcept {
8982
397k
  auto it = std::lower_bound(
8983
397k
      std::begin(dir_table), std::end(dir_table), code_point,
8984
4.07M
      [](const directions& d, uint32_t c) { return d.final_code < c; });
8985
8986
  // next check is almost surely in vain, but we use it for safety.
8987
397k
  if (it == std::end(dir_table)) {
8988
0
    return direction::NONE;
8989
0
  }
8990
  // We have that d.final_code >= c.
8991
397k
  if (code_point >= it->start_code) {
8992
395k
    return it->direct;
8993
395k
  }
8994
1.37k
  return direction::NONE;
8995
397k
}
8996
8997
inline static size_t find_last_not_of_nsm(
8998
38.8k
    const std::u32string_view label) noexcept {
8999
41.1k
  for (int i = static_cast<int>(label.size() - 1); i >= 0; i--)
9000
41.1k
    if (find_direction(label[i]) != direction::NSM) return i;
9001
9002
0
  return std::u32string_view::npos;
9003
38.8k
}
9004
9005
// An RTL label is a label that contains at least one character of type R, AL,
9006
// or AN. https://www.rfc-editor.org/rfc/rfc5893#section-2
9007
38.8k
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
9008
38.8k
  const size_t mask =
9009
38.8k
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
9010
9011
38.8k
  size_t directions = 0;
9012
382k
  for (size_t i = 0; i < label.size(); i++) {
9013
343k
    directions |= 1u << find_direction(label[i]);
9014
343k
  }
9015
38.8k
  return (directions & mask) != 0;
9016
38.8k
}
9017
9018
40.8k
bool is_label_valid(const std::u32string_view label) {
9019
40.8k
  if (label.empty()) {
9020
0
    return true;
9021
0
  }
9022
9023
  ///////////////
9024
  // We have a normalization step which ensures that we are in NFC.
9025
  // If we receive punycode, we normalize and check that the normalized
9026
  // version matches the original.
9027
  // --------------------------------------
9028
  // The label must be in Unicode Normalization Form NFC.
9029
9030
  // Current URL standard indicatest that CheckHyphens is set to false.
9031
  // ---------------------------------------
9032
  // If CheckHyphens, the label must not contain a U+002D HYPHEN-MINUS character
9033
  // in both the third and fourth positions. If CheckHyphens, the label must
9034
  // neither begin nor end with a U+002D HYPHEN-MINUS character.
9035
9036
  // This is not necessary because we segment the
9037
  // labels by '.'.
9038
  // ---------------------------------------
9039
  // The label must not contain a U+002E ( . ) FULL STOP.
9040
  // if (label.find('.') != std::string_view::npos) return false;
9041
9042
  // The label must not begin with a combining mark, that is:
9043
  // General_Category=Mark.
9044
40.8k
  constexpr static uint32_t combining[] = {
9045
40.8k
      0x300,   0x301,   0x302,   0x303,   0x304,   0x305,   0x306,   0x307,
9046
40.8k
      0x308,   0x309,   0x30a,   0x30b,   0x30c,   0x30d,   0x30e,   0x30f,
9047
40.8k
      0x310,   0x311,   0x312,   0x313,   0x314,   0x315,   0x316,   0x317,
9048
40.8k
      0x318,   0x319,   0x31a,   0x31b,   0x31c,   0x31d,   0x31e,   0x31f,
9049
40.8k
      0x320,   0x321,   0x322,   0x323,   0x324,   0x325,   0x326,   0x327,
9050
40.8k
      0x328,   0x329,   0x32a,   0x32b,   0x32c,   0x32d,   0x32e,   0x32f,
9051
40.8k
      0x330,   0x331,   0x332,   0x333,   0x334,   0x335,   0x336,   0x337,
9052
40.8k
      0x338,   0x339,   0x33a,   0x33b,   0x33c,   0x33d,   0x33e,   0x33f,
9053
40.8k
      0x340,   0x341,   0x342,   0x343,   0x344,   0x345,   0x346,   0x347,
9054
40.8k
      0x348,   0x349,   0x34a,   0x34b,   0x34c,   0x34d,   0x34e,   0x34f,
9055
40.8k
      0x350,   0x351,   0x352,   0x353,   0x354,   0x355,   0x356,   0x357,
9056
40.8k
      0x358,   0x359,   0x35a,   0x35b,   0x35c,   0x35d,   0x35e,   0x35f,
9057
40.8k
      0x360,   0x361,   0x362,   0x363,   0x364,   0x365,   0x366,   0x367,
9058
40.8k
      0x368,   0x369,   0x36a,   0x36b,   0x36c,   0x36d,   0x36e,   0x36f,
9059
40.8k
      0x483,   0x484,   0x485,   0x486,   0x487,   0x488,   0x489,   0x591,
9060
40.8k
      0x592,   0x593,   0x594,   0x595,   0x596,   0x597,   0x598,   0x599,
9061
40.8k
      0x59a,   0x59b,   0x59c,   0x59d,   0x59e,   0x59f,   0x5a0,   0x5a1,
9062
40.8k
      0x5a2,   0x5a3,   0x5a4,   0x5a5,   0x5a6,   0x5a7,   0x5a8,   0x5a9,
9063
40.8k
      0x5aa,   0x5ab,   0x5ac,   0x5ad,   0x5ae,   0x5af,   0x5b0,   0x5b1,
9064
40.8k
      0x5b2,   0x5b3,   0x5b4,   0x5b5,   0x5b6,   0x5b7,   0x5b8,   0x5b9,
9065
40.8k
      0x5ba,   0x5bb,   0x5bc,   0x5bd,   0x5bf,   0x5c1,   0x5c2,   0x5c4,
9066
40.8k
      0x5c5,   0x5c7,   0x610,   0x611,   0x612,   0x613,   0x614,   0x615,
9067
40.8k
      0x616,   0x617,   0x618,   0x619,   0x61a,   0x64b,   0x64c,   0x64d,
9068
40.8k
      0x64e,   0x64f,   0x650,   0x651,   0x652,   0x653,   0x654,   0x655,
9069
40.8k
      0x656,   0x657,   0x658,   0x659,   0x65a,   0x65b,   0x65c,   0x65d,
9070
40.8k
      0x65e,   0x65f,   0x670,   0x6d6,   0x6d7,   0x6d8,   0x6d9,   0x6da,
9071
40.8k
      0x6db,   0x6dc,   0x6df,   0x6e0,   0x6e1,   0x6e2,   0x6e3,   0x6e4,
9072
40.8k
      0x6e7,   0x6e8,   0x6ea,   0x6eb,   0x6ec,   0x6ed,   0x711,   0x730,
9073
40.8k
      0x731,   0x732,   0x733,   0x734,   0x735,   0x736,   0x737,   0x738,
9074
40.8k
      0x739,   0x73a,   0x73b,   0x73c,   0x73d,   0x73e,   0x73f,   0x740,
9075
40.8k
      0x741,   0x742,   0x743,   0x744,   0x745,   0x746,   0x747,   0x748,
9076
40.8k
      0x749,   0x74a,   0x7a6,   0x7a7,   0x7a8,   0x7a9,   0x7aa,   0x7ab,
9077
40.8k
      0x7ac,   0x7ad,   0x7ae,   0x7af,   0x7b0,   0x7eb,   0x7ec,   0x7ed,
9078
40.8k
      0x7ee,   0x7ef,   0x7f0,   0x7f1,   0x7f2,   0x7f3,   0x7fd,   0x816,
9079
40.8k
      0x817,   0x818,   0x819,   0x81b,   0x81c,   0x81d,   0x81e,   0x81f,
9080
40.8k
      0x820,   0x821,   0x822,   0x823,   0x825,   0x826,   0x827,   0x829,
9081
40.8k
      0x82a,   0x82b,   0x82c,   0x82d,   0x859,   0x85a,   0x85b,   0x8d3,
9082
40.8k
      0x8d4,   0x8d5,   0x8d6,   0x8d7,   0x8d8,   0x8d9,   0x8da,   0x8db,
9083
40.8k
      0x8dc,   0x8dd,   0x8de,   0x8df,   0x8e0,   0x8e1,   0x8e3,   0x8e4,
9084
40.8k
      0x8e5,   0x8e6,   0x8e7,   0x8e8,   0x8e9,   0x8ea,   0x8eb,   0x8ec,
9085
40.8k
      0x8ed,   0x8ee,   0x8ef,   0x8f0,   0x8f1,   0x8f2,   0x8f3,   0x8f4,
9086
40.8k
      0x8f5,   0x8f6,   0x8f7,   0x8f8,   0x8f9,   0x8fa,   0x8fb,   0x8fc,
9087
40.8k
      0x8fd,   0x8fe,   0x8ff,   0x900,   0x901,   0x902,   0x903,   0x93a,
9088
40.8k
      0x93b,   0x93c,   0x93e,   0x93f,   0x940,   0x941,   0x942,   0x943,
9089
40.8k
      0x944,   0x945,   0x946,   0x947,   0x948,   0x949,   0x94a,   0x94b,
9090
40.8k
      0x94c,   0x94d,   0x94e,   0x94f,   0x951,   0x952,   0x953,   0x954,
9091
40.8k
      0x955,   0x956,   0x957,   0x962,   0x963,   0x981,   0x982,   0x983,
9092
40.8k
      0x9bc,   0x9be,   0x9bf,   0x9c0,   0x9c1,   0x9c2,   0x9c3,   0x9c4,
9093
40.8k
      0x9c7,   0x9c8,   0x9cb,   0x9cc,   0x9cd,   0x9d7,   0x9e2,   0x9e3,
9094
40.8k
      0x9fe,   0xa01,   0xa02,   0xa03,   0xa3c,   0xa3e,   0xa3f,   0xa40,
9095
40.8k
      0xa41,   0xa42,   0xa47,   0xa48,   0xa4b,   0xa4c,   0xa4d,   0xa51,
9096
40.8k
      0xa70,   0xa71,   0xa75,   0xa81,   0xa82,   0xa83,   0xabc,   0xabe,
9097
40.8k
      0xabf,   0xac0,   0xac1,   0xac2,   0xac3,   0xac4,   0xac5,   0xac7,
9098
40.8k
      0xac8,   0xac9,   0xacb,   0xacc,   0xacd,   0xae2,   0xae3,   0xafa,
9099
40.8k
      0xafb,   0xafc,   0xafd,   0xafe,   0xaff,   0xb01,   0xb02,   0xb03,
9100
40.8k
      0xb3c,   0xb3e,   0xb3f,   0xb40,   0xb41,   0xb42,   0xb43,   0xb44,
9101
40.8k
      0xb47,   0xb48,   0xb4b,   0xb4c,   0xb4d,   0xb55,   0xb56,   0xb57,
9102
40.8k
      0xb62,   0xb63,   0xb82,   0xbbe,   0xbbf,   0xbc0,   0xbc1,   0xbc2,
9103
40.8k
      0xbc6,   0xbc7,   0xbc8,   0xbca,   0xbcb,   0xbcc,   0xbcd,   0xbd7,
9104
40.8k
      0xc00,   0xc01,   0xc02,   0xc03,   0xc04,   0xc3e,   0xc3f,   0xc40,
9105
40.8k
      0xc41,   0xc42,   0xc43,   0xc44,   0xc46,   0xc47,   0xc48,   0xc4a,
9106
40.8k
      0xc4b,   0xc4c,   0xc4d,   0xc55,   0xc56,   0xc62,   0xc63,   0xc81,
9107
40.8k
      0xc82,   0xc83,   0xcbc,   0xcbe,   0xcbf,   0xcc0,   0xcc1,   0xcc2,
9108
40.8k
      0xcc3,   0xcc4,   0xcc6,   0xcc7,   0xcc8,   0xcca,   0xccb,   0xccc,
9109
40.8k
      0xccd,   0xcd5,   0xcd6,   0xce2,   0xce3,   0xd00,   0xd01,   0xd02,
9110
40.8k
      0xd03,   0xd3b,   0xd3c,   0xd3e,   0xd3f,   0xd40,   0xd41,   0xd42,
9111
40.8k
      0xd43,   0xd44,   0xd46,   0xd47,   0xd48,   0xd4a,   0xd4b,   0xd4c,
9112
40.8k
      0xd4d,   0xd57,   0xd62,   0xd63,   0xd81,   0xd82,   0xd83,   0xdca,
9113
40.8k
      0xdcf,   0xdd0,   0xdd1,   0xdd2,   0xdd3,   0xdd4,   0xdd6,   0xdd8,
9114
40.8k
      0xdd9,   0xdda,   0xddb,   0xddc,   0xddd,   0xdde,   0xddf,   0xdf2,
9115
40.8k
      0xdf3,   0xe31,   0xe34,   0xe35,   0xe36,   0xe37,   0xe38,   0xe39,
9116
40.8k
      0xe3a,   0xe47,   0xe48,   0xe49,   0xe4a,   0xe4b,   0xe4c,   0xe4d,
9117
40.8k
      0xe4e,   0xeb1,   0xeb4,   0xeb5,   0xeb6,   0xeb7,   0xeb8,   0xeb9,
9118
40.8k
      0xeba,   0xebb,   0xebc,   0xec8,   0xec9,   0xeca,   0xecb,   0xecc,
9119
40.8k
      0xecd,   0xf18,   0xf19,   0xf35,   0xf37,   0xf39,   0xf3e,   0xf3f,
9120
40.8k
      0xf71,   0xf72,   0xf73,   0xf74,   0xf75,   0xf76,   0xf77,   0xf78,
9121
40.8k
      0xf79,   0xf7a,   0xf7b,   0xf7c,   0xf7d,   0xf7e,   0xf7f,   0xf80,
9122
40.8k
      0xf81,   0xf82,   0xf83,   0xf84,   0xf86,   0xf87,   0xf8d,   0xf8e,
9123
40.8k
      0xf8f,   0xf90,   0xf91,   0xf92,   0xf93,   0xf94,   0xf95,   0xf96,
9124
40.8k
      0xf97,   0xf99,   0xf9a,   0xf9b,   0xf9c,   0xf9d,   0xf9e,   0xf9f,
9125
40.8k
      0xfa0,   0xfa1,   0xfa2,   0xfa3,   0xfa4,   0xfa5,   0xfa6,   0xfa7,
9126
40.8k
      0xfa8,   0xfa9,   0xfaa,   0xfab,   0xfac,   0xfad,   0xfae,   0xfaf,
9127
40.8k
      0xfb0,   0xfb1,   0xfb2,   0xfb3,   0xfb4,   0xfb5,   0xfb6,   0xfb7,
9128
40.8k
      0xfb8,   0xfb9,   0xfba,   0xfbb,   0xfbc,   0xfc6,   0x102b,  0x102c,
9129
40.8k
      0x102d,  0x102e,  0x102f,  0x1030,  0x1031,  0x1032,  0x1033,  0x1034,
9130
40.8k
      0x1035,  0x1036,  0x1037,  0x1038,  0x1039,  0x103a,  0x103b,  0x103c,
9131
40.8k
      0x103d,  0x103e,  0x1056,  0x1057,  0x1058,  0x1059,  0x105e,  0x105f,
9132
40.8k
      0x1060,  0x1062,  0x1063,  0x1064,  0x1067,  0x1068,  0x1069,  0x106a,
9133
40.8k
      0x106b,  0x106c,  0x106d,  0x1071,  0x1072,  0x1073,  0x1074,  0x1082,
9134
40.8k
      0x1083,  0x1084,  0x1085,  0x1086,  0x1087,  0x1088,  0x1089,  0x108a,
9135
40.8k
      0x108b,  0x108c,  0x108d,  0x108f,  0x109a,  0x109b,  0x109c,  0x109d,
9136
40.8k
      0x135d,  0x135e,  0x135f,  0x1712,  0x1713,  0x1714,  0x1732,  0x1733,
9137
40.8k
      0x1734,  0x1752,  0x1753,  0x1772,  0x1773,  0x17b4,  0x17b5,  0x17b6,
9138
40.8k
      0x17b7,  0x17b8,  0x17b9,  0x17ba,  0x17bb,  0x17bc,  0x17bd,  0x17be,
9139
40.8k
      0x17bf,  0x17c0,  0x17c1,  0x17c2,  0x17c3,  0x17c4,  0x17c5,  0x17c6,
9140
40.8k
      0x17c7,  0x17c8,  0x17c9,  0x17ca,  0x17cb,  0x17cc,  0x17cd,  0x17ce,
9141
40.8k
      0x17cf,  0x17d0,  0x17d1,  0x17d2,  0x17d3,  0x17dd,  0x180b,  0x180c,
9142
40.8k
      0x180d,  0x1885,  0x1886,  0x18a9,  0x1920,  0x1921,  0x1922,  0x1923,
9143
40.8k
      0x1924,  0x1925,  0x1926,  0x1927,  0x1928,  0x1929,  0x192a,  0x192b,
9144
40.8k
      0x1930,  0x1931,  0x1932,  0x1933,  0x1934,  0x1935,  0x1936,  0x1937,
9145
40.8k
      0x1938,  0x1939,  0x193a,  0x193b,  0x1a17,  0x1a18,  0x1a19,  0x1a1a,
9146
40.8k
      0x1a1b,  0x1a55,  0x1a56,  0x1a57,  0x1a58,  0x1a59,  0x1a5a,  0x1a5b,
9147
40.8k
      0x1a5c,  0x1a5d,  0x1a5e,  0x1a60,  0x1a61,  0x1a62,  0x1a63,  0x1a64,
9148
40.8k
      0x1a65,  0x1a66,  0x1a67,  0x1a68,  0x1a69,  0x1a6a,  0x1a6b,  0x1a6c,
9149
40.8k
      0x1a6d,  0x1a6e,  0x1a6f,  0x1a70,  0x1a71,  0x1a72,  0x1a73,  0x1a74,
9150
40.8k
      0x1a75,  0x1a76,  0x1a77,  0x1a78,  0x1a79,  0x1a7a,  0x1a7b,  0x1a7c,
9151
40.8k
      0x1a7f,  0x1ab0,  0x1ab1,  0x1ab2,  0x1ab3,  0x1ab4,  0x1ab5,  0x1ab6,
9152
40.8k
      0x1ab7,  0x1ab8,  0x1ab9,  0x1aba,  0x1abb,  0x1abc,  0x1abd,  0x1abe,
9153
40.8k
      0x1abf,  0x1ac0,  0x1b00,  0x1b01,  0x1b02,  0x1b03,  0x1b04,  0x1b34,
9154
40.8k
      0x1b35,  0x1b36,  0x1b37,  0x1b38,  0x1b39,  0x1b3a,  0x1b3b,  0x1b3c,
9155
40.8k
      0x1b3d,  0x1b3e,  0x1b3f,  0x1b40,  0x1b41,  0x1b42,  0x1b43,  0x1b44,
9156
40.8k
      0x1b6b,  0x1b6c,  0x1b6d,  0x1b6e,  0x1b6f,  0x1b70,  0x1b71,  0x1b72,
9157
40.8k
      0x1b73,  0x1b80,  0x1b81,  0x1b82,  0x1ba1,  0x1ba2,  0x1ba3,  0x1ba4,
9158
40.8k
      0x1ba5,  0x1ba6,  0x1ba7,  0x1ba8,  0x1ba9,  0x1baa,  0x1bab,  0x1bac,
9159
40.8k
      0x1bad,  0x1be6,  0x1be7,  0x1be8,  0x1be9,  0x1bea,  0x1beb,  0x1bec,
9160
40.8k
      0x1bed,  0x1bee,  0x1bef,  0x1bf0,  0x1bf1,  0x1bf2,  0x1bf3,  0x1c24,
9161
40.8k
      0x1c25,  0x1c26,  0x1c27,  0x1c28,  0x1c29,  0x1c2a,  0x1c2b,  0x1c2c,
9162
40.8k
      0x1c2d,  0x1c2e,  0x1c2f,  0x1c30,  0x1c31,  0x1c32,  0x1c33,  0x1c34,
9163
40.8k
      0x1c35,  0x1c36,  0x1c37,  0x1cd0,  0x1cd1,  0x1cd2,  0x1cd4,  0x1cd5,
9164
40.8k
      0x1cd6,  0x1cd7,  0x1cd8,  0x1cd9,  0x1cda,  0x1cdb,  0x1cdc,  0x1cdd,
9165
40.8k
      0x1cde,  0x1cdf,  0x1ce0,  0x1ce1,  0x1ce2,  0x1ce3,  0x1ce4,  0x1ce5,
9166
40.8k
      0x1ce6,  0x1ce7,  0x1ce8,  0x1ced,  0x1cf4,  0x1cf7,  0x1cf8,  0x1cf9,
9167
40.8k
      0x1dc0,  0x1dc1,  0x1dc2,  0x1dc3,  0x1dc4,  0x1dc5,  0x1dc6,  0x1dc7,
9168
40.8k
      0x1dc8,  0x1dc9,  0x1dca,  0x1dcb,  0x1dcc,  0x1dcd,  0x1dce,  0x1dcf,
9169
40.8k
      0x1dd0,  0x1dd1,  0x1dd2,  0x1dd3,  0x1dd4,  0x1dd5,  0x1dd6,  0x1dd7,
9170
40.8k
      0x1dd8,  0x1dd9,  0x1dda,  0x1ddb,  0x1ddc,  0x1ddd,  0x1dde,  0x1ddf,
9171
40.8k
      0x1de0,  0x1de1,  0x1de2,  0x1de3,  0x1de4,  0x1de5,  0x1de6,  0x1de7,
9172
40.8k
      0x1de8,  0x1de9,  0x1dea,  0x1deb,  0x1dec,  0x1ded,  0x1dee,  0x1def,
9173
40.8k
      0x1df0,  0x1df1,  0x1df2,  0x1df3,  0x1df4,  0x1df5,  0x1df6,  0x1df7,
9174
40.8k
      0x1df8,  0x1df9,  0x1dfb,  0x1dfc,  0x1dfd,  0x1dfe,  0x1dff,  0x20d0,
9175
40.8k
      0x20d1,  0x20d2,  0x20d3,  0x20d4,  0x20d5,  0x20d6,  0x20d7,  0x20d8,
9176
40.8k
      0x20d9,  0x20da,  0x20db,  0x20dc,  0x20dd,  0x20de,  0x20df,  0x20e0,
9177
40.8k
      0x20e1,  0x20e2,  0x20e3,  0x20e4,  0x20e5,  0x20e6,  0x20e7,  0x20e8,
9178
40.8k
      0x20e9,  0x20ea,  0x20eb,  0x20ec,  0x20ed,  0x20ee,  0x20ef,  0x20f0,
9179
40.8k
      0x2cef,  0x2cf0,  0x2cf1,  0x2d7f,  0x2de0,  0x2de1,  0x2de2,  0x2de3,
9180
40.8k
      0x2de4,  0x2de5,  0x2de6,  0x2de7,  0x2de8,  0x2de9,  0x2dea,  0x2deb,
9181
40.8k
      0x2dec,  0x2ded,  0x2dee,  0x2def,  0x2df0,  0x2df1,  0x2df2,  0x2df3,
9182
40.8k
      0x2df4,  0x2df5,  0x2df6,  0x2df7,  0x2df8,  0x2df9,  0x2dfa,  0x2dfb,
9183
40.8k
      0x2dfc,  0x2dfd,  0x2dfe,  0x2dff,  0x302a,  0x302b,  0x302c,  0x302d,
9184
40.8k
      0x302e,  0x302f,  0x3099,  0x309a,  0xa66f,  0xa670,  0xa671,  0xa672,
9185
40.8k
      0xa674,  0xa675,  0xa676,  0xa677,  0xa678,  0xa679,  0xa67a,  0xa67b,
9186
40.8k
      0xa67c,  0xa67d,  0xa69e,  0xa69f,  0xa6f0,  0xa6f1,  0xa802,  0xa806,
9187
40.8k
      0xa80b,  0xa823,  0xa824,  0xa825,  0xa826,  0xa827,  0xa82c,  0xa880,
9188
40.8k
      0xa881,  0xa8b4,  0xa8b5,  0xa8b6,  0xa8b7,  0xa8b8,  0xa8b9,  0xa8ba,
9189
40.8k
      0xa8bb,  0xa8bc,  0xa8bd,  0xa8be,  0xa8bf,  0xa8c0,  0xa8c1,  0xa8c2,
9190
40.8k
      0xa8c3,  0xa8c4,  0xa8c5,  0xa8e0,  0xa8e1,  0xa8e2,  0xa8e3,  0xa8e4,
9191
40.8k
      0xa8e5,  0xa8e6,  0xa8e7,  0xa8e8,  0xa8e9,  0xa8ea,  0xa8eb,  0xa8ec,
9192
40.8k
      0xa8ed,  0xa8ee,  0xa8ef,  0xa8f0,  0xa8f1,  0xa8ff,  0xa926,  0xa927,
9193
40.8k
      0xa928,  0xa929,  0xa92a,  0xa92b,  0xa92c,  0xa92d,  0xa947,  0xa948,
9194
40.8k
      0xa949,  0xa94a,  0xa94b,  0xa94c,  0xa94d,  0xa94e,  0xa94f,  0xa950,
9195
40.8k
      0xa951,  0xa952,  0xa953,  0xa980,  0xa981,  0xa982,  0xa983,  0xa9b3,
9196
40.8k
      0xa9b4,  0xa9b5,  0xa9b6,  0xa9b7,  0xa9b8,  0xa9b9,  0xa9ba,  0xa9bb,
9197
40.8k
      0xa9bc,  0xa9bd,  0xa9be,  0xa9bf,  0xa9c0,  0xa9e5,  0xaa29,  0xaa2a,
9198
40.8k
      0xaa2b,  0xaa2c,  0xaa2d,  0xaa2e,  0xaa2f,  0xaa30,  0xaa31,  0xaa32,
9199
40.8k
      0xaa33,  0xaa34,  0xaa35,  0xaa36,  0xaa43,  0xaa4c,  0xaa4d,  0xaa7b,
9200
40.8k
      0xaa7c,  0xaa7d,  0xaab0,  0xaab2,  0xaab3,  0xaab4,  0xaab7,  0xaab8,
9201
40.8k
      0xaabe,  0xaabf,  0xaac1,  0xaaeb,  0xaaec,  0xaaed,  0xaaee,  0xaaef,
9202
40.8k
      0xaaf5,  0xaaf6,  0xabe3,  0xabe4,  0xabe5,  0xabe6,  0xabe7,  0xabe8,
9203
40.8k
      0xabe9,  0xabea,  0xabec,  0xabed,  0xfb1e,  0xfe00,  0xfe01,  0xfe02,
9204
40.8k
      0xfe03,  0xfe04,  0xfe05,  0xfe06,  0xfe07,  0xfe08,  0xfe09,  0xfe0a,
9205
40.8k
      0xfe0b,  0xfe0c,  0xfe0d,  0xfe0e,  0xfe0f,  0xfe20,  0xfe21,  0xfe22,
9206
40.8k
      0xfe23,  0xfe24,  0xfe25,  0xfe26,  0xfe27,  0xfe28,  0xfe29,  0xfe2a,
9207
40.8k
      0xfe2b,  0xfe2c,  0xfe2d,  0xfe2e,  0xfe2f,  0x101fd, 0x102e0, 0x10376,
9208
40.8k
      0x10377, 0x10378, 0x10379, 0x1037a, 0x10a01, 0x10a02, 0x10a03, 0x10a05,
9209
40.8k
      0x10a06, 0x10a0c, 0x10a0d, 0x10a0e, 0x10a0f, 0x10a38, 0x10a39, 0x10a3a,
9210
40.8k
      0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d25, 0x10d26, 0x10d27, 0x10eab,
9211
40.8k
      0x10eac, 0x10f46, 0x10f47, 0x10f48, 0x10f49, 0x10f4a, 0x10f4b, 0x10f4c,
9212
40.8k
      0x10f4d, 0x10f4e, 0x10f4f, 0x10f50, 0x11000, 0x11001, 0x11002, 0x11038,
9213
40.8k
      0x11039, 0x1103a, 0x1103b, 0x1103c, 0x1103d, 0x1103e, 0x1103f, 0x11040,
9214
40.8k
      0x11041, 0x11042, 0x11043, 0x11044, 0x11045, 0x11046, 0x1107f, 0x11080,
9215
40.8k
      0x11081, 0x11082, 0x110b0, 0x110b1, 0x110b2, 0x110b3, 0x110b4, 0x110b5,
9216
40.8k
      0x110b6, 0x110b7, 0x110b8, 0x110b9, 0x110ba, 0x11100, 0x11101, 0x11102,
9217
40.8k
      0x11127, 0x11128, 0x11129, 0x1112a, 0x1112b, 0x1112c, 0x1112d, 0x1112e,
9218
40.8k
      0x1112f, 0x11130, 0x11131, 0x11132, 0x11133, 0x11134, 0x11145, 0x11146,
9219
40.8k
      0x11173, 0x11180, 0x11181, 0x11182, 0x111b3, 0x111b4, 0x111b5, 0x111b6,
9220
40.8k
      0x111b7, 0x111b8, 0x111b9, 0x111ba, 0x111bb, 0x111bc, 0x111bd, 0x111be,
9221
40.8k
      0x111bf, 0x111c0, 0x111c9, 0x111ca, 0x111cb, 0x111cc, 0x111ce, 0x111cf,
9222
40.8k
      0x1122c, 0x1122d, 0x1122e, 0x1122f, 0x11230, 0x11231, 0x11232, 0x11233,
9223
40.8k
      0x11234, 0x11235, 0x11236, 0x11237, 0x1123e, 0x112df, 0x112e0, 0x112e1,
9224
40.8k
      0x112e2, 0x112e3, 0x112e4, 0x112e5, 0x112e6, 0x112e7, 0x112e8, 0x112e9,
9225
40.8k
      0x112ea, 0x11300, 0x11301, 0x11302, 0x11303, 0x1133b, 0x1133c, 0x1133e,
9226
40.8k
      0x1133f, 0x11340, 0x11341, 0x11342, 0x11343, 0x11344, 0x11347, 0x11348,
9227
40.8k
      0x1134b, 0x1134c, 0x1134d, 0x11357, 0x11362, 0x11363, 0x11366, 0x11367,
9228
40.8k
      0x11368, 0x11369, 0x1136a, 0x1136b, 0x1136c, 0x11370, 0x11371, 0x11372,
9229
40.8k
      0x11373, 0x11374, 0x11435, 0x11436, 0x11437, 0x11438, 0x11439, 0x1143a,
9230
40.8k
      0x1143b, 0x1143c, 0x1143d, 0x1143e, 0x1143f, 0x11440, 0x11441, 0x11442,
9231
40.8k
      0x11443, 0x11444, 0x11445, 0x11446, 0x1145e, 0x114b0, 0x114b1, 0x114b2,
9232
40.8k
      0x114b3, 0x114b4, 0x114b5, 0x114b6, 0x114b7, 0x114b8, 0x114b9, 0x114ba,
9233
40.8k
      0x114bb, 0x114bc, 0x114bd, 0x114be, 0x114bf, 0x114c0, 0x114c1, 0x114c2,
9234
40.8k
      0x114c3, 0x115af, 0x115b0, 0x115b1, 0x115b2, 0x115b3, 0x115b4, 0x115b5,
9235
40.8k
      0x115b8, 0x115b9, 0x115ba, 0x115bb, 0x115bc, 0x115bd, 0x115be, 0x115bf,
9236
40.8k
      0x115c0, 0x115dc, 0x115dd, 0x11630, 0x11631, 0x11632, 0x11633, 0x11634,
9237
40.8k
      0x11635, 0x11636, 0x11637, 0x11638, 0x11639, 0x1163a, 0x1163b, 0x1163c,
9238
40.8k
      0x1163d, 0x1163e, 0x1163f, 0x11640, 0x116ab, 0x116ac, 0x116ad, 0x116ae,
9239
40.8k
      0x116af, 0x116b0, 0x116b1, 0x116b2, 0x116b3, 0x116b4, 0x116b5, 0x116b6,
9240
40.8k
      0x116b7, 0x1171d, 0x1171e, 0x1171f, 0x11720, 0x11721, 0x11722, 0x11723,
9241
40.8k
      0x11724, 0x11725, 0x11726, 0x11727, 0x11728, 0x11729, 0x1172a, 0x1172b,
9242
40.8k
      0x1182c, 0x1182d, 0x1182e, 0x1182f, 0x11830, 0x11831, 0x11832, 0x11833,
9243
40.8k
      0x11834, 0x11835, 0x11836, 0x11837, 0x11838, 0x11839, 0x1183a, 0x11930,
9244
40.8k
      0x11931, 0x11932, 0x11933, 0x11934, 0x11935, 0x11937, 0x11938, 0x1193b,
9245
40.8k
      0x1193c, 0x1193d, 0x1193e, 0x11940, 0x11942, 0x11943, 0x119d1, 0x119d2,
9246
40.8k
      0x119d3, 0x119d4, 0x119d5, 0x119d6, 0x119d7, 0x119da, 0x119db, 0x119dc,
9247
40.8k
      0x119dd, 0x119de, 0x119df, 0x119e0, 0x119e4, 0x11a01, 0x11a02, 0x11a03,
9248
40.8k
      0x11a04, 0x11a05, 0x11a06, 0x11a07, 0x11a08, 0x11a09, 0x11a0a, 0x11a33,
9249
40.8k
      0x11a34, 0x11a35, 0x11a36, 0x11a37, 0x11a38, 0x11a39, 0x11a3b, 0x11a3c,
9250
40.8k
      0x11a3d, 0x11a3e, 0x11a47, 0x11a51, 0x11a52, 0x11a53, 0x11a54, 0x11a55,
9251
40.8k
      0x11a56, 0x11a57, 0x11a58, 0x11a59, 0x11a5a, 0x11a5b, 0x11a8a, 0x11a8b,
9252
40.8k
      0x11a8c, 0x11a8d, 0x11a8e, 0x11a8f, 0x11a90, 0x11a91, 0x11a92, 0x11a93,
9253
40.8k
      0x11a94, 0x11a95, 0x11a96, 0x11a97, 0x11a98, 0x11a99, 0x11c2f, 0x11c30,
9254
40.8k
      0x11c31, 0x11c32, 0x11c33, 0x11c34, 0x11c35, 0x11c36, 0x11c38, 0x11c39,
9255
40.8k
      0x11c3a, 0x11c3b, 0x11c3c, 0x11c3d, 0x11c3e, 0x11c3f, 0x11c92, 0x11c93,
9256
40.8k
      0x11c94, 0x11c95, 0x11c96, 0x11c97, 0x11c98, 0x11c99, 0x11c9a, 0x11c9b,
9257
40.8k
      0x11c9c, 0x11c9d, 0x11c9e, 0x11c9f, 0x11ca0, 0x11ca1, 0x11ca2, 0x11ca3,
9258
40.8k
      0x11ca4, 0x11ca5, 0x11ca6, 0x11ca7, 0x11ca9, 0x11caa, 0x11cab, 0x11cac,
9259
40.8k
      0x11cad, 0x11cae, 0x11caf, 0x11cb0, 0x11cb1, 0x11cb2, 0x11cb3, 0x11cb4,
9260
40.8k
      0x11cb5, 0x11cb6, 0x11d31, 0x11d32, 0x11d33, 0x11d34, 0x11d35, 0x11d36,
9261
40.8k
      0x11d3a, 0x11d3c, 0x11d3d, 0x11d3f, 0x11d40, 0x11d41, 0x11d42, 0x11d43,
9262
40.8k
      0x11d44, 0x11d45, 0x11d47, 0x11d8a, 0x11d8b, 0x11d8c, 0x11d8d, 0x11d8e,
9263
40.8k
      0x11d90, 0x11d91, 0x11d93, 0x11d94, 0x11d95, 0x11d96, 0x11d97, 0x11ef3,
9264
40.8k
      0x11ef4, 0x11ef5, 0x11ef6, 0x16af0, 0x16af1, 0x16af2, 0x16af3, 0x16af4,
9265
40.8k
      0x16b30, 0x16b31, 0x16b32, 0x16b33, 0x16b34, 0x16b35, 0x16b36, 0x16f4f,
9266
40.8k
      0x16f51, 0x16f52, 0x16f53, 0x16f54, 0x16f55, 0x16f56, 0x16f57, 0x16f58,
9267
40.8k
      0x16f59, 0x16f5a, 0x16f5b, 0x16f5c, 0x16f5d, 0x16f5e, 0x16f5f, 0x16f60,
9268
40.8k
      0x16f61, 0x16f62, 0x16f63, 0x16f64, 0x16f65, 0x16f66, 0x16f67, 0x16f68,
9269
40.8k
      0x16f69, 0x16f6a, 0x16f6b, 0x16f6c, 0x16f6d, 0x16f6e, 0x16f6f, 0x16f70,
9270
40.8k
      0x16f71, 0x16f72, 0x16f73, 0x16f74, 0x16f75, 0x16f76, 0x16f77, 0x16f78,
9271
40.8k
      0x16f79, 0x16f7a, 0x16f7b, 0x16f7c, 0x16f7d, 0x16f7e, 0x16f7f, 0x16f80,
9272
40.8k
      0x16f81, 0x16f82, 0x16f83, 0x16f84, 0x16f85, 0x16f86, 0x16f87, 0x16f8f,
9273
40.8k
      0x16f90, 0x16f91, 0x16f92, 0x16fe4, 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e,
9274
40.8k
      0x1d165, 0x1d166, 0x1d167, 0x1d168, 0x1d169, 0x1d16d, 0x1d16e, 0x1d16f,
9275
40.8k
      0x1d170, 0x1d171, 0x1d172, 0x1d17b, 0x1d17c, 0x1d17d, 0x1d17e, 0x1d17f,
9276
40.8k
      0x1d180, 0x1d181, 0x1d182, 0x1d185, 0x1d186, 0x1d187, 0x1d188, 0x1d189,
9277
40.8k
      0x1d18a, 0x1d18b, 0x1d1aa, 0x1d1ab, 0x1d1ac, 0x1d1ad, 0x1d242, 0x1d243,
9278
40.8k
      0x1d244, 0x1da00, 0x1da01, 0x1da02, 0x1da03, 0x1da04, 0x1da05, 0x1da06,
9279
40.8k
      0x1da07, 0x1da08, 0x1da09, 0x1da0a, 0x1da0b, 0x1da0c, 0x1da0d, 0x1da0e,
9280
40.8k
      0x1da0f, 0x1da10, 0x1da11, 0x1da12, 0x1da13, 0x1da14, 0x1da15, 0x1da16,
9281
40.8k
      0x1da17, 0x1da18, 0x1da19, 0x1da1a, 0x1da1b, 0x1da1c, 0x1da1d, 0x1da1e,
9282
40.8k
      0x1da1f, 0x1da20, 0x1da21, 0x1da22, 0x1da23, 0x1da24, 0x1da25, 0x1da26,
9283
40.8k
      0x1da27, 0x1da28, 0x1da29, 0x1da2a, 0x1da2b, 0x1da2c, 0x1da2d, 0x1da2e,
9284
40.8k
      0x1da2f, 0x1da30, 0x1da31, 0x1da32, 0x1da33, 0x1da34, 0x1da35, 0x1da36,
9285
40.8k
      0x1da3b, 0x1da3c, 0x1da3d, 0x1da3e, 0x1da3f, 0x1da40, 0x1da41, 0x1da42,
9286
40.8k
      0x1da43, 0x1da44, 0x1da45, 0x1da46, 0x1da47, 0x1da48, 0x1da49, 0x1da4a,
9287
40.8k
      0x1da4b, 0x1da4c, 0x1da4d, 0x1da4e, 0x1da4f, 0x1da50, 0x1da51, 0x1da52,
9288
40.8k
      0x1da53, 0x1da54, 0x1da55, 0x1da56, 0x1da57, 0x1da58, 0x1da59, 0x1da5a,
9289
40.8k
      0x1da5b, 0x1da5c, 0x1da5d, 0x1da5e, 0x1da5f, 0x1da60, 0x1da61, 0x1da62,
9290
40.8k
      0x1da63, 0x1da64, 0x1da65, 0x1da66, 0x1da67, 0x1da68, 0x1da69, 0x1da6a,
9291
40.8k
      0x1da6b, 0x1da6c, 0x1da75, 0x1da84, 0x1da9b, 0x1da9c, 0x1da9d, 0x1da9e,
9292
40.8k
      0x1da9f, 0x1daa1, 0x1daa2, 0x1daa3, 0x1daa4, 0x1daa5, 0x1daa6, 0x1daa7,
9293
40.8k
      0x1daa8, 0x1daa9, 0x1daaa, 0x1daab, 0x1daac, 0x1daad, 0x1daae, 0x1daaf,
9294
40.8k
      0x1e000, 0x1e001, 0x1e002, 0x1e003, 0x1e004, 0x1e005, 0x1e006, 0x1e008,
9295
40.8k
      0x1e009, 0x1e00a, 0x1e00b, 0x1e00c, 0x1e00d, 0x1e00e, 0x1e00f, 0x1e010,
9296
40.8k
      0x1e011, 0x1e012, 0x1e013, 0x1e014, 0x1e015, 0x1e016, 0x1e017, 0x1e018,
9297
40.8k
      0x1e01b, 0x1e01c, 0x1e01d, 0x1e01e, 0x1e01f, 0x1e020, 0x1e021, 0x1e023,
9298
40.8k
      0x1e024, 0x1e026, 0x1e027, 0x1e028, 0x1e029, 0x1e02a, 0x1e130, 0x1e131,
9299
40.8k
      0x1e132, 0x1e133, 0x1e134, 0x1e135, 0x1e136, 0x1e2ec, 0x1e2ed, 0x1e2ee,
9300
40.8k
      0x1e2ef, 0x1e8d0, 0x1e8d1, 0x1e8d2, 0x1e8d3, 0x1e8d4, 0x1e8d5, 0x1e8d6,
9301
40.8k
      0x1e944, 0x1e945, 0x1e946, 0x1e947, 0x1e948, 0x1e949, 0x1e94a, 0xe0100,
9302
40.8k
      0xe0101, 0xe0102, 0xe0103, 0xe0104, 0xe0105, 0xe0106, 0xe0107, 0xe0108,
9303
40.8k
      0xe0109, 0xe010a, 0xe010b, 0xe010c, 0xe010d, 0xe010e, 0xe010f, 0xe0110,
9304
40.8k
      0xe0111, 0xe0112, 0xe0113, 0xe0114, 0xe0115, 0xe0116, 0xe0117, 0xe0118,
9305
40.8k
      0xe0119, 0xe011a, 0xe011b, 0xe011c, 0xe011d, 0xe011e, 0xe011f, 0xe0120,
9306
40.8k
      0xe0121, 0xe0122, 0xe0123, 0xe0124, 0xe0125, 0xe0126, 0xe0127, 0xe0128,
9307
40.8k
      0xe0129, 0xe012a, 0xe012b, 0xe012c, 0xe012d, 0xe012e, 0xe012f, 0xe0130,
9308
40.8k
      0xe0131, 0xe0132, 0xe0133, 0xe0134, 0xe0135, 0xe0136, 0xe0137, 0xe0138,
9309
40.8k
      0xe0139, 0xe013a, 0xe013b, 0xe013c, 0xe013d, 0xe013e, 0xe013f, 0xe0140,
9310
40.8k
      0xe0141, 0xe0142, 0xe0143, 0xe0144, 0xe0145, 0xe0146, 0xe0147, 0xe0148,
9311
40.8k
      0xe0149, 0xe014a, 0xe014b, 0xe014c, 0xe014d, 0xe014e, 0xe014f, 0xe0150,
9312
40.8k
      0xe0151, 0xe0152, 0xe0153, 0xe0154, 0xe0155, 0xe0156, 0xe0157, 0xe0158,
9313
40.8k
      0xe0159, 0xe015a, 0xe015b, 0xe015c, 0xe015d, 0xe015e, 0xe015f, 0xe0160,
9314
40.8k
      0xe0161, 0xe0162, 0xe0163, 0xe0164, 0xe0165, 0xe0166, 0xe0167, 0xe0168,
9315
40.8k
      0xe0169, 0xe016a, 0xe016b, 0xe016c, 0xe016d, 0xe016e, 0xe016f, 0xe0170,
9316
40.8k
      0xe0171, 0xe0172, 0xe0173, 0xe0174, 0xe0175, 0xe0176, 0xe0177, 0xe0178,
9317
40.8k
      0xe0179, 0xe017a, 0xe017b, 0xe017c, 0xe017d, 0xe017e, 0xe017f, 0xe0180,
9318
40.8k
      0xe0181, 0xe0182, 0xe0183, 0xe0184, 0xe0185, 0xe0186, 0xe0187, 0xe0188,
9319
40.8k
      0xe0189, 0xe018a, 0xe018b, 0xe018c, 0xe018d, 0xe018e, 0xe018f, 0xe0190,
9320
40.8k
      0xe0191, 0xe0192, 0xe0193, 0xe0194, 0xe0195, 0xe0196, 0xe0197, 0xe0198,
9321
40.8k
      0xe0199, 0xe019a, 0xe019b, 0xe019c, 0xe019d, 0xe019e, 0xe019f, 0xe01a0,
9322
40.8k
      0xe01a1, 0xe01a2, 0xe01a3, 0xe01a4, 0xe01a5, 0xe01a6, 0xe01a7, 0xe01a8,
9323
40.8k
      0xe01a9, 0xe01aa, 0xe01ab, 0xe01ac, 0xe01ad, 0xe01ae, 0xe01af, 0xe01b0,
9324
40.8k
      0xe01b1, 0xe01b2, 0xe01b3, 0xe01b4, 0xe01b5, 0xe01b6, 0xe01b7, 0xe01b8,
9325
40.8k
      0xe01b9, 0xe01ba, 0xe01bb, 0xe01bc, 0xe01bd, 0xe01be, 0xe01bf, 0xe01c0,
9326
40.8k
      0xe01c1, 0xe01c2, 0xe01c3, 0xe01c4, 0xe01c5, 0xe01c6, 0xe01c7, 0xe01c8,
9327
40.8k
      0xe01c9, 0xe01ca, 0xe01cb, 0xe01cc, 0xe01cd, 0xe01ce, 0xe01cf, 0xe01d0,
9328
40.8k
      0xe01d1, 0xe01d2, 0xe01d3, 0xe01d4, 0xe01d5, 0xe01d6, 0xe01d7, 0xe01d8,
9329
40.8k
      0xe01d9, 0xe01da, 0xe01db, 0xe01dc, 0xe01dd, 0xe01de, 0xe01df, 0xe01e0,
9330
40.8k
      0xe01e1, 0xe01e2, 0xe01e3, 0xe01e4, 0xe01e5, 0xe01e6, 0xe01e7, 0xe01e8,
9331
40.8k
      0xe01e9, 0xe01ea, 0xe01eb, 0xe01ec, 0xe01ed, 0xe01ee, 0xe01ef};
9332
40.8k
  if (std::binary_search(std::begin(combining), std::end(combining),
9333
40.8k
                         label.front())) {
9334
114
    return false;
9335
114
  }
9336
  // We verify this next step as part of the mapping:
9337
  // ---------------------------------------------
9338
  // Each code point in the label must only have certain status values
9339
  // according to Section 5, IDNA Mapping Table:
9340
  // - For Transitional Processing, each value must be valid.
9341
  // - For Nontransitional Processing, each value must be either valid or
9342
  // deviation.
9343
9344
  // If CheckJoiners, the label must satisfy the ContextJ rules from Appendix
9345
  // A, in The Unicode Code Points and Internationalized Domain Names for
9346
  // Applications (IDNA) [IDNA2008].
9347
40.7k
  constexpr static uint32_t virama[] = {
9348
40.7k
      0x094D,  0x09CD,  0x0A4D,  0x0ACD,  0x0B4D,  0x0BCD,  0x0C4D,  0x0CCD,
9349
40.7k
      0x0D3B,  0x0D3C,  0x0D4D,  0x0DCA,  0x0E3A,  0x0EBA,  0x0F84,  0x1039,
9350
40.7k
      0x103A,  0x1714,  0x1734,  0x17D2,  0x1A60,  0x1B44,  0x1BAA,  0x1BAB,
9351
40.7k
      0x1BF2,  0x1BF3,  0x2D7F,  0xA806,  0xA82C,  0xA8C4,  0xA953,  0xA9C0,
9352
40.7k
      0xAAF6,  0xABED,  0x10A3F, 0x11046, 0x1107F, 0x110B9, 0x11133, 0x11134,
9353
40.7k
      0x111C0, 0x11235, 0x112EA, 0x1134D, 0x11442, 0x114C2, 0x115BF, 0x1163F,
9354
40.7k
      0x116B6, 0x1172B, 0x11839, 0x1193D, 0x1193E, 0x119E0, 0x11A34, 0x11A47,
9355
40.7k
      0x11A99, 0x11C3F, 0x11D44, 0x11D45, 0x11D97};
9356
40.7k
  constexpr static uint32_t R[] = {
9357
40.7k
      0x622, 0x623, 0x624, 0x625, 0x627, 0x629, 0x62f, 0x630, 0x631,
9358
40.7k
      0x632, 0x648, 0x671, 0x672, 0x673, 0x675, 0x676, 0x677, 0x688,
9359
40.7k
      0x689, 0x68a, 0x68b, 0x68c, 0x68d, 0x68e, 0x68f, 0x690, 0x691,
9360
40.7k
      0x692, 0x693, 0x694, 0x695, 0x696, 0x697, 0x698, 0x699, 0x6c0,
9361
40.7k
      0x6c3, 0x6c4, 0x6c5, 0x6c6, 0x6c7, 0x6c8, 0x6c9, 0x6ca, 0x6cb,
9362
40.7k
      0x6cd, 0x6cf, 0x6d2, 0x6d3, 0x6d5, 0x6ee, 0x6ef, 0x710, 0x715,
9363
40.7k
      0x716, 0x717, 0x718, 0x719, 0x71e, 0x728, 0x72a, 0x72c, 0x72f,
9364
40.7k
      0x74d, 0x759, 0x75a, 0x75b, 0x854, 0x8aa, 0x8ab, 0x8ac};
9365
40.7k
  constexpr static uint32_t L[] = {0xa872};
9366
40.7k
  constexpr static uint32_t D[] = {
9367
40.7k
      0x620,  0x626,  0x628,  0x62a,  0x62b,  0x62c,  0x62d,  0x62e,  0x633,
9368
40.7k
      0x634,  0x635,  0x636,  0x637,  0x638,  0x639,  0x63a,  0x63b,  0x63c,
9369
40.7k
      0x63d,  0x63e,  0x63f,  0x641,  0x642,  0x643,  0x644,  0x645,  0x646,
9370
40.7k
      0x647,  0x649,  0x64a,  0x66e,  0x66f,  0x678,  0x679,  0x67a,  0x67b,
9371
40.7k
      0x67c,  0x67d,  0x67e,  0x67f,  0x680,  0x681,  0x682,  0x683,  0x684,
9372
40.7k
      0x685,  0x686,  0x687,  0x69a,  0x69b,  0x69c,  0x69d,  0x69e,  0x69f,
9373
40.7k
      0x6a0,  0x6a1,  0x6a2,  0x6a3,  0x6a4,  0x6a5,  0x6a6,  0x6a7,  0x6a8,
9374
40.7k
      0x6a9,  0x6aa,  0x6ab,  0x6ac,  0x6ad,  0x6ae,  0x6af,  0x6b0,  0x6b1,
9375
40.7k
      0x6b2,  0x6b3,  0x6b4,  0x6b5,  0x6b6,  0x6b7,  0x6b8,  0x6b9,  0x6ba,
9376
40.7k
      0x6bb,  0x6bc,  0x6bd,  0x6be,  0x6bf,  0x6c1,  0x6c2,  0x6cc,  0x6ce,
9377
40.7k
      0x6d0,  0x6d1,  0x6fa,  0x6fb,  0x6fc,  0x6ff,  0x712,  0x713,  0x714,
9378
40.7k
      0x71a,  0x71b,  0x71c,  0x71d,  0x71f,  0x720,  0x721,  0x722,  0x723,
9379
40.7k
      0x724,  0x725,  0x726,  0x727,  0x729,  0x72b,  0x72d,  0x72e,  0x74e,
9380
40.7k
      0x74f,  0x750,  0x751,  0x752,  0x753,  0x754,  0x755,  0x756,  0x757,
9381
40.7k
      0x758,  0x75c,  0x75d,  0x75e,  0x75f,  0x760,  0x761,  0x762,  0x763,
9382
40.7k
      0x764,  0x765,  0x766,  0x850,  0x851,  0x852,  0x853,  0x855,  0x8a0,
9383
40.7k
      0x8a2,  0x8a3,  0x8a4,  0x8a5,  0x8a6,  0x8a7,  0x8a8,  0x8a9,  0x1807,
9384
40.7k
      0x1820, 0x1821, 0x1822, 0x1823, 0x1824, 0x1825, 0x1826, 0x1827, 0x1828,
9385
40.7k
      0x1829, 0x182a, 0x182b, 0x182c, 0x182d, 0x182e, 0x182f, 0x1830, 0x1831,
9386
40.7k
      0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837, 0x1838, 0x1839, 0x183a,
9387
40.7k
      0x183b, 0x183c, 0x183d, 0x183e, 0x183f, 0x1840, 0x1841, 0x1842, 0x1843,
9388
40.7k
      0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x184a, 0x184b, 0x184c,
9389
40.7k
      0x184d, 0x184e, 0x184f, 0x1850, 0x1851, 0x1852, 0x1853, 0x1854, 0x1855,
9390
40.7k
      0x1856, 0x1857, 0x1858, 0x1859, 0x185a, 0x185b, 0x185c, 0x185d, 0x185e,
9391
40.7k
      0x185f, 0x1860, 0x1861, 0x1862, 0x1863, 0x1864, 0x1865, 0x1866, 0x1867,
9392
40.7k
      0x1868, 0x1869, 0x186a, 0x186b, 0x186c, 0x186d, 0x186e, 0x186f, 0x1870,
9393
40.7k
      0x1871, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, 0x1877, 0x1887, 0x1888,
9394
40.7k
      0x1889, 0x188a, 0x188b, 0x188c, 0x188d, 0x188e, 0x188f, 0x1890, 0x1891,
9395
40.7k
      0x1892, 0x1893, 0x1894, 0x1895, 0x1896, 0x1897, 0x1898, 0x1899, 0x189a,
9396
40.7k
      0x189b, 0x189c, 0x189d, 0x189e, 0x189f, 0x18a0, 0x18a1, 0x18a2, 0x18a3,
9397
40.7k
      0x18a4, 0x18a5, 0x18a6, 0x18a7, 0x18a8, 0x18aa, 0xa840, 0xa841, 0xa842,
9398
40.7k
      0xa843, 0xa844, 0xa845, 0xa846, 0xa847, 0xa848, 0xa849, 0xa84a, 0xa84b,
9399
40.7k
      0xa84c, 0xa84d, 0xa84e, 0xa84f, 0xa850, 0xa851, 0xa852, 0xa853, 0xa854,
9400
40.7k
      0xa855, 0xa856, 0xa857, 0xa858, 0xa859, 0xa85a, 0xa85b, 0xa85c, 0xa85d,
9401
40.7k
      0xa85e, 0xa85f, 0xa860, 0xa861, 0xa862, 0xa863, 0xa864, 0xa865, 0xa866,
9402
40.7k
      0xa867, 0xa868, 0xa869, 0xa86a, 0xa86b, 0xa86c, 0xa86d, 0xa86e, 0xa86f,
9403
40.7k
      0xa870, 0xa871};
9404
9405
434k
  for (size_t i = 0; i < label.size(); i++) {
9406
396k
    uint32_t c = label[i];
9407
396k
    if (c == 0x200c) {
9408
1.43k
      if (i > 0) {
9409
1.43k
        if (std::binary_search(std::begin(virama), std::end(virama),
9410
1.43k
                               label[i - 1])) {
9411
300
          return true;
9412
300
        }
9413
1.43k
      }
9414
1.13k
      if ((i == 0) || (i + 1 >= label.size())) {
9415
146
        return false;
9416
146
      }
9417
      // we go backward looking for L or D
9418
1.77k
      auto is_l_or_d = [](uint32_t code) {
9419
1.77k
        return std::binary_search(std::begin(L), std::end(L), code) ||
9420
1.71k
               std::binary_search(std::begin(D), std::end(D), code);
9421
1.77k
      };
9422
1.99k
      auto is_r_or_d = [](uint32_t code) {
9423
1.99k
        return std::binary_search(std::begin(R), std::end(R), code) ||
9424
1.74k
               std::binary_search(std::begin(D), std::end(D), code);
9425
1.99k
      };
9426
992
      std::u32string_view before = label.substr(0, i);
9427
992
      std::u32string_view after = label.substr(i + 1);
9428
992
      return (std::find_if(before.begin(), before.end(), is_l_or_d) !=
9429
992
              before.end()) &&
9430
844
             (std::find_if(after.begin(), after.end(), is_r_or_d) !=
9431
844
              after.end());
9432
394k
    } else if (c == 0x200d) {
9433
526
      if (i > 0) {
9434
512
        if (std::binary_search(std::begin(virama), std::end(virama),
9435
512
                               label[i - 1])) {
9436
372
          return true;
9437
372
        }
9438
512
      }
9439
154
      return false;
9440
526
    }
9441
396k
  }
9442
9443
  // If CheckBidi, and if the domain name is a  Bidi domain name, then the label
9444
  // must satisfy all six of the numbered conditions in [IDNA2008] RFC 5893,
9445
  // Section 2.
9446
9447
  // The following rule, consisting of six conditions, applies to labels
9448
  // in Bidi domain names.  The requirements that this rule satisfies are
9449
  // described in Section 3.  All of the conditions must be satisfied for
9450
  // the rule to be satisfied.
9451
  //
9452
  //  1.  The first character must be a character with Bidi property L, R,
9453
  //     or AL.  If it has the R or AL property, it is an RTL label; if it
9454
  //     has the L property, it is an LTR label.
9455
  //
9456
  //  2.  In an RTL label, only characters with the Bidi properties R, AL,
9457
  //      AN, EN, ES, CS, ET, ON, BN, or NSM are allowed.
9458
  //
9459
  //   3.  In an RTL label, the end of the label must be a character with
9460
  //       Bidi property R, AL, EN, or AN, followed by zero or more
9461
  //       characters with Bidi property NSM.
9462
  //
9463
  //   4.  In an RTL label, if an EN is present, no AN may be present, and
9464
  //       vice versa.
9465
  //
9466
  //  5.  In an LTR label, only characters with the Bidi properties L, EN,
9467
  //       ES, CS, ET, ON, BN, or NSM are allowed.
9468
  //
9469
  //   6.  In an LTR label, the end of the label must be a character with
9470
  //       Bidi property L or EN, followed by zero or more characters with
9471
  //       Bidi property NSM.
9472
9473
38.8k
  size_t last_non_nsm_char = find_last_not_of_nsm(label);
9474
38.8k
  if (last_non_nsm_char == std::u32string_view::npos) {
9475
0
    return false;
9476
0
  }
9477
9478
  // A "Bidi domain name" is a domain name that contains at least one RTL label.
9479
  // The following rule, consisting of six conditions, applies to labels in Bidi
9480
  // domain names.
9481
38.8k
  if (is_rtl_label(label)) {
9482
    // The first character must be a character with Bidi property L, R,
9483
    // or AL. If it has the R or AL property, it is an RTL label; if it
9484
    // has the L property, it is an LTR label.
9485
9486
3.05k
    if (find_direction(label[0]) == direction::L) {
9487
      // Eval as LTR
9488
9489
      // In an LTR label, only characters with the Bidi properties L, EN,
9490
      // ES, CS, ET, ON, BN, or NSM are allowed.
9491
3.57k
      for (size_t i = 0; i < last_non_nsm_char; i++) {
9492
3.01k
        const direction d = find_direction(label[i]);
9493
3.01k
        if (!(d == direction::L || d == direction::EN || d == direction::ES ||
9494
1.30k
              d == direction::CS || d == direction::ET || d == direction::ON ||
9495
684
              d == direction::BN || d == direction::NSM)) {
9496
108
          return false;
9497
108
        }
9498
9499
2.90k
        if ((i == last_non_nsm_char) &&
9500
0
            !(d == direction::L || d == direction::EN)) {
9501
0
          return false;
9502
0
        }
9503
2.90k
      }
9504
9505
560
      return true;
9506
9507
2.38k
    } else {
9508
      // Eval as RTL
9509
9510
2.38k
      bool has_an = false;
9511
2.38k
      bool has_en = false;
9512
8.59k
      for (size_t i = 0; i <= last_non_nsm_char; i++) {
9513
6.57k
        const direction d = find_direction(label[i]);
9514
9515
        // NOLINTBEGIN(bugprone-assignment-in-if-condition)
9516
        // In an RTL label, if an EN is present, no AN may be present, and vice
9517
        // versa.
9518
6.57k
        if ((d == direction::EN && ((has_en = true) && has_an)) ||
9519
6.56k
            (d == direction::AN && ((has_an = true) && has_en))) {
9520
16
          return false;
9521
16
        }
9522
        // NOLINTEND(bugprone-assignment-in-if-condition)
9523
9524
6.55k
        if (!(d == direction::R || d == direction::AL || d == direction::AN ||
9525
2.59k
              d == direction::EN || d == direction::ES || d == direction::CS ||
9526
1.59k
              d == direction::ET || d == direction::ON || d == direction::BN ||
9527
812
              d == direction::NSM)) {
9528
258
          return false;
9529
258
        }
9530
9531
6.30k
        if (i == last_non_nsm_char &&
9532
2.11k
            !(d == direction::R || d == direction::AL || d == direction::AN ||
9533
308
              d == direction::EN)) {
9534
90
          return false;
9535
90
        }
9536
6.30k
      }
9537
9538
2.02k
      return true;
9539
2.38k
    }
9540
3.05k
  }
9541
9542
35.7k
  return true;
9543
38.8k
}
9544
9545
}  // namespace ada::idna
9546
/* end file src/validity.cpp */
9547
/* begin file src/to_ascii.cpp */
9548
9549
#include <algorithm>
9550
#include <cstdint>
9551
#include <ranges>
9552
9553
9554
#ifdef ADA_USE_SIMDUTF
9555
#include "simdutf.h"
9556
#endif
9557
9558
namespace ada::idna {
9559
9560
43.7k
bool constexpr is_ascii(std::u32string_view view) {
9561
70.9k
  for (uint32_t c : view) {
9562
70.9k
    if (c >= 0x80) {
9563
41.6k
      return false;
9564
41.6k
    }
9565
70.9k
  }
9566
2.06k
  return true;
9567
43.7k
}
9568
9569
18.1k
bool constexpr is_ascii(std::string_view view) {
9570
152k
  for (uint8_t c : view) {
9571
152k
    if (c >= 0x80) {
9572
11.2k
      return false;
9573
11.2k
    }
9574
152k
  }
9575
6.80k
  return true;
9576
18.1k
}
9577
9578
constexpr static uint8_t is_forbidden_domain_code_point_table[] = {
9579
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9580
    1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
9581
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
9582
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
9583
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9584
    0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9585
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9586
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9587
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9588
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9589
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
9590
9591
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
9592
9593
0
inline bool is_forbidden_domain_code_point(const char c) noexcept {
9594
0
  return is_forbidden_domain_code_point_table[uint8_t(c)];
9595
0
}
9596
9597
0
bool contains_forbidden_domain_code_point(std::string_view view) {
9598
0
  return std::ranges::any_of(view, is_forbidden_domain_code_point);
9599
0
}
9600
9601
// We return "" on error.
9602
6.80k
static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9603
6.80k
  static const std::string error = "";
9604
  // copy and map
9605
  // we could be more efficient by avoiding the copy when unnecessary.
9606
6.80k
  std::string mapped_string = std::string(ut8_string);
9607
6.80k
  ascii_map(mapped_string.data(), mapped_string.size());
9608
6.80k
  std::string out;
9609
6.80k
  size_t label_start = 0;
9610
9611
19.8k
  while (label_start != mapped_string.size()) {
9612
13.9k
    size_t loc_dot = mapped_string.find('.', label_start);
9613
13.9k
    bool is_last_label = (loc_dot == std::string_view::npos);
9614
13.9k
    size_t label_size = is_last_label ? mapped_string.size() - label_start
9615
13.9k
                                      : loc_dot - label_start;
9616
13.9k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9617
13.9k
    std::string_view label_view(mapped_string.data() + label_start, label_size);
9618
13.9k
    label_start += label_size_with_dot;
9619
13.9k
    if (label_size == 0) {
9620
      // empty label? Nothing to do.
9621
10.6k
    } else if (label_view.starts_with("xn--")) {
9622
      // The xn-- part is the expensive game.
9623
3.41k
      out.append(label_view);
9624
3.41k
      std::string_view puny_segment_ascii(
9625
3.41k
          out.data() + out.size() - label_view.size() + 4,
9626
3.41k
          label_view.size() - 4);
9627
3.41k
      std::u32string tmp_buffer;
9628
3.41k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9629
3.41k
      if (!is_ok) {
9630
260
        return error;
9631
260
      }
9632
      // If the input is just ASCII, it should not have been encoded
9633
      // as punycode.
9634
      // https://github.com/whatwg/url/issues/760
9635
3.15k
      if (is_ascii(tmp_buffer)) {
9636
152
        return error;
9637
152
      }
9638
2.99k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9639
2.99k
      if (tmp_buffer != post_map) {
9640
338
        return error;
9641
338
      }
9642
2.66k
      std::u32string pre_normal = post_map;
9643
2.66k
      normalize(post_map);
9644
2.66k
      if (post_map != pre_normal) {
9645
118
        return error;
9646
118
      }
9647
2.54k
      if (post_map.empty()) {
9648
0
        return error;
9649
0
      }
9650
2.54k
      if (!is_label_valid(post_map)) {
9651
18
        return error;
9652
18
      }
9653
7.21k
    } else {
9654
7.21k
      out.append(label_view);
9655
7.21k
    }
9656
13.0k
    if (!is_last_label) {
9657
7.50k
      out.push_back('.');
9658
7.50k
    }
9659
13.0k
  }
9660
5.92k
  return out;
9661
6.80k
}
9662
9663
// We return "" on error.
9664
18.1k
std::string to_ascii(std::string_view ut8_string) {
9665
18.1k
  if (is_ascii(ut8_string)) {
9666
6.80k
    return from_ascii_to_ascii(ut8_string);
9667
6.80k
  }
9668
11.2k
  static const std::string error = "";
9669
  // We convert to UTF-32
9670
9671
#ifdef ADA_USE_SIMDUTF
9672
  size_t utf32_length =
9673
      simdutf::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9674
  std::u32string utf32(utf32_length, '\0');
9675
  size_t actual_utf32_length = simdutf::convert_utf8_to_utf32(
9676
      ut8_string.data(), ut8_string.size(), utf32.data());
9677
#else
9678
11.2k
  size_t utf32_length =
9679
11.2k
      ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9680
11.2k
  std::u32string utf32(utf32_length, '\0');
9681
11.2k
  size_t actual_utf32_length = ada::idna::utf8_to_utf32(
9682
11.2k
      ut8_string.data(), ut8_string.size(), utf32.data());
9683
11.2k
#endif
9684
11.2k
  if (actual_utf32_length == 0) {
9685
2.40k
    return error;
9686
2.40k
  }
9687
  // mapping
9688
8.89k
  utf32 = ada::idna::map(utf32);
9689
8.89k
  normalize(utf32);
9690
8.89k
  std::string out;
9691
8.89k
  size_t label_start = 0;
9692
9693
49.1k
  while (label_start != utf32.size()) {
9694
42.0k
    size_t loc_dot = utf32.find('.', label_start);
9695
42.0k
    bool is_last_label = (loc_dot == std::string_view::npos);
9696
42.0k
    size_t label_size =
9697
42.0k
        is_last_label ? utf32.size() - label_start : loc_dot - label_start;
9698
42.0k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9699
42.0k
    std::u32string_view label_view(utf32.data() + label_start, label_size);
9700
42.0k
    label_start += label_size_with_dot;
9701
42.0k
    if (label_size == 0) {
9702
      // empty label? Nothing to do.
9703
40.7k
    } else if (label_view.starts_with(U"xn--")) {
9704
      // we do not need to check, e.g., Xn-- because mapping goes to lower case
9705
43.4k
      for (char32_t c : label_view) {
9706
43.4k
        if (c >= 0x80) {
9707
26
          return error;
9708
26
        }
9709
43.4k
        out += (unsigned char)(c);
9710
43.4k
      }
9711
2.37k
      std::string_view puny_segment_ascii(
9712
2.37k
          out.data() + out.size() - label_view.size() + 4,
9713
2.37k
          label_view.size() - 4);
9714
2.37k
      std::u32string tmp_buffer;
9715
2.37k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9716
2.37k
      if (!is_ok) {
9717
132
        return error;
9718
132
      }
9719
      // If the input is just ASCII, it should not have been encoded
9720
      // as punycode.
9721
      // https://github.com/whatwg/url/issues/760
9722
2.24k
      if (is_ascii(tmp_buffer)) {
9723
120
        return error;
9724
120
      }
9725
2.12k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9726
2.12k
      if (tmp_buffer != post_map) {
9727
212
        return error;
9728
212
      }
9729
1.91k
      std::u32string pre_normal = post_map;
9730
1.91k
      normalize(post_map);
9731
1.91k
      if (post_map != pre_normal) {
9732
92
        return error;
9733
92
      }
9734
1.82k
      if (post_map.empty()) {
9735
0
        return error;
9736
0
      }
9737
1.82k
      if (!is_label_valid(post_map)) {
9738
10
        return error;
9739
10
      }
9740
38.3k
    } else {
9741
      // The fast path here is an ascii label.
9742
38.3k
      if (is_ascii(label_view)) {
9743
        // no validation needed.
9744
17.9k
        for (char32_t c : label_view) {
9745
17.9k
          out += (unsigned char)(c);
9746
17.9k
        }
9747
36.5k
      } else {
9748
        // slow path.
9749
        // first check validity.
9750
36.5k
        if (!is_label_valid(label_view)) {
9751
1.25k
          return error;
9752
1.25k
        }
9753
        // It is valid! So now we must encode it as punycode...
9754
35.2k
        out.append("xn--");
9755
35.2k
        bool is_ok = ada::idna::utf32_to_punycode(label_view, out);
9756
35.2k
        if (!is_ok) {
9757
0
          return error;
9758
0
        }
9759
35.2k
      }
9760
38.3k
    }
9761
40.2k
    if (!is_last_label) {
9762
33.7k
      out.push_back('.');
9763
33.7k
    }
9764
40.2k
  }
9765
7.05k
  return out;
9766
8.89k
}
9767
}  // namespace ada::idna
9768
/* end file src/to_ascii.cpp */
9769
/* begin file src/to_unicode.cpp */
9770
9771
#include <algorithm>
9772
#include <string>
9773
9774
9775
#ifdef ADA_USE_SIMDUTF
9776
#include "simdutf.h"
9777
#endif
9778
9779
namespace ada::idna {
9780
0
std::string to_unicode(std::string_view input) {
9781
0
  std::string output;
9782
0
  output.reserve(input.size());
9783
9784
0
  size_t label_start = 0;
9785
0
  while (label_start < input.size()) {
9786
0
    size_t loc_dot = input.find('.', label_start);
9787
0
    bool is_last_label = (loc_dot == std::string_view::npos);
9788
0
    size_t label_size =
9789
0
        is_last_label ? input.size() - label_start : loc_dot - label_start;
9790
0
    auto label_view = std::string_view(input.data() + label_start, label_size);
9791
9792
0
    if (label_view.starts_with("xn--") && ada::idna::is_ascii(label_view)) {
9793
0
      label_view.remove_prefix(4);
9794
0
      if (ada::idna::verify_punycode(label_view)) {
9795
0
        std::u32string tmp_buffer;
9796
0
        if (ada::idna::punycode_to_utf32(label_view, tmp_buffer)) {
9797
#ifdef ADA_USE_SIMDUTF
9798
          auto utf8_size = simdutf::utf8_length_from_utf32(tmp_buffer.data(),
9799
                                                           tmp_buffer.size());
9800
          std::string final_utf8(utf8_size, '\0');
9801
          simdutf::convert_utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9802
                                         final_utf8.data());
9803
#else
9804
0
          auto utf8_size = ada::idna::utf8_length_from_utf32(tmp_buffer.data(),
9805
0
                                                             tmp_buffer.size());
9806
0
          std::string final_utf8(utf8_size, '\0');
9807
0
          ada::idna::utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9808
0
                                   final_utf8.data());
9809
0
#endif
9810
0
          output.append(final_utf8);
9811
0
        } else {
9812
          // ToUnicode never fails.  If any step fails, then the original input
9813
          // sequence is returned immediately in that step.
9814
0
          output.append(
9815
0
              std::string_view(input.data() + label_start, label_size));
9816
0
        }
9817
0
      } else {
9818
0
        output.append(std::string_view(input.data() + label_start, label_size));
9819
0
      }
9820
0
    } else {
9821
0
      output.append(label_view);
9822
0
    }
9823
9824
0
    if (!is_last_label) {
9825
0
      output.push_back('.');
9826
0
    }
9827
9828
0
    label_start += label_size + 1;
9829
0
  }
9830
9831
0
  return output;
9832
0
}
9833
}  // namespace ada::idna
9834
/* end file src/to_unicode.cpp */
9835
/* begin file src/identifier.cpp */
9836
9837
#include <algorithm>
9838
#include <array>
9839
#include <string>
9840
9841
/* begin file src/id_tables.cpp */
9842
// IDNA  16.0.0
9843
9844
// clang-format off
9845
#ifndef ADA_IDNA_IDENTIFIER_TABLES_H
9846
#define ADA_IDNA_IDENTIFIER_TABLES_H
9847
#include <cstdint>
9848
9849
namespace ada::idna {
9850
9851
const uint32_t id_continue[1393][2] =
9852
{
9853
  {48, 57}, {65, 90}, {95, 95}, {97, 122},
9854
  {170, 170}, {181, 181}, {183, 183}, {186, 186},
9855
  {192, 214}, {216, 246}, {248, 442}, {443, 443},
9856
  {444, 447}, {448, 451}, {452, 659}, {660, 660},
9857
  {661, 687}, {688, 705}, {710, 721}, {736, 740},
9858
  {748, 748}, {750, 750}, {768, 879}, {880, 883},
9859
  {884, 884}, {886, 887}, {890, 890}, {891, 893},
9860
  {895, 895}, {902, 902}, {903, 903}, {904, 906},
9861
  {908, 908}, {910, 929}, {931, 1013}, {1015, 1153},
9862
  {1155, 1159}, {1162, 1327}, {1329, 1366}, {1369, 1369},
9863
  {1376, 1416}, {1425, 1469}, {1471, 1471}, {1473, 1474},
9864
  {1476, 1477}, {1479, 1479}, {1488, 1514}, {1519, 1522},
9865
  {1552, 1562}, {1568, 1599}, {1600, 1600}, {1601, 1610},
9866
  {1611, 1631}, {1632, 1641}, {1646, 1647}, {1648, 1648},
9867
  {1649, 1747}, {1749, 1749}, {1750, 1756}, {1759, 1764},
9868
  {1765, 1766}, {1767, 1768}, {1770, 1773}, {1774, 1775},
9869
  {1776, 1785}, {1786, 1788}, {1791, 1791}, {1808, 1808},
9870
  {1809, 1809}, {1810, 1839}, {1840, 1866}, {1869, 1957},
9871
  {1958, 1968}, {1969, 1969}, {1984, 1993}, {1994, 2026},
9872
  {2027, 2035}, {2036, 2037}, {2042, 2042}, {2045, 2045},
9873
  {2048, 2069}, {2070, 2073}, {2074, 2074}, {2075, 2083},
9874
  {2084, 2084}, {2085, 2087}, {2088, 2088}, {2089, 2093},
9875
  {2112, 2136}, {2137, 2139}, {2144, 2154}, {2160, 2183},
9876
  {2185, 2190}, {2199, 2207}, {2208, 2248}, {2249, 2249},
9877
  {2250, 2273}, {2275, 2306}, {2307, 2307}, {2308, 2361},
9878
  {2362, 2362}, {2363, 2363}, {2364, 2364}, {2365, 2365},
9879
  {2366, 2368}, {2369, 2376}, {2377, 2380}, {2381, 2381},
9880
  {2382, 2383}, {2384, 2384}, {2385, 2391}, {2392, 2401},
9881
  {2402, 2403}, {2406, 2415}, {2417, 2417}, {2418, 2432},
9882
  {2433, 2433}, {2434, 2435}, {2437, 2444}, {2447, 2448},
9883
  {2451, 2472}, {2474, 2480}, {2482, 2482}, {2486, 2489},
9884
  {2492, 2492}, {2493, 2493}, {2494, 2496}, {2497, 2500},
9885
  {2503, 2504}, {2507, 2508}, {2509, 2509}, {2510, 2510},
9886
  {2519, 2519}, {2524, 2525}, {2527, 2529}, {2530, 2531},
9887
  {2534, 2543}, {2544, 2545}, {2556, 2556}, {2558, 2558},
9888
  {2561, 2562}, {2563, 2563}, {2565, 2570}, {2575, 2576},
9889
  {2579, 2600}, {2602, 2608}, {2610, 2611}, {2613, 2614},
9890
  {2616, 2617}, {2620, 2620}, {2622, 2624}, {2625, 2626},
9891
  {2631, 2632}, {2635, 2637}, {2641, 2641}, {2649, 2652},
9892
  {2654, 2654}, {2662, 2671}, {2672, 2673}, {2674, 2676},
9893
  {2677, 2677}, {2689, 2690}, {2691, 2691}, {2693, 2701},
9894
  {2703, 2705}, {2707, 2728}, {2730, 2736}, {2738, 2739},
9895
  {2741, 2745}, {2748, 2748}, {2749, 2749}, {2750, 2752},
9896
  {2753, 2757}, {2759, 2760}, {2761, 2761}, {2763, 2764},
9897
  {2765, 2765}, {2768, 2768}, {2784, 2785}, {2786, 2787},
9898
  {2790, 2799}, {2809, 2809}, {2810, 2815}, {2817, 2817},
9899
  {2818, 2819}, {2821, 2828}, {2831, 2832}, {2835, 2856},
9900
  {2858, 2864}, {2866, 2867}, {2869, 2873}, {2876, 2876},
9901
  {2877, 2877}, {2878, 2878}, {2879, 2879}, {2880, 2880},
9902
  {2881, 2884}, {2887, 2888}, {2891, 2892}, {2893, 2893},
9903
  {2901, 2902}, {2903, 2903}, {2908, 2909}, {2911, 2913},
9904
  {2914, 2915}, {2918, 2927}, {2929, 2929}, {2946, 2946},
9905
  {2947, 2947}, {2949, 2954}, {2958, 2960}, {2962, 2965},
9906
  {2969, 2970}, {2972, 2972}, {2974, 2975}, {2979, 2980},
9907
  {2984, 2986}, {2990, 3001}, {3006, 3007}, {3008, 3008},
9908
  {3009, 3010}, {3014, 3016}, {3018, 3020}, {3021, 3021},
9909
  {3024, 3024}, {3031, 3031}, {3046, 3055}, {3072, 3072},
9910
  {3073, 3075}, {3076, 3076}, {3077, 3084}, {3086, 3088},
9911
  {3090, 3112}, {3114, 3129}, {3132, 3132}, {3133, 3133},
9912
  {3134, 3136}, {3137, 3140}, {3142, 3144}, {3146, 3149},
9913
  {3157, 3158}, {3160, 3162}, {3165, 3165}, {3168, 3169},
9914
  {3170, 3171}, {3174, 3183}, {3200, 3200}, {3201, 3201},
9915
  {3202, 3203}, {3205, 3212}, {3214, 3216}, {3218, 3240},
9916
  {3242, 3251}, {3253, 3257}, {3260, 3260}, {3261, 3261},
9917
  {3262, 3262}, {3263, 3263}, {3264, 3268}, {3270, 3270},
9918
  {3271, 3272}, {3274, 3275}, {3276, 3277}, {3285, 3286},
9919
  {3293, 3294}, {3296, 3297}, {3298, 3299}, {3302, 3311},
9920
  {3313, 3314}, {3315, 3315}, {3328, 3329}, {3330, 3331},
9921
  {3332, 3340}, {3342, 3344}, {3346, 3386}, {3387, 3388},
9922
  {3389, 3389}, {3390, 3392}, {3393, 3396}, {3398, 3400},
9923
  {3402, 3404}, {3405, 3405}, {3406, 3406}, {3412, 3414},
9924
  {3415, 3415}, {3423, 3425}, {3426, 3427}, {3430, 3439},
9925
  {3450, 3455}, {3457, 3457}, {3458, 3459}, {3461, 3478},
9926
  {3482, 3505}, {3507, 3515}, {3517, 3517}, {3520, 3526},
9927
  {3530, 3530}, {3535, 3537}, {3538, 3540}, {3542, 3542},
9928
  {3544, 3551}, {3558, 3567}, {3570, 3571}, {3585, 3632},
9929
  {3633, 3633}, {3634, 3635}, {3636, 3642}, {3648, 3653},
9930
  {3654, 3654}, {3655, 3662}, {3664, 3673}, {3713, 3714},
9931
  {3716, 3716}, {3718, 3722}, {3724, 3747}, {3749, 3749},
9932
  {3751, 3760}, {3761, 3761}, {3762, 3763}, {3764, 3772},
9933
  {3773, 3773}, {3776, 3780}, {3782, 3782}, {3784, 3790},
9934
  {3792, 3801}, {3804, 3807}, {3840, 3840}, {3864, 3865},
9935
  {3872, 3881}, {3893, 3893}, {3895, 3895}, {3897, 3897},
9936
  {3902, 3903}, {3904, 3911}, {3913, 3948}, {3953, 3966},
9937
  {3967, 3967}, {3968, 3972}, {3974, 3975}, {3976, 3980},
9938
  {3981, 3991}, {3993, 4028}, {4038, 4038}, {4096, 4138},
9939
  {4139, 4140}, {4141, 4144}, {4145, 4145}, {4146, 4151},
9940
  {4152, 4152}, {4153, 4154}, {4155, 4156}, {4157, 4158},
9941
  {4159, 4159}, {4160, 4169}, {4176, 4181}, {4182, 4183},
9942
  {4184, 4185}, {4186, 4189}, {4190, 4192}, {4193, 4193},
9943
  {4194, 4196}, {4197, 4198}, {4199, 4205}, {4206, 4208},
9944
  {4209, 4212}, {4213, 4225}, {4226, 4226}, {4227, 4228},
9945
  {4229, 4230}, {4231, 4236}, {4237, 4237}, {4238, 4238},
9946
  {4239, 4239}, {4240, 4249}, {4250, 4252}, {4253, 4253},
9947
  {4256, 4293}, {4295, 4295}, {4301, 4301}, {4304, 4346},
9948
  {4348, 4348}, {4349, 4351}, {4352, 4680}, {4682, 4685},
9949
  {4688, 4694}, {4696, 4696}, {4698, 4701}, {4704, 4744},
9950
  {4746, 4749}, {4752, 4784}, {4786, 4789}, {4792, 4798},
9951
  {4800, 4800}, {4802, 4805}, {4808, 4822}, {4824, 4880},
9952
  {4882, 4885}, {4888, 4954}, {4957, 4959}, {4969, 4977},
9953
  {4992, 5007}, {5024, 5109}, {5112, 5117}, {5121, 5740},
9954
  {5743, 5759}, {5761, 5786}, {5792, 5866}, {5870, 5872},
9955
  {5873, 5880}, {5888, 5905}, {5906, 5908}, {5909, 5909},
9956
  {5919, 5937}, {5938, 5939}, {5940, 5940}, {5952, 5969},
9957
  {5970, 5971}, {5984, 5996}, {5998, 6000}, {6002, 6003},
9958
  {6016, 6067}, {6068, 6069}, {6070, 6070}, {6071, 6077},
9959
  {6078, 6085}, {6086, 6086}, {6087, 6088}, {6089, 6099},
9960
  {6103, 6103}, {6108, 6108}, {6109, 6109}, {6112, 6121},
9961
  {6155, 6157}, {6159, 6159}, {6160, 6169}, {6176, 6210},
9962
  {6211, 6211}, {6212, 6264}, {6272, 6276}, {6277, 6278},
9963
  {6279, 6312}, {6313, 6313}, {6314, 6314}, {6320, 6389},
9964
  {6400, 6430}, {6432, 6434}, {6435, 6438}, {6439, 6440},
9965
  {6441, 6443}, {6448, 6449}, {6450, 6450}, {6451, 6456},
9966
  {6457, 6459}, {6470, 6479}, {6480, 6509}, {6512, 6516},
9967
  {6528, 6571}, {6576, 6601}, {6608, 6617}, {6618, 6618},
9968
  {6656, 6678}, {6679, 6680}, {6681, 6682}, {6683, 6683},
9969
  {6688, 6740}, {6741, 6741}, {6742, 6742}, {6743, 6743},
9970
  {6744, 6750}, {6752, 6752}, {6753, 6753}, {6754, 6754},
9971
  {6755, 6756}, {6757, 6764}, {6765, 6770}, {6771, 6780},
9972
  {6783, 6783}, {6784, 6793}, {6800, 6809}, {6823, 6823},
9973
  {6832, 6845}, {6847, 6862}, {6912, 6915}, {6916, 6916},
9974
  {6917, 6963}, {6964, 6964}, {6965, 6965}, {6966, 6970},
9975
  {6971, 6971}, {6972, 6972}, {6973, 6977}, {6978, 6978},
9976
  {6979, 6980}, {6981, 6988}, {6992, 7001}, {7019, 7027},
9977
  {7040, 7041}, {7042, 7042}, {7043, 7072}, {7073, 7073},
9978
  {7074, 7077}, {7078, 7079}, {7080, 7081}, {7082, 7082},
9979
  {7083, 7085}, {7086, 7087}, {7088, 7097}, {7098, 7141},
9980
  {7142, 7142}, {7143, 7143}, {7144, 7145}, {7146, 7148},
9981
  {7149, 7149}, {7150, 7150}, {7151, 7153}, {7154, 7155},
9982
  {7168, 7203}, {7204, 7211}, {7212, 7219}, {7220, 7221},
9983
  {7222, 7223}, {7232, 7241}, {7245, 7247}, {7248, 7257},
9984
  {7258, 7287}, {7288, 7293}, {7296, 7306}, {7312, 7354},
9985
  {7357, 7359}, {7376, 7378}, {7380, 7392}, {7393, 7393},
9986
  {7394, 7400}, {7401, 7404}, {7405, 7405}, {7406, 7411},
9987
  {7412, 7412}, {7413, 7414}, {7415, 7415}, {7416, 7417},
9988
  {7418, 7418}, {7424, 7467}, {7468, 7530}, {7531, 7543},
9989
  {7544, 7544}, {7545, 7578}, {7579, 7615}, {7616, 7679},
9990
  {7680, 7957}, {7960, 7965}, {7968, 8005}, {8008, 8013},
9991
  {8016, 8023}, {8025, 8025}, {8027, 8027}, {8029, 8029},
9992
  {8031, 8061}, {8064, 8116}, {8118, 8124}, {8126, 8126},
9993
  {8130, 8132}, {8134, 8140}, {8144, 8147}, {8150, 8155},
9994
  {8160, 8172}, {8178, 8180}, {8182, 8188}, {8204, 8205},
9995
  {8255, 8256}, {8276, 8276}, {8305, 8305}, {8319, 8319},
9996
  {8336, 8348}, {8400, 8412}, {8417, 8417}, {8421, 8432},
9997
  {8450, 8450}, {8455, 8455}, {8458, 8467}, {8469, 8469},
9998
  {8472, 8472}, {8473, 8477}, {8484, 8484}, {8486, 8486},
9999
  {8488, 8488}, {8490, 8493}, {8494, 8494}, {8495, 8500},
10000
  {8501, 8504}, {8505, 8505}, {8508, 8511}, {8517, 8521},
10001
  {8526, 8526}, {8544, 8578}, {8579, 8580}, {8581, 8584},
10002
  {11264, 11387}, {11388, 11389}, {11390, 11492}, {11499, 11502},
10003
  {11503, 11505}, {11506, 11507}, {11520, 11557}, {11559, 11559},
10004
  {11565, 11565}, {11568, 11623}, {11631, 11631}, {11647, 11647},
10005
  {11648, 11670}, {11680, 11686}, {11688, 11694}, {11696, 11702},
10006
  {11704, 11710}, {11712, 11718}, {11720, 11726}, {11728, 11734},
10007
  {11736, 11742}, {11744, 11775}, {12293, 12293}, {12294, 12294},
10008
  {12295, 12295}, {12321, 12329}, {12330, 12333}, {12334, 12335},
10009
  {12337, 12341}, {12344, 12346}, {12347, 12347}, {12348, 12348},
10010
  {12353, 12438}, {12441, 12442}, {12443, 12444}, {12445, 12446},
10011
  {12447, 12447}, {12449, 12538}, {12539, 12539}, {12540, 12542},
10012
  {12543, 12543}, {12549, 12591}, {12593, 12686}, {12704, 12735},
10013
  {12784, 12799}, {13312, 19903}, {19968, 40980}, {40981, 40981},
10014
  {40982, 42124}, {42192, 42231}, {42232, 42237}, {42240, 42507},
10015
  {42508, 42508}, {42512, 42527}, {42528, 42537}, {42538, 42539},
10016
  {42560, 42605}, {42606, 42606}, {42607, 42607}, {42612, 42621},
10017
  {42623, 42623}, {42624, 42651}, {42652, 42653}, {42654, 42655},
10018
  {42656, 42725}, {42726, 42735}, {42736, 42737}, {42775, 42783},
10019
  {42786, 42863}, {42864, 42864}, {42865, 42887}, {42888, 42888},
10020
  {42891, 42894}, {42895, 42895}, {42896, 42957}, {42960, 42961},
10021
  {42963, 42963}, {42965, 42972}, {42994, 42996}, {42997, 42998},
10022
  {42999, 42999}, {43000, 43001}, {43002, 43002}, {43003, 43009},
10023
  {43010, 43010}, {43011, 43013}, {43014, 43014}, {43015, 43018},
10024
  {43019, 43019}, {43020, 43042}, {43043, 43044}, {43045, 43046},
10025
  {43047, 43047}, {43052, 43052}, {43072, 43123}, {43136, 43137},
10026
  {43138, 43187}, {43188, 43203}, {43204, 43205}, {43216, 43225},
10027
  {43232, 43249}, {43250, 43255}, {43259, 43259}, {43261, 43262},
10028
  {43263, 43263}, {43264, 43273}, {43274, 43301}, {43302, 43309},
10029
  {43312, 43334}, {43335, 43345}, {43346, 43347}, {43360, 43388},
10030
  {43392, 43394}, {43395, 43395}, {43396, 43442}, {43443, 43443},
10031
  {43444, 43445}, {43446, 43449}, {43450, 43451}, {43452, 43453},
10032
  {43454, 43456}, {43471, 43471}, {43472, 43481}, {43488, 43492},
10033
  {43493, 43493}, {43494, 43494}, {43495, 43503}, {43504, 43513},
10034
  {43514, 43518}, {43520, 43560}, {43561, 43566}, {43567, 43568},
10035
  {43569, 43570}, {43571, 43572}, {43573, 43574}, {43584, 43586},
10036
  {43587, 43587}, {43588, 43595}, {43596, 43596}, {43597, 43597},
10037
  {43600, 43609}, {43616, 43631}, {43632, 43632}, {43633, 43638},
10038
  {43642, 43642}, {43643, 43643}, {43644, 43644}, {43645, 43645},
10039
  {43646, 43695}, {43696, 43696}, {43697, 43697}, {43698, 43700},
10040
  {43701, 43702}, {43703, 43704}, {43705, 43709}, {43710, 43711},
10041
  {43712, 43712}, {43713, 43713}, {43714, 43714}, {43739, 43740},
10042
  {43741, 43741}, {43744, 43754}, {43755, 43755}, {43756, 43757},
10043
  {43758, 43759}, {43762, 43762}, {43763, 43764}, {43765, 43765},
10044
  {43766, 43766}, {43777, 43782}, {43785, 43790}, {43793, 43798},
10045
  {43808, 43814}, {43816, 43822}, {43824, 43866}, {43868, 43871},
10046
  {43872, 43880}, {43881, 43881}, {43888, 43967}, {43968, 44002},
10047
  {44003, 44004}, {44005, 44005}, {44006, 44007}, {44008, 44008},
10048
  {44009, 44010}, {44012, 44012}, {44013, 44013}, {44016, 44025},
10049
  {44032, 55203}, {55216, 55238}, {55243, 55291}, {63744, 64109},
10050
  {64112, 64217}, {64256, 64262}, {64275, 64279}, {64285, 64285},
10051
  {64286, 64286}, {64287, 64296}, {64298, 64310}, {64312, 64316},
10052
  {64318, 64318}, {64320, 64321}, {64323, 64324}, {64326, 64433},
10053
  {64467, 64829}, {64848, 64911}, {64914, 64967}, {65008, 65019},
10054
  {65024, 65039}, {65056, 65071}, {65075, 65076}, {65101, 65103},
10055
  {65136, 65140}, {65142, 65276}, {65296, 65305}, {65313, 65338},
10056
  {65343, 65343}, {65345, 65370}, {65381, 65381}, {65382, 65391},
10057
  {65392, 65392}, {65393, 65437}, {65438, 65439}, {65440, 65470},
10058
  {65474, 65479}, {65482, 65487}, {65490, 65495}, {65498, 65500},
10059
  {65536, 65547}, {65549, 65574}, {65576, 65594}, {65596, 65597},
10060
  {65599, 65613}, {65616, 65629}, {65664, 65786}, {65856, 65908},
10061
  {66045, 66045}, {66176, 66204}, {66208, 66256}, {66272, 66272},
10062
  {66304, 66335}, {66349, 66368}, {66369, 66369}, {66370, 66377},
10063
  {66378, 66378}, {66384, 66421}, {66422, 66426}, {66432, 66461},
10064
  {66464, 66499}, {66504, 66511}, {66513, 66517}, {66560, 66639},
10065
  {66640, 66717}, {66720, 66729}, {66736, 66771}, {66776, 66811},
10066
  {66816, 66855}, {66864, 66915}, {66928, 66938}, {66940, 66954},
10067
  {66956, 66962}, {66964, 66965}, {66967, 66977}, {66979, 66993},
10068
  {66995, 67001}, {67003, 67004}, {67008, 67059}, {67072, 67382},
10069
  {67392, 67413}, {67424, 67431}, {67456, 67461}, {67463, 67504},
10070
  {67506, 67514}, {67584, 67589}, {67592, 67592}, {67594, 67637},
10071
  {67639, 67640}, {67644, 67644}, {67647, 67669}, {67680, 67702},
10072
  {67712, 67742}, {67808, 67826}, {67828, 67829}, {67840, 67861},
10073
  {67872, 67897}, {67968, 68023}, {68030, 68031}, {68096, 68096},
10074
  {68097, 68099}, {68101, 68102}, {68108, 68111}, {68112, 68115},
10075
  {68117, 68119}, {68121, 68149}, {68152, 68154}, {68159, 68159},
10076
  {68192, 68220}, {68224, 68252}, {68288, 68295}, {68297, 68324},
10077
  {68325, 68326}, {68352, 68405}, {68416, 68437}, {68448, 68466},
10078
  {68480, 68497}, {68608, 68680}, {68736, 68786}, {68800, 68850},
10079
  {68864, 68899}, {68900, 68903}, {68912, 68921}, {68928, 68937},
10080
  {68938, 68941}, {68942, 68942}, {68943, 68943}, {68944, 68965},
10081
  {68969, 68973}, {68975, 68975}, {68976, 68997}, {69248, 69289},
10082
  {69291, 69292}, {69296, 69297}, {69314, 69316}, {69372, 69375},
10083
  {69376, 69404}, {69415, 69415}, {69424, 69445}, {69446, 69456},
10084
  {69488, 69505}, {69506, 69509}, {69552, 69572}, {69600, 69622},
10085
  {69632, 69632}, {69633, 69633}, {69634, 69634}, {69635, 69687},
10086
  {69688, 69702}, {69734, 69743}, {69744, 69744}, {69745, 69746},
10087
  {69747, 69748}, {69749, 69749}, {69759, 69761}, {69762, 69762},
10088
  {69763, 69807}, {69808, 69810}, {69811, 69814}, {69815, 69816},
10089
  {69817, 69818}, {69826, 69826}, {69840, 69864}, {69872, 69881},
10090
  {69888, 69890}, {69891, 69926}, {69927, 69931}, {69932, 69932},
10091
  {69933, 69940}, {69942, 69951}, {69956, 69956}, {69957, 69958},
10092
  {69959, 69959}, {69968, 70002}, {70003, 70003}, {70006, 70006},
10093
  {70016, 70017}, {70018, 70018}, {70019, 70066}, {70067, 70069},
10094
  {70070, 70078}, {70079, 70080}, {70081, 70084}, {70089, 70092},
10095
  {70094, 70094}, {70095, 70095}, {70096, 70105}, {70106, 70106},
10096
  {70108, 70108}, {70144, 70161}, {70163, 70187}, {70188, 70190},
10097
  {70191, 70193}, {70194, 70195}, {70196, 70196}, {70197, 70197},
10098
  {70198, 70199}, {70206, 70206}, {70207, 70208}, {70209, 70209},
10099
  {70272, 70278}, {70280, 70280}, {70282, 70285}, {70287, 70301},
10100
  {70303, 70312}, {70320, 70366}, {70367, 70367}, {70368, 70370},
10101
  {70371, 70378}, {70384, 70393}, {70400, 70401}, {70402, 70403},
10102
  {70405, 70412}, {70415, 70416}, {70419, 70440}, {70442, 70448},
10103
  {70450, 70451}, {70453, 70457}, {70459, 70460}, {70461, 70461},
10104
  {70462, 70463}, {70464, 70464}, {70465, 70468}, {70471, 70472},
10105
  {70475, 70477}, {70480, 70480}, {70487, 70487}, {70493, 70497},
10106
  {70498, 70499}, {70502, 70508}, {70512, 70516}, {70528, 70537},
10107
  {70539, 70539}, {70542, 70542}, {70544, 70581}, {70583, 70583},
10108
  {70584, 70586}, {70587, 70592}, {70594, 70594}, {70597, 70597},
10109
  {70599, 70602}, {70604, 70605}, {70606, 70606}, {70607, 70607},
10110
  {70608, 70608}, {70609, 70609}, {70610, 70610}, {70611, 70611},
10111
  {70625, 70626}, {70656, 70708}, {70709, 70711}, {70712, 70719},
10112
  {70720, 70721}, {70722, 70724}, {70725, 70725}, {70726, 70726},
10113
  {70727, 70730}, {70736, 70745}, {70750, 70750}, {70751, 70753},
10114
  {70784, 70831}, {70832, 70834}, {70835, 70840}, {70841, 70841},
10115
  {70842, 70842}, {70843, 70846}, {70847, 70848}, {70849, 70849},
10116
  {70850, 70851}, {70852, 70853}, {70855, 70855}, {70864, 70873},
10117
  {71040, 71086}, {71087, 71089}, {71090, 71093}, {71096, 71099},
10118
  {71100, 71101}, {71102, 71102}, {71103, 71104}, {71128, 71131},
10119
  {71132, 71133}, {71168, 71215}, {71216, 71218}, {71219, 71226},
10120
  {71227, 71228}, {71229, 71229}, {71230, 71230}, {71231, 71232},
10121
  {71236, 71236}, {71248, 71257}, {71296, 71338}, {71339, 71339},
10122
  {71340, 71340}, {71341, 71341}, {71342, 71343}, {71344, 71349},
10123
  {71350, 71350}, {71351, 71351}, {71352, 71352}, {71360, 71369},
10124
  {71376, 71395}, {71424, 71450}, {71453, 71453}, {71454, 71454},
10125
  {71455, 71455}, {71456, 71457}, {71458, 71461}, {71462, 71462},
10126
  {71463, 71467}, {71472, 71481}, {71488, 71494}, {71680, 71723},
10127
  {71724, 71726}, {71727, 71735}, {71736, 71736}, {71737, 71738},
10128
  {71840, 71903}, {71904, 71913}, {71935, 71942}, {71945, 71945},
10129
  {71948, 71955}, {71957, 71958}, {71960, 71983}, {71984, 71989},
10130
  {71991, 71992}, {71995, 71996}, {71997, 71997}, {71998, 71998},
10131
  {71999, 71999}, {72000, 72000}, {72001, 72001}, {72002, 72002},
10132
  {72003, 72003}, {72016, 72025}, {72096, 72103}, {72106, 72144},
10133
  {72145, 72147}, {72148, 72151}, {72154, 72155}, {72156, 72159},
10134
  {72160, 72160}, {72161, 72161}, {72163, 72163}, {72164, 72164},
10135
  {72192, 72192}, {72193, 72202}, {72203, 72242}, {72243, 72248},
10136
  {72249, 72249}, {72250, 72250}, {72251, 72254}, {72263, 72263},
10137
  {72272, 72272}, {72273, 72278}, {72279, 72280}, {72281, 72283},
10138
  {72284, 72329}, {72330, 72342}, {72343, 72343}, {72344, 72345},
10139
  {72349, 72349}, {72368, 72440}, {72640, 72672}, {72688, 72697},
10140
  {72704, 72712}, {72714, 72750}, {72751, 72751}, {72752, 72758},
10141
  {72760, 72765}, {72766, 72766}, {72767, 72767}, {72768, 72768},
10142
  {72784, 72793}, {72818, 72847}, {72850, 72871}, {72873, 72873},
10143
  {72874, 72880}, {72881, 72881}, {72882, 72883}, {72884, 72884},
10144
  {72885, 72886}, {72960, 72966}, {72968, 72969}, {72971, 73008},
10145
  {73009, 73014}, {73018, 73018}, {73020, 73021}, {73023, 73029},
10146
  {73030, 73030}, {73031, 73031}, {73040, 73049}, {73056, 73061},
10147
  {73063, 73064}, {73066, 73097}, {73098, 73102}, {73104, 73105},
10148
  {73107, 73108}, {73109, 73109}, {73110, 73110}, {73111, 73111},
10149
  {73112, 73112}, {73120, 73129}, {73440, 73458}, {73459, 73460},
10150
  {73461, 73462}, {73472, 73473}, {73474, 73474}, {73475, 73475},
10151
  {73476, 73488}, {73490, 73523}, {73524, 73525}, {73526, 73530},
10152
  {73534, 73535}, {73536, 73536}, {73537, 73537}, {73538, 73538},
10153
  {73552, 73561}, {73562, 73562}, {73648, 73648}, {73728, 74649},
10154
  {74752, 74862}, {74880, 75075}, {77712, 77808}, {77824, 78895},
10155
  {78912, 78912}, {78913, 78918}, {78919, 78933}, {78944, 82938},
10156
  {82944, 83526}, {90368, 90397}, {90398, 90409}, {90410, 90412},
10157
  {90413, 90415}, {90416, 90425}, {92160, 92728}, {92736, 92766},
10158
  {92768, 92777}, {92784, 92862}, {92864, 92873}, {92880, 92909},
10159
  {92912, 92916}, {92928, 92975}, {92976, 92982}, {92992, 92995},
10160
  {93008, 93017}, {93027, 93047}, {93053, 93071}, {93504, 93506},
10161
  {93507, 93546}, {93547, 93548}, {93552, 93561}, {93760, 93823},
10162
  {93952, 94026}, {94031, 94031}, {94032, 94032}, {94033, 94087},
10163
  {94095, 94098}, {94099, 94111}, {94176, 94177}, {94179, 94179},
10164
  {94180, 94180}, {94192, 94193}, {94208, 100343}, {100352, 101589},
10165
  {101631, 101640}, {110576, 110579}, {110581, 110587}, {110589, 110590},
10166
  {110592, 110882}, {110898, 110898}, {110928, 110930}, {110933, 110933},
10167
  {110948, 110951}, {110960, 111355}, {113664, 113770}, {113776, 113788},
10168
  {113792, 113800}, {113808, 113817}, {113821, 113822}, {118000, 118009},
10169
  {118528, 118573}, {118576, 118598}, {119141, 119142}, {119143, 119145},
10170
  {119149, 119154}, {119163, 119170}, {119173, 119179}, {119210, 119213},
10171
  {119362, 119364}, {119808, 119892}, {119894, 119964}, {119966, 119967},
10172
  {119970, 119970}, {119973, 119974}, {119977, 119980}, {119982, 119993},
10173
  {119995, 119995}, {119997, 120003}, {120005, 120069}, {120071, 120074},
10174
  {120077, 120084}, {120086, 120092}, {120094, 120121}, {120123, 120126},
10175
  {120128, 120132}, {120134, 120134}, {120138, 120144}, {120146, 120485},
10176
  {120488, 120512}, {120514, 120538}, {120540, 120570}, {120572, 120596},
10177
  {120598, 120628}, {120630, 120654}, {120656, 120686}, {120688, 120712},
10178
  {120714, 120744}, {120746, 120770}, {120772, 120779}, {120782, 120831},
10179
  {121344, 121398}, {121403, 121452}, {121461, 121461}, {121476, 121476},
10180
  {121499, 121503}, {121505, 121519}, {122624, 122633}, {122634, 122634},
10181
  {122635, 122654}, {122661, 122666}, {122880, 122886}, {122888, 122904},
10182
  {122907, 122913}, {122915, 122916}, {122918, 122922}, {122928, 122989},
10183
  {123023, 123023}, {123136, 123180}, {123184, 123190}, {123191, 123197},
10184
  {123200, 123209}, {123214, 123214}, {123536, 123565}, {123566, 123566},
10185
  {123584, 123627}, {123628, 123631}, {123632, 123641}, {124112, 124138},
10186
  {124139, 124139}, {124140, 124143}, {124144, 124153}, {124368, 124397},
10187
  {124398, 124399}, {124400, 124400}, {124401, 124410}, {124896, 124902},
10188
  {124904, 124907}, {124909, 124910}, {124912, 124926}, {124928, 125124},
10189
  {125136, 125142}, {125184, 125251}, {125252, 125258}, {125259, 125259},
10190
  {125264, 125273}, {126464, 126467}, {126469, 126495}, {126497, 126498},
10191
  {126500, 126500}, {126503, 126503}, {126505, 126514}, {126516, 126519},
10192
  {126521, 126521}, {126523, 126523}, {126530, 126530}, {126535, 126535},
10193
  {126537, 126537}, {126539, 126539}, {126541, 126543}, {126545, 126546},
10194
  {126548, 126548}, {126551, 126551}, {126553, 126553}, {126555, 126555},
10195
  {126557, 126557}, {126559, 126559}, {126561, 126562}, {126564, 126564},
10196
  {126567, 126570}, {126572, 126578}, {126580, 126583}, {126585, 126588},
10197
  {126590, 126590}, {126592, 126601}, {126603, 126619}, {126625, 126627},
10198
  {126629, 126633}, {126635, 126651}, {130032, 130041}, {131072, 173791},
10199
  {173824, 177977}, {177984, 178205}, {178208, 183969}, {183984, 191456},
10200
  {191472, 192093}, {194560, 195101}, {196608, 201546}, {201552, 205743},
10201
  {917760, 917999}
10202
};
10203
const uint32_t id_start[763][2] =
10204
{
10205
  {65, 90}, {97, 122}, {170, 170}, {181, 181},
10206
  {186, 186}, {192, 214}, {216, 246}, {248, 442},
10207
  {443, 443}, {444, 447}, {448, 451}, {452, 659},
10208
  {660, 660}, {661, 687}, {688, 705}, {710, 721},
10209
  {736, 740}, {748, 748}, {750, 750}, {880, 883},
10210
  {884, 884}, {886, 887}, {890, 890}, {891, 893},
10211
  {895, 895}, {902, 902}, {904, 906}, {908, 908},
10212
  {910, 929}, {931, 1013}, {1015, 1153}, {1162, 1327},
10213
  {1329, 1366}, {1369, 1369}, {1376, 1416}, {1488, 1514},
10214
  {1519, 1522}, {1568, 1599}, {1600, 1600}, {1601, 1610},
10215
  {1646, 1647}, {1649, 1747}, {1749, 1749}, {1765, 1766},
10216
  {1774, 1775}, {1786, 1788}, {1791, 1791}, {1808, 1808},
10217
  {1810, 1839}, {1869, 1957}, {1969, 1969}, {1994, 2026},
10218
  {2036, 2037}, {2042, 2042}, {2048, 2069}, {2074, 2074},
10219
  {2084, 2084}, {2088, 2088}, {2112, 2136}, {2144, 2154},
10220
  {2160, 2183}, {2185, 2190}, {2208, 2248}, {2249, 2249},
10221
  {2308, 2361}, {2365, 2365}, {2384, 2384}, {2392, 2401},
10222
  {2417, 2417}, {2418, 2432}, {2437, 2444}, {2447, 2448},
10223
  {2451, 2472}, {2474, 2480}, {2482, 2482}, {2486, 2489},
10224
  {2493, 2493}, {2510, 2510}, {2524, 2525}, {2527, 2529},
10225
  {2544, 2545}, {2556, 2556}, {2565, 2570}, {2575, 2576},
10226
  {2579, 2600}, {2602, 2608}, {2610, 2611}, {2613, 2614},
10227
  {2616, 2617}, {2649, 2652}, {2654, 2654}, {2674, 2676},
10228
  {2693, 2701}, {2703, 2705}, {2707, 2728}, {2730, 2736},
10229
  {2738, 2739}, {2741, 2745}, {2749, 2749}, {2768, 2768},
10230
  {2784, 2785}, {2809, 2809}, {2821, 2828}, {2831, 2832},
10231
  {2835, 2856}, {2858, 2864}, {2866, 2867}, {2869, 2873},
10232
  {2877, 2877}, {2908, 2909}, {2911, 2913}, {2929, 2929},
10233
  {2947, 2947}, {2949, 2954}, {2958, 2960}, {2962, 2965},
10234
  {2969, 2970}, {2972, 2972}, {2974, 2975}, {2979, 2980},
10235
  {2984, 2986}, {2990, 3001}, {3024, 3024}, {3077, 3084},
10236
  {3086, 3088}, {3090, 3112}, {3114, 3129}, {3133, 3133},
10237
  {3160, 3162}, {3165, 3165}, {3168, 3169}, {3200, 3200},
10238
  {3205, 3212}, {3214, 3216}, {3218, 3240}, {3242, 3251},
10239
  {3253, 3257}, {3261, 3261}, {3293, 3294}, {3296, 3297},
10240
  {3313, 3314}, {3332, 3340}, {3342, 3344}, {3346, 3386},
10241
  {3389, 3389}, {3406, 3406}, {3412, 3414}, {3423, 3425},
10242
  {3450, 3455}, {3461, 3478}, {3482, 3505}, {3507, 3515},
10243
  {3517, 3517}, {3520, 3526}, {3585, 3632}, {3634, 3635},
10244
  {3648, 3653}, {3654, 3654}, {3713, 3714}, {3716, 3716},
10245
  {3718, 3722}, {3724, 3747}, {3749, 3749}, {3751, 3760},
10246
  {3762, 3763}, {3773, 3773}, {3776, 3780}, {3782, 3782},
10247
  {3804, 3807}, {3840, 3840}, {3904, 3911}, {3913, 3948},
10248
  {3976, 3980}, {4096, 4138}, {4159, 4159}, {4176, 4181},
10249
  {4186, 4189}, {4193, 4193}, {4197, 4198}, {4206, 4208},
10250
  {4213, 4225}, {4238, 4238}, {4256, 4293}, {4295, 4295},
10251
  {4301, 4301}, {4304, 4346}, {4348, 4348}, {4349, 4351},
10252
  {4352, 4680}, {4682, 4685}, {4688, 4694}, {4696, 4696},
10253
  {4698, 4701}, {4704, 4744}, {4746, 4749}, {4752, 4784},
10254
  {4786, 4789}, {4792, 4798}, {4800, 4800}, {4802, 4805},
10255
  {4808, 4822}, {4824, 4880}, {4882, 4885}, {4888, 4954},
10256
  {4992, 5007}, {5024, 5109}, {5112, 5117}, {5121, 5740},
10257
  {5743, 5759}, {5761, 5786}, {5792, 5866}, {5870, 5872},
10258
  {5873, 5880}, {5888, 5905}, {5919, 5937}, {5952, 5969},
10259
  {5984, 5996}, {5998, 6000}, {6016, 6067}, {6103, 6103},
10260
  {6108, 6108}, {6176, 6210}, {6211, 6211}, {6212, 6264},
10261
  {6272, 6276}, {6277, 6278}, {6279, 6312}, {6314, 6314},
10262
  {6320, 6389}, {6400, 6430}, {6480, 6509}, {6512, 6516},
10263
  {6528, 6571}, {6576, 6601}, {6656, 6678}, {6688, 6740},
10264
  {6823, 6823}, {6917, 6963}, {6981, 6988}, {7043, 7072},
10265
  {7086, 7087}, {7098, 7141}, {7168, 7203}, {7245, 7247},
10266
  {7258, 7287}, {7288, 7293}, {7296, 7306}, {7312, 7354},
10267
  {7357, 7359}, {7401, 7404}, {7406, 7411}, {7413, 7414},
10268
  {7418, 7418}, {7424, 7467}, {7468, 7530}, {7531, 7543},
10269
  {7544, 7544}, {7545, 7578}, {7579, 7615}, {7680, 7957},
10270
  {7960, 7965}, {7968, 8005}, {8008, 8013}, {8016, 8023},
10271
  {8025, 8025}, {8027, 8027}, {8029, 8029}, {8031, 8061},
10272
  {8064, 8116}, {8118, 8124}, {8126, 8126}, {8130, 8132},
10273
  {8134, 8140}, {8144, 8147}, {8150, 8155}, {8160, 8172},
10274
  {8178, 8180}, {8182, 8188}, {8305, 8305}, {8319, 8319},
10275
  {8336, 8348}, {8450, 8450}, {8455, 8455}, {8458, 8467},
10276
  {8469, 8469}, {8472, 8472}, {8473, 8477}, {8484, 8484},
10277
  {8486, 8486}, {8488, 8488}, {8490, 8493}, {8494, 8494},
10278
  {8495, 8500}, {8501, 8504}, {8505, 8505}, {8508, 8511},
10279
  {8517, 8521}, {8526, 8526}, {8544, 8578}, {8579, 8580},
10280
  {8581, 8584}, {11264, 11387}, {11388, 11389}, {11390, 11492},
10281
  {11499, 11502}, {11506, 11507}, {11520, 11557}, {11559, 11559},
10282
  {11565, 11565}, {11568, 11623}, {11631, 11631}, {11648, 11670},
10283
  {11680, 11686}, {11688, 11694}, {11696, 11702}, {11704, 11710},
10284
  {11712, 11718}, {11720, 11726}, {11728, 11734}, {11736, 11742},
10285
  {12293, 12293}, {12294, 12294}, {12295, 12295}, {12321, 12329},
10286
  {12337, 12341}, {12344, 12346}, {12347, 12347}, {12348, 12348},
10287
  {12353, 12438}, {12443, 12444}, {12445, 12446}, {12447, 12447},
10288
  {12449, 12538}, {12540, 12542}, {12543, 12543}, {12549, 12591},
10289
  {12593, 12686}, {12704, 12735}, {12784, 12799}, {13312, 19903},
10290
  {19968, 40980}, {40981, 40981}, {40982, 42124}, {42192, 42231},
10291
  {42232, 42237}, {42240, 42507}, {42508, 42508}, {42512, 42527},
10292
  {42538, 42539}, {42560, 42605}, {42606, 42606}, {42623, 42623},
10293
  {42624, 42651}, {42652, 42653}, {42656, 42725}, {42726, 42735},
10294
  {42775, 42783}, {42786, 42863}, {42864, 42864}, {42865, 42887},
10295
  {42888, 42888}, {42891, 42894}, {42895, 42895}, {42896, 42957},
10296
  {42960, 42961}, {42963, 42963}, {42965, 42972}, {42994, 42996},
10297
  {42997, 42998}, {42999, 42999}, {43000, 43001}, {43002, 43002},
10298
  {43003, 43009}, {43011, 43013}, {43015, 43018}, {43020, 43042},
10299
  {43072, 43123}, {43138, 43187}, {43250, 43255}, {43259, 43259},
10300
  {43261, 43262}, {43274, 43301}, {43312, 43334}, {43360, 43388},
10301
  {43396, 43442}, {43471, 43471}, {43488, 43492}, {43494, 43494},
10302
  {43495, 43503}, {43514, 43518}, {43520, 43560}, {43584, 43586},
10303
  {43588, 43595}, {43616, 43631}, {43632, 43632}, {43633, 43638},
10304
  {43642, 43642}, {43646, 43695}, {43697, 43697}, {43701, 43702},
10305
  {43705, 43709}, {43712, 43712}, {43714, 43714}, {43739, 43740},
10306
  {43741, 43741}, {43744, 43754}, {43762, 43762}, {43763, 43764},
10307
  {43777, 43782}, {43785, 43790}, {43793, 43798}, {43808, 43814},
10308
  {43816, 43822}, {43824, 43866}, {43868, 43871}, {43872, 43880},
10309
  {43881, 43881}, {43888, 43967}, {43968, 44002}, {44032, 55203},
10310
  {55216, 55238}, {55243, 55291}, {63744, 64109}, {64112, 64217},
10311
  {64256, 64262}, {64275, 64279}, {64285, 64285}, {64287, 64296},
10312
  {64298, 64310}, {64312, 64316}, {64318, 64318}, {64320, 64321},
10313
  {64323, 64324}, {64326, 64433}, {64467, 64829}, {64848, 64911},
10314
  {64914, 64967}, {65008, 65019}, {65136, 65140}, {65142, 65276},
10315
  {65313, 65338}, {65345, 65370}, {65382, 65391}, {65392, 65392},
10316
  {65393, 65437}, {65438, 65439}, {65440, 65470}, {65474, 65479},
10317
  {65482, 65487}, {65490, 65495}, {65498, 65500}, {65536, 65547},
10318
  {65549, 65574}, {65576, 65594}, {65596, 65597}, {65599, 65613},
10319
  {65616, 65629}, {65664, 65786}, {65856, 65908}, {66176, 66204},
10320
  {66208, 66256}, {66304, 66335}, {66349, 66368}, {66369, 66369},
10321
  {66370, 66377}, {66378, 66378}, {66384, 66421}, {66432, 66461},
10322
  {66464, 66499}, {66504, 66511}, {66513, 66517}, {66560, 66639},
10323
  {66640, 66717}, {66736, 66771}, {66776, 66811}, {66816, 66855},
10324
  {66864, 66915}, {66928, 66938}, {66940, 66954}, {66956, 66962},
10325
  {66964, 66965}, {66967, 66977}, {66979, 66993}, {66995, 67001},
10326
  {67003, 67004}, {67008, 67059}, {67072, 67382}, {67392, 67413},
10327
  {67424, 67431}, {67456, 67461}, {67463, 67504}, {67506, 67514},
10328
  {67584, 67589}, {67592, 67592}, {67594, 67637}, {67639, 67640},
10329
  {67644, 67644}, {67647, 67669}, {67680, 67702}, {67712, 67742},
10330
  {67808, 67826}, {67828, 67829}, {67840, 67861}, {67872, 67897},
10331
  {67968, 68023}, {68030, 68031}, {68096, 68096}, {68112, 68115},
10332
  {68117, 68119}, {68121, 68149}, {68192, 68220}, {68224, 68252},
10333
  {68288, 68295}, {68297, 68324}, {68352, 68405}, {68416, 68437},
10334
  {68448, 68466}, {68480, 68497}, {68608, 68680}, {68736, 68786},
10335
  {68800, 68850}, {68864, 68899}, {68938, 68941}, {68942, 68942},
10336
  {68943, 68943}, {68944, 68965}, {68975, 68975}, {68976, 68997},
10337
  {69248, 69289}, {69296, 69297}, {69314, 69316}, {69376, 69404},
10338
  {69415, 69415}, {69424, 69445}, {69488, 69505}, {69552, 69572},
10339
  {69600, 69622}, {69635, 69687}, {69745, 69746}, {69749, 69749},
10340
  {69763, 69807}, {69840, 69864}, {69891, 69926}, {69956, 69956},
10341
  {69959, 69959}, {69968, 70002}, {70006, 70006}, {70019, 70066},
10342
  {70081, 70084}, {70106, 70106}, {70108, 70108}, {70144, 70161},
10343
  {70163, 70187}, {70207, 70208}, {70272, 70278}, {70280, 70280},
10344
  {70282, 70285}, {70287, 70301}, {70303, 70312}, {70320, 70366},
10345
  {70405, 70412}, {70415, 70416}, {70419, 70440}, {70442, 70448},
10346
  {70450, 70451}, {70453, 70457}, {70461, 70461}, {70480, 70480},
10347
  {70493, 70497}, {70528, 70537}, {70539, 70539}, {70542, 70542},
10348
  {70544, 70581}, {70583, 70583}, {70609, 70609}, {70611, 70611},
10349
  {70656, 70708}, {70727, 70730}, {70751, 70753}, {70784, 70831},
10350
  {70852, 70853}, {70855, 70855}, {71040, 71086}, {71128, 71131},
10351
  {71168, 71215}, {71236, 71236}, {71296, 71338}, {71352, 71352},
10352
  {71424, 71450}, {71488, 71494}, {71680, 71723}, {71840, 71903},
10353
  {71935, 71942}, {71945, 71945}, {71948, 71955}, {71957, 71958},
10354
  {71960, 71983}, {71999, 71999}, {72001, 72001}, {72096, 72103},
10355
  {72106, 72144}, {72161, 72161}, {72163, 72163}, {72192, 72192},
10356
  {72203, 72242}, {72250, 72250}, {72272, 72272}, {72284, 72329},
10357
  {72349, 72349}, {72368, 72440}, {72640, 72672}, {72704, 72712},
10358
  {72714, 72750}, {72768, 72768}, {72818, 72847}, {72960, 72966},
10359
  {72968, 72969}, {72971, 73008}, {73030, 73030}, {73056, 73061},
10360
  {73063, 73064}, {73066, 73097}, {73112, 73112}, {73440, 73458},
10361
  {73474, 73474}, {73476, 73488}, {73490, 73523}, {73648, 73648},
10362
  {73728, 74649}, {74752, 74862}, {74880, 75075}, {77712, 77808},
10363
  {77824, 78895}, {78913, 78918}, {78944, 82938}, {82944, 83526},
10364
  {90368, 90397}, {92160, 92728}, {92736, 92766}, {92784, 92862},
10365
  {92880, 92909}, {92928, 92975}, {92992, 92995}, {93027, 93047},
10366
  {93053, 93071}, {93504, 93506}, {93507, 93546}, {93547, 93548},
10367
  {93760, 93823}, {93952, 94026}, {94032, 94032}, {94099, 94111},
10368
  {94176, 94177}, {94179, 94179}, {94208, 100343}, {100352, 101589},
10369
  {101631, 101640}, {110576, 110579}, {110581, 110587}, {110589, 110590},
10370
  {110592, 110882}, {110898, 110898}, {110928, 110930}, {110933, 110933},
10371
  {110948, 110951}, {110960, 111355}, {113664, 113770}, {113776, 113788},
10372
  {113792, 113800}, {113808, 113817}, {119808, 119892}, {119894, 119964},
10373
  {119966, 119967}, {119970, 119970}, {119973, 119974}, {119977, 119980},
10374
  {119982, 119993}, {119995, 119995}, {119997, 120003}, {120005, 120069},
10375
  {120071, 120074}, {120077, 120084}, {120086, 120092}, {120094, 120121},
10376
  {120123, 120126}, {120128, 120132}, {120134, 120134}, {120138, 120144},
10377
  {120146, 120485}, {120488, 120512}, {120514, 120538}, {120540, 120570},
10378
  {120572, 120596}, {120598, 120628}, {120630, 120654}, {120656, 120686},
10379
  {120688, 120712}, {120714, 120744}, {120746, 120770}, {120772, 120779},
10380
  {122624, 122633}, {122634, 122634}, {122635, 122654}, {122661, 122666},
10381
  {122928, 122989}, {123136, 123180}, {123191, 123197}, {123214, 123214},
10382
  {123536, 123565}, {123584, 123627}, {124112, 124138}, {124139, 124139},
10383
  {124368, 124397}, {124400, 124400}, {124896, 124902}, {124904, 124907},
10384
  {124909, 124910}, {124912, 124926}, {124928, 125124}, {125184, 125251},
10385
  {125259, 125259}, {126464, 126467}, {126469, 126495}, {126497, 126498},
10386
  {126500, 126500}, {126503, 126503}, {126505, 126514}, {126516, 126519},
10387
  {126521, 126521}, {126523, 126523}, {126530, 126530}, {126535, 126535},
10388
  {126537, 126537}, {126539, 126539}, {126541, 126543}, {126545, 126546},
10389
  {126548, 126548}, {126551, 126551}, {126553, 126553}, {126555, 126555},
10390
  {126557, 126557}, {126559, 126559}, {126561, 126562}, {126564, 126564},
10391
  {126567, 126570}, {126572, 126578}, {126580, 126583}, {126585, 126588},
10392
  {126590, 126590}, {126592, 126601}, {126603, 126619}, {126625, 126627},
10393
  {126629, 126633}, {126635, 126651}, {131072, 173791}, {173824, 177977},
10394
  {177984, 178205}, {178208, 183969}, {183984, 191456}, {191472, 192093},
10395
  {194560, 195101}, {196608, 201546}, {201552, 205743}
10396
};
10397
10398
10399
} // namespace ada::idna
10400
#endif // ADA_IDNA_IDENTIFIER_TABLES_H
10401
/* end file src/id_tables.cpp */
10402
10403
namespace ada::idna {
10404
0
constexpr bool is_ascii_letter(char32_t c) noexcept {
10405
0
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
10406
0
}
10407
10408
0
constexpr bool is_ascii_letter_or_digit(char32_t c) noexcept {
10409
0
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
10410
0
         (c >= '0' && c <= '9');
10411
0
}
10412
10413
0
bool valid_name_code_point(char32_t code_point, bool first) {
10414
  // https://tc39.es/ecma262/#prod-IdentifierStart
10415
  // Fast paths:
10416
0
  if (first &&
10417
0
      (code_point == '$' || code_point == '_' || is_ascii_letter(code_point))) {
10418
0
    return true;
10419
0
  }
10420
0
  if (!first && (code_point == '$' || is_ascii_letter_or_digit(code_point))) {
10421
0
    return true;
10422
0
  }
10423
  // Slow path...
10424
0
  if (code_point == 0xffffffff) {
10425
0
    return false;  // minimal error handling
10426
0
  }
10427
0
  if (first) {
10428
0
    auto iter = std::lower_bound(
10429
0
        std::begin(ada::idna::id_start), std::end(ada::idna::id_start),
10430
0
        code_point,
10431
0
        [](const uint32_t* range, uint32_t cp) { return range[1] < cp; });
10432
0
    return iter != std::end(id_start) && code_point >= (*iter)[0];
10433
0
  } else {
10434
0
    auto iter = std::lower_bound(
10435
0
        std::begin(id_continue), std::end(id_continue), code_point,
10436
0
        [](const uint32_t* range, uint32_t cp) { return range[1] < cp; });
10437
0
    return iter != std::end(id_start) && code_point >= (*iter)[0];
10438
0
  }
10439
0
}
10440
}  // namespace ada::idna
10441
/* end file src/identifier.cpp */
10442
/* end file src/idna.cpp */
10443
/* end file src/ada_idna.cpp */
10444
ADA_POP_DISABLE_WARNINGS
10445
10446
#include <algorithm>
10447
#if ADA_SSSE3
10448
#include <tmmintrin.h>
10449
#elif ADA_NEON
10450
#include <arm_neon.h>
10451
#elif ADA_SSE2
10452
#include <emmintrin.h>
10453
#elif ADA_LSX
10454
#include <lsxintrin.h>
10455
#elif ADA_RVV
10456
#include <riscv_vector.h>
10457
#endif
10458
10459
#include <ranges>
10460
10461
namespace ada::unicode {
10462
10463
210k
constexpr bool is_tabs_or_newline(char c) noexcept {
10464
210k
  return c == '\r' || c == '\n' || c == '\t';
10465
210k
}
10466
10467
115k
constexpr uint64_t broadcast(uint8_t v) noexcept {
10468
115k
  return 0x101010101010101ull * v;
10469
115k
}
10470
10471
38.4k
constexpr bool to_lower_ascii(char* input, size_t length) noexcept {
10472
38.4k
  uint64_t broadcast_80 = broadcast(0x80);
10473
38.4k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
10474
38.4k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
10475
38.4k
  uint64_t non_ascii = 0;
10476
38.4k
  size_t i = 0;
10477
10478
87.4k
  for (; i + 7 < length; i += 8) {
10479
49.0k
    uint64_t word{};
10480
49.0k
    memcpy(&word, input + i, sizeof(word));
10481
49.0k
    non_ascii |= (word & broadcast_80);
10482
49.0k
    word ^=
10483
49.0k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10484
49.0k
    memcpy(input + i, &word, sizeof(word));
10485
49.0k
  }
10486
38.4k
  if (i < length) {
10487
37.2k
    uint64_t word{};
10488
37.2k
    memcpy(&word, input + i, length - i);
10489
37.2k
    non_ascii |= (word & broadcast_80);
10490
37.2k
    word ^=
10491
37.2k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10492
37.2k
    memcpy(input + i, &word, length - i);
10493
37.2k
  }
10494
38.4k
  return non_ascii == 0;
10495
38.4k
}
10496
#if ADA_SSSE3
10497
ada_really_inline bool has_tabs_or_newline(
10498
    std::string_view user_input) noexcept {
10499
  // first check for short strings in which case we do it naively.
10500
  if (user_input.size() < 16) {  // slow path
10501
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10502
  }
10503
  // fast path for long strings (expected to be common)
10504
  // Using SSSE3's _mm_shuffle_epi8 for table lookup (same approach as NEON)
10505
  size_t i = 0;
10506
  // Lookup table where positions 9, 10, 13 contain their own values
10507
  // Everything else is set to 1 so it won't match
10508
  const __m128i rnt =
10509
      _mm_setr_epi8(1, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 0, 0, 13, 0, 0);
10510
  __m128i running = _mm_setzero_si128();
10511
  for (; i + 15 < user_input.size(); i += 16) {
10512
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
10513
    // Shuffle the lookup table using input bytes as indices
10514
    __m128i shuffled = _mm_shuffle_epi8(rnt, word);
10515
    // Compare: if shuffled value matches input, we found \t, \n, or \r
10516
    __m128i matches = _mm_cmpeq_epi8(shuffled, word);
10517
    running = _mm_or_si128(running, matches);
10518
  }
10519
  if (i < user_input.size()) {
10520
    __m128i word = _mm_loadu_si128(
10521
        (const __m128i*)(user_input.data() + user_input.length() - 16));
10522
    __m128i shuffled = _mm_shuffle_epi8(rnt, word);
10523
    __m128i matches = _mm_cmpeq_epi8(shuffled, word);
10524
    running = _mm_or_si128(running, matches);
10525
  }
10526
  return _mm_movemask_epi8(running) != 0;
10527
}
10528
#elif ADA_NEON
10529
ada_really_inline bool has_tabs_or_newline(
10530
    std::string_view user_input) noexcept {
10531
  // first check for short strings in which case we do it naively.
10532
  if (user_input.size() < 16) {  // slow path
10533
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10534
  }
10535
  // fast path for long strings (expected to be common)
10536
  size_t i = 0;
10537
  /**
10538
   * The fastest way to check for `\t` (==9), '\n'(== 10) and `\r` (==13) relies
10539
   * on table lookup instruction. We notice that these are all unique numbers
10540
   * between 0..15. Let's prepare a special register, where we put '\t' in the
10541
   * 9th position, '\n' - 10th and '\r' - 13th. Then we shuffle this register by
10542
   * input register. If the input had `\t` in position X then this shuffled
10543
   * register will also have '\t' in that position. Comparing input with this
10544
   * shuffled register will mark us all interesting characters in the input.
10545
   *
10546
   * credit for algorithmic idea: @aqrit, credit for description:
10547
   * @DenisYaroshevskiy
10548
   */
10549
  static uint8_t rnt_array[16] = {1, 0, 0,  0, 0, 0,  0, 0,
10550
                                  0, 9, 10, 0, 0, 13, 0, 0};
10551
  const uint8x16_t rnt = vld1q_u8(rnt_array);
10552
  // m['0xd', '0xa', '0x9']
10553
  uint8x16_t running{0};
10554
  for (; i + 15 < user_input.size(); i += 16) {
10555
    uint8x16_t word = vld1q_u8((const uint8_t*)user_input.data() + i);
10556
10557
    running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word));
10558
  }
10559
  if (i < user_input.size()) {
10560
    uint8x16_t word =
10561
        vld1q_u8((const uint8_t*)user_input.data() + user_input.length() - 16);
10562
    running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word));
10563
  }
10564
  return vmaxvq_u32(vreinterpretq_u32_u8(running)) != 0;
10565
}
10566
#elif ADA_SSE2
10567
ada_really_inline bool has_tabs_or_newline(
10568
72.1k
    std::string_view user_input) noexcept {
10569
  // first check for short strings in which case we do it naively.
10570
72.1k
  if (user_input.size() < 16) {  // slow path
10571
29.8k
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10572
29.8k
  }
10573
  // fast path for long strings (expected to be common)
10574
42.3k
  size_t i = 0;
10575
42.3k
  const __m128i mask1 = _mm_set1_epi8('\r');
10576
42.3k
  const __m128i mask2 = _mm_set1_epi8('\n');
10577
42.3k
  const __m128i mask3 = _mm_set1_epi8('\t');
10578
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10579
42.3k
  __m128i running{0};
10580
158k
  for (; i + 15 < user_input.size(); i += 16) {
10581
116k
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
10582
116k
    running = _mm_or_si128(
10583
116k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10584
116k
                                           _mm_cmpeq_epi8(word, mask2))),
10585
116k
        _mm_cmpeq_epi8(word, mask3));
10586
116k
  }
10587
42.3k
  if (i < user_input.size()) {
10588
39.3k
    __m128i word = _mm_loadu_si128(
10589
39.3k
        (const __m128i*)(user_input.data() + user_input.length() - 16));
10590
39.3k
    running = _mm_or_si128(
10591
39.3k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10592
39.3k
                                           _mm_cmpeq_epi8(word, mask2))),
10593
39.3k
        _mm_cmpeq_epi8(word, mask3));
10594
39.3k
  }
10595
42.3k
  return _mm_movemask_epi8(running) != 0;
10596
72.1k
}
10597
#elif ADA_LSX
10598
ada_really_inline bool has_tabs_or_newline(
10599
    std::string_view user_input) noexcept {
10600
  // first check for short strings in which case we do it naively.
10601
  if (user_input.size() < 16) {  // slow path
10602
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10603
  }
10604
  // fast path for long strings (expected to be common)
10605
  size_t i = 0;
10606
  const __m128i mask1 = __lsx_vrepli_b('\r');
10607
  const __m128i mask2 = __lsx_vrepli_b('\n');
10608
  const __m128i mask3 = __lsx_vrepli_b('\t');
10609
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10610
  __m128i running{0};
10611
  for (; i + 15 < user_input.size(); i += 16) {
10612
    __m128i word = __lsx_vld((const __m128i*)(user_input.data() + i), 0);
10613
    running = __lsx_vor_v(
10614
        __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1),
10615
                                         __lsx_vseq_b(word, mask2))),
10616
        __lsx_vseq_b(word, mask3));
10617
  }
10618
  if (i < user_input.size()) {
10619
    __m128i word = __lsx_vld(
10620
        (const __m128i*)(user_input.data() + user_input.length() - 16), 0);
10621
    running = __lsx_vor_v(
10622
        __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1),
10623
                                         __lsx_vseq_b(word, mask2))),
10624
        __lsx_vseq_b(word, mask3));
10625
  }
10626
  if (__lsx_bz_v(running)) return false;
10627
  return true;
10628
}
10629
#elif ADA_RVV
10630
ada_really_inline bool has_tabs_or_newline(
10631
    std::string_view user_input) noexcept {
10632
  uint8_t* src = (uint8_t*)user_input.data();
10633
  for (size_t vl, n = user_input.size(); n > 0; n -= vl, src += vl) {
10634
    vl = __riscv_vsetvl_e8m1(n);
10635
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
10636
    vbool8_t m1 = __riscv_vmseq(v, '\r', vl);
10637
    vbool8_t m2 = __riscv_vmseq(v, '\n', vl);
10638
    vbool8_t m3 = __riscv_vmseq(v, '\t', vl);
10639
    vbool8_t m = __riscv_vmor(__riscv_vmor(m1, m2, vl), m3, vl);
10640
    long idx = __riscv_vfirst(m, vl);
10641
    if (idx >= 0) return true;
10642
  }
10643
  return false;
10644
}
10645
#else
10646
ada_really_inline bool has_tabs_or_newline(
10647
    std::string_view user_input) noexcept {
10648
  auto has_zero_byte = [](uint64_t v) {
10649
    return ((v - 0x0101010101010101) & ~(v) & 0x8080808080808080);
10650
  };
10651
  size_t i = 0;
10652
  uint64_t mask1 = broadcast('\r');
10653
  uint64_t mask2 = broadcast('\n');
10654
  uint64_t mask3 = broadcast('\t');
10655
  uint64_t running{0};
10656
  for (; i + 7 < user_input.size(); i += 8) {
10657
    uint64_t word{};
10658
    memcpy(&word, user_input.data() + i, sizeof(word));
10659
    uint64_t xor1 = word ^ mask1;
10660
    uint64_t xor2 = word ^ mask2;
10661
    uint64_t xor3 = word ^ mask3;
10662
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
10663
  }
10664
  if (i < user_input.size()) {
10665
    uint64_t word{};
10666
    memcpy(&word, user_input.data() + i, user_input.size() - i);
10667
    uint64_t xor1 = word ^ mask1;
10668
    uint64_t xor2 = word ^ mask2;
10669
    uint64_t xor3 = word ^ mask3;
10670
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
10671
  }
10672
  return running;
10673
}
10674
#endif
10675
10676
// A forbidden host code point is U+0000 NULL, U+0009 TAB, U+000A LF, U+000D CR,
10677
// U+0020 SPACE, U+0023 (#), U+002F (/), U+003A (:), U+003C (<), U+003E (>),
10678
// U+003F (?), U+0040 (@), U+005B ([), U+005C (\), U+005D (]), U+005E (^), or
10679
// U+007C (|).
10680
constexpr static std::array<uint8_t, 256> is_forbidden_host_code_point_table =
10681
    []() consteval {
10682
      std::array<uint8_t, 256> result{};
10683
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10684
                        '>', '?', '@', '[', '\\', ']', '^', '|'}) {
10685
        result[c] = true;
10686
      }
10687
      return result;
10688
    }();
10689
10690
ada_really_inline constexpr bool is_forbidden_host_code_point(
10691
17.8k
    const char c) noexcept {
10692
17.8k
  return is_forbidden_host_code_point_table[uint8_t(c)];
10693
17.8k
}
10694
10695
constexpr static std::array<uint8_t, 256> is_forbidden_domain_code_point_table =
10696
    []() consteval {
10697
      std::array<uint8_t, 256> result{};
10698
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10699
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
10700
        result[c] = true;
10701
      }
10702
      for (uint8_t c = 0; c <= 32; c++) {
10703
        result[c] = true;
10704
      }
10705
      for (size_t c = 127; c < 255; c++) {
10706
        result[c] = true;
10707
      }
10708
      return result;
10709
    }();
10710
10711
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
10712
10713
ada_really_inline constexpr bool is_forbidden_domain_code_point(
10714
972k
    const char c) noexcept {
10715
972k
  return is_forbidden_domain_code_point_table[uint8_t(c)];
10716
972k
}
10717
10718
ada_really_inline constexpr bool contains_forbidden_domain_code_point(
10719
37.8k
    const char* input, size_t length) noexcept {
10720
37.8k
  size_t i = 0;
10721
37.8k
  uint8_t accumulator{};
10722
413k
  for (; i + 4 <= length; i += 4) {
10723
375k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10724
375k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 1])];
10725
375k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 2])];
10726
375k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 3])];
10727
375k
  }
10728
107k
  for (; i < length; i++) {
10729
70.1k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10730
70.1k
  }
10731
37.8k
  return accumulator;
10732
37.8k
}
10733
10734
constexpr static std::array<uint8_t, 256>
10735
    is_forbidden_domain_code_point_table_or_upper = []() consteval {
10736
      std::array<uint8_t, 256> result{};
10737
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10738
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
10739
        result[c] = 1;
10740
      }
10741
      for (uint8_t c = 'A'; c <= 'Z'; c++) {
10742
        result[c] = 2;
10743
      }
10744
      for (uint8_t c = 0; c <= 32; c++) {
10745
        result[c] = 1;
10746
      }
10747
      for (size_t c = 127; c < 255; c++) {
10748
        result[c] = 1;
10749
      }
10750
      return result;
10751
    }();
10752
10753
ada_really_inline constexpr uint8_t
10754
contains_forbidden_domain_code_point_or_upper(const char* input,
10755
25.0k
                                              size_t length) noexcept {
10756
25.0k
  size_t i = 0;
10757
25.0k
  uint8_t accumulator{};
10758
125k
  for (; i + 4 <= length; i += 4) {
10759
100k
    accumulator |=
10760
100k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10761
100k
    accumulator |=
10762
100k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 1])];
10763
100k
    accumulator |=
10764
100k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 2])];
10765
100k
    accumulator |=
10766
100k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 3])];
10767
100k
  }
10768
75.8k
  for (; i < length; i++) {
10769
50.8k
    accumulator |=
10770
50.8k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10771
50.8k
  }
10772
25.0k
  return accumulator;
10773
25.0k
}
10774
10775
// std::isalnum(c) || c == '+' || c == '-' || c == '.') is true for
10776
constexpr static std::array<bool, 256> is_alnum_plus_table = []() consteval {
10777
  std::array<bool, 256> result{};
10778
  for (size_t c = 0; c < 256; c++) {
10779
    result[c] = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
10780
                (c >= 'A' && c <= 'Z') || c == '+' || c == '-' || c == '.';
10781
  }
10782
  return result;
10783
}();
10784
10785
251k
ada_really_inline constexpr bool is_alnum_plus(const char c) noexcept {
10786
251k
  return is_alnum_plus_table[uint8_t(c)];
10787
  // A table is almost surely much faster than the
10788
  // following under most compilers: return
10789
  // return (std::isalnum(c) || c == '+' || c == '-' || c == '.');
10790
251k
}
10791
10792
30.5k
ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept {
10793
30.5k
  return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
10794
4.13k
         (c >= 'a' && c <= 'f');
10795
30.5k
}
10796
10797
37.8k
ada_really_inline constexpr bool is_ascii_digit(const char c) noexcept {
10798
  // An ASCII digit is a code point in the range U+0030 (0) to U+0039 (9),
10799
  // inclusive.
10800
37.8k
  return (c >= '0' && c <= '9');
10801
37.8k
}
10802
10803
0
ada_really_inline constexpr bool is_ascii(const char32_t c) noexcept {
10804
  // If code point is between U+0000 and U+007F inclusive, then return true.
10805
0
  return c <= 0x7F;
10806
0
}
10807
10808
93.6k
ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept {
10809
93.6k
  return (unsigned char)c <= ' ';
10810
93.6k
}
10811
10812
ada_really_inline constexpr bool is_ascii_tab_or_newline(
10813
3.86M
    const char c) noexcept {
10814
3.86M
  return c == '\t' || c == '\n' || c == '\r';
10815
3.86M
}
10816
10817
constexpr std::string_view table_is_double_dot_path_segment[] = {
10818
    "..", "%2e.", ".%2e", "%2e%2e"};
10819
10820
ada_really_inline constexpr bool is_double_dot_path_segment(
10821
125k
    std::string_view input) noexcept {
10822
  // This will catch most cases:
10823
  // The length must be 2,4 or 6.
10824
  // We divide by two and require
10825
  // that the result be between 1 and 3 inclusively.
10826
125k
  uint64_t half_length = uint64_t(input.size()) / 2;
10827
125k
  if (half_length - 1 > 2) {
10828
66.7k
    return false;
10829
66.7k
  }
10830
  // We have a string of length 2, 4 or 6.
10831
  // We now check the first character:
10832
59.1k
  if ((input[0] != '.') && (input[0] != '%')) {
10833
10.1k
    return false;
10834
10.1k
  }
10835
  // We are unlikely the get beyond this point.
10836
48.9k
  int hash_value = (input.size() + (unsigned)(input[0])) & 3;
10837
48.9k
  const std::string_view target = table_is_double_dot_path_segment[hash_value];
10838
48.9k
  if (target.size() != input.size()) {
10839
13.4k
    return false;
10840
13.4k
  }
10841
  // We almost never get here.
10842
  // Optimizing the rest is relatively unimportant.
10843
35.4k
  auto prefix_equal_unsafe = [](std::string_view a, std::string_view b) {
10844
35.4k
    uint16_t A, B;
10845
35.4k
    memcpy(&A, a.data(), sizeof(A));
10846
35.4k
    memcpy(&B, b.data(), sizeof(B));
10847
35.4k
    return A == B;
10848
35.4k
  };
10849
35.4k
  if (!prefix_equal_unsafe(input, target)) {
10850
2.95k
    return false;
10851
2.95k
  }
10852
40.3k
  for (size_t i = 2; i < input.size(); i++) {
10853
12.4k
    char c = input[i];
10854
12.4k
    if ((uint8_t((c | 0x20) - 0x61) <= 25 ? (c | 0x20) : c) != target[i]) {
10855
4.59k
      return false;
10856
4.59k
    }
10857
12.4k
  }
10858
27.9k
  return true;
10859
  // The above code might be a bit better than the code below. Compilers
10860
  // are not stupid and may use the fact that these strings have length 2,4 and
10861
  // 6 and other tricks.
10862
  // return input == ".." ||
10863
  //  input == ".%2e" || input == ".%2E" ||
10864
  //  input == "%2e." || input == "%2E." ||
10865
  //  input == "%2e%2e" || input == "%2E%2E" || input == "%2E%2e" || input ==
10866
  //  "%2e%2E";
10867
32.5k
}
10868
10869
ada_really_inline constexpr bool is_single_dot_path_segment(
10870
195k
    std::string_view input) noexcept {
10871
195k
  return input == "." || input == "%2e" || input == "%2E";
10872
195k
}
10873
10874
27.4k
ada_really_inline constexpr bool is_lowercase_hex(const char c) noexcept {
10875
27.4k
  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
10876
27.4k
}
10877
10878
constexpr static char hex_to_binary_table[] = {
10879
    0,  1,  2,  3,  4, 5, 6, 7, 8, 9, 0, 0,  0,  0,  0,  0,  0, 10, 11,
10880
    12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0,  0,
10881
    0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
10882
26.7k
unsigned constexpr convert_hex_to_binary(const char c) noexcept {
10883
26.7k
  return hex_to_binary_table[c - '0'];
10884
26.7k
}
10885
10886
1.26k
std::string percent_decode(const std::string_view input, size_t first_percent) {
10887
  // next line is for safety only, we expect users to avoid calling
10888
  // percent_decode when first_percent is outside the range.
10889
1.26k
  if (first_percent == std::string_view::npos) {
10890
0
    return std::string(input);
10891
0
  }
10892
1.26k
  std::string dest;
10893
1.26k
  dest.reserve(input.length());
10894
1.26k
  dest.append(input.substr(0, first_percent));
10895
1.26k
  const char* pointer = input.data() + first_percent;
10896
1.26k
  const char* end = input.data() + input.size();
10897
  // Optimization opportunity: if the following code gets
10898
  // called often, it can be optimized quite a bit.
10899
29.6k
  while (pointer < end) {
10900
28.3k
    const char ch = pointer[0];
10901
28.3k
    size_t remaining = end - pointer - 1;
10902
28.3k
    if (ch != '%' || remaining < 2 ||
10903
14.2k
        (  // ch == '%' && // It is unnecessary to check that ch == '%'.
10904
14.2k
            (!is_ascii_hex_digit(pointer[1]) ||
10905
16.0k
             !is_ascii_hex_digit(pointer[2])))) {
10906
16.0k
      dest += ch;
10907
16.0k
      pointer++;
10908
16.0k
    } else {
10909
12.3k
      unsigned a = convert_hex_to_binary(pointer[1]);
10910
12.3k
      unsigned b = convert_hex_to_binary(pointer[2]);
10911
12.3k
      char c = static_cast<char>(a * 16 + b);
10912
12.3k
      dest += c;
10913
12.3k
      pointer += 3;
10914
12.3k
    }
10915
28.3k
  }
10916
1.26k
  return dest;
10917
1.26k
}
10918
10919
std::string percent_encode(const std::string_view input,
10920
54.8k
                           const uint8_t character_set[]) {
10921
386k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10922
386k
    return character_sets::bit_at(character_set, c);
10923
386k
  });
10924
  // Optimization: Don't iterate if percent encode is not required
10925
54.8k
  if (pointer == input.end()) {
10926
22.7k
    return std::string(input);
10927
22.7k
  }
10928
10929
32.1k
  std::string result;
10930
32.1k
  result.reserve(input.length());  // in the worst case, percent encoding might
10931
                                   // produce 3 characters.
10932
32.1k
  result.append(input.substr(0, std::distance(input.begin(), pointer)));
10933
10934
1.04M
  for (; pointer != input.end(); pointer++) {
10935
1.01M
    if (character_sets::bit_at(character_set, *pointer)) {
10936
795k
      result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10937
795k
    } else {
10938
219k
      result += *pointer;
10939
219k
    }
10940
1.01M
  }
10941
10942
32.1k
  return result;
10943
54.8k
}
10944
10945
template <bool append>
10946
bool percent_encode(const std::string_view input, const uint8_t character_set[],
10947
96.1k
                    std::string& out) {
10948
96.1k
  ada_log("percent_encode ", input, " to output string while ",
10949
96.1k
          append ? "appending" : "overwriting");
10950
386k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10951
386k
    return character_sets::bit_at(character_set, c);
10952
386k
  });
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
10950
150k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10951
150k
    return character_sets::bit_at(character_set, c);
10952
150k
  });
ada::unicode::percent_encode<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)::{lambda(char)#1}::operator()(char) const
Line
Count
Source
10950
235k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10951
235k
    return character_sets::bit_at(character_set, c);
10952
235k
  });
10953
96.1k
  ada_log("percent_encode done checking, moved to ",
10954
96.1k
          std::distance(input.begin(), pointer));
10955
10956
  // Optimization: Don't iterate if percent encode is not required
10957
96.1k
  if (pointer == input.end()) {
10958
49.8k
    ada_log("percent_encode encoding not needed.");
10959
49.8k
    return false;
10960
49.8k
  }
10961
46.2k
  if constexpr (!append) {
10962
35.1k
    out.clear();
10963
35.1k
  }
10964
46.2k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10965
46.2k
          " bytes");
10966
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10967
46.2k
  out.append(input.data(), std::distance(input.begin(), pointer));
10968
46.2k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10969
46.2k
          " bytes");
10970
1.02M
  for (; pointer != input.end(); pointer++) {
10971
976k
    if (character_sets::bit_at(character_set, *pointer)) {
10972
788k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10973
788k
    } else {
10974
188k
      out += *pointer;
10975
188k
    }
10976
976k
  }
10977
46.2k
  return true;
10978
96.1k
}
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
10947
77.0k
                    std::string& out) {
10948
77.0k
  ada_log("percent_encode ", input, " to output string while ",
10949
77.0k
          append ? "appending" : "overwriting");
10950
77.0k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10951
77.0k
    return character_sets::bit_at(character_set, c);
10952
77.0k
  });
10953
77.0k
  ada_log("percent_encode done checking, moved to ",
10954
77.0k
          std::distance(input.begin(), pointer));
10955
10956
  // Optimization: Don't iterate if percent encode is not required
10957
77.0k
  if (pointer == input.end()) {
10958
41.8k
    ada_log("percent_encode encoding not needed.");
10959
41.8k
    return false;
10960
41.8k
  }
10961
35.1k
  if constexpr (!append) {
10962
35.1k
    out.clear();
10963
35.1k
  }
10964
35.1k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10965
35.1k
          " bytes");
10966
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10967
35.1k
  out.append(input.data(), std::distance(input.begin(), pointer));
10968
35.1k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10969
35.1k
          " bytes");
10970
611k
  for (; pointer != input.end(); pointer++) {
10971
576k
    if (character_sets::bit_at(character_set, *pointer)) {
10972
485k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10973
485k
    } else {
10974
90.7k
      out += *pointer;
10975
90.7k
    }
10976
576k
  }
10977
35.1k
  return true;
10978
77.0k
}
bool ada::unicode::percent_encode<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Line
Count
Source
10947
19.1k
                    std::string& out) {
10948
19.1k
  ada_log("percent_encode ", input, " to output string while ",
10949
19.1k
          append ? "appending" : "overwriting");
10950
19.1k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10951
19.1k
    return character_sets::bit_at(character_set, c);
10952
19.1k
  });
10953
19.1k
  ada_log("percent_encode done checking, moved to ",
10954
19.1k
          std::distance(input.begin(), pointer));
10955
10956
  // Optimization: Don't iterate if percent encode is not required
10957
19.1k
  if (pointer == input.end()) {
10958
8.06k
    ada_log("percent_encode encoding not needed.");
10959
8.06k
    return false;
10960
8.06k
  }
10961
  if constexpr (!append) {
10962
    out.clear();
10963
  }
10964
11.0k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10965
11.0k
          " bytes");
10966
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10967
11.0k
  out.append(input.data(), std::distance(input.begin(), pointer));
10968
11.0k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10969
11.0k
          " bytes");
10970
411k
  for (; pointer != input.end(); pointer++) {
10971
400k
    if (character_sets::bit_at(character_set, *pointer)) {
10972
303k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10973
303k
    } else {
10974
97.5k
      out += *pointer;
10975
97.5k
    }
10976
400k
  }
10977
11.0k
  return true;
10978
19.1k
}
10979
10980
bool to_ascii(std::optional<std::string>& out, const std::string_view plain,
10981
18.1k
              size_t first_percent) {
10982
18.1k
  std::string percent_decoded_buffer;
10983
18.1k
  std::string_view input = plain;
10984
18.1k
  if (first_percent != std::string_view::npos) {
10985
1.26k
    percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
10986
1.26k
    input = percent_decoded_buffer;
10987
1.26k
  }
10988
  // input is a non-empty UTF-8 string, must be percent decoded
10989
18.1k
  std::string idna_ascii = ada::idna::to_ascii(input);
10990
18.1k
  if (idna_ascii.empty() || contains_forbidden_domain_code_point(
10991
12.8k
                                idna_ascii.data(), idna_ascii.size())) {
10992
9.18k
    return false;
10993
9.18k
  }
10994
8.92k
  out = std::move(idna_ascii);
10995
8.92k
  return true;
10996
18.1k
}
10997
10998
std::string percent_encode(const std::string_view input,
10999
15.0k
                           const uint8_t character_set[], size_t index) {
11000
15.0k
  std::string out;
11001
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
11002
15.0k
  out.append(input.data(), index);
11003
15.0k
  auto pointer = input.begin() + index;
11004
497k
  for (; pointer != input.end(); pointer++) {
11005
482k
    if (character_sets::bit_at(character_set, *pointer)) {
11006
369k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
11007
369k
    } else {
11008
112k
      out += *pointer;
11009
112k
    }
11010
482k
  }
11011
15.0k
  return out;
11012
15.0k
}
11013
11014
}  // namespace ada::unicode
11015
/* end file src/unicode.cpp */
11016
/* begin file src/serializers.cpp */
11017
#include <array>
11018
#include <charconv>
11019
#include <string>
11020
11021
namespace ada::serializers {
11022
11023
void find_longest_sequence_of_ipv6_pieces(
11024
    const std::array<uint16_t, 8>& address, size_t& compress,
11025
256
    size_t& compress_length) noexcept {
11026
876
  for (size_t i = 0; i < 8; i++) {
11027
706
    if (address[i] == 0) {
11028
320
      size_t next = i + 1;
11029
1.54k
      while (next != 8 && address[next] == 0) ++next;
11030
320
      const size_t count = next - i;
11031
320
      if (compress_length < count) {
11032
246
        compress_length = count;
11033
246
        compress = i;
11034
246
        if (next == 8) break;
11035
160
        i = next;
11036
160
      }
11037
320
    }
11038
706
  }
11039
256
}
11040
11041
256
std::string ipv6(const std::array<uint16_t, 8>& address) noexcept {
11042
256
  size_t compress_length = 0;  // The length of a long sequence of zeros.
11043
256
  size_t compress = 0;         // The start of a long sequence of zeros.
11044
256
  find_longest_sequence_of_ipv6_pieces(address, compress, compress_length);
11045
11046
256
  if (compress_length <= 1) {
11047
    // Optimization opportunity: Find a faster way then snprintf for imploding
11048
    // and return here.
11049
34
    compress = compress_length = 8;
11050
34
  }
11051
11052
256
  std::string output(4 * 8 + 7 + 2, '\0');
11053
256
  size_t piece_index = 0;
11054
256
  char* point = output.data();
11055
256
  char* point_end = output.data() + output.size();
11056
256
  *point++ = '[';
11057
730
  while (true) {
11058
730
    if (piece_index == compress) {
11059
222
      *point++ = ':';
11060
      // If we skip a value initially, we need to write '::', otherwise
11061
      // a single ':' will do since it follows a previous ':'.
11062
222
      if (piece_index == 0) {
11063
142
        *point++ = ':';
11064
142
      }
11065
222
      piece_index += compress_length;
11066
222
      if (piece_index == 8) {
11067
86
        break;
11068
86
      }
11069
222
    }
11070
644
    point = std::to_chars(point, point_end, address[piece_index], 16).ptr;
11071
644
    piece_index++;
11072
644
    if (piece_index == 8) {
11073
170
      break;
11074
170
    }
11075
474
    *point++ = ':';
11076
474
  }
11077
256
  *point++ = ']';
11078
256
  output.resize(point - output.data());
11079
256
  return output;
11080
256
}
11081
11082
2.96k
std::string ipv4(const uint64_t address) noexcept {
11083
2.96k
  std::string output(15, '\0');
11084
2.96k
  char* point = output.data();
11085
2.96k
  char* point_end = output.data() + output.size();
11086
2.96k
  point = std::to_chars(point, point_end, uint8_t(address >> 24)).ptr;
11087
11.8k
  for (int i = 2; i >= 0; i--) {
11088
8.89k
    *point++ = '.';
11089
8.89k
    point = std::to_chars(point, point_end, uint8_t(address >> (i * 8))).ptr;
11090
8.89k
  }
11091
2.96k
  output.resize(point - output.data());
11092
2.96k
  return output;
11093
2.96k
}
11094
11095
}  // namespace ada::serializers
11096
/* end file src/serializers.cpp */
11097
/* begin file src/implementation.cpp */
11098
11099
#include <string_view>
11100
11101
11102
namespace ada {
11103
11104
template <class result_type>
11105
ada_warn_unused tl::expected<result_type, errors> parse(
11106
44.3k
    std::string_view input, const result_type* base_url) {
11107
44.3k
  result_type u =
11108
44.3k
      ada::parser::parse_url_impl<result_type, true>(input, base_url);
11109
44.3k
  if (!u.is_valid) {
11110
12.6k
    return tl::unexpected(errors::type_error);
11111
12.6k
  }
11112
31.6k
  return u;
11113
44.3k
}
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
11106
22.1k
    std::string_view input, const result_type* base_url) {
11107
22.1k
  result_type u =
11108
22.1k
      ada::parser::parse_url_impl<result_type, true>(input, base_url);
11109
22.1k
  if (!u.is_valid) {
11110
6.26k
    return tl::unexpected(errors::type_error);
11111
6.26k
  }
11112
15.8k
  return u;
11113
22.1k
}
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
11106
22.1k
    std::string_view input, const result_type* base_url) {
11107
22.1k
  result_type u =
11108
22.1k
      ada::parser::parse_url_impl<result_type, true>(input, base_url);
11109
22.1k
  if (!u.is_valid) {
11110
6.40k
    return tl::unexpected(errors::type_error);
11111
6.40k
  }
11112
15.7k
  return u;
11113
22.1k
}
11114
11115
template ada::result<url> parse<url>(std::string_view input,
11116
                                     const url* base_url = nullptr);
11117
template ada::result<url_aggregator> parse<url_aggregator>(
11118
    std::string_view input, const url_aggregator* base_url = nullptr);
11119
11120
9.27k
std::string href_from_file(std::string_view input) {
11121
  // This is going to be much faster than constructing a URL.
11122
9.27k
  std::string tmp_buffer;
11123
9.27k
  std::string_view internal_input;
11124
9.27k
  if (unicode::has_tabs_or_newline(input)) {
11125
143
    tmp_buffer = input;
11126
143
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
11127
143
    internal_input = tmp_buffer;
11128
9.13k
  } else {
11129
9.13k
    internal_input = input;
11130
9.13k
  }
11131
9.27k
  std::string path;
11132
9.27k
  if (internal_input.empty()) {
11133
35
    path = "/";
11134
9.23k
  } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
11135
732
    helpers::parse_prepared_path(internal_input.substr(1),
11136
732
                                 ada::scheme::type::FILE, path);
11137
8.50k
  } else {
11138
8.50k
    helpers::parse_prepared_path(internal_input, ada::scheme::type::FILE, path);
11139
8.50k
  }
11140
9.27k
  return "file://" + path;
11141
9.27k
}
11142
11143
0
bool can_parse(std::string_view input, const std::string_view* base_input) {
11144
0
  ada::url_aggregator base_aggregator;
11145
0
  ada::url_aggregator* base_pointer = nullptr;
11146
11147
0
  if (base_input != nullptr) {
11148
0
    base_aggregator = ada::parser::parse_url_impl<ada::url_aggregator, false>(
11149
0
        *base_input, nullptr);
11150
0
    if (!base_aggregator.is_valid) {
11151
0
      return false;
11152
0
    }
11153
0
    base_pointer = &base_aggregator;
11154
0
  }
11155
11156
0
  ada::url_aggregator result =
11157
0
      ada::parser::parse_url_impl<ada::url_aggregator, false>(input,
11158
0
                                                              base_pointer);
11159
0
  return result.is_valid;
11160
0
}
11161
11162
0
ada_warn_unused std::string_view to_string(ada::encoding_type type) {
11163
0
  switch (type) {
11164
0
    case ada::encoding_type::UTF8:
11165
0
      return "UTF-8";
11166
0
    case ada::encoding_type::UTF_16LE:
11167
0
      return "UTF-16LE";
11168
0
    case ada::encoding_type::UTF_16BE:
11169
0
      return "UTF-16BE";
11170
0
    default:
11171
0
      unreachable();
11172
0
  }
11173
0
}
11174
11175
}  // namespace ada
11176
/* end file src/implementation.cpp */
11177
/* begin file src/helpers.cpp */
11178
#include <cstring>
11179
#include <sstream>
11180
11181
11182
#if ADA_SSSE3
11183
#include <tmmintrin.h>
11184
#endif
11185
11186
namespace ada::helpers {
11187
11188
template <typename out_iter>
11189
101k
void encode_json(std::string_view view, out_iter out) {
11190
  // trivial implementation. could be faster.
11191
101k
  const char* hexvalues =
11192
101k
      "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
11193
8.20M
  for (uint8_t c : view) {
11194
8.20M
    if (c == '\\') {
11195
4.74k
      *out++ = '\\';
11196
4.74k
      *out++ = '\\';
11197
8.19M
    } else if (c == '"') {
11198
2.41k
      *out++ = '\\';
11199
2.41k
      *out++ = '"';
11200
8.19M
    } else if (c <= 0x1f) {
11201
0
      *out++ = '\\';
11202
0
      *out++ = 'u';
11203
0
      *out++ = '0';
11204
0
      *out++ = '0';
11205
0
      *out++ = hexvalues[2 * c];
11206
0
      *out++ = hexvalues[2 * c + 1];
11207
8.19M
    } else {
11208
8.19M
      *out++ = c;
11209
8.19M
    }
11210
8.20M
  }
11211
101k
}
11212
11213
0
ada_unused std::string get_state(ada::state s) {
11214
0
  switch (s) {
11215
0
    case ada::state::AUTHORITY:
11216
0
      return "Authority";
11217
0
    case ada::state::SCHEME_START:
11218
0
      return "Scheme Start";
11219
0
    case ada::state::SCHEME:
11220
0
      return "Scheme";
11221
0
    case ada::state::HOST:
11222
0
      return "Host";
11223
0
    case ada::state::NO_SCHEME:
11224
0
      return "No Scheme";
11225
0
    case ada::state::FRAGMENT:
11226
0
      return "Fragment";
11227
0
    case ada::state::RELATIVE_SCHEME:
11228
0
      return "Relative Scheme";
11229
0
    case ada::state::RELATIVE_SLASH:
11230
0
      return "Relative Slash";
11231
0
    case ada::state::FILE:
11232
0
      return "File";
11233
0
    case ada::state::FILE_HOST:
11234
0
      return "File Host";
11235
0
    case ada::state::FILE_SLASH:
11236
0
      return "File Slash";
11237
0
    case ada::state::PATH_OR_AUTHORITY:
11238
0
      return "Path or Authority";
11239
0
    case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES:
11240
0
      return "Special Authority Ignore Slashes";
11241
0
    case ada::state::SPECIAL_AUTHORITY_SLASHES:
11242
0
      return "Special Authority Slashes";
11243
0
    case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY:
11244
0
      return "Special Relative or Authority";
11245
0
    case ada::state::QUERY:
11246
0
      return "Query";
11247
0
    case ada::state::PATH:
11248
0
      return "Path";
11249
0
    case ada::state::PATH_START:
11250
0
      return "Path Start";
11251
0
    case ada::state::OPAQUE_PATH:
11252
0
      return "Opaque Path";
11253
0
    case ada::state::PORT:
11254
0
      return "Port";
11255
0
    default:
11256
0
      return "unknown state";
11257
0
  }
11258
0
}
11259
11260
ada_really_inline std::optional<std::string_view> prune_hash(
11261
44.3k
    std::string_view& input) noexcept {
11262
  // compiles down to 20--30 instructions including a class to memchr (C
11263
  // function). this function should be quite fast.
11264
44.3k
  size_t location_of_first = input.find('#');
11265
44.3k
  if (location_of_first == std::string_view::npos) {
11266
43.5k
    return std::nullopt;
11267
43.5k
  }
11268
720
  std::string_view hash = input;
11269
720
  hash.remove_prefix(location_of_first + 1);
11270
720
  input.remove_suffix(input.size() - location_of_first);
11271
720
  return hash;
11272
44.3k
}
11273
11274
ada_really_inline bool shorten_path(std::string& path,
11275
27.9k
                                    ada::scheme::type type) noexcept {
11276
  // Let path be url's path.
11277
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
11278
  // Windows drive letter, then return.
11279
27.9k
  if (type == ada::scheme::type::FILE &&
11280
20.7k
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11281
12.0k
    if (checkers::is_normalized_windows_drive_letter(
11282
12.0k
            helpers::substring(path, 1))) {
11283
3.62k
      return false;
11284
3.62k
    }
11285
12.0k
  }
11286
11287
  // Remove path's last item, if any.
11288
24.3k
  size_t last_delimiter = path.rfind('/');
11289
24.3k
  if (last_delimiter != std::string::npos) {
11290
15.0k
    path.erase(last_delimiter);
11291
15.0k
    return true;
11292
15.0k
  }
11293
11294
9.28k
  return false;
11295
24.3k
}
11296
11297
ada_really_inline bool shorten_path(std::string_view& path,
11298
0
                                    ada::scheme::type type) noexcept {
11299
  // Let path be url's path.
11300
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
11301
  // Windows drive letter, then return.
11302
0
  if (type == ada::scheme::type::FILE &&
11303
0
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11304
0
    if (checkers::is_normalized_windows_drive_letter(
11305
0
            helpers::substring(path, 1))) {
11306
0
      return false;
11307
0
    }
11308
0
  }
11309
11310
  // Remove path's last item, if any.
11311
0
  if (!path.empty()) {
11312
0
    size_t slash_loc = path.rfind('/');
11313
0
    if (slash_loc != std::string_view::npos) {
11314
0
      path.remove_suffix(path.size() - slash_loc);
11315
0
      return true;
11316
0
    }
11317
0
  }
11318
11319
0
  return false;
11320
0
}
11321
11322
ada_really_inline void remove_ascii_tab_or_newline(
11323
116k
    std::string& input) noexcept {
11324
  // if this ever becomes a performance issue, we could use an approach similar
11325
  // to has_tabs_or_newline
11326
116k
  std::erase_if(input, ada::unicode::is_ascii_tab_or_newline);
11327
116k
}
11328
11329
ada_really_inline constexpr std::string_view substring(std::string_view input,
11330
27.9k
                                                       size_t pos) noexcept {
11331
27.9k
  ADA_ASSERT_TRUE(pos <= input.size());
11332
  // The following is safer but unneeded if we have the above line:
11333
  // return pos > input.size() ? std::string_view() : input.substr(pos);
11334
27.9k
  return input.substr(pos);
11335
27.9k
}
11336
11337
0
ada_really_inline void resize(std::string_view& input, size_t pos) noexcept {
11338
0
  ADA_ASSERT_TRUE(pos <= input.size());
11339
0
  input.remove_suffix(input.size() - pos);
11340
0
}
11341
11342
// computes the number of trailing zeroes
11343
// this is a private inline function only defined in this source file.
11344
13.6k
ada_really_inline int trailing_zeroes(uint32_t input_num) noexcept {
11345
#ifdef ADA_REGULAR_VISUAL_STUDIO
11346
  unsigned long ret;
11347
  // Search the mask data from least significant bit (LSB)
11348
  // to the most significant bit (MSB) for a set bit (1).
11349
  _BitScanForward(&ret, input_num);
11350
  return (int)ret;
11351
#else   // ADA_REGULAR_VISUAL_STUDIO
11352
13.6k
  return __builtin_ctzl(input_num);
11353
13.6k
#endif  // ADA_REGULAR_VISUAL_STUDIO
11354
13.6k
}
11355
11356
// starting at index location, this finds the next location of a character
11357
// :, /, \\, ? or [. If none is found, view.size() is returned.
11358
// For use within get_host_delimiter_location.
11359
#if ADA_SSSE3
11360
ada_really_inline size_t find_next_host_delimiter_special(
11361
    std::string_view view, size_t location) noexcept {
11362
  // first check for short strings in which case we do it naively.
11363
  if (view.size() - location < 16) {  // slow path
11364
    for (size_t i = location; i < view.size(); i++) {
11365
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11366
          view[i] == '?' || view[i] == '[') {
11367
        return i;
11368
      }
11369
    }
11370
    return size_t(view.size());
11371
  }
11372
  // fast path for long strings (expected to be common)
11373
  // Using SSSE3's _mm_shuffle_epi8 for table lookup (same approach as NEON)
11374
  size_t i = location;
11375
  const __m128i low_mask =
11376
      _mm_setr_epi8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11377
                    0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
11378
  const __m128i high_mask =
11379
      _mm_setr_epi8(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
11380
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11381
  const __m128i fmask = _mm_set1_epi8(0xf);
11382
  const __m128i zero = _mm_setzero_si128();
11383
  for (; i + 15 < view.size(); i += 16) {
11384
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11385
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
11386
    __m128i highpart = _mm_shuffle_epi8(
11387
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
11388
    __m128i classify = _mm_and_si128(lowpart, highpart);
11389
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
11390
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
11391
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
11392
    // avoid false positives.
11393
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
11394
    if (mask != 0) {
11395
      return i + trailing_zeroes(static_cast<uint32_t>(mask));
11396
    }
11397
  }
11398
  if (i < view.size()) {
11399
    __m128i word =
11400
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11401
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
11402
    __m128i highpart = _mm_shuffle_epi8(
11403
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
11404
    __m128i classify = _mm_and_si128(lowpart, highpart);
11405
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
11406
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
11407
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
11408
    // avoid false positives.
11409
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
11410
    if (mask != 0) {
11411
      return view.length() - 16 + trailing_zeroes(static_cast<uint32_t>(mask));
11412
    }
11413
  }
11414
  return size_t(view.size());
11415
}
11416
#elif ADA_NEON
11417
// The ada_make_uint8x16_t macro is necessary because Visual Studio does not
11418
// support direct initialization of uint8x16_t. See
11419
// https://developercommunity.visualstudio.com/t/error-C2078:-too-many-initializers-whe/402911?q=backend+neon
11420
#ifndef ada_make_uint8x16_t
11421
#define ada_make_uint8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
11422
                            x13, x14, x15, x16)                                \
11423
  ([=]() {                                                                     \
11424
    static uint8_t array[16] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8,          \
11425
                                x9, x10, x11, x12, x13, x14, x15, x16};        \
11426
    return vld1q_u8(array);                                                    \
11427
  }())
11428
#endif
11429
11430
ada_really_inline size_t find_next_host_delimiter_special(
11431
    std::string_view view, size_t location) noexcept {
11432
  // first check for short strings in which case we do it naively.
11433
  if (view.size() - location < 16) {  // slow path
11434
    for (size_t i = location; i < view.size(); i++) {
11435
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11436
          view[i] == '?' || view[i] == '[') {
11437
        return i;
11438
      }
11439
    }
11440
    return size_t(view.size());
11441
  }
11442
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
11443
    uint8x16_t bit_mask =
11444
        ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
11445
                            0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
11446
    uint8x16_t minput = vandq_u8(input, bit_mask);
11447
    uint8x16_t tmp = vpaddq_u8(minput, minput);
11448
    tmp = vpaddq_u8(tmp, tmp);
11449
    tmp = vpaddq_u8(tmp, tmp);
11450
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
11451
  };
11452
11453
  // fast path for long strings (expected to be common)
11454
  size_t i = location;
11455
  uint8x16_t low_mask =
11456
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11457
                          0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
11458
  uint8x16_t high_mask =
11459
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
11460
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11461
  uint8x16_t fmask = vmovq_n_u8(0xf);
11462
  uint8x16_t zero{0};
11463
  for (; i + 15 < view.size(); i += 16) {
11464
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
11465
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11466
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11467
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11468
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11469
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11470
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11471
      return i + trailing_zeroes(is_non_zero);
11472
    }
11473
  }
11474
11475
  if (i < view.size()) {
11476
    uint8x16_t word =
11477
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
11478
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11479
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11480
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11481
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11482
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11483
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11484
      return view.length() - 16 + trailing_zeroes(is_non_zero);
11485
    }
11486
  }
11487
  return size_t(view.size());
11488
}
11489
#elif ADA_SSE2
11490
ada_really_inline size_t find_next_host_delimiter_special(
11491
62.3k
    std::string_view view, size_t location) noexcept {
11492
  // first check for short strings in which case we do it naively.
11493
62.3k
  if (view.size() - location < 16) {  // slow path
11494
409k
    for (size_t i = location; i < view.size(); i++) {
11495
379k
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11496
366k
          view[i] == '?' || view[i] == '[') {
11497
14.4k
        return i;
11498
14.4k
      }
11499
379k
    }
11500
29.9k
    return size_t(view.size());
11501
44.4k
  }
11502
  // fast path for long strings (expected to be common)
11503
17.9k
  size_t i = location;
11504
17.9k
  const __m128i mask1 = _mm_set1_epi8(':');
11505
17.9k
  const __m128i mask2 = _mm_set1_epi8('/');
11506
17.9k
  const __m128i mask3 = _mm_set1_epi8('\\');
11507
17.9k
  const __m128i mask4 = _mm_set1_epi8('?');
11508
17.9k
  const __m128i mask5 = _mm_set1_epi8('[');
11509
11510
47.6k
  for (; i + 15 < view.size(); i += 16) {
11511
41.4k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11512
41.4k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11513
41.4k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11514
41.4k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11515
41.4k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11516
41.4k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11517
41.4k
    __m128i m = _mm_or_si128(
11518
41.4k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11519
41.4k
    int mask = _mm_movemask_epi8(m);
11520
41.4k
    if (mask != 0) {
11521
11.8k
      return i + trailing_zeroes(mask);
11522
11.8k
    }
11523
41.4k
  }
11524
6.16k
  if (i < view.size()) {
11525
5.49k
    __m128i word =
11526
5.49k
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11527
5.49k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11528
5.49k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11529
5.49k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11530
5.49k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11531
5.49k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11532
5.49k
    __m128i m = _mm_or_si128(
11533
5.49k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11534
5.49k
    int mask = _mm_movemask_epi8(m);
11535
5.49k
    if (mask != 0) {
11536
1.41k
      return view.length() - 16 + trailing_zeroes(mask);
11537
1.41k
    }
11538
5.49k
  }
11539
4.75k
  return size_t(view.length());
11540
6.16k
}
11541
#elif ADA_LSX
11542
ada_really_inline size_t find_next_host_delimiter_special(
11543
    std::string_view view, size_t location) noexcept {
11544
  // first check for short strings in which case we do it naively.
11545
  if (view.size() - location < 16) {  // slow path
11546
    for (size_t i = location; i < view.size(); i++) {
11547
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11548
          view[i] == '?' || view[i] == '[') {
11549
        return i;
11550
      }
11551
    }
11552
    return size_t(view.size());
11553
  }
11554
  // fast path for long strings (expected to be common)
11555
  size_t i = location;
11556
  const __m128i mask1 = __lsx_vrepli_b(':');
11557
  const __m128i mask2 = __lsx_vrepli_b('/');
11558
  const __m128i mask3 = __lsx_vrepli_b('\\');
11559
  const __m128i mask4 = __lsx_vrepli_b('?');
11560
  const __m128i mask5 = __lsx_vrepli_b('[');
11561
11562
  for (; i + 15 < view.size(); i += 16) {
11563
    __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0);
11564
    __m128i m1 = __lsx_vseq_b(word, mask1);
11565
    __m128i m2 = __lsx_vseq_b(word, mask2);
11566
    __m128i m3 = __lsx_vseq_b(word, mask3);
11567
    __m128i m4 = __lsx_vseq_b(word, mask4);
11568
    __m128i m5 = __lsx_vseq_b(word, mask5);
11569
    __m128i m =
11570
        __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5);
11571
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11572
    if (mask != 0) {
11573
      return i + trailing_zeroes(mask);
11574
    }
11575
  }
11576
  if (i < view.size()) {
11577
    __m128i word =
11578
        __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0);
11579
    __m128i m1 = __lsx_vseq_b(word, mask1);
11580
    __m128i m2 = __lsx_vseq_b(word, mask2);
11581
    __m128i m3 = __lsx_vseq_b(word, mask3);
11582
    __m128i m4 = __lsx_vseq_b(word, mask4);
11583
    __m128i m5 = __lsx_vseq_b(word, mask5);
11584
    __m128i m =
11585
        __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5);
11586
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11587
    if (mask != 0) {
11588
      return view.length() - 16 + trailing_zeroes(mask);
11589
    }
11590
  }
11591
  return size_t(view.length());
11592
}
11593
#elif ADA_RVV
11594
ada_really_inline size_t find_next_host_delimiter_special(
11595
    std::string_view view, size_t location) noexcept {
11596
  // The LUT approach was a bit slower on the SpacemiT X60, but I could see it
11597
  // being faster on future hardware.
11598
#if 0
11599
  // LUT generated using: s=":/\\?["; list(zip([((ord(c)>>2)&0xF)for c in s],s))
11600
  static const uint8_t tbl[16] = {
11601
    0xF, 0, 0, 0, 0, 0, '[', '\\', 0, 0, 0, '/', 0, 0, ':', '?'
11602
  };
11603
  vuint8m1_t vtbl = __riscv_vle8_v_u8m1(tbl, 16);
11604
#endif
11605
  uint8_t* src = (uint8_t*)view.data() + location;
11606
  for (size_t vl, n = view.size() - location; n > 0;
11607
       n -= vl, src += vl, location += vl) {
11608
    vl = __riscv_vsetvl_e8m1(n);
11609
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
11610
#if 0
11611
    vuint8m1_t vidx = __riscv_vand(__riscv_vsrl(v, 2, vl), 0xF, vl);
11612
    vuint8m1_t vlut = __riscv_vrgather(vtbl, vidx, vl);
11613
    vbool8_t m = __riscv_vmseq(v, vlut, vl);
11614
#else
11615
    vbool8_t m1 = __riscv_vmseq(v, ':', vl);
11616
    vbool8_t m2 = __riscv_vmseq(v, '/', vl);
11617
    vbool8_t m3 = __riscv_vmseq(v, '?', vl);
11618
    vbool8_t m4 = __riscv_vmseq(v, '[', vl);
11619
    vbool8_t m5 = __riscv_vmseq(v, '\\', vl);
11620
    vbool8_t m = __riscv_vmor(
11621
        __riscv_vmor(__riscv_vmor(m1, m2, vl), __riscv_vmor(m3, m4, vl), vl),
11622
        m5, vl);
11623
#endif
11624
    long idx = __riscv_vfirst(m, vl);
11625
    if (idx >= 0) return location + idx;
11626
  }
11627
  return size_t(view.size());
11628
}
11629
#else
11630
// : / [ \\ ?
11631
static constexpr std::array<uint8_t, 256> special_host_delimiters =
11632
    []() consteval {
11633
      std::array<uint8_t, 256> result{};
11634
      for (int i : {':', '/', '[', '\\', '?'}) {
11635
        result[i] = 1;
11636
      }
11637
      return result;
11638
    }();
11639
// credit: @the-moisrex recommended a table-based approach
11640
ada_really_inline size_t find_next_host_delimiter_special(
11641
    std::string_view view, size_t location) noexcept {
11642
  auto const str = view.substr(location);
11643
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
11644
    if (special_host_delimiters[(uint8_t)*pos]) {
11645
      return pos - str.begin() + location;
11646
    }
11647
  }
11648
  return size_t(view.size());
11649
}
11650
#endif
11651
11652
// starting at index location, this finds the next location of a character
11653
// :, /, ? or [. If none is found, view.size() is returned.
11654
// For use within get_host_delimiter_location.
11655
#if ADA_SSSE3
11656
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11657
                                                  size_t location) noexcept {
11658
  // first check for short strings in which case we do it naively.
11659
  if (view.size() - location < 16) {  // slow path
11660
    for (size_t i = location; i < view.size(); i++) {
11661
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11662
          view[i] == '[') {
11663
        return i;
11664
      }
11665
    }
11666
    return size_t(view.size());
11667
  }
11668
  // fast path for long strings (expected to be common)
11669
  size_t i = location;
11670
  // Lookup tables for bit classification:
11671
  // ':' (0x3A): low[0xA]=0x01, high[0x3]=0x01 -> match
11672
  // '/' (0x2F): low[0xF]=0x02, high[0x2]=0x02 -> match
11673
  // '?' (0x3F): low[0xF]=0x01, high[0x3]=0x01 -> match
11674
  // '[' (0x5B): low[0xB]=0x04, high[0x5]=0x04 -> match
11675
  const __m128i low_mask =
11676
      _mm_setr_epi8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11677
                    0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
11678
  const __m128i high_mask =
11679
      _mm_setr_epi8(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
11680
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11681
  const __m128i fmask = _mm_set1_epi8(0xf);
11682
  const __m128i zero = _mm_setzero_si128();
11683
11684
  for (; i + 15 < view.size(); i += 16) {
11685
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11686
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
11687
    __m128i highpart = _mm_shuffle_epi8(
11688
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
11689
    __m128i classify = _mm_and_si128(lowpart, highpart);
11690
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
11691
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
11692
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
11693
    // avoid false positives.
11694
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
11695
    if (mask != 0) {
11696
      return i + trailing_zeroes(static_cast<uint32_t>(mask));
11697
    }
11698
  }
11699
11700
  if (i < view.size()) {
11701
    __m128i word =
11702
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11703
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
11704
    __m128i highpart = _mm_shuffle_epi8(
11705
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
11706
    __m128i classify = _mm_and_si128(lowpart, highpart);
11707
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
11708
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
11709
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
11710
    // avoid false positives.
11711
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
11712
    if (mask != 0) {
11713
      return view.length() - 16 + trailing_zeroes(static_cast<uint32_t>(mask));
11714
    }
11715
  }
11716
  return size_t(view.size());
11717
}
11718
#elif ADA_NEON
11719
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11720
                                                  size_t location) noexcept {
11721
  // first check for short strings in which case we do it naively.
11722
  if (view.size() - location < 16) {  // slow path
11723
    for (size_t i = location; i < view.size(); i++) {
11724
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11725
          view[i] == '[') {
11726
        return i;
11727
      }
11728
    }
11729
    return size_t(view.size());
11730
  }
11731
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
11732
    uint8x16_t bit_mask =
11733
        ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
11734
                            0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
11735
    uint8x16_t minput = vandq_u8(input, bit_mask);
11736
    uint8x16_t tmp = vpaddq_u8(minput, minput);
11737
    tmp = vpaddq_u8(tmp, tmp);
11738
    tmp = vpaddq_u8(tmp, tmp);
11739
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
11740
  };
11741
11742
  // fast path for long strings (expected to be common)
11743
  size_t i = location;
11744
  uint8x16_t low_mask =
11745
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11746
                          0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
11747
  uint8x16_t high_mask =
11748
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
11749
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11750
  uint8x16_t fmask = vmovq_n_u8(0xf);
11751
  uint8x16_t zero{0};
11752
  for (; i + 15 < view.size(); i += 16) {
11753
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
11754
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11755
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11756
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11757
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11758
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11759
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11760
      return i + trailing_zeroes(is_non_zero);
11761
    }
11762
  }
11763
11764
  if (i < view.size()) {
11765
    uint8x16_t word =
11766
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
11767
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11768
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11769
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11770
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11771
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11772
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11773
      return view.length() - 16 + trailing_zeroes(is_non_zero);
11774
    }
11775
  }
11776
  return size_t(view.size());
11777
}
11778
#elif ADA_SSE2
11779
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11780
1.22k
                                                  size_t location) noexcept {
11781
  // first check for short strings in which case we do it naively.
11782
1.22k
  if (view.size() - location < 16) {  // slow path
11783
1.77k
    for (size_t i = location; i < view.size(); i++) {
11784
1.45k
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11785
1.30k
          view[i] == '[') {
11786
310
        return i;
11787
310
      }
11788
1.45k
    }
11789
318
    return size_t(view.size());
11790
628
  }
11791
  // fast path for long strings (expected to be common)
11792
596
  size_t i = location;
11793
596
  const __m128i mask1 = _mm_set1_epi8(':');
11794
596
  const __m128i mask2 = _mm_set1_epi8('/');
11795
596
  const __m128i mask4 = _mm_set1_epi8('?');
11796
596
  const __m128i mask5 = _mm_set1_epi8('[');
11797
11798
2.01k
  for (; i + 15 < view.size(); i += 16) {
11799
1.83k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11800
1.83k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11801
1.83k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11802
1.83k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11803
1.83k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11804
1.83k
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
11805
1.83k
    int mask = _mm_movemask_epi8(m);
11806
1.83k
    if (mask != 0) {
11807
412
      return i + trailing_zeroes(mask);
11808
412
    }
11809
1.83k
  }
11810
184
  if (i < view.size()) {
11811
140
    __m128i word =
11812
140
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11813
140
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11814
140
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11815
140
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11816
140
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11817
140
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
11818
140
    int mask = _mm_movemask_epi8(m);
11819
140
    if (mask != 0) {
11820
68
      return view.length() - 16 + trailing_zeroes(mask);
11821
68
    }
11822
140
  }
11823
116
  return size_t(view.length());
11824
184
}
11825
#elif ADA_LSX
11826
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11827
                                                  size_t location) noexcept {
11828
  // first check for short strings in which case we do it naively.
11829
  if (view.size() - location < 16) {  // slow path
11830
    for (size_t i = location; i < view.size(); i++) {
11831
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11832
          view[i] == '[') {
11833
        return i;
11834
      }
11835
    }
11836
    return size_t(view.size());
11837
  }
11838
  // fast path for long strings (expected to be common)
11839
  size_t i = location;
11840
  const __m128i mask1 = __lsx_vrepli_b(':');
11841
  const __m128i mask2 = __lsx_vrepli_b('/');
11842
  const __m128i mask4 = __lsx_vrepli_b('?');
11843
  const __m128i mask5 = __lsx_vrepli_b('[');
11844
11845
  for (; i + 15 < view.size(); i += 16) {
11846
    __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0);
11847
    __m128i m1 = __lsx_vseq_b(word, mask1);
11848
    __m128i m2 = __lsx_vseq_b(word, mask2);
11849
    __m128i m4 = __lsx_vseq_b(word, mask4);
11850
    __m128i m5 = __lsx_vseq_b(word, mask5);
11851
    __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5));
11852
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11853
    if (mask != 0) {
11854
      return i + trailing_zeroes(mask);
11855
    }
11856
  }
11857
  if (i < view.size()) {
11858
    __m128i word =
11859
        __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0);
11860
    __m128i m1 = __lsx_vseq_b(word, mask1);
11861
    __m128i m2 = __lsx_vseq_b(word, mask2);
11862
    __m128i m4 = __lsx_vseq_b(word, mask4);
11863
    __m128i m5 = __lsx_vseq_b(word, mask5);
11864
    __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5));
11865
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11866
    if (mask != 0) {
11867
      return view.length() - 16 + trailing_zeroes(mask);
11868
    }
11869
  }
11870
  return size_t(view.length());
11871
}
11872
#elif ADA_RVV
11873
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11874
                                                  size_t location) noexcept {
11875
  uint8_t* src = (uint8_t*)view.data() + location;
11876
  for (size_t vl, n = view.size() - location; n > 0;
11877
       n -= vl, src += vl, location += vl) {
11878
    vl = __riscv_vsetvl_e8m1(n);
11879
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
11880
    vbool8_t m1 = __riscv_vmseq(v, ':', vl);
11881
    vbool8_t m2 = __riscv_vmseq(v, '/', vl);
11882
    vbool8_t m3 = __riscv_vmseq(v, '?', vl);
11883
    vbool8_t m4 = __riscv_vmseq(v, '[', vl);
11884
    vbool8_t m =
11885
        __riscv_vmor(__riscv_vmor(m1, m2, vl), __riscv_vmor(m3, m4, vl), vl);
11886
    long idx = __riscv_vfirst(m, vl);
11887
    if (idx >= 0) return location + idx;
11888
  }
11889
  return size_t(view.size());
11890
}
11891
#else
11892
// : / [ ?
11893
static constexpr std::array<uint8_t, 256> host_delimiters = []() consteval {
11894
  std::array<uint8_t, 256> result{};
11895
  for (int i : {':', '/', '?', '['}) {
11896
    result[i] = 1;
11897
  }
11898
  return result;
11899
}();
11900
// credit: @the-moisrex recommended a table-based approach
11901
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11902
                                                  size_t location) noexcept {
11903
  auto const str = view.substr(location);
11904
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
11905
    if (host_delimiters[(uint8_t)*pos]) {
11906
      return pos - str.begin() + location;
11907
    }
11908
  }
11909
  return size_t(view.size());
11910
}
11911
#endif
11912
11913
ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
11914
59.0k
    const bool is_special, std::string_view& view) noexcept {
11915
  /**
11916
   * The spec at https://url.spec.whatwg.org/#hostname-state expects us to
11917
   * compute a variable called insideBrackets but this variable is only used
11918
   * once, to check whether a ':' character was found outside brackets. Exact
11919
   * text: "Otherwise, if c is U+003A (:) and insideBrackets is false, then:".
11920
   * It is conceptually simpler and arguably more efficient to just return a
11921
   * Boolean indicating whether ':' was found outside brackets.
11922
   */
11923
59.0k
  const size_t view_size = view.size();
11924
59.0k
  size_t location = 0;
11925
59.0k
  bool found_colon = false;
11926
  /**
11927
   * Performance analysis:
11928
   *
11929
   * We are basically seeking the end of the hostname which can be indicated
11930
   * by the end of the view, or by one of the characters ':', '/', '?', '\\'
11931
   * (where '\\' is only applicable for special URLs). However, these must
11932
   * appear outside a bracket range. E.g., if you have [something?]fd: then the
11933
   * '?' does not count.
11934
   *
11935
   * So we can skip ahead to the next delimiter, as long as we include '[' in
11936
   * the set of delimiters, and that we handle it first.
11937
   *
11938
   * So the trick is to have a fast function that locates the next delimiter.
11939
   * Unless we find '[', then it only needs to be called once! Ideally, such a
11940
   * function would be provided by the C++ standard library, but it seems that
11941
   * find_first_of is not very fast, so we are forced to roll our own.
11942
   *
11943
   * We do not break into two loops for speed, but for clarity.
11944
   */
11945
59.0k
  if (is_special) {
11946
    // We move to the next delimiter.
11947
58.2k
    location = find_next_host_delimiter_special(view, location);
11948
    // Unless we find '[' then we are going only going to have to call
11949
    // find_next_host_delimiter_special once.
11950
62.3k
    for (; location < view_size;
11951
58.2k
         location = find_next_host_delimiter_special(view, location)) {
11952
27.6k
      if (view[location] == '[') {
11953
4.36k
        location = view.find(']', location);
11954
4.36k
        if (location == std::string_view::npos) {
11955
          // performance: view.find might get translated to a memchr, which
11956
          // has no notion of std::string_view::npos, so the code does not
11957
          // reflect the assembly.
11958
262
          location = view_size;
11959
262
          break;
11960
262
        }
11961
23.3k
      } else {
11962
23.3k
        found_colon = view[location] == ':';
11963
23.3k
        break;
11964
23.3k
      }
11965
27.6k
    }
11966
58.2k
  } else {
11967
    // We move to the next delimiter.
11968
762
    location = find_next_host_delimiter(view, location);
11969
    // Unless we find '[' then we are going only going to have to call
11970
    // find_next_host_delimiter_special once.
11971
1.22k
    for (; location < view_size;
11972
790
         location = find_next_host_delimiter(view, location)) {
11973
790
      if (view[location] == '[') {
11974
510
        location = view.find(']', location);
11975
510
        if (location == std::string_view::npos) {
11976
          // performance: view.find might get translated to a memchr, which
11977
          // has no notion of std::string_view::npos, so the code does not
11978
          // reflect the assembly.
11979
48
          location = view_size;
11980
48
          break;
11981
48
        }
11982
510
      } else {
11983
280
        found_colon = view[location] == ':';
11984
280
        break;
11985
280
      }
11986
790
    }
11987
762
  }
11988
  // performance: remove_suffix may translate into a single instruction.
11989
59.0k
  view.remove_suffix(view_size - location);
11990
59.0k
  return {location, found_colon};
11991
59.0k
}
11992
11993
44.3k
void trim_c0_whitespace(std::string_view& input) noexcept {
11994
47.4k
  while (!input.empty() &&
11995
47.3k
         ada::unicode::is_c0_control_or_space(input.front())) {
11996
3.16k
    input.remove_prefix(1);
11997
3.16k
  }
11998
46.4k
  while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
11999
2.14k
    input.remove_suffix(1);
12000
2.14k
  }
12001
44.3k
}
12002
12003
ada_really_inline void parse_prepared_path(std::string_view input,
12004
                                           ada::scheme::type type,
12005
21.2k
                                           std::string& path) {
12006
21.2k
  ada_log("parse_prepared_path ", input);
12007
21.2k
  uint8_t accumulator = checkers::path_signature(input);
12008
  // Let us first detect a trivial case.
12009
  // If it is special, we check that we have no dot, no %,  no \ and no
12010
  // character needing percent encoding. Otherwise, we check that we have no %,
12011
  // no dot, and no character needing percent encoding.
12012
21.2k
  constexpr uint8_t need_encoding = 1;
12013
21.2k
  constexpr uint8_t backslash_char = 2;
12014
21.2k
  constexpr uint8_t dot_char = 4;
12015
21.2k
  constexpr uint8_t percent_char = 8;
12016
21.2k
  bool special = type != ada::scheme::NOT_SPECIAL;
12017
21.2k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
12018
10.8k
                                      checkers::is_windows_drive_letter(input));
12019
21.2k
  bool trivial_path =
12020
21.2k
      (special ? (accumulator == 0)
12021
21.2k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
12022
1.00k
                  0)) &&
12023
3.95k
      (!may_need_slow_file_handling);
12024
21.2k
  if (accumulator == dot_char && !may_need_slow_file_handling) {
12025
    // '4' means that we have at least one dot, but nothing that requires
12026
    // percent encoding or decoding. The only part that is not trivial is
12027
    // that we may have single dots and double dots path segments.
12028
    // If we have such segments, then we either have a path that begins
12029
    // with '.' (easy to check), or we have the sequence './'.
12030
    // Note: input cannot be empty, it must at least contain one character ('.')
12031
    // Note: we know that '\' is not present.
12032
4.01k
    if (input[0] != '.') {
12033
3.02k
      size_t slashdot = 0;
12034
3.02k
      bool dot_is_file = true;
12035
14.8k
      for (;;) {
12036
14.8k
        slashdot = input.find("/.", slashdot);
12037
14.8k
        if (slashdot == std::string_view::npos) {  // common case
12038
3.02k
          break;
12039
11.8k
        } else {  // uncommon
12040
          // only three cases matter: /./, /.. or a final /
12041
11.8k
          slashdot += 2;
12042
11.8k
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
12043
2.87k
                           input[slashdot] == '/');
12044
11.8k
        }
12045
14.8k
      }
12046
3.02k
      trivial_path = dot_is_file;
12047
3.02k
    }
12048
4.01k
  }
12049
21.2k
  if (trivial_path) {
12050
5.03k
    ada_log("parse_path trivial");
12051
5.03k
    path += '/';
12052
5.03k
    path += input;
12053
5.03k
    return;
12054
5.03k
  }
12055
  // We are going to need to look a bit at the path, but let us see if we can
12056
  // ignore percent encoding *and* backslashes *and* percent characters.
12057
  // Except for the trivial case, this is likely to capture 99% of paths out
12058
  // there.
12059
16.2k
  bool fast_path =
12060
16.2k
      (special &&
12061
15.3k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
12062
2.87k
      (type != ada::scheme::type::FILE);
12063
16.2k
  if (fast_path) {
12064
1.42k
    ada_log("parse_prepared_path fast");
12065
    // Here we don't need to worry about \ or percent encoding.
12066
    // We also do not have a file protocol. We might have dots, however,
12067
    // but dots must as appear as '.', and they cannot be encoded because
12068
    // the symbol '%' is not present.
12069
1.42k
    size_t previous_location = 0;  // We start at 0.
12070
17.8k
    do {
12071
17.8k
      size_t new_location = input.find('/', previous_location);
12072
      // std::string_view path_view = input;
12073
      //  We process the last segment separately:
12074
17.8k
      if (new_location == std::string_view::npos) {
12075
1.42k
        std::string_view path_view = input.substr(previous_location);
12076
1.42k
        if (path_view == "..") {  // The path ends with ..
12077
          // e.g., if you receive ".." with an empty path, you go to "/".
12078
186
          if (path.empty()) {
12079
71
            path = '/';
12080
71
            return;
12081
71
          }
12082
          // Fast case where we have nothing to do:
12083
115
          if (path.back() == '/') {
12084
44
            return;
12085
44
          }
12086
          // If you have the path "/joe/myfriend",
12087
          // then you delete 'myfriend'.
12088
71
          path.resize(path.rfind('/') + 1);
12089
71
          return;
12090
115
        }
12091
1.23k
        path += '/';
12092
1.23k
        if (path_view != ".") {
12093
983
          path.append(path_view);
12094
983
        }
12095
1.23k
        return;
12096
16.4k
      } else {
12097
        // This is a non-final segment.
12098
16.4k
        std::string_view path_view =
12099
16.4k
            input.substr(previous_location, new_location - previous_location);
12100
16.4k
        previous_location = new_location + 1;
12101
16.4k
        if (path_view == "..") {
12102
3.86k
          size_t last_delimiter = path.rfind('/');
12103
3.86k
          if (last_delimiter != std::string::npos) {
12104
1.96k
            path.erase(last_delimiter);
12105
1.96k
          }
12106
12.5k
        } else if (path_view != ".") {
12107
10.5k
          path += '/';
12108
10.5k
          path.append(path_view);
12109
10.5k
        }
12110
16.4k
      }
12111
17.8k
    } while (true);
12112
14.8k
  } else {
12113
14.8k
    ada_log("parse_path slow");
12114
    // we have reached the general case
12115
14.8k
    bool needs_percent_encoding = (accumulator & 1);
12116
14.8k
    std::string path_buffer_tmp;
12117
81.1k
    do {
12118
81.1k
      size_t location = (special && (accumulator & 2))
12119
81.1k
                            ? input.find_first_of("/\\")
12120
81.1k
                            : input.find('/');
12121
81.1k
      std::string_view path_view = input;
12122
81.1k
      if (location != std::string_view::npos) {
12123
66.2k
        path_view.remove_suffix(path_view.size() - location);
12124
66.2k
        input.remove_prefix(location + 1);
12125
66.2k
      }
12126
      // path_buffer is either path_view or it might point at a percent encoded
12127
      // temporary file.
12128
81.1k
      std::string_view path_buffer =
12129
81.1k
          (needs_percent_encoding &&
12130
47.7k
           ada::unicode::percent_encode<false>(
12131
47.7k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
12132
81.1k
              ? path_buffer_tmp
12133
81.1k
              : path_view;
12134
81.1k
      if (unicode::is_double_dot_path_segment(path_buffer)) {
12135
17.3k
        helpers::shorten_path(path, type);
12136
17.3k
        if (location == std::string_view::npos) {
12137
1.37k
          path += '/';
12138
1.37k
        }
12139
63.7k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
12140
4.89k
                 (location == std::string_view::npos)) {
12141
439
        path += '/';
12142
439
      }
12143
      // Otherwise, if path_buffer is not a single-dot path segment, then:
12144
63.2k
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
12145
        // If url's scheme is "file", url's path is empty, and path_buffer is a
12146
        // Windows drive letter, then replace the second code point in
12147
        // path_buffer with U+003A (:).
12148
58.8k
        if (type == ada::scheme::type::FILE && path.empty() &&
12149
12.9k
            checkers::is_windows_drive_letter(path_buffer)) {
12150
861
          path += '/';
12151
861
          path += path_buffer[0];
12152
861
          path += ':';
12153
861
          path_buffer.remove_prefix(2);
12154
861
          path.append(path_buffer);
12155
57.9k
        } else {
12156
          // Append path_buffer to url's path.
12157
57.9k
          path += '/';
12158
57.9k
          path.append(path_buffer);
12159
57.9k
        }
12160
58.8k
      }
12161
81.1k
      if (location == std::string_view::npos) {
12162
14.8k
        return;
12163
14.8k
      }
12164
81.1k
    } while (true);
12165
14.8k
  }
12166
16.2k
}
12167
12168
0
bool overlaps(std::string_view input1, const std::string& input2) noexcept {
12169
0
  ada_log("helpers::overlaps check if string_view '", input1, "' [",
12170
0
          input1.size(), " bytes] is part of string '", input2, "' [",
12171
0
          input2.size(), " bytes]");
12172
0
  return !input1.empty() && !input2.empty() && input1.data() >= input2.data() &&
12173
0
         input1.data() < input2.data() + input2.size();
12174
0
}
12175
12176
template <class url_type>
12177
ada_really_inline void strip_trailing_spaces_from_opaque_path(
12178
32
    url_type& url) noexcept {
12179
32
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
12180
32
  if (!url.has_opaque_path) return;
12181
0
  if (url.has_hash()) return;
12182
0
  if (url.has_search()) return;
12183
12184
0
  auto path = std::string(url.get_pathname());
12185
0
  while (!path.empty() && path.back() == ' ') {
12186
0
    path.resize(path.size() - 1);
12187
0
  }
12188
0
  url.update_base_pathname(path);
12189
0
}
void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url>(ada::url&)
Line
Count
Source
12178
16
    url_type& url) noexcept {
12179
16
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
12180
16
  if (!url.has_opaque_path) return;
12181
0
  if (url.has_hash()) return;
12182
0
  if (url.has_search()) return;
12183
12184
0
  auto path = std::string(url.get_pathname());
12185
0
  while (!path.empty() && path.back() == ' ') {
12186
0
    path.resize(path.size() - 1);
12187
0
  }
12188
0
  url.update_base_pathname(path);
12189
0
}
void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url_aggregator>(ada::url_aggregator&)
Line
Count
Source
12178
16
    url_type& url) noexcept {
12179
16
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
12180
16
  if (!url.has_opaque_path) return;
12181
0
  if (url.has_hash()) return;
12182
0
  if (url.has_search()) return;
12183
12184
0
  auto path = std::string(url.get_pathname());
12185
0
  while (!path.empty() && path.back() == ' ') {
12186
0
    path.resize(path.size() - 1);
12187
0
  }
12188
0
  url.update_base_pathname(path);
12189
0
}
12190
12191
// @ / \\ ?
12192
static constexpr std::array<uint8_t, 256> authority_delimiter_special =
12193
    []() consteval {
12194
      std::array<uint8_t, 256> result{};
12195
      for (uint8_t i : {'@', '/', '\\', '?'}) {
12196
        result[i] = 1;
12197
      }
12198
      return result;
12199
    }();
12200
// credit: @the-moisrex recommended a table-based approach
12201
ada_really_inline size_t
12202
14.5k
find_authority_delimiter_special(std::string_view view) noexcept {
12203
  // performance note: we might be able to gain further performance
12204
  // with SIMD intrinsics.
12205
68.1k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12206
67.0k
    if (authority_delimiter_special[(uint8_t)*pos]) {
12207
13.4k
      return pos - view.begin();
12208
13.4k
    }
12209
67.0k
  }
12210
1.14k
  return size_t(view.size());
12211
14.5k
}
12212
12213
// @ / ?
12214
static constexpr std::array<uint8_t, 256> authority_delimiter = []() consteval {
12215
  std::array<uint8_t, 256> result{};
12216
  for (uint8_t i : {'@', '/', '?'}) {
12217
    result[i] = 1;
12218
  }
12219
  return result;
12220
}();
12221
// credit: @the-moisrex recommended a table-based approach
12222
ada_really_inline size_t
12223
1.24k
find_authority_delimiter(std::string_view view) noexcept {
12224
  // performance note: we might be able to gain further performance
12225
  // with SIMD instrinsics.
12226
6.58k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12227
6.45k
    if (authority_delimiter[(uint8_t)*pos]) {
12228
1.11k
      return pos - view.begin();
12229
1.11k
    }
12230
6.45k
  }
12231
130
  return size_t(view.size());
12232
1.24k
}
12233
12234
}  // namespace ada::helpers
12235
12236
namespace ada {
12237
0
ada_warn_unused std::string to_string(ada::state state) {
12238
0
  return ada::helpers::get_state(state);
12239
0
}
12240
#undef ada_make_uint8x16_t
12241
}  // namespace ada
12242
/* end file src/helpers.cpp */
12243
/* begin file src/url.cpp */
12244
12245
#include <numeric>
12246
#include <algorithm>
12247
#include <iterator>
12248
#include <ranges>
12249
#include <string>
12250
#include <string_view>
12251
12252
namespace ada {
12253
12254
259
bool url::parse_opaque_host(std::string_view input) {
12255
259
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
12256
259
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
12257
19
    return is_valid = false;
12258
19
  }
12259
12260
  // Return the result of running UTF-8 percent-encode on input using the C0
12261
  // control percent-encode set.
12262
240
  host = ada::unicode::percent_encode(
12263
240
      input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
12264
240
  return true;
12265
259
}
12266
12267
2.19k
bool url::parse_ipv4(std::string_view input) {
12268
2.19k
  ada_log("parse_ipv4 ", input, " [", input.size(), " bytes]");
12269
2.19k
  if (input.back() == '.') {
12270
25
    input.remove_suffix(1);
12271
25
  }
12272
2.19k
  size_t digit_count{0};
12273
2.19k
  int pure_decimal_count = 0;  // entries that are decimal
12274
2.19k
  std::string_view original_input =
12275
2.19k
      input;  // we might use this if pure_decimal_count == 4.
12276
2.19k
  uint64_t ipv4{0};
12277
  // we could unroll for better performance?
12278
2.60k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
12279
2.58k
    uint32_t
12280
2.58k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
12281
2.58k
    bool is_hex = checkers::has_hex_prefix(input);
12282
2.58k
    if (is_hex && ((input.length() == 2) ||
12283
944
                   ((input.length() > 2) && (input[2] == '.')))) {
12284
      // special case
12285
57
      segment_result = 0;
12286
57
      input.remove_prefix(2);
12287
2.53k
    } else {
12288
2.53k
      std::from_chars_result r{};
12289
2.53k
      if (is_hex) {
12290
924
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
12291
924
                            segment_result, 16);
12292
1.60k
      } else if ((input.length() >= 2) && input[0] == '0' &&
12293
501
                 checkers::is_digit(input[1])) {
12294
411
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
12295
411
                            segment_result, 8);
12296
1.19k
      } else {
12297
1.19k
        pure_decimal_count++;
12298
1.19k
        r = std::from_chars(input.data(), input.data() + input.size(),
12299
1.19k
                            segment_result, 10);
12300
1.19k
      }
12301
2.53k
      if (r.ec != std::errc()) {
12302
438
        return is_valid = false;
12303
438
      }
12304
2.09k
      input.remove_prefix(r.ptr - input.data());
12305
2.09k
    }
12306
2.15k
    if (input.empty()) {
12307
      // We have the last value.
12308
      // At this stage, ipv4 contains digit_count*8 bits.
12309
      // So we have 32-digit_count*8 bits left.
12310
1.52k
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
12311
45
        return is_valid = false;
12312
45
      }
12313
1.48k
      ipv4 <<= (32 - digit_count * 8);
12314
1.48k
      ipv4 |= segment_result;
12315
1.48k
      goto final;
12316
1.52k
    } else {
12317
      // There is more, so that the value must no be larger than 255
12318
      // and we must have a '.'.
12319
622
      if ((segment_result > 255) || (input[0] != '.')) {
12320
212
        return is_valid = false;
12321
212
      }
12322
410
      ipv4 <<= 8;
12323
410
      ipv4 |= segment_result;
12324
410
      input.remove_prefix(1);  // remove '.'
12325
410
    }
12326
2.15k
  }
12327
19
  if ((digit_count != 4) || (!input.empty())) {
12328
19
    return is_valid = false;
12329
19
  }
12330
1.48k
final:
12331
  // We could also check r.ptr to see where the parsing ended.
12332
1.48k
  if (pure_decimal_count == 4) {
12333
0
    host = original_input;  // The original input was already all decimal and we
12334
                            // validated it.
12335
1.48k
  } else {
12336
1.48k
    host = ada::serializers::ipv4(ipv4);  // We have to reserialize the address.
12337
1.48k
  }
12338
1.48k
  host_type = IPV4;
12339
1.48k
  return true;
12340
19
}
12341
12342
436
bool url::parse_ipv6(std::string_view input) {
12343
436
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
12344
12345
436
  if (input.empty()) {
12346
21
    return is_valid = false;
12347
21
  }
12348
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
12349
415
  std::array<uint16_t, 8> address{};
12350
12351
  // Let pieceIndex be 0.
12352
415
  int piece_index = 0;
12353
12354
  // Let compress be null.
12355
415
  std::optional<int> compress{};
12356
12357
  // Let pointer be a pointer for input.
12358
415
  std::string_view::iterator pointer = input.begin();
12359
12360
  // If c is U+003A (:), then:
12361
415
  if (input[0] == ':') {
12362
    // If remaining does not start with U+003A (:), validation error, return
12363
    // failure.
12364
93
    if (input.size() == 1 || input[1] != ':') {
12365
14
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
12366
14
      return is_valid = false;
12367
14
    }
12368
12369
    // Increase pointer by 2.
12370
79
    pointer += 2;
12371
12372
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
12373
79
    compress = ++piece_index;
12374
79
  }
12375
12376
  // While c is not the EOF code point:
12377
956
  while (pointer != input.end()) {
12378
    // If pieceIndex is 8, validation error, return failure.
12379
782
    if (piece_index == 8) {
12380
5
      ada_log("parse_ipv6 piece_index == 8");
12381
5
      return is_valid = false;
12382
5
    }
12383
12384
    // If c is U+003A (:), then:
12385
777
    if (*pointer == ':') {
12386
      // If compress is non-null, validation error, return failure.
12387
65
      if (compress.has_value()) {
12388
6
        ada_log("parse_ipv6 compress is non-null");
12389
6
        return is_valid = false;
12390
6
      }
12391
12392
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
12393
      // then continue.
12394
59
      pointer++;
12395
59
      compress = ++piece_index;
12396
59
      continue;
12397
65
    }
12398
12399
    // Let value and length be 0.
12400
712
    uint16_t value = 0, length = 0;
12401
12402
    // While length is less than 4 and c is an ASCII hex digit,
12403
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
12404
    // increase pointer and length by 1.
12405
1.78k
    while (length < 4 && pointer != input.end() &&
12406
1.59k
           unicode::is_ascii_hex_digit(*pointer)) {
12407
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12408
1.06k
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
12409
1.06k
      pointer++;
12410
1.06k
      length++;
12411
1.06k
    }
12412
12413
    // If c is U+002E (.), then:
12414
712
    if (pointer != input.end() && *pointer == '.') {
12415
      // If length is 0, validation error, return failure.
12416
98
      if (length == 0) {
12417
3
        ada_log("parse_ipv6 length is 0");
12418
3
        return is_valid = false;
12419
3
      }
12420
12421
      // Decrease pointer by length.
12422
95
      pointer -= length;
12423
12424
      // If pieceIndex is greater than 6, validation error, return failure.
12425
95
      if (piece_index > 6) {
12426
3
        ada_log("parse_ipv6 piece_index > 6");
12427
3
        return is_valid = false;
12428
3
      }
12429
12430
      // Let numbersSeen be 0.
12431
92
      int numbers_seen = 0;
12432
12433
      // While c is not the EOF code point:
12434
225
      while (pointer != input.end()) {
12435
        // Let ipv4Piece be null.
12436
211
        std::optional<uint16_t> ipv4_piece{};
12437
12438
        // If numbersSeen is greater than 0, then:
12439
211
        if (numbers_seen > 0) {
12440
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
12441
          // pointer by 1.
12442
119
          if (*pointer == '.' && numbers_seen < 4) {
12443
89
            pointer++;
12444
89
          }
12445
          // Otherwise, validation error, return failure.
12446
30
          else {
12447
30
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
12448
30
            return is_valid = false;
12449
30
          }
12450
119
        }
12451
12452
        // If c is not an ASCII digit, validation error, return failure.
12453
181
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
12454
28
          ada_log(
12455
28
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
12456
28
              "failure");
12457
28
          return is_valid = false;
12458
28
        }
12459
12460
        // While c is an ASCII digit:
12461
377
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
12462
          // Let number be c interpreted as decimal number.
12463
244
          int number = *pointer - '0';
12464
12465
          // If ipv4Piece is null, then set ipv4Piece to number.
12466
244
          if (!ipv4_piece.has_value()) {
12467
153
            ipv4_piece = number;
12468
153
          }
12469
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
12470
91
          else if (ipv4_piece == 0) {
12471
3
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
12472
3
            return is_valid = false;
12473
3
          }
12474
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
12475
88
          else {
12476
88
            ipv4_piece = *ipv4_piece * 10 + number;
12477
88
          }
12478
12479
          // If ipv4Piece is greater than 255, validation error, return failure.
12480
241
          if (ipv4_piece > 255) {
12481
17
            ada_log("parse_ipv6 ipv4_piece > 255");
12482
17
            return is_valid = false;
12483
17
          }
12484
12485
          // Increase pointer by 1.
12486
224
          pointer++;
12487
224
        }
12488
12489
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
12490
        // ipv4Piece.
12491
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12492
133
        address[piece_index] =
12493
133
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
12494
12495
        // Increase numbersSeen by 1.
12496
133
        numbers_seen++;
12497
12498
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
12499
133
        if (numbers_seen == 2 || numbers_seen == 4) {
12500
46
          piece_index++;
12501
46
        }
12502
133
      }
12503
12504
      // If numbersSeen is not 4, validation error, return failure.
12505
14
      if (numbers_seen != 4) {
12506
11
        return is_valid = false;
12507
11
      }
12508
12509
      // Break.
12510
3
      break;
12511
14
    }
12512
    // Otherwise, if c is U+003A (:):
12513
614
    else if ((pointer != input.end()) && (*pointer == ':')) {
12514
      // Increase pointer by 1.
12515
370
      pointer++;
12516
12517
      // If c is the EOF code point, validation error, return failure.
12518
370
      if (pointer == input.end()) {
12519
5
        ada_log(
12520
5
            "parse_ipv6 If c is the EOF code point, validation error, return "
12521
5
            "failure");
12522
5
        return is_valid = false;
12523
5
      }
12524
370
    }
12525
    // Otherwise, if c is not the EOF code point, validation error, return
12526
    // failure.
12527
244
    else if (pointer != input.end()) {
12528
113
      ada_log(
12529
113
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
12530
113
          "error, return failure");
12531
113
      return is_valid = false;
12532
113
    }
12533
12534
    // Set address[pieceIndex] to value.
12535
496
    address[piece_index] = value;
12536
12537
    // Increase pieceIndex by 1.
12538
496
    piece_index++;
12539
496
  }
12540
12541
  // If compress is non-null, then:
12542
177
  if (compress.has_value()) {
12543
    // Let swaps be pieceIndex - compress.
12544
119
    int swaps = piece_index - *compress;
12545
12546
    // Set pieceIndex to 7.
12547
119
    piece_index = 7;
12548
12549
    // While pieceIndex is not 0 and swaps is greater than 0,
12550
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
12551
    // decrease both pieceIndex and swaps by 1.
12552
254
    while (piece_index != 0 && swaps > 0) {
12553
135
      std::swap(address[piece_index], address[*compress + swaps - 1]);
12554
135
      piece_index--;
12555
135
      swaps--;
12556
135
    }
12557
119
  }
12558
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
12559
  // return failure.
12560
58
  else if (piece_index != 8) {
12561
49
    ada_log(
12562
49
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
12563
49
        "error, return failure");
12564
49
    return is_valid = false;
12565
49
  }
12566
128
  host = ada::serializers::ipv6(address);
12567
128
  ada_log("parse_ipv6 ", *host);
12568
128
  host_type = IPV6;
12569
128
  return true;
12570
177
}
12571
12572
template <bool has_state_override>
12573
20.6k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12574
20.6k
  auto parsed_type = ada::scheme::get_scheme_type(input);
12575
20.6k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
12576
  /**
12577
   * In the common case, we will immediately recognize a special scheme (e.g.,
12578
   *http, https), in which case, we can go really fast.
12579
   **/
12580
20.6k
  if (is_input_special) {  // fast path!!!
12581
13.9k
    if constexpr (has_state_override) {
12582
      // If url's scheme is not a special scheme and buffer is a special scheme,
12583
      // then return.
12584
1.61k
      if (is_special() != is_input_special) {
12585
0
        return false;
12586
0
      }
12587
12588
      // If url includes credentials or has a non-null port, and buffer is
12589
      // "file", then return.
12590
1.61k
      if ((has_credentials() || port.has_value()) &&
12591
0
          parsed_type == ada::scheme::type::FILE) {
12592
0
        return false;
12593
0
      }
12594
12595
      // If url's scheme is "file" and its host is an empty host, then return.
12596
      // An empty host is the empty string.
12597
1.61k
      if (type == ada::scheme::type::FILE && host.has_value() &&
12598
0
          host.value().empty()) {
12599
0
        return false;
12600
0
      }
12601
1.61k
    }
12602
12603
1.61k
    type = parsed_type;
12604
12605
13.9k
    if constexpr (has_state_override) {
12606
      // This is uncommon.
12607
1.61k
      uint16_t urls_scheme_port = get_special_port();
12608
12609
1.61k
      if (urls_scheme_port) {
12610
        // If url's port is url's scheme's default port, then set url's port to
12611
        // null.
12612
1.09k
        if (port.has_value() && *port == urls_scheme_port) {
12613
0
          port = std::nullopt;
12614
0
        }
12615
1.09k
      }
12616
1.61k
    }
12617
13.9k
  } else {  // slow path
12618
6.72k
    std::string _buffer(input);
12619
    // Next function is only valid if the input is ASCII and returns false
12620
    // otherwise, but it seems that we always have ascii content so we do not
12621
    // need to check the return value.
12622
    // bool is_ascii =
12623
6.72k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
12624
12625
6.72k
    if constexpr (has_state_override) {
12626
      // If url's scheme is a special scheme and buffer is not a special scheme,
12627
      // then return. If url's scheme is not a special scheme and buffer is a
12628
      // special scheme, then return.
12629
2.47k
      if (is_special() != ada::scheme::is_special(_buffer)) {
12630
1.84k
        return true;
12631
1.84k
      }
12632
12633
      // If url includes credentials or has a non-null port, and buffer is
12634
      // "file", then return.
12635
639
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
12636
0
        return true;
12637
0
      }
12638
12639
      // If url's scheme is "file" and its host is an empty host, then return.
12640
      // An empty host is the empty string.
12641
639
      if (type == ada::scheme::type::FILE && host.has_value() &&
12642
0
          host.value().empty()) {
12643
0
        return true;
12644
0
      }
12645
639
    }
12646
12647
639
    set_scheme(std::move(_buffer));
12648
12649
6.72k
    if constexpr (has_state_override) {
12650
      // This is uncommon.
12651
2.47k
      uint16_t urls_scheme_port = get_special_port();
12652
12653
2.47k
      if (urls_scheme_port) {
12654
        // If url's port is url's scheme's default port, then set url's port to
12655
        // null.
12656
449
        if (port.has_value() && *port == urls_scheme_port) {
12657
0
          port = std::nullopt;
12658
0
        }
12659
449
      }
12660
2.47k
    }
12661
6.72k
  }
12662
12663
0
  return true;
12664
20.6k
}
bool ada::url::parse_scheme<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
12573
4.09k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12574
4.09k
  auto parsed_type = ada::scheme::get_scheme_type(input);
12575
4.09k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
12576
  /**
12577
   * In the common case, we will immediately recognize a special scheme (e.g.,
12578
   *http, https), in which case, we can go really fast.
12579
   **/
12580
4.09k
  if (is_input_special) {  // fast path!!!
12581
1.61k
    if constexpr (has_state_override) {
12582
      // If url's scheme is not a special scheme and buffer is a special scheme,
12583
      // then return.
12584
1.61k
      if (is_special() != is_input_special) {
12585
0
        return false;
12586
0
      }
12587
12588
      // If url includes credentials or has a non-null port, and buffer is
12589
      // "file", then return.
12590
1.61k
      if ((has_credentials() || port.has_value()) &&
12591
0
          parsed_type == ada::scheme::type::FILE) {
12592
0
        return false;
12593
0
      }
12594
12595
      // If url's scheme is "file" and its host is an empty host, then return.
12596
      // An empty host is the empty string.
12597
1.61k
      if (type == ada::scheme::type::FILE && host.has_value() &&
12598
0
          host.value().empty()) {
12599
0
        return false;
12600
0
      }
12601
1.61k
    }
12602
12603
1.61k
    type = parsed_type;
12604
12605
1.61k
    if constexpr (has_state_override) {
12606
      // This is uncommon.
12607
1.61k
      uint16_t urls_scheme_port = get_special_port();
12608
12609
1.61k
      if (urls_scheme_port) {
12610
        // If url's port is url's scheme's default port, then set url's port to
12611
        // null.
12612
1.09k
        if (port.has_value() && *port == urls_scheme_port) {
12613
0
          port = std::nullopt;
12614
0
        }
12615
1.09k
      }
12616
1.61k
    }
12617
2.47k
  } else {  // slow path
12618
2.47k
    std::string _buffer(input);
12619
    // Next function is only valid if the input is ASCII and returns false
12620
    // otherwise, but it seems that we always have ascii content so we do not
12621
    // need to check the return value.
12622
    // bool is_ascii =
12623
2.47k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
12624
12625
2.47k
    if constexpr (has_state_override) {
12626
      // If url's scheme is a special scheme and buffer is not a special scheme,
12627
      // then return. If url's scheme is not a special scheme and buffer is a
12628
      // special scheme, then return.
12629
2.47k
      if (is_special() != ada::scheme::is_special(_buffer)) {
12630
1.84k
        return true;
12631
1.84k
      }
12632
12633
      // If url includes credentials or has a non-null port, and buffer is
12634
      // "file", then return.
12635
639
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
12636
0
        return true;
12637
0
      }
12638
12639
      // If url's scheme is "file" and its host is an empty host, then return.
12640
      // An empty host is the empty string.
12641
639
      if (type == ada::scheme::type::FILE && host.has_value() &&
12642
0
          host.value().empty()) {
12643
0
        return true;
12644
0
      }
12645
639
    }
12646
12647
639
    set_scheme(std::move(_buffer));
12648
12649
2.47k
    if constexpr (has_state_override) {
12650
      // This is uncommon.
12651
2.47k
      uint16_t urls_scheme_port = get_special_port();
12652
12653
2.47k
      if (urls_scheme_port) {
12654
        // If url's port is url's scheme's default port, then set url's port to
12655
        // null.
12656
449
        if (port.has_value() && *port == urls_scheme_port) {
12657
0
          port = std::nullopt;
12658
0
        }
12659
449
      }
12660
2.47k
    }
12661
2.47k
  }
12662
12663
0
  return true;
12664
4.09k
}
bool ada::url::parse_scheme<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
12573
16.5k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12574
16.5k
  auto parsed_type = ada::scheme::get_scheme_type(input);
12575
16.5k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
12576
  /**
12577
   * In the common case, we will immediately recognize a special scheme (e.g.,
12578
   *http, https), in which case, we can go really fast.
12579
   **/
12580
16.5k
  if (is_input_special) {  // fast path!!!
12581
    if constexpr (has_state_override) {
12582
      // If url's scheme is not a special scheme and buffer is a special scheme,
12583
      // then return.
12584
      if (is_special() != is_input_special) {
12585
        return false;
12586
      }
12587
12588
      // If url includes credentials or has a non-null port, and buffer is
12589
      // "file", then return.
12590
      if ((has_credentials() || port.has_value()) &&
12591
          parsed_type == ada::scheme::type::FILE) {
12592
        return false;
12593
      }
12594
12595
      // If url's scheme is "file" and its host is an empty host, then return.
12596
      // An empty host is the empty string.
12597
      if (type == ada::scheme::type::FILE && host.has_value() &&
12598
          host.value().empty()) {
12599
        return false;
12600
      }
12601
    }
12602
12603
12.3k
    type = parsed_type;
12604
12605
    if constexpr (has_state_override) {
12606
      // This is uncommon.
12607
      uint16_t urls_scheme_port = get_special_port();
12608
12609
      if (urls_scheme_port) {
12610
        // If url's port is url's scheme's default port, then set url's port to
12611
        // null.
12612
        if (port.has_value() && *port == urls_scheme_port) {
12613
          port = std::nullopt;
12614
        }
12615
      }
12616
    }
12617
12.3k
  } else {  // slow path
12618
4.24k
    std::string _buffer(input);
12619
    // Next function is only valid if the input is ASCII and returns false
12620
    // otherwise, but it seems that we always have ascii content so we do not
12621
    // need to check the return value.
12622
    // bool is_ascii =
12623
4.24k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
12624
12625
    if constexpr (has_state_override) {
12626
      // If url's scheme is a special scheme and buffer is not a special scheme,
12627
      // then return. If url's scheme is not a special scheme and buffer is a
12628
      // special scheme, then return.
12629
      if (is_special() != ada::scheme::is_special(_buffer)) {
12630
        return true;
12631
      }
12632
12633
      // If url includes credentials or has a non-null port, and buffer is
12634
      // "file", then return.
12635
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
12636
        return true;
12637
      }
12638
12639
      // If url's scheme is "file" and its host is an empty host, then return.
12640
      // An empty host is the empty string.
12641
      if (type == ada::scheme::type::FILE && host.has_value() &&
12642
          host.value().empty()) {
12643
        return true;
12644
      }
12645
    }
12646
12647
4.24k
    set_scheme(std::move(_buffer));
12648
12649
    if constexpr (has_state_override) {
12650
      // This is uncommon.
12651
      uint16_t urls_scheme_port = get_special_port();
12652
12653
      if (urls_scheme_port) {
12654
        // If url's port is url's scheme's default port, then set url's port to
12655
        // null.
12656
        if (port.has_value() && *port == urls_scheme_port) {
12657
          port = std::nullopt;
12658
        }
12659
      }
12660
    }
12661
4.24k
  }
12662
12663
16.5k
  return true;
12664
16.5k
}
12665
12666
26.0k
ada_really_inline bool url::parse_host(std::string_view input) {
12667
26.0k
  ada_log("parse_host ", input, " [", input.size(), " bytes]");
12668
26.0k
  if (input.empty()) {
12669
9
    return is_valid = false;
12670
9
  }  // technically unnecessary.
12671
  // If input starts with U+005B ([), then:
12672
25.9k
  if (input[0] == '[') {
12673
    // If input does not end with U+005D (]), validation error, return failure.
12674
706
    if (input.back() != ']') {
12675
270
      return is_valid = false;
12676
270
    }
12677
436
    ada_log("parse_host ipv6");
12678
12679
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
12680
    // trailing U+005D (]) removed.
12681
436
    input.remove_prefix(1);
12682
436
    input.remove_suffix(1);
12683
436
    return parse_ipv6(input);
12684
706
  }
12685
12686
  // If isNotSpecial is true, then return the result of opaque-host parsing
12687
  // input.
12688
25.2k
  if (!is_special()) {
12689
259
    return parse_opaque_host(input);
12690
259
  }
12691
12692
  // Fast path: try to parse as pure decimal IPv4(a.b.c.d) first.
12693
25.0k
  const uint64_t fast_result = checkers::try_parse_ipv4_fast(input);
12694
25.0k
  if (fast_result < checkers::ipv4_fast_fail) {
12695
    // Fast path succeeded - input is pure decimal IPv4
12696
19
    if (!input.empty() && input.back() == '.') {
12697
5
      host = input.substr(0, input.size() - 1);
12698
14
    } else {
12699
14
      host = input;
12700
14
    }
12701
19
    host_type = IPV4;
12702
19
    ada_log("parse_host fast path decimal ipv4");
12703
19
    return true;
12704
19
  }
12705
  // Let domain be the result of running UTF-8 decode without BOM on the
12706
  // percent-decoding of input. Let asciiDomain be the result of running domain
12707
  // to ASCII with domain and false. The most common case is an ASCII input, in
12708
  // which case we do not need to call the expensive 'to_ascii' if a few
12709
  // conditions are met: no '%' and no 'xn-' subsequence.
12710
25.0k
  std::string buffer = std::string(input);
12711
  // This next function checks that the result is ascii, but we are going to
12712
  // to check anyhow with is_forbidden.
12713
  // bool is_ascii =
12714
25.0k
  unicode::to_lower_ascii(buffer.data(), buffer.size());
12715
25.0k
  bool is_forbidden = unicode::contains_forbidden_domain_code_point(
12716
25.0k
      buffer.data(), buffer.size());
12717
25.0k
  if (is_forbidden == 0 && buffer.find("xn-") == std::string_view::npos) {
12718
    // fast path
12719
16.9k
    host = std::move(buffer);
12720
12721
    // Check for other IPv4 formats (hex, octal, etc.)
12722
16.9k
    if (checkers::is_ipv4(host.value())) {
12723
1.92k
      ada_log("parse_host fast path ipv4");
12724
1.92k
      return parse_ipv4(host.value());
12725
1.92k
    }
12726
15.0k
    ada_log("parse_host fast path ", *host);
12727
15.0k
    return true;
12728
16.9k
  }
12729
8.07k
  ada_log("parse_host calling to_ascii");
12730
8.07k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
12731
8.07k
  if (!is_valid) {
12732
4.48k
    ada_log("parse_host to_ascii returns false");
12733
4.48k
    return is_valid = false;
12734
4.48k
  }
12735
3.59k
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
12736
3.59k
          " bytes]");
12737
12738
3.59k
  if (std::any_of(host.value().begin(), host.value().end(),
12739
3.59k
                  ada::unicode::is_forbidden_domain_code_point)) {
12740
0
    host = std::nullopt;
12741
0
    return is_valid = false;
12742
0
  }
12743
12744
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
12745
  // asciiDomain.
12746
3.59k
  if (checkers::is_ipv4(host.value())) {
12747
272
    ada_log("parse_host got ipv4 ", *host);
12748
272
    return parse_ipv4(host.value());
12749
272
  }
12750
12751
3.32k
  return true;
12752
3.59k
}
12753
12754
9.27k
ada_really_inline void url::parse_path(std::string_view input) {
12755
9.27k
  ada_log("parse_path ", input);
12756
9.27k
  std::string tmp_buffer;
12757
9.27k
  std::string_view internal_input;
12758
9.27k
  if (unicode::has_tabs_or_newline(input)) {
12759
143
    tmp_buffer = input;
12760
    // Optimization opportunity: Instead of copying and then pruning, we could
12761
    // just directly build the string from user_input.
12762
143
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12763
143
    internal_input = tmp_buffer;
12764
9.13k
  } else {
12765
9.13k
    internal_input = input;
12766
9.13k
  }
12767
12768
  // If url is special, then:
12769
9.27k
  if (is_special()) {
12770
9.27k
    if (internal_input.empty()) {
12771
35
      path = "/";
12772
9.23k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
12773
732
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
12774
8.50k
    } else {
12775
8.50k
      helpers::parse_prepared_path(internal_input, type, path);
12776
8.50k
    }
12777
9.27k
  } else if (!internal_input.empty()) {
12778
0
    if (internal_input[0] == '/') {
12779
0
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
12780
0
    } else {
12781
0
      helpers::parse_prepared_path(internal_input, type, path);
12782
0
    }
12783
0
  } else {
12784
0
    if (!host.has_value()) {
12785
0
      path = "/";
12786
0
    }
12787
0
  }
12788
9.27k
}
12789
12790
9.27k
[[nodiscard]] std::string url::to_string() const {
12791
9.27k
  if (!is_valid) {
12792
2.48k
    return "null";
12793
2.48k
  }
12794
6.78k
  std::string answer;
12795
6.78k
  auto back = std::back_insert_iterator(answer);
12796
6.78k
  answer.append("{\n");
12797
6.78k
  answer.append("\t\"protocol\":\"");
12798
6.78k
  helpers::encode_json(get_protocol(), back);
12799
6.78k
  answer.append("\",\n");
12800
6.78k
  if (has_credentials()) {
12801
6.77k
    answer.append("\t\"username\":\"");
12802
6.77k
    helpers::encode_json(username, back);
12803
6.77k
    answer.append("\",\n");
12804
6.77k
    answer.append("\t\"password\":\"");
12805
6.77k
    helpers::encode_json(password, back);
12806
6.77k
    answer.append("\",\n");
12807
6.77k
  }
12808
6.78k
  if (host.has_value()) {
12809
6.78k
    answer.append("\t\"host\":\"");
12810
6.78k
    helpers::encode_json(host.value(), back);
12811
6.78k
    answer.append("\",\n");
12812
6.78k
  }
12813
6.78k
  if (port.has_value()) {
12814
913
    answer.append("\t\"port\":\"");
12815
913
    answer.append(std::to_string(port.value()));
12816
913
    answer.append("\",\n");
12817
913
  }
12818
6.78k
  answer.append("\t\"path\":\"");
12819
6.78k
  helpers::encode_json(path, back);
12820
6.78k
  answer.append("\",\n");
12821
6.78k
  answer.append("\t\"opaque path\":");
12822
6.78k
  answer.append((has_opaque_path ? "true" : "false"));
12823
6.78k
  if (has_search()) {
12824
6.78k
    answer.append(",\n");
12825
6.78k
    answer.append("\t\"query\":\"");
12826
    // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
12827
6.78k
    helpers::encode_json(query.value(), back);
12828
6.78k
    answer.append("\"");
12829
6.78k
  }
12830
6.78k
  if (hash.has_value()) {
12831
6.78k
    answer.append(",\n");
12832
6.78k
    answer.append("\t\"hash\":\"");
12833
6.78k
    helpers::encode_json(hash.value(), back);
12834
6.78k
    answer.append("\"");
12835
6.78k
  }
12836
6.78k
  answer.append("\n}");
12837
6.78k
  return answer;
12838
9.27k
}
12839
12840
0
[[nodiscard]] bool url::has_valid_domain() const noexcept {
12841
0
  if (!host.has_value()) {
12842
0
    return false;
12843
0
  }
12844
0
  return checkers::verify_dns_length(host.value());
12845
0
}
12846
12847
12.5k
[[nodiscard]] std::string url::get_origin() const noexcept {
12848
12.5k
  if (is_special()) {
12849
    // Return a new opaque origin.
12850
11.1k
    if (type == scheme::FILE) {
12851
1.33k
      return "null";
12852
1.33k
    }
12853
9.77k
    return ada::helpers::concat(get_protocol(), "//", get_host());
12854
11.1k
  }
12855
12856
1.41k
  if (non_special_scheme == "blob") {
12857
499
    if (!path.empty()) {
12858
489
      auto result = ada::parse<ada::url>(path);
12859
489
      if (result &&
12860
236
          (result->type == scheme::HTTP || result->type == scheme::HTTPS)) {
12861
        // If pathURL's scheme is not "http" and not "https", then return a
12862
        // new opaque origin.
12863
18
        return ada::helpers::concat(result->get_protocol(), "//",
12864
18
                                    result->get_host());
12865
18
      }
12866
489
    }
12867
499
  }
12868
12869
  // Return a new opaque origin.
12870
1.39k
  return "null";
12871
1.41k
}
12872
12873
38.4k
[[nodiscard]] std::string url::get_protocol() const noexcept {
12874
38.4k
  if (is_special()) {
12875
32.8k
    return helpers::concat(ada::scheme::details::is_special_list[type], ":");
12876
32.8k
  }
12877
  // We only move the 'scheme' if it is non-special.
12878
5.65k
  return helpers::concat(non_special_scheme, ":");
12879
38.4k
}
12880
12881
19.0k
[[nodiscard]] std::string url::get_host() const noexcept {
12882
  // If url's host is null, then return the empty string.
12883
  // If url's port is null, return url's host, serialized.
12884
  // Return url's host, serialized, followed by U+003A (:) and url's port,
12885
  // serialized.
12886
19.0k
  if (!host.has_value()) {
12887
0
    return "";
12888
0
  }
12889
19.0k
  if (port.has_value()) {
12890
1.89k
    return host.value() + ":" + get_port();
12891
1.89k
  }
12892
17.1k
  return host.value();
12893
19.0k
}
12894
12895
9.27k
[[nodiscard]] std::string url::get_hostname() const noexcept {
12896
9.27k
  return host.value_or("");
12897
9.27k
}
12898
12899
9.27k
[[nodiscard]] std::string url::get_search() const noexcept {
12900
  // If this's URL's query is either null or the empty string, then return the
12901
  // empty string. Return U+003F (?), followed by this's URL's query.
12902
9.27k
  return (!query.has_value() || (query.value().empty())) ? ""
12903
9.27k
                                                         : "?" + query.value();
12904
9.27k
}
12905
12906
9.27k
[[nodiscard]] const std::string& url::get_username() const noexcept {
12907
9.27k
  return username;
12908
9.27k
}
12909
12910
9.60k
[[nodiscard]] const std::string& url::get_password() const noexcept {
12911
9.60k
  return password;
12912
9.60k
}
12913
12914
11.3k
[[nodiscard]] std::string url::get_port() const noexcept {
12915
11.3k
  return port.has_value() ? std::to_string(port.value()) : "";
12916
11.3k
}
12917
12918
9.27k
[[nodiscard]] std::string url::get_hash() const noexcept {
12919
  // If this's URL's fragment is either null or the empty string, then return
12920
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
12921
9.27k
  return (!hash.has_value() || (hash.value().empty())) ? ""
12922
9.27k
                                                       : "#" + hash.value();
12923
9.27k
}
12924
12925
template <bool override_hostname>
12926
18.5k
bool url::set_host_or_hostname(const std::string_view input) {
12927
18.5k
  if (has_opaque_path) {
12928
0
    return false;
12929
0
  }
12930
12931
18.5k
  std::optional<std::string> previous_host = host;
12932
18.5k
  std::optional<uint16_t> previous_port = port;
12933
12934
18.5k
  size_t host_end_pos = input.find('#');
12935
18.5k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
12936
18.5k
                                      ? host_end_pos
12937
18.5k
                                      : input.size());
12938
18.5k
  helpers::remove_ascii_tab_or_newline(_host);
12939
18.5k
  std::string_view new_host(_host);
12940
12941
  // If url's scheme is "file", then set state to file host state, instead of
12942
  // host state.
12943
18.5k
  if (type != ada::scheme::type::FILE) {
12944
17.1k
    std::string_view host_view(_host.data(), _host.length());
12945
17.1k
    auto [location, found_colon] =
12946
17.1k
        helpers::get_host_delimiter_location(is_special(), host_view);
12947
12948
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12949
    // Note: the 'found_colon' value is true if and only if a colon was
12950
    // encountered while not inside brackets.
12951
17.1k
    if (found_colon) {
12952
      // If buffer is the empty string, host-missing validation error, return
12953
      // failure.
12954
7.57k
      std::string_view buffer = host_view.substr(0, location);
12955
7.57k
      if (buffer.empty()) {
12956
30
        return false;
12957
30
      }
12958
12959
      // If state override is given and state override is hostname state, then
12960
      // return failure.
12961
7.54k
      if constexpr (override_hostname) {
12962
3.77k
        return false;
12963
3.77k
      }
12964
12965
      // Let host be the result of host parsing buffer with url is not special.
12966
0
      bool succeeded = parse_host(buffer);
12967
7.54k
      if (!succeeded) {
12968
374
        host = std::move(previous_host);
12969
374
        update_base_port(previous_port);
12970
374
        return false;
12971
374
      }
12972
12973
      // Set url's host to host, buffer to the empty string, and state to port
12974
      // state.
12975
7.17k
      std::string_view port_buffer = new_host.substr(location + 1);
12976
7.17k
      if (!port_buffer.empty()) {
12977
2.95k
        set_port(port_buffer);
12978
2.95k
      }
12979
7.17k
      return true;
12980
7.54k
    }
12981
    // Otherwise, if one of the following is true:
12982
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12983
    // - url is special and c is U+005C (\)
12984
9.55k
    else {
12985
      // If url is special and host_view is the empty string, host-missing
12986
      // validation error, return failure.
12987
9.55k
      if (host_view.empty() && is_special()) {
12988
1.62k
        return false;
12989
1.62k
      }
12990
12991
      // Otherwise, if state override is given, host_view is the empty string,
12992
      // and either url includes credentials or url's port is non-null, then
12993
      // return failure.
12994
7.93k
      if (host_view.empty() && (has_credentials() || port.has_value())) {
12995
0
        return false;
12996
0
      }
12997
12998
      // Let host be the result of host parsing host_view with url is not
12999
      // special.
13000
7.93k
      if (host_view.empty() && !is_special()) {
13001
0
        host = "";
13002
0
        return true;
13003
0
      }
13004
13005
7.93k
      bool succeeded = parse_host(host_view);
13006
7.93k
      if (!succeeded) {
13007
3.53k
        host = std::move(previous_host);
13008
3.53k
        update_base_port(previous_port);
13009
3.53k
        return false;
13010
3.53k
      }
13011
4.39k
      return true;
13012
7.93k
    }
13013
17.1k
  }
13014
13015
1.41k
  size_t location = new_host.find_first_of("/\\?");
13016
1.41k
  if (location != std::string_view::npos) {
13017
1.29k
    new_host.remove_suffix(new_host.length() - location);
13018
1.29k
  }
13019
13020
1.41k
  if (new_host.empty()) {
13021
    // Set url's host to the empty string.
13022
0
    host = "";
13023
1.41k
  } else {
13024
    // Let host be the result of host parsing buffer with url is not special.
13025
1.41k
    if (!parse_host(new_host)) {
13026
1.41k
      host = std::move(previous_host);
13027
1.41k
      update_base_port(previous_port);
13028
1.41k
      return false;
13029
1.41k
    }
13030
13031
    // If host is "localhost", then set host to the empty string.
13032
4
    if (host == "localhost") {
13033
0
      host = "";
13034
0
    }
13035
4
  }
13036
4
  return true;
13037
1.41k
}
bool ada::url::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
12926
9.27k
bool url::set_host_or_hostname(const std::string_view input) {
12927
9.27k
  if (has_opaque_path) {
12928
0
    return false;
12929
0
  }
12930
12931
9.27k
  std::optional<std::string> previous_host = host;
12932
9.27k
  std::optional<uint16_t> previous_port = port;
12933
12934
9.27k
  size_t host_end_pos = input.find('#');
12935
9.27k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
12936
9.27k
                                      ? host_end_pos
12937
9.27k
                                      : input.size());
12938
9.27k
  helpers::remove_ascii_tab_or_newline(_host);
12939
9.27k
  std::string_view new_host(_host);
12940
12941
  // If url's scheme is "file", then set state to file host state, instead of
12942
  // host state.
12943
9.27k
  if (type != ada::scheme::type::FILE) {
12944
8.56k
    std::string_view host_view(_host.data(), _host.length());
12945
8.56k
    auto [location, found_colon] =
12946
8.56k
        helpers::get_host_delimiter_location(is_special(), host_view);
12947
12948
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12949
    // Note: the 'found_colon' value is true if and only if a colon was
12950
    // encountered while not inside brackets.
12951
8.56k
    if (found_colon) {
12952
      // If buffer is the empty string, host-missing validation error, return
12953
      // failure.
12954
3.78k
      std::string_view buffer = host_view.substr(0, location);
12955
3.78k
      if (buffer.empty()) {
12956
15
        return false;
12957
15
      }
12958
12959
      // If state override is given and state override is hostname state, then
12960
      // return failure.
12961
      if constexpr (override_hostname) {
12962
        return false;
12963
      }
12964
12965
      // Let host be the result of host parsing buffer with url is not special.
12966
3.77k
      bool succeeded = parse_host(buffer);
12967
3.77k
      if (!succeeded) {
12968
374
        host = std::move(previous_host);
12969
374
        update_base_port(previous_port);
12970
374
        return false;
12971
374
      }
12972
12973
      // Set url's host to host, buffer to the empty string, and state to port
12974
      // state.
12975
3.39k
      std::string_view port_buffer = new_host.substr(location + 1);
12976
3.39k
      if (!port_buffer.empty()) {
12977
2.95k
        set_port(port_buffer);
12978
2.95k
      }
12979
3.39k
      return true;
12980
3.77k
    }
12981
    // Otherwise, if one of the following is true:
12982
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12983
    // - url is special and c is U+005C (\)
12984
4.77k
    else {
12985
      // If url is special and host_view is the empty string, host-missing
12986
      // validation error, return failure.
12987
4.77k
      if (host_view.empty() && is_special()) {
12988
810
        return false;
12989
810
      }
12990
12991
      // Otherwise, if state override is given, host_view is the empty string,
12992
      // and either url includes credentials or url's port is non-null, then
12993
      // return failure.
12994
3.96k
      if (host_view.empty() && (has_credentials() || port.has_value())) {
12995
0
        return false;
12996
0
      }
12997
12998
      // Let host be the result of host parsing host_view with url is not
12999
      // special.
13000
3.96k
      if (host_view.empty() && !is_special()) {
13001
0
        host = "";
13002
0
        return true;
13003
0
      }
13004
13005
3.96k
      bool succeeded = parse_host(host_view);
13006
3.96k
      if (!succeeded) {
13007
1.76k
        host = std::move(previous_host);
13008
1.76k
        update_base_port(previous_port);
13009
1.76k
        return false;
13010
1.76k
      }
13011
2.19k
      return true;
13012
3.96k
    }
13013
8.56k
  }
13014
13015
709
  size_t location = new_host.find_first_of("/\\?");
13016
709
  if (location != std::string_view::npos) {
13017
645
    new_host.remove_suffix(new_host.length() - location);
13018
645
  }
13019
13020
709
  if (new_host.empty()) {
13021
    // Set url's host to the empty string.
13022
0
    host = "";
13023
709
  } else {
13024
    // Let host be the result of host parsing buffer with url is not special.
13025
709
    if (!parse_host(new_host)) {
13026
707
      host = std::move(previous_host);
13027
707
      update_base_port(previous_port);
13028
707
      return false;
13029
707
    }
13030
13031
    // If host is "localhost", then set host to the empty string.
13032
2
    if (host == "localhost") {
13033
0
      host = "";
13034
0
    }
13035
2
  }
13036
2
  return true;
13037
709
}
bool ada::url::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
12926
9.27k
bool url::set_host_or_hostname(const std::string_view input) {
12927
9.27k
  if (has_opaque_path) {
12928
0
    return false;
12929
0
  }
12930
12931
9.27k
  std::optional<std::string> previous_host = host;
12932
9.27k
  std::optional<uint16_t> previous_port = port;
12933
12934
9.27k
  size_t host_end_pos = input.find('#');
12935
9.27k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
12936
9.27k
                                      ? host_end_pos
12937
9.27k
                                      : input.size());
12938
9.27k
  helpers::remove_ascii_tab_or_newline(_host);
12939
9.27k
  std::string_view new_host(_host);
12940
12941
  // If url's scheme is "file", then set state to file host state, instead of
12942
  // host state.
12943
9.27k
  if (type != ada::scheme::type::FILE) {
12944
8.56k
    std::string_view host_view(_host.data(), _host.length());
12945
8.56k
    auto [location, found_colon] =
12946
8.56k
        helpers::get_host_delimiter_location(is_special(), host_view);
12947
12948
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12949
    // Note: the 'found_colon' value is true if and only if a colon was
12950
    // encountered while not inside brackets.
12951
8.56k
    if (found_colon) {
12952
      // If buffer is the empty string, host-missing validation error, return
12953
      // failure.
12954
3.78k
      std::string_view buffer = host_view.substr(0, location);
12955
3.78k
      if (buffer.empty()) {
12956
15
        return false;
12957
15
      }
12958
12959
      // If state override is given and state override is hostname state, then
12960
      // return failure.
12961
3.77k
      if constexpr (override_hostname) {
12962
3.77k
        return false;
12963
3.77k
      }
12964
12965
      // Let host be the result of host parsing buffer with url is not special.
12966
0
      bool succeeded = parse_host(buffer);
12967
3.77k
      if (!succeeded) {
12968
0
        host = std::move(previous_host);
12969
0
        update_base_port(previous_port);
12970
0
        return false;
12971
0
      }
12972
12973
      // Set url's host to host, buffer to the empty string, and state to port
12974
      // state.
12975
3.77k
      std::string_view port_buffer = new_host.substr(location + 1);
12976
3.77k
      if (!port_buffer.empty()) {
12977
0
        set_port(port_buffer);
12978
0
      }
12979
3.77k
      return true;
12980
3.77k
    }
12981
    // Otherwise, if one of the following is true:
12982
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12983
    // - url is special and c is U+005C (\)
12984
4.77k
    else {
12985
      // If url is special and host_view is the empty string, host-missing
12986
      // validation error, return failure.
12987
4.77k
      if (host_view.empty() && is_special()) {
12988
810
        return false;
12989
810
      }
12990
12991
      // Otherwise, if state override is given, host_view is the empty string,
12992
      // and either url includes credentials or url's port is non-null, then
12993
      // return failure.
12994
3.96k
      if (host_view.empty() && (has_credentials() || port.has_value())) {
12995
0
        return false;
12996
0
      }
12997
12998
      // Let host be the result of host parsing host_view with url is not
12999
      // special.
13000
3.96k
      if (host_view.empty() && !is_special()) {
13001
0
        host = "";
13002
0
        return true;
13003
0
      }
13004
13005
3.96k
      bool succeeded = parse_host(host_view);
13006
3.96k
      if (!succeeded) {
13007
1.76k
        host = std::move(previous_host);
13008
1.76k
        update_base_port(previous_port);
13009
1.76k
        return false;
13010
1.76k
      }
13011
2.19k
      return true;
13012
3.96k
    }
13013
8.56k
  }
13014
13015
709
  size_t location = new_host.find_first_of("/\\?");
13016
709
  if (location != std::string_view::npos) {
13017
645
    new_host.remove_suffix(new_host.length() - location);
13018
645
  }
13019
13020
709
  if (new_host.empty()) {
13021
    // Set url's host to the empty string.
13022
0
    host = "";
13023
709
  } else {
13024
    // Let host be the result of host parsing buffer with url is not special.
13025
709
    if (!parse_host(new_host)) {
13026
707
      host = std::move(previous_host);
13027
707
      update_base_port(previous_port);
13028
707
      return false;
13029
707
    }
13030
13031
    // If host is "localhost", then set host to the empty string.
13032
2
    if (host == "localhost") {
13033
0
      host = "";
13034
0
    }
13035
2
  }
13036
2
  return true;
13037
709
}
13038
13039
9.27k
bool url::set_host(const std::string_view input) {
13040
9.27k
  return set_host_or_hostname<false>(input);
13041
9.27k
}
13042
13043
9.27k
bool url::set_hostname(const std::string_view input) {
13044
9.27k
  return set_host_or_hostname<true>(input);
13045
9.27k
}
13046
13047
9.27k
bool url::set_username(const std::string_view input) {
13048
9.27k
  if (cannot_have_credentials_or_port()) {
13049
709
    return false;
13050
709
  }
13051
8.56k
  username = ada::unicode::percent_encode(
13052
8.56k
      input, character_sets::USERINFO_PERCENT_ENCODE);
13053
8.56k
  return true;
13054
9.27k
}
13055
13056
9.27k
bool url::set_password(const std::string_view input) {
13057
9.27k
  if (cannot_have_credentials_or_port()) {
13058
709
    return false;
13059
709
  }
13060
8.56k
  password = ada::unicode::percent_encode(
13061
8.56k
      input, character_sets::USERINFO_PERCENT_ENCODE);
13062
8.56k
  return true;
13063
9.27k
}
13064
13065
12.2k
bool url::set_port(const std::string_view input) {
13066
12.2k
  if (cannot_have_credentials_or_port()) {
13067
709
    return false;
13068
709
  }
13069
13070
11.5k
  if (input.empty()) {
13071
8
    port = std::nullopt;
13072
8
    return true;
13073
8
  }
13074
13075
11.5k
  std::string trimmed(input);
13076
11.5k
  helpers::remove_ascii_tab_or_newline(trimmed);
13077
13078
11.5k
  if (trimmed.empty()) {
13079
27
    return true;
13080
27
  }
13081
13082
  // Input should not start with a non-digit character.
13083
11.4k
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
13084
9.99k
    return false;
13085
9.99k
  }
13086
13087
  // Find the first non-digit character to determine the length of digits
13088
1.49k
  auto first_non_digit =
13089
1.49k
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
13090
1.49k
  std::string_view digits_to_parse =
13091
1.49k
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
13092
13093
  // Revert changes if parse_port fails.
13094
1.49k
  std::optional<uint16_t> previous_port = port;
13095
1.49k
  parse_port(digits_to_parse);
13096
1.49k
  if (is_valid) {
13097
996
    return true;
13098
996
  }
13099
496
  port = std::move(previous_port);
13100
496
  is_valid = true;
13101
496
  return false;
13102
1.49k
}
13103
13104
9.27k
void url::set_hash(const std::string_view input) {
13105
9.27k
  if (input.empty()) {
13106
8
    hash = std::nullopt;
13107
8
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13108
8
    return;
13109
8
  }
13110
13111
9.26k
  std::string new_value;
13112
9.26k
  new_value = input[0] == '#' ? input.substr(1) : input;
13113
9.26k
  helpers::remove_ascii_tab_or_newline(new_value);
13114
9.26k
  hash = unicode::percent_encode(new_value,
13115
9.26k
                                 ada::character_sets::FRAGMENT_PERCENT_ENCODE);
13116
9.26k
}
13117
13118
9.27k
void url::set_search(const std::string_view input) {
13119
9.27k
  if (input.empty()) {
13120
8
    query = std::nullopt;
13121
8
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13122
8
    return;
13123
8
  }
13124
13125
9.26k
  std::string new_value;
13126
9.26k
  new_value = input[0] == '?' ? input.substr(1) : input;
13127
9.26k
  helpers::remove_ascii_tab_or_newline(new_value);
13128
13129
9.26k
  auto query_percent_encode_set =
13130
9.26k
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13131
9.26k
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
13132
13133
9.26k
  query = ada::unicode::percent_encode(new_value, query_percent_encode_set);
13134
9.26k
}
13135
13136
9.27k
bool url::set_pathname(const std::string_view input) {
13137
9.27k
  if (has_opaque_path) {
13138
0
    return false;
13139
0
  }
13140
9.27k
  path.clear();
13141
9.27k
  parse_path(input);
13142
9.27k
  return true;
13143
9.27k
}
13144
13145
9.27k
bool url::set_protocol(const std::string_view input) {
13146
9.27k
  std::string view(input);
13147
9.27k
  helpers::remove_ascii_tab_or_newline(view);
13148
9.27k
  if (view.empty()) {
13149
35
    return true;
13150
35
  }
13151
13152
  // Schemes should start with alpha values.
13153
9.23k
  if (!checkers::is_alpha(view[0])) {
13154
4.51k
    return false;
13155
4.51k
  }
13156
13157
4.72k
  view.append(":");
13158
13159
4.72k
  std::string::iterator pointer =
13160
4.72k
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
13161
13162
4.72k
  if (pointer != view.end() && *pointer == ':') {
13163
4.09k
    return parse_scheme<true>(
13164
4.09k
        std::string_view(view.data(), pointer - view.begin()));
13165
4.09k
  }
13166
631
  return false;
13167
4.72k
}
13168
13169
3.11k
bool url::set_href(const std::string_view input) {
13170
3.11k
  ada::result<ada::url> out = ada::parse<ada::url>(input);
13171
13172
3.11k
  if (out) {
13173
3.11k
    *this = *out;
13174
3.11k
  }
13175
13176
3.11k
  return out.has_value();
13177
3.11k
}
13178
13179
}  // namespace ada
13180
/* end file src/url.cpp */
13181
/* begin file src/parser.cpp */
13182
13183
#include <limits>
13184
#include <ranges>
13185
13186
13187
namespace ada::parser {
13188
13189
template <class result_type, bool store_values>
13190
result_type parse_url_impl(std::string_view user_input,
13191
44.3k
                           const result_type* base_url) {
13192
  // We can specialize the implementation per type.
13193
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
13194
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
13195
  // something else } is free (at runtime). This means that ada::url_aggregator
13196
  // and ada::url **do not have to support the exact same API**.
13197
44.3k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13198
44.3k
  constexpr bool result_type_is_ada_url_aggregator =
13199
44.3k
      std::is_same_v<url_aggregator, result_type>;
13200
44.3k
  static_assert(result_type_is_ada_url ||
13201
44.3k
                result_type_is_ada_url_aggregator);  // We don't support
13202
                                                     // anything else for now.
13203
13204
44.3k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13205
44.3k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13206
44.3k
          ")");
13207
13208
44.3k
  state state = state::SCHEME_START;
13209
44.3k
  result_type url{};
13210
13211
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
13212
  // surely the result of a bug or are otherwise a security concern.
13213
44.3k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) [[unlikely]] {
13214
0
    url.is_valid = false;
13215
0
  }
13216
  // Going forward, user_input.size() is in [0,
13217
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
13218
  // base, or the optional_url was invalid, we must return.
13219
44.3k
  if (base_url != nullptr) {
13220
0
    url.is_valid &= base_url->is_valid;
13221
0
  }
13222
44.3k
  if (!url.is_valid) {
13223
0
    return url;
13224
0
  }
13225
44.3k
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
13226
    // Most of the time, we just need user_input.size().
13227
    // In some instances, we may need a bit more.
13228
    ///////////////////////////
13229
    // This is *very* important. This line should *not* be removed
13230
    // hastily. There are principled reasons why reserve is important
13231
    // for performance. If you have a benchmark with small inputs,
13232
    // it may not matter, but in other instances, it could.
13233
    ////
13234
    // This rounds up to the next power of two.
13235
    // We know that user_input.size() is in [0,
13236
    // std::numeric_limits<uint32_t>::max).
13237
22.1k
    uint32_t reserve_capacity =
13238
22.1k
        (0xFFFFFFFF >>
13239
22.1k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13240
22.1k
        1;
13241
22.1k
    url.reserve(reserve_capacity);
13242
22.1k
  }
13243
44.3k
  std::string tmp_buffer;
13244
44.3k
  std::string_view url_data;
13245
44.3k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13246
350
    tmp_buffer = user_input;
13247
    // Optimization opportunity: Instead of copying and then pruning, we could
13248
    // just directly build the string from user_input.
13249
350
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13250
350
    url_data = tmp_buffer;
13251
43.9k
  } else [[likely]] {
13252
43.9k
    url_data = user_input;
13253
43.9k
  }
13254
13255
  // Leading and trailing control characters are uncommon and easy to deal with
13256
  // (no performance concern).
13257
44.3k
  helpers::trim_c0_whitespace(url_data);
13258
13259
  // Optimization opportunity. Most websites do not have fragment.
13260
44.3k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13261
  // We add it last so that an implementation like ada::url_aggregator
13262
  // can append it last to its internal buffer, thus improving performance.
13263
13264
  // Here url_data no longer has its fragment.
13265
  // We are going to access the data from url_data (it is immutable).
13266
  // At any given time, we are pointing at byte 'input_position' in url_data.
13267
  // The input_position variable should range from 0 to input_size.
13268
  // It is illegal to access url_data at input_size.
13269
44.3k
  size_t input_position = 0;
13270
44.3k
  const size_t input_size = url_data.size();
13271
  // Keep running the following state machine by switching on state.
13272
  // If after a run pointer points to the EOF code point, go to the next step.
13273
  // Otherwise, increase pointer by 1 and continue with the state machine.
13274
  // We never decrement input_position.
13275
216k
  while (input_position <= input_size) {
13276
207k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13277
207k
            " in state ", ada::to_string(state));
13278
207k
    switch (state) {
13279
44.3k
      case state::SCHEME_START: {
13280
44.3k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13281
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13282
        // state to scheme state.
13283
44.3k
        if ((input_position != input_size) &&
13284
44.1k
            checkers::is_alpha(url_data[input_position])) {
13285
35.2k
          state = state::SCHEME;
13286
35.2k
          input_position++;
13287
35.2k
        } else {
13288
          // Otherwise, if state override is not given, set state to no scheme
13289
          // state and decrease pointer by 1.
13290
9.03k
          state = state::NO_SCHEME;
13291
9.03k
        }
13292
44.3k
        break;
13293
0
      }
13294
35.2k
      case state::SCHEME: {
13295
35.2k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13296
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13297
        // append c, lowercased, to buffer.
13298
182k
        while ((input_position != input_size) &&
13299
182k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13300
147k
          input_position++;
13301
147k
        }
13302
        // Otherwise, if c is U+003A (:), then:
13303
35.2k
        if ((input_position != input_size) &&
13304
34.4k
            (url_data[input_position] == ':')) {
13305
33.1k
          ada_log("SCHEME the scheme should be ",
13306
33.1k
                  url_data.substr(0, input_position));
13307
33.1k
          if constexpr (result_type_is_ada_url) {
13308
16.5k
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13309
0
              return url;
13310
0
            }
13311
16.5k
          } else {
13312
            // we pass the colon along instead of painfully adding it back.
13313
16.5k
            if (!url.parse_scheme_with_colon(
13314
16.5k
                    url_data.substr(0, input_position + 1))) {
13315
0
              return url;
13316
0
            }
13317
16.5k
          }
13318
33.1k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13319
13320
          // If url's scheme is "file", then:
13321
33.1k
          if (url.type == scheme::type::FILE) {
13322
            // Set state to file state.
13323
2.83k
            state = state::FILE;
13324
2.83k
          }
13325
          // Otherwise, if url is special, base is non-null, and base's scheme
13326
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13327
          // != nullptr is false.
13328
30.3k
          else if (url.is_special() && base_url != nullptr &&
13329
0
                   base_url->type == url.type) {
13330
            // Set state to special relative or authority state.
13331
0
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13332
0
          }
13333
          // Otherwise, if url is special, set state to special authority
13334
          // slashes state.
13335
30.3k
          else if (url.is_special()) {
13336
24.2k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13337
24.2k
          }
13338
          // Otherwise, if remaining starts with an U+002F (/), set state to
13339
          // path or authority state and increase pointer by 1.
13340
6.12k
          else if (input_position + 1 < input_size &&
13341
5.39k
                   url_data[input_position + 1] == '/') {
13342
2.68k
            state = state::PATH_OR_AUTHORITY;
13343
2.68k
            input_position++;
13344
2.68k
          }
13345
          // Otherwise, set url's path to the empty string and set state to
13346
          // opaque path state.
13347
3.44k
          else {
13348
3.44k
            state = state::OPAQUE_PATH;
13349
3.44k
          }
13350
33.1k
        }
13351
        // Otherwise, if state override is not given, set buffer to the empty
13352
        // string, state to no scheme state, and start over (from the first code
13353
        // point in input).
13354
2.08k
        else {
13355
2.08k
          state = state::NO_SCHEME;
13356
2.08k
          input_position = 0;
13357
2.08k
          break;
13358
2.08k
        }
13359
33.1k
        input_position++;
13360
33.1k
        break;
13361
35.2k
      }
13362
11.1k
      case state::NO_SCHEME: {
13363
11.1k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13364
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13365
        // validation error, return failure.
13366
11.1k
        if (base_url == nullptr ||
13367
11.1k
            (base_url->has_opaque_path && !fragment.has_value())) {
13368
11.1k
          ada_log("NO_SCHEME validation error");
13369
11.1k
          url.is_valid = false;
13370
11.1k
          return url;
13371
11.1k
        }
13372
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13373
        // set url's scheme to base's scheme, url's path to base's path, url's
13374
        // query to base's query, and set state to fragment state.
13375
0
        else if (base_url->has_opaque_path && fragment.has_value() &&
13376
0
                 input_position == input_size) {
13377
0
          ada_log("NO_SCHEME opaque base with fragment");
13378
0
          url.copy_scheme(*base_url);
13379
0
          url.has_opaque_path = base_url->has_opaque_path;
13380
13381
0
          if constexpr (result_type_is_ada_url) {
13382
0
            url.path = base_url->path;
13383
0
            url.query = base_url->query;
13384
0
          } else {
13385
0
            url.update_base_pathname(base_url->get_pathname());
13386
0
            url.update_base_search(base_url->get_search());
13387
0
          }
13388
0
          url.update_unencoded_base_hash(*fragment);
13389
0
          return url;
13390
0
        }
13391
        // Otherwise, if base's scheme is not "file", set state to relative
13392
        // state and decrease pointer by 1.
13393
0
        else if (base_url->type != scheme::type::FILE) {
13394
0
          ada_log("NO_SCHEME non-file relative path");
13395
0
          state = state::RELATIVE_SCHEME;
13396
0
        }
13397
        // Otherwise, set state to file state and decrease pointer by 1.
13398
0
        else {
13399
0
          ada_log("NO_SCHEME file base type");
13400
0
          state = state::FILE;
13401
0
        }
13402
0
        break;
13403
11.1k
      }
13404
24.9k
      case state::AUTHORITY: {
13405
24.9k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13406
        // most URLs have no @. Having no @ tells us that we don't have to worry
13407
        // about AUTHORITY. Of course, we could have @ and still not have to
13408
        // worry about AUTHORITY.
13409
        // TODO: Instead of just collecting a bool, collect the location of the
13410
        // '@' and do something useful with it.
13411
        // TODO: We could do various processing early on, using a single pass
13412
        // over the string to collect information about it, e.g., telling us
13413
        // whether there is a @ and if so, where (or how many).
13414
13415
        // Check if url data contains an @.
13416
24.9k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13417
23.5k
          state = state::HOST;
13418
23.5k
          break;
13419
23.5k
        }
13420
1.45k
        bool at_sign_seen{false};
13421
1.45k
        bool password_token_seen{false};
13422
        /**
13423
         * We expect something of the sort...
13424
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13425
         * --------^
13426
         */
13427
15.8k
        do {
13428
15.8k
          std::string_view view = url_data.substr(input_position);
13429
          // The delimiters are @, /, ? \\.
13430
15.8k
          size_t location =
13431
15.8k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13432
15.8k
                               : helpers::find_authority_delimiter(view);
13433
15.8k
          std::string_view authority_view = view.substr(0, location);
13434
15.8k
          size_t end_of_authority = input_position + authority_view.size();
13435
          // If c is U+0040 (@), then:
13436
15.8k
          if ((end_of_authority != input_size) &&
13437
14.5k
              (url_data[end_of_authority] == '@')) {
13438
            // If atSignSeen is true, then prepend "%40" to buffer.
13439
14.3k
            if (at_sign_seen) {
13440
12.9k
              if (password_token_seen) {
13441
5.04k
                if constexpr (result_type_is_ada_url) {
13442
2.52k
                  url.password += "%40";
13443
2.52k
                } else {
13444
2.52k
                  url.append_base_password("%40");
13445
2.52k
                }
13446
7.93k
              } else {
13447
7.93k
                if constexpr (result_type_is_ada_url) {
13448
3.96k
                  url.username += "%40";
13449
3.96k
                } else {
13450
3.96k
                  url.append_base_username("%40");
13451
3.96k
                }
13452
7.93k
              }
13453
12.9k
            }
13454
13455
14.3k
            at_sign_seen = true;
13456
13457
14.3k
            if (!password_token_seen) {
13458
9.30k
              size_t password_token_location = authority_view.find(':');
13459
9.30k
              password_token_seen =
13460
9.30k
                  password_token_location != std::string_view::npos;
13461
13462
9.30k
              if constexpr (store_values) {
13463
9.30k
                if (!password_token_seen) {
13464
8.70k
                  if constexpr (result_type_is_ada_url) {
13465
4.35k
                    url.username += unicode::percent_encode(
13466
4.35k
                        authority_view,
13467
4.35k
                        character_sets::USERINFO_PERCENT_ENCODE);
13468
4.35k
                  } else {
13469
4.35k
                    url.append_base_username(unicode::percent_encode(
13470
4.35k
                        authority_view,
13471
4.35k
                        character_sets::USERINFO_PERCENT_ENCODE));
13472
4.35k
                  }
13473
8.70k
                } else {
13474
606
                  if constexpr (result_type_is_ada_url) {
13475
303
                    url.username += unicode::percent_encode(
13476
303
                        authority_view.substr(0, password_token_location),
13477
303
                        character_sets::USERINFO_PERCENT_ENCODE);
13478
303
                    url.password += unicode::percent_encode(
13479
303
                        authority_view.substr(password_token_location + 1),
13480
303
                        character_sets::USERINFO_PERCENT_ENCODE);
13481
303
                  } else {
13482
303
                    url.append_base_username(unicode::percent_encode(
13483
303
                        authority_view.substr(0, password_token_location),
13484
303
                        character_sets::USERINFO_PERCENT_ENCODE));
13485
303
                    url.append_base_password(unicode::percent_encode(
13486
303
                        authority_view.substr(password_token_location + 1),
13487
303
                        character_sets::USERINFO_PERCENT_ENCODE));
13488
303
                  }
13489
606
                }
13490
9.30k
              }
13491
9.30k
            } else if constexpr (store_values) {
13492
5.04k
              if constexpr (result_type_is_ada_url) {
13493
2.52k
                url.password += unicode::percent_encode(
13494
2.52k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13495
2.52k
              } else {
13496
2.52k
                url.append_base_password(unicode::percent_encode(
13497
2.52k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13498
2.52k
              }
13499
5.04k
            }
13500
14.3k
          }
13501
          // Otherwise, if one of the following is true:
13502
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13503
          // - url is special and c is U+005C (\)
13504
1.45k
          else if (end_of_authority == input_size ||
13505
186
                   url_data[end_of_authority] == '/' ||
13506
58
                   url_data[end_of_authority] == '?' ||
13507
1.45k
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13508
            // If atSignSeen is true and authority_view is the empty string,
13509
            // validation error, return failure.
13510
1.45k
            if (at_sign_seen && authority_view.empty()) {
13511
216
              url.is_valid = false;
13512
216
              return url;
13513
216
            }
13514
1.24k
            state = state::HOST;
13515
1.24k
            break;
13516
1.45k
          }
13517
14.3k
          if (end_of_authority == input_size) {
13518
0
            if constexpr (store_values) {
13519
0
              if (fragment.has_value()) {
13520
0
                url.update_unencoded_base_hash(*fragment);
13521
0
              }
13522
0
            }
13523
0
            return url;
13524
0
          }
13525
14.3k
          input_position = end_of_authority + 1;
13526
14.3k
        } while (true);
13527
13528
1.24k
        break;
13529
1.45k
      }
13530
1.24k
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
13531
0
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
13532
0
                helpers::substring(url_data, input_position));
13533
13534
        // If c is U+002F (/) and remaining starts with U+002F (/),
13535
        // then set state to special authority ignore slashes state and increase
13536
        // pointer by 1.
13537
0
        if (url_data.substr(input_position, 2) == "//") {
13538
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13539
0
          input_position += 2;
13540
0
        } else {
13541
          // Otherwise, validation error, set state to relative state and
13542
          // decrease pointer by 1.
13543
0
          state = state::RELATIVE_SCHEME;
13544
0
        }
13545
13546
0
        break;
13547
1.45k
      }
13548
2.68k
      case state::PATH_OR_AUTHORITY: {
13549
2.68k
        ada_log("PATH_OR_AUTHORITY ",
13550
2.68k
                helpers::substring(url_data, input_position));
13551
13552
        // If c is U+002F (/), then set state to authority state.
13553
2.68k
        if ((input_position != input_size) &&
13554
2.67k
            (url_data[input_position] == '/')) {
13555
774
          state = state::AUTHORITY;
13556
774
          input_position++;
13557
1.91k
        } else {
13558
          // Otherwise, set state to path state, and decrease pointer by 1.
13559
1.91k
          state = state::PATH;
13560
1.91k
        }
13561
13562
2.68k
        break;
13563
1.45k
      }
13564
0
      case state::RELATIVE_SCHEME: {
13565
0
        ada_log("RELATIVE_SCHEME ",
13566
0
                helpers::substring(url_data, input_position));
13567
13568
        // Set url's scheme to base's scheme.
13569
0
        url.copy_scheme(*base_url);
13570
13571
        // If c is U+002F (/), then set state to relative slash state.
13572
0
        if ((input_position != input_size) &&
13573
            // NOLINTNEXTLINE(bugprone-branch-clone)
13574
0
            (url_data[input_position] == '/')) {
13575
0
          ada_log(
13576
0
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
13577
0
              "slash state");
13578
0
          state = state::RELATIVE_SLASH;
13579
0
        } else if (url.is_special() && (input_position != input_size) &&
13580
0
                   (url_data[input_position] == '\\')) {
13581
          // Otherwise, if url is special and c is U+005C (\), validation error,
13582
          // set state to relative slash state.
13583
0
          ada_log(
13584
0
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
13585
0
              "error, set state to relative slash state");
13586
0
          state = state::RELATIVE_SLASH;
13587
0
        } else {
13588
0
          ada_log("RELATIVE_SCHEME otherwise");
13589
          // Set url's username to base's username, url's password to base's
13590
          // password, url's host to base's host, url's port to base's port,
13591
          // url's path to a clone of base's path, and url's query to base's
13592
          // query.
13593
0
          if constexpr (result_type_is_ada_url) {
13594
0
            url.username = base_url->username;
13595
0
            url.password = base_url->password;
13596
0
            url.host = base_url->host;
13597
0
            url.port = base_url->port;
13598
            // cloning the base path includes cloning the has_opaque_path flag
13599
0
            url.has_opaque_path = base_url->has_opaque_path;
13600
0
            url.path = base_url->path;
13601
0
            url.query = base_url->query;
13602
0
          } else {
13603
0
            url.update_base_authority(base_url->get_href(),
13604
0
                                      base_url->get_components());
13605
0
            url.update_host_to_base_host(base_url->get_hostname());
13606
0
            url.update_base_port(base_url->retrieve_base_port());
13607
            // cloning the base path includes cloning the has_opaque_path flag
13608
0
            url.has_opaque_path = base_url->has_opaque_path;
13609
0
            url.update_base_pathname(base_url->get_pathname());
13610
0
            url.update_base_search(base_url->get_search());
13611
0
          }
13612
13613
0
          url.has_opaque_path = base_url->has_opaque_path;
13614
13615
          // If c is U+003F (?), then set url's query to the empty string, and
13616
          // state to query state.
13617
0
          if ((input_position != input_size) &&
13618
0
              (url_data[input_position] == '?')) {
13619
0
            state = state::QUERY;
13620
0
          }
13621
          // Otherwise, if c is not the EOF code point:
13622
0
          else if (input_position != input_size) {
13623
            // Set url's query to null.
13624
0
            url.clear_search();
13625
0
            if constexpr (result_type_is_ada_url) {
13626
              // Shorten url's path.
13627
0
              helpers::shorten_path(url.path, url.type);
13628
0
            } else {
13629
0
              std::string_view path = url.get_pathname();
13630
0
              if (helpers::shorten_path(path, url.type)) {
13631
0
                url.update_base_pathname(std::move(std::string(path)));
13632
0
              }
13633
0
            }
13634
            // Set state to path state and decrease pointer by 1.
13635
0
            state = state::PATH;
13636
0
            break;
13637
0
          }
13638
0
        }
13639
0
        input_position++;
13640
0
        break;
13641
0
      }
13642
0
      case state::RELATIVE_SLASH: {
13643
0
        ada_log("RELATIVE_SLASH ",
13644
0
                helpers::substring(url_data, input_position));
13645
13646
        // If url is special and c is U+002F (/) or U+005C (\), then:
13647
0
        if (url.is_special() && (input_position != input_size) &&
13648
0
            (url_data[input_position] == '/' ||
13649
0
             url_data[input_position] == '\\')) {
13650
          // Set state to special authority ignore slashes state.
13651
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13652
0
        }
13653
        // Otherwise, if c is U+002F (/), then set state to authority state.
13654
0
        else if ((input_position != input_size) &&
13655
0
                 (url_data[input_position] == '/')) {
13656
0
          state = state::AUTHORITY;
13657
0
        }
13658
        // Otherwise, set
13659
        // - url's username to base's username,
13660
        // - url's password to base's password,
13661
        // - url's host to base's host,
13662
        // - url's port to base's port,
13663
        // - state to path state, and then, decrease pointer by 1.
13664
0
        else {
13665
0
          if constexpr (result_type_is_ada_url) {
13666
0
            url.username = base_url->username;
13667
0
            url.password = base_url->password;
13668
0
            url.host = base_url->host;
13669
0
            url.port = base_url->port;
13670
0
          } else {
13671
0
            url.update_base_authority(base_url->get_href(),
13672
0
                                      base_url->get_components());
13673
0
            url.update_host_to_base_host(base_url->get_hostname());
13674
0
            url.update_base_port(base_url->retrieve_base_port());
13675
0
          }
13676
0
          state = state::PATH;
13677
0
          break;
13678
0
        }
13679
13680
0
        input_position++;
13681
0
        break;
13682
0
      }
13683
24.2k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13684
24.2k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13685
24.2k
                helpers::substring(url_data, input_position));
13686
13687
        // If c is U+002F (/) and remaining starts with U+002F (/),
13688
        // then set state to special authority ignore slashes state and increase
13689
        // pointer by 1.
13690
24.2k
        if (url_data.substr(input_position, 2) == "//") {
13691
18.6k
          input_position += 2;
13692
18.6k
        }
13693
13694
24.2k
        [[fallthrough]];
13695
24.2k
      }
13696
24.2k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13697
24.2k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13698
24.2k
                helpers::substring(url_data, input_position));
13699
13700
        // If c is neither U+002F (/) nor U+005C (\), then set state to
13701
        // authority state and decrease pointer by 1.
13702
25.4k
        while ((input_position != input_size) &&
13703
25.4k
               ((url_data[input_position] == '/') ||
13704
24.5k
                (url_data[input_position] == '\\'))) {
13705
1.25k
          input_position++;
13706
1.25k
        }
13707
24.2k
        state = state::AUTHORITY;
13708
13709
24.2k
        break;
13710
24.2k
      }
13711
642
      case state::QUERY: {
13712
642
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13713
642
        if constexpr (store_values) {
13714
          // Let queryPercentEncodeSet be the special-query percent-encode set
13715
          // if url is special; otherwise the query percent-encode set.
13716
642
          const uint8_t* query_percent_encode_set =
13717
642
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13718
642
                               : character_sets::QUERY_PERCENT_ENCODE;
13719
13720
          // Percent-encode after encoding, with encoding, buffer, and
13721
          // queryPercentEncodeSet, and append the result to url's query.
13722
642
          url.update_base_search(url_data.substr(input_position),
13723
642
                                 query_percent_encode_set);
13724
642
          ada_log("QUERY update_base_search completed ");
13725
642
          if (fragment.has_value()) {
13726
45
            url.update_unencoded_base_hash(*fragment);
13727
45
          }
13728
642
        }
13729
642
        return url;
13730
24.2k
      }
13731
24.7k
      case state::HOST: {
13732
24.7k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13733
13734
24.7k
        std::string_view host_view = url_data.substr(input_position);
13735
24.7k
        auto [location, found_colon] =
13736
24.7k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13737
24.7k
        input_position = (location != std::string_view::npos)
13738
24.7k
                             ? input_position + location
13739
24.7k
                             : input_size;
13740
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13741
        // Note: the 'found_colon' value is true if and only if a colon was
13742
        // encountered while not inside brackets.
13743
24.7k
        if (found_colon) {
13744
          // If buffer is the empty string, validation error, return failure.
13745
          // Let host be the result of host parsing buffer with url is not
13746
          // special.
13747
1.44k
          ada_log("HOST parsing ", host_view);
13748
1.44k
          if (!url.parse_host(host_view)) {
13749
187
            return url;
13750
187
          }
13751
1.25k
          ada_log("HOST parsing results in ", url.get_hostname());
13752
          // Set url's host to host, buffer to the empty string, and state to
13753
          // port state.
13754
1.25k
          state = state::PORT;
13755
1.25k
          input_position++;
13756
1.25k
        }
13757
        // Otherwise, if one of the following is true:
13758
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13759
        // - url is special and c is U+005C (\)
13760
        // The get_host_delimiter_location function either brings us to
13761
        // the colon outside of the bracket, or to one of those characters.
13762
23.3k
        else {
13763
          // If url is special and host_view is the empty string, validation
13764
          // error, return failure.
13765
23.3k
          if (host_view.empty() && url.is_special()) {
13766
22
            url.is_valid = false;
13767
22
            return url;
13768
22
          }
13769
23.3k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
13770
          // Let host be the result of host parsing host_view with url is not
13771
          // special.
13772
23.3k
          if (host_view.empty()) {
13773
82
            url.update_base_hostname("");
13774
23.2k
          } else if (!url.parse_host(host_view)) {
13775
692
            return url;
13776
692
          }
13777
22.6k
          ada_log("HOST parsing results in ", url.get_hostname(),
13778
22.6k
                  " href=", url.get_href());
13779
13780
          // Set url's host to host, and state to path start state.
13781
22.6k
          state = state::PATH_START;
13782
22.6k
        }
13783
13784
23.8k
        break;
13785
24.7k
      }
13786
23.8k
      case state::OPAQUE_PATH: {
13787
3.44k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13788
3.44k
        std::string_view view = url_data.substr(input_position);
13789
        // If c is U+003F (?), then set url's query to the empty string and
13790
        // state to query state.
13791
3.44k
        size_t location = view.find('?');
13792
3.44k
        if (location != std::string_view::npos) {
13793
288
          view.remove_suffix(view.size() - location);
13794
288
          state = state::QUERY;
13795
288
          input_position += location + 1;
13796
3.15k
        } else {
13797
3.15k
          input_position = input_size + 1;
13798
3.15k
        }
13799
3.44k
        url.has_opaque_path = true;
13800
13801
        // This is a really unlikely scenario in real world. We should not seek
13802
        // to optimize it.
13803
3.44k
        if (view.ends_with(' ')) {
13804
132
          std::string modified_view =
13805
132
              std::string(view.substr(0, view.size() - 1)) + "%20";
13806
132
          url.update_base_pathname(unicode::percent_encode(
13807
132
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13808
3.30k
        } else {
13809
3.30k
          url.update_base_pathname(unicode::percent_encode(
13810
3.30k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13811
3.30k
        }
13812
3.44k
        break;
13813
24.7k
      }
13814
1.25k
      case state::PORT: {
13815
1.25k
        ada_log("PORT ", helpers::substring(url_data, input_position));
13816
1.25k
        std::string_view port_view = url_data.substr(input_position);
13817
1.25k
        input_position += url.parse_port(port_view, true);
13818
1.25k
        if (!url.is_valid) {
13819
218
          return url;
13820
218
        }
13821
1.03k
        state = state::PATH_START;
13822
1.03k
        [[fallthrough]];
13823
1.03k
      }
13824
24.5k
      case state::PATH_START: {
13825
24.5k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13826
13827
        // If url is special, then:
13828
24.5k
        if (url.is_special()) {
13829
          // Set state to path state.
13830
24.0k
          state = state::PATH;
13831
13832
          // Optimization: Avoiding going into PATH state improves the
13833
          // performance of urls ending with /.
13834
24.0k
          if (input_position == input_size) {
13835
22.2k
            if constexpr (store_values) {
13836
22.2k
              url.update_base_pathname("/");
13837
22.2k
              if (fragment.has_value()) {
13838
180
                url.update_unencoded_base_hash(*fragment);
13839
180
              }
13840
22.2k
            }
13841
22.2k
            return url;
13842
22.2k
          }
13843
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
13844
          // by 1. We know that (input_position == input_size) is impossible
13845
          // here, because of the previous if-check.
13846
1.82k
          if ((url_data[input_position] != '/') &&
13847
226
              (url_data[input_position] != '\\')) {
13848
193
            break;
13849
193
          }
13850
1.82k
        }
13851
        // Otherwise, if state override is not given and c is U+003F (?),
13852
        // set url's query to the empty string and state to query state.
13853
520
        else if ((input_position != input_size) &&
13854
112
                 (url_data[input_position] == '?')) {
13855
20
          state = state::QUERY;
13856
20
        }
13857
        // Otherwise, if c is not the EOF code point:
13858
500
        else if (input_position != input_size) {
13859
          // Set state to path state.
13860
92
          state = state::PATH;
13861
13862
          // If c is not U+002F (/), then decrease pointer by 1.
13863
92
          if (url_data[input_position] != '/') {
13864
0
            break;
13865
0
          }
13866
92
        }
13867
13868
2.15k
        input_position++;
13869
2.15k
        break;
13870
24.5k
      }
13871
5.52k
      case state::PATH: {
13872
5.52k
        ada_log("PATH ", helpers::substring(url_data, input_position));
13873
5.52k
        std::string_view view = url_data.substr(input_position);
13874
13875
        // Most time, we do not need percent encoding.
13876
        // Furthermore, we can immediately locate the '?'.
13877
5.52k
        size_t locofquestionmark = view.find('?');
13878
5.52k
        if (locofquestionmark != std::string_view::npos) {
13879
334
          state = state::QUERY;
13880
334
          view.remove_suffix(view.size() - locofquestionmark);
13881
334
          input_position += locofquestionmark + 1;
13882
5.18k
        } else {
13883
5.18k
          input_position = input_size + 1;
13884
5.18k
        }
13885
5.52k
        if constexpr (store_values) {
13886
5.52k
          if constexpr (result_type_is_ada_url) {
13887
2.81k
            helpers::parse_prepared_path(view, url.type, url.path);
13888
2.81k
          } else {
13889
2.70k
            url.consume_prepared_path(view);
13890
2.70k
            ADA_ASSERT_TRUE(url.validate());
13891
2.70k
          }
13892
5.52k
        }
13893
5.52k
        break;
13894
24.5k
      }
13895
1.58k
      case state::FILE_SLASH: {
13896
1.58k
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13897
13898
        // If c is U+002F (/) or U+005C (\), then:
13899
1.58k
        if ((input_position != input_size) &&
13900
1.57k
            (url_data[input_position] == '/' ||
13901
1.15k
             url_data[input_position] == '\\')) {
13902
1.15k
          ada_log("FILE_SLASH c is U+002F or U+005C");
13903
          // Set state to file host state.
13904
1.15k
          state = state::FILE_HOST;
13905
1.15k
          input_position++;
13906
1.15k
        } else {
13907
436
          ada_log("FILE_SLASH otherwise");
13908
          // If base is non-null and base's scheme is "file", then:
13909
          // Note: it is unsafe to do base_url->scheme unless you know that
13910
          // base_url_has_value() is true.
13911
436
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13912
            // Set url's host to base's host.
13913
0
            if constexpr (result_type_is_ada_url) {
13914
0
              url.host = base_url->host;
13915
0
            } else {
13916
0
              url.update_host_to_base_host(base_url->get_host());
13917
0
            }
13918
            // If the code point substring from pointer to the end of input does
13919
            // not start with a Windows drive letter and base's path[0] is a
13920
            // normalized Windows drive letter, then append base's path[0] to
13921
            // url's path.
13922
0
            if (!base_url->get_pathname().empty()) {
13923
0
              if (!checkers::is_windows_drive_letter(
13924
0
                      url_data.substr(input_position))) {
13925
0
                std::string_view first_base_url_path =
13926
0
                    base_url->get_pathname().substr(1);
13927
0
                size_t loc = first_base_url_path.find('/');
13928
0
                if (loc != std::string_view::npos) {
13929
0
                  helpers::resize(first_base_url_path, loc);
13930
0
                }
13931
0
                if (checkers::is_normalized_windows_drive_letter(
13932
0
                        first_base_url_path)) {
13933
0
                  if constexpr (result_type_is_ada_url) {
13934
0
                    url.path += '/';
13935
0
                    url.path += first_base_url_path;
13936
0
                  } else {
13937
0
                    url.append_base_pathname(
13938
0
                        helpers::concat("/", first_base_url_path));
13939
0
                  }
13940
0
                }
13941
0
              }
13942
0
            }
13943
0
          }
13944
13945
          // Set state to path state, and decrease pointer by 1.
13946
436
          state = state::PATH;
13947
436
        }
13948
13949
1.58k
        break;
13950
24.5k
      }
13951
1.15k
      case state::FILE_HOST: {
13952
1.15k
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13953
1.15k
        std::string_view view = url_data.substr(input_position);
13954
13955
1.15k
        size_t location = view.find_first_of("/\\?");
13956
1.15k
        std::string_view file_host_buffer(
13957
1.15k
            view.data(),
13958
1.15k
            (location != std::string_view::npos) ? location : view.size());
13959
13960
1.15k
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13961
10
          state = state::PATH;
13962
1.14k
        } else if (file_host_buffer.empty()) {
13963
          // Set url's host to the empty string.
13964
50
          if constexpr (result_type_is_ada_url) {
13965
25
            url.host = "";
13966
25
          } else {
13967
25
            url.update_base_hostname("");
13968
25
          }
13969
          // Set state to path start state.
13970
50
          state = state::PATH_START;
13971
1.09k
        } else {
13972
1.09k
          size_t consumed_bytes = file_host_buffer.size();
13973
1.09k
          input_position += consumed_bytes;
13974
          // Let host be the result of host parsing buffer with url is not
13975
          // special.
13976
1.09k
          if (!url.parse_host(file_host_buffer)) {
13977
223
            return url;
13978
223
          }
13979
13980
869
          if constexpr (result_type_is_ada_url) {
13981
            // If host is "localhost", then set host to the empty string.
13982
443
            if (url.host.has_value() && url.host.value() == "localhost") {
13983
3
              url.host = "";
13984
3
            }
13985
443
          } else {
13986
426
            if (url.get_hostname() == "localhost") {
13987
3
              url.update_base_hostname("");
13988
3
            }
13989
426
          }
13990
13991
          // Set buffer to the empty string and state to path start state.
13992
869
          state = state::PATH_START;
13993
869
        }
13994
13995
929
        break;
13996
1.15k
      }
13997
2.83k
      case state::FILE: {
13998
2.83k
        ada_log("FILE ", helpers::substring(url_data, input_position));
13999
2.83k
        std::string_view file_view = url_data.substr(input_position);
14000
14001
2.83k
        url.set_protocol_as_file();
14002
2.83k
        if constexpr (result_type_is_ada_url) {
14003
          // Set url's host to the empty string.
14004
1.41k
          url.host = "";
14005
1.41k
        } else {
14006
1.41k
          url.update_base_hostname("");
14007
1.41k
        }
14008
        // If c is U+002F (/) or U+005C (\), then:
14009
2.83k
        if (input_position != input_size &&
14010
2.81k
            (url_data[input_position] == '/' ||
14011
1.58k
             url_data[input_position] == '\\')) {
14012
1.58k
          ada_log("FILE c is U+002F or U+005C");
14013
          // Set state to file slash state.
14014
1.58k
          state = state::FILE_SLASH;
14015
1.58k
        }
14016
        // Otherwise, if base is non-null and base's scheme is "file":
14017
1.24k
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
14018
          // Set url's host to base's host, url's path to a clone of base's
14019
          // path, and url's query to base's query.
14020
0
          ada_log("FILE base non-null");
14021
0
          if constexpr (result_type_is_ada_url) {
14022
0
            url.host = base_url->host;
14023
0
            url.path = base_url->path;
14024
0
            url.query = base_url->query;
14025
0
          } else {
14026
0
            url.update_host_to_base_host(base_url->get_hostname());
14027
0
            url.update_base_pathname(base_url->get_pathname());
14028
0
            url.update_base_search(base_url->get_search());
14029
0
          }
14030
0
          url.has_opaque_path = base_url->has_opaque_path;
14031
14032
          // If c is U+003F (?), then set url's query to the empty string and
14033
          // state to query state.
14034
0
          if (input_position != input_size && url_data[input_position] == '?') {
14035
0
            state = state::QUERY;
14036
0
          }
14037
          // Otherwise, if c is not the EOF code point:
14038
0
          else if (input_position != input_size) {
14039
            // Set url's query to null.
14040
0
            url.clear_search();
14041
            // If the code point substring from pointer to the end of input does
14042
            // not start with a Windows drive letter, then shorten url's path.
14043
0
            if (!checkers::is_windows_drive_letter(file_view)) {
14044
0
              if constexpr (result_type_is_ada_url) {
14045
0
                helpers::shorten_path(url.path, url.type);
14046
0
              } else {
14047
0
                std::string_view path = url.get_pathname();
14048
0
                if (helpers::shorten_path(path, url.type)) {
14049
0
                  url.update_base_pathname(std::move(std::string(path)));
14050
0
                }
14051
0
              }
14052
0
            }
14053
            // Otherwise:
14054
0
            else {
14055
              // Set url's path to an empty list.
14056
0
              url.clear_pathname();
14057
0
              url.has_opaque_path = true;
14058
0
            }
14059
14060
            // Set state to path state and decrease pointer by 1.
14061
0
            state = state::PATH;
14062
0
            break;
14063
0
          }
14064
0
        }
14065
        // Otherwise, set state to path state, and decrease pointer by 1.
14066
1.24k
        else {
14067
1.24k
          ada_log("FILE go to path");
14068
1.24k
          state = state::PATH;
14069
1.24k
          break;
14070
1.24k
        }
14071
14072
1.58k
        input_position++;
14073
1.58k
        break;
14074
2.83k
      }
14075
0
      default:
14076
0
        unreachable();
14077
207k
    }
14078
207k
  }
14079
8.74k
  if constexpr (store_values) {
14080
8.74k
    if (fragment.has_value()) {
14081
325
      url.update_unencoded_base_hash(*fragment);
14082
325
    }
14083
8.74k
  }
14084
8.74k
  return url;
14085
44.3k
}
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
13191
22.1k
                           const result_type* base_url) {
13192
  // We can specialize the implementation per type.
13193
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
13194
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
13195
  // something else } is free (at runtime). This means that ada::url_aggregator
13196
  // and ada::url **do not have to support the exact same API**.
13197
22.1k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13198
22.1k
  constexpr bool result_type_is_ada_url_aggregator =
13199
22.1k
      std::is_same_v<url_aggregator, result_type>;
13200
22.1k
  static_assert(result_type_is_ada_url ||
13201
22.1k
                result_type_is_ada_url_aggregator);  // We don't support
13202
                                                     // anything else for now.
13203
13204
22.1k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13205
22.1k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13206
22.1k
          ")");
13207
13208
22.1k
  state state = state::SCHEME_START;
13209
22.1k
  result_type url{};
13210
13211
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
13212
  // surely the result of a bug or are otherwise a security concern.
13213
22.1k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) [[unlikely]] {
13214
0
    url.is_valid = false;
13215
0
  }
13216
  // Going forward, user_input.size() is in [0,
13217
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
13218
  // base, or the optional_url was invalid, we must return.
13219
22.1k
  if (base_url != nullptr) {
13220
0
    url.is_valid &= base_url->is_valid;
13221
0
  }
13222
22.1k
  if (!url.is_valid) {
13223
0
    return url;
13224
0
  }
13225
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
13226
    // Most of the time, we just need user_input.size().
13227
    // In some instances, we may need a bit more.
13228
    ///////////////////////////
13229
    // This is *very* important. This line should *not* be removed
13230
    // hastily. There are principled reasons why reserve is important
13231
    // for performance. If you have a benchmark with small inputs,
13232
    // it may not matter, but in other instances, it could.
13233
    ////
13234
    // This rounds up to the next power of two.
13235
    // We know that user_input.size() is in [0,
13236
    // std::numeric_limits<uint32_t>::max).
13237
    uint32_t reserve_capacity =
13238
        (0xFFFFFFFF >>
13239
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13240
        1;
13241
    url.reserve(reserve_capacity);
13242
  }
13243
22.1k
  std::string tmp_buffer;
13244
22.1k
  std::string_view url_data;
13245
22.1k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13246
175
    tmp_buffer = user_input;
13247
    // Optimization opportunity: Instead of copying and then pruning, we could
13248
    // just directly build the string from user_input.
13249
175
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13250
175
    url_data = tmp_buffer;
13251
21.9k
  } else [[likely]] {
13252
21.9k
    url_data = user_input;
13253
21.9k
  }
13254
13255
  // Leading and trailing control characters are uncommon and easy to deal with
13256
  // (no performance concern).
13257
22.1k
  helpers::trim_c0_whitespace(url_data);
13258
13259
  // Optimization opportunity. Most websites do not have fragment.
13260
22.1k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13261
  // We add it last so that an implementation like ada::url_aggregator
13262
  // can append it last to its internal buffer, thus improving performance.
13263
13264
  // Here url_data no longer has its fragment.
13265
  // We are going to access the data from url_data (it is immutable).
13266
  // At any given time, we are pointing at byte 'input_position' in url_data.
13267
  // The input_position variable should range from 0 to input_size.
13268
  // It is illegal to access url_data at input_size.
13269
22.1k
  size_t input_position = 0;
13270
22.1k
  const size_t input_size = url_data.size();
13271
  // Keep running the following state machine by switching on state.
13272
  // If after a run pointer points to the EOF code point, go to the next step.
13273
  // Otherwise, increase pointer by 1 and continue with the state machine.
13274
  // We never decrement input_position.
13275
108k
  while (input_position <= input_size) {
13276
103k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13277
103k
            " in state ", ada::to_string(state));
13278
103k
    switch (state) {
13279
22.1k
      case state::SCHEME_START: {
13280
22.1k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13281
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13282
        // state to scheme state.
13283
22.1k
        if ((input_position != input_size) &&
13284
22.0k
            checkers::is_alpha(url_data[input_position])) {
13285
17.6k
          state = state::SCHEME;
13286
17.6k
          input_position++;
13287
17.6k
        } else {
13288
          // Otherwise, if state override is not given, set state to no scheme
13289
          // state and decrease pointer by 1.
13290
4.51k
          state = state::NO_SCHEME;
13291
4.51k
        }
13292
22.1k
        break;
13293
0
      }
13294
17.6k
      case state::SCHEME: {
13295
17.6k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13296
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13297
        // append c, lowercased, to buffer.
13298
91.4k
        while ((input_position != input_size) &&
13299
91.0k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13300
73.8k
          input_position++;
13301
73.8k
        }
13302
        // Otherwise, if c is U+003A (:), then:
13303
17.6k
        if ((input_position != input_size) &&
13304
17.2k
            (url_data[input_position] == ':')) {
13305
16.5k
          ada_log("SCHEME the scheme should be ",
13306
16.5k
                  url_data.substr(0, input_position));
13307
16.5k
          if constexpr (result_type_is_ada_url) {
13308
16.5k
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13309
0
              return url;
13310
0
            }
13311
          } else {
13312
            // we pass the colon along instead of painfully adding it back.
13313
            if (!url.parse_scheme_with_colon(
13314
                    url_data.substr(0, input_position + 1))) {
13315
              return url;
13316
            }
13317
          }
13318
16.5k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13319
13320
          // If url's scheme is "file", then:
13321
16.5k
          if (url.type == scheme::type::FILE) {
13322
            // Set state to file state.
13323
1.41k
            state = state::FILE;
13324
1.41k
          }
13325
          // Otherwise, if url is special, base is non-null, and base's scheme
13326
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13327
          // != nullptr is false.
13328
15.1k
          else if (url.is_special() && base_url != nullptr &&
13329
0
                   base_url->type == url.type) {
13330
            // Set state to special relative or authority state.
13331
0
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13332
0
          }
13333
          // Otherwise, if url is special, set state to special authority
13334
          // slashes state.
13335
15.1k
          else if (url.is_special()) {
13336
12.1k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13337
12.1k
          }
13338
          // Otherwise, if remaining starts with an U+002F (/), set state to
13339
          // path or authority state and increase pointer by 1.
13340
3.06k
          else if (input_position + 1 < input_size &&
13341
2.69k
                   url_data[input_position + 1] == '/') {
13342
1.34k
            state = state::PATH_OR_AUTHORITY;
13343
1.34k
            input_position++;
13344
1.34k
          }
13345
          // Otherwise, set url's path to the empty string and set state to
13346
          // opaque path state.
13347
1.72k
          else {
13348
1.72k
            state = state::OPAQUE_PATH;
13349
1.72k
          }
13350
16.5k
        }
13351
        // Otherwise, if state override is not given, set buffer to the empty
13352
        // string, state to no scheme state, and start over (from the first code
13353
        // point in input).
13354
1.04k
        else {
13355
1.04k
          state = state::NO_SCHEME;
13356
1.04k
          input_position = 0;
13357
1.04k
          break;
13358
1.04k
        }
13359
16.5k
        input_position++;
13360
16.5k
        break;
13361
17.6k
      }
13362
5.56k
      case state::NO_SCHEME: {
13363
5.56k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13364
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13365
        // validation error, return failure.
13366
5.56k
        if (base_url == nullptr ||
13367
5.56k
            (base_url->has_opaque_path && !fragment.has_value())) {
13368
5.56k
          ada_log("NO_SCHEME validation error");
13369
5.56k
          url.is_valid = false;
13370
5.56k
          return url;
13371
5.56k
        }
13372
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13373
        // set url's scheme to base's scheme, url's path to base's path, url's
13374
        // query to base's query, and set state to fragment state.
13375
0
        else if (base_url->has_opaque_path && fragment.has_value() &&
13376
0
                 input_position == input_size) {
13377
0
          ada_log("NO_SCHEME opaque base with fragment");
13378
0
          url.copy_scheme(*base_url);
13379
0
          url.has_opaque_path = base_url->has_opaque_path;
13380
13381
0
          if constexpr (result_type_is_ada_url) {
13382
0
            url.path = base_url->path;
13383
0
            url.query = base_url->query;
13384
          } else {
13385
            url.update_base_pathname(base_url->get_pathname());
13386
            url.update_base_search(base_url->get_search());
13387
          }
13388
0
          url.update_unencoded_base_hash(*fragment);
13389
0
          return url;
13390
0
        }
13391
        // Otherwise, if base's scheme is not "file", set state to relative
13392
        // state and decrease pointer by 1.
13393
0
        else if (base_url->type != scheme::type::FILE) {
13394
0
          ada_log("NO_SCHEME non-file relative path");
13395
0
          state = state::RELATIVE_SCHEME;
13396
0
        }
13397
        // Otherwise, set state to file state and decrease pointer by 1.
13398
0
        else {
13399
0
          ada_log("NO_SCHEME file base type");
13400
0
          state = state::FILE;
13401
0
        }
13402
0
        break;
13403
5.56k
      }
13404
12.4k
      case state::AUTHORITY: {
13405
12.4k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13406
        // most URLs have no @. Having no @ tells us that we don't have to worry
13407
        // about AUTHORITY. Of course, we could have @ and still not have to
13408
        // worry about AUTHORITY.
13409
        // TODO: Instead of just collecting a bool, collect the location of the
13410
        // '@' and do something useful with it.
13411
        // TODO: We could do various processing early on, using a single pass
13412
        // over the string to collect information about it, e.g., telling us
13413
        // whether there is a @ and if so, where (or how many).
13414
13415
        // Check if url data contains an @.
13416
12.4k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13417
11.7k
          state = state::HOST;
13418
11.7k
          break;
13419
11.7k
        }
13420
728
        bool at_sign_seen{false};
13421
728
        bool password_token_seen{false};
13422
        /**
13423
         * We expect something of the sort...
13424
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13425
         * --------^
13426
         */
13427
7.90k
        do {
13428
7.90k
          std::string_view view = url_data.substr(input_position);
13429
          // The delimiters are @, /, ? \\.
13430
7.90k
          size_t location =
13431
7.90k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13432
7.90k
                               : helpers::find_authority_delimiter(view);
13433
7.90k
          std::string_view authority_view = view.substr(0, location);
13434
7.90k
          size_t end_of_authority = input_position + authority_view.size();
13435
          // If c is U+0040 (@), then:
13436
7.90k
          if ((end_of_authority != input_size) &&
13437
7.26k
              (url_data[end_of_authority] == '@')) {
13438
            // If atSignSeen is true, then prepend "%40" to buffer.
13439
7.17k
            if (at_sign_seen) {
13440
6.48k
              if (password_token_seen) {
13441
2.52k
                if constexpr (result_type_is_ada_url) {
13442
2.52k
                  url.password += "%40";
13443
                } else {
13444
                  url.append_base_password("%40");
13445
                }
13446
3.96k
              } else {
13447
3.96k
                if constexpr (result_type_is_ada_url) {
13448
3.96k
                  url.username += "%40";
13449
                } else {
13450
                  url.append_base_username("%40");
13451
                }
13452
3.96k
              }
13453
6.48k
            }
13454
13455
7.17k
            at_sign_seen = true;
13456
13457
7.17k
            if (!password_token_seen) {
13458
4.65k
              size_t password_token_location = authority_view.find(':');
13459
4.65k
              password_token_seen =
13460
4.65k
                  password_token_location != std::string_view::npos;
13461
13462
4.65k
              if constexpr (store_values) {
13463
4.65k
                if (!password_token_seen) {
13464
4.35k
                  if constexpr (result_type_is_ada_url) {
13465
4.35k
                    url.username += unicode::percent_encode(
13466
4.35k
                        authority_view,
13467
4.35k
                        character_sets::USERINFO_PERCENT_ENCODE);
13468
                  } else {
13469
                    url.append_base_username(unicode::percent_encode(
13470
                        authority_view,
13471
                        character_sets::USERINFO_PERCENT_ENCODE));
13472
                  }
13473
4.35k
                } else {
13474
303
                  if constexpr (result_type_is_ada_url) {
13475
303
                    url.username += unicode::percent_encode(
13476
303
                        authority_view.substr(0, password_token_location),
13477
303
                        character_sets::USERINFO_PERCENT_ENCODE);
13478
303
                    url.password += unicode::percent_encode(
13479
303
                        authority_view.substr(password_token_location + 1),
13480
303
                        character_sets::USERINFO_PERCENT_ENCODE);
13481
                  } else {
13482
                    url.append_base_username(unicode::percent_encode(
13483
                        authority_view.substr(0, password_token_location),
13484
                        character_sets::USERINFO_PERCENT_ENCODE));
13485
                    url.append_base_password(unicode::percent_encode(
13486
                        authority_view.substr(password_token_location + 1),
13487
                        character_sets::USERINFO_PERCENT_ENCODE));
13488
                  }
13489
303
                }
13490
4.65k
              }
13491
4.65k
            } else if constexpr (store_values) {
13492
2.52k
              if constexpr (result_type_is_ada_url) {
13493
2.52k
                url.password += unicode::percent_encode(
13494
2.52k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13495
              } else {
13496
                url.append_base_password(unicode::percent_encode(
13497
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13498
              }
13499
2.52k
            }
13500
7.17k
          }
13501
          // Otherwise, if one of the following is true:
13502
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13503
          // - url is special and c is U+005C (\)
13504
728
          else if (end_of_authority == input_size ||
13505
93
                   url_data[end_of_authority] == '/' ||
13506
29
                   url_data[end_of_authority] == '?' ||
13507
728
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13508
            // If atSignSeen is true and authority_view is the empty string,
13509
            // validation error, return failure.
13510
728
            if (at_sign_seen && authority_view.empty()) {
13511
108
              url.is_valid = false;
13512
108
              return url;
13513
108
            }
13514
620
            state = state::HOST;
13515
620
            break;
13516
728
          }
13517
7.17k
          if (end_of_authority == input_size) {
13518
0
            if constexpr (store_values) {
13519
0
              if (fragment.has_value()) {
13520
0
                url.update_unencoded_base_hash(*fragment);
13521
0
              }
13522
0
            }
13523
0
            return url;
13524
0
          }
13525
7.17k
          input_position = end_of_authority + 1;
13526
7.17k
        } while (true);
13527
13528
620
        break;
13529
728
      }
13530
620
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
13531
0
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
13532
0
                helpers::substring(url_data, input_position));
13533
13534
        // If c is U+002F (/) and remaining starts with U+002F (/),
13535
        // then set state to special authority ignore slashes state and increase
13536
        // pointer by 1.
13537
0
        if (url_data.substr(input_position, 2) == "//") {
13538
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13539
0
          input_position += 2;
13540
0
        } else {
13541
          // Otherwise, validation error, set state to relative state and
13542
          // decrease pointer by 1.
13543
0
          state = state::RELATIVE_SCHEME;
13544
0
        }
13545
13546
0
        break;
13547
728
      }
13548
1.34k
      case state::PATH_OR_AUTHORITY: {
13549
1.34k
        ada_log("PATH_OR_AUTHORITY ",
13550
1.34k
                helpers::substring(url_data, input_position));
13551
13552
        // If c is U+002F (/), then set state to authority state.
13553
1.34k
        if ((input_position != input_size) &&
13554
1.33k
            (url_data[input_position] == '/')) {
13555
387
          state = state::AUTHORITY;
13556
387
          input_position++;
13557
956
        } else {
13558
          // Otherwise, set state to path state, and decrease pointer by 1.
13559
956
          state = state::PATH;
13560
956
        }
13561
13562
1.34k
        break;
13563
728
      }
13564
0
      case state::RELATIVE_SCHEME: {
13565
0
        ada_log("RELATIVE_SCHEME ",
13566
0
                helpers::substring(url_data, input_position));
13567
13568
        // Set url's scheme to base's scheme.
13569
0
        url.copy_scheme(*base_url);
13570
13571
        // If c is U+002F (/), then set state to relative slash state.
13572
0
        if ((input_position != input_size) &&
13573
            // NOLINTNEXTLINE(bugprone-branch-clone)
13574
0
            (url_data[input_position] == '/')) {
13575
0
          ada_log(
13576
0
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
13577
0
              "slash state");
13578
0
          state = state::RELATIVE_SLASH;
13579
0
        } else if (url.is_special() && (input_position != input_size) &&
13580
0
                   (url_data[input_position] == '\\')) {
13581
          // Otherwise, if url is special and c is U+005C (\), validation error,
13582
          // set state to relative slash state.
13583
0
          ada_log(
13584
0
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
13585
0
              "error, set state to relative slash state");
13586
0
          state = state::RELATIVE_SLASH;
13587
0
        } else {
13588
0
          ada_log("RELATIVE_SCHEME otherwise");
13589
          // Set url's username to base's username, url's password to base's
13590
          // password, url's host to base's host, url's port to base's port,
13591
          // url's path to a clone of base's path, and url's query to base's
13592
          // query.
13593
0
          if constexpr (result_type_is_ada_url) {
13594
0
            url.username = base_url->username;
13595
0
            url.password = base_url->password;
13596
0
            url.host = base_url->host;
13597
0
            url.port = base_url->port;
13598
            // cloning the base path includes cloning the has_opaque_path flag
13599
0
            url.has_opaque_path = base_url->has_opaque_path;
13600
0
            url.path = base_url->path;
13601
0
            url.query = base_url->query;
13602
          } else {
13603
            url.update_base_authority(base_url->get_href(),
13604
                                      base_url->get_components());
13605
            url.update_host_to_base_host(base_url->get_hostname());
13606
            url.update_base_port(base_url->retrieve_base_port());
13607
            // cloning the base path includes cloning the has_opaque_path flag
13608
            url.has_opaque_path = base_url->has_opaque_path;
13609
            url.update_base_pathname(base_url->get_pathname());
13610
            url.update_base_search(base_url->get_search());
13611
          }
13612
13613
0
          url.has_opaque_path = base_url->has_opaque_path;
13614
13615
          // If c is U+003F (?), then set url's query to the empty string, and
13616
          // state to query state.
13617
0
          if ((input_position != input_size) &&
13618
0
              (url_data[input_position] == '?')) {
13619
0
            state = state::QUERY;
13620
0
          }
13621
          // Otherwise, if c is not the EOF code point:
13622
0
          else if (input_position != input_size) {
13623
            // Set url's query to null.
13624
0
            url.clear_search();
13625
0
            if constexpr (result_type_is_ada_url) {
13626
              // Shorten url's path.
13627
0
              helpers::shorten_path(url.path, url.type);
13628
            } else {
13629
              std::string_view path = url.get_pathname();
13630
              if (helpers::shorten_path(path, url.type)) {
13631
                url.update_base_pathname(std::move(std::string(path)));
13632
              }
13633
            }
13634
            // Set state to path state and decrease pointer by 1.
13635
0
            state = state::PATH;
13636
0
            break;
13637
0
          }
13638
0
        }
13639
0
        input_position++;
13640
0
        break;
13641
0
      }
13642
0
      case state::RELATIVE_SLASH: {
13643
0
        ada_log("RELATIVE_SLASH ",
13644
0
                helpers::substring(url_data, input_position));
13645
13646
        // If url is special and c is U+002F (/) or U+005C (\), then:
13647
0
        if (url.is_special() && (input_position != input_size) &&
13648
0
            (url_data[input_position] == '/' ||
13649
0
             url_data[input_position] == '\\')) {
13650
          // Set state to special authority ignore slashes state.
13651
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13652
0
        }
13653
        // Otherwise, if c is U+002F (/), then set state to authority state.
13654
0
        else if ((input_position != input_size) &&
13655
0
                 (url_data[input_position] == '/')) {
13656
0
          state = state::AUTHORITY;
13657
0
        }
13658
        // Otherwise, set
13659
        // - url's username to base's username,
13660
        // - url's password to base's password,
13661
        // - url's host to base's host,
13662
        // - url's port to base's port,
13663
        // - state to path state, and then, decrease pointer by 1.
13664
0
        else {
13665
0
          if constexpr (result_type_is_ada_url) {
13666
0
            url.username = base_url->username;
13667
0
            url.password = base_url->password;
13668
0
            url.host = base_url->host;
13669
0
            url.port = base_url->port;
13670
          } else {
13671
            url.update_base_authority(base_url->get_href(),
13672
                                      base_url->get_components());
13673
            url.update_host_to_base_host(base_url->get_hostname());
13674
            url.update_base_port(base_url->retrieve_base_port());
13675
          }
13676
0
          state = state::PATH;
13677
0
          break;
13678
0
        }
13679
13680
0
        input_position++;
13681
0
        break;
13682
0
      }
13683
12.1k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13684
12.1k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13685
12.1k
                helpers::substring(url_data, input_position));
13686
13687
        // If c is U+002F (/) and remaining starts with U+002F (/),
13688
        // then set state to special authority ignore slashes state and increase
13689
        // pointer by 1.
13690
12.1k
        if (url_data.substr(input_position, 2) == "//") {
13691
9.30k
          input_position += 2;
13692
9.30k
        }
13693
13694
12.1k
        [[fallthrough]];
13695
12.1k
      }
13696
12.1k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13697
12.1k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13698
12.1k
                helpers::substring(url_data, input_position));
13699
13700
        // If c is neither U+002F (/) nor U+005C (\), then set state to
13701
        // authority state and decrease pointer by 1.
13702
12.7k
        while ((input_position != input_size) &&
13703
12.7k
               ((url_data[input_position] == '/') ||
13704
12.2k
                (url_data[input_position] == '\\'))) {
13705
627
          input_position++;
13706
627
        }
13707
12.1k
        state = state::AUTHORITY;
13708
13709
12.1k
        break;
13710
12.1k
      }
13711
324
      case state::QUERY: {
13712
324
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13713
324
        if constexpr (store_values) {
13714
          // Let queryPercentEncodeSet be the special-query percent-encode set
13715
          // if url is special; otherwise the query percent-encode set.
13716
324
          const uint8_t* query_percent_encode_set =
13717
324
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13718
324
                               : character_sets::QUERY_PERCENT_ENCODE;
13719
13720
          // Percent-encode after encoding, with encoding, buffer, and
13721
          // queryPercentEncodeSet, and append the result to url's query.
13722
324
          url.update_base_search(url_data.substr(input_position),
13723
324
                                 query_percent_encode_set);
13724
324
          ada_log("QUERY update_base_search completed ");
13725
324
          if (fragment.has_value()) {
13726
23
            url.update_unencoded_base_hash(*fragment);
13727
23
          }
13728
324
        }
13729
324
        return url;
13730
12.1k
      }
13731
12.3k
      case state::HOST: {
13732
12.3k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13733
13734
12.3k
        std::string_view host_view = url_data.substr(input_position);
13735
12.3k
        auto [location, found_colon] =
13736
12.3k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13737
12.3k
        input_position = (location != std::string_view::npos)
13738
12.3k
                             ? input_position + location
13739
12.3k
                             : input_size;
13740
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13741
        // Note: the 'found_colon' value is true if and only if a colon was
13742
        // encountered while not inside brackets.
13743
12.3k
        if (found_colon) {
13744
          // If buffer is the empty string, validation error, return failure.
13745
          // Let host be the result of host parsing buffer with url is not
13746
          // special.
13747
722
          ada_log("HOST parsing ", host_view);
13748
722
          if (!url.parse_host(host_view)) {
13749
86
            return url;
13750
86
          }
13751
636
          ada_log("HOST parsing results in ", url.get_hostname());
13752
          // Set url's host to host, buffer to the empty string, and state to
13753
          // port state.
13754
636
          state = state::PORT;
13755
636
          input_position++;
13756
636
        }
13757
        // Otherwise, if one of the following is true:
13758
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13759
        // - url is special and c is U+005C (\)
13760
        // The get_host_delimiter_location function either brings us to
13761
        // the colon outside of the bracket, or to one of those characters.
13762
11.6k
        else {
13763
          // If url is special and host_view is the empty string, validation
13764
          // error, return failure.
13765
11.6k
          if (host_view.empty() && url.is_special()) {
13766
11
            url.is_valid = false;
13767
11
            return url;
13768
11
          }
13769
11.6k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
13770
          // Let host be the result of host parsing host_view with url is not
13771
          // special.
13772
11.6k
          if (host_view.empty()) {
13773
41
            url.update_base_hostname("");
13774
11.6k
          } else if (!url.parse_host(host_view)) {
13775
290
            return url;
13776
290
          }
13777
11.3k
          ada_log("HOST parsing results in ", url.get_hostname(),
13778
11.3k
                  " href=", url.get_href());
13779
13780
          // Set url's host to host, and state to path start state.
13781
11.3k
          state = state::PATH_START;
13782
11.3k
        }
13783
13784
12.0k
        break;
13785
12.3k
      }
13786
12.0k
      case state::OPAQUE_PATH: {
13787
1.72k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13788
1.72k
        std::string_view view = url_data.substr(input_position);
13789
        // If c is U+003F (?), then set url's query to the empty string and
13790
        // state to query state.
13791
1.72k
        size_t location = view.find('?');
13792
1.72k
        if (location != std::string_view::npos) {
13793
144
          view.remove_suffix(view.size() - location);
13794
144
          state = state::QUERY;
13795
144
          input_position += location + 1;
13796
1.57k
        } else {
13797
1.57k
          input_position = input_size + 1;
13798
1.57k
        }
13799
1.72k
        url.has_opaque_path = true;
13800
13801
        // This is a really unlikely scenario in real world. We should not seek
13802
        // to optimize it.
13803
1.72k
        if (view.ends_with(' ')) {
13804
66
          std::string modified_view =
13805
66
              std::string(view.substr(0, view.size() - 1)) + "%20";
13806
66
          url.update_base_pathname(unicode::percent_encode(
13807
66
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13808
1.65k
        } else {
13809
1.65k
          url.update_base_pathname(unicode::percent_encode(
13810
1.65k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13811
1.65k
        }
13812
1.72k
        break;
13813
12.3k
      }
13814
636
      case state::PORT: {
13815
636
        ada_log("PORT ", helpers::substring(url_data, input_position));
13816
636
        std::string_view port_view = url_data.substr(input_position);
13817
636
        input_position += url.parse_port(port_view, true);
13818
636
        if (!url.is_valid) {
13819
111
          return url;
13820
111
        }
13821
525
        state = state::PATH_START;
13822
525
        [[fallthrough]];
13823
525
      }
13824
12.3k
      case state::PATH_START: {
13825
12.3k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13826
13827
        // If url is special, then:
13828
12.3k
        if (url.is_special()) {
13829
          // Set state to path state.
13830
12.1k
          state = state::PATH;
13831
13832
          // Optimization: Avoiding going into PATH state improves the
13833
          // performance of urls ending with /.
13834
12.1k
          if (input_position == input_size) {
13835
11.1k
            if constexpr (store_values) {
13836
11.1k
              url.update_base_pathname("/");
13837
11.1k
              if (fragment.has_value()) {
13838
92
                url.update_unencoded_base_hash(*fragment);
13839
92
              }
13840
11.1k
            }
13841
11.1k
            return url;
13842
11.1k
          }
13843
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
13844
          // by 1. We know that (input_position == input_size) is impossible
13845
          // here, because of the previous if-check.
13846
968
          if ((url_data[input_position] != '/') &&
13847
116
              (url_data[input_position] != '\\')) {
13848
99
            break;
13849
99
          }
13850
968
        }
13851
        // Otherwise, if state override is not given and c is U+003F (?),
13852
        // set url's query to the empty string and state to query state.
13853
260
        else if ((input_position != input_size) &&
13854
56
                 (url_data[input_position] == '?')) {
13855
10
          state = state::QUERY;
13856
10
        }
13857
        // Otherwise, if c is not the EOF code point:
13858
250
        else if (input_position != input_size) {
13859
          // Set state to path state.
13860
46
          state = state::PATH;
13861
13862
          // If c is not U+002F (/), then decrease pointer by 1.
13863
46
          if (url_data[input_position] != '/') {
13864
0
            break;
13865
0
          }
13866
46
        }
13867
13868
1.12k
        input_position++;
13869
1.12k
        break;
13870
12.3k
      }
13871
2.81k
      case state::PATH: {
13872
2.81k
        ada_log("PATH ", helpers::substring(url_data, input_position));
13873
2.81k
        std::string_view view = url_data.substr(input_position);
13874
13875
        // Most time, we do not need percent encoding.
13876
        // Furthermore, we can immediately locate the '?'.
13877
2.81k
        size_t locofquestionmark = view.find('?');
13878
2.81k
        if (locofquestionmark != std::string_view::npos) {
13879
170
          state = state::QUERY;
13880
170
          view.remove_suffix(view.size() - locofquestionmark);
13881
170
          input_position += locofquestionmark + 1;
13882
2.64k
        } else {
13883
2.64k
          input_position = input_size + 1;
13884
2.64k
        }
13885
2.81k
        if constexpr (store_values) {
13886
2.81k
          if constexpr (result_type_is_ada_url) {
13887
2.81k
            helpers::parse_prepared_path(view, url.type, url.path);
13888
          } else {
13889
            url.consume_prepared_path(view);
13890
            ADA_ASSERT_TRUE(url.validate());
13891
          }
13892
2.81k
        }
13893
2.81k
        break;
13894
12.3k
      }
13895
794
      case state::FILE_SLASH: {
13896
794
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13897
13898
        // If c is U+002F (/) or U+005C (\), then:
13899
794
        if ((input_position != input_size) &&
13900
789
            (url_data[input_position] == '/' ||
13901
576
             url_data[input_position] == '\\')) {
13902
576
          ada_log("FILE_SLASH c is U+002F or U+005C");
13903
          // Set state to file host state.
13904
576
          state = state::FILE_HOST;
13905
576
          input_position++;
13906
576
        } else {
13907
218
          ada_log("FILE_SLASH otherwise");
13908
          // If base is non-null and base's scheme is "file", then:
13909
          // Note: it is unsafe to do base_url->scheme unless you know that
13910
          // base_url_has_value() is true.
13911
218
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13912
            // Set url's host to base's host.
13913
0
            if constexpr (result_type_is_ada_url) {
13914
0
              url.host = base_url->host;
13915
            } else {
13916
              url.update_host_to_base_host(base_url->get_host());
13917
            }
13918
            // If the code point substring from pointer to the end of input does
13919
            // not start with a Windows drive letter and base's path[0] is a
13920
            // normalized Windows drive letter, then append base's path[0] to
13921
            // url's path.
13922
0
            if (!base_url->get_pathname().empty()) {
13923
0
              if (!checkers::is_windows_drive_letter(
13924
0
                      url_data.substr(input_position))) {
13925
0
                std::string_view first_base_url_path =
13926
0
                    base_url->get_pathname().substr(1);
13927
0
                size_t loc = first_base_url_path.find('/');
13928
0
                if (loc != std::string_view::npos) {
13929
0
                  helpers::resize(first_base_url_path, loc);
13930
0
                }
13931
0
                if (checkers::is_normalized_windows_drive_letter(
13932
0
                        first_base_url_path)) {
13933
0
                  if constexpr (result_type_is_ada_url) {
13934
0
                    url.path += '/';
13935
0
                    url.path += first_base_url_path;
13936
                  } else {
13937
                    url.append_base_pathname(
13938
                        helpers::concat("/", first_base_url_path));
13939
                  }
13940
0
                }
13941
0
              }
13942
0
            }
13943
0
          }
13944
13945
          // Set state to path state, and decrease pointer by 1.
13946
218
          state = state::PATH;
13947
218
        }
13948
13949
794
        break;
13950
12.3k
      }
13951
576
      case state::FILE_HOST: {
13952
576
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13953
576
        std::string_view view = url_data.substr(input_position);
13954
13955
576
        size_t location = view.find_first_of("/\\?");
13956
576
        std::string_view file_host_buffer(
13957
576
            view.data(),
13958
576
            (location != std::string_view::npos) ? location : view.size());
13959
13960
576
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13961
5
          state = state::PATH;
13962
571
        } else if (file_host_buffer.empty()) {
13963
          // Set url's host to the empty string.
13964
25
          if constexpr (result_type_is_ada_url) {
13965
25
            url.host = "";
13966
          } else {
13967
            url.update_base_hostname("");
13968
          }
13969
          // Set state to path start state.
13970
25
          state = state::PATH_START;
13971
546
        } else {
13972
546
          size_t consumed_bytes = file_host_buffer.size();
13973
546
          input_position += consumed_bytes;
13974
          // Let host be the result of host parsing buffer with url is not
13975
          // special.
13976
546
          if (!url.parse_host(file_host_buffer)) {
13977
103
            return url;
13978
103
          }
13979
13980
443
          if constexpr (result_type_is_ada_url) {
13981
            // If host is "localhost", then set host to the empty string.
13982
443
            if (url.host.has_value() && url.host.value() == "localhost") {
13983
3
              url.host = "";
13984
3
            }
13985
          } else {
13986
            if (url.get_hostname() == "localhost") {
13987
              url.update_base_hostname("");
13988
            }
13989
          }
13990
13991
          // Set buffer to the empty string and state to path start state.
13992
443
          state = state::PATH_START;
13993
443
        }
13994
13995
473
        break;
13996
576
      }
13997
1.41k
      case state::FILE: {
13998
1.41k
        ada_log("FILE ", helpers::substring(url_data, input_position));
13999
1.41k
        std::string_view file_view = url_data.substr(input_position);
14000
14001
1.41k
        url.set_protocol_as_file();
14002
1.41k
        if constexpr (result_type_is_ada_url) {
14003
          // Set url's host to the empty string.
14004
1.41k
          url.host = "";
14005
        } else {
14006
          url.update_base_hostname("");
14007
        }
14008
        // If c is U+002F (/) or U+005C (\), then:
14009
1.41k
        if (input_position != input_size &&
14010
1.40k
            (url_data[input_position] == '/' ||
14011
794
             url_data[input_position] == '\\')) {
14012
794
          ada_log("FILE c is U+002F or U+005C");
14013
          // Set state to file slash state.
14014
794
          state = state::FILE_SLASH;
14015
794
        }
14016
        // Otherwise, if base is non-null and base's scheme is "file":
14017
624
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
14018
          // Set url's host to base's host, url's path to a clone of base's
14019
          // path, and url's query to base's query.
14020
0
          ada_log("FILE base non-null");
14021
0
          if constexpr (result_type_is_ada_url) {
14022
0
            url.host = base_url->host;
14023
0
            url.path = base_url->path;
14024
0
            url.query = base_url->query;
14025
          } else {
14026
            url.update_host_to_base_host(base_url->get_hostname());
14027
            url.update_base_pathname(base_url->get_pathname());
14028
            url.update_base_search(base_url->get_search());
14029
          }
14030
0
          url.has_opaque_path = base_url->has_opaque_path;
14031
14032
          // If c is U+003F (?), then set url's query to the empty string and
14033
          // state to query state.
14034
0
          if (input_position != input_size && url_data[input_position] == '?') {
14035
0
            state = state::QUERY;
14036
0
          }
14037
          // Otherwise, if c is not the EOF code point:
14038
0
          else if (input_position != input_size) {
14039
            // Set url's query to null.
14040
0
            url.clear_search();
14041
            // If the code point substring from pointer to the end of input does
14042
            // not start with a Windows drive letter, then shorten url's path.
14043
0
            if (!checkers::is_windows_drive_letter(file_view)) {
14044
0
              if constexpr (result_type_is_ada_url) {
14045
0
                helpers::shorten_path(url.path, url.type);
14046
              } else {
14047
                std::string_view path = url.get_pathname();
14048
                if (helpers::shorten_path(path, url.type)) {
14049
                  url.update_base_pathname(std::move(std::string(path)));
14050
                }
14051
              }
14052
0
            }
14053
            // Otherwise:
14054
0
            else {
14055
              // Set url's path to an empty list.
14056
0
              url.clear_pathname();
14057
0
              url.has_opaque_path = true;
14058
0
            }
14059
14060
            // Set state to path state and decrease pointer by 1.
14061
0
            state = state::PATH;
14062
0
            break;
14063
0
          }
14064
0
        }
14065
        // Otherwise, set state to path state, and decrease pointer by 1.
14066
624
        else {
14067
624
          ada_log("FILE go to path");
14068
624
          state = state::PATH;
14069
624
          break;
14070
624
        }
14071
14072
794
        input_position++;
14073
794
        break;
14074
1.41k
      }
14075
0
      default:
14076
0
        unreachable();
14077
103k
    }
14078
103k
  }
14079
4.42k
  if constexpr (store_values) {
14080
4.42k
    if (fragment.has_value()) {
14081
163
      url.update_unencoded_base_hash(*fragment);
14082
163
    }
14083
4.42k
  }
14084
4.42k
  return url;
14085
22.1k
}
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
13191
22.1k
                           const result_type* base_url) {
13192
  // We can specialize the implementation per type.
13193
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
13194
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
13195
  // something else } is free (at runtime). This means that ada::url_aggregator
13196
  // and ada::url **do not have to support the exact same API**.
13197
22.1k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13198
22.1k
  constexpr bool result_type_is_ada_url_aggregator =
13199
22.1k
      std::is_same_v<url_aggregator, result_type>;
13200
22.1k
  static_assert(result_type_is_ada_url ||
13201
22.1k
                result_type_is_ada_url_aggregator);  // We don't support
13202
                                                     // anything else for now.
13203
13204
22.1k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13205
22.1k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13206
22.1k
          ")");
13207
13208
22.1k
  state state = state::SCHEME_START;
13209
22.1k
  result_type url{};
13210
13211
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
13212
  // surely the result of a bug or are otherwise a security concern.
13213
22.1k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) [[unlikely]] {
13214
0
    url.is_valid = false;
13215
0
  }
13216
  // Going forward, user_input.size() is in [0,
13217
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
13218
  // base, or the optional_url was invalid, we must return.
13219
22.1k
  if (base_url != nullptr) {
13220
0
    url.is_valid &= base_url->is_valid;
13221
0
  }
13222
22.1k
  if (!url.is_valid) {
13223
0
    return url;
13224
0
  }
13225
22.1k
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
13226
    // Most of the time, we just need user_input.size().
13227
    // In some instances, we may need a bit more.
13228
    ///////////////////////////
13229
    // This is *very* important. This line should *not* be removed
13230
    // hastily. There are principled reasons why reserve is important
13231
    // for performance. If you have a benchmark with small inputs,
13232
    // it may not matter, but in other instances, it could.
13233
    ////
13234
    // This rounds up to the next power of two.
13235
    // We know that user_input.size() is in [0,
13236
    // std::numeric_limits<uint32_t>::max).
13237
22.1k
    uint32_t reserve_capacity =
13238
22.1k
        (0xFFFFFFFF >>
13239
22.1k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13240
22.1k
        1;
13241
22.1k
    url.reserve(reserve_capacity);
13242
22.1k
  }
13243
22.1k
  std::string tmp_buffer;
13244
22.1k
  std::string_view url_data;
13245
22.1k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13246
175
    tmp_buffer = user_input;
13247
    // Optimization opportunity: Instead of copying and then pruning, we could
13248
    // just directly build the string from user_input.
13249
175
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13250
175
    url_data = tmp_buffer;
13251
21.9k
  } else [[likely]] {
13252
21.9k
    url_data = user_input;
13253
21.9k
  }
13254
13255
  // Leading and trailing control characters are uncommon and easy to deal with
13256
  // (no performance concern).
13257
22.1k
  helpers::trim_c0_whitespace(url_data);
13258
13259
  // Optimization opportunity. Most websites do not have fragment.
13260
22.1k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13261
  // We add it last so that an implementation like ada::url_aggregator
13262
  // can append it last to its internal buffer, thus improving performance.
13263
13264
  // Here url_data no longer has its fragment.
13265
  // We are going to access the data from url_data (it is immutable).
13266
  // At any given time, we are pointing at byte 'input_position' in url_data.
13267
  // The input_position variable should range from 0 to input_size.
13268
  // It is illegal to access url_data at input_size.
13269
22.1k
  size_t input_position = 0;
13270
22.1k
  const size_t input_size = url_data.size();
13271
  // Keep running the following state machine by switching on state.
13272
  // If after a run pointer points to the EOF code point, go to the next step.
13273
  // Otherwise, increase pointer by 1 and continue with the state machine.
13274
  // We never decrement input_position.
13275
107k
  while (input_position <= input_size) {
13276
103k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13277
103k
            " in state ", ada::to_string(state));
13278
103k
    switch (state) {
13279
22.1k
      case state::SCHEME_START: {
13280
22.1k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13281
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13282
        // state to scheme state.
13283
22.1k
        if ((input_position != input_size) &&
13284
22.0k
            checkers::is_alpha(url_data[input_position])) {
13285
17.6k
          state = state::SCHEME;
13286
17.6k
          input_position++;
13287
17.6k
        } else {
13288
          // Otherwise, if state override is not given, set state to no scheme
13289
          // state and decrease pointer by 1.
13290
4.51k
          state = state::NO_SCHEME;
13291
4.51k
        }
13292
22.1k
        break;
13293
0
      }
13294
17.6k
      case state::SCHEME: {
13295
17.6k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13296
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13297
        // append c, lowercased, to buffer.
13298
91.4k
        while ((input_position != input_size) &&
13299
91.0k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13300
73.8k
          input_position++;
13301
73.8k
        }
13302
        // Otherwise, if c is U+003A (:), then:
13303
17.6k
        if ((input_position != input_size) &&
13304
17.2k
            (url_data[input_position] == ':')) {
13305
16.5k
          ada_log("SCHEME the scheme should be ",
13306
16.5k
                  url_data.substr(0, input_position));
13307
          if constexpr (result_type_is_ada_url) {
13308
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13309
              return url;
13310
            }
13311
16.5k
          } else {
13312
            // we pass the colon along instead of painfully adding it back.
13313
16.5k
            if (!url.parse_scheme_with_colon(
13314
16.5k
                    url_data.substr(0, input_position + 1))) {
13315
0
              return url;
13316
0
            }
13317
16.5k
          }
13318
16.5k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13319
13320
          // If url's scheme is "file", then:
13321
16.5k
          if (url.type == scheme::type::FILE) {
13322
            // Set state to file state.
13323
1.41k
            state = state::FILE;
13324
1.41k
          }
13325
          // Otherwise, if url is special, base is non-null, and base's scheme
13326
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13327
          // != nullptr is false.
13328
15.1k
          else if (url.is_special() && base_url != nullptr &&
13329
0
                   base_url->type == url.type) {
13330
            // Set state to special relative or authority state.
13331
0
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13332
0
          }
13333
          // Otherwise, if url is special, set state to special authority
13334
          // slashes state.
13335
15.1k
          else if (url.is_special()) {
13336
12.1k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13337
12.1k
          }
13338
          // Otherwise, if remaining starts with an U+002F (/), set state to
13339
          // path or authority state and increase pointer by 1.
13340
3.06k
          else if (input_position + 1 < input_size &&
13341
2.69k
                   url_data[input_position + 1] == '/') {
13342
1.34k
            state = state::PATH_OR_AUTHORITY;
13343
1.34k
            input_position++;
13344
1.34k
          }
13345
          // Otherwise, set url's path to the empty string and set state to
13346
          // opaque path state.
13347
1.72k
          else {
13348
1.72k
            state = state::OPAQUE_PATH;
13349
1.72k
          }
13350
16.5k
        }
13351
        // Otherwise, if state override is not given, set buffer to the empty
13352
        // string, state to no scheme state, and start over (from the first code
13353
        // point in input).
13354
1.04k
        else {
13355
1.04k
          state = state::NO_SCHEME;
13356
1.04k
          input_position = 0;
13357
1.04k
          break;
13358
1.04k
        }
13359
16.5k
        input_position++;
13360
16.5k
        break;
13361
17.6k
      }
13362
5.56k
      case state::NO_SCHEME: {
13363
5.56k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13364
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13365
        // validation error, return failure.
13366
5.56k
        if (base_url == nullptr ||
13367
5.56k
            (base_url->has_opaque_path && !fragment.has_value())) {
13368
5.56k
          ada_log("NO_SCHEME validation error");
13369
5.56k
          url.is_valid = false;
13370
5.56k
          return url;
13371
5.56k
        }
13372
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13373
        // set url's scheme to base's scheme, url's path to base's path, url's
13374
        // query to base's query, and set state to fragment state.
13375
0
        else if (base_url->has_opaque_path && fragment.has_value() &&
13376
0
                 input_position == input_size) {
13377
0
          ada_log("NO_SCHEME opaque base with fragment");
13378
0
          url.copy_scheme(*base_url);
13379
0
          url.has_opaque_path = base_url->has_opaque_path;
13380
13381
          if constexpr (result_type_is_ada_url) {
13382
            url.path = base_url->path;
13383
            url.query = base_url->query;
13384
0
          } else {
13385
0
            url.update_base_pathname(base_url->get_pathname());
13386
0
            url.update_base_search(base_url->get_search());
13387
0
          }
13388
0
          url.update_unencoded_base_hash(*fragment);
13389
0
          return url;
13390
0
        }
13391
        // Otherwise, if base's scheme is not "file", set state to relative
13392
        // state and decrease pointer by 1.
13393
0
        else if (base_url->type != scheme::type::FILE) {
13394
0
          ada_log("NO_SCHEME non-file relative path");
13395
0
          state = state::RELATIVE_SCHEME;
13396
0
        }
13397
        // Otherwise, set state to file state and decrease pointer by 1.
13398
0
        else {
13399
0
          ada_log("NO_SCHEME file base type");
13400
0
          state = state::FILE;
13401
0
        }
13402
0
        break;
13403
5.56k
      }
13404
12.4k
      case state::AUTHORITY: {
13405
12.4k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13406
        // most URLs have no @. Having no @ tells us that we don't have to worry
13407
        // about AUTHORITY. Of course, we could have @ and still not have to
13408
        // worry about AUTHORITY.
13409
        // TODO: Instead of just collecting a bool, collect the location of the
13410
        // '@' and do something useful with it.
13411
        // TODO: We could do various processing early on, using a single pass
13412
        // over the string to collect information about it, e.g., telling us
13413
        // whether there is a @ and if so, where (or how many).
13414
13415
        // Check if url data contains an @.
13416
12.4k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13417
11.7k
          state = state::HOST;
13418
11.7k
          break;
13419
11.7k
        }
13420
728
        bool at_sign_seen{false};
13421
728
        bool password_token_seen{false};
13422
        /**
13423
         * We expect something of the sort...
13424
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13425
         * --------^
13426
         */
13427
7.90k
        do {
13428
7.90k
          std::string_view view = url_data.substr(input_position);
13429
          // The delimiters are @, /, ? \\.
13430
7.90k
          size_t location =
13431
7.90k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13432
7.90k
                               : helpers::find_authority_delimiter(view);
13433
7.90k
          std::string_view authority_view = view.substr(0, location);
13434
7.90k
          size_t end_of_authority = input_position + authority_view.size();
13435
          // If c is U+0040 (@), then:
13436
7.90k
          if ((end_of_authority != input_size) &&
13437
7.26k
              (url_data[end_of_authority] == '@')) {
13438
            // If atSignSeen is true, then prepend "%40" to buffer.
13439
7.17k
            if (at_sign_seen) {
13440
6.48k
              if (password_token_seen) {
13441
                if constexpr (result_type_is_ada_url) {
13442
                  url.password += "%40";
13443
2.52k
                } else {
13444
2.52k
                  url.append_base_password("%40");
13445
2.52k
                }
13446
3.96k
              } else {
13447
                if constexpr (result_type_is_ada_url) {
13448
                  url.username += "%40";
13449
3.96k
                } else {
13450
3.96k
                  url.append_base_username("%40");
13451
3.96k
                }
13452
3.96k
              }
13453
6.48k
            }
13454
13455
7.17k
            at_sign_seen = true;
13456
13457
7.17k
            if (!password_token_seen) {
13458
4.65k
              size_t password_token_location = authority_view.find(':');
13459
4.65k
              password_token_seen =
13460
4.65k
                  password_token_location != std::string_view::npos;
13461
13462
4.65k
              if constexpr (store_values) {
13463
4.65k
                if (!password_token_seen) {
13464
                  if constexpr (result_type_is_ada_url) {
13465
                    url.username += unicode::percent_encode(
13466
                        authority_view,
13467
                        character_sets::USERINFO_PERCENT_ENCODE);
13468
4.35k
                  } else {
13469
4.35k
                    url.append_base_username(unicode::percent_encode(
13470
4.35k
                        authority_view,
13471
4.35k
                        character_sets::USERINFO_PERCENT_ENCODE));
13472
4.35k
                  }
13473
4.35k
                } else {
13474
                  if constexpr (result_type_is_ada_url) {
13475
                    url.username += unicode::percent_encode(
13476
                        authority_view.substr(0, password_token_location),
13477
                        character_sets::USERINFO_PERCENT_ENCODE);
13478
                    url.password += unicode::percent_encode(
13479
                        authority_view.substr(password_token_location + 1),
13480
                        character_sets::USERINFO_PERCENT_ENCODE);
13481
303
                  } else {
13482
303
                    url.append_base_username(unicode::percent_encode(
13483
303
                        authority_view.substr(0, password_token_location),
13484
303
                        character_sets::USERINFO_PERCENT_ENCODE));
13485
303
                    url.append_base_password(unicode::percent_encode(
13486
303
                        authority_view.substr(password_token_location + 1),
13487
303
                        character_sets::USERINFO_PERCENT_ENCODE));
13488
303
                  }
13489
303
                }
13490
4.65k
              }
13491
4.65k
            } else if constexpr (store_values) {
13492
              if constexpr (result_type_is_ada_url) {
13493
                url.password += unicode::percent_encode(
13494
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13495
2.52k
              } else {
13496
2.52k
                url.append_base_password(unicode::percent_encode(
13497
2.52k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13498
2.52k
              }
13499
2.52k
            }
13500
7.17k
          }
13501
          // Otherwise, if one of the following is true:
13502
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13503
          // - url is special and c is U+005C (\)
13504
728
          else if (end_of_authority == input_size ||
13505
93
                   url_data[end_of_authority] == '/' ||
13506
29
                   url_data[end_of_authority] == '?' ||
13507
728
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13508
            // If atSignSeen is true and authority_view is the empty string,
13509
            // validation error, return failure.
13510
728
            if (at_sign_seen && authority_view.empty()) {
13511
108
              url.is_valid = false;
13512
108
              return url;
13513
108
            }
13514
620
            state = state::HOST;
13515
620
            break;
13516
728
          }
13517
7.17k
          if (end_of_authority == input_size) {
13518
0
            if constexpr (store_values) {
13519
0
              if (fragment.has_value()) {
13520
0
                url.update_unencoded_base_hash(*fragment);
13521
0
              }
13522
0
            }
13523
0
            return url;
13524
0
          }
13525
7.17k
          input_position = end_of_authority + 1;
13526
7.17k
        } while (true);
13527
13528
620
        break;
13529
728
      }
13530
620
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
13531
0
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
13532
0
                helpers::substring(url_data, input_position));
13533
13534
        // If c is U+002F (/) and remaining starts with U+002F (/),
13535
        // then set state to special authority ignore slashes state and increase
13536
        // pointer by 1.
13537
0
        if (url_data.substr(input_position, 2) == "//") {
13538
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13539
0
          input_position += 2;
13540
0
        } else {
13541
          // Otherwise, validation error, set state to relative state and
13542
          // decrease pointer by 1.
13543
0
          state = state::RELATIVE_SCHEME;
13544
0
        }
13545
13546
0
        break;
13547
728
      }
13548
1.34k
      case state::PATH_OR_AUTHORITY: {
13549
1.34k
        ada_log("PATH_OR_AUTHORITY ",
13550
1.34k
                helpers::substring(url_data, input_position));
13551
13552
        // If c is U+002F (/), then set state to authority state.
13553
1.34k
        if ((input_position != input_size) &&
13554
1.33k
            (url_data[input_position] == '/')) {
13555
387
          state = state::AUTHORITY;
13556
387
          input_position++;
13557
956
        } else {
13558
          // Otherwise, set state to path state, and decrease pointer by 1.
13559
956
          state = state::PATH;
13560
956
        }
13561
13562
1.34k
        break;
13563
728
      }
13564
0
      case state::RELATIVE_SCHEME: {
13565
0
        ada_log("RELATIVE_SCHEME ",
13566
0
                helpers::substring(url_data, input_position));
13567
13568
        // Set url's scheme to base's scheme.
13569
0
        url.copy_scheme(*base_url);
13570
13571
        // If c is U+002F (/), then set state to relative slash state.
13572
0
        if ((input_position != input_size) &&
13573
            // NOLINTNEXTLINE(bugprone-branch-clone)
13574
0
            (url_data[input_position] == '/')) {
13575
0
          ada_log(
13576
0
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
13577
0
              "slash state");
13578
0
          state = state::RELATIVE_SLASH;
13579
0
        } else if (url.is_special() && (input_position != input_size) &&
13580
0
                   (url_data[input_position] == '\\')) {
13581
          // Otherwise, if url is special and c is U+005C (\), validation error,
13582
          // set state to relative slash state.
13583
0
          ada_log(
13584
0
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
13585
0
              "error, set state to relative slash state");
13586
0
          state = state::RELATIVE_SLASH;
13587
0
        } else {
13588
0
          ada_log("RELATIVE_SCHEME otherwise");
13589
          // Set url's username to base's username, url's password to base's
13590
          // password, url's host to base's host, url's port to base's port,
13591
          // url's path to a clone of base's path, and url's query to base's
13592
          // query.
13593
          if constexpr (result_type_is_ada_url) {
13594
            url.username = base_url->username;
13595
            url.password = base_url->password;
13596
            url.host = base_url->host;
13597
            url.port = base_url->port;
13598
            // cloning the base path includes cloning the has_opaque_path flag
13599
            url.has_opaque_path = base_url->has_opaque_path;
13600
            url.path = base_url->path;
13601
            url.query = base_url->query;
13602
0
          } else {
13603
0
            url.update_base_authority(base_url->get_href(),
13604
0
                                      base_url->get_components());
13605
0
            url.update_host_to_base_host(base_url->get_hostname());
13606
0
            url.update_base_port(base_url->retrieve_base_port());
13607
            // cloning the base path includes cloning the has_opaque_path flag
13608
0
            url.has_opaque_path = base_url->has_opaque_path;
13609
0
            url.update_base_pathname(base_url->get_pathname());
13610
0
            url.update_base_search(base_url->get_search());
13611
0
          }
13612
13613
0
          url.has_opaque_path = base_url->has_opaque_path;
13614
13615
          // If c is U+003F (?), then set url's query to the empty string, and
13616
          // state to query state.
13617
0
          if ((input_position != input_size) &&
13618
0
              (url_data[input_position] == '?')) {
13619
0
            state = state::QUERY;
13620
0
          }
13621
          // Otherwise, if c is not the EOF code point:
13622
0
          else if (input_position != input_size) {
13623
            // Set url's query to null.
13624
0
            url.clear_search();
13625
            if constexpr (result_type_is_ada_url) {
13626
              // Shorten url's path.
13627
              helpers::shorten_path(url.path, url.type);
13628
0
            } else {
13629
0
              std::string_view path = url.get_pathname();
13630
0
              if (helpers::shorten_path(path, url.type)) {
13631
0
                url.update_base_pathname(std::move(std::string(path)));
13632
0
              }
13633
0
            }
13634
            // Set state to path state and decrease pointer by 1.
13635
0
            state = state::PATH;
13636
0
            break;
13637
0
          }
13638
0
        }
13639
0
        input_position++;
13640
0
        break;
13641
0
      }
13642
0
      case state::RELATIVE_SLASH: {
13643
0
        ada_log("RELATIVE_SLASH ",
13644
0
                helpers::substring(url_data, input_position));
13645
13646
        // If url is special and c is U+002F (/) or U+005C (\), then:
13647
0
        if (url.is_special() && (input_position != input_size) &&
13648
0
            (url_data[input_position] == '/' ||
13649
0
             url_data[input_position] == '\\')) {
13650
          // Set state to special authority ignore slashes state.
13651
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13652
0
        }
13653
        // Otherwise, if c is U+002F (/), then set state to authority state.
13654
0
        else if ((input_position != input_size) &&
13655
0
                 (url_data[input_position] == '/')) {
13656
0
          state = state::AUTHORITY;
13657
0
        }
13658
        // Otherwise, set
13659
        // - url's username to base's username,
13660
        // - url's password to base's password,
13661
        // - url's host to base's host,
13662
        // - url's port to base's port,
13663
        // - state to path state, and then, decrease pointer by 1.
13664
0
        else {
13665
          if constexpr (result_type_is_ada_url) {
13666
            url.username = base_url->username;
13667
            url.password = base_url->password;
13668
            url.host = base_url->host;
13669
            url.port = base_url->port;
13670
0
          } else {
13671
0
            url.update_base_authority(base_url->get_href(),
13672
0
                                      base_url->get_components());
13673
0
            url.update_host_to_base_host(base_url->get_hostname());
13674
0
            url.update_base_port(base_url->retrieve_base_port());
13675
0
          }
13676
0
          state = state::PATH;
13677
0
          break;
13678
0
        }
13679
13680
0
        input_position++;
13681
0
        break;
13682
0
      }
13683
12.1k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13684
12.1k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13685
12.1k
                helpers::substring(url_data, input_position));
13686
13687
        // If c is U+002F (/) and remaining starts with U+002F (/),
13688
        // then set state to special authority ignore slashes state and increase
13689
        // pointer by 1.
13690
12.1k
        if (url_data.substr(input_position, 2) == "//") {
13691
9.30k
          input_position += 2;
13692
9.30k
        }
13693
13694
12.1k
        [[fallthrough]];
13695
12.1k
      }
13696
12.1k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13697
12.1k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13698
12.1k
                helpers::substring(url_data, input_position));
13699
13700
        // If c is neither U+002F (/) nor U+005C (\), then set state to
13701
        // authority state and decrease pointer by 1.
13702
12.7k
        while ((input_position != input_size) &&
13703
12.7k
               ((url_data[input_position] == '/') ||
13704
12.2k
                (url_data[input_position] == '\\'))) {
13705
627
          input_position++;
13706
627
        }
13707
12.1k
        state = state::AUTHORITY;
13708
13709
12.1k
        break;
13710
12.1k
      }
13711
318
      case state::QUERY: {
13712
318
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13713
318
        if constexpr (store_values) {
13714
          // Let queryPercentEncodeSet be the special-query percent-encode set
13715
          // if url is special; otherwise the query percent-encode set.
13716
318
          const uint8_t* query_percent_encode_set =
13717
318
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13718
318
                               : character_sets::QUERY_PERCENT_ENCODE;
13719
13720
          // Percent-encode after encoding, with encoding, buffer, and
13721
          // queryPercentEncodeSet, and append the result to url's query.
13722
318
          url.update_base_search(url_data.substr(input_position),
13723
318
                                 query_percent_encode_set);
13724
318
          ada_log("QUERY update_base_search completed ");
13725
318
          if (fragment.has_value()) {
13726
22
            url.update_unencoded_base_hash(*fragment);
13727
22
          }
13728
318
        }
13729
318
        return url;
13730
12.1k
      }
13731
12.3k
      case state::HOST: {
13732
12.3k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13733
13734
12.3k
        std::string_view host_view = url_data.substr(input_position);
13735
12.3k
        auto [location, found_colon] =
13736
12.3k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13737
12.3k
        input_position = (location != std::string_view::npos)
13738
12.3k
                             ? input_position + location
13739
12.3k
                             : input_size;
13740
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13741
        // Note: the 'found_colon' value is true if and only if a colon was
13742
        // encountered while not inside brackets.
13743
12.3k
        if (found_colon) {
13744
          // If buffer is the empty string, validation error, return failure.
13745
          // Let host be the result of host parsing buffer with url is not
13746
          // special.
13747
722
          ada_log("HOST parsing ", host_view);
13748
722
          if (!url.parse_host(host_view)) {
13749
101
            return url;
13750
101
          }
13751
621
          ada_log("HOST parsing results in ", url.get_hostname());
13752
          // Set url's host to host, buffer to the empty string, and state to
13753
          // port state.
13754
621
          state = state::PORT;
13755
621
          input_position++;
13756
621
        }
13757
        // Otherwise, if one of the following is true:
13758
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13759
        // - url is special and c is U+005C (\)
13760
        // The get_host_delimiter_location function either brings us to
13761
        // the colon outside of the bracket, or to one of those characters.
13762
11.6k
        else {
13763
          // If url is special and host_view is the empty string, validation
13764
          // error, return failure.
13765
11.6k
          if (host_view.empty() && url.is_special()) {
13766
11
            url.is_valid = false;
13767
11
            return url;
13768
11
          }
13769
11.6k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
13770
          // Let host be the result of host parsing host_view with url is not
13771
          // special.
13772
11.6k
          if (host_view.empty()) {
13773
41
            url.update_base_hostname("");
13774
11.6k
          } else if (!url.parse_host(host_view)) {
13775
402
            return url;
13776
402
          }
13777
11.2k
          ada_log("HOST parsing results in ", url.get_hostname(),
13778
11.2k
                  " href=", url.get_href());
13779
13780
          // Set url's host to host, and state to path start state.
13781
11.2k
          state = state::PATH_START;
13782
11.2k
        }
13783
13784
11.8k
        break;
13785
12.3k
      }
13786
11.8k
      case state::OPAQUE_PATH: {
13787
1.72k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13788
1.72k
        std::string_view view = url_data.substr(input_position);
13789
        // If c is U+003F (?), then set url's query to the empty string and
13790
        // state to query state.
13791
1.72k
        size_t location = view.find('?');
13792
1.72k
        if (location != std::string_view::npos) {
13793
144
          view.remove_suffix(view.size() - location);
13794
144
          state = state::QUERY;
13795
144
          input_position += location + 1;
13796
1.57k
        } else {
13797
1.57k
          input_position = input_size + 1;
13798
1.57k
        }
13799
1.72k
        url.has_opaque_path = true;
13800
13801
        // This is a really unlikely scenario in real world. We should not seek
13802
        // to optimize it.
13803
1.72k
        if (view.ends_with(' ')) {
13804
66
          std::string modified_view =
13805
66
              std::string(view.substr(0, view.size() - 1)) + "%20";
13806
66
          url.update_base_pathname(unicode::percent_encode(
13807
66
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13808
1.65k
        } else {
13809
1.65k
          url.update_base_pathname(unicode::percent_encode(
13810
1.65k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13811
1.65k
        }
13812
1.72k
        break;
13813
12.3k
      }
13814
621
      case state::PORT: {
13815
621
        ada_log("PORT ", helpers::substring(url_data, input_position));
13816
621
        std::string_view port_view = url_data.substr(input_position);
13817
621
        input_position += url.parse_port(port_view, true);
13818
621
        if (!url.is_valid) {
13819
107
          return url;
13820
107
        }
13821
514
        state = state::PATH_START;
13822
514
        [[fallthrough]];
13823
514
      }
13824
12.2k
      case state::PATH_START: {
13825
12.2k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13826
13827
        // If url is special, then:
13828
12.2k
        if (url.is_special()) {
13829
          // Set state to path state.
13830
11.9k
          state = state::PATH;
13831
13832
          // Optimization: Avoiding going into PATH state improves the
13833
          // performance of urls ending with /.
13834
11.9k
          if (input_position == input_size) {
13835
11.1k
            if constexpr (store_values) {
13836
11.1k
              url.update_base_pathname("/");
13837
11.1k
              if (fragment.has_value()) {
13838
88
                url.update_unencoded_base_hash(*fragment);
13839
88
              }
13840
11.1k
            }
13841
11.1k
            return url;
13842
11.1k
          }
13843
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
13844
          // by 1. We know that (input_position == input_size) is impossible
13845
          // here, because of the previous if-check.
13846
855
          if ((url_data[input_position] != '/') &&
13847
110
              (url_data[input_position] != '\\')) {
13848
94
            break;
13849
94
          }
13850
855
        }
13851
        // Otherwise, if state override is not given and c is U+003F (?),
13852
        // set url's query to the empty string and state to query state.
13853
260
        else if ((input_position != input_size) &&
13854
56
                 (url_data[input_position] == '?')) {
13855
10
          state = state::QUERY;
13856
10
        }
13857
        // Otherwise, if c is not the EOF code point:
13858
250
        else if (input_position != input_size) {
13859
          // Set state to path state.
13860
46
          state = state::PATH;
13861
13862
          // If c is not U+002F (/), then decrease pointer by 1.
13863
46
          if (url_data[input_position] != '/') {
13864
0
            break;
13865
0
          }
13866
46
        }
13867
13868
1.02k
        input_position++;
13869
1.02k
        break;
13870
12.2k
      }
13871
2.70k
      case state::PATH: {
13872
2.70k
        ada_log("PATH ", helpers::substring(url_data, input_position));
13873
2.70k
        std::string_view view = url_data.substr(input_position);
13874
13875
        // Most time, we do not need percent encoding.
13876
        // Furthermore, we can immediately locate the '?'.
13877
2.70k
        size_t locofquestionmark = view.find('?');
13878
2.70k
        if (locofquestionmark != std::string_view::npos) {
13879
164
          state = state::QUERY;
13880
164
          view.remove_suffix(view.size() - locofquestionmark);
13881
164
          input_position += locofquestionmark + 1;
13882
2.54k
        } else {
13883
2.54k
          input_position = input_size + 1;
13884
2.54k
        }
13885
2.70k
        if constexpr (store_values) {
13886
          if constexpr (result_type_is_ada_url) {
13887
            helpers::parse_prepared_path(view, url.type, url.path);
13888
2.70k
          } else {
13889
2.70k
            url.consume_prepared_path(view);
13890
2.70k
            ADA_ASSERT_TRUE(url.validate());
13891
2.70k
          }
13892
2.70k
        }
13893
2.70k
        break;
13894
12.2k
      }
13895
794
      case state::FILE_SLASH: {
13896
794
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13897
13898
        // If c is U+002F (/) or U+005C (\), then:
13899
794
        if ((input_position != input_size) &&
13900
789
            (url_data[input_position] == '/' ||
13901
576
             url_data[input_position] == '\\')) {
13902
576
          ada_log("FILE_SLASH c is U+002F or U+005C");
13903
          // Set state to file host state.
13904
576
          state = state::FILE_HOST;
13905
576
          input_position++;
13906
576
        } else {
13907
218
          ada_log("FILE_SLASH otherwise");
13908
          // If base is non-null and base's scheme is "file", then:
13909
          // Note: it is unsafe to do base_url->scheme unless you know that
13910
          // base_url_has_value() is true.
13911
218
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13912
            // Set url's host to base's host.
13913
            if constexpr (result_type_is_ada_url) {
13914
              url.host = base_url->host;
13915
0
            } else {
13916
0
              url.update_host_to_base_host(base_url->get_host());
13917
0
            }
13918
            // If the code point substring from pointer to the end of input does
13919
            // not start with a Windows drive letter and base's path[0] is a
13920
            // normalized Windows drive letter, then append base's path[0] to
13921
            // url's path.
13922
0
            if (!base_url->get_pathname().empty()) {
13923
0
              if (!checkers::is_windows_drive_letter(
13924
0
                      url_data.substr(input_position))) {
13925
0
                std::string_view first_base_url_path =
13926
0
                    base_url->get_pathname().substr(1);
13927
0
                size_t loc = first_base_url_path.find('/');
13928
0
                if (loc != std::string_view::npos) {
13929
0
                  helpers::resize(first_base_url_path, loc);
13930
0
                }
13931
0
                if (checkers::is_normalized_windows_drive_letter(
13932
0
                        first_base_url_path)) {
13933
                  if constexpr (result_type_is_ada_url) {
13934
                    url.path += '/';
13935
                    url.path += first_base_url_path;
13936
0
                  } else {
13937
0
                    url.append_base_pathname(
13938
0
                        helpers::concat("/", first_base_url_path));
13939
0
                  }
13940
0
                }
13941
0
              }
13942
0
            }
13943
0
          }
13944
13945
          // Set state to path state, and decrease pointer by 1.
13946
218
          state = state::PATH;
13947
218
        }
13948
13949
794
        break;
13950
12.2k
      }
13951
576
      case state::FILE_HOST: {
13952
576
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13953
576
        std::string_view view = url_data.substr(input_position);
13954
13955
576
        size_t location = view.find_first_of("/\\?");
13956
576
        std::string_view file_host_buffer(
13957
576
            view.data(),
13958
576
            (location != std::string_view::npos) ? location : view.size());
13959
13960
576
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13961
5
          state = state::PATH;
13962
571
        } else if (file_host_buffer.empty()) {
13963
          // Set url's host to the empty string.
13964
          if constexpr (result_type_is_ada_url) {
13965
            url.host = "";
13966
25
          } else {
13967
25
            url.update_base_hostname("");
13968
25
          }
13969
          // Set state to path start state.
13970
25
          state = state::PATH_START;
13971
546
        } else {
13972
546
          size_t consumed_bytes = file_host_buffer.size();
13973
546
          input_position += consumed_bytes;
13974
          // Let host be the result of host parsing buffer with url is not
13975
          // special.
13976
546
          if (!url.parse_host(file_host_buffer)) {
13977
120
            return url;
13978
120
          }
13979
13980
          if constexpr (result_type_is_ada_url) {
13981
            // If host is "localhost", then set host to the empty string.
13982
            if (url.host.has_value() && url.host.value() == "localhost") {
13983
              url.host = "";
13984
            }
13985
426
          } else {
13986
426
            if (url.get_hostname() == "localhost") {
13987
3
              url.update_base_hostname("");
13988
3
            }
13989
426
          }
13990
13991
          // Set buffer to the empty string and state to path start state.
13992
426
          state = state::PATH_START;
13993
426
        }
13994
13995
456
        break;
13996
576
      }
13997
1.41k
      case state::FILE: {
13998
1.41k
        ada_log("FILE ", helpers::substring(url_data, input_position));
13999
1.41k
        std::string_view file_view = url_data.substr(input_position);
14000
14001
1.41k
        url.set_protocol_as_file();
14002
        if constexpr (result_type_is_ada_url) {
14003
          // Set url's host to the empty string.
14004
          url.host = "";
14005
1.41k
        } else {
14006
1.41k
          url.update_base_hostname("");
14007
1.41k
        }
14008
        // If c is U+002F (/) or U+005C (\), then:
14009
1.41k
        if (input_position != input_size &&
14010
1.40k
            (url_data[input_position] == '/' ||
14011
794
             url_data[input_position] == '\\')) {
14012
794
          ada_log("FILE c is U+002F or U+005C");
14013
          // Set state to file slash state.
14014
794
          state = state::FILE_SLASH;
14015
794
        }
14016
        // Otherwise, if base is non-null and base's scheme is "file":
14017
624
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
14018
          // Set url's host to base's host, url's path to a clone of base's
14019
          // path, and url's query to base's query.
14020
0
          ada_log("FILE base non-null");
14021
          if constexpr (result_type_is_ada_url) {
14022
            url.host = base_url->host;
14023
            url.path = base_url->path;
14024
            url.query = base_url->query;
14025
0
          } else {
14026
0
            url.update_host_to_base_host(base_url->get_hostname());
14027
0
            url.update_base_pathname(base_url->get_pathname());
14028
0
            url.update_base_search(base_url->get_search());
14029
0
          }
14030
0
          url.has_opaque_path = base_url->has_opaque_path;
14031
14032
          // If c is U+003F (?), then set url's query to the empty string and
14033
          // state to query state.
14034
0
          if (input_position != input_size && url_data[input_position] == '?') {
14035
0
            state = state::QUERY;
14036
0
          }
14037
          // Otherwise, if c is not the EOF code point:
14038
0
          else if (input_position != input_size) {
14039
            // Set url's query to null.
14040
0
            url.clear_search();
14041
            // If the code point substring from pointer to the end of input does
14042
            // not start with a Windows drive letter, then shorten url's path.
14043
0
            if (!checkers::is_windows_drive_letter(file_view)) {
14044
              if constexpr (result_type_is_ada_url) {
14045
                helpers::shorten_path(url.path, url.type);
14046
0
              } else {
14047
0
                std::string_view path = url.get_pathname();
14048
0
                if (helpers::shorten_path(path, url.type)) {
14049
0
                  url.update_base_pathname(std::move(std::string(path)));
14050
0
                }
14051
0
              }
14052
0
            }
14053
            // Otherwise:
14054
0
            else {
14055
              // Set url's path to an empty list.
14056
0
              url.clear_pathname();
14057
0
              url.has_opaque_path = true;
14058
0
            }
14059
14060
            // Set state to path state and decrease pointer by 1.
14061
0
            state = state::PATH;
14062
0
            break;
14063
0
          }
14064
0
        }
14065
        // Otherwise, set state to path state, and decrease pointer by 1.
14066
624
        else {
14067
624
          ada_log("FILE go to path");
14068
624
          state = state::PATH;
14069
624
          break;
14070
624
        }
14071
14072
794
        input_position++;
14073
794
        break;
14074
1.41k
      }
14075
0
      default:
14076
0
        unreachable();
14077
103k
    }
14078
103k
  }
14079
4.32k
  if constexpr (store_values) {
14080
4.32k
    if (fragment.has_value()) {
14081
162
      url.update_unencoded_base_hash(*fragment);
14082
162
    }
14083
4.32k
  }
14084
4.32k
  return url;
14085
22.1k
}
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*)
14086
14087
template url parse_url_impl(std::string_view user_input,
14088
                            const url* base_url = nullptr);
14089
template url_aggregator parse_url_impl(
14090
    std::string_view user_input, const url_aggregator* base_url = nullptr);
14091
14092
template <class result_type>
14093
result_type parse_url(std::string_view user_input,
14094
0
                      const result_type* base_url) {
14095
0
  return parse_url_impl<result_type, true>(user_input, base_url);
14096
0
}
Unexecuted instantiation: ada::url ada::parser::parse_url<ada::url>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url const*)
Unexecuted instantiation: ada::url_aggregator ada::parser::parse_url<ada::url_aggregator>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator const*)
14097
14098
template url parse_url<url>(std::string_view user_input,
14099
                            const url* base_url = nullptr);
14100
template url_aggregator parse_url<url_aggregator>(
14101
    std::string_view user_input, const url_aggregator* base_url = nullptr);
14102
}  // namespace ada::parser
14103
/* end file src/parser.cpp */
14104
/* begin file src/url_components.cpp */
14105
14106
#include <iterator>
14107
#include <string>
14108
14109
namespace ada {
14110
14111
0
[[nodiscard]] std::string url_components::to_string() const {
14112
0
  std::string answer;
14113
0
  auto back = std::back_insert_iterator(answer);
14114
0
  answer.append("{\n");
14115
14116
0
  answer.append("\t\"protocol_end\":\"");
14117
0
  helpers::encode_json(std::to_string(protocol_end), back);
14118
0
  answer.append("\",\n");
14119
14120
0
  answer.append("\t\"username_end\":\"");
14121
0
  helpers::encode_json(std::to_string(username_end), back);
14122
0
  answer.append("\",\n");
14123
14124
0
  answer.append("\t\"host_start\":\"");
14125
0
  helpers::encode_json(std::to_string(host_start), back);
14126
0
  answer.append("\",\n");
14127
14128
0
  answer.append("\t\"host_end\":\"");
14129
0
  helpers::encode_json(std::to_string(host_end), back);
14130
0
  answer.append("\",\n");
14131
14132
0
  answer.append("\t\"port\":\"");
14133
0
  helpers::encode_json(std::to_string(port), back);
14134
0
  answer.append("\",\n");
14135
14136
0
  answer.append("\t\"pathname_start\":\"");
14137
0
  helpers::encode_json(std::to_string(pathname_start), back);
14138
0
  answer.append("\",\n");
14139
14140
0
  answer.append("\t\"search_start\":\"");
14141
0
  helpers::encode_json(std::to_string(search_start), back);
14142
0
  answer.append("\",\n");
14143
14144
0
  answer.append("\t\"hash_start\":\"");
14145
0
  helpers::encode_json(std::to_string(hash_start), back);
14146
0
  answer.append("\",\n");
14147
14148
0
  answer.append("\n}");
14149
0
  return answer;
14150
0
}
14151
14152
}  // namespace ada
14153
/* end file src/url_components.cpp */
14154
/* begin file src/url_aggregator.cpp */
14155
14156
#include <iterator>
14157
#include <ranges>
14158
#include <string>
14159
#include <string_view>
14160
14161
namespace ada {
14162
template <bool has_state_override>
14163
[[nodiscard]] ada_really_inline bool url_aggregator::parse_scheme_with_colon(
14164
20.6k
    const std::string_view input_with_colon) {
14165
20.6k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14166
20.6k
  ADA_ASSERT_TRUE(validate());
14167
20.6k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14168
20.6k
  std::string_view input{input_with_colon};
14169
20.6k
  input.remove_suffix(1);
14170
20.6k
  auto parsed_type = ada::scheme::get_scheme_type(input);
14171
20.6k
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
14172
  /**
14173
   * In the common case, we will immediately recognize a special scheme (e.g.,
14174
   *http, https), in which case, we can go really fast.
14175
   **/
14176
20.6k
  if (is_input_special) {  // fast path!!!
14177
13.9k
    if constexpr (has_state_override) {
14178
      // If url's scheme is not a special scheme and buffer is a special scheme,
14179
      // then return.
14180
1.61k
      if (is_special() != is_input_special) {
14181
0
        return false;
14182
0
      }
14183
14184
      // If url includes credentials or has a non-null port, and buffer is
14185
      // "file", then return.
14186
1.61k
      if ((has_credentials() || components.port != url_components::omitted) &&
14187
0
          parsed_type == ada::scheme::type::FILE) {
14188
0
        return false;
14189
0
      }
14190
14191
      // If url's scheme is "file" and its host is an empty host, then return.
14192
      // An empty host is the empty string.
14193
1.61k
      if (type == ada::scheme::type::FILE &&
14194
0
          components.host_start == components.host_end) {
14195
0
        return false;
14196
0
      }
14197
1.61k
    }
14198
14199
1.61k
    type = parsed_type;
14200
13.9k
    set_scheme_from_view_with_colon(input_with_colon);
14201
14202
13.9k
    if constexpr (has_state_override) {
14203
      // This is uncommon.
14204
1.61k
      uint16_t urls_scheme_port = get_special_port();
14205
14206
      // If url's port is url's scheme's default port, then set url's port to
14207
      // null.
14208
1.61k
      if (components.port == urls_scheme_port) {
14209
0
        clear_port();
14210
0
      }
14211
1.61k
    }
14212
13.9k
  } else {  // slow path
14213
6.72k
    std::string _buffer(input);
14214
    // Next function is only valid if the input is ASCII and returns false
14215
    // otherwise, but it seems that we always have ascii content so we do not
14216
    // need to check the return value.
14217
6.72k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14218
14219
6.72k
    if constexpr (has_state_override) {
14220
      // If url's scheme is a special scheme and buffer is not a special scheme,
14221
      // then return. If url's scheme is not a special scheme and buffer is a
14222
      // special scheme, then return.
14223
2.47k
      if (is_special() != ada::scheme::is_special(_buffer)) {
14224
1.84k
        return true;
14225
1.84k
      }
14226
14227
      // If url includes credentials or has a non-null port, and buffer is
14228
      // "file", then return.
14229
639
      if ((has_credentials() || components.port != url_components::omitted) &&
14230
0
          _buffer == "file") {
14231
0
        return true;
14232
0
      }
14233
14234
      // If url's scheme is "file" and its host is an empty host, then return.
14235
      // An empty host is the empty string.
14236
639
      if (type == ada::scheme::type::FILE &&
14237
0
          components.host_start == components.host_end) {
14238
0
        return true;
14239
0
      }
14240
639
    }
14241
14242
639
    set_scheme(_buffer);
14243
14244
6.72k
    if constexpr (has_state_override) {
14245
      // This is uncommon.
14246
2.47k
      uint16_t urls_scheme_port = get_special_port();
14247
14248
      // If url's port is url's scheme's default port, then set url's port to
14249
      // null.
14250
2.47k
      if (components.port == urls_scheme_port) {
14251
0
        clear_port();
14252
0
      }
14253
2.47k
    }
14254
6.72k
  }
14255
0
  ADA_ASSERT_TRUE(validate());
14256
20.6k
  return true;
14257
20.6k
}
bool ada::url_aggregator::parse_scheme_with_colon<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14164
16.5k
    const std::string_view input_with_colon) {
14165
16.5k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14166
16.5k
  ADA_ASSERT_TRUE(validate());
14167
16.5k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14168
16.5k
  std::string_view input{input_with_colon};
14169
16.5k
  input.remove_suffix(1);
14170
16.5k
  auto parsed_type = ada::scheme::get_scheme_type(input);
14171
16.5k
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
14172
  /**
14173
   * In the common case, we will immediately recognize a special scheme (e.g.,
14174
   *http, https), in which case, we can go really fast.
14175
   **/
14176
16.5k
  if (is_input_special) {  // fast path!!!
14177
    if constexpr (has_state_override) {
14178
      // If url's scheme is not a special scheme and buffer is a special scheme,
14179
      // then return.
14180
      if (is_special() != is_input_special) {
14181
        return false;
14182
      }
14183
14184
      // If url includes credentials or has a non-null port, and buffer is
14185
      // "file", then return.
14186
      if ((has_credentials() || components.port != url_components::omitted) &&
14187
          parsed_type == ada::scheme::type::FILE) {
14188
        return false;
14189
      }
14190
14191
      // If url's scheme is "file" and its host is an empty host, then return.
14192
      // An empty host is the empty string.
14193
      if (type == ada::scheme::type::FILE &&
14194
          components.host_start == components.host_end) {
14195
        return false;
14196
      }
14197
    }
14198
14199
12.3k
    type = parsed_type;
14200
12.3k
    set_scheme_from_view_with_colon(input_with_colon);
14201
14202
    if constexpr (has_state_override) {
14203
      // This is uncommon.
14204
      uint16_t urls_scheme_port = get_special_port();
14205
14206
      // If url's port is url's scheme's default port, then set url's port to
14207
      // null.
14208
      if (components.port == urls_scheme_port) {
14209
        clear_port();
14210
      }
14211
    }
14212
12.3k
  } else {  // slow path
14213
4.24k
    std::string _buffer(input);
14214
    // Next function is only valid if the input is ASCII and returns false
14215
    // otherwise, but it seems that we always have ascii content so we do not
14216
    // need to check the return value.
14217
4.24k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14218
14219
    if constexpr (has_state_override) {
14220
      // If url's scheme is a special scheme and buffer is not a special scheme,
14221
      // then return. If url's scheme is not a special scheme and buffer is a
14222
      // special scheme, then return.
14223
      if (is_special() != ada::scheme::is_special(_buffer)) {
14224
        return true;
14225
      }
14226
14227
      // If url includes credentials or has a non-null port, and buffer is
14228
      // "file", then return.
14229
      if ((has_credentials() || components.port != url_components::omitted) &&
14230
          _buffer == "file") {
14231
        return true;
14232
      }
14233
14234
      // If url's scheme is "file" and its host is an empty host, then return.
14235
      // An empty host is the empty string.
14236
      if (type == ada::scheme::type::FILE &&
14237
          components.host_start == components.host_end) {
14238
        return true;
14239
      }
14240
    }
14241
14242
4.24k
    set_scheme(_buffer);
14243
14244
    if constexpr (has_state_override) {
14245
      // This is uncommon.
14246
      uint16_t urls_scheme_port = get_special_port();
14247
14248
      // If url's port is url's scheme's default port, then set url's port to
14249
      // null.
14250
      if (components.port == urls_scheme_port) {
14251
        clear_port();
14252
      }
14253
    }
14254
4.24k
  }
14255
16.5k
  ADA_ASSERT_TRUE(validate());
14256
16.5k
  return true;
14257
16.5k
}
bool ada::url_aggregator::parse_scheme_with_colon<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14164
4.09k
    const std::string_view input_with_colon) {
14165
4.09k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14166
4.09k
  ADA_ASSERT_TRUE(validate());
14167
4.09k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14168
4.09k
  std::string_view input{input_with_colon};
14169
4.09k
  input.remove_suffix(1);
14170
4.09k
  auto parsed_type = ada::scheme::get_scheme_type(input);
14171
4.09k
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
14172
  /**
14173
   * In the common case, we will immediately recognize a special scheme (e.g.,
14174
   *http, https), in which case, we can go really fast.
14175
   **/
14176
4.09k
  if (is_input_special) {  // fast path!!!
14177
1.61k
    if constexpr (has_state_override) {
14178
      // If url's scheme is not a special scheme and buffer is a special scheme,
14179
      // then return.
14180
1.61k
      if (is_special() != is_input_special) {
14181
0
        return false;
14182
0
      }
14183
14184
      // If url includes credentials or has a non-null port, and buffer is
14185
      // "file", then return.
14186
1.61k
      if ((has_credentials() || components.port != url_components::omitted) &&
14187
0
          parsed_type == ada::scheme::type::FILE) {
14188
0
        return false;
14189
0
      }
14190
14191
      // If url's scheme is "file" and its host is an empty host, then return.
14192
      // An empty host is the empty string.
14193
1.61k
      if (type == ada::scheme::type::FILE &&
14194
0
          components.host_start == components.host_end) {
14195
0
        return false;
14196
0
      }
14197
1.61k
    }
14198
14199
1.61k
    type = parsed_type;
14200
1.61k
    set_scheme_from_view_with_colon(input_with_colon);
14201
14202
1.61k
    if constexpr (has_state_override) {
14203
      // This is uncommon.
14204
1.61k
      uint16_t urls_scheme_port = get_special_port();
14205
14206
      // If url's port is url's scheme's default port, then set url's port to
14207
      // null.
14208
1.61k
      if (components.port == urls_scheme_port) {
14209
0
        clear_port();
14210
0
      }
14211
1.61k
    }
14212
2.47k
  } else {  // slow path
14213
2.47k
    std::string _buffer(input);
14214
    // Next function is only valid if the input is ASCII and returns false
14215
    // otherwise, but it seems that we always have ascii content so we do not
14216
    // need to check the return value.
14217
2.47k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14218
14219
2.47k
    if constexpr (has_state_override) {
14220
      // If url's scheme is a special scheme and buffer is not a special scheme,
14221
      // then return. If url's scheme is not a special scheme and buffer is a
14222
      // special scheme, then return.
14223
2.47k
      if (is_special() != ada::scheme::is_special(_buffer)) {
14224
1.84k
        return true;
14225
1.84k
      }
14226
14227
      // If url includes credentials or has a non-null port, and buffer is
14228
      // "file", then return.
14229
639
      if ((has_credentials() || components.port != url_components::omitted) &&
14230
0
          _buffer == "file") {
14231
0
        return true;
14232
0
      }
14233
14234
      // If url's scheme is "file" and its host is an empty host, then return.
14235
      // An empty host is the empty string.
14236
639
      if (type == ada::scheme::type::FILE &&
14237
0
          components.host_start == components.host_end) {
14238
0
        return true;
14239
0
      }
14240
639
    }
14241
14242
639
    set_scheme(_buffer);
14243
14244
2.47k
    if constexpr (has_state_override) {
14245
      // This is uncommon.
14246
2.47k
      uint16_t urls_scheme_port = get_special_port();
14247
14248
      // If url's port is url's scheme's default port, then set url's port to
14249
      // null.
14250
2.47k
      if (components.port == urls_scheme_port) {
14251
0
        clear_port();
14252
0
      }
14253
2.47k
    }
14254
2.47k
  }
14255
0
  ADA_ASSERT_TRUE(validate());
14256
4.09k
  return true;
14257
4.09k
}
14258
14259
0
inline void url_aggregator::copy_scheme(const url_aggregator& u) noexcept {
14260
0
  ada_log("url_aggregator::copy_scheme ", u.buffer);
14261
0
  ADA_ASSERT_TRUE(validate());
14262
  // next line could overflow but unsigned arithmetic has well-defined
14263
  // overflows.
14264
0
  uint32_t new_difference = u.components.protocol_end - components.protocol_end;
14265
0
  type = u.type;
14266
0
  buffer.erase(0, components.protocol_end);
14267
0
  buffer.insert(0, u.get_protocol());
14268
0
  components.protocol_end = u.components.protocol_end;
14269
14270
  // No need to update the components
14271
0
  if (new_difference == 0) {
14272
0
    return;
14273
0
  }
14274
14275
  // Update the rest of the components.
14276
0
  components.username_end += new_difference;
14277
0
  components.host_start += new_difference;
14278
0
  components.host_end += new_difference;
14279
0
  components.pathname_start += new_difference;
14280
0
  if (components.search_start != url_components::omitted) {
14281
0
    components.search_start += new_difference;
14282
0
  }
14283
0
  if (components.hash_start != url_components::omitted) {
14284
0
    components.hash_start += new_difference;
14285
0
  }
14286
0
  ADA_ASSERT_TRUE(validate());
14287
0
}
14288
14289
inline void url_aggregator::set_scheme_from_view_with_colon(
14290
13.9k
    std::string_view new_scheme_with_colon) noexcept {
14291
13.9k
  ada_log("url_aggregator::set_scheme_from_view_with_colon ",
14292
13.9k
          new_scheme_with_colon);
14293
13.9k
  ADA_ASSERT_TRUE(validate());
14294
13.9k
  ADA_ASSERT_TRUE(!new_scheme_with_colon.empty() &&
14295
13.9k
                  new_scheme_with_colon.back() == ':');
14296
  // next line could overflow but unsigned arithmetic has well-defined
14297
  // overflows.
14298
13.9k
  uint32_t new_difference =
14299
13.9k
      uint32_t(new_scheme_with_colon.size()) - components.protocol_end;
14300
14301
13.9k
  if (buffer.empty()) {
14302
12.3k
    buffer.append(new_scheme_with_colon);
14303
12.3k
  } else {
14304
1.61k
    buffer.erase(0, components.protocol_end);
14305
1.61k
    buffer.insert(0, new_scheme_with_colon);
14306
1.61k
  }
14307
13.9k
  components.protocol_end += new_difference;
14308
14309
  // Update the rest of the components.
14310
13.9k
  components.username_end += new_difference;
14311
13.9k
  components.host_start += new_difference;
14312
13.9k
  components.host_end += new_difference;
14313
13.9k
  components.pathname_start += new_difference;
14314
13.9k
  if (components.search_start != url_components::omitted) {
14315
0
    components.search_start += new_difference;
14316
0
  }
14317
13.9k
  if (components.hash_start != url_components::omitted) {
14318
0
    components.hash_start += new_difference;
14319
0
  }
14320
13.9k
  ADA_ASSERT_TRUE(validate());
14321
13.9k
}
14322
14323
4.88k
inline void url_aggregator::set_scheme(std::string_view new_scheme) noexcept {
14324
4.88k
  ada_log("url_aggregator::set_scheme ", new_scheme);
14325
4.88k
  ADA_ASSERT_TRUE(validate());
14326
4.88k
  ADA_ASSERT_TRUE(new_scheme.empty() || new_scheme.back() != ':');
14327
  // next line could overflow but unsigned arithmetic has well-defined
14328
  // overflows.
14329
4.88k
  uint32_t new_difference =
14330
4.88k
      uint32_t(new_scheme.size()) - components.protocol_end + 1;
14331
14332
4.88k
  type = ada::scheme::get_scheme_type(new_scheme);
14333
4.88k
  if (buffer.empty()) {
14334
4.24k
    buffer.append(helpers::concat(new_scheme, ":"));
14335
4.24k
  } else {
14336
639
    buffer.erase(0, components.protocol_end);
14337
639
    buffer.insert(0, helpers::concat(new_scheme, ":"));
14338
639
  }
14339
4.88k
  components.protocol_end = uint32_t(new_scheme.size() + 1);
14340
14341
  // Update the rest of the components.
14342
4.88k
  components.username_end += new_difference;
14343
4.88k
  components.host_start += new_difference;
14344
4.88k
  components.host_end += new_difference;
14345
4.88k
  components.pathname_start += new_difference;
14346
4.88k
  if (components.search_start != url_components::omitted) {
14347
0
    components.search_start += new_difference;
14348
0
  }
14349
4.88k
  if (components.hash_start != url_components::omitted) {
14350
0
    components.hash_start += new_difference;
14351
0
  }
14352
4.88k
  ADA_ASSERT_TRUE(validate());
14353
4.88k
}
14354
14355
9.27k
bool url_aggregator::set_protocol(const std::string_view input) {
14356
9.27k
  ada_log("url_aggregator::set_protocol ", input);
14357
9.27k
  ADA_ASSERT_TRUE(validate());
14358
9.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14359
9.27k
  std::string view(input);
14360
9.27k
  helpers::remove_ascii_tab_or_newline(view);
14361
9.27k
  if (view.empty()) {
14362
35
    return true;
14363
35
  }
14364
14365
  // Schemes should start with alpha values.
14366
9.23k
  if (!checkers::is_alpha(view[0])) {
14367
4.51k
    return false;
14368
4.51k
  }
14369
14370
4.72k
  view.append(":");
14371
14372
4.72k
  std::string::iterator pointer =
14373
4.72k
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
14374
14375
4.72k
  if (pointer != view.end() && *pointer == ':') {
14376
4.09k
    return parse_scheme_with_colon<true>(
14377
4.09k
        view.substr(0, pointer - view.begin() + 1));
14378
4.09k
  }
14379
631
  return false;
14380
4.72k
}
14381
14382
9.27k
bool url_aggregator::set_username(const std::string_view input) {
14383
9.27k
  ada_log("url_aggregator::set_username '", input, "' ");
14384
9.27k
  ADA_ASSERT_TRUE(validate());
14385
9.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14386
9.27k
  if (cannot_have_credentials_or_port()) {
14387
709
    return false;
14388
709
  }
14389
8.56k
  size_t idx = ada::unicode::percent_encode_index(
14390
8.56k
      input, character_sets::USERINFO_PERCENT_ENCODE);
14391
8.56k
  if (idx == input.size()) {
14392
1.09k
    update_base_username(input);
14393
7.46k
  } else {
14394
    // We only create a temporary string if we have to!
14395
7.46k
    update_base_username(ada::unicode::percent_encode(
14396
7.46k
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14397
7.46k
  }
14398
8.56k
  ADA_ASSERT_TRUE(validate());
14399
8.56k
  return true;
14400
9.27k
}
14401
14402
9.27k
bool url_aggregator::set_password(const std::string_view input) {
14403
9.27k
  ada_log("url_aggregator::set_password '", input, "'");
14404
9.27k
  ADA_ASSERT_TRUE(validate());
14405
9.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14406
9.27k
  if (cannot_have_credentials_or_port()) {
14407
709
    return false;
14408
709
  }
14409
8.56k
  size_t idx = ada::unicode::percent_encode_index(
14410
8.56k
      input, character_sets::USERINFO_PERCENT_ENCODE);
14411
8.56k
  if (idx == input.size()) {
14412
1.09k
    update_base_password(input);
14413
7.46k
  } else {
14414
    // We only create a temporary string if we have to!
14415
7.46k
    update_base_password(ada::unicode::percent_encode(
14416
7.46k
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14417
7.46k
  }
14418
8.56k
  ADA_ASSERT_TRUE(validate());
14419
8.56k
  return true;
14420
9.27k
}
14421
14422
12.2k
bool url_aggregator::set_port(const std::string_view input) {
14423
12.2k
  ada_log("url_aggregator::set_port ", input);
14424
12.2k
  ADA_ASSERT_TRUE(validate());
14425
12.2k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14426
12.2k
  if (cannot_have_credentials_or_port()) {
14427
709
    return false;
14428
709
  }
14429
14430
11.4k
  if (input.empty()) {
14431
8
    clear_port();
14432
8
    return true;
14433
8
  }
14434
14435
11.4k
  std::string trimmed(input);
14436
11.4k
  helpers::remove_ascii_tab_or_newline(trimmed);
14437
14438
11.4k
  if (trimmed.empty()) {
14439
27
    return true;
14440
27
  }
14441
14442
  // Input should not start with a non-digit character.
14443
11.4k
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
14444
9.99k
    return false;
14445
9.99k
  }
14446
14447
  // Find the first non-digit character to determine the length of digits
14448
1.47k
  auto first_non_digit =
14449
1.47k
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
14450
1.47k
  std::string_view digits_to_parse =
14451
1.47k
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
14452
14453
  // Revert changes if parse_port fails.
14454
1.47k
  uint32_t previous_port = components.port;
14455
1.47k
  parse_port(digits_to_parse);
14456
1.47k
  if (is_valid) {
14457
979
    return true;
14458
979
  }
14459
494
  update_base_port(previous_port);
14460
494
  is_valid = true;
14461
494
  ADA_ASSERT_TRUE(validate());
14462
494
  return false;
14463
1.47k
}
14464
14465
9.27k
bool url_aggregator::set_pathname(const std::string_view input) {
14466
9.27k
  ada_log("url_aggregator::set_pathname ", input);
14467
9.27k
  ADA_ASSERT_TRUE(validate());
14468
9.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14469
9.27k
  if (has_opaque_path) {
14470
0
    return false;
14471
0
  }
14472
9.27k
  clear_pathname();
14473
9.27k
  parse_path(input);
14474
9.27k
  if (get_pathname().starts_with("//") && !has_authority() && !has_dash_dot()) {
14475
0
    buffer.insert(components.pathname_start, "/.");
14476
0
    components.pathname_start += 2;
14477
0
  }
14478
9.27k
  ADA_ASSERT_TRUE(validate());
14479
9.27k
  return true;
14480
9.27k
}
14481
14482
9.27k
ada_really_inline void url_aggregator::parse_path(std::string_view input) {
14483
9.27k
  ada_log("url_aggregator::parse_path ", input);
14484
9.27k
  ADA_ASSERT_TRUE(validate());
14485
9.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14486
9.27k
  std::string tmp_buffer;
14487
9.27k
  std::string_view internal_input;
14488
9.27k
  if (unicode::has_tabs_or_newline(input)) {
14489
143
    tmp_buffer = input;
14490
    // Optimization opportunity: Instead of copying and then pruning, we could
14491
    // just directly build the string from user_input.
14492
143
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
14493
143
    internal_input = tmp_buffer;
14494
9.13k
  } else {
14495
9.13k
    internal_input = input;
14496
9.13k
  }
14497
14498
  // If url is special, then:
14499
9.27k
  if (is_special()) {
14500
9.27k
    if (internal_input.empty()) {
14501
35
      update_base_pathname("/");
14502
9.23k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
14503
732
      consume_prepared_path(internal_input.substr(1));
14504
8.50k
    } else {
14505
8.50k
      consume_prepared_path(internal_input);
14506
8.50k
    }
14507
9.27k
  } else if (!internal_input.empty()) {
14508
0
    if (internal_input[0] == '/') {
14509
0
      consume_prepared_path(internal_input.substr(1));
14510
0
    } else {
14511
0
      consume_prepared_path(internal_input);
14512
0
    }
14513
0
  } else {
14514
    // Non-special URLs with an empty host can have their paths erased
14515
    // Path-only URLs cannot have their paths erased
14516
0
    if (components.host_start == components.host_end && !has_authority()) {
14517
0
      update_base_pathname("/");
14518
0
    }
14519
0
  }
14520
9.27k
  ADA_ASSERT_TRUE(validate());
14521
9.27k
}
14522
14523
9.27k
void url_aggregator::set_search(const std::string_view input) {
14524
9.27k
  ada_log("url_aggregator::set_search ", input);
14525
9.27k
  ADA_ASSERT_TRUE(validate());
14526
9.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14527
9.27k
  if (input.empty()) {
14528
8
    clear_search();
14529
8
    helpers::strip_trailing_spaces_from_opaque_path(*this);
14530
8
    return;
14531
8
  }
14532
14533
9.26k
  std::string new_value;
14534
9.26k
  new_value = input[0] == '?' ? input.substr(1) : input;
14535
9.26k
  helpers::remove_ascii_tab_or_newline(new_value);
14536
14537
9.26k
  auto query_percent_encode_set =
14538
9.26k
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
14539
9.26k
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
14540
14541
9.26k
  update_base_search(new_value, query_percent_encode_set);
14542
9.26k
  ADA_ASSERT_TRUE(validate());
14543
9.26k
}
14544
14545
9.27k
void url_aggregator::set_hash(const std::string_view input) {
14546
9.27k
  ada_log("url_aggregator::set_hash ", input);
14547
9.27k
  ADA_ASSERT_TRUE(validate());
14548
9.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14549
9.27k
  if (input.empty()) {
14550
8
    if (components.hash_start != url_components::omitted) {
14551
0
      buffer.resize(components.hash_start);
14552
0
      components.hash_start = url_components::omitted;
14553
0
    }
14554
8
    helpers::strip_trailing_spaces_from_opaque_path(*this);
14555
8
    return;
14556
8
  }
14557
14558
9.26k
  std::string new_value;
14559
9.26k
  new_value = input[0] == '#' ? input.substr(1) : input;
14560
9.26k
  helpers::remove_ascii_tab_or_newline(new_value);
14561
9.26k
  update_unencoded_base_hash(new_value);
14562
9.26k
  ADA_ASSERT_TRUE(validate());
14563
9.26k
}
14564
14565
3.11k
bool url_aggregator::set_href(const std::string_view input) {
14566
3.11k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14567
3.11k
  ada_log("url_aggregator::set_href ", input, " [", input.size(), " bytes]");
14568
3.11k
  ada::result<url_aggregator> out = ada::parse<url_aggregator>(input);
14569
3.11k
  ada_log("url_aggregator::set_href, success :", out.has_value());
14570
14571
3.11k
  if (out) {
14572
3.11k
    ada_log("url_aggregator::set_href, parsed ", out->to_string());
14573
    // TODO: Figure out why the following line puts test to never finish.
14574
3.11k
    *this = *out;
14575
3.11k
  }
14576
14577
3.11k
  return out.has_value();
14578
3.11k
}
14579
14580
26.0k
ada_really_inline bool url_aggregator::parse_host(std::string_view input) {
14581
26.0k
  ada_log("url_aggregator:parse_host \"", input, "\" [", input.size(),
14582
26.0k
          " bytes]");
14583
26.0k
  ADA_ASSERT_TRUE(validate());
14584
26.0k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14585
26.0k
  if (input.empty()) {
14586
9
    return is_valid = false;
14587
9
  }  // technically unnecessary.
14588
  // If input starts with U+005B ([), then:
14589
25.9k
  if (input[0] == '[') {
14590
    // If input does not end with U+005D (]), validation error, return failure.
14591
706
    if (input.back() != ']') {
14592
270
      return is_valid = false;
14593
270
    }
14594
436
    ada_log("parse_host ipv6");
14595
14596
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
14597
    // trailing U+005D (]) removed.
14598
436
    input.remove_prefix(1);
14599
436
    input.remove_suffix(1);
14600
436
    return parse_ipv6(input);
14601
706
  }
14602
14603
  // If isNotSpecial is true, then return the result of opaque-host parsing
14604
  // input.
14605
25.2k
  if (!is_special()) {
14606
259
    return parse_opaque_host(input);
14607
259
  }
14608
  // Let domain be the result of running UTF-8 decode without BOM on the
14609
  // percent-decoding of input. Let asciiDomain be the result of running domain
14610
  // to ASCII with domain and false. The most common case is an ASCII input, in
14611
  // which case we do not need to call the expensive 'to_ascii' if a few
14612
  // conditions are met: no '%' and no 'xn-' subsequence.
14613
14614
  // Often, the input does not contain any forbidden code points, and no upper
14615
  // case ASCII letter, then we can just copy it to the buffer. We want to
14616
  // optimize for such a common case.
14617
14618
  // Fast path: try to parse as pure decimal IPv4(a.b.c.d) first.
14619
25.0k
  const uint64_t fast_result = checkers::try_parse_ipv4_fast(input);
14620
25.0k
  if (fast_result < checkers::ipv4_fast_fail) {
14621
    // Fast path succeeded - input is pure decimal IPv4
14622
19
    if (!input.empty() && input.back() == '.') {
14623
5
      update_base_hostname(input.substr(0, input.size() - 1));
14624
14
    } else {
14625
14
      update_base_hostname(input);
14626
14
    }
14627
19
    host_type = IPV4;
14628
19
    ada_log("parse_host fast path decimal ipv4");
14629
19
    ADA_ASSERT_TRUE(validate());
14630
19
    return true;
14631
19
  }
14632
25.0k
  uint8_t is_forbidden_or_upper =
14633
25.0k
      unicode::contains_forbidden_domain_code_point_or_upper(input.data(),
14634
25.0k
                                                             input.size());
14635
  // Minor optimization opportunity:
14636
  // contains_forbidden_domain_code_point_or_upper could be extend to check for
14637
  // the presence of characters that cannot appear in the ipv4 address and we
14638
  // could also check whether x and n and - are present, and so we could skip
14639
  // some of the checks below. However, the gains are likely to be small, and
14640
  // the code would be more complex.
14641
25.0k
  if (is_forbidden_or_upper == 0 &&
14642
15.2k
      input.find("xn-") == std::string_view::npos) {
14643
    // fast path
14644
14.9k
    update_base_hostname(input);
14645
14646
    // Check for other IPv4 formats (hex, octal, etc.)
14647
14.9k
    if (checkers::is_ipv4(get_hostname())) {
14648
1.51k
      ada_log("parse_host fast path ipv4");
14649
1.51k
      return parse_ipv4(get_hostname(), true);
14650
1.51k
    }
14651
13.4k
    ada_log("parse_host fast path ", get_hostname());
14652
13.4k
    return true;
14653
14.9k
  }
14654
  // We have encountered at least one forbidden code point or the input contains
14655
  // 'xn-' (case insensitive), so we need to call 'to_ascii' to perform the full
14656
  // conversion.
14657
14658
10.0k
  ada_log("parse_host calling to_ascii");
14659
10.0k
  std::optional<std::string> host = std::string(get_hostname());
14660
10.0k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
14661
10.0k
  if (!is_valid) {
14662
4.70k
    ada_log("parse_host to_ascii returns false");
14663
4.70k
    return is_valid = false;
14664
4.70k
  }
14665
5.33k
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
14666
5.33k
          " bytes]");
14667
14668
5.33k
  if (std::ranges::any_of(host.value(),
14669
5.33k
                          ada::unicode::is_forbidden_domain_code_point)) {
14670
0
    return is_valid = false;
14671
0
  }
14672
14673
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
14674
  // asciiDomain.
14675
5.33k
  if (checkers::is_ipv4(host.value())) {
14676
651
    ada_log("parse_host got ipv4 ", *host);
14677
651
    return parse_ipv4(host.value(), false);
14678
651
  }
14679
14680
4.68k
  update_base_hostname(host.value());
14681
4.68k
  ADA_ASSERT_TRUE(validate());
14682
4.68k
  return true;
14683
5.33k
}
14684
14685
template <bool override_hostname>
14686
18.5k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14687
18.5k
  ada_log("url_aggregator::set_host_or_hostname ", input);
14688
18.5k
  ADA_ASSERT_TRUE(validate());
14689
18.5k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14690
18.5k
  if (has_opaque_path) {
14691
0
    return false;
14692
0
  }
14693
14694
18.5k
  std::string previous_host(get_hostname());
14695
18.5k
  uint32_t previous_port = components.port;
14696
14697
18.5k
  size_t host_end_pos = input.find('#');
14698
18.5k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14699
18.5k
                                      ? host_end_pos
14700
18.5k
                                      : input.size());
14701
18.5k
  helpers::remove_ascii_tab_or_newline(_host);
14702
18.5k
  std::string_view new_host(_host);
14703
14704
  // If url's scheme is "file", then set state to file host state, instead of
14705
  // host state.
14706
18.5k
  if (type != ada::scheme::type::FILE) {
14707
17.1k
    std::string_view host_view(_host.data(), _host.length());
14708
17.1k
    auto [location, found_colon] =
14709
17.1k
        helpers::get_host_delimiter_location(is_special(), host_view);
14710
14711
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14712
    // Note: the 'found_colon' value is true if and only if a colon was
14713
    // encountered while not inside brackets.
14714
17.1k
    if (found_colon) {
14715
      // If buffer is the empty string, host-missing validation error, return
14716
      // failure.
14717
7.57k
      std::string_view host_buffer = host_view.substr(0, location);
14718
7.57k
      if (host_buffer.empty()) {
14719
30
        return false;
14720
30
      }
14721
14722
      // If state override is given and state override is hostname state, then
14723
      // return failure.
14724
7.54k
      if constexpr (override_hostname) {
14725
3.77k
        return false;
14726
3.77k
      }
14727
14728
      // Let host be the result of host parsing buffer with url is not special.
14729
0
      bool succeeded = parse_host(host_buffer);
14730
7.54k
      if (!succeeded) {
14731
402
        update_base_hostname(previous_host);
14732
402
        update_base_port(previous_port);
14733
402
        return false;
14734
402
      }
14735
14736
      // Set url's host to host, buffer to the empty string, and state to port
14737
      // state.
14738
7.14k
      std::string_view port_buffer = new_host.substr(location + 1);
14739
7.14k
      if (!port_buffer.empty()) {
14740
2.93k
        set_port(port_buffer);
14741
2.93k
      }
14742
7.14k
      return true;
14743
7.54k
    }
14744
    // Otherwise, if one of the following is true:
14745
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14746
    // - url is special and c is U+005C (\)
14747
9.55k
    else {
14748
      // If url is special and host_view is the empty string, host-missing
14749
      // validation error, return failure.
14750
9.55k
      if (host_view.empty() && is_special()) {
14751
1.62k
        return false;
14752
1.62k
      }
14753
14754
      // Otherwise, if state override is given, host_view is the empty string,
14755
      // and either url includes credentials or url's port is non-null, then
14756
      // return failure.
14757
7.93k
      if (host_view.empty() && (has_credentials() || has_port())) {
14758
0
        return false;
14759
0
      }
14760
14761
      // Let host be the result of host parsing host_view with url is not
14762
      // special.
14763
7.93k
      if (host_view.empty() && !is_special()) {
14764
0
        if (has_hostname()) {
14765
0
          clear_hostname();  // easy!
14766
0
        } else if (has_dash_dot()) {
14767
0
          add_authority_slashes_if_needed();
14768
0
          delete_dash_dot();
14769
0
        }
14770
0
        return true;
14771
0
      }
14772
14773
7.93k
      bool succeeded = parse_host(host_view);
14774
7.93k
      if (!succeeded) {
14775
3.55k
        update_base_hostname(previous_host);
14776
3.55k
        update_base_port(previous_port);
14777
3.55k
        return false;
14778
4.38k
      } else if (has_dash_dot()) {
14779
        // Should remove dash_dot from pathname
14780
0
        delete_dash_dot();
14781
0
      }
14782
4.38k
      return true;
14783
7.93k
    }
14784
17.1k
  }
14785
14786
1.41k
  size_t location = new_host.find_first_of("/\\?");
14787
1.41k
  if (location != std::string_view::npos) {
14788
1.29k
    new_host.remove_suffix(new_host.length() - location);
14789
1.29k
  }
14790
14791
1.41k
  if (new_host.empty()) {
14792
    // Set url's host to the empty string.
14793
0
    clear_hostname();
14794
1.41k
  } else {
14795
    // Let host be the result of host parsing buffer with url is not special.
14796
1.41k
    if (!parse_host(new_host)) {
14797
1.41k
      update_base_hostname(previous_host);
14798
1.41k
      update_base_port(previous_port);
14799
1.41k
      return false;
14800
1.41k
    }
14801
14802
    // If host is "localhost", then set host to the empty string.
14803
4
    if (helpers::substring(buffer, components.host_start,
14804
4
                           components.host_end) == "localhost") {
14805
0
      clear_hostname();
14806
0
    }
14807
4
  }
14808
4
  ADA_ASSERT_TRUE(validate());
14809
4
  return true;
14810
1.41k
}
bool ada::url_aggregator::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14686
9.27k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14687
9.27k
  ada_log("url_aggregator::set_host_or_hostname ", input);
14688
9.27k
  ADA_ASSERT_TRUE(validate());
14689
9.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14690
9.27k
  if (has_opaque_path) {
14691
0
    return false;
14692
0
  }
14693
14694
9.27k
  std::string previous_host(get_hostname());
14695
9.27k
  uint32_t previous_port = components.port;
14696
14697
9.27k
  size_t host_end_pos = input.find('#');
14698
9.27k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14699
9.27k
                                      ? host_end_pos
14700
9.27k
                                      : input.size());
14701
9.27k
  helpers::remove_ascii_tab_or_newline(_host);
14702
9.27k
  std::string_view new_host(_host);
14703
14704
  // If url's scheme is "file", then set state to file host state, instead of
14705
  // host state.
14706
9.27k
  if (type != ada::scheme::type::FILE) {
14707
8.56k
    std::string_view host_view(_host.data(), _host.length());
14708
8.56k
    auto [location, found_colon] =
14709
8.56k
        helpers::get_host_delimiter_location(is_special(), host_view);
14710
14711
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14712
    // Note: the 'found_colon' value is true if and only if a colon was
14713
    // encountered while not inside brackets.
14714
8.56k
    if (found_colon) {
14715
      // If buffer is the empty string, host-missing validation error, return
14716
      // failure.
14717
3.78k
      std::string_view host_buffer = host_view.substr(0, location);
14718
3.78k
      if (host_buffer.empty()) {
14719
15
        return false;
14720
15
      }
14721
14722
      // If state override is given and state override is hostname state, then
14723
      // return failure.
14724
      if constexpr (override_hostname) {
14725
        return false;
14726
      }
14727
14728
      // Let host be the result of host parsing buffer with url is not special.
14729
3.77k
      bool succeeded = parse_host(host_buffer);
14730
3.77k
      if (!succeeded) {
14731
402
        update_base_hostname(previous_host);
14732
402
        update_base_port(previous_port);
14733
402
        return false;
14734
402
      }
14735
14736
      // Set url's host to host, buffer to the empty string, and state to port
14737
      // state.
14738
3.37k
      std::string_view port_buffer = new_host.substr(location + 1);
14739
3.37k
      if (!port_buffer.empty()) {
14740
2.93k
        set_port(port_buffer);
14741
2.93k
      }
14742
3.37k
      return true;
14743
3.77k
    }
14744
    // Otherwise, if one of the following is true:
14745
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14746
    // - url is special and c is U+005C (\)
14747
4.77k
    else {
14748
      // If url is special and host_view is the empty string, host-missing
14749
      // validation error, return failure.
14750
4.77k
      if (host_view.empty() && is_special()) {
14751
810
        return false;
14752
810
      }
14753
14754
      // Otherwise, if state override is given, host_view is the empty string,
14755
      // and either url includes credentials or url's port is non-null, then
14756
      // return failure.
14757
3.96k
      if (host_view.empty() && (has_credentials() || has_port())) {
14758
0
        return false;
14759
0
      }
14760
14761
      // Let host be the result of host parsing host_view with url is not
14762
      // special.
14763
3.96k
      if (host_view.empty() && !is_special()) {
14764
0
        if (has_hostname()) {
14765
0
          clear_hostname();  // easy!
14766
0
        } else if (has_dash_dot()) {
14767
0
          add_authority_slashes_if_needed();
14768
0
          delete_dash_dot();
14769
0
        }
14770
0
        return true;
14771
0
      }
14772
14773
3.96k
      bool succeeded = parse_host(host_view);
14774
3.96k
      if (!succeeded) {
14775
1.77k
        update_base_hostname(previous_host);
14776
1.77k
        update_base_port(previous_port);
14777
1.77k
        return false;
14778
2.19k
      } else if (has_dash_dot()) {
14779
        // Should remove dash_dot from pathname
14780
0
        delete_dash_dot();
14781
0
      }
14782
2.19k
      return true;
14783
3.96k
    }
14784
8.56k
  }
14785
14786
709
  size_t location = new_host.find_first_of("/\\?");
14787
709
  if (location != std::string_view::npos) {
14788
645
    new_host.remove_suffix(new_host.length() - location);
14789
645
  }
14790
14791
709
  if (new_host.empty()) {
14792
    // Set url's host to the empty string.
14793
0
    clear_hostname();
14794
709
  } else {
14795
    // Let host be the result of host parsing buffer with url is not special.
14796
709
    if (!parse_host(new_host)) {
14797
707
      update_base_hostname(previous_host);
14798
707
      update_base_port(previous_port);
14799
707
      return false;
14800
707
    }
14801
14802
    // If host is "localhost", then set host to the empty string.
14803
2
    if (helpers::substring(buffer, components.host_start,
14804
2
                           components.host_end) == "localhost") {
14805
0
      clear_hostname();
14806
0
    }
14807
2
  }
14808
2
  ADA_ASSERT_TRUE(validate());
14809
2
  return true;
14810
709
}
bool ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14686
9.27k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14687
9.27k
  ada_log("url_aggregator::set_host_or_hostname ", input);
14688
9.27k
  ADA_ASSERT_TRUE(validate());
14689
9.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14690
9.27k
  if (has_opaque_path) {
14691
0
    return false;
14692
0
  }
14693
14694
9.27k
  std::string previous_host(get_hostname());
14695
9.27k
  uint32_t previous_port = components.port;
14696
14697
9.27k
  size_t host_end_pos = input.find('#');
14698
9.27k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14699
9.27k
                                      ? host_end_pos
14700
9.27k
                                      : input.size());
14701
9.27k
  helpers::remove_ascii_tab_or_newline(_host);
14702
9.27k
  std::string_view new_host(_host);
14703
14704
  // If url's scheme is "file", then set state to file host state, instead of
14705
  // host state.
14706
9.27k
  if (type != ada::scheme::type::FILE) {
14707
8.56k
    std::string_view host_view(_host.data(), _host.length());
14708
8.56k
    auto [location, found_colon] =
14709
8.56k
        helpers::get_host_delimiter_location(is_special(), host_view);
14710
14711
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14712
    // Note: the 'found_colon' value is true if and only if a colon was
14713
    // encountered while not inside brackets.
14714
8.56k
    if (found_colon) {
14715
      // If buffer is the empty string, host-missing validation error, return
14716
      // failure.
14717
3.78k
      std::string_view host_buffer = host_view.substr(0, location);
14718
3.78k
      if (host_buffer.empty()) {
14719
15
        return false;
14720
15
      }
14721
14722
      // If state override is given and state override is hostname state, then
14723
      // return failure.
14724
3.77k
      if constexpr (override_hostname) {
14725
3.77k
        return false;
14726
3.77k
      }
14727
14728
      // Let host be the result of host parsing buffer with url is not special.
14729
0
      bool succeeded = parse_host(host_buffer);
14730
3.77k
      if (!succeeded) {
14731
0
        update_base_hostname(previous_host);
14732
0
        update_base_port(previous_port);
14733
0
        return false;
14734
0
      }
14735
14736
      // Set url's host to host, buffer to the empty string, and state to port
14737
      // state.
14738
3.77k
      std::string_view port_buffer = new_host.substr(location + 1);
14739
3.77k
      if (!port_buffer.empty()) {
14740
0
        set_port(port_buffer);
14741
0
      }
14742
3.77k
      return true;
14743
3.77k
    }
14744
    // Otherwise, if one of the following is true:
14745
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14746
    // - url is special and c is U+005C (\)
14747
4.77k
    else {
14748
      // If url is special and host_view is the empty string, host-missing
14749
      // validation error, return failure.
14750
4.77k
      if (host_view.empty() && is_special()) {
14751
810
        return false;
14752
810
      }
14753
14754
      // Otherwise, if state override is given, host_view is the empty string,
14755
      // and either url includes credentials or url's port is non-null, then
14756
      // return failure.
14757
3.96k
      if (host_view.empty() && (has_credentials() || has_port())) {
14758
0
        return false;
14759
0
      }
14760
14761
      // Let host be the result of host parsing host_view with url is not
14762
      // special.
14763
3.96k
      if (host_view.empty() && !is_special()) {
14764
0
        if (has_hostname()) {
14765
0
          clear_hostname();  // easy!
14766
0
        } else if (has_dash_dot()) {
14767
0
          add_authority_slashes_if_needed();
14768
0
          delete_dash_dot();
14769
0
        }
14770
0
        return true;
14771
0
      }
14772
14773
3.96k
      bool succeeded = parse_host(host_view);
14774
3.96k
      if (!succeeded) {
14775
1.77k
        update_base_hostname(previous_host);
14776
1.77k
        update_base_port(previous_port);
14777
1.77k
        return false;
14778
2.19k
      } else if (has_dash_dot()) {
14779
        // Should remove dash_dot from pathname
14780
0
        delete_dash_dot();
14781
0
      }
14782
2.19k
      return true;
14783
3.96k
    }
14784
8.56k
  }
14785
14786
709
  size_t location = new_host.find_first_of("/\\?");
14787
709
  if (location != std::string_view::npos) {
14788
645
    new_host.remove_suffix(new_host.length() - location);
14789
645
  }
14790
14791
709
  if (new_host.empty()) {
14792
    // Set url's host to the empty string.
14793
0
    clear_hostname();
14794
709
  } else {
14795
    // Let host be the result of host parsing buffer with url is not special.
14796
709
    if (!parse_host(new_host)) {
14797
707
      update_base_hostname(previous_host);
14798
707
      update_base_port(previous_port);
14799
707
      return false;
14800
707
    }
14801
14802
    // If host is "localhost", then set host to the empty string.
14803
2
    if (helpers::substring(buffer, components.host_start,
14804
2
                           components.host_end) == "localhost") {
14805
0
      clear_hostname();
14806
0
    }
14807
2
  }
14808
2
  ADA_ASSERT_TRUE(validate());
14809
2
  return true;
14810
709
}
14811
14812
9.27k
bool url_aggregator::set_host(const std::string_view input) {
14813
9.27k
  ada_log("url_aggregator::set_host '", input, "'");
14814
9.27k
  ADA_ASSERT_TRUE(validate());
14815
9.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14816
9.27k
  return set_host_or_hostname<false>(input);
14817
9.27k
}
14818
14819
9.27k
bool url_aggregator::set_hostname(const std::string_view input) {
14820
9.27k
  ada_log("url_aggregator::set_hostname '", input, "'");
14821
9.27k
  ADA_ASSERT_TRUE(validate());
14822
9.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14823
9.27k
  return set_host_or_hostname<true>(input);
14824
9.27k
}
14825
14826
12.3k
[[nodiscard]] std::string url_aggregator::get_origin() const noexcept {
14827
12.3k
  ada_log("url_aggregator::get_origin");
14828
12.3k
  if (is_special()) {
14829
    // Return a new opaque origin.
14830
10.9k
    if (type == scheme::FILE) {
14831
1.32k
      return "null";
14832
1.32k
    }
14833
14834
9.65k
    return helpers::concat(get_protocol(), "//", get_host());
14835
10.9k
  }
14836
14837
1.41k
  if (get_protocol() == "blob:") {
14838
499
    std::string_view path = get_pathname();
14839
499
    if (!path.empty()) {
14840
489
      auto out = ada::parse<ada::url_aggregator>(path);
14841
489
      if (out && (out->type == scheme::HTTP || out->type == scheme::HTTPS)) {
14842
        // If pathURL's scheme is not "http" and not "https", then return a
14843
        // new opaque origin.
14844
18
        return helpers::concat(out->get_protocol(), "//", out->get_host());
14845
18
      }
14846
489
    }
14847
499
  }
14848
14849
  // Return a new opaque origin.
14850
1.39k
  return "null";
14851
1.41k
}
14852
14853
[[nodiscard]] std::string_view url_aggregator::get_username() const noexcept
14854
16.0k
    ada_lifetime_bound {
14855
16.0k
  ada_log("url_aggregator::get_username");
14856
16.0k
  if (has_non_empty_username()) {
14857
15.3k
    return helpers::substring(buffer, components.protocol_end + 2,
14858
15.3k
                              components.username_end);
14859
15.3k
  }
14860
717
  return "";
14861
16.0k
}
14862
14863
[[nodiscard]] std::string_view url_aggregator::get_password() const noexcept
14864
16.0k
    ada_lifetime_bound {
14865
16.0k
  ada_log("url_aggregator::get_password");
14866
16.0k
  if (has_non_empty_password()) {
14867
15.3k
    return helpers::substring(buffer, components.username_end + 1,
14868
15.3k
                              components.host_start);
14869
15.3k
  }
14870
717
  return "";
14871
16.0k
}
14872
14873
[[nodiscard]] std::string_view url_aggregator::get_port() const noexcept
14874
9.27k
    ada_lifetime_bound {
14875
9.27k
  ada_log("url_aggregator::get_port");
14876
9.27k
  if (components.port == url_components::omitted) {
14877
8.37k
    return "";
14878
8.37k
  }
14879
900
  return helpers::substring(buffer, components.host_end + 1,
14880
900
                            components.pathname_start);
14881
9.27k
}
14882
14883
[[nodiscard]] std::string_view url_aggregator::get_hash() const noexcept
14884
16.0k
    ada_lifetime_bound {
14885
16.0k
  ada_log("url_aggregator::get_hash");
14886
  // If this's URL's fragment is either null or the empty string, then return
14887
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
14888
16.0k
  if (components.hash_start == url_components::omitted) {
14889
8
    return "";
14890
8
  }
14891
16.0k
  if (buffer.size() - components.hash_start <= 1) {
14892
58
    return "";
14893
58
  }
14894
15.9k
  return helpers::substring(buffer, components.hash_start);
14895
16.0k
}
14896
14897
[[nodiscard]] std::string_view url_aggregator::get_host() const noexcept
14898
25.7k
    ada_lifetime_bound {
14899
25.7k
  ada_log("url_aggregator::get_host");
14900
  // Technically, we should check if there is a hostname, but
14901
  // the code below works even if there isn't.
14902
  // if(!has_hostname()) { return ""; }
14903
25.7k
  size_t start = components.host_start;
14904
25.7k
  if (components.host_end > components.host_start &&
14905
25.7k
      buffer[components.host_start] == '@') {
14906
24.1k
    start++;
14907
24.1k
  }
14908
  // if we have an empty host, then the space between components.host_end and
14909
  // components.pathname_start may be occupied by /.
14910
25.7k
  if (start == components.host_end) {
14911
0
    return {};
14912
0
  }
14913
25.7k
  return helpers::substring(buffer, start, components.pathname_start);
14914
25.7k
}
14915
14916
[[nodiscard]] std::string_view url_aggregator::get_hostname() const noexcept
14917
54.7k
    ada_lifetime_bound {
14918
54.7k
  ada_log("url_aggregator::get_hostname");
14919
  // Technically, we should check if there is a hostname, but
14920
  // the code below works even if there isn't.
14921
  // if(!has_hostname()) { return ""; }
14922
54.7k
  size_t start = components.host_start;
14923
  // So host_start is not where the host begins.
14924
54.7k
  if (components.host_end > components.host_start &&
14925
53.3k
      buffer[components.host_start] == '@') {
14926
38.5k
    start++;
14927
38.5k
  }
14928
54.7k
  return helpers::substring(buffer, start, components.host_end);
14929
54.7k
}
14930
14931
[[nodiscard]] std::string_view url_aggregator::get_search() const noexcept
14932
16.0k
    ada_lifetime_bound {
14933
16.0k
  ada_log("url_aggregator::get_search");
14934
  // If this's URL's query is either null or the empty string, then return the
14935
  // empty string. Return U+003F (?), followed by this's URL's query.
14936
16.0k
  if (components.search_start == url_components::omitted) {
14937
8
    return "";
14938
8
  }
14939
16.0k
  auto ending_index = uint32_t(buffer.size());
14940
16.0k
  if (components.hash_start != url_components::omitted) {
14941
16.0k
    ending_index = components.hash_start;
14942
16.0k
  }
14943
16.0k
  if (ending_index - components.search_start <= 1) {
14944
56
    return "";
14945
56
  }
14946
15.9k
  return helpers::substring(buffer, components.search_start, ending_index);
14947
16.0k
}
14948
14949
[[nodiscard]] std::string_view url_aggregator::get_protocol() const noexcept
14950
30.2k
    ada_lifetime_bound {
14951
30.2k
  ada_log("url_aggregator::get_protocol");
14952
30.2k
  return helpers::substring(buffer, 0, components.protocol_end);
14953
30.2k
}
14954
14955
9.27k
[[nodiscard]] std::string ada::url_aggregator::to_string() const {
14956
9.27k
  ada_log("url_aggregator::to_string buffer:", buffer, " [", buffer.size(),
14957
9.27k
          " bytes]");
14958
9.27k
  if (!is_valid) {
14959
2.51k
    return "null";
14960
2.51k
  }
14961
14962
6.76k
  std::string answer;
14963
6.76k
  auto back = std::back_insert_iterator(answer);
14964
6.76k
  answer.append("{\n");
14965
14966
6.76k
  answer.append("\t\"buffer\":\"");
14967
6.76k
  helpers::encode_json(buffer, back);
14968
6.76k
  answer.append("\",\n");
14969
14970
6.76k
  answer.append("\t\"protocol\":\"");
14971
6.76k
  helpers::encode_json(get_protocol(), back);
14972
6.76k
  answer.append("\",\n");
14973
14974
6.76k
  if (has_credentials()) {
14975
6.75k
    answer.append("\t\"username\":\"");
14976
6.75k
    helpers::encode_json(get_username(), back);
14977
6.75k
    answer.append("\",\n");
14978
6.75k
    answer.append("\t\"password\":\"");
14979
6.75k
    helpers::encode_json(get_password(), back);
14980
6.75k
    answer.append("\",\n");
14981
6.75k
  }
14982
14983
6.76k
  answer.append("\t\"host\":\"");
14984
6.76k
  helpers::encode_json(get_host(), back);
14985
6.76k
  answer.append("\",\n");
14986
14987
6.76k
  answer.append("\t\"path\":\"");
14988
6.76k
  helpers::encode_json(get_pathname(), back);
14989
6.76k
  answer.append("\",\n");
14990
6.76k
  answer.append("\t\"opaque path\":");
14991
6.76k
  answer.append((has_opaque_path ? "true" : "false"));
14992
6.76k
  answer.append(",\n");
14993
14994
6.76k
  if (components.search_start != url_components::omitted) {
14995
6.75k
    answer.append("\t\"query\":\"");
14996
6.75k
    helpers::encode_json(get_search(), back);
14997
6.75k
    answer.append("\",\n");
14998
6.75k
  }
14999
6.76k
  if (components.hash_start != url_components::omitted) {
15000
6.75k
    answer.append("\t\"fragment\":\"");
15001
6.75k
    helpers::encode_json(get_hash(), back);
15002
6.75k
    answer.append("\",\n");
15003
6.75k
  }
15004
15005
54.0k
  auto convert_offset_to_string = [](uint32_t offset) -> std::string {
15006
54.0k
    if (offset == url_components::omitted) {
15007
5.87k
      return "null";
15008
48.2k
    } else {
15009
48.2k
      return std::to_string(offset);
15010
48.2k
    }
15011
54.0k
  };
15012
15013
6.76k
  answer.append("\t\"protocol_end\":");
15014
6.76k
  answer.append(convert_offset_to_string(components.protocol_end));
15015
6.76k
  answer.append(",\n");
15016
15017
6.76k
  answer.append("\t\"username_end\":");
15018
6.76k
  answer.append(convert_offset_to_string(components.username_end));
15019
6.76k
  answer.append(",\n");
15020
15021
6.76k
  answer.append("\t\"host_start\":");
15022
6.76k
  answer.append(convert_offset_to_string(components.host_start));
15023
6.76k
  answer.append(",\n");
15024
15025
6.76k
  answer.append("\t\"host_end\":");
15026
6.76k
  answer.append(convert_offset_to_string(components.host_end));
15027
6.76k
  answer.append(",\n");
15028
15029
6.76k
  answer.append("\t\"port\":");
15030
6.76k
  answer.append(convert_offset_to_string(components.port));
15031
6.76k
  answer.append(",\n");
15032
15033
6.76k
  answer.append("\t\"pathname_start\":");
15034
6.76k
  answer.append(convert_offset_to_string(components.pathname_start));
15035
6.76k
  answer.append(",\n");
15036
15037
6.76k
  answer.append("\t\"search_start\":");
15038
6.76k
  answer.append(convert_offset_to_string(components.search_start));
15039
6.76k
  answer.append(",\n");
15040
15041
6.76k
  answer.append("\t\"hash_start\":");
15042
6.76k
  answer.append(convert_offset_to_string(components.hash_start));
15043
6.76k
  answer.append("\n}");
15044
15045
6.76k
  return answer;
15046
9.27k
}
15047
15048
0
[[nodiscard]] bool url_aggregator::has_valid_domain() const noexcept {
15049
0
  if (components.host_start == components.host_end) {
15050
0
    return false;
15051
0
  }
15052
0
  return checkers::verify_dns_length(get_hostname());
15053
0
}
15054
15055
2.16k
bool url_aggregator::parse_ipv4(std::string_view input, bool in_place) {
15056
2.16k
  ada_log("parse_ipv4 ", input, " [", input.size(),
15057
2.16k
          " bytes], overlaps with buffer: ",
15058
2.16k
          helpers::overlaps(input, buffer) ? "yes" : "no");
15059
2.16k
  ADA_ASSERT_TRUE(validate());
15060
2.16k
  const bool trailing_dot = (input.back() == '.');
15061
2.16k
  if (trailing_dot) {
15062
25
    input.remove_suffix(1);
15063
25
  }
15064
2.16k
  size_t digit_count{0};
15065
2.16k
  int pure_decimal_count = 0;  // entries that are decimal
15066
2.16k
  uint64_t ipv4{0};
15067
  // we could unroll for better performance?
15068
2.56k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
15069
2.54k
    uint32_t
15070
2.54k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
15071
2.54k
    bool is_hex = checkers::has_hex_prefix(input);
15072
2.54k
    if (is_hex && ((input.length() == 2) ||
15073
943
                   ((input.length() > 2) && (input[2] == '.')))) {
15074
      // special case
15075
57
      segment_result = 0;
15076
57
      input.remove_prefix(2);
15077
2.48k
    } else {
15078
2.48k
      std::from_chars_result r{};
15079
2.48k
      if (is_hex) {
15080
923
        ada_log("parse_ipv4 trying to parse hex number");
15081
923
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
15082
923
                            segment_result, 16);
15083
1.56k
      } else if ((input.length() >= 2) && input[0] == '0' &&
15084
491
                 checkers::is_digit(input[1])) {
15085
407
        ada_log("parse_ipv4 trying to parse octal number");
15086
407
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
15087
407
                            segment_result, 8);
15088
1.15k
      } else {
15089
1.15k
        ada_log("parse_ipv4 trying to parse decimal number");
15090
1.15k
        pure_decimal_count++;
15091
1.15k
        r = std::from_chars(input.data(), input.data() + input.size(),
15092
1.15k
                            segment_result, 10);
15093
1.15k
      }
15094
2.48k
      if (r.ec != std::errc()) {
15095
426
        ada_log("parse_ipv4 parsing failed");
15096
426
        return is_valid = false;
15097
426
      }
15098
2.06k
      ada_log("parse_ipv4 parsed ", segment_result);
15099
2.06k
      input.remove_prefix(r.ptr - input.data());
15100
2.06k
    }
15101
2.11k
    if (input.empty()) {
15102
      // We have the last value.
15103
      // At this stage, ipv4 contains digit_count*8 bits.
15104
      // So we have 32-digit_count*8 bits left.
15105
1.52k
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
15106
45
        return is_valid = false;
15107
45
      }
15108
1.48k
      ipv4 <<= (32 - digit_count * 8);
15109
1.48k
      ipv4 |= segment_result;
15110
1.48k
      goto final;
15111
1.52k
    } else {
15112
      // There is more, so that the value must no be larger than 255
15113
      // and we must have a '.'.
15114
591
      if ((segment_result > 255) || (input[0] != '.')) {
15115
195
        return is_valid = false;
15116
195
      }
15117
396
      ipv4 <<= 8;
15118
396
      ipv4 |= segment_result;
15119
396
      input.remove_prefix(1);  // remove '.'
15120
396
    }
15121
2.11k
  }
15122
19
  if ((digit_count != 4) || (!input.empty())) {
15123
19
    ada_log("parse_ipv4 found invalid (more than 4 numbers or empty) ");
15124
19
    return is_valid = false;
15125
19
  }
15126
1.48k
final:
15127
1.48k
  ada_log("url_aggregator::parse_ipv4 completed ", get_href(),
15128
1.48k
          " host: ", get_host());
15129
15130
  // We could also check r.ptr to see where the parsing ended.
15131
1.48k
  if (in_place && pure_decimal_count == 4 && !trailing_dot) {
15132
0
    ada_log(
15133
0
        "url_aggregator::parse_ipv4 completed and was already correct in the "
15134
0
        "buffer");
15135
    // The original input was already all decimal and we validated it. So we
15136
    // don't need to do anything.
15137
1.48k
  } else {
15138
1.48k
    ada_log("url_aggregator::parse_ipv4 completed and we need to update it");
15139
    // Optimization opportunity: Get rid of unnecessary string return in ipv4
15140
    // serializer.
15141
    // TODO: This is likely a bug because it goes back update_base_hostname, not
15142
    // what we want to do.
15143
1.48k
    update_base_hostname(
15144
1.48k
        ada::serializers::ipv4(ipv4));  // We have to reserialize the address.
15145
1.48k
  }
15146
1.48k
  host_type = IPV4;
15147
1.48k
  ADA_ASSERT_TRUE(validate());
15148
1.48k
  return true;
15149
19
}
15150
15151
436
bool url_aggregator::parse_ipv6(std::string_view input) {
15152
  // TODO: Implement in_place optimization: we know that input points
15153
  // in the buffer, so we can just check whether the buffer is already
15154
  // well formatted.
15155
  // TODO: Find a way to merge parse_ipv6 with url.cpp implementation.
15156
436
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
15157
436
  ADA_ASSERT_TRUE(validate());
15158
436
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15159
436
  if (input.empty()) {
15160
21
    return is_valid = false;
15161
21
  }
15162
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
15163
415
  std::array<uint16_t, 8> address{};
15164
15165
  // Let pieceIndex be 0.
15166
415
  int piece_index = 0;
15167
15168
  // Let compress be null.
15169
415
  std::optional<int> compress{};
15170
15171
  // Let pointer be a pointer for input.
15172
415
  std::string_view::iterator pointer = input.begin();
15173
15174
  // If c is U+003A (:), then:
15175
415
  if (input[0] == ':') {
15176
    // If remaining does not start with U+003A (:), validation error, return
15177
    // failure.
15178
93
    if (input.size() == 1 || input[1] != ':') {
15179
14
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
15180
14
      return is_valid = false;
15181
14
    }
15182
15183
    // Increase pointer by 2.
15184
79
    pointer += 2;
15185
15186
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
15187
79
    compress = ++piece_index;
15188
79
  }
15189
15190
  // While c is not the EOF code point:
15191
956
  while (pointer != input.end()) {
15192
    // If pieceIndex is 8, validation error, return failure.
15193
782
    if (piece_index == 8) {
15194
5
      ada_log("parse_ipv6 piece_index == 8");
15195
5
      return is_valid = false;
15196
5
    }
15197
15198
    // If c is U+003A (:), then:
15199
777
    if (*pointer == ':') {
15200
      // If compress is non-null, validation error, return failure.
15201
65
      if (compress.has_value()) {
15202
6
        ada_log("parse_ipv6 compress is non-null");
15203
6
        return is_valid = false;
15204
6
      }
15205
15206
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
15207
      // then continue.
15208
59
      pointer++;
15209
59
      compress = ++piece_index;
15210
59
      continue;
15211
65
    }
15212
15213
    // Let value and length be 0.
15214
712
    uint16_t value = 0, length = 0;
15215
15216
    // While length is less than 4 and c is an ASCII hex digit,
15217
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
15218
    // increase pointer and length by 1.
15219
1.78k
    while (length < 4 && pointer != input.end() &&
15220
1.59k
           unicode::is_ascii_hex_digit(*pointer)) {
15221
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
15222
1.06k
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
15223
1.06k
      pointer++;
15224
1.06k
      length++;
15225
1.06k
    }
15226
15227
    // If c is U+002E (.), then:
15228
712
    if (pointer != input.end() && *pointer == '.') {
15229
      // If length is 0, validation error, return failure.
15230
98
      if (length == 0) {
15231
3
        ada_log("parse_ipv6 length is 0");
15232
3
        return is_valid = false;
15233
3
      }
15234
15235
      // Decrease pointer by length.
15236
95
      pointer -= length;
15237
15238
      // If pieceIndex is greater than 6, validation error, return failure.
15239
95
      if (piece_index > 6) {
15240
3
        ada_log("parse_ipv6 piece_index > 6");
15241
3
        return is_valid = false;
15242
3
      }
15243
15244
      // Let numbersSeen be 0.
15245
92
      int numbers_seen = 0;
15246
15247
      // While c is not the EOF code point:
15248
225
      while (pointer != input.end()) {
15249
        // Let ipv4Piece be null.
15250
211
        std::optional<uint16_t> ipv4_piece{};
15251
15252
        // If numbersSeen is greater than 0, then:
15253
211
        if (numbers_seen > 0) {
15254
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
15255
          // pointer by 1.
15256
119
          if (*pointer == '.' && numbers_seen < 4) {
15257
89
            pointer++;
15258
89
          } else {
15259
            // Otherwise, validation error, return failure.
15260
30
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
15261
30
            return is_valid = false;
15262
30
          }
15263
119
        }
15264
15265
        // If c is not an ASCII digit, validation error, return failure.
15266
181
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
15267
28
          ada_log(
15268
28
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
15269
28
              "failure");
15270
28
          return is_valid = false;
15271
28
        }
15272
15273
        // While c is an ASCII digit:
15274
377
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
15275
          // Let number be c interpreted as decimal number.
15276
244
          int number = *pointer - '0';
15277
15278
          // If ipv4Piece is null, then set ipv4Piece to number.
15279
244
          if (!ipv4_piece.has_value()) {
15280
153
            ipv4_piece = number;
15281
153
          }
15282
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
15283
91
          else if (ipv4_piece == 0) {
15284
3
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
15285
3
            return is_valid = false;
15286
3
          }
15287
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
15288
88
          else {
15289
88
            ipv4_piece = *ipv4_piece * 10 + number;
15290
88
          }
15291
15292
          // If ipv4Piece is greater than 255, validation error, return failure.
15293
241
          if (ipv4_piece > 255) {
15294
17
            ada_log("parse_ipv6 ipv4_piece > 255");
15295
17
            return is_valid = false;
15296
17
          }
15297
15298
          // Increase pointer by 1.
15299
224
          pointer++;
15300
224
        }
15301
15302
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
15303
        // ipv4Piece.
15304
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
15305
133
        address[piece_index] =
15306
133
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
15307
15308
        // Increase numbersSeen by 1.
15309
133
        numbers_seen++;
15310
15311
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
15312
133
        if (numbers_seen == 2 || numbers_seen == 4) {
15313
46
          piece_index++;
15314
46
        }
15315
133
      }
15316
15317
      // If numbersSeen is not 4, validation error, return failure.
15318
14
      if (numbers_seen != 4) {
15319
11
        return is_valid = false;
15320
11
      }
15321
15322
      // Break.
15323
3
      break;
15324
14
    }
15325
    // Otherwise, if c is U+003A (:):
15326
614
    else if ((pointer != input.end()) && (*pointer == ':')) {
15327
      // Increase pointer by 1.
15328
370
      pointer++;
15329
15330
      // If c is the EOF code point, validation error, return failure.
15331
370
      if (pointer == input.end()) {
15332
5
        ada_log(
15333
5
            "parse_ipv6 If c is the EOF code point, validation error, return "
15334
5
            "failure");
15335
5
        return is_valid = false;
15336
5
      }
15337
370
    }
15338
    // Otherwise, if c is not the EOF code point, validation error, return
15339
    // failure.
15340
244
    else if (pointer != input.end()) {
15341
113
      ada_log(
15342
113
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
15343
113
          "error, return failure");
15344
113
      return is_valid = false;
15345
113
    }
15346
15347
    // Set address[pieceIndex] to value.
15348
496
    address[piece_index] = value;
15349
15350
    // Increase pieceIndex by 1.
15351
496
    piece_index++;
15352
496
  }
15353
15354
  // If compress is non-null, then:
15355
177
  if (compress.has_value()) {
15356
    // Let swaps be pieceIndex - compress.
15357
119
    int swaps = piece_index - *compress;
15358
15359
    // Set pieceIndex to 7.
15360
119
    piece_index = 7;
15361
15362
    // While pieceIndex is not 0 and swaps is greater than 0,
15363
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
15364
    // decrease both pieceIndex and swaps by 1.
15365
254
    while (piece_index != 0 && swaps > 0) {
15366
135
      std::swap(address[piece_index], address[*compress + swaps - 1]);
15367
135
      piece_index--;
15368
135
      swaps--;
15369
135
    }
15370
119
  }
15371
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
15372
  // return failure.
15373
58
  else if (piece_index != 8) {
15374
49
    ada_log(
15375
49
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
15376
49
        "error, return failure");
15377
49
    return is_valid = false;
15378
49
  }
15379
  // TODO: Optimization opportunity: Get rid of unnecessary string creation.
15380
  // TODO: This is likely a bug because it goes back update_base_hostname, not
15381
  // what we want to do.
15382
128
  update_base_hostname(ada::serializers::ipv6(address));
15383
128
  ada_log("parse_ipv6 ", get_hostname());
15384
128
  ADA_ASSERT_TRUE(validate());
15385
128
  host_type = IPV6;
15386
128
  return true;
15387
177
}
15388
15389
259
bool url_aggregator::parse_opaque_host(std::string_view input) {
15390
259
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
15391
259
  ADA_ASSERT_TRUE(validate());
15392
259
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15393
259
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
15394
19
    return is_valid = false;
15395
19
  }
15396
15397
  // Return the result of running UTF-8 percent-encode on input using the C0
15398
  // control percent-encode set.
15399
240
  size_t idx = ada::unicode::percent_encode_index(
15400
240
      input, character_sets::C0_CONTROL_PERCENT_ENCODE);
15401
240
  if (idx == input.size()) {
15402
117
    update_base_hostname(input);
15403
123
  } else {
15404
    // We only create a temporary string if we need to.
15405
123
    update_base_hostname(ada::unicode::percent_encode(
15406
123
        input, character_sets::C0_CONTROL_PERCENT_ENCODE, idx));
15407
123
  }
15408
240
  ADA_ASSERT_TRUE(validate());
15409
240
  return true;
15410
259
}
15411
15412
9.27k
[[nodiscard]] std::string url_aggregator::to_diagram() const {
15413
9.27k
  if (!is_valid) {
15414
2.51k
    return "invalid";
15415
2.51k
  }
15416
6.76k
  std::string answer;
15417
6.76k
  answer.append(buffer);
15418
6.76k
  answer.append(" [");
15419
6.76k
  answer.append(std::to_string(buffer.size()));
15420
6.76k
  answer.append(" bytes]");
15421
6.76k
  answer.append("\n");
15422
  // first line
15423
6.76k
  std::string line1;
15424
6.76k
  line1.resize(buffer.size(), ' ');
15425
6.76k
  if (components.hash_start != url_components::omitted) {
15426
6.75k
    line1[components.hash_start] = '|';
15427
6.75k
  }
15428
6.76k
  if (components.search_start != url_components::omitted) {
15429
6.75k
    line1[components.search_start] = '|';
15430
6.75k
  }
15431
6.76k
  if (components.pathname_start != buffer.size()) {
15432
6.76k
    line1[components.pathname_start] = '|';
15433
6.76k
  }
15434
6.76k
  if (components.host_end != buffer.size()) {
15435
6.76k
    line1[components.host_end] = '|';
15436
6.76k
  }
15437
6.76k
  if (components.host_start != buffer.size()) {
15438
6.76k
    line1[components.host_start] = '|';
15439
6.76k
  }
15440
6.76k
  if (components.username_end != buffer.size()) {
15441
6.76k
    line1[components.username_end] = '|';
15442
6.76k
  }
15443
6.76k
  if (components.protocol_end != buffer.size()) {
15444
6.76k
    line1[components.protocol_end] = '|';
15445
6.76k
  }
15446
6.76k
  answer.append(line1);
15447
6.76k
  answer.append("\n");
15448
15449
6.76k
  std::string line2 = line1;
15450
6.76k
  if (components.hash_start != url_components::omitted) {
15451
6.75k
    line2[components.hash_start] = '`';
15452
6.75k
    line1[components.hash_start] = ' ';
15453
15454
469k
    for (size_t i = components.hash_start + 1; i < line2.size(); i++) {
15455
462k
      line2[i] = '-';
15456
462k
    }
15457
6.75k
    line2.append(" hash_start");
15458
6.75k
    answer.append(line2);
15459
6.75k
    answer.append("\n");
15460
6.75k
  }
15461
15462
6.76k
  std::string line3 = line1;
15463
6.76k
  if (components.search_start != url_components::omitted) {
15464
6.75k
    line3[components.search_start] = '`';
15465
6.75k
    line1[components.search_start] = ' ';
15466
15467
940k
    for (size_t i = components.search_start + 1; i < line3.size(); i++) {
15468
933k
      line3[i] = '-';
15469
933k
    }
15470
6.75k
    line3.append(" search_start ");
15471
6.75k
    line3.append(std::to_string(components.search_start));
15472
6.75k
    answer.append(line3);
15473
6.75k
    answer.append("\n");
15474
6.75k
  }
15475
15476
6.76k
  std::string line4 = line1;
15477
6.76k
  if (components.pathname_start != buffer.size()) {
15478
6.76k
    line4[components.pathname_start] = '`';
15479
6.76k
    line1[components.pathname_start] = ' ';
15480
1.37M
    for (size_t i = components.pathname_start + 1; i < line4.size(); i++) {
15481
1.36M
      line4[i] = '-';
15482
1.36M
    }
15483
6.76k
    line4.append(" pathname_start ");
15484
6.76k
    line4.append(std::to_string(components.pathname_start));
15485
6.76k
    answer.append(line4);
15486
6.76k
    answer.append("\n");
15487
6.76k
  }
15488
15489
6.76k
  std::string line5 = line1;
15490
6.76k
  if (components.host_end != buffer.size()) {
15491
6.76k
    line5[components.host_end] = '`';
15492
6.76k
    line1[components.host_end] = ' ';
15493
15494
1.37M
    for (size_t i = components.host_end + 1; i < line5.size(); i++) {
15495
1.37M
      line5[i] = '-';
15496
1.37M
    }
15497
6.76k
    line5.append(" host_end ");
15498
6.76k
    line5.append(std::to_string(components.host_end));
15499
6.76k
    answer.append(line5);
15500
6.76k
    answer.append("\n");
15501
6.76k
  }
15502
15503
6.76k
  std::string line6 = line1;
15504
6.76k
  if (components.host_start != buffer.size()) {
15505
6.76k
    line6[components.host_start] = '`';
15506
6.76k
    line1[components.host_start] = ' ';
15507
15508
1.61M
    for (size_t i = components.host_start + 1; i < line6.size(); i++) {
15509
1.60M
      line6[i] = '-';
15510
1.60M
    }
15511
6.76k
    line6.append(" host_start ");
15512
6.76k
    line6.append(std::to_string(components.host_start));
15513
6.76k
    answer.append(line6);
15514
6.76k
    answer.append("\n");
15515
6.76k
  }
15516
15517
6.76k
  std::string line7 = line1;
15518
6.76k
  if (components.username_end != buffer.size()) {
15519
6.76k
    line7[components.username_end] = '`';
15520
6.76k
    line1[components.username_end] = ' ';
15521
15522
2.16M
    for (size_t i = components.username_end + 1; i < line7.size(); i++) {
15523
2.15M
      line7[i] = '-';
15524
2.15M
    }
15525
6.76k
    line7.append(" username_end ");
15526
6.76k
    line7.append(std::to_string(components.username_end));
15527
6.76k
    answer.append(line7);
15528
6.76k
    answer.append("\n");
15529
6.76k
  }
15530
15531
6.76k
  std::string line8 = line1;
15532
6.76k
  if (components.protocol_end != buffer.size()) {
15533
6.76k
    line8[components.protocol_end] = '`';
15534
6.76k
    line1[components.protocol_end] = ' ';
15535
15536
2.72M
    for (size_t i = components.protocol_end + 1; i < line8.size(); i++) {
15537
2.71M
      line8[i] = '-';
15538
2.71M
    }
15539
6.76k
    line8.append(" protocol_end ");
15540
6.76k
    line8.append(std::to_string(components.protocol_end));
15541
6.76k
    answer.append(line8);
15542
6.76k
    answer.append("\n");
15543
6.76k
  }
15544
15545
6.76k
  if (components.hash_start == url_components::omitted) {
15546
8
    answer.append("note: hash omitted\n");
15547
8
  }
15548
6.76k
  if (components.search_start == url_components::omitted) {
15549
8
    answer.append("note: search omitted\n");
15550
8
  }
15551
6.76k
  if (components.protocol_end > buffer.size()) {
15552
0
    answer.append("warning: protocol_end overflows\n");
15553
0
  }
15554
6.76k
  if (components.username_end > buffer.size()) {
15555
0
    answer.append("warning: username_end overflows\n");
15556
0
  }
15557
6.76k
  if (components.host_start > buffer.size()) {
15558
0
    answer.append("warning: host_start overflows\n");
15559
0
  }
15560
6.76k
  if (components.host_end > buffer.size()) {
15561
0
    answer.append("warning: host_end overflows\n");
15562
0
  }
15563
6.76k
  if (components.pathname_start > buffer.size()) {
15564
0
    answer.append("warning: pathname_start overflows\n");
15565
0
  }
15566
6.76k
  return answer;
15567
9.27k
}
15568
15569
0
void url_aggregator::delete_dash_dot() {
15570
0
  ada_log("url_aggregator::delete_dash_dot");
15571
0
  ADA_ASSERT_TRUE(validate());
15572
0
  ADA_ASSERT_TRUE(has_dash_dot());
15573
0
  buffer.erase(components.host_end, 2);
15574
0
  components.pathname_start -= 2;
15575
0
  if (components.search_start != url_components::omitted) {
15576
0
    components.search_start -= 2;
15577
0
  }
15578
0
  if (components.hash_start != url_components::omitted) {
15579
0
    components.hash_start -= 2;
15580
0
  }
15581
0
  ADA_ASSERT_TRUE(validate());
15582
0
  ADA_ASSERT_TRUE(!has_dash_dot());
15583
0
}
15584
15585
11.9k
inline void url_aggregator::consume_prepared_path(std::string_view input) {
15586
11.9k
  ada_log("url_aggregator::consume_prepared_path ", input);
15587
  /***
15588
   * This is largely duplicated code from helpers::parse_prepared_path, which is
15589
   * unfortunate. This particular function is nearly identical, except that it
15590
   * is a method on url_aggregator. The idea is that the trivial path (which is
15591
   * very common) merely appends to the buffer. This is the same trivial path as
15592
   * with helpers::parse_prepared_path, except that we have the additional check
15593
   * for is_at_path(). Otherwise, we grab a copy of the current path and we
15594
   * modify it, and then insert it back into the buffer.
15595
   */
15596
11.9k
  uint8_t accumulator = checkers::path_signature(input);
15597
  // Let us first detect a trivial case.
15598
  // If it is special, we check that we have no dot, no %,  no \ and no
15599
  // character needing percent encoding. Otherwise, we check that we have no %,
15600
  // no dot, and no character needing percent encoding.
15601
11.9k
  constexpr uint8_t need_encoding = 1;
15602
11.9k
  constexpr uint8_t backslash_char = 2;
15603
11.9k
  constexpr uint8_t dot_char = 4;
15604
11.9k
  constexpr uint8_t percent_char = 8;
15605
11.9k
  bool special = type != ada::scheme::NOT_SPECIAL;
15606
11.9k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
15607
1.60k
                                      checkers::is_windows_drive_letter(input));
15608
11.9k
  bool trivial_path =
15609
11.9k
      (special ? (accumulator == 0)
15610
11.9k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
15611
1.00k
                  0)) &&
15612
2.11k
      (!may_need_slow_file_handling);
15613
11.9k
  if (accumulator == dot_char && !may_need_slow_file_handling) {
15614
    // '4' means that we have at least one dot, but nothing that requires
15615
    // percent encoding or decoding. The only part that is not trivial is
15616
    // that we may have single dots and double dots path segments.
15617
    // If we have such segments, then we either have a path that begins
15618
    // with '.' (easy to check), or we have the sequence './'.
15619
    // Note: input cannot be empty, it must at least contain one character ('.')
15620
    // Note: we know that '\' is not present.
15621
2.55k
    if (input[0] != '.') {
15622
1.81k
      size_t slashdot = 0;
15623
1.81k
      bool dot_is_file = true;
15624
9.52k
      for (;;) {
15625
9.52k
        slashdot = input.find("/.", slashdot);
15626
9.52k
        if (slashdot == std::string_view::npos) {  // common case
15627
1.81k
          break;
15628
7.71k
        } else {  // uncommon
15629
          // only three cases matter: /./, /.. or a final /
15630
7.71k
          slashdot += 2;
15631
7.71k
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
15632
2.14k
                           input[slashdot] == '/');
15633
7.71k
        }
15634
9.52k
      }
15635
1.81k
      trivial_path = dot_is_file;
15636
1.81k
    }
15637
2.55k
  }
15638
11.9k
  if (trivial_path && is_at_path()) {
15639
2.72k
    ada_log("parse_path trivial");
15640
2.72k
    buffer += '/';
15641
2.72k
    buffer += input;
15642
2.72k
    return;
15643
2.72k
  }
15644
9.22k
  std::string path = std::string(get_pathname());
15645
  // We are going to need to look a bit at the path, but let us see if we can
15646
  // ignore percent encoding *and* backslashes *and* percent characters.
15647
  // Except for the trivial case, this is likely to capture 99% of paths out
15648
  // there.
15649
9.22k
  bool fast_path =
15650
9.22k
      (special &&
15651
8.31k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
15652
1.77k
      (type != ada::scheme::type::FILE);
15653
9.22k
  if (fast_path) {
15654
1.38k
    ada_log("parse_prepared_path fast");
15655
    // Here we don't need to worry about \ or percent encoding.
15656
    // We also do not have a file protocol. We might have dots, however,
15657
    // but dots must as appear as '.', and they cannot be encoded because
15658
    // the symbol '%' is not present.
15659
1.38k
    size_t previous_location = 0;  // We start at 0.
15660
17.7k
    do {
15661
17.7k
      size_t new_location = input.find('/', previous_location);
15662
      // std::string_view path_view = input;
15663
      //  We process the last segment separately:
15664
17.7k
      if (new_location == std::string_view::npos) {
15665
1.38k
        std::string_view path_view = input.substr(previous_location);
15666
1.38k
        if (path_view == "..") {  // The path ends with ..
15667
          // e.g., if you receive ".." with an empty path, you go to "/".
15668
179
          if (path.empty()) {
15669
68
            path = '/';
15670
68
            update_base_pathname(path);
15671
68
            return;
15672
68
          }
15673
          // Fast case where we have nothing to do:
15674
111
          if (path.back() == '/') {
15675
43
            update_base_pathname(path);
15676
43
            return;
15677
43
          }
15678
          // If you have the path "/joe/myfriend",
15679
          // then you delete 'myfriend'.
15680
68
          path.resize(path.rfind('/') + 1);
15681
68
          update_base_pathname(path);
15682
68
          return;
15683
111
        }
15684
1.20k
        path += '/';
15685
1.20k
        if (path_view != ".") {
15686
960
          path.append(path_view);
15687
960
        }
15688
1.20k
        update_base_pathname(path);
15689
1.20k
        return;
15690
16.3k
      } else {
15691
        // This is a non-final segment.
15692
16.3k
        std::string_view path_view =
15693
16.3k
            input.substr(previous_location, new_location - previous_location);
15694
16.3k
        previous_location = new_location + 1;
15695
16.3k
        if (path_view == "..") {
15696
3.84k
          size_t last_delimiter = path.rfind('/');
15697
3.84k
          if (last_delimiter != std::string::npos) {
15698
1.95k
            path.erase(last_delimiter);
15699
1.95k
          }
15700
12.4k
        } else if (path_view != ".") {
15701
10.4k
          path += '/';
15702
10.4k
          path.append(path_view);
15703
10.4k
        }
15704
16.3k
      }
15705
17.7k
    } while (true);
15706
7.83k
  } else {
15707
7.83k
    ada_log("parse_path slow");
15708
    // we have reached the general case
15709
7.83k
    bool needs_percent_encoding = (accumulator & 1);
15710
7.83k
    std::string path_buffer_tmp;
15711
44.7k
    do {
15712
44.7k
      size_t location = (special && (accumulator & 2))
15713
44.7k
                            ? input.find_first_of("/\\")
15714
44.7k
                            : input.find('/');
15715
44.7k
      std::string_view path_view = input;
15716
44.7k
      if (location != std::string_view::npos) {
15717
36.9k
        path_view.remove_suffix(path_view.size() - location);
15718
36.9k
        input.remove_prefix(location + 1);
15719
36.9k
      }
15720
      // path_buffer is either path_view or it might point at a percent encoded
15721
      // temporary string.
15722
44.7k
      std::string_view path_buffer =
15723
44.7k
          (needs_percent_encoding &&
15724
29.2k
           ada::unicode::percent_encode<false>(
15725
29.2k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
15726
44.7k
              ? path_buffer_tmp
15727
44.7k
              : path_view;
15728
44.7k
      if (unicode::is_double_dot_path_segment(path_buffer)) {
15729
10.5k
        helpers::shorten_path(path, type);
15730
10.5k
        if (location == std::string_view::npos) {
15731
843
          path += '/';
15732
843
        }
15733
34.2k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
15734
2.18k
                 (location == std::string_view::npos)) {
15735
183
        path += '/';
15736
183
      }
15737
      // Otherwise, if path_buffer is not a single-dot path segment, then:
15738
34.0k
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
15739
        // If url's scheme is "file", url's path is empty, and path_buffer is a
15740
        // Windows drive letter, then replace the second code point in
15741
        // path_buffer with U+003A (:).
15742
32.0k
        if (type == ada::scheme::type::FILE && path.empty() &&
15743
4.11k
            checkers::is_windows_drive_letter(path_buffer)) {
15744
175
          path += '/';
15745
175
          path += path_buffer[0];
15746
175
          path += ':';
15747
175
          path_buffer.remove_prefix(2);
15748
175
          path.append(path_buffer);
15749
31.8k
        } else {
15750
          // Append path_buffer to url's path.
15751
31.8k
          path += '/';
15752
31.8k
          path.append(path_buffer);
15753
31.8k
        }
15754
32.0k
      }
15755
44.7k
      if (location == std::string_view::npos) {
15756
7.83k
        update_base_pathname(path);
15757
7.83k
        return;
15758
7.83k
      }
15759
44.7k
    } while (true);
15760
7.83k
  }
15761
9.22k
}
15762
}  // namespace ada
15763
/* end file src/url_aggregator.cpp */
15764
15765
#if ADA_INCLUDE_URL_PATTERN
15766
/* begin file src/url_pattern.cpp */
15767
#if ADA_INCLUDE_URL_PATTERN
15768
15769
15770
#include <algorithm>
15771
#include <optional>
15772
#include <string>
15773
15774
namespace ada {
15775
15776
tl::expected<url_pattern_init, errors> url_pattern_init::process(
15777
    const url_pattern_init& init, url_pattern_init::process_type type,
15778
    std::optional<std::string_view> protocol,
15779
    std::optional<std::string_view> username,
15780
    std::optional<std::string_view> password,
15781
    std::optional<std::string_view> hostname,
15782
    std::optional<std::string_view> port,
15783
    std::optional<std::string_view> pathname,
15784
    std::optional<std::string_view> search,
15785
0
    std::optional<std::string_view> hash) {
15786
  // Let result be the result of creating a new URLPatternInit.
15787
0
  auto result = url_pattern_init{};
15788
15789
  // If protocol is not null, set result["protocol"] to protocol.
15790
0
  if (protocol.has_value()) result.protocol = *protocol;
15791
15792
  // If username is not null, set result["username"] to username.
15793
0
  if (username.has_value()) result.username = *username;
15794
15795
  // If password is not null, set result["password"] to password.
15796
0
  if (password.has_value()) result.password = *password;
15797
15798
  // If hostname is not null, set result["hostname"] to hostname.
15799
0
  if (hostname.has_value()) result.hostname = *hostname;
15800
15801
  // If port is not null, set result["port"] to port.
15802
0
  if (port.has_value()) result.port = *port;
15803
15804
  // If pathname is not null, set result["pathname"] to pathname.
15805
0
  if (pathname.has_value()) result.pathname = *pathname;
15806
15807
  // If search is not null, set result["search"] to search.
15808
0
  if (search.has_value()) result.search = *search;
15809
15810
  // If hash is not null, set result["hash"] to hash.
15811
0
  if (hash.has_value()) result.hash = *hash;
15812
15813
  // Let baseURL be null.
15814
0
  std::optional<url_aggregator> base_url{};
15815
15816
  // If init["baseURL"] exists:
15817
0
  if (init.base_url.has_value()) {
15818
    // Set baseURL to the result of parsing init["baseURL"].
15819
0
    auto parsing_result = ada::parse<url_aggregator>(*init.base_url);
15820
    // If baseURL is failure, then throw a TypeError.
15821
0
    if (!parsing_result) {
15822
0
      return tl::unexpected(errors::type_error);
15823
0
    }
15824
0
    base_url = std::move(*parsing_result);
15825
15826
    // If init["protocol"] does not exist, then set result["protocol"] to the
15827
    // result of processing a base URL string given baseURL's scheme and type.
15828
0
    if (!init.protocol.has_value()) {
15829
0
      ADA_ASSERT_TRUE(base_url.has_value());
15830
0
      std::string_view base_url_protocol = base_url->get_protocol();
15831
0
      if (base_url_protocol.ends_with(":")) base_url_protocol.remove_suffix(1);
15832
0
      result.protocol =
15833
0
          url_pattern_helpers::process_base_url_string(base_url_protocol, type);
15834
0
    }
15835
15836
    // If type is not "pattern" and init contains none of "protocol",
15837
    // "hostname", "port" and "username", then set result["username"] to the
15838
    // result of processing a base URL string given baseURL's username and type.
15839
0
    if (type != process_type::pattern && !init.protocol && !init.hostname &&
15840
0
        !init.port && !init.username) {
15841
0
      result.username = url_pattern_helpers::process_base_url_string(
15842
0
          base_url->get_username(), type);
15843
0
    }
15844
15845
    // TODO: Optimization opportunity: Merge this with the previous check.
15846
    // If type is not "pattern" and init contains none of "protocol",
15847
    // "hostname", "port", "username" and "password", then set
15848
    // result["password"] to the result of processing a base URL string given
15849
    // baseURL's password and type.
15850
0
    if (type != process_type::pattern && !init.protocol && !init.hostname &&
15851
0
        !init.port && !init.username && !init.password) {
15852
0
      result.password = url_pattern_helpers::process_base_url_string(
15853
0
          base_url->get_password(), type);
15854
0
    }
15855
15856
    // If init contains neither "protocol" nor "hostname", then:
15857
0
    if (!init.protocol && !init.hostname) {
15858
      // Let baseHost be baseURL's host.
15859
      // If baseHost is null, then set baseHost to the empty string.
15860
0
      auto base_host = base_url->get_hostname();
15861
      // Set result["hostname"] to the result of processing a base URL string
15862
      // given baseHost and type.
15863
0
      result.hostname =
15864
0
          url_pattern_helpers::process_base_url_string(base_host, type);
15865
0
    }
15866
15867
    // If init contains none of "protocol", "hostname", and "port", then:
15868
0
    if (!init.protocol && !init.hostname && !init.port) {
15869
      // If baseURL's port is null, then set result["port"] to the empty string.
15870
      // Otherwise, set result["port"] to baseURL's port, serialized.
15871
0
      result.port = base_url->get_port();
15872
0
    }
15873
15874
    // If init contains none of "protocol", "hostname", "port", and "pathname",
15875
    // then set result["pathname"] to the result of processing a base URL string
15876
    // given the result of URL path serializing baseURL and type.
15877
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname) {
15878
0
      result.pathname = url_pattern_helpers::process_base_url_string(
15879
0
          base_url->get_pathname(), type);
15880
0
    }
15881
15882
    // If init contains none of "protocol", "hostname", "port", "pathname", and
15883
    // "search", then:
15884
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname &&
15885
0
        !init.search) {
15886
      // Let baseQuery be baseURL's query.
15887
      // Set result["search"] to the result of processing a base URL string
15888
      // given baseQuery and type.
15889
0
      result.search = url_pattern_helpers::process_base_url_string(
15890
0
          base_url->get_search(), type);
15891
0
    }
15892
15893
    // If init contains none of "protocol", "hostname", "port", "pathname",
15894
    // "search", and "hash", then:
15895
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname &&
15896
0
        !init.search && !init.hash) {
15897
      // Let baseFragment be baseURL's fragment.
15898
      // Set result["hash"] to the result of processing a base URL string given
15899
      // baseFragment and type.
15900
0
      result.hash = url_pattern_helpers::process_base_url_string(
15901
0
          base_url->get_hash(), type);
15902
0
    }
15903
0
  }
15904
15905
  // If init["protocol"] exists, then set result["protocol"] to the result of
15906
  // process protocol for init given init["protocol"] and type.
15907
0
  if (init.protocol) {
15908
0
    auto process_result = process_protocol(*init.protocol, type);
15909
0
    if (!process_result) {
15910
0
      return tl::unexpected(process_result.error());
15911
0
    }
15912
0
    result.protocol = std::move(*process_result);
15913
0
  }
15914
15915
  // If init["username"] exists, then set result["username"] to the result of
15916
  // process username for init given init["username"] and type.
15917
0
  if (init.username.has_value()) {
15918
0
    auto process_result = process_username(*init.username, type);
15919
0
    if (!process_result) {
15920
0
      return tl::unexpected(process_result.error());
15921
0
    }
15922
0
    result.username = std::move(*process_result);
15923
0
  }
15924
15925
  // If init["password"] exists, then set result["password"] to the result of
15926
  // process password for init given init["password"] and type.
15927
0
  if (init.password.has_value()) {
15928
0
    auto process_result = process_password(*init.password, type);
15929
0
    if (!process_result) {
15930
0
      return tl::unexpected(process_result.error());
15931
0
    }
15932
0
    result.password = std::move(*process_result);
15933
0
  }
15934
15935
  // If init["hostname"] exists, then set result["hostname"] to the result of
15936
  // process hostname for init given init["hostname"] and type.
15937
0
  if (init.hostname.has_value()) {
15938
0
    auto process_result = process_hostname(*init.hostname, type);
15939
0
    if (!process_result) {
15940
0
      return tl::unexpected(process_result.error());
15941
0
    }
15942
0
    result.hostname = std::move(*process_result);
15943
0
  }
15944
15945
  // If init["port"] exists, then set result["port"] to the result of process
15946
  // port for init given init["port"], result["protocol"], and type.
15947
0
  if (init.port) {
15948
0
    auto process_result =
15949
0
        process_port(*init.port, result.protocol.value_or("fake"), type);
15950
0
    if (!process_result) {
15951
0
      return tl::unexpected(process_result.error());
15952
0
    }
15953
0
    result.port = std::move(*process_result);
15954
0
  }
15955
15956
  // If init["pathname"] exists:
15957
0
  if (init.pathname.has_value()) {
15958
    // Set result["pathname"] to init["pathname"].
15959
0
    result.pathname = init.pathname;
15960
15961
    // If the following are all true:
15962
    // - baseURL is not null;
15963
    // - baseURL has an opaque path; and
15964
    // - the result of running is an absolute pathname given result["pathname"]
15965
    // and type is false,
15966
0
    if (base_url && !base_url->has_opaque_path &&
15967
0
        !url_pattern_helpers::is_absolute_pathname(*result.pathname, type)) {
15968
      // Let baseURLPath be the result of running process a base URL string
15969
      // given the result of URL path serializing baseURL and type.
15970
      // TODO: Optimization opportunity: Avoid returning a string if no slash
15971
      // exist.
15972
0
      std::string base_url_path = url_pattern_helpers::process_base_url_string(
15973
0
          base_url->get_pathname(), type);
15974
15975
      // Let slash index be the index of the last U+002F (/) code point found in
15976
      // baseURLPath, interpreted as a sequence of code points, or null if there
15977
      // are no instances of the code point.
15978
0
      auto slash_index = base_url_path.find_last_of('/');
15979
15980
      // If slash index is not null:
15981
0
      if (slash_index != std::string::npos) {
15982
        // Let new pathname be the code point substring from 0 to slash index +
15983
        // 1 within baseURLPath.
15984
0
        base_url_path.resize(slash_index + 1);
15985
        // Append result["pathname"] to the end of new pathname.
15986
0
        ADA_ASSERT_TRUE(result.pathname.has_value());
15987
0
        base_url_path.append(std::move(*result.pathname));
15988
        // Set result["pathname"] to new pathname.
15989
0
        result.pathname = std::move(base_url_path);
15990
0
      }
15991
0
    }
15992
15993
    // Set result["pathname"] to the result of process pathname for init given
15994
    // result["pathname"], result["protocol"], and type.
15995
0
    auto pathname_processing_result =
15996
0
        process_pathname(*result.pathname, result.protocol.value_or(""), type);
15997
0
    if (!pathname_processing_result) {
15998
0
      return tl::unexpected(pathname_processing_result.error());
15999
0
    }
16000
0
    result.pathname = std::move(*pathname_processing_result);
16001
0
  }
16002
16003
  // If init["search"] exists then set result["search"] to the result of process
16004
  // search for init given init["search"] and type.
16005
0
  if (init.search) {
16006
0
    auto process_result = process_search(*init.search, type);
16007
0
    if (!process_result) {
16008
0
      return tl::unexpected(process_result.error());
16009
0
    }
16010
0
    result.search = std::move(*process_result);
16011
0
  }
16012
16013
  // If init["hash"] exists then set result["hash"] to the result of process
16014
  // hash for init given init["hash"] and type.
16015
0
  if (init.hash) {
16016
0
    auto process_result = process_hash(*init.hash, type);
16017
0
    if (!process_result) {
16018
0
      return tl::unexpected(process_result.error());
16019
0
    }
16020
0
    result.hash = std::move(*process_result);
16021
0
  }
16022
  // Return result.
16023
0
  return result;
16024
0
}
16025
16026
tl::expected<std::string, errors> url_pattern_init::process_protocol(
16027
0
    std::string_view value, process_type type) {
16028
0
  ada_log("process_protocol=", value, " [", type, "]");
16029
  // Let strippedValue be the given value with a single trailing U+003A (:)
16030
  // removed, if any.
16031
0
  if (value.ends_with(":")) {
16032
0
    value.remove_suffix(1);
16033
0
  }
16034
  // If type is "pattern" then return strippedValue.
16035
0
  if (type == process_type::pattern) {
16036
0
    return std::string(value);
16037
0
  }
16038
  // Return the result of running canonicalize a protocol given strippedValue.
16039
0
  return url_pattern_helpers::canonicalize_protocol(value);
16040
0
}
16041
16042
tl::expected<std::string, errors> url_pattern_init::process_username(
16043
0
    std::string_view value, process_type type) {
16044
  // If type is "pattern" then return value.
16045
0
  if (type == process_type::pattern) {
16046
0
    return std::string(value);
16047
0
  }
16048
  // Return the result of running canonicalize a username given value.
16049
0
  return url_pattern_helpers::canonicalize_username(value);
16050
0
}
16051
16052
tl::expected<std::string, errors> url_pattern_init::process_password(
16053
0
    std::string_view value, process_type type) {
16054
  // If type is "pattern" then return value.
16055
0
  if (type == process_type::pattern) {
16056
0
    return std::string(value);
16057
0
  }
16058
  // Return the result of running canonicalize a password given value.
16059
0
  return url_pattern_helpers::canonicalize_password(value);
16060
0
}
16061
16062
tl::expected<std::string, errors> url_pattern_init::process_hostname(
16063
0
    std::string_view value, process_type type) {
16064
0
  ada_log("process_hostname value=", value, " type=", type);
16065
  // If type is "pattern" then return value.
16066
0
  if (type == process_type::pattern) {
16067
0
    return std::string(value);
16068
0
  }
16069
  // Return the result of running canonicalize a hostname given value.
16070
0
  return url_pattern_helpers::canonicalize_hostname(value);
16071
0
}
16072
16073
tl::expected<std::string, errors> url_pattern_init::process_port(
16074
0
    std::string_view port, std::string_view protocol, process_type type) {
16075
  // If type is "pattern" then return portValue.
16076
0
  if (type == process_type::pattern) {
16077
0
    return std::string(port);
16078
0
  }
16079
  // Return the result of running canonicalize a port given portValue and
16080
  // protocolValue.
16081
0
  return url_pattern_helpers::canonicalize_port_with_protocol(port, protocol);
16082
0
}
16083
16084
tl::expected<std::string, errors> url_pattern_init::process_pathname(
16085
0
    std::string_view value, std::string_view protocol, process_type type) {
16086
  // If type is "pattern" then return pathnameValue.
16087
0
  if (type == process_type::pattern) {
16088
0
    return std::string(value);
16089
0
  }
16090
16091
  // If protocolValue is a special scheme or the empty string, then return the
16092
  // result of running canonicalize a pathname given pathnameValue.
16093
0
  if (protocol.empty() || scheme::is_special(protocol)) {
16094
0
    return url_pattern_helpers::canonicalize_pathname(value);
16095
0
  }
16096
16097
  // Return the result of running canonicalize an opaque pathname given
16098
  // pathnameValue.
16099
0
  return url_pattern_helpers::canonicalize_opaque_pathname(value);
16100
0
}
16101
16102
tl::expected<std::string, errors> url_pattern_init::process_search(
16103
0
    std::string_view value, process_type type) {
16104
  // Let strippedValue be the given value with a single leading U+003F (?)
16105
  // removed, if any.
16106
0
  if (value.starts_with("?")) {
16107
0
    value.remove_prefix(1);
16108
0
  }
16109
  // We cannot assert that the value is no longer starting with a single
16110
  // question mark because technically it can start. The question is whether or
16111
  // not we should remove the first question mark. Ref:
16112
  // https://github.com/ada-url/ada/pull/992 The spec is not clear on this.
16113
16114
  // If type is "pattern" then return strippedValue.
16115
0
  if (type == process_type::pattern) {
16116
0
    return std::string(value);
16117
0
  }
16118
  // Return the result of running canonicalize a search given strippedValue.
16119
0
  return url_pattern_helpers::canonicalize_search(value);
16120
0
}
16121
16122
tl::expected<std::string, errors> url_pattern_init::process_hash(
16123
0
    std::string_view value, process_type type) {
16124
  // Let strippedValue be the given value with a single leading U+0023 (#)
16125
  // removed, if any.
16126
0
  if (value.starts_with("#")) {
16127
0
    value.remove_prefix(1);
16128
0
  }
16129
0
  ADA_ASSERT_TRUE(!value.starts_with("#"));
16130
  // If type is "pattern" then return strippedValue.
16131
0
  if (type == process_type::pattern) {
16132
0
    return std::string(value);
16133
0
  }
16134
  // Return the result of running canonicalize a hash given strippedValue.
16135
0
  return url_pattern_helpers::canonicalize_hash(value);
16136
0
}
16137
16138
}  // namespace ada
16139
16140
#endif  // ADA_INCLUDE_URL_PATTERN
16141
/* end file src/url_pattern.cpp */
16142
/* begin file src/url_pattern_helpers.cpp */
16143
#if ADA_INCLUDE_URL_PATTERN
16144
16145
#include <algorithm>
16146
#include <array>
16147
#include <charconv>
16148
#include <optional>
16149
#include <ranges>
16150
#include <string>
16151
16152
16153
namespace ada::url_pattern_helpers {
16154
16155
std::tuple<std::string, std::vector<std::string>>
16156
generate_regular_expression_and_name_list(
16157
    const std::vector<url_pattern_part>& part_list,
16158
0
    url_pattern_compile_component_options options) {
16159
  // Let result be "^"
16160
0
  std::string result = "^";
16161
  // Reserve capacity to reduce reallocations
16162
0
  result.reserve(part_list.size() * 16);
16163
16164
  // Let name list be a new list
16165
0
  std::vector<std::string> name_list{};
16166
0
  name_list.reserve(part_list.size());
16167
16168
  // Pre-generate segment wildcard regexp if needed (avoids repeated generation)
16169
0
  std::string segment_wildcard_regexp;
16170
16171
  // For each part of part list:
16172
0
  for (const url_pattern_part& part : part_list) {
16173
    // If part's type is "fixed-text":
16174
0
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
16175
      // If part's modifier is "none"
16176
0
      if (part.modifier == url_pattern_part_modifier::none) {
16177
0
        result.append(escape_regexp_string(part.value));
16178
0
      } else {
16179
        // (?:<fixed text>)<modifier>
16180
0
        result.append("(?:");
16181
0
        result.append(escape_regexp_string(part.value));
16182
0
        result.push_back(')');
16183
0
        result.append(convert_modifier_to_string(part.modifier));
16184
0
      }
16185
0
      continue;
16186
0
    }
16187
16188
    // Assert: part's name is not the empty string
16189
0
    ADA_ASSERT_TRUE(!part.name.empty());
16190
0
    name_list.push_back(part.name);
16191
16192
    // Use string_view to avoid copies where possible
16193
0
    std::string_view regexp_value = part.value;
16194
16195
0
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD) {
16196
      // Lazy generate segment wildcard regexp
16197
0
      if (segment_wildcard_regexp.empty()) {
16198
0
        segment_wildcard_regexp = generate_segment_wildcard_regexp(options);
16199
0
      }
16200
0
      regexp_value = segment_wildcard_regexp;
16201
0
    } else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
16202
0
      regexp_value = ".*";
16203
0
    }
16204
16205
    // If part's prefix is the empty string and part's suffix is the empty
16206
    // string
16207
0
    if (part.prefix.empty() && part.suffix.empty()) {
16208
      // If part's modifier is "none" or "optional"
16209
0
      if (part.modifier == url_pattern_part_modifier::none ||
16210
0
          part.modifier == url_pattern_part_modifier::optional) {
16211
        // (<regexp value>)<modifier>
16212
0
        result.push_back('(');
16213
0
        result.append(regexp_value);
16214
0
        result.push_back(')');
16215
0
        result.append(convert_modifier_to_string(part.modifier));
16216
0
      } else {
16217
        // ((?:<regexp value>)<modifier>)
16218
0
        result.append("((?:");
16219
0
        result.append(regexp_value);
16220
0
        result.push_back(')');
16221
0
        result.append(convert_modifier_to_string(part.modifier));
16222
0
        result.push_back(')');
16223
0
      }
16224
0
      continue;
16225
0
    }
16226
16227
    // If part's modifier is "none" or "optional"
16228
0
    if (part.modifier == url_pattern_part_modifier::none ||
16229
0
        part.modifier == url_pattern_part_modifier::optional) {
16230
      // (?:<prefix>(<regexp value>)<suffix>)<modifier>
16231
0
      result.append("(?:");
16232
0
      result.append(escape_regexp_string(part.prefix));
16233
0
      result.push_back('(');
16234
0
      result.append(regexp_value);
16235
0
      result.push_back(')');
16236
0
      result.append(escape_regexp_string(part.suffix));
16237
0
      result.push_back(')');
16238
0
      result.append(convert_modifier_to_string(part.modifier));
16239
0
      continue;
16240
0
    }
16241
16242
    // Assert: part's modifier is "zero-or-more" or "one-or-more"
16243
0
    ADA_ASSERT_TRUE(part.modifier == url_pattern_part_modifier::zero_or_more ||
16244
0
                    part.modifier == url_pattern_part_modifier::one_or_more);
16245
16246
    // Assert: part's prefix is not the empty string or part's suffix is not the
16247
    // empty string
16248
0
    ADA_ASSERT_TRUE(!part.prefix.empty() || !part.suffix.empty());
16249
16250
    // (?:<prefix>((?:<regexp value>)(?:<suffix><prefix>(?:<regexp
16251
    // value>))*)<suffix>)?
16252
    // Append "(?:" to the end of result.
16253
0
    result.append("(?:");
16254
    // Append the result of running escape a regexp string given part's prefix
16255
    // to the end of result.
16256
0
    result.append(escape_regexp_string(part.prefix));
16257
    // Append "((?:" to the end of result.
16258
0
    result.append("((?:");
16259
    // Append regexp value to the end of result.
16260
0
    result.append(regexp_value);
16261
    // Append ")(?:" to the end of result.
16262
0
    result.append(")(?:");
16263
    // Append the result of running escape a regexp string given part's suffix
16264
    // to the end of result.
16265
0
    result.append(escape_regexp_string(part.suffix));
16266
    // Append the result of running escape a regexp string given part's prefix
16267
    // to the end of result.
16268
0
    result.append(escape_regexp_string(part.prefix));
16269
    // Append "(?:" to the end of result.
16270
0
    result.append("(?:");
16271
    // Append regexp value to the end of result.
16272
0
    result.append(regexp_value);
16273
    // Append "))*)" to the end of result.
16274
0
    result.append("))*)");
16275
    // Append the result of running escape a regexp string given part's suffix
16276
    // to the end of result.
16277
0
    result.append(escape_regexp_string(part.suffix));
16278
    // Append ")" to the end of result.
16279
0
    result.append(")");
16280
16281
    // If part's modifier is "zero-or-more" then append "?" to the end of result
16282
0
    if (part.modifier == url_pattern_part_modifier::zero_or_more) {
16283
0
      result += "?";
16284
0
    }
16285
0
  }
16286
16287
  // Append "$" to the end of result
16288
0
  result += "$";
16289
16290
  // Return (result, name list)
16291
0
  return {std::move(result), std::move(name_list)};
16292
0
}
16293
16294
0
bool is_ipv6_address(std::string_view input) noexcept {
16295
  // If input's code point length is less than 2, then return false.
16296
0
  if (input.size() < 2) return false;
16297
16298
  // Let input code points be input interpreted as a list of code points.
16299
  // If input code points[0] is U+005B ([), then return true.
16300
0
  if (input.front() == '[') return true;
16301
  // If input code points[0] is U+007B ({) and input code points[1] is U+005B
16302
  // ([), then return true.
16303
0
  if (input.starts_with("{[")) return true;
16304
  // If input code points[0] is U+005C (\) and input code points[1] is U+005B
16305
  // ([), then return true.
16306
0
  return input.starts_with("\\[");
16307
0
}
16308
16309
std::string_view convert_modifier_to_string(
16310
0
    url_pattern_part_modifier modifier) {
16311
0
  switch (modifier) {
16312
      // If modifier is "zero-or-more", then return "*".
16313
0
    case url_pattern_part_modifier::zero_or_more:
16314
0
      return "*";
16315
    // If modifier is "optional", then return "?".
16316
0
    case url_pattern_part_modifier::optional:
16317
0
      return "?";
16318
    // If modifier is "one-or-more", then return "+".
16319
0
    case url_pattern_part_modifier::one_or_more:
16320
0
      return "+";
16321
    // Return the empty string.
16322
0
    default:
16323
0
      return "";
16324
0
  }
16325
0
}
16326
16327
std::string generate_segment_wildcard_regexp(
16328
0
    url_pattern_compile_component_options options) {
16329
  // Let result be "[^".
16330
0
  std::string result = "[^";
16331
  // Append the result of running escape a regexp string given options's
16332
  // delimiter code point to the end of result.
16333
0
  result.append(escape_regexp_string(options.get_delimiter()));
16334
  // Append "]+?" to the end of result.
16335
0
  result.append("]+?");
16336
  // Return result.
16337
0
  ada_log("generate_segment_wildcard_regexp result: ", result);
16338
0
  return result;
16339
0
}
16340
16341
namespace {
16342
// Unified lookup table for URL pattern character classification
16343
// Bit flags for different character types
16344
constexpr uint8_t CHAR_SCHEME = 1;  // valid in scheme (a-z, A-Z, 0-9, +, -, .)
16345
constexpr uint8_t CHAR_UPPER = 2;   // uppercase letter (needs lowercasing)
16346
constexpr uint8_t CHAR_SIMPLE_HOSTNAME = 4;  // simple hostname (a-z, 0-9, -, .)
16347
constexpr uint8_t CHAR_SIMPLE_PATHNAME =
16348
    8;  // simple pathname (a-z, A-Z, 0-9, /, -, _, ~)
16349
16350
constexpr std::array<uint8_t, 256> char_class_table = []() consteval {
16351
  std::array<uint8_t, 256> table{};
16352
  for (int c = 'a'; c <= 'z'; c++)
16353
    table[c] = CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME | CHAR_SIMPLE_PATHNAME;
16354
  for (int c = 'A'; c <= 'Z'; c++)
16355
    table[c] = CHAR_SCHEME | CHAR_UPPER | CHAR_SIMPLE_PATHNAME;
16356
  for (int c = '0'; c <= '9'; c++)
16357
    table[c] = CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME | CHAR_SIMPLE_PATHNAME;
16358
  table['+'] = CHAR_SCHEME;
16359
  table['-'] = CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME | CHAR_SIMPLE_PATHNAME;
16360
  table['.'] =
16361
      CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME;  // not pathname (needs normalization)
16362
  table['/'] = CHAR_SIMPLE_PATHNAME;
16363
  table['_'] = CHAR_SIMPLE_PATHNAME;
16364
  table['~'] = CHAR_SIMPLE_PATHNAME;
16365
  return table;
16366
}();
16367
}  // namespace
16368
16369
tl::expected<std::string, errors> canonicalize_protocol(
16370
0
    std::string_view input) {
16371
0
  ada_log("canonicalize_protocol called with input=", input);
16372
0
  if (input.empty()) [[unlikely]] {
16373
0
    return "";
16374
0
  }
16375
16376
0
  if (input.ends_with(":")) {
16377
0
    input.remove_suffix(1);
16378
0
  }
16379
16380
  // Fast path: special schemes are already canonical
16381
0
  if (scheme::is_special(input)) {
16382
0
    return std::string(input);
16383
0
  }
16384
16385
  // Fast path: validate scheme chars and check for uppercase
16386
  // First char must be alpha (not +, -, ., or digit)
16387
0
  uint8_t first_flags = char_class_table[static_cast<uint8_t>(input[0])];
16388
0
  if (!(first_flags & CHAR_SCHEME) || input[0] == '+' || input[0] == '-' ||
16389
0
      input[0] == '.' || unicode::is_ascii_digit(input[0])) {
16390
0
    return tl::unexpected(errors::type_error);
16391
0
  }
16392
16393
0
  uint8_t needs_lowercase = first_flags & CHAR_UPPER;
16394
0
  for (size_t i = 1; i < input.size(); i++) {
16395
0
    uint8_t flags = char_class_table[static_cast<uint8_t>(input[i])];
16396
0
    if (!(flags & CHAR_SCHEME)) {
16397
0
      return tl::unexpected(errors::type_error);
16398
0
    }
16399
0
    needs_lowercase |= flags & CHAR_UPPER;
16400
0
  }
16401
16402
0
  if (needs_lowercase == 0) {
16403
0
    return std::string(input);
16404
0
  }
16405
16406
0
  std::string result(input);
16407
0
  unicode::to_lower_ascii(result.data(), result.size());
16408
0
  return result;
16409
0
}
16410
16411
tl::expected<std::string, errors> canonicalize_username(
16412
0
    std::string_view input) {
16413
  // If value is the empty string, return value.
16414
0
  if (input.empty()) [[unlikely]] {
16415
0
    return "";
16416
0
  }
16417
  // Percent-encode the input using the userinfo percent-encode set.
16418
0
  size_t idx = ada::unicode::percent_encode_index(
16419
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
16420
0
  if (idx == input.size()) {
16421
    // No encoding needed, return input as-is
16422
0
    return std::string(input);
16423
0
  }
16424
  // Percent-encode from the first character that needs encoding
16425
0
  return ada::unicode::percent_encode(
16426
0
      input, character_sets::USERINFO_PERCENT_ENCODE, idx);
16427
0
}
16428
16429
tl::expected<std::string, errors> canonicalize_password(
16430
0
    std::string_view input) {
16431
  // If value is the empty string, return value.
16432
0
  if (input.empty()) [[unlikely]] {
16433
0
    return "";
16434
0
  }
16435
  // Percent-encode the input using the userinfo percent-encode set.
16436
0
  size_t idx = ada::unicode::percent_encode_index(
16437
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
16438
0
  if (idx == input.size()) {
16439
    // No encoding needed, return input as-is
16440
0
    return std::string(input);
16441
0
  }
16442
  // Percent-encode from the first character that needs encoding
16443
0
  return ada::unicode::percent_encode(
16444
0
      input, character_sets::USERINFO_PERCENT_ENCODE, idx);
16445
0
}
16446
16447
tl::expected<std::string, errors> canonicalize_hostname(
16448
0
    std::string_view input) {
16449
0
  ada_log("canonicalize_hostname input=", input);
16450
0
  if (input.empty()) [[unlikely]] {
16451
0
    return "";
16452
0
  }
16453
16454
  // Fast path: simple hostnames (lowercase ASCII, digits, -, .) need no IDNA
16455
0
  bool needs_processing = false;
16456
0
  for (char c : input) {
16457
0
    needs_processing |=
16458
0
        !(char_class_table[static_cast<uint8_t>(c)] & CHAR_SIMPLE_HOSTNAME);
16459
0
  }
16460
0
  if (!needs_processing) {
16461
0
    return std::string(input);
16462
0
  }
16463
16464
  // Let dummyURL be a new URL record.
16465
  // Let parseResult be the result of running the basic URL parser given value
16466
  // with dummyURL as url and hostname state as state override.
16467
16468
  // IMPORTANT: The protocol needs to be a special protocol, otherwise the
16469
  // hostname will not be converted using IDNA.
16470
0
  auto url = ada::parse<url_aggregator>("https://dummy.test", nullptr);
16471
0
  ADA_ASSERT_TRUE(url);
16472
  // if (!isValidHostnameInput(hostname)) return kj::none;
16473
0
  if (!url->set_hostname(input)) {
16474
    // If parseResult is failure, then throw a TypeError.
16475
0
    return tl::unexpected(errors::type_error);
16476
0
  }
16477
  // Return dummyURL's host, serialized, or empty string if it is null.
16478
0
  return std::string(url->get_hostname());
16479
0
}
16480
16481
tl::expected<std::string, errors> canonicalize_ipv6_hostname(
16482
0
    std::string_view input) {
16483
0
  ada_log("canonicalize_ipv6_hostname input=", input);
16484
  // TODO: Optimization opportunity: Use lookup table to speed up checking
16485
0
  if (std::ranges::any_of(input, [](char c) {
16486
0
        return c != '[' && c != ']' && c != ':' &&
16487
0
               !unicode::is_ascii_hex_digit(c);
16488
0
      })) {
16489
0
    return tl::unexpected(errors::type_error);
16490
0
  }
16491
  // Append the result of running ASCII lowercase given code point to the end of
16492
  // result.
16493
0
  auto hostname = std::string(input);
16494
0
  unicode::to_lower_ascii(hostname.data(), hostname.size());
16495
0
  return hostname;
16496
0
}
16497
16498
tl::expected<std::string, errors> canonicalize_port(
16499
0
    std::string_view port_value) {
16500
  // If portValue is the empty string, return portValue.
16501
0
  if (port_value.empty()) [[unlikely]] {
16502
0
    return "";
16503
0
  }
16504
16505
  // Remove ASCII tab or newline characters
16506
0
  std::string trimmed(port_value);
16507
0
  helpers::remove_ascii_tab_or_newline(trimmed);
16508
16509
0
  if (trimmed.empty()) {
16510
0
    return "";
16511
0
  }
16512
16513
  // Input should start with a digit character
16514
0
  if (!unicode::is_ascii_digit(trimmed.front())) {
16515
0
    return tl::unexpected(errors::type_error);
16516
0
  }
16517
16518
  // Find the first non-digit character
16519
0
  auto first_non_digit =
16520
0
      std::ranges::find_if_not(trimmed, unicode::is_ascii_digit);
16521
0
  std::string_view digits_to_parse =
16522
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
16523
16524
  // Here we have that a range of ASCII digit characters identified
16525
  // by digits_to_parse. It is none empty.
16526
  // We want to determine whether it is a valid port number (0-65535).
16527
  // Clearly, if the length is greater than 5, it is invalid.
16528
  // If the length is 5, we need to compare lexicographically to "65535".
16529
  // Otherwise it is valid.
16530
0
  if (digits_to_parse.size() == 5) {
16531
0
    if (digits_to_parse > "65535") {
16532
0
      return tl::unexpected(errors::type_error);
16533
0
    }
16534
0
  } else if (digits_to_parse.size() > 5) {
16535
0
    return tl::unexpected(errors::type_error);
16536
0
  }
16537
0
  if (digits_to_parse[0] == '0' && digits_to_parse.size() > 1) {
16538
    // Leading zeros are not allowed for multi-digit ports
16539
0
    return tl::unexpected(errors::type_error);
16540
0
  }
16541
  // It is valid! Most times, we do not need to parse it into an integer.
16542
0
  return std::string(digits_to_parse);
16543
0
}
16544
16545
tl::expected<std::string, errors> canonicalize_port_with_protocol(
16546
0
    std::string_view port_value, std::string_view protocol) {
16547
  // If portValue is the empty string, return portValue.
16548
0
  if (port_value.empty()) [[unlikely]] {
16549
0
    return "";
16550
0
  }
16551
16552
  // Handle empty or trailing colon in protocol
16553
0
  if (protocol.empty()) {
16554
0
    protocol = "fake";
16555
0
  } else if (protocol.ends_with(":")) {
16556
0
    protocol.remove_suffix(1);
16557
0
  }
16558
16559
  // Remove ASCII tab or newline characters
16560
0
  std::string trimmed(port_value);
16561
0
  helpers::remove_ascii_tab_or_newline(trimmed);
16562
16563
0
  if (trimmed.empty()) {
16564
0
    return "";
16565
0
  }
16566
16567
  // Input should start with a digit character
16568
0
  if (!unicode::is_ascii_digit(trimmed.front())) {
16569
0
    return tl::unexpected(errors::type_error);
16570
0
  }
16571
16572
  // Find the first non-digit character
16573
0
  auto first_non_digit =
16574
0
      std::ranges::find_if_not(trimmed, unicode::is_ascii_digit);
16575
0
  std::string_view digits_to_parse =
16576
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
16577
16578
  // Parse the port number
16579
0
  uint16_t parsed_port{};
16580
0
  auto result = std::from_chars(digits_to_parse.data(),
16581
0
                                digits_to_parse.data() + digits_to_parse.size(),
16582
0
                                parsed_port);
16583
16584
0
  if (result.ec == std::errc::result_out_of_range) {
16585
0
    return tl::unexpected(errors::type_error);
16586
0
  }
16587
16588
0
  if (result.ec == std::errc()) {
16589
    // Check if this is the default port for the scheme
16590
0
    uint16_t default_port = scheme::get_special_port(protocol);
16591
16592
    // If it's the default port for a special scheme, return empty string
16593
0
    if (default_port != 0 && default_port == parsed_port) {
16594
0
      return "";
16595
0
    }
16596
16597
    // Successfully parsed, return as string
16598
0
    return std::to_string(parsed_port);
16599
0
  }
16600
16601
0
  return tl::unexpected(errors::type_error);
16602
0
}
16603
16604
tl::expected<std::string, errors> canonicalize_pathname(
16605
0
    std::string_view input) {
16606
0
  if (input.empty()) [[unlikely]] {
16607
0
    return "";
16608
0
  }
16609
16610
  // Fast path: simple pathnames (no . which needs normalization) can be
16611
  // returned as-is
16612
0
  bool needs_processing = false;
16613
0
  for (char c : input) {
16614
0
    needs_processing |=
16615
0
        !(char_class_table[static_cast<uint8_t>(c)] & CHAR_SIMPLE_PATHNAME);
16616
0
  }
16617
0
  if (!needs_processing) {
16618
0
    return std::string(input);
16619
0
  }
16620
16621
  // Let leading slash be true if the first code point in value is U+002F (/)
16622
  // and otherwise false.
16623
0
  const bool leading_slash = input.starts_with("/");
16624
  // Let modified value be "/-" if leading slash is false and otherwise the
16625
  // empty string.
16626
0
  const auto modified_value = leading_slash ? "" : "/-";
16627
0
  const auto full_url =
16628
0
      std::string("fake://fake-url") + modified_value + std::string(input);
16629
0
  if (auto url = ada::parse<url_aggregator>(full_url, nullptr)) {
16630
0
    const auto pathname = url->get_pathname();
16631
    // If leading slash is false, then set result to the code point substring
16632
    // from 2 to the end of the string within result.
16633
0
    return leading_slash ? std::string(pathname)
16634
0
                         : std::string(pathname.substr(2));
16635
0
  }
16636
  // If parseResult is failure, then throw a TypeError.
16637
0
  return tl::unexpected(errors::type_error);
16638
0
}
16639
16640
tl::expected<std::string, errors> canonicalize_opaque_pathname(
16641
0
    std::string_view input) {
16642
  // If value is the empty string, return value.
16643
0
  if (input.empty()) [[unlikely]] {
16644
0
    return "";
16645
0
  }
16646
  // Let dummyURL be a new URL record.
16647
  // Set dummyURL's path to the empty string.
16648
  // Let parseResult be the result of running URL parsing given value with
16649
  // dummyURL as url and opaque path state as state override.
16650
0
  if (auto url =
16651
0
          ada::parse<url_aggregator>("fake:" + std::string(input), nullptr)) {
16652
    // Return the result of URL path serializing dummyURL.
16653
0
    return std::string(url->get_pathname());
16654
0
  }
16655
  // If parseResult is failure, then throw a TypeError.
16656
0
  return tl::unexpected(errors::type_error);
16657
0
}
16658
16659
0
tl::expected<std::string, errors> canonicalize_search(std::string_view input) {
16660
  // If value is the empty string, return value.
16661
0
  if (input.empty()) [[unlikely]] {
16662
0
    return "";
16663
0
  }
16664
  // Remove leading '?' if present
16665
0
  std::string new_value;
16666
0
  new_value = input[0] == '?' ? input.substr(1) : input;
16667
  // Remove ASCII tab or newline characters
16668
0
  helpers::remove_ascii_tab_or_newline(new_value);
16669
16670
0
  if (new_value.empty()) {
16671
0
    return "";
16672
0
  }
16673
16674
  // Percent-encode using QUERY_PERCENT_ENCODE (for non-special URLs)
16675
  // Note: "fake://dummy.test" is not a special URL, so we use
16676
  // QUERY_PERCENT_ENCODE
16677
0
  size_t idx = ada::unicode::percent_encode_index(
16678
0
      new_value, character_sets::QUERY_PERCENT_ENCODE);
16679
0
  if (idx == new_value.size()) {
16680
    // No encoding needed
16681
0
    return new_value;
16682
0
  }
16683
  // Percent-encode from the first character that needs encoding
16684
0
  return ada::unicode::percent_encode(
16685
0
      new_value, character_sets::QUERY_PERCENT_ENCODE, idx);
16686
0
}
16687
16688
0
tl::expected<std::string, errors> canonicalize_hash(std::string_view input) {
16689
  // If value is the empty string, return value.
16690
0
  if (input.empty()) [[unlikely]] {
16691
0
    return "";
16692
0
  }
16693
  // Remove leading '#' if present
16694
0
  std::string new_value;
16695
0
  new_value = input[0] == '#' ? input.substr(1) : input;
16696
  // Remove ASCII tab or newline characters
16697
0
  helpers::remove_ascii_tab_or_newline(new_value);
16698
16699
0
  if (new_value.empty()) {
16700
0
    return "";
16701
0
  }
16702
16703
  // Percent-encode using FRAGMENT_PERCENT_ENCODE
16704
0
  size_t idx = ada::unicode::percent_encode_index(
16705
0
      new_value, character_sets::FRAGMENT_PERCENT_ENCODE);
16706
0
  if (idx == new_value.size()) {
16707
    // No encoding needed
16708
0
    return new_value;
16709
0
  }
16710
  // Percent-encode from the first character that needs encoding
16711
0
  return ada::unicode::percent_encode(
16712
0
      new_value, character_sets::FRAGMENT_PERCENT_ENCODE, idx);
16713
0
}
16714
16715
tl::expected<std::vector<token>, errors> tokenize(std::string_view input,
16716
0
                                                  token_policy policy) {
16717
0
  ada_log("tokenize input: ", input);
16718
  // Let tokenizer be a new tokenizer.
16719
  // Set tokenizer's input to input.
16720
  // Set tokenizer's policy to policy.
16721
0
  auto tokenizer = Tokenizer(input, policy);
16722
  // While tokenizer's index is less than tokenizer's input's code point length:
16723
0
  while (tokenizer.index < tokenizer.input.size()) {
16724
    // Run seek and get the next code point given tokenizer and tokenizer's
16725
    // index.
16726
0
    tokenizer.seek_and_get_next_code_point(tokenizer.index);
16727
16728
    // If tokenizer's code point is U+002A (*):
16729
0
    if (tokenizer.code_point == '*') {
16730
      // Run add a token with default position and length given tokenizer and
16731
      // "asterisk".
16732
0
      tokenizer.add_token_with_defaults(token_type::ASTERISK);
16733
0
      ada_log("add ASTERISK token");
16734
      // Continue.
16735
0
      continue;
16736
0
    }
16737
16738
    // If tokenizer's code point is U+002B (+) or U+003F (?):
16739
0
    if (tokenizer.code_point == '+' || tokenizer.code_point == '?') {
16740
      // Run add a token with default position and length given tokenizer and
16741
      // "other-modifier".
16742
0
      tokenizer.add_token_with_defaults(token_type::OTHER_MODIFIER);
16743
      // Continue.
16744
0
      continue;
16745
0
    }
16746
16747
    // If tokenizer's code point is U+005C (\):
16748
0
    if (tokenizer.code_point == '\\') {
16749
      // If tokenizer's index is equal to tokenizer's input's code point length
16750
      // - 1:
16751
0
      if (tokenizer.index == tokenizer.input.size() - 1) {
16752
        // Run process a tokenizing error given tokenizer, tokenizer's next
16753
        // index, and tokenizer's index.
16754
0
        if (auto error = tokenizer.process_tokenizing_error(
16755
0
                tokenizer.next_index, tokenizer.index)) {
16756
0
          ada_log("process_tokenizing_error failed");
16757
0
          return tl::unexpected(*error);
16758
0
        }
16759
0
        continue;
16760
0
      }
16761
16762
      // Let escaped index be tokenizer's next index.
16763
0
      auto escaped_index = tokenizer.next_index;
16764
      // Run get the next code point given tokenizer.
16765
0
      tokenizer.get_next_code_point();
16766
      // Run add a token with default length given tokenizer, "escaped-char",
16767
      // tokenizer's next index, and escaped index.
16768
0
      tokenizer.add_token_with_default_length(
16769
0
          token_type::ESCAPED_CHAR, tokenizer.next_index, escaped_index);
16770
0
      ada_log("add ESCAPED_CHAR token on next_index ", tokenizer.next_index,
16771
0
              " with escaped index ", escaped_index);
16772
      // Continue.
16773
0
      continue;
16774
0
    }
16775
16776
    // If tokenizer's code point is U+007B ({):
16777
0
    if (tokenizer.code_point == '{') {
16778
      // Run add a token with default position and length given tokenizer and
16779
      // "open".
16780
0
      tokenizer.add_token_with_defaults(token_type::OPEN);
16781
0
      ada_log("add OPEN token");
16782
0
      continue;
16783
0
    }
16784
16785
    // If tokenizer's code point is U+007D (}):
16786
0
    if (tokenizer.code_point == '}') {
16787
      // Run add a token with default position and length given tokenizer and
16788
      // "close".
16789
0
      tokenizer.add_token_with_defaults(token_type::CLOSE);
16790
0
      ada_log("add CLOSE token");
16791
0
      continue;
16792
0
    }
16793
16794
    // If tokenizer's code point is U+003A (:):
16795
0
    if (tokenizer.code_point == ':') {
16796
      // Let name position be tokenizer's next index.
16797
0
      auto name_position = tokenizer.next_index;
16798
      // Let name start be name position.
16799
0
      auto name_start = name_position;
16800
      // While name position is less than tokenizer's input's code point length:
16801
0
      while (name_position < tokenizer.input.size()) {
16802
        // Run seek and get the next code point given tokenizer and name
16803
        // position.
16804
0
        tokenizer.seek_and_get_next_code_point(name_position);
16805
        // Let first code point be true if name position equals name start and
16806
        // false otherwise.
16807
0
        bool first_code_point = name_position == name_start;
16808
        // Let valid code point be the result of running is a valid name code
16809
        // point given tokenizer's code point and first code point.
16810
0
        auto valid_code_point =
16811
0
            idna::valid_name_code_point(tokenizer.code_point, first_code_point);
16812
0
        ada_log("tokenizer.code_point=", uint32_t(tokenizer.code_point),
16813
0
                " first_code_point=", first_code_point,
16814
0
                " valid_code_point=", valid_code_point);
16815
        // If valid code point is false break.
16816
0
        if (!valid_code_point) break;
16817
        // Set name position to tokenizer's next index.
16818
0
        name_position = tokenizer.next_index;
16819
0
      }
16820
16821
      // If name position is less than or equal to name start:
16822
0
      if (name_position <= name_start) {
16823
        // Run process a tokenizing error given tokenizer, name start, and
16824
        // tokenizer's index.
16825
0
        if (auto error = tokenizer.process_tokenizing_error(name_start,
16826
0
                                                            tokenizer.index)) {
16827
0
          ada_log("process_tokenizing_error failed");
16828
0
          return tl::unexpected(*error);
16829
0
        }
16830
        // Continue
16831
0
        continue;
16832
0
      }
16833
16834
      // Run add a token with default length given tokenizer, "name", name
16835
      // position, and name start.
16836
0
      tokenizer.add_token_with_default_length(token_type::NAME, name_position,
16837
0
                                              name_start);
16838
0
      continue;
16839
0
    }
16840
16841
    // If tokenizer's code point is U+0028 (():
16842
0
    if (tokenizer.code_point == '(') {
16843
      // Let depth be 1.
16844
0
      size_t depth = 1;
16845
      // Let regexp position be tokenizer's next index.
16846
0
      auto regexp_position = tokenizer.next_index;
16847
      // Let regexp start be regexp position.
16848
0
      auto regexp_start = regexp_position;
16849
      // Let error be false.
16850
0
      bool error = false;
16851
16852
      // While regexp position is less than tokenizer's input's code point
16853
      // length:
16854
0
      while (regexp_position < tokenizer.input.size()) {
16855
        // Run seek and get the next code point given tokenizer and regexp
16856
        // position.
16857
0
        tokenizer.seek_and_get_next_code_point(regexp_position);
16858
16859
        // TODO: Optimization opportunity: The next 2 if statements can be
16860
        // merged. If the result of running is ASCII given tokenizer's code
16861
        // point is false:
16862
0
        if (!unicode::is_ascii(tokenizer.code_point)) {
16863
          // Run process a tokenizing error given tokenizer, regexp start, and
16864
          // tokenizer's index.
16865
0
          if (auto process_error = tokenizer.process_tokenizing_error(
16866
0
                  regexp_start, tokenizer.index)) {
16867
0
            return tl::unexpected(*process_error);
16868
0
          }
16869
          // Set error to true.
16870
0
          error = true;
16871
0
          break;
16872
0
        }
16873
16874
        // If regexp position equals regexp start and tokenizer's code point is
16875
        // U+003F (?):
16876
0
        if (regexp_position == regexp_start && tokenizer.code_point == '?') {
16877
          // Run process a tokenizing error given tokenizer, regexp start, and
16878
          // tokenizer's index.
16879
0
          if (auto process_error = tokenizer.process_tokenizing_error(
16880
0
                  regexp_start, tokenizer.index)) {
16881
0
            return tl::unexpected(*process_error);
16882
0
          }
16883
          // Set error to true;
16884
0
          error = true;
16885
0
          break;
16886
0
        }
16887
16888
        // If tokenizer's code point is U+005C (\):
16889
0
        if (tokenizer.code_point == '\\') {
16890
          // If regexp position equals tokenizer's input's code point length - 1
16891
0
          if (regexp_position == tokenizer.input.size() - 1) {
16892
            // Run process a tokenizing error given tokenizer, regexp start, and
16893
            // tokenizer's index.
16894
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16895
0
                    regexp_start, tokenizer.index)) {
16896
0
              return tl::unexpected(*process_error);
16897
0
            }
16898
            // Set error to true.
16899
0
            error = true;
16900
0
            break;
16901
0
          }
16902
          // Run get the next code point given tokenizer.
16903
0
          tokenizer.get_next_code_point();
16904
          // If the result of running is ASCII given tokenizer's code point is
16905
          // false:
16906
0
          if (!unicode::is_ascii(tokenizer.code_point)) {
16907
            // Run process a tokenizing error given tokenizer, regexp start, and
16908
            // tokenizer's index.
16909
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16910
0
                    regexp_start, tokenizer.index);
16911
0
                process_error.has_value()) {
16912
0
              return tl::unexpected(*process_error);
16913
0
            }
16914
            // Set error to true.
16915
0
            error = true;
16916
0
            break;
16917
0
          }
16918
          // Set regexp position to tokenizer's next index.
16919
0
          regexp_position = tokenizer.next_index;
16920
0
          continue;
16921
0
        }
16922
16923
        // If tokenizer's code point is U+0029 ()):
16924
0
        if (tokenizer.code_point == ')') {
16925
          // Decrement depth by 1.
16926
0
          depth--;
16927
          // If depth is 0:
16928
0
          if (depth == 0) {
16929
            // Set regexp position to tokenizer's next index.
16930
0
            regexp_position = tokenizer.next_index;
16931
            // Break.
16932
0
            break;
16933
0
          }
16934
0
        } else if (tokenizer.code_point == '(') {
16935
          // Otherwise if tokenizer's code point is U+0028 (():
16936
          // Increment depth by 1.
16937
0
          depth++;
16938
          // If regexp position equals tokenizer's input's code point length -
16939
          // 1:
16940
0
          if (regexp_position == tokenizer.input.size() - 1) {
16941
            // Run process a tokenizing error given tokenizer, regexp start, and
16942
            // tokenizer's index.
16943
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16944
0
                    regexp_start, tokenizer.index)) {
16945
0
              return tl::unexpected(*process_error);
16946
0
            }
16947
            // Set error to true.
16948
0
            error = true;
16949
0
            break;
16950
0
          }
16951
          // Let temporary position be tokenizer's next index.
16952
0
          auto temporary_position = tokenizer.next_index;
16953
          // Run get the next code point given tokenizer.
16954
0
          tokenizer.get_next_code_point();
16955
          // If tokenizer's code point is not U+003F (?):
16956
0
          if (tokenizer.code_point != '?') {
16957
            // Run process a tokenizing error given tokenizer, regexp start, and
16958
            // tokenizer's index.
16959
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16960
0
                    regexp_start, tokenizer.index)) {
16961
0
              return tl::unexpected(*process_error);
16962
0
            }
16963
            // Set error to true.
16964
0
            error = true;
16965
0
            break;
16966
0
          }
16967
          // Set tokenizer's next index to temporary position.
16968
0
          tokenizer.next_index = temporary_position;
16969
0
        }
16970
        // Set regexp position to tokenizer's next index.
16971
0
        regexp_position = tokenizer.next_index;
16972
0
      }
16973
16974
      // If error is true continue.
16975
0
      if (error) continue;
16976
      // If depth is not zero:
16977
0
      if (depth != 0) {
16978
        // Run process a tokenizing error given tokenizer, regexp start, and
16979
        // tokenizer's index.
16980
0
        if (auto process_error = tokenizer.process_tokenizing_error(
16981
0
                regexp_start, tokenizer.index)) {
16982
0
          return tl::unexpected(*process_error);
16983
0
        }
16984
0
        continue;
16985
0
      }
16986
      // Let regexp length be regexp position - regexp start - 1.
16987
0
      auto regexp_length = regexp_position - regexp_start - 1;
16988
      // If regexp length is zero:
16989
0
      if (regexp_length == 0) {
16990
        // Run process a tokenizing error given tokenizer, regexp start, and
16991
        // tokenizer's index.
16992
0
        if (auto process_error = tokenizer.process_tokenizing_error(
16993
0
                regexp_start, tokenizer.index)) {
16994
0
          ada_log("process_tokenizing_error failed");
16995
0
          return tl::unexpected(*process_error);
16996
0
        }
16997
0
        continue;
16998
0
      }
16999
      // Run add a token given tokenizer, "regexp", regexp position, regexp
17000
      // start, and regexp length.
17001
0
      tokenizer.add_token(token_type::REGEXP, regexp_position, regexp_start,
17002
0
                          regexp_length);
17003
0
      continue;
17004
0
    }
17005
    // Run add a token with default position and length given tokenizer and
17006
    // "char".
17007
0
    tokenizer.add_token_with_defaults(token_type::CHAR);
17008
0
  }
17009
  // Run add a token with default length given tokenizer, "end", tokenizer's
17010
  // index, and tokenizer's index.
17011
0
  tokenizer.add_token_with_default_length(token_type::END, tokenizer.index,
17012
0
                                          tokenizer.index);
17013
17014
0
  ada_log("tokenizer.token_list size is: ", tokenizer.token_list.size());
17015
  // Return tokenizer's token list.
17016
0
  return tokenizer.token_list;
17017
0
}
17018
17019
namespace {
17020
constexpr std::array<uint8_t, 256> escape_pattern_table = []() consteval {
17021
  std::array<uint8_t, 256> out{};
17022
  for (auto& c : {'+', '*', '?', ':', '{', '}', '(', ')', '\\'}) {
17023
    out[c] = 1;
17024
  }
17025
  return out;
17026
}();
17027
17028
0
constexpr bool should_escape_pattern_char(char c) {
17029
0
  return escape_pattern_table[static_cast<uint8_t>(c)];
17030
0
}
17031
}  // namespace
17032
17033
0
std::string escape_pattern_string(std::string_view input) {
17034
0
  ada_log("escape_pattern_string called with input=", input);
17035
0
  if (input.empty()) [[unlikely]] {
17036
0
    return "";
17037
0
  }
17038
  // Assert: input is an ASCII string.
17039
0
  ADA_ASSERT_TRUE(ada::idna::is_ascii(input));
17040
  // Let result be the empty string.
17041
0
  std::string result{};
17042
  // Reserve extra space for potential escapes
17043
0
  result.reserve(input.size() * 2);
17044
17045
  // While index is less than input's length:
17046
0
  for (const char c : input) {
17047
0
    if (should_escape_pattern_char(c)) {
17048
      // Append U+005C (\) to the end of result.
17049
0
      result.push_back('\\');
17050
0
    }
17051
    // Append c to the end of result.
17052
0
    result.push_back(c);
17053
0
  }
17054
  // Return result.
17055
0
  return result;
17056
0
}
17057
17058
namespace {
17059
constexpr std::array<uint8_t, 256> escape_regexp_table = []() consteval {
17060
  std::array<uint8_t, 256> out{};
17061
  for (auto& c : {'.', '+', '*', '?', '^', '$', '{', '}', '(', ')', '[', ']',
17062
                  '|', '/', '\\'}) {
17063
    out[c] = 1;
17064
  }
17065
  return out;
17066
}();
17067
17068
0
constexpr bool should_escape_regexp_char(char c) {
17069
0
  return escape_regexp_table[(uint8_t)c];
17070
0
}
17071
}  // namespace
17072
17073
0
std::string escape_regexp_string(std::string_view input) {
17074
  // Assert: input is an ASCII string.
17075
0
  ADA_ASSERT_TRUE(idna::is_ascii(input));
17076
  // Let result be the empty string.
17077
0
  std::string result{};
17078
  // Reserve extra space for potential escapes (worst case: all chars escaped)
17079
0
  result.reserve(input.size() * 2);
17080
0
  for (const char c : input) {
17081
0
    if (should_escape_regexp_char(c)) {
17082
      // Avoid temporary string allocation - directly append characters
17083
0
      result.push_back('\\');
17084
0
      result.push_back(c);
17085
0
    } else {
17086
0
      result.push_back(c);
17087
0
    }
17088
0
  }
17089
0
  return result;
17090
0
}
17091
17092
std::string process_base_url_string(std::string_view input,
17093
0
                                    url_pattern_init::process_type type) {
17094
  // If type is not "pattern" return input.
17095
0
  if (type != url_pattern_init::process_type::pattern) {
17096
0
    return std::string(input);
17097
0
  }
17098
  // Return the result of escaping a pattern string given input.
17099
0
  return escape_pattern_string(input);
17100
0
}
17101
17102
constexpr bool is_absolute_pathname(
17103
0
    std::string_view input, url_pattern_init::process_type type) noexcept {
17104
  // If input is the empty string, then return false.
17105
0
  if (input.empty()) [[unlikely]] {
17106
0
    return false;
17107
0
  }
17108
  // If input[0] is U+002F (/), then return true.
17109
0
  if (input.starts_with("/")) return true;
17110
  // If type is "url", then return false.
17111
0
  if (type == url_pattern_init::process_type::url) return false;
17112
  // If input's code point length is less than 2, then return false.
17113
0
  if (input.size() < 2) return false;
17114
  // If input[0] is U+005C (\) and input[1] is U+002F (/), then return true.
17115
  // If input[0] is U+007B ({) and input[1] is U+002F (/), then return true.
17116
  // Return false.
17117
0
  return input[1] == '/' && (input[0] == '\\' || input[0] == '{');
17118
0
}
17119
17120
std::string generate_pattern_string(
17121
    std::vector<url_pattern_part>& part_list,
17122
0
    url_pattern_compile_component_options& options) {
17123
  // Let result be the empty string.
17124
0
  std::string result{};
17125
  // Let index list be the result of getting the indices for part list.
17126
  // For each index of index list:
17127
0
  for (size_t index = 0; index < part_list.size(); index++) {
17128
    // Let part be part list[index].
17129
    // Use reference to avoid copy
17130
0
    const auto& part = part_list[index];
17131
    // Let previous part be part list[index - 1] if index is greater than 0,
17132
    // otherwise let it be null.
17133
    // Use pointer to avoid copy
17134
0
    const url_pattern_part* previous_part =
17135
0
        index == 0 ? nullptr : &part_list[index - 1];
17136
    // Let next part be part list[index + 1] if index is less than index list's
17137
    // size - 1, otherwise let it be null.
17138
0
    const url_pattern_part* next_part =
17139
0
        index < part_list.size() - 1 ? &part_list[index + 1] : nullptr;
17140
    // If part's type is "fixed-text" then:
17141
0
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
17142
      // If part's modifier is "none" then:
17143
0
      if (part.modifier == url_pattern_part_modifier::none) {
17144
        // Append the result of running escape a pattern string given part's
17145
        // value to the end of result.
17146
0
        result.append(escape_pattern_string(part.value));
17147
0
        continue;
17148
0
      }
17149
      // Append "{" to the end of result.
17150
0
      result += "{";
17151
      // Append the result of running escape a pattern string given part's value
17152
      // to the end of result.
17153
0
      result.append(escape_pattern_string(part.value));
17154
      // Append "}" to the end of result.
17155
0
      result += "}";
17156
      // Append the result of running convert a modifier to a string given
17157
      // part's modifier to the end of result.
17158
0
      result.append(convert_modifier_to_string(part.modifier));
17159
0
      continue;
17160
0
    }
17161
    // Let custom name be true if part's name[0] is not an ASCII digit;
17162
    // otherwise false.
17163
0
    bool custom_name = !unicode::is_ascii_digit(part.name[0]);
17164
    // Let needs grouping be true if at least one of the following are true,
17165
    // otherwise let it be false:
17166
    // - part's suffix is not the empty string.
17167
    // - part's prefix is not the empty string and is not options's prefix code
17168
    // point.
17169
0
    bool needs_grouping =
17170
0
        !part.suffix.empty() ||
17171
0
        (!part.prefix.empty() && part.prefix[0] != options.get_prefix()[0]);
17172
17173
    // If all of the following are true:
17174
    // - needs grouping is false; and
17175
    // - custom name is true; and
17176
    // - part's type is "segment-wildcard"; and
17177
    // - part's modifier is "none"; and
17178
    // - next part is not null; and
17179
    // - next part's prefix is the empty string; and
17180
    // - next part's suffix is the empty string
17181
0
    if (!needs_grouping && custom_name &&
17182
0
        part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
17183
0
        part.modifier == url_pattern_part_modifier::none && next_part &&
17184
0
        next_part->prefix.empty() && next_part->suffix.empty()) {
17185
      // If next part's type is "fixed-text":
17186
0
      if (next_part->type == url_pattern_part_type::FIXED_TEXT) {
17187
        // Set needs grouping to true if the result of running is a valid name
17188
        // code point given next part's value's first code point and the boolean
17189
        // false is true.
17190
0
        if (idna::valid_name_code_point(next_part->value[0], false)) {
17191
0
          needs_grouping = true;
17192
0
        }
17193
0
      } else {
17194
        // Set needs grouping to true if next part's name[0] is an ASCII digit.
17195
0
        needs_grouping = !next_part->name.empty() &&
17196
0
                         unicode::is_ascii_digit(next_part->name[0]);
17197
0
      }
17198
0
    }
17199
17200
    // If all of the following are true:
17201
    // - needs grouping is false; and
17202
    // - part's prefix is the empty string; and
17203
    // - previous part is not null; and
17204
    // - previous part's type is "fixed-text"; and
17205
    // - previous part's value's last code point is options's prefix code point.
17206
    // then set needs grouping to true.
17207
0
    if (!needs_grouping && part.prefix.empty() && previous_part &&
17208
0
        previous_part->type == url_pattern_part_type::FIXED_TEXT &&
17209
0
        !options.get_prefix().empty() &&
17210
0
        previous_part->value.at(previous_part->value.size() - 1) ==
17211
0
            options.get_prefix()[0]) {
17212
0
      needs_grouping = true;
17213
0
    }
17214
17215
    // Assert: part's name is not the empty string or null.
17216
0
    ADA_ASSERT_TRUE(!part.name.empty());
17217
17218
    // If needs grouping is true, then append "{" to the end of result.
17219
0
    if (needs_grouping) {
17220
0
      result.append("{");
17221
0
    }
17222
17223
    // Append the result of running escape a pattern string given part's prefix
17224
    // to the end of result.
17225
0
    result.append(escape_pattern_string(part.prefix));
17226
17227
    // If custom name is true:
17228
0
    if (custom_name) {
17229
      // Append ":" to the end of result.
17230
0
      result.append(":");
17231
      // Append part's name to the end of result.
17232
0
      result.append(part.name);
17233
0
    }
17234
17235
    // If part's type is "regexp" then:
17236
0
    if (part.type == url_pattern_part_type::REGEXP) {
17237
      // Append "(" to the end of result.
17238
0
      result.append("(");
17239
      // Append part's value to the end of result.
17240
0
      result.append(part.value);
17241
      // Append ")" to the end of result.
17242
0
      result.append(")");
17243
0
    } else if (part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
17244
0
               !custom_name) {
17245
      // Otherwise if part's type is "segment-wildcard" and custom name is
17246
      // false: Append "(" to the end of result.
17247
0
      result.append("(");
17248
      // Append the result of running generate a segment wildcard regexp given
17249
      // options to the end of result.
17250
0
      result.append(generate_segment_wildcard_regexp(options));
17251
      // Append ")" to the end of result.
17252
0
      result.append(")");
17253
0
    } else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
17254
      // Otherwise if part's type is "full-wildcard":
17255
      // If custom name is false and one of the following is true:
17256
      // - previous part is null; or
17257
      // - previous part's type is "fixed-text"; or
17258
      // - previous part's modifier is not "none"; or
17259
      // - needs grouping is true; or
17260
      // - part's prefix is not the empty string
17261
      // - then append "*" to the end of result.
17262
0
      if (!custom_name &&
17263
0
          (!previous_part ||
17264
0
           previous_part->type == url_pattern_part_type::FIXED_TEXT ||
17265
0
           previous_part->modifier != url_pattern_part_modifier::none ||
17266
0
           needs_grouping || !part.prefix.empty())) {
17267
0
        result.append("*");
17268
0
      } else {
17269
        // Append "(" to the end of result.
17270
        // Append full wildcard regexp value to the end of result.
17271
        // Append ")" to the end of result.
17272
0
        result.append("(.*)");
17273
0
      }
17274
0
    }
17275
17276
    // If all of the following are true:
17277
    // - part's type is "segment-wildcard"; and
17278
    // - custom name is true; and
17279
    // - part's suffix is not the empty string; and
17280
    // - The result of running is a valid name code point given part's suffix's
17281
    // first code point and the boolean false is true then append U+005C (\) to
17282
    // the end of result.
17283
0
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD && custom_name &&
17284
0
        !part.suffix.empty() &&
17285
0
        idna::valid_name_code_point(part.suffix[0], false)) {
17286
0
      result.append("\\");
17287
0
    }
17288
17289
    // Append the result of running escape a pattern string given part's suffix
17290
    // to the end of result.
17291
0
    result.append(escape_pattern_string(part.suffix));
17292
    // If needs grouping is true, then append "}" to the end of result.
17293
0
    if (needs_grouping) result.append("}");
17294
    // Append the result of running convert a modifier to a string given part's
17295
    // modifier to the end of result.
17296
0
    result.append(convert_modifier_to_string(part.modifier));
17297
0
  }
17298
  // Return result.
17299
0
  return result;
17300
0
}
17301
}  // namespace ada::url_pattern_helpers
17302
17303
#endif  // ADA_INCLUDE_URL_PATTERN
17304
/* end file src/url_pattern_helpers.cpp */
17305
/* begin file src/url_pattern_regex.cpp */
17306
#if ADA_INCLUDE_URL_PATTERN
17307
17308
17309
namespace ada::url_pattern_regex {
17310
17311
#ifdef ADA_USE_UNSAFE_STD_REGEX_PROVIDER
17312
std::optional<std::regex> std_regex_provider::create_instance(
17313
    std::string_view pattern, bool ignore_case) {
17314
  // Let flags be an empty string.
17315
  // If options's ignore case is true then set flags to "vi".
17316
  // Otherwise set flags to "v"
17317
  auto flags = ignore_case
17318
                   ? std::regex::icase | std::regex_constants::ECMAScript
17319
                   : std::regex_constants::ECMAScript;
17320
  try {
17321
    return std::regex(pattern.data(), pattern.size(), flags);
17322
  } catch (const std::regex_error& e) {
17323
    (void)e;
17324
    ada_log("std_regex_provider::create_instance failed:", e.what());
17325
    return std::nullopt;
17326
  }
17327
}
17328
17329
std::optional<std::vector<std::optional<std::string>>>
17330
std_regex_provider::regex_search(std::string_view input,
17331
                                 const std::regex& pattern) {
17332
  // Use iterator-based regex_search to avoid string allocation
17333
  std::match_results<std::string_view::const_iterator> match_result;
17334
  if (!std::regex_search(input.begin(), input.end(), match_result, pattern,
17335
                         std::regex_constants::match_any)) {
17336
    return std::nullopt;
17337
  }
17338
  std::vector<std::optional<std::string>> matches;
17339
  // If input is empty, let's assume the result will be empty as well.
17340
  if (input.empty() || match_result.empty()) {
17341
    return matches;
17342
  }
17343
  matches.reserve(match_result.size());
17344
  for (size_t i = 1; i < match_result.size(); ++i) {
17345
    if (auto entry = match_result[i]; entry.matched) {
17346
      matches.emplace_back(entry.str());
17347
    }
17348
  }
17349
  return matches;
17350
}
17351
17352
bool std_regex_provider::regex_match(std::string_view input,
17353
                                     const std::regex& pattern) {
17354
  return std::regex_match(input.begin(), input.end(), pattern);
17355
}
17356
17357
#endif  // ADA_USE_UNSAFE_STD_REGEX_PROVIDER
17358
17359
}  // namespace ada::url_pattern_regex
17360
17361
#endif  // ADA_INCLUDE_URL_PATTERN
17362
/* end file src/url_pattern_regex.cpp */
17363
#endif  // ADA_INCLUDE_URL_PATTERN
17364
17365
/* begin file src/ada_c.cpp */
17366
17367
0
ada::result<ada::url_aggregator>& get_instance(void* result) noexcept {
17368
0
  return *(ada::result<ada::url_aggregator>*)result;
17369
0
}
17370
17371
extern "C" {
17372
typedef void* ada_url;
17373
typedef void* ada_url_search_params;
17374
typedef void* ada_strings;
17375
typedef void* ada_url_search_params_keys_iter;
17376
typedef void* ada_url_search_params_values_iter;
17377
typedef void* ada_url_search_params_entries_iter;
17378
17379
struct ada_string {
17380
  const char* data;
17381
  size_t length;
17382
};
17383
17384
struct ada_owned_string {
17385
  const char* data;
17386
  size_t length;
17387
};
17388
17389
struct ada_string_pair {
17390
  ada_string key;
17391
  ada_string value;
17392
};
17393
17394
0
ada_string ada_string_create(const char* data, size_t length) {
17395
0
  ada_string out{};
17396
0
  out.data = data;
17397
0
  out.length = length;
17398
0
  return out;
17399
0
}
17400
17401
struct ada_url_components {
17402
  /*
17403
   * By using 32-bit integers, we implicitly assume that the URL string
17404
   * cannot exceed 4 GB.
17405
   *
17406
   * https://user:pass@example.com:1234/foo/bar?baz#quux
17407
   *       |     |    |          | ^^^^|       |   |
17408
   *       |     |    |          | |   |       |   `----- hash_start
17409
   *       |     |    |          | |   |       `--------- search_start
17410
   *       |     |    |          | |   `----------------- pathname_start
17411
   *       |     |    |          | `--------------------- port
17412
   *       |     |    |          `----------------------- host_end
17413
   *       |     |    `---------------------------------- host_start
17414
   *       |     `--------------------------------------- username_end
17415
   *       `--------------------------------------------- protocol_end
17416
   */
17417
  uint32_t protocol_end;
17418
  /**
17419
   * Username end is not `omitted` by default (-1) to make username and password
17420
   * getters less costly to implement.
17421
   */
17422
  uint32_t username_end;
17423
  uint32_t host_start;
17424
  uint32_t host_end;
17425
  uint32_t port;
17426
  uint32_t pathname_start;
17427
  uint32_t search_start;
17428
  uint32_t hash_start;
17429
};
17430
17431
0
ada_url ada_parse(const char* input, size_t length) noexcept {
17432
0
  return new ada::result<ada::url_aggregator>(
17433
0
      ada::parse<ada::url_aggregator>(std::string_view(input, length)));
17434
0
}
17435
17436
ada_url ada_parse_with_base(const char* input, size_t input_length,
17437
0
                            const char* base, size_t base_length) noexcept {
17438
0
  auto base_out =
17439
0
      ada::parse<ada::url_aggregator>(std::string_view(base, base_length));
17440
17441
0
  if (!base_out) {
17442
0
    return new ada::result<ada::url_aggregator>(base_out);
17443
0
  }
17444
17445
0
  return new ada::result<ada::url_aggregator>(ada::parse<ada::url_aggregator>(
17446
0
      std::string_view(input, input_length), &base_out.value()));
17447
0
}
17448
17449
0
bool ada_can_parse(const char* input, size_t length) noexcept {
17450
0
  return ada::can_parse(std::string_view(input, length));
17451
0
}
17452
17453
bool ada_can_parse_with_base(const char* input, size_t input_length,
17454
0
                             const char* base, size_t base_length) noexcept {
17455
0
  std::string_view base_view(base, base_length);
17456
0
  return ada::can_parse(std::string_view(input, input_length), &base_view);
17457
0
}
17458
17459
0
void ada_free(ada_url result) noexcept {
17460
0
  auto* r = (ada::result<ada::url_aggregator>*)result;
17461
0
  delete r;
17462
0
}
17463
17464
0
ada_url ada_copy(ada_url input) noexcept {
17465
0
  ada::result<ada::url_aggregator>& r = get_instance(input);
17466
0
  return new ada::result<ada::url_aggregator>(r);
17467
0
}
17468
17469
0
bool ada_is_valid(ada_url result) noexcept {
17470
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17471
0
  return r.has_value();
17472
0
}
17473
17474
// caller must free the result with ada_free_owned_string
17475
0
ada_owned_string ada_get_origin(ada_url result) noexcept {
17476
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17477
0
  ada_owned_string owned{};
17478
0
  if (!r) {
17479
0
    owned.data = nullptr;
17480
0
    owned.length = 0;
17481
0
    return owned;
17482
0
  }
17483
0
  std::string out = r->get_origin();
17484
0
  owned.length = out.size();
17485
0
  owned.data = new char[owned.length];
17486
0
  memcpy((void*)owned.data, out.data(), owned.length);
17487
0
  return owned;
17488
0
}
17489
17490
0
void ada_free_owned_string(ada_owned_string owned) noexcept {
17491
0
  delete[] owned.data;
17492
0
}
17493
17494
0
ada_string ada_get_href(ada_url result) noexcept {
17495
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17496
0
  if (!r) {
17497
0
    return ada_string_create(nullptr, 0);
17498
0
  }
17499
0
  std::string_view out = r->get_href();
17500
0
  return ada_string_create(out.data(), out.length());
17501
0
}
17502
17503
0
ada_string ada_get_username(ada_url result) noexcept {
17504
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17505
0
  if (!r) {
17506
0
    return ada_string_create(nullptr, 0);
17507
0
  }
17508
0
  std::string_view out = r->get_username();
17509
0
  return ada_string_create(out.data(), out.length());
17510
0
}
17511
17512
0
ada_string ada_get_password(ada_url result) noexcept {
17513
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17514
0
  if (!r) {
17515
0
    return ada_string_create(nullptr, 0);
17516
0
  }
17517
0
  std::string_view out = r->get_password();
17518
0
  return ada_string_create(out.data(), out.length());
17519
0
}
17520
17521
0
ada_string ada_get_port(ada_url result) noexcept {
17522
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17523
0
  if (!r) {
17524
0
    return ada_string_create(nullptr, 0);
17525
0
  }
17526
0
  std::string_view out = r->get_port();
17527
0
  return ada_string_create(out.data(), out.length());
17528
0
}
17529
17530
0
ada_string ada_get_hash(ada_url result) noexcept {
17531
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17532
0
  if (!r) {
17533
0
    return ada_string_create(nullptr, 0);
17534
0
  }
17535
0
  std::string_view out = r->get_hash();
17536
0
  return ada_string_create(out.data(), out.length());
17537
0
}
17538
17539
0
ada_string ada_get_host(ada_url result) noexcept {
17540
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17541
0
  if (!r) {
17542
0
    return ada_string_create(nullptr, 0);
17543
0
  }
17544
0
  std::string_view out = r->get_host();
17545
0
  return ada_string_create(out.data(), out.length());
17546
0
}
17547
17548
0
ada_string ada_get_hostname(ada_url result) noexcept {
17549
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17550
0
  if (!r) {
17551
0
    return ada_string_create(nullptr, 0);
17552
0
  }
17553
0
  std::string_view out = r->get_hostname();
17554
0
  return ada_string_create(out.data(), out.length());
17555
0
}
17556
17557
0
ada_string ada_get_pathname(ada_url result) noexcept {
17558
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17559
0
  if (!r) {
17560
0
    return ada_string_create(nullptr, 0);
17561
0
  }
17562
0
  std::string_view out = r->get_pathname();
17563
0
  return ada_string_create(out.data(), out.length());
17564
0
}
17565
17566
0
ada_string ada_get_search(ada_url result) noexcept {
17567
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17568
0
  if (!r) {
17569
0
    return ada_string_create(nullptr, 0);
17570
0
  }
17571
0
  std::string_view out = r->get_search();
17572
0
  return ada_string_create(out.data(), out.length());
17573
0
}
17574
17575
0
ada_string ada_get_protocol(ada_url result) noexcept {
17576
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17577
0
  if (!r) {
17578
0
    return ada_string_create(nullptr, 0);
17579
0
  }
17580
0
  std::string_view out = r->get_protocol();
17581
0
  return ada_string_create(out.data(), out.length());
17582
0
}
17583
17584
0
uint8_t ada_get_host_type(ada_url result) noexcept {
17585
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17586
0
  if (!r) {
17587
0
    return 0;
17588
0
  }
17589
0
  return r->host_type;
17590
0
}
17591
17592
0
uint8_t ada_get_scheme_type(ada_url result) noexcept {
17593
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17594
0
  if (!r) {
17595
0
    return 0;
17596
0
  }
17597
0
  return r->type;
17598
0
}
17599
17600
0
bool ada_set_href(ada_url result, const char* input, size_t length) noexcept {
17601
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17602
0
  if (!r) {
17603
0
    return false;
17604
0
  }
17605
0
  return r->set_href(std::string_view(input, length));
17606
0
}
17607
17608
0
bool ada_set_host(ada_url result, const char* input, size_t length) noexcept {
17609
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17610
0
  if (!r) {
17611
0
    return false;
17612
0
  }
17613
0
  return r->set_host(std::string_view(input, length));
17614
0
}
17615
17616
bool ada_set_hostname(ada_url result, const char* input,
17617
0
                      size_t length) noexcept {
17618
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17619
0
  if (!r) {
17620
0
    return false;
17621
0
  }
17622
0
  return r->set_hostname(std::string_view(input, length));
17623
0
}
17624
17625
bool ada_set_protocol(ada_url result, const char* input,
17626
0
                      size_t length) noexcept {
17627
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17628
0
  if (!r) {
17629
0
    return false;
17630
0
  }
17631
0
  return r->set_protocol(std::string_view(input, length));
17632
0
}
17633
17634
bool ada_set_username(ada_url result, const char* input,
17635
0
                      size_t length) noexcept {
17636
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17637
0
  if (!r) {
17638
0
    return false;
17639
0
  }
17640
0
  return r->set_username(std::string_view(input, length));
17641
0
}
17642
17643
bool ada_set_password(ada_url result, const char* input,
17644
0
                      size_t length) noexcept {
17645
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17646
0
  if (!r) {
17647
0
    return false;
17648
0
  }
17649
0
  return r->set_password(std::string_view(input, length));
17650
0
}
17651
17652
0
bool ada_set_port(ada_url result, const char* input, size_t length) noexcept {
17653
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17654
0
  if (!r) {
17655
0
    return false;
17656
0
  }
17657
0
  return r->set_port(std::string_view(input, length));
17658
0
}
17659
17660
bool ada_set_pathname(ada_url result, const char* input,
17661
0
                      size_t length) noexcept {
17662
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17663
0
  if (!r) {
17664
0
    return false;
17665
0
  }
17666
0
  return r->set_pathname(std::string_view(input, length));
17667
0
}
17668
17669
/**
17670
 * Update the search/query of the URL.
17671
 *
17672
 * If a URL has `?` as the search value, passing empty string to this function
17673
 * does not remove the attribute. If you need to remove it, please use
17674
 * `ada_clear_search` method.
17675
 */
17676
0
void ada_set_search(ada_url result, const char* input, size_t length) noexcept {
17677
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17678
0
  if (r) {
17679
0
    r->set_search(std::string_view(input, length));
17680
0
  }
17681
0
}
17682
17683
/**
17684
 * Update the hash/fragment of the URL.
17685
 *
17686
 * If a URL has `#` as the hash value, passing empty string to this function
17687
 * does not remove the attribute. If you need to remove it, please use
17688
 * `ada_clear_hash` method.
17689
 */
17690
0
void ada_set_hash(ada_url result, const char* input, size_t length) noexcept {
17691
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17692
0
  if (r) {
17693
0
    r->set_hash(std::string_view(input, length));
17694
0
  }
17695
0
}
17696
17697
0
void ada_clear_port(ada_url result) noexcept {
17698
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17699
0
  if (r) {
17700
0
    r->clear_port();
17701
0
  }
17702
0
}
17703
17704
/**
17705
 * Removes the hash of the URL.
17706
 *
17707
 * Despite `ada_set_hash` method, this function allows the complete
17708
 * removal of the hash attribute, even if it has a value of `#`.
17709
 */
17710
0
void ada_clear_hash(ada_url result) noexcept {
17711
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17712
0
  if (r) {
17713
0
    r->clear_hash();
17714
0
  }
17715
0
}
17716
17717
/**
17718
 * Removes the search of the URL.
17719
 *
17720
 * Despite `ada_set_search` method, this function allows the complete
17721
 * removal of the search attribute, even if it has a value of `?`.
17722
 */
17723
0
void ada_clear_search(ada_url result) noexcept {
17724
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17725
0
  if (r) {
17726
0
    r->clear_search();
17727
0
  }
17728
0
}
17729
17730
0
bool ada_has_credentials(ada_url result) noexcept {
17731
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17732
0
  if (!r) {
17733
0
    return false;
17734
0
  }
17735
0
  return r->has_credentials();
17736
0
}
17737
17738
0
bool ada_has_empty_hostname(ada_url result) noexcept {
17739
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17740
0
  if (!r) {
17741
0
    return false;
17742
0
  }
17743
0
  return r->has_empty_hostname();
17744
0
}
17745
17746
0
bool ada_has_hostname(ada_url result) noexcept {
17747
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17748
0
  if (!r) {
17749
0
    return false;
17750
0
  }
17751
0
  return r->has_hostname();
17752
0
}
17753
17754
0
bool ada_has_non_empty_username(ada_url result) noexcept {
17755
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17756
0
  if (!r) {
17757
0
    return false;
17758
0
  }
17759
0
  return r->has_non_empty_username();
17760
0
}
17761
17762
0
bool ada_has_non_empty_password(ada_url result) noexcept {
17763
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17764
0
  if (!r) {
17765
0
    return false;
17766
0
  }
17767
0
  return r->has_non_empty_password();
17768
0
}
17769
17770
0
bool ada_has_port(ada_url result) noexcept {
17771
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17772
0
  if (!r) {
17773
0
    return false;
17774
0
  }
17775
0
  return r->has_port();
17776
0
}
17777
17778
0
bool ada_has_password(ada_url result) noexcept {
17779
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17780
0
  if (!r) {
17781
0
    return false;
17782
0
  }
17783
0
  return r->has_password();
17784
0
}
17785
17786
0
bool ada_has_hash(ada_url result) noexcept {
17787
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17788
0
  if (!r) {
17789
0
    return false;
17790
0
  }
17791
0
  return r->has_hash();
17792
0
}
17793
17794
0
bool ada_has_search(ada_url result) noexcept {
17795
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17796
0
  if (!r) {
17797
0
    return false;
17798
0
  }
17799
0
  return r->has_search();
17800
0
}
17801
17802
// returns a pointer to the internal url_aggregator::url_components
17803
0
const ada_url_components* ada_get_components(ada_url result) noexcept {
17804
0
  static_assert(sizeof(ada_url_components) == sizeof(ada::url_components));
17805
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17806
0
  if (!r) {
17807
0
    return nullptr;
17808
0
  }
17809
0
  return reinterpret_cast<const ada_url_components*>(&r->get_components());
17810
0
}
17811
17812
0
ada_owned_string ada_idna_to_unicode(const char* input, size_t length) {
17813
0
  std::string out = ada::idna::to_unicode(std::string_view(input, length));
17814
0
  ada_owned_string owned{};
17815
0
  owned.length = out.length();
17816
0
  owned.data = new char[owned.length];
17817
0
  memcpy((void*)owned.data, out.data(), owned.length);
17818
0
  return owned;
17819
0
}
17820
17821
0
ada_owned_string ada_idna_to_ascii(const char* input, size_t length) {
17822
0
  std::string out = ada::idna::to_ascii(std::string_view(input, length));
17823
0
  ada_owned_string owned{};
17824
0
  owned.length = out.size();
17825
0
  owned.data = new char[owned.length];
17826
0
  memcpy((void*)owned.data, out.data(), owned.length);
17827
0
  return owned;
17828
0
}
17829
17830
ada_url_search_params ada_parse_search_params(const char* input,
17831
0
                                              size_t length) {
17832
0
  return new ada::result<ada::url_search_params>(
17833
0
      ada::url_search_params(std::string_view(input, length)));
17834
0
}
17835
17836
0
void ada_free_search_params(ada_url_search_params result) {
17837
0
  auto* r = (ada::result<ada::url_search_params>*)result;
17838
0
  delete r;
17839
0
}
17840
17841
0
ada_owned_string ada_search_params_to_string(ada_url_search_params result) {
17842
0
  ada::result<ada::url_search_params>& r =
17843
0
      *(ada::result<ada::url_search_params>*)result;
17844
0
  if (!r) return ada_owned_string{nullptr, 0};
17845
0
  std::string out = r->to_string();
17846
0
  ada_owned_string owned{};
17847
0
  owned.length = out.size();
17848
0
  owned.data = new char[owned.length];
17849
0
  memcpy((void*)owned.data, out.data(), owned.length);
17850
0
  return owned;
17851
0
}
17852
17853
0
size_t ada_search_params_size(ada_url_search_params result) {
17854
0
  ada::result<ada::url_search_params>& r =
17855
0
      *(ada::result<ada::url_search_params>*)result;
17856
0
  if (!r) {
17857
0
    return 0;
17858
0
  }
17859
0
  return r->size();
17860
0
}
17861
17862
0
void ada_search_params_sort(ada_url_search_params result) {
17863
0
  ada::result<ada::url_search_params>& r =
17864
0
      *(ada::result<ada::url_search_params>*)result;
17865
0
  if (r) {
17866
0
    r->sort();
17867
0
  }
17868
0
}
17869
17870
void ada_search_params_reset(ada_url_search_params result, const char* input,
17871
0
                             size_t length) {
17872
0
  ada::result<ada::url_search_params>& r =
17873
0
      *(ada::result<ada::url_search_params>*)result;
17874
0
  if (r) {
17875
0
    r->reset(std::string_view(input, length));
17876
0
  }
17877
0
}
17878
17879
void ada_search_params_append(ada_url_search_params result, const char* key,
17880
                              size_t key_length, const char* value,
17881
0
                              size_t value_length) {
17882
0
  ada::result<ada::url_search_params>& r =
17883
0
      *(ada::result<ada::url_search_params>*)result;
17884
0
  if (r) {
17885
0
    r->append(std::string_view(key, key_length),
17886
0
              std::string_view(value, value_length));
17887
0
  }
17888
0
}
17889
17890
void ada_search_params_set(ada_url_search_params result, const char* key,
17891
                           size_t key_length, const char* value,
17892
0
                           size_t value_length) {
17893
0
  ada::result<ada::url_search_params>& r =
17894
0
      *(ada::result<ada::url_search_params>*)result;
17895
0
  if (r) {
17896
0
    r->set(std::string_view(key, key_length),
17897
0
           std::string_view(value, value_length));
17898
0
  }
17899
0
}
17900
17901
void ada_search_params_remove(ada_url_search_params result, const char* key,
17902
0
                              size_t key_length) {
17903
0
  ada::result<ada::url_search_params>& r =
17904
0
      *(ada::result<ada::url_search_params>*)result;
17905
0
  if (r) {
17906
0
    r->remove(std::string_view(key, key_length));
17907
0
  }
17908
0
}
17909
17910
void ada_search_params_remove_value(ada_url_search_params result,
17911
                                    const char* key, size_t key_length,
17912
0
                                    const char* value, size_t value_length) {
17913
0
  ada::result<ada::url_search_params>& r =
17914
0
      *(ada::result<ada::url_search_params>*)result;
17915
0
  if (r) {
17916
0
    r->remove(std::string_view(key, key_length),
17917
0
              std::string_view(value, value_length));
17918
0
  }
17919
0
}
17920
17921
bool ada_search_params_has(ada_url_search_params result, const char* key,
17922
0
                           size_t key_length) {
17923
0
  ada::result<ada::url_search_params>& r =
17924
0
      *(ada::result<ada::url_search_params>*)result;
17925
0
  if (!r) {
17926
0
    return false;
17927
0
  }
17928
0
  return r->has(std::string_view(key, key_length));
17929
0
}
17930
17931
bool ada_search_params_has_value(ada_url_search_params result, const char* key,
17932
                                 size_t key_length, const char* value,
17933
0
                                 size_t value_length) {
17934
0
  ada::result<ada::url_search_params>& r =
17935
0
      *(ada::result<ada::url_search_params>*)result;
17936
0
  if (!r) {
17937
0
    return false;
17938
0
  }
17939
0
  return r->has(std::string_view(key, key_length),
17940
0
                std::string_view(value, value_length));
17941
0
}
17942
17943
ada_string ada_search_params_get(ada_url_search_params result, const char* key,
17944
0
                                 size_t key_length) {
17945
0
  ada::result<ada::url_search_params>& r =
17946
0
      *(ada::result<ada::url_search_params>*)result;
17947
0
  if (!r) {
17948
0
    return ada_string_create(nullptr, 0);
17949
0
  }
17950
0
  auto found = r->get(std::string_view(key, key_length));
17951
0
  if (!found.has_value()) {
17952
0
    return ada_string_create(nullptr, 0);
17953
0
  }
17954
0
  return ada_string_create(found->data(), found->length());
17955
0
}
17956
17957
ada_strings ada_search_params_get_all(ada_url_search_params result,
17958
0
                                      const char* key, size_t key_length) {
17959
0
  ada::result<ada::url_search_params>& r =
17960
0
      *(ada::result<ada::url_search_params>*)result;
17961
0
  if (!r) {
17962
0
    return new ada::result<std::vector<std::string>>(
17963
0
        std::vector<std::string>());
17964
0
  }
17965
0
  return new ada::result<std::vector<std::string>>(
17966
0
      r->get_all(std::string_view(key, key_length)));
17967
0
}
17968
17969
ada_url_search_params_keys_iter ada_search_params_get_keys(
17970
0
    ada_url_search_params result) {
17971
0
  ada::result<ada::url_search_params>& r =
17972
0
      *(ada::result<ada::url_search_params>*)result;
17973
0
  if (!r) {
17974
0
    return new ada::result<ada::url_search_params_keys_iter>(
17975
0
        ada::url_search_params_keys_iter());
17976
0
  }
17977
0
  return new ada::result<ada::url_search_params_keys_iter>(r->get_keys());
17978
0
}
17979
17980
ada_url_search_params_values_iter ada_search_params_get_values(
17981
0
    ada_url_search_params result) {
17982
0
  ada::result<ada::url_search_params>& r =
17983
0
      *(ada::result<ada::url_search_params>*)result;
17984
0
  if (!r) {
17985
0
    return new ada::result<ada::url_search_params_values_iter>(
17986
0
        ada::url_search_params_values_iter());
17987
0
  }
17988
0
  return new ada::result<ada::url_search_params_values_iter>(r->get_values());
17989
0
}
17990
17991
ada_url_search_params_entries_iter ada_search_params_get_entries(
17992
0
    ada_url_search_params result) {
17993
0
  ada::result<ada::url_search_params>& r =
17994
0
      *(ada::result<ada::url_search_params>*)result;
17995
0
  if (!r) {
17996
0
    return new ada::result<ada::url_search_params_entries_iter>(
17997
0
        ada::url_search_params_entries_iter());
17998
0
  }
17999
0
  return new ada::result<ada::url_search_params_entries_iter>(r->get_entries());
18000
0
}
18001
18002
0
void ada_free_strings(ada_strings result) {
18003
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
18004
0
  delete r;
18005
0
}
18006
18007
0
size_t ada_strings_size(ada_strings result) {
18008
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
18009
0
  if (!r) {
18010
0
    return 0;
18011
0
  }
18012
0
  return (*r)->size();
18013
0
}
18014
18015
0
ada_string ada_strings_get(ada_strings result, size_t index) {
18016
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
18017
0
  if (!r) {
18018
0
    return ada_string_create(nullptr, 0);
18019
0
  }
18020
0
  std::string_view view = (*r)->at(index);
18021
0
  return ada_string_create(view.data(), view.length());
18022
0
}
18023
18024
0
void ada_free_search_params_keys_iter(ada_url_search_params_keys_iter result) {
18025
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
18026
0
  delete r;
18027
0
}
18028
18029
ada_string ada_search_params_keys_iter_next(
18030
0
    ada_url_search_params_keys_iter result) {
18031
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
18032
0
  if (!r) {
18033
0
    return ada_string_create(nullptr, 0);
18034
0
  }
18035
0
  auto next = (*r)->next();
18036
0
  if (!next.has_value()) {
18037
0
    return ada_string_create(nullptr, 0);
18038
0
  }
18039
0
  return ada_string_create(next->data(), next->length());
18040
0
}
18041
18042
bool ada_search_params_keys_iter_has_next(
18043
0
    ada_url_search_params_keys_iter result) {
18044
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
18045
0
  if (!r) {
18046
0
    return false;
18047
0
  }
18048
0
  return (*r)->has_next();
18049
0
}
18050
18051
void ada_free_search_params_values_iter(
18052
0
    ada_url_search_params_values_iter result) {
18053
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
18054
0
  delete r;
18055
0
}
18056
18057
ada_string ada_search_params_values_iter_next(
18058
0
    ada_url_search_params_values_iter result) {
18059
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
18060
0
  if (!r) {
18061
0
    return ada_string_create(nullptr, 0);
18062
0
  }
18063
0
  auto next = (*r)->next();
18064
0
  if (!next.has_value()) {
18065
0
    return ada_string_create(nullptr, 0);
18066
0
  }
18067
0
  return ada_string_create(next->data(), next->length());
18068
0
}
18069
18070
bool ada_search_params_values_iter_has_next(
18071
0
    ada_url_search_params_values_iter result) {
18072
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
18073
0
  if (!r) {
18074
0
    return false;
18075
0
  }
18076
0
  return (*r)->has_next();
18077
0
}
18078
18079
void ada_free_search_params_entries_iter(
18080
0
    ada_url_search_params_entries_iter result) {
18081
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
18082
0
  delete r;
18083
0
}
18084
18085
ada_string_pair ada_search_params_entries_iter_next(
18086
0
    ada_url_search_params_entries_iter result) {
18087
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
18088
0
  if (!r) return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)};
18089
0
  auto next = (*r)->next();
18090
0
  if (!next.has_value()) {
18091
0
    return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)};
18092
0
  }
18093
0
  return ada_string_pair{
18094
0
      ada_string_create(next->first.data(), next->first.length()),
18095
0
      ada_string_create(next->second.data(), next->second.length())};
18096
0
}
18097
18098
bool ada_search_params_entries_iter_has_next(
18099
0
    ada_url_search_params_entries_iter result) {
18100
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
18101
0
  if (!r) {
18102
0
    return false;
18103
0
  }
18104
0
  return (*r)->has_next();
18105
0
}
18106
18107
typedef struct {
18108
  int major;
18109
  int minor;
18110
  int revision;
18111
} ada_version_components;
18112
18113
0
const char* ada_get_version() { return ADA_VERSION; }
18114
18115
0
ada_version_components ada_get_version_components() {
18116
0
  return ada_version_components{
18117
0
      .major = ada::ADA_VERSION_MAJOR,
18118
0
      .minor = ada::ADA_VERSION_MINOR,
18119
0
      .revision = ada::ADA_VERSION_REVISION,
18120
0
  };
18121
0
}
18122
18123
}  // extern "C"
18124
/* end file src/ada_c.cpp */
18125
/* end file src/ada.cpp */