Coverage Report

Created: 2025-10-10 06:28

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 2025-10-03 19:59:52 -0400. Do not edit! */
2
/* begin file src/ada.cpp */
3
#include "ada.h"
4
/* begin file src/checkers.cpp */
5
6
#include <algorithm>
7
#include <array>
8
#include <string_view>
9
10
namespace ada::checkers {
11
12
39.3k
ada_really_inline constexpr bool is_ipv4(std::string_view view) noexcept {
13
  // The string is not empty and does not contain upper case ASCII characters.
14
  //
15
  // Optimization. To be considered as a possible ipv4, the string must end
16
  // with 'x' or a lowercase hex character.
17
  // Most of the time, this will be false so this simple check will save a lot
18
  // of effort.
19
  // If the address ends with a dot, we need to prune it (special case).
20
39.3k
  if (view.ends_with('.')) {
21
1.42k
    view.remove_suffix(1);
22
1.42k
    if (view.empty()) {
23
658
      return false;
24
658
    }
25
1.42k
  }
26
38.6k
  char last_char = view.back();
27
38.6k
  bool possible_ipv4 = (last_char >= '0' && last_char <= '9') ||
28
34.4k
                       (last_char >= 'a' && last_char <= 'f') ||
29
27.6k
                       last_char == 'x';
30
38.6k
  if (!possible_ipv4) {
31
26.9k
    return false;
32
26.9k
  }
33
  // From the last character, find the last dot.
34
11.7k
  size_t last_dot = view.rfind('.');
35
11.7k
  if (last_dot != std::string_view::npos) {
36
    // We have at least one dot.
37
2.94k
    view = view.substr(last_dot + 1);
38
2.94k
  }
39
  /** Optimization opportunity: we have basically identified the last number of
40
     the ipv4 if we return true here. We might as well parse it and have at
41
     least one number parsed when we get to parse_ipv4. */
42
11.7k
  if (std::ranges::all_of(view, ada::checkers::is_digit)) {
43
2.91k
    return true;
44
2.91k
  }
45
  // It could be hex (0x), but not if there is a single character.
46
8.83k
  if (view.size() == 1) {
47
1.55k
    return false;
48
1.55k
  }
49
  // It must start with 0x.
50
7.28k
  if (!view.starts_with("0x")) {
51
5.19k
    return false;
52
5.19k
  }
53
  // We must allow "0x".
54
2.08k
  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.98k
  view.remove_prefix(2);
60
1.98k
  return std::ranges::all_of(view, ada::unicode::is_lowercase_hex);
61
2.08k
}
62
63
// for use with path_signature, we include all characters that need percent
64
// encoding.
65
static constexpr std::array<uint8_t, 256> path_signature_table =
66
    []() consteval {
67
      std::array<uint8_t, 256> result{};
68
      for (size_t i = 0; i < 256; i++) {
69
        if (i <= 0x20 || i == 0x22 || i == 0x23 || i == 0x3c || i == 0x3e ||
70
            i == 0x3f || i == 0x5e || i == 0x60 || i == 0x7b || i == 0x7d ||
71
            i > 0x7e) {
72
          result[i] = 1;
73
        } else if (i == 0x25) {
74
          result[i] = 8;
75
        } else if (i == 0x2e) {
76
          result[i] = 4;
77
        } else if (i == 0x5c) {
78
          result[i] = 2;
79
        } else {
80
          result[i] = 0;
81
        }
82
      }
83
      return result;
84
    }();
85
86
ada_really_inline constexpr uint8_t path_signature(
87
32.1k
    std::string_view input) noexcept {
88
  // The path percent-encode set is the query percent-encode set and U+003F (?),
89
  // U+0060 (`), U+007B ({), and U+007D (}). The query percent-encode set is the
90
  // C0 control percent-encode set and U+0020 SPACE, U+0022 ("), U+0023 (#),
91
  // U+003C (<), and U+003E (>). The C0 control percent-encode set are the C0
92
  // controls and all code points greater than U+007E (~).
93
32.1k
  size_t i = 0;
94
32.1k
  uint8_t accumulator{};
95
152k
  for (; i + 7 < input.size(); i += 8) {
96
120k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])] |
97
120k
                           path_signature_table[uint8_t(input[i + 1])] |
98
120k
                           path_signature_table[uint8_t(input[i + 2])] |
99
120k
                           path_signature_table[uint8_t(input[i + 3])] |
100
120k
                           path_signature_table[uint8_t(input[i + 4])] |
101
120k
                           path_signature_table[uint8_t(input[i + 5])] |
102
120k
                           path_signature_table[uint8_t(input[i + 6])] |
103
120k
                           path_signature_table[uint8_t(input[i + 7])]);
104
120k
  }
105
143k
  for (; i < input.size(); i++) {
106
110k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])]);
107
110k
  }
108
32.1k
  return accumulator;
109
32.1k
}
110
111
ada_really_inline constexpr bool verify_dns_length(
112
8.96k
    std::string_view input) noexcept {
113
8.96k
  if (input.back() == '.') {
114
917
    if (input.size() > 254) return false;
115
8.05k
  } else if (input.size() > 253)
116
42
    return false;
117
118
8.92k
  size_t start = 0;
119
27.7k
  while (start < input.size()) {
120
20.8k
    auto dot_location = input.find('.', start);
121
    // If not found, it's likely the end of the domain
122
20.8k
    if (dot_location == std::string_view::npos) dot_location = input.size();
123
124
20.8k
    auto label_size = dot_location - start;
125
20.8k
    if (label_size > 63 || label_size == 0) return false;
126
127
18.8k
    start = dot_location + 1;
128
18.8k
  }
129
130
6.87k
  return true;
131
8.92k
}
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
10.4k
size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) {
150
10.4k
  const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
151
10.4k
  size_t pos = 0;
152
10.4k
  const char32_t* start{utf32_output};
153
154k
  while (pos < len) {
154
    // try to convert the next block of 16 ASCII bytes
155
145k
    if (pos + 16 <= len) {  // if it is safe to read 16 more
156
                            // bytes, check that they are ascii
157
102k
      uint64_t v1;
158
102k
      std::memcpy(&v1, data + pos, sizeof(uint64_t));
159
102k
      uint64_t v2;
160
102k
      std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
161
102k
      uint64_t v{v1 | v2};
162
102k
      if ((v & 0x8080808080808080) == 0) {
163
1.96k
        size_t final_pos = pos + 16;
164
33.3k
        while (pos < final_pos) {
165
31.4k
          *utf32_output++ = char32_t(buf[pos]);
166
31.4k
          pos++;
167
31.4k
        }
168
1.96k
        continue;
169
1.96k
      }
170
102k
    }
171
143k
    uint8_t leading_byte = data[pos];  // leading byte
172
143k
    if (leading_byte < 0b10000000) {
173
      // converting one ASCII byte !!!
174
63.2k
      *utf32_output++ = char32_t(leading_byte);
175
63.2k
      pos++;
176
80.6k
    } else if ((leading_byte & 0b11100000) == 0b11000000) {
177
      // We have a two-byte UTF-8
178
11.2k
      if (pos + 1 >= len) {
179
214
        return 0;
180
214
      }  // minimal bound checking
181
11.0k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
182
202
        return 0;
183
202
      }
184
      // range check
185
10.8k
      uint32_t code_point =
186
10.8k
          (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
187
10.8k
      if (code_point < 0x80 || 0x7ff < code_point) {
188
10
        return 0;
189
10
      }
190
10.8k
      *utf32_output++ = char32_t(code_point);
191
10.8k
      pos += 2;
192
69.3k
    } else if ((leading_byte & 0b11110000) == 0b11100000) {
193
      // We have a three-byte UTF-8
194
66.7k
      if (pos + 2 >= len) {
195
42
        return 0;
196
42
      }  // minimal bound checking
197
198
66.6k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
199
88
        return 0;
200
88
      }
201
66.5k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
202
34
        return 0;
203
34
      }
204
      // range check
205
66.5k
      uint32_t code_point = (leading_byte & 0b00001111) << 12 |
206
66.5k
                            (data[pos + 1] & 0b00111111) << 6 |
207
66.5k
                            (data[pos + 2] & 0b00111111);
208
66.5k
      if (code_point < 0x800 || 0xffff < code_point ||
209
66.5k
          (0xd7ff < code_point && code_point < 0xe000)) {
210
32
        return 0;
211
32
      }
212
66.5k
      *utf32_output++ = char32_t(code_point);
213
66.5k
      pos += 3;
214
66.5k
    } else if ((leading_byte & 0b11111000) == 0b11110000) {  // 0b11110000
215
      // we have a 4-byte UTF-8 word.
216
1.21k
      if (pos + 3 >= len) {
217
62
        return 0;
218
62
      }  // minimal bound checking
219
1.15k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
220
46
        return 0;
221
46
      }
222
1.11k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
223
6
        return 0;
224
6
      }
225
1.10k
      if ((data[pos + 3] & 0b11000000) != 0b10000000) {
226
22
        return 0;
227
22
      }
228
229
      // range check
230
1.08k
      uint32_t code_point = (leading_byte & 0b00000111) << 18 |
231
1.08k
                            (data[pos + 1] & 0b00111111) << 12 |
232
1.08k
                            (data[pos + 2] & 0b00111111) << 6 |
233
1.08k
                            (data[pos + 3] & 0b00111111);
234
1.08k
      if (code_point <= 0xffff || 0x10ffff < code_point) {
235
40
        return 0;
236
40
      }
237
1.04k
      *utf32_output++ = char32_t(code_point);
238
1.04k
      pos += 4;
239
1.44k
    } else {
240
1.44k
      return 0;
241
1.44k
    }
242
143k
  }
243
8.16k
  return utf32_output - start;
244
10.4k
}
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
10.4k
size_t utf32_length_from_utf8(const char* buf, size_t len) {
260
10.4k
  const int8_t* p = reinterpret_cast<const int8_t*>(buf);
261
373k
  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
373k
    return c > -65;
265
373k
  });
266
10.4k
}
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
203k
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
203k
  uint32_t len = std::size(table);
2785
203k
  uint32_t low = 0;
2786
203k
  uint32_t high = len - 1;
2787
2.72M
  while (low <= high) {
2788
2.61M
    uint32_t middle_index = (low + high) >> 1;  // cannot overflow
2789
2.61M
    uint32_t middle_value = table[middle_index][0];
2790
2.61M
    if (middle_value < key) {
2791
877k
      low = middle_index + 1;
2792
1.73M
    } else if (middle_value > key) {
2793
1.64M
      high = middle_index - 1;
2794
1.64M
    } else {
2795
89.0k
      return middle_index;  // perfect match
2796
89.0k
    }
2797
2.61M
  }
2798
114k
  return low == 0 ? 0 : low - 1;
2799
203k
}
2800
2801
6.76k
void ascii_map(char* input, size_t length) {
2802
20.2k
  auto broadcast = [](uint8_t v) -> uint64_t {
2803
20.2k
    return 0x101010101010101ull * v;
2804
20.2k
  };
2805
6.76k
  uint64_t broadcast_80 = broadcast(0x80);
2806
6.76k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
2807
6.76k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2808
6.76k
  size_t i = 0;
2809
2810
16.6k
  for (; i + 7 < length; i += 8) {
2811
9.88k
    uint64_t word{};
2812
9.88k
    memcpy(&word, input + i, sizeof(word));
2813
9.88k
    word ^=
2814
9.88k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2815
9.88k
    memcpy(input + i, &word, sizeof(word));
2816
9.88k
  }
2817
6.76k
  if (i < length) {
2818
6.20k
    uint64_t word{};
2819
6.20k
    memcpy(&word, input + i, length - i);
2820
6.20k
    word ^=
2821
6.20k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2822
6.20k
    memcpy(input + i, &word, length - i);
2823
6.20k
  }
2824
6.76k
}
2825
2826
// Map the characters according to IDNA, returning the empty string on error.
2827
13.2k
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
13.2k
  static std::u32string error = U"";
2842
13.2k
  std::u32string answer;
2843
13.2k
  answer.reserve(input.size());
2844
203k
  for (char32_t x : input) {
2845
203k
    size_t index = find_range_index(x);
2846
203k
    uint32_t descriptor = table[index][1];
2847
203k
    uint8_t code = uint8_t(descriptor);
2848
203k
    switch (code) {
2849
524
      case 0:
2850
524
        break;  // nothing to do, ignored
2851
119k
      case 1:
2852
119k
        answer.push_back(x);  // valid, we just copy it to output
2853
119k
        break;
2854
446
      case 2:
2855
446
        return error;  // disallowed
2856
      // case 3 :
2857
82.6k
      default:
2858
        // We have a mapping
2859
82.6k
        {
2860
82.6k
          size_t char_count = (descriptor >> 24);
2861
82.6k
          uint16_t char_index = uint16_t(descriptor >> 8);
2862
566k
          for (size_t idx = char_index; idx < char_index + char_count; idx++) {
2863
483k
            answer.push_back(mappings[idx]);
2864
483k
          }
2865
82.6k
        }
2866
203k
    }
2867
203k
  }
2868
12.7k
  return answer;
2869
13.2k
}
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
12.5k
    const std::u32string_view input) noexcept {
7789
12.5k
  bool decomposition_needed{false};
7790
12.5k
  size_t additional_elements{0};
7791
476k
  for (char32_t current_character : input) {
7792
476k
    size_t decomposition_length{0};
7793
7794
476k
    if (current_character >= hangul_sbase &&
7795
29.9k
        current_character < hangul_sbase + hangul_scount) {
7796
27.0k
      decomposition_length = 2;
7797
27.0k
      if ((current_character - hangul_sbase) % hangul_tcount) {
7798
12.0k
        decomposition_length = 3;
7799
12.0k
      }
7800
449k
    } else if (current_character < 0x110000) {
7801
449k
      const uint8_t di = decomposition_index[current_character >> 8];
7802
449k
      const uint16_t* const decomposition =
7803
449k
          decomposition_block[di] + (current_character % 256);
7804
449k
      decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
7805
449k
      if ((decomposition_length > 0) && (decomposition[0] & 1)) {
7806
0
        decomposition_length = 0;
7807
0
      }
7808
449k
    }
7809
476k
    if (decomposition_length != 0) {
7810
31.5k
      decomposition_needed = true;
7811
31.5k
      additional_elements += decomposition_length - 1;
7812
31.5k
    }
7813
476k
  }
7814
12.5k
  return {decomposition_needed, additional_elements};
7815
12.5k
}
7816
7817
3.85k
void decompose(std::u32string& input, size_t additional_elements) {
7818
3.85k
  input.resize(input.size() + additional_elements);
7819
3.85k
  for (size_t descending_idx = input.size(),
7820
3.85k
              input_count = descending_idx - additional_elements;
7821
238k
       input_count--;) {
7822
234k
    if (input[input_count] >= hangul_sbase &&
7823
28.0k
        input[input_count] < hangul_sbase + hangul_scount) {
7824
      // Hangul decomposition.
7825
27.0k
      char32_t s_index = input[input_count] - hangul_sbase;
7826
27.0k
      if (s_index % hangul_tcount != 0) {
7827
12.0k
        input[--descending_idx] = hangul_tbase + s_index % hangul_tcount;
7828
12.0k
      }
7829
27.0k
      input[--descending_idx] =
7830
27.0k
          hangul_vbase + (s_index % hangul_ncount) / hangul_tcount;
7831
27.0k
      input[--descending_idx] = hangul_lbase + s_index / hangul_ncount;
7832
207k
    } else if (input[input_count] < 0x110000) {
7833
      // Check decomposition_data.
7834
207k
      const uint16_t* decomposition =
7835
207k
          decomposition_block[decomposition_index[input[input_count] >> 8]] +
7836
207k
          (input[input_count] % 256);
7837
207k
      uint16_t decomposition_length =
7838
207k
          (decomposition[1] >> 2) - (decomposition[0] >> 2);
7839
207k
      if (decomposition_length > 0 && (decomposition[0] & 1)) {
7840
0
        decomposition_length = 0;
7841
0
      }
7842
207k
      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
202k
      } else {
7849
        // No decomposition.
7850
202k
        input[--descending_idx] = input[input_count];
7851
202k
      }
7852
207k
    } else {
7853
      // Non-Unicode character.
7854
0
      input[--descending_idx] = input[input_count];
7855
0
    }
7856
234k
  }
7857
3.85k
}
7858
7859
965k
uint8_t get_ccc(char32_t c) noexcept {
7860
965k
  return c < 0x110000 ? canonical_combining_class_block
7861
965k
                            [canonical_combining_class_index[c >> 8]][c % 256]
7862
965k
                      : 0;
7863
965k
}
7864
7865
12.5k
void sort_marks(std::u32string& input) {
7866
521k
  for (size_t idx = 1; idx < input.size(); idx++) {
7867
508k
    uint8_t ccc = get_ccc(input[idx]);
7868
508k
    if (ccc == 0) {
7869
495k
      continue;
7870
495k
    }  // Skip non-combining characters.
7871
12.8k
    auto current_character = input[idx];
7872
12.8k
    size_t back_idx = idx;
7873
14.5k
    while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) {
7874
1.63k
      input[back_idx] = input[back_idx - 1];
7875
1.63k
      back_idx--;
7876
1.63k
    }
7877
12.8k
    input[back_idx] = current_character;
7878
12.8k
  }
7879
12.5k
}
7880
7881
12.5k
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
12.5k
  auto [decomposition_needed, additional_elements] =
7887
12.5k
      compute_decomposition_length(input);
7888
12.5k
  if (decomposition_needed) {
7889
3.85k
    decompose(input, additional_elements);
7890
3.85k
  }
7891
12.5k
  sort_marks(input);
7892
12.5k
}
7893
7894
12.5k
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
12.5k
  size_t input_count{0};
7900
12.5k
  size_t composition_count{0};
7901
481k
  for (; input_count < input.size(); input_count++, composition_count++) {
7902
469k
    input[composition_count] = input[input_count];
7903
469k
    if (input[input_count] >= hangul_lbase &&
7904
228k
        input[input_count] < hangul_lbase + hangul_lcount) {
7905
28.3k
      if (input_count + 1 < input.size() &&
7906
28.1k
          input[input_count + 1] >= hangul_vbase &&
7907
27.3k
          input[input_count + 1] < hangul_vbase + hangul_vcount) {
7908
27.0k
        input[composition_count] =
7909
27.0k
            hangul_sbase +
7910
27.0k
            ((input[input_count] - hangul_lbase) * hangul_vcount +
7911
27.0k
             input[input_count + 1] - hangul_vbase) *
7912
27.0k
                hangul_tcount;
7913
27.0k
        input_count++;
7914
27.0k
        if (input_count + 1 < input.size() &&
7915
26.8k
            input[input_count + 1] > hangul_tbase &&
7916
12.4k
            input[input_count + 1] < hangul_tbase + hangul_tcount) {
7917
12.0k
          input[composition_count] += input[++input_count] - hangul_tbase;
7918
12.0k
        }
7919
27.0k
      }
7920
440k
    } else if (input[input_count] >= hangul_sbase &&
7921
2.15k
               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
440k
    } else if (input[input_count] < 0x110000) {
7929
440k
      const uint16_t* composition =
7930
440k
          &composition_block[composition_index[input[input_count] >> 8]]
7931
440k
                            [input[input_count] % 256];
7932
440k
      size_t initial_composition_count = composition_count;
7933
453k
      for (int32_t previous_ccc = -1; input_count + 1 < input.size();
7934
441k
           input_count++) {
7935
441k
        uint8_t ccc = get_ccc(input[input_count + 1]);
7936
7937
441k
        if (composition[1] != composition[0] && previous_ccc < ccc) {
7938
          // Try finding a composition.
7939
95.8k
          int left = composition[0];
7940
95.8k
          int right = composition[1];
7941
240k
          while (left + 2 < right) {
7942
            // mean without overflow
7943
145k
            int middle = left + (((right - left) >> 1) & ~1);
7944
145k
            if (composition_data[middle] <= input[input_count + 1]) {
7945
10.1k
              left = middle;
7946
10.1k
            }
7947
145k
            if (composition_data[middle] >= input[input_count + 1]) {
7948
138k
              right = middle;
7949
138k
            }
7950
145k
          }
7951
95.8k
          if (composition_data[left] == input[input_count + 1]) {
7952
5.67k
            input[initial_composition_count] = composition_data[left + 1];
7953
5.67k
            composition =
7954
5.67k
                &composition_block
7955
5.67k
                    [composition_index[composition_data[left + 1] >> 8]]
7956
5.67k
                    [composition_data[left + 1] % 256];
7957
5.67k
            continue;
7958
5.67k
          }
7959
95.8k
        }
7960
7961
436k
        if (ccc == 0) {
7962
429k
          break;
7963
429k
        }  // Not a combining character.
7964
7.21k
        previous_ccc = ccc;
7965
7.21k
        input[++composition_count] = input[input_count + 1];
7966
7.21k
      }
7967
440k
    }
7968
469k
  }
7969
7970
12.5k
  if (composition_count < input_count) {
7971
3.88k
    input.resize(composition_count);
7972
3.88k
  }
7973
12.5k
}
7974
7975
12.5k
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
12.5k
  decompose_nfc(input);
7981
12.5k
  compose(input);
7982
12.5k
}
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
55.1k
static constexpr int32_t char_to_digit_value(char value) {
8001
55.1k
  if (value >= 'a' && value <= 'z') return value - 'a';
8002
7.13k
  if (value >= '0' && value <= '9') return value - '0' + 26;
8003
72
  return -1;
8004
7.13k
}
8005
8006
695k
static constexpr char digit_to_char(int32_t digit) {
8007
695k
  return digit < 26 ? char(digit + 97) : char(digit + 22);
8008
695k
}
8009
8010
309k
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
8011
309k
  if (firsttime) {
8012
37.8k
    d = d / damp;
8013
271k
  } else {
8014
271k
    d = d / 2;
8015
271k
  }
8016
309k
  d += d / n;
8017
309k
  int32_t k = 0;
8018
457k
  while (d > ((base - tmin) * tmax) / 2) {
8019
147k
    d /= base - tmin;
8020
147k
    k += base;
8021
147k
  }
8022
309k
  return k + (((base - tmin + 1) * d) / (d + skew));
8023
309k
}
8024
8025
5.73k
bool punycode_to_utf32(std::string_view input, std::u32string &out) {
8026
  // See https://github.com/whatwg/url/issues/803
8027
5.73k
  if (input.starts_with("xn--")) {
8028
6
    return false;
8029
6
  }
8030
5.72k
  int32_t written_out{0};
8031
5.72k
  out.reserve(out.size() + input.size());
8032
5.72k
  uint32_t n = initial_n;
8033
5.72k
  int32_t i = 0;
8034
5.72k
  int32_t bias = initial_bias;
8035
  // grab ascii content
8036
5.72k
  size_t end_of_ascii = input.find_last_of('-');
8037
5.72k
  if (end_of_ascii != std::string_view::npos) {
8038
7.30k
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8039
7.30k
      if (c >= 0x80) {
8040
0
        return false;
8041
0
      }
8042
7.30k
      out.push_back(c);
8043
7.30k
      written_out++;
8044
7.30k
    }
8045
516
    input.remove_prefix(end_of_ascii + 1);
8046
516
  }
8047
46.2k
  while (!input.empty()) {
8048
40.8k
    int32_t oldi = i;
8049
40.8k
    int32_t w = 1;
8050
55.3k
    for (int32_t k = base;; k += base) {
8051
55.3k
      if (input.empty()) {
8052
188
        return false;
8053
188
      }
8054
55.1k
      uint8_t code_point = input.front();
8055
55.1k
      input.remove_prefix(1);
8056
55.1k
      int32_t digit = char_to_digit_value(code_point);
8057
55.1k
      if (digit < 0) {
8058
72
        return false;
8059
72
      }
8060
55.1k
      if (digit > (0x7fffffff - i) / w) {
8061
22
        return false;
8062
22
      }
8063
55.0k
      i = i + digit * w;
8064
55.0k
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8065
55.0k
      if (digit < t) {
8066
40.5k
        break;
8067
40.5k
      }
8068
14.4k
      if (w > 0x7fffffff / (base - t)) {
8069
0
        return false;
8070
0
      }
8071
14.4k
      w = w * (base - t);
8072
14.4k
    }
8073
40.5k
    bias = adapt(i - oldi, written_out + 1, oldi == 0);
8074
40.5k
    if (i / (written_out + 1) > int32_t(0x7fffffff - n)) {
8075
92
      return false;
8076
92
    }
8077
40.5k
    n = n + i / (written_out + 1);
8078
40.5k
    i = i % (written_out + 1);
8079
40.5k
    if (n < 0x80) {
8080
0
      return false;
8081
0
    }
8082
40.5k
    out.insert(out.begin() + i, n);
8083
40.5k
    written_out++;
8084
40.5k
    ++i;
8085
40.5k
  }
8086
5.35k
  return true;
8087
5.72k
}
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
32.5k
bool utf32_to_punycode(std::u32string_view input, std::string &out) {
8151
32.5k
  out.reserve(input.size() + out.size());
8152
32.5k
  uint32_t n = initial_n;
8153
32.5k
  int32_t d = 0;
8154
32.5k
  int32_t bias = initial_bias;
8155
32.5k
  size_t h = 0;
8156
  // first push the ascii content
8157
308k
  for (uint32_t c : input) {
8158
308k
    if (c < 0x80) {
8159
39.4k
      ++h;
8160
39.4k
      out.push_back(char(c));
8161
39.4k
    }
8162
308k
    if (c > 0x10ffff || (c >= 0xd800 && c < 0xe000)) {
8163
0
      return false;
8164
0
    }
8165
308k
  }
8166
32.5k
  size_t b = h;
8167
32.5k
  if (b > 0) {
8168
11.6k
    out.push_back('-');
8169
11.6k
  }
8170
212k
  while (h < input.size()) {
8171
180k
    uint32_t m = 0x10FFFF;
8172
3.06M
    for (auto code_point : input) {
8173
3.06M
      if (code_point >= n && code_point < m) m = code_point;
8174
3.06M
    }
8175
8176
180k
    if ((m - n) > (0x7fffffff - d) / (h + 1)) {
8177
0
      return false;
8178
0
    }
8179
180k
    d = d + int32_t((m - n) * (h + 1));
8180
180k
    n = m;
8181
3.06M
    for (auto c : input) {
8182
3.06M
      if (c < n) {
8183
1.62M
        if (d == 0x7fffffff) {
8184
0
          return false;
8185
0
        }
8186
1.62M
        ++d;
8187
1.62M
      }
8188
3.06M
      if (c == n) {
8189
268k
        int32_t q = d;
8190
695k
        for (int32_t k = base;; k += base) {
8191
695k
          int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8192
8193
695k
          if (q < t) {
8194
268k
            break;
8195
268k
          }
8196
426k
          out.push_back(digit_to_char(t + ((q - t) % (base - t))));
8197
426k
          q = (q - t) / (base - t);
8198
426k
        }
8199
268k
        out.push_back(digit_to_char(q));
8200
268k
        bias = adapt(d, int32_t(h + 1), h == b);
8201
268k
        d = 0;
8202
268k
        ++h;
8203
268k
      }
8204
3.06M
    }
8205
180k
    ++d;
8206
180k
    ++n;
8207
180k
  }
8208
32.5k
  return true;
8209
32.5k
}
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
359k
inline static direction find_direction(uint32_t code_point) noexcept {
8982
359k
  auto it = std::lower_bound(
8983
359k
      std::begin(dir_table), std::end(dir_table), code_point,
8984
3.68M
      [](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
359k
  if (it == std::end(dir_table)) {
8988
0
    return direction::NONE;
8989
0
  }
8990
  // We have that d.final_code >= c.
8991
359k
  if (code_point >= it->start_code) {
8992
358k
    return it->direct;
8993
358k
  }
8994
930
  return direction::NONE;
8995
359k
}
8996
8997
inline static size_t find_last_not_of_nsm(
8998
36.0k
    const std::u32string_view label) noexcept {
8999
38.9k
  for (int i = static_cast<int>(label.size() - 1); i >= 0; i--)
9000
38.9k
    if (find_direction(label[i]) != direction::NSM) return i;
9001
9002
0
  return std::u32string_view::npos;
9003
36.0k
}
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
36.0k
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
9008
36.0k
  const size_t mask =
9009
36.0k
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
9010
9011
36.0k
  size_t directions = 0;
9012
343k
  for (size_t i = 0; i < label.size(); i++) {
9013
307k
    directions |= 1u << find_direction(label[i]);
9014
307k
  }
9015
36.0k
  return (directions & mask) != 0;
9016
36.0k
}
9017
9018
38.0k
bool is_label_valid(const std::u32string_view label) {
9019
38.0k
  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
38.0k
  constexpr static uint32_t combining[] = {
9045
38.0k
      0x300,   0x301,   0x302,   0x303,   0x304,   0x305,   0x306,   0x307,
9046
38.0k
      0x308,   0x309,   0x30a,   0x30b,   0x30c,   0x30d,   0x30e,   0x30f,
9047
38.0k
      0x310,   0x311,   0x312,   0x313,   0x314,   0x315,   0x316,   0x317,
9048
38.0k
      0x318,   0x319,   0x31a,   0x31b,   0x31c,   0x31d,   0x31e,   0x31f,
9049
38.0k
      0x320,   0x321,   0x322,   0x323,   0x324,   0x325,   0x326,   0x327,
9050
38.0k
      0x328,   0x329,   0x32a,   0x32b,   0x32c,   0x32d,   0x32e,   0x32f,
9051
38.0k
      0x330,   0x331,   0x332,   0x333,   0x334,   0x335,   0x336,   0x337,
9052
38.0k
      0x338,   0x339,   0x33a,   0x33b,   0x33c,   0x33d,   0x33e,   0x33f,
9053
38.0k
      0x340,   0x341,   0x342,   0x343,   0x344,   0x345,   0x346,   0x347,
9054
38.0k
      0x348,   0x349,   0x34a,   0x34b,   0x34c,   0x34d,   0x34e,   0x34f,
9055
38.0k
      0x350,   0x351,   0x352,   0x353,   0x354,   0x355,   0x356,   0x357,
9056
38.0k
      0x358,   0x359,   0x35a,   0x35b,   0x35c,   0x35d,   0x35e,   0x35f,
9057
38.0k
      0x360,   0x361,   0x362,   0x363,   0x364,   0x365,   0x366,   0x367,
9058
38.0k
      0x368,   0x369,   0x36a,   0x36b,   0x36c,   0x36d,   0x36e,   0x36f,
9059
38.0k
      0x483,   0x484,   0x485,   0x486,   0x487,   0x488,   0x489,   0x591,
9060
38.0k
      0x592,   0x593,   0x594,   0x595,   0x596,   0x597,   0x598,   0x599,
9061
38.0k
      0x59a,   0x59b,   0x59c,   0x59d,   0x59e,   0x59f,   0x5a0,   0x5a1,
9062
38.0k
      0x5a2,   0x5a3,   0x5a4,   0x5a5,   0x5a6,   0x5a7,   0x5a8,   0x5a9,
9063
38.0k
      0x5aa,   0x5ab,   0x5ac,   0x5ad,   0x5ae,   0x5af,   0x5b0,   0x5b1,
9064
38.0k
      0x5b2,   0x5b3,   0x5b4,   0x5b5,   0x5b6,   0x5b7,   0x5b8,   0x5b9,
9065
38.0k
      0x5ba,   0x5bb,   0x5bc,   0x5bd,   0x5bf,   0x5c1,   0x5c2,   0x5c4,
9066
38.0k
      0x5c5,   0x5c7,   0x610,   0x611,   0x612,   0x613,   0x614,   0x615,
9067
38.0k
      0x616,   0x617,   0x618,   0x619,   0x61a,   0x64b,   0x64c,   0x64d,
9068
38.0k
      0x64e,   0x64f,   0x650,   0x651,   0x652,   0x653,   0x654,   0x655,
9069
38.0k
      0x656,   0x657,   0x658,   0x659,   0x65a,   0x65b,   0x65c,   0x65d,
9070
38.0k
      0x65e,   0x65f,   0x670,   0x6d6,   0x6d7,   0x6d8,   0x6d9,   0x6da,
9071
38.0k
      0x6db,   0x6dc,   0x6df,   0x6e0,   0x6e1,   0x6e2,   0x6e3,   0x6e4,
9072
38.0k
      0x6e7,   0x6e8,   0x6ea,   0x6eb,   0x6ec,   0x6ed,   0x711,   0x730,
9073
38.0k
      0x731,   0x732,   0x733,   0x734,   0x735,   0x736,   0x737,   0x738,
9074
38.0k
      0x739,   0x73a,   0x73b,   0x73c,   0x73d,   0x73e,   0x73f,   0x740,
9075
38.0k
      0x741,   0x742,   0x743,   0x744,   0x745,   0x746,   0x747,   0x748,
9076
38.0k
      0x749,   0x74a,   0x7a6,   0x7a7,   0x7a8,   0x7a9,   0x7aa,   0x7ab,
9077
38.0k
      0x7ac,   0x7ad,   0x7ae,   0x7af,   0x7b0,   0x7eb,   0x7ec,   0x7ed,
9078
38.0k
      0x7ee,   0x7ef,   0x7f0,   0x7f1,   0x7f2,   0x7f3,   0x7fd,   0x816,
9079
38.0k
      0x817,   0x818,   0x819,   0x81b,   0x81c,   0x81d,   0x81e,   0x81f,
9080
38.0k
      0x820,   0x821,   0x822,   0x823,   0x825,   0x826,   0x827,   0x829,
9081
38.0k
      0x82a,   0x82b,   0x82c,   0x82d,   0x859,   0x85a,   0x85b,   0x8d3,
9082
38.0k
      0x8d4,   0x8d5,   0x8d6,   0x8d7,   0x8d8,   0x8d9,   0x8da,   0x8db,
9083
38.0k
      0x8dc,   0x8dd,   0x8de,   0x8df,   0x8e0,   0x8e1,   0x8e3,   0x8e4,
9084
38.0k
      0x8e5,   0x8e6,   0x8e7,   0x8e8,   0x8e9,   0x8ea,   0x8eb,   0x8ec,
9085
38.0k
      0x8ed,   0x8ee,   0x8ef,   0x8f0,   0x8f1,   0x8f2,   0x8f3,   0x8f4,
9086
38.0k
      0x8f5,   0x8f6,   0x8f7,   0x8f8,   0x8f9,   0x8fa,   0x8fb,   0x8fc,
9087
38.0k
      0x8fd,   0x8fe,   0x8ff,   0x900,   0x901,   0x902,   0x903,   0x93a,
9088
38.0k
      0x93b,   0x93c,   0x93e,   0x93f,   0x940,   0x941,   0x942,   0x943,
9089
38.0k
      0x944,   0x945,   0x946,   0x947,   0x948,   0x949,   0x94a,   0x94b,
9090
38.0k
      0x94c,   0x94d,   0x94e,   0x94f,   0x951,   0x952,   0x953,   0x954,
9091
38.0k
      0x955,   0x956,   0x957,   0x962,   0x963,   0x981,   0x982,   0x983,
9092
38.0k
      0x9bc,   0x9be,   0x9bf,   0x9c0,   0x9c1,   0x9c2,   0x9c3,   0x9c4,
9093
38.0k
      0x9c7,   0x9c8,   0x9cb,   0x9cc,   0x9cd,   0x9d7,   0x9e2,   0x9e3,
9094
38.0k
      0x9fe,   0xa01,   0xa02,   0xa03,   0xa3c,   0xa3e,   0xa3f,   0xa40,
9095
38.0k
      0xa41,   0xa42,   0xa47,   0xa48,   0xa4b,   0xa4c,   0xa4d,   0xa51,
9096
38.0k
      0xa70,   0xa71,   0xa75,   0xa81,   0xa82,   0xa83,   0xabc,   0xabe,
9097
38.0k
      0xabf,   0xac0,   0xac1,   0xac2,   0xac3,   0xac4,   0xac5,   0xac7,
9098
38.0k
      0xac8,   0xac9,   0xacb,   0xacc,   0xacd,   0xae2,   0xae3,   0xafa,
9099
38.0k
      0xafb,   0xafc,   0xafd,   0xafe,   0xaff,   0xb01,   0xb02,   0xb03,
9100
38.0k
      0xb3c,   0xb3e,   0xb3f,   0xb40,   0xb41,   0xb42,   0xb43,   0xb44,
9101
38.0k
      0xb47,   0xb48,   0xb4b,   0xb4c,   0xb4d,   0xb55,   0xb56,   0xb57,
9102
38.0k
      0xb62,   0xb63,   0xb82,   0xbbe,   0xbbf,   0xbc0,   0xbc1,   0xbc2,
9103
38.0k
      0xbc6,   0xbc7,   0xbc8,   0xbca,   0xbcb,   0xbcc,   0xbcd,   0xbd7,
9104
38.0k
      0xc00,   0xc01,   0xc02,   0xc03,   0xc04,   0xc3e,   0xc3f,   0xc40,
9105
38.0k
      0xc41,   0xc42,   0xc43,   0xc44,   0xc46,   0xc47,   0xc48,   0xc4a,
9106
38.0k
      0xc4b,   0xc4c,   0xc4d,   0xc55,   0xc56,   0xc62,   0xc63,   0xc81,
9107
38.0k
      0xc82,   0xc83,   0xcbc,   0xcbe,   0xcbf,   0xcc0,   0xcc1,   0xcc2,
9108
38.0k
      0xcc3,   0xcc4,   0xcc6,   0xcc7,   0xcc8,   0xcca,   0xccb,   0xccc,
9109
38.0k
      0xccd,   0xcd5,   0xcd6,   0xce2,   0xce3,   0xd00,   0xd01,   0xd02,
9110
38.0k
      0xd03,   0xd3b,   0xd3c,   0xd3e,   0xd3f,   0xd40,   0xd41,   0xd42,
9111
38.0k
      0xd43,   0xd44,   0xd46,   0xd47,   0xd48,   0xd4a,   0xd4b,   0xd4c,
9112
38.0k
      0xd4d,   0xd57,   0xd62,   0xd63,   0xd81,   0xd82,   0xd83,   0xdca,
9113
38.0k
      0xdcf,   0xdd0,   0xdd1,   0xdd2,   0xdd3,   0xdd4,   0xdd6,   0xdd8,
9114
38.0k
      0xdd9,   0xdda,   0xddb,   0xddc,   0xddd,   0xdde,   0xddf,   0xdf2,
9115
38.0k
      0xdf3,   0xe31,   0xe34,   0xe35,   0xe36,   0xe37,   0xe38,   0xe39,
9116
38.0k
      0xe3a,   0xe47,   0xe48,   0xe49,   0xe4a,   0xe4b,   0xe4c,   0xe4d,
9117
38.0k
      0xe4e,   0xeb1,   0xeb4,   0xeb5,   0xeb6,   0xeb7,   0xeb8,   0xeb9,
9118
38.0k
      0xeba,   0xebb,   0xebc,   0xec8,   0xec9,   0xeca,   0xecb,   0xecc,
9119
38.0k
      0xecd,   0xf18,   0xf19,   0xf35,   0xf37,   0xf39,   0xf3e,   0xf3f,
9120
38.0k
      0xf71,   0xf72,   0xf73,   0xf74,   0xf75,   0xf76,   0xf77,   0xf78,
9121
38.0k
      0xf79,   0xf7a,   0xf7b,   0xf7c,   0xf7d,   0xf7e,   0xf7f,   0xf80,
9122
38.0k
      0xf81,   0xf82,   0xf83,   0xf84,   0xf86,   0xf87,   0xf8d,   0xf8e,
9123
38.0k
      0xf8f,   0xf90,   0xf91,   0xf92,   0xf93,   0xf94,   0xf95,   0xf96,
9124
38.0k
      0xf97,   0xf99,   0xf9a,   0xf9b,   0xf9c,   0xf9d,   0xf9e,   0xf9f,
9125
38.0k
      0xfa0,   0xfa1,   0xfa2,   0xfa3,   0xfa4,   0xfa5,   0xfa6,   0xfa7,
9126
38.0k
      0xfa8,   0xfa9,   0xfaa,   0xfab,   0xfac,   0xfad,   0xfae,   0xfaf,
9127
38.0k
      0xfb0,   0xfb1,   0xfb2,   0xfb3,   0xfb4,   0xfb5,   0xfb6,   0xfb7,
9128
38.0k
      0xfb8,   0xfb9,   0xfba,   0xfbb,   0xfbc,   0xfc6,   0x102b,  0x102c,
9129
38.0k
      0x102d,  0x102e,  0x102f,  0x1030,  0x1031,  0x1032,  0x1033,  0x1034,
9130
38.0k
      0x1035,  0x1036,  0x1037,  0x1038,  0x1039,  0x103a,  0x103b,  0x103c,
9131
38.0k
      0x103d,  0x103e,  0x1056,  0x1057,  0x1058,  0x1059,  0x105e,  0x105f,
9132
38.0k
      0x1060,  0x1062,  0x1063,  0x1064,  0x1067,  0x1068,  0x1069,  0x106a,
9133
38.0k
      0x106b,  0x106c,  0x106d,  0x1071,  0x1072,  0x1073,  0x1074,  0x1082,
9134
38.0k
      0x1083,  0x1084,  0x1085,  0x1086,  0x1087,  0x1088,  0x1089,  0x108a,
9135
38.0k
      0x108b,  0x108c,  0x108d,  0x108f,  0x109a,  0x109b,  0x109c,  0x109d,
9136
38.0k
      0x135d,  0x135e,  0x135f,  0x1712,  0x1713,  0x1714,  0x1732,  0x1733,
9137
38.0k
      0x1734,  0x1752,  0x1753,  0x1772,  0x1773,  0x17b4,  0x17b5,  0x17b6,
9138
38.0k
      0x17b7,  0x17b8,  0x17b9,  0x17ba,  0x17bb,  0x17bc,  0x17bd,  0x17be,
9139
38.0k
      0x17bf,  0x17c0,  0x17c1,  0x17c2,  0x17c3,  0x17c4,  0x17c5,  0x17c6,
9140
38.0k
      0x17c7,  0x17c8,  0x17c9,  0x17ca,  0x17cb,  0x17cc,  0x17cd,  0x17ce,
9141
38.0k
      0x17cf,  0x17d0,  0x17d1,  0x17d2,  0x17d3,  0x17dd,  0x180b,  0x180c,
9142
38.0k
      0x180d,  0x1885,  0x1886,  0x18a9,  0x1920,  0x1921,  0x1922,  0x1923,
9143
38.0k
      0x1924,  0x1925,  0x1926,  0x1927,  0x1928,  0x1929,  0x192a,  0x192b,
9144
38.0k
      0x1930,  0x1931,  0x1932,  0x1933,  0x1934,  0x1935,  0x1936,  0x1937,
9145
38.0k
      0x1938,  0x1939,  0x193a,  0x193b,  0x1a17,  0x1a18,  0x1a19,  0x1a1a,
9146
38.0k
      0x1a1b,  0x1a55,  0x1a56,  0x1a57,  0x1a58,  0x1a59,  0x1a5a,  0x1a5b,
9147
38.0k
      0x1a5c,  0x1a5d,  0x1a5e,  0x1a60,  0x1a61,  0x1a62,  0x1a63,  0x1a64,
9148
38.0k
      0x1a65,  0x1a66,  0x1a67,  0x1a68,  0x1a69,  0x1a6a,  0x1a6b,  0x1a6c,
9149
38.0k
      0x1a6d,  0x1a6e,  0x1a6f,  0x1a70,  0x1a71,  0x1a72,  0x1a73,  0x1a74,
9150
38.0k
      0x1a75,  0x1a76,  0x1a77,  0x1a78,  0x1a79,  0x1a7a,  0x1a7b,  0x1a7c,
9151
38.0k
      0x1a7f,  0x1ab0,  0x1ab1,  0x1ab2,  0x1ab3,  0x1ab4,  0x1ab5,  0x1ab6,
9152
38.0k
      0x1ab7,  0x1ab8,  0x1ab9,  0x1aba,  0x1abb,  0x1abc,  0x1abd,  0x1abe,
9153
38.0k
      0x1abf,  0x1ac0,  0x1b00,  0x1b01,  0x1b02,  0x1b03,  0x1b04,  0x1b34,
9154
38.0k
      0x1b35,  0x1b36,  0x1b37,  0x1b38,  0x1b39,  0x1b3a,  0x1b3b,  0x1b3c,
9155
38.0k
      0x1b3d,  0x1b3e,  0x1b3f,  0x1b40,  0x1b41,  0x1b42,  0x1b43,  0x1b44,
9156
38.0k
      0x1b6b,  0x1b6c,  0x1b6d,  0x1b6e,  0x1b6f,  0x1b70,  0x1b71,  0x1b72,
9157
38.0k
      0x1b73,  0x1b80,  0x1b81,  0x1b82,  0x1ba1,  0x1ba2,  0x1ba3,  0x1ba4,
9158
38.0k
      0x1ba5,  0x1ba6,  0x1ba7,  0x1ba8,  0x1ba9,  0x1baa,  0x1bab,  0x1bac,
9159
38.0k
      0x1bad,  0x1be6,  0x1be7,  0x1be8,  0x1be9,  0x1bea,  0x1beb,  0x1bec,
9160
38.0k
      0x1bed,  0x1bee,  0x1bef,  0x1bf0,  0x1bf1,  0x1bf2,  0x1bf3,  0x1c24,
9161
38.0k
      0x1c25,  0x1c26,  0x1c27,  0x1c28,  0x1c29,  0x1c2a,  0x1c2b,  0x1c2c,
9162
38.0k
      0x1c2d,  0x1c2e,  0x1c2f,  0x1c30,  0x1c31,  0x1c32,  0x1c33,  0x1c34,
9163
38.0k
      0x1c35,  0x1c36,  0x1c37,  0x1cd0,  0x1cd1,  0x1cd2,  0x1cd4,  0x1cd5,
9164
38.0k
      0x1cd6,  0x1cd7,  0x1cd8,  0x1cd9,  0x1cda,  0x1cdb,  0x1cdc,  0x1cdd,
9165
38.0k
      0x1cde,  0x1cdf,  0x1ce0,  0x1ce1,  0x1ce2,  0x1ce3,  0x1ce4,  0x1ce5,
9166
38.0k
      0x1ce6,  0x1ce7,  0x1ce8,  0x1ced,  0x1cf4,  0x1cf7,  0x1cf8,  0x1cf9,
9167
38.0k
      0x1dc0,  0x1dc1,  0x1dc2,  0x1dc3,  0x1dc4,  0x1dc5,  0x1dc6,  0x1dc7,
9168
38.0k
      0x1dc8,  0x1dc9,  0x1dca,  0x1dcb,  0x1dcc,  0x1dcd,  0x1dce,  0x1dcf,
9169
38.0k
      0x1dd0,  0x1dd1,  0x1dd2,  0x1dd3,  0x1dd4,  0x1dd5,  0x1dd6,  0x1dd7,
9170
38.0k
      0x1dd8,  0x1dd9,  0x1dda,  0x1ddb,  0x1ddc,  0x1ddd,  0x1dde,  0x1ddf,
9171
38.0k
      0x1de0,  0x1de1,  0x1de2,  0x1de3,  0x1de4,  0x1de5,  0x1de6,  0x1de7,
9172
38.0k
      0x1de8,  0x1de9,  0x1dea,  0x1deb,  0x1dec,  0x1ded,  0x1dee,  0x1def,
9173
38.0k
      0x1df0,  0x1df1,  0x1df2,  0x1df3,  0x1df4,  0x1df5,  0x1df6,  0x1df7,
9174
38.0k
      0x1df8,  0x1df9,  0x1dfb,  0x1dfc,  0x1dfd,  0x1dfe,  0x1dff,  0x20d0,
9175
38.0k
      0x20d1,  0x20d2,  0x20d3,  0x20d4,  0x20d5,  0x20d6,  0x20d7,  0x20d8,
9176
38.0k
      0x20d9,  0x20da,  0x20db,  0x20dc,  0x20dd,  0x20de,  0x20df,  0x20e0,
9177
38.0k
      0x20e1,  0x20e2,  0x20e3,  0x20e4,  0x20e5,  0x20e6,  0x20e7,  0x20e8,
9178
38.0k
      0x20e9,  0x20ea,  0x20eb,  0x20ec,  0x20ed,  0x20ee,  0x20ef,  0x20f0,
9179
38.0k
      0x2cef,  0x2cf0,  0x2cf1,  0x2d7f,  0x2de0,  0x2de1,  0x2de2,  0x2de3,
9180
38.0k
      0x2de4,  0x2de5,  0x2de6,  0x2de7,  0x2de8,  0x2de9,  0x2dea,  0x2deb,
9181
38.0k
      0x2dec,  0x2ded,  0x2dee,  0x2def,  0x2df0,  0x2df1,  0x2df2,  0x2df3,
9182
38.0k
      0x2df4,  0x2df5,  0x2df6,  0x2df7,  0x2df8,  0x2df9,  0x2dfa,  0x2dfb,
9183
38.0k
      0x2dfc,  0x2dfd,  0x2dfe,  0x2dff,  0x302a,  0x302b,  0x302c,  0x302d,
9184
38.0k
      0x302e,  0x302f,  0x3099,  0x309a,  0xa66f,  0xa670,  0xa671,  0xa672,
9185
38.0k
      0xa674,  0xa675,  0xa676,  0xa677,  0xa678,  0xa679,  0xa67a,  0xa67b,
9186
38.0k
      0xa67c,  0xa67d,  0xa69e,  0xa69f,  0xa6f0,  0xa6f1,  0xa802,  0xa806,
9187
38.0k
      0xa80b,  0xa823,  0xa824,  0xa825,  0xa826,  0xa827,  0xa82c,  0xa880,
9188
38.0k
      0xa881,  0xa8b4,  0xa8b5,  0xa8b6,  0xa8b7,  0xa8b8,  0xa8b9,  0xa8ba,
9189
38.0k
      0xa8bb,  0xa8bc,  0xa8bd,  0xa8be,  0xa8bf,  0xa8c0,  0xa8c1,  0xa8c2,
9190
38.0k
      0xa8c3,  0xa8c4,  0xa8c5,  0xa8e0,  0xa8e1,  0xa8e2,  0xa8e3,  0xa8e4,
9191
38.0k
      0xa8e5,  0xa8e6,  0xa8e7,  0xa8e8,  0xa8e9,  0xa8ea,  0xa8eb,  0xa8ec,
9192
38.0k
      0xa8ed,  0xa8ee,  0xa8ef,  0xa8f0,  0xa8f1,  0xa8ff,  0xa926,  0xa927,
9193
38.0k
      0xa928,  0xa929,  0xa92a,  0xa92b,  0xa92c,  0xa92d,  0xa947,  0xa948,
9194
38.0k
      0xa949,  0xa94a,  0xa94b,  0xa94c,  0xa94d,  0xa94e,  0xa94f,  0xa950,
9195
38.0k
      0xa951,  0xa952,  0xa953,  0xa980,  0xa981,  0xa982,  0xa983,  0xa9b3,
9196
38.0k
      0xa9b4,  0xa9b5,  0xa9b6,  0xa9b7,  0xa9b8,  0xa9b9,  0xa9ba,  0xa9bb,
9197
38.0k
      0xa9bc,  0xa9bd,  0xa9be,  0xa9bf,  0xa9c0,  0xa9e5,  0xaa29,  0xaa2a,
9198
38.0k
      0xaa2b,  0xaa2c,  0xaa2d,  0xaa2e,  0xaa2f,  0xaa30,  0xaa31,  0xaa32,
9199
38.0k
      0xaa33,  0xaa34,  0xaa35,  0xaa36,  0xaa43,  0xaa4c,  0xaa4d,  0xaa7b,
9200
38.0k
      0xaa7c,  0xaa7d,  0xaab0,  0xaab2,  0xaab3,  0xaab4,  0xaab7,  0xaab8,
9201
38.0k
      0xaabe,  0xaabf,  0xaac1,  0xaaeb,  0xaaec,  0xaaed,  0xaaee,  0xaaef,
9202
38.0k
      0xaaf5,  0xaaf6,  0xabe3,  0xabe4,  0xabe5,  0xabe6,  0xabe7,  0xabe8,
9203
38.0k
      0xabe9,  0xabea,  0xabec,  0xabed,  0xfb1e,  0xfe00,  0xfe01,  0xfe02,
9204
38.0k
      0xfe03,  0xfe04,  0xfe05,  0xfe06,  0xfe07,  0xfe08,  0xfe09,  0xfe0a,
9205
38.0k
      0xfe0b,  0xfe0c,  0xfe0d,  0xfe0e,  0xfe0f,  0xfe20,  0xfe21,  0xfe22,
9206
38.0k
      0xfe23,  0xfe24,  0xfe25,  0xfe26,  0xfe27,  0xfe28,  0xfe29,  0xfe2a,
9207
38.0k
      0xfe2b,  0xfe2c,  0xfe2d,  0xfe2e,  0xfe2f,  0x101fd, 0x102e0, 0x10376,
9208
38.0k
      0x10377, 0x10378, 0x10379, 0x1037a, 0x10a01, 0x10a02, 0x10a03, 0x10a05,
9209
38.0k
      0x10a06, 0x10a0c, 0x10a0d, 0x10a0e, 0x10a0f, 0x10a38, 0x10a39, 0x10a3a,
9210
38.0k
      0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d25, 0x10d26, 0x10d27, 0x10eab,
9211
38.0k
      0x10eac, 0x10f46, 0x10f47, 0x10f48, 0x10f49, 0x10f4a, 0x10f4b, 0x10f4c,
9212
38.0k
      0x10f4d, 0x10f4e, 0x10f4f, 0x10f50, 0x11000, 0x11001, 0x11002, 0x11038,
9213
38.0k
      0x11039, 0x1103a, 0x1103b, 0x1103c, 0x1103d, 0x1103e, 0x1103f, 0x11040,
9214
38.0k
      0x11041, 0x11042, 0x11043, 0x11044, 0x11045, 0x11046, 0x1107f, 0x11080,
9215
38.0k
      0x11081, 0x11082, 0x110b0, 0x110b1, 0x110b2, 0x110b3, 0x110b4, 0x110b5,
9216
38.0k
      0x110b6, 0x110b7, 0x110b8, 0x110b9, 0x110ba, 0x11100, 0x11101, 0x11102,
9217
38.0k
      0x11127, 0x11128, 0x11129, 0x1112a, 0x1112b, 0x1112c, 0x1112d, 0x1112e,
9218
38.0k
      0x1112f, 0x11130, 0x11131, 0x11132, 0x11133, 0x11134, 0x11145, 0x11146,
9219
38.0k
      0x11173, 0x11180, 0x11181, 0x11182, 0x111b3, 0x111b4, 0x111b5, 0x111b6,
9220
38.0k
      0x111b7, 0x111b8, 0x111b9, 0x111ba, 0x111bb, 0x111bc, 0x111bd, 0x111be,
9221
38.0k
      0x111bf, 0x111c0, 0x111c9, 0x111ca, 0x111cb, 0x111cc, 0x111ce, 0x111cf,
9222
38.0k
      0x1122c, 0x1122d, 0x1122e, 0x1122f, 0x11230, 0x11231, 0x11232, 0x11233,
9223
38.0k
      0x11234, 0x11235, 0x11236, 0x11237, 0x1123e, 0x112df, 0x112e0, 0x112e1,
9224
38.0k
      0x112e2, 0x112e3, 0x112e4, 0x112e5, 0x112e6, 0x112e7, 0x112e8, 0x112e9,
9225
38.0k
      0x112ea, 0x11300, 0x11301, 0x11302, 0x11303, 0x1133b, 0x1133c, 0x1133e,
9226
38.0k
      0x1133f, 0x11340, 0x11341, 0x11342, 0x11343, 0x11344, 0x11347, 0x11348,
9227
38.0k
      0x1134b, 0x1134c, 0x1134d, 0x11357, 0x11362, 0x11363, 0x11366, 0x11367,
9228
38.0k
      0x11368, 0x11369, 0x1136a, 0x1136b, 0x1136c, 0x11370, 0x11371, 0x11372,
9229
38.0k
      0x11373, 0x11374, 0x11435, 0x11436, 0x11437, 0x11438, 0x11439, 0x1143a,
9230
38.0k
      0x1143b, 0x1143c, 0x1143d, 0x1143e, 0x1143f, 0x11440, 0x11441, 0x11442,
9231
38.0k
      0x11443, 0x11444, 0x11445, 0x11446, 0x1145e, 0x114b0, 0x114b1, 0x114b2,
9232
38.0k
      0x114b3, 0x114b4, 0x114b5, 0x114b6, 0x114b7, 0x114b8, 0x114b9, 0x114ba,
9233
38.0k
      0x114bb, 0x114bc, 0x114bd, 0x114be, 0x114bf, 0x114c0, 0x114c1, 0x114c2,
9234
38.0k
      0x114c3, 0x115af, 0x115b0, 0x115b1, 0x115b2, 0x115b3, 0x115b4, 0x115b5,
9235
38.0k
      0x115b8, 0x115b9, 0x115ba, 0x115bb, 0x115bc, 0x115bd, 0x115be, 0x115bf,
9236
38.0k
      0x115c0, 0x115dc, 0x115dd, 0x11630, 0x11631, 0x11632, 0x11633, 0x11634,
9237
38.0k
      0x11635, 0x11636, 0x11637, 0x11638, 0x11639, 0x1163a, 0x1163b, 0x1163c,
9238
38.0k
      0x1163d, 0x1163e, 0x1163f, 0x11640, 0x116ab, 0x116ac, 0x116ad, 0x116ae,
9239
38.0k
      0x116af, 0x116b0, 0x116b1, 0x116b2, 0x116b3, 0x116b4, 0x116b5, 0x116b6,
9240
38.0k
      0x116b7, 0x1171d, 0x1171e, 0x1171f, 0x11720, 0x11721, 0x11722, 0x11723,
9241
38.0k
      0x11724, 0x11725, 0x11726, 0x11727, 0x11728, 0x11729, 0x1172a, 0x1172b,
9242
38.0k
      0x1182c, 0x1182d, 0x1182e, 0x1182f, 0x11830, 0x11831, 0x11832, 0x11833,
9243
38.0k
      0x11834, 0x11835, 0x11836, 0x11837, 0x11838, 0x11839, 0x1183a, 0x11930,
9244
38.0k
      0x11931, 0x11932, 0x11933, 0x11934, 0x11935, 0x11937, 0x11938, 0x1193b,
9245
38.0k
      0x1193c, 0x1193d, 0x1193e, 0x11940, 0x11942, 0x11943, 0x119d1, 0x119d2,
9246
38.0k
      0x119d3, 0x119d4, 0x119d5, 0x119d6, 0x119d7, 0x119da, 0x119db, 0x119dc,
9247
38.0k
      0x119dd, 0x119de, 0x119df, 0x119e0, 0x119e4, 0x11a01, 0x11a02, 0x11a03,
9248
38.0k
      0x11a04, 0x11a05, 0x11a06, 0x11a07, 0x11a08, 0x11a09, 0x11a0a, 0x11a33,
9249
38.0k
      0x11a34, 0x11a35, 0x11a36, 0x11a37, 0x11a38, 0x11a39, 0x11a3b, 0x11a3c,
9250
38.0k
      0x11a3d, 0x11a3e, 0x11a47, 0x11a51, 0x11a52, 0x11a53, 0x11a54, 0x11a55,
9251
38.0k
      0x11a56, 0x11a57, 0x11a58, 0x11a59, 0x11a5a, 0x11a5b, 0x11a8a, 0x11a8b,
9252
38.0k
      0x11a8c, 0x11a8d, 0x11a8e, 0x11a8f, 0x11a90, 0x11a91, 0x11a92, 0x11a93,
9253
38.0k
      0x11a94, 0x11a95, 0x11a96, 0x11a97, 0x11a98, 0x11a99, 0x11c2f, 0x11c30,
9254
38.0k
      0x11c31, 0x11c32, 0x11c33, 0x11c34, 0x11c35, 0x11c36, 0x11c38, 0x11c39,
9255
38.0k
      0x11c3a, 0x11c3b, 0x11c3c, 0x11c3d, 0x11c3e, 0x11c3f, 0x11c92, 0x11c93,
9256
38.0k
      0x11c94, 0x11c95, 0x11c96, 0x11c97, 0x11c98, 0x11c99, 0x11c9a, 0x11c9b,
9257
38.0k
      0x11c9c, 0x11c9d, 0x11c9e, 0x11c9f, 0x11ca0, 0x11ca1, 0x11ca2, 0x11ca3,
9258
38.0k
      0x11ca4, 0x11ca5, 0x11ca6, 0x11ca7, 0x11ca9, 0x11caa, 0x11cab, 0x11cac,
9259
38.0k
      0x11cad, 0x11cae, 0x11caf, 0x11cb0, 0x11cb1, 0x11cb2, 0x11cb3, 0x11cb4,
9260
38.0k
      0x11cb5, 0x11cb6, 0x11d31, 0x11d32, 0x11d33, 0x11d34, 0x11d35, 0x11d36,
9261
38.0k
      0x11d3a, 0x11d3c, 0x11d3d, 0x11d3f, 0x11d40, 0x11d41, 0x11d42, 0x11d43,
9262
38.0k
      0x11d44, 0x11d45, 0x11d47, 0x11d8a, 0x11d8b, 0x11d8c, 0x11d8d, 0x11d8e,
9263
38.0k
      0x11d90, 0x11d91, 0x11d93, 0x11d94, 0x11d95, 0x11d96, 0x11d97, 0x11ef3,
9264
38.0k
      0x11ef4, 0x11ef5, 0x11ef6, 0x16af0, 0x16af1, 0x16af2, 0x16af3, 0x16af4,
9265
38.0k
      0x16b30, 0x16b31, 0x16b32, 0x16b33, 0x16b34, 0x16b35, 0x16b36, 0x16f4f,
9266
38.0k
      0x16f51, 0x16f52, 0x16f53, 0x16f54, 0x16f55, 0x16f56, 0x16f57, 0x16f58,
9267
38.0k
      0x16f59, 0x16f5a, 0x16f5b, 0x16f5c, 0x16f5d, 0x16f5e, 0x16f5f, 0x16f60,
9268
38.0k
      0x16f61, 0x16f62, 0x16f63, 0x16f64, 0x16f65, 0x16f66, 0x16f67, 0x16f68,
9269
38.0k
      0x16f69, 0x16f6a, 0x16f6b, 0x16f6c, 0x16f6d, 0x16f6e, 0x16f6f, 0x16f70,
9270
38.0k
      0x16f71, 0x16f72, 0x16f73, 0x16f74, 0x16f75, 0x16f76, 0x16f77, 0x16f78,
9271
38.0k
      0x16f79, 0x16f7a, 0x16f7b, 0x16f7c, 0x16f7d, 0x16f7e, 0x16f7f, 0x16f80,
9272
38.0k
      0x16f81, 0x16f82, 0x16f83, 0x16f84, 0x16f85, 0x16f86, 0x16f87, 0x16f8f,
9273
38.0k
      0x16f90, 0x16f91, 0x16f92, 0x16fe4, 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e,
9274
38.0k
      0x1d165, 0x1d166, 0x1d167, 0x1d168, 0x1d169, 0x1d16d, 0x1d16e, 0x1d16f,
9275
38.0k
      0x1d170, 0x1d171, 0x1d172, 0x1d17b, 0x1d17c, 0x1d17d, 0x1d17e, 0x1d17f,
9276
38.0k
      0x1d180, 0x1d181, 0x1d182, 0x1d185, 0x1d186, 0x1d187, 0x1d188, 0x1d189,
9277
38.0k
      0x1d18a, 0x1d18b, 0x1d1aa, 0x1d1ab, 0x1d1ac, 0x1d1ad, 0x1d242, 0x1d243,
9278
38.0k
      0x1d244, 0x1da00, 0x1da01, 0x1da02, 0x1da03, 0x1da04, 0x1da05, 0x1da06,
9279
38.0k
      0x1da07, 0x1da08, 0x1da09, 0x1da0a, 0x1da0b, 0x1da0c, 0x1da0d, 0x1da0e,
9280
38.0k
      0x1da0f, 0x1da10, 0x1da11, 0x1da12, 0x1da13, 0x1da14, 0x1da15, 0x1da16,
9281
38.0k
      0x1da17, 0x1da18, 0x1da19, 0x1da1a, 0x1da1b, 0x1da1c, 0x1da1d, 0x1da1e,
9282
38.0k
      0x1da1f, 0x1da20, 0x1da21, 0x1da22, 0x1da23, 0x1da24, 0x1da25, 0x1da26,
9283
38.0k
      0x1da27, 0x1da28, 0x1da29, 0x1da2a, 0x1da2b, 0x1da2c, 0x1da2d, 0x1da2e,
9284
38.0k
      0x1da2f, 0x1da30, 0x1da31, 0x1da32, 0x1da33, 0x1da34, 0x1da35, 0x1da36,
9285
38.0k
      0x1da3b, 0x1da3c, 0x1da3d, 0x1da3e, 0x1da3f, 0x1da40, 0x1da41, 0x1da42,
9286
38.0k
      0x1da43, 0x1da44, 0x1da45, 0x1da46, 0x1da47, 0x1da48, 0x1da49, 0x1da4a,
9287
38.0k
      0x1da4b, 0x1da4c, 0x1da4d, 0x1da4e, 0x1da4f, 0x1da50, 0x1da51, 0x1da52,
9288
38.0k
      0x1da53, 0x1da54, 0x1da55, 0x1da56, 0x1da57, 0x1da58, 0x1da59, 0x1da5a,
9289
38.0k
      0x1da5b, 0x1da5c, 0x1da5d, 0x1da5e, 0x1da5f, 0x1da60, 0x1da61, 0x1da62,
9290
38.0k
      0x1da63, 0x1da64, 0x1da65, 0x1da66, 0x1da67, 0x1da68, 0x1da69, 0x1da6a,
9291
38.0k
      0x1da6b, 0x1da6c, 0x1da75, 0x1da84, 0x1da9b, 0x1da9c, 0x1da9d, 0x1da9e,
9292
38.0k
      0x1da9f, 0x1daa1, 0x1daa2, 0x1daa3, 0x1daa4, 0x1daa5, 0x1daa6, 0x1daa7,
9293
38.0k
      0x1daa8, 0x1daa9, 0x1daaa, 0x1daab, 0x1daac, 0x1daad, 0x1daae, 0x1daaf,
9294
38.0k
      0x1e000, 0x1e001, 0x1e002, 0x1e003, 0x1e004, 0x1e005, 0x1e006, 0x1e008,
9295
38.0k
      0x1e009, 0x1e00a, 0x1e00b, 0x1e00c, 0x1e00d, 0x1e00e, 0x1e00f, 0x1e010,
9296
38.0k
      0x1e011, 0x1e012, 0x1e013, 0x1e014, 0x1e015, 0x1e016, 0x1e017, 0x1e018,
9297
38.0k
      0x1e01b, 0x1e01c, 0x1e01d, 0x1e01e, 0x1e01f, 0x1e020, 0x1e021, 0x1e023,
9298
38.0k
      0x1e024, 0x1e026, 0x1e027, 0x1e028, 0x1e029, 0x1e02a, 0x1e130, 0x1e131,
9299
38.0k
      0x1e132, 0x1e133, 0x1e134, 0x1e135, 0x1e136, 0x1e2ec, 0x1e2ed, 0x1e2ee,
9300
38.0k
      0x1e2ef, 0x1e8d0, 0x1e8d1, 0x1e8d2, 0x1e8d3, 0x1e8d4, 0x1e8d5, 0x1e8d6,
9301
38.0k
      0x1e944, 0x1e945, 0x1e946, 0x1e947, 0x1e948, 0x1e949, 0x1e94a, 0xe0100,
9302
38.0k
      0xe0101, 0xe0102, 0xe0103, 0xe0104, 0xe0105, 0xe0106, 0xe0107, 0xe0108,
9303
38.0k
      0xe0109, 0xe010a, 0xe010b, 0xe010c, 0xe010d, 0xe010e, 0xe010f, 0xe0110,
9304
38.0k
      0xe0111, 0xe0112, 0xe0113, 0xe0114, 0xe0115, 0xe0116, 0xe0117, 0xe0118,
9305
38.0k
      0xe0119, 0xe011a, 0xe011b, 0xe011c, 0xe011d, 0xe011e, 0xe011f, 0xe0120,
9306
38.0k
      0xe0121, 0xe0122, 0xe0123, 0xe0124, 0xe0125, 0xe0126, 0xe0127, 0xe0128,
9307
38.0k
      0xe0129, 0xe012a, 0xe012b, 0xe012c, 0xe012d, 0xe012e, 0xe012f, 0xe0130,
9308
38.0k
      0xe0131, 0xe0132, 0xe0133, 0xe0134, 0xe0135, 0xe0136, 0xe0137, 0xe0138,
9309
38.0k
      0xe0139, 0xe013a, 0xe013b, 0xe013c, 0xe013d, 0xe013e, 0xe013f, 0xe0140,
9310
38.0k
      0xe0141, 0xe0142, 0xe0143, 0xe0144, 0xe0145, 0xe0146, 0xe0147, 0xe0148,
9311
38.0k
      0xe0149, 0xe014a, 0xe014b, 0xe014c, 0xe014d, 0xe014e, 0xe014f, 0xe0150,
9312
38.0k
      0xe0151, 0xe0152, 0xe0153, 0xe0154, 0xe0155, 0xe0156, 0xe0157, 0xe0158,
9313
38.0k
      0xe0159, 0xe015a, 0xe015b, 0xe015c, 0xe015d, 0xe015e, 0xe015f, 0xe0160,
9314
38.0k
      0xe0161, 0xe0162, 0xe0163, 0xe0164, 0xe0165, 0xe0166, 0xe0167, 0xe0168,
9315
38.0k
      0xe0169, 0xe016a, 0xe016b, 0xe016c, 0xe016d, 0xe016e, 0xe016f, 0xe0170,
9316
38.0k
      0xe0171, 0xe0172, 0xe0173, 0xe0174, 0xe0175, 0xe0176, 0xe0177, 0xe0178,
9317
38.0k
      0xe0179, 0xe017a, 0xe017b, 0xe017c, 0xe017d, 0xe017e, 0xe017f, 0xe0180,
9318
38.0k
      0xe0181, 0xe0182, 0xe0183, 0xe0184, 0xe0185, 0xe0186, 0xe0187, 0xe0188,
9319
38.0k
      0xe0189, 0xe018a, 0xe018b, 0xe018c, 0xe018d, 0xe018e, 0xe018f, 0xe0190,
9320
38.0k
      0xe0191, 0xe0192, 0xe0193, 0xe0194, 0xe0195, 0xe0196, 0xe0197, 0xe0198,
9321
38.0k
      0xe0199, 0xe019a, 0xe019b, 0xe019c, 0xe019d, 0xe019e, 0xe019f, 0xe01a0,
9322
38.0k
      0xe01a1, 0xe01a2, 0xe01a3, 0xe01a4, 0xe01a5, 0xe01a6, 0xe01a7, 0xe01a8,
9323
38.0k
      0xe01a9, 0xe01aa, 0xe01ab, 0xe01ac, 0xe01ad, 0xe01ae, 0xe01af, 0xe01b0,
9324
38.0k
      0xe01b1, 0xe01b2, 0xe01b3, 0xe01b4, 0xe01b5, 0xe01b6, 0xe01b7, 0xe01b8,
9325
38.0k
      0xe01b9, 0xe01ba, 0xe01bb, 0xe01bc, 0xe01bd, 0xe01be, 0xe01bf, 0xe01c0,
9326
38.0k
      0xe01c1, 0xe01c2, 0xe01c3, 0xe01c4, 0xe01c5, 0xe01c6, 0xe01c7, 0xe01c8,
9327
38.0k
      0xe01c9, 0xe01ca, 0xe01cb, 0xe01cc, 0xe01cd, 0xe01ce, 0xe01cf, 0xe01d0,
9328
38.0k
      0xe01d1, 0xe01d2, 0xe01d3, 0xe01d4, 0xe01d5, 0xe01d6, 0xe01d7, 0xe01d8,
9329
38.0k
      0xe01d9, 0xe01da, 0xe01db, 0xe01dc, 0xe01dd, 0xe01de, 0xe01df, 0xe01e0,
9330
38.0k
      0xe01e1, 0xe01e2, 0xe01e3, 0xe01e4, 0xe01e5, 0xe01e6, 0xe01e7, 0xe01e8,
9331
38.0k
      0xe01e9, 0xe01ea, 0xe01eb, 0xe01ec, 0xe01ed, 0xe01ee, 0xe01ef};
9332
38.0k
  if (std::binary_search(std::begin(combining), std::end(combining),
9333
38.0k
                         label.front())) {
9334
130
    return false;
9335
130
  }
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
37.8k
  constexpr static uint32_t virama[] = {
9348
37.8k
      0x094D,  0x09CD,  0x0A4D,  0x0ACD,  0x0B4D,  0x0BCD,  0x0C4D,  0x0CCD,
9349
37.8k
      0x0D3B,  0x0D3C,  0x0D4D,  0x0DCA,  0x0E3A,  0x0EBA,  0x0F84,  0x1039,
9350
37.8k
      0x103A,  0x1714,  0x1734,  0x17D2,  0x1A60,  0x1B44,  0x1BAA,  0x1BAB,
9351
37.8k
      0x1BF2,  0x1BF3,  0x2D7F,  0xA806,  0xA82C,  0xA8C4,  0xA953,  0xA9C0,
9352
37.8k
      0xAAF6,  0xABED,  0x10A3F, 0x11046, 0x1107F, 0x110B9, 0x11133, 0x11134,
9353
37.8k
      0x111C0, 0x11235, 0x112EA, 0x1134D, 0x11442, 0x114C2, 0x115BF, 0x1163F,
9354
37.8k
      0x116B6, 0x1172B, 0x11839, 0x1193D, 0x1193E, 0x119E0, 0x11A34, 0x11A47,
9355
37.8k
      0x11A99, 0x11C3F, 0x11D44, 0x11D45, 0x11D97};
9356
37.8k
  constexpr static uint32_t R[] = {
9357
37.8k
      0x622, 0x623, 0x624, 0x625, 0x627, 0x629, 0x62f, 0x630, 0x631,
9358
37.8k
      0x632, 0x648, 0x671, 0x672, 0x673, 0x675, 0x676, 0x677, 0x688,
9359
37.8k
      0x689, 0x68a, 0x68b, 0x68c, 0x68d, 0x68e, 0x68f, 0x690, 0x691,
9360
37.8k
      0x692, 0x693, 0x694, 0x695, 0x696, 0x697, 0x698, 0x699, 0x6c0,
9361
37.8k
      0x6c3, 0x6c4, 0x6c5, 0x6c6, 0x6c7, 0x6c8, 0x6c9, 0x6ca, 0x6cb,
9362
37.8k
      0x6cd, 0x6cf, 0x6d2, 0x6d3, 0x6d5, 0x6ee, 0x6ef, 0x710, 0x715,
9363
37.8k
      0x716, 0x717, 0x718, 0x719, 0x71e, 0x728, 0x72a, 0x72c, 0x72f,
9364
37.8k
      0x74d, 0x759, 0x75a, 0x75b, 0x854, 0x8aa, 0x8ab, 0x8ac};
9365
37.8k
  constexpr static uint32_t L[] = {0xa872};
9366
37.8k
  constexpr static uint32_t D[] = {
9367
37.8k
      0x620,  0x626,  0x628,  0x62a,  0x62b,  0x62c,  0x62d,  0x62e,  0x633,
9368
37.8k
      0x634,  0x635,  0x636,  0x637,  0x638,  0x639,  0x63a,  0x63b,  0x63c,
9369
37.8k
      0x63d,  0x63e,  0x63f,  0x641,  0x642,  0x643,  0x644,  0x645,  0x646,
9370
37.8k
      0x647,  0x649,  0x64a,  0x66e,  0x66f,  0x678,  0x679,  0x67a,  0x67b,
9371
37.8k
      0x67c,  0x67d,  0x67e,  0x67f,  0x680,  0x681,  0x682,  0x683,  0x684,
9372
37.8k
      0x685,  0x686,  0x687,  0x69a,  0x69b,  0x69c,  0x69d,  0x69e,  0x69f,
9373
37.8k
      0x6a0,  0x6a1,  0x6a2,  0x6a3,  0x6a4,  0x6a5,  0x6a6,  0x6a7,  0x6a8,
9374
37.8k
      0x6a9,  0x6aa,  0x6ab,  0x6ac,  0x6ad,  0x6ae,  0x6af,  0x6b0,  0x6b1,
9375
37.8k
      0x6b2,  0x6b3,  0x6b4,  0x6b5,  0x6b6,  0x6b7,  0x6b8,  0x6b9,  0x6ba,
9376
37.8k
      0x6bb,  0x6bc,  0x6bd,  0x6be,  0x6bf,  0x6c1,  0x6c2,  0x6cc,  0x6ce,
9377
37.8k
      0x6d0,  0x6d1,  0x6fa,  0x6fb,  0x6fc,  0x6ff,  0x712,  0x713,  0x714,
9378
37.8k
      0x71a,  0x71b,  0x71c,  0x71d,  0x71f,  0x720,  0x721,  0x722,  0x723,
9379
37.8k
      0x724,  0x725,  0x726,  0x727,  0x729,  0x72b,  0x72d,  0x72e,  0x74e,
9380
37.8k
      0x74f,  0x750,  0x751,  0x752,  0x753,  0x754,  0x755,  0x756,  0x757,
9381
37.8k
      0x758,  0x75c,  0x75d,  0x75e,  0x75f,  0x760,  0x761,  0x762,  0x763,
9382
37.8k
      0x764,  0x765,  0x766,  0x850,  0x851,  0x852,  0x853,  0x855,  0x8a0,
9383
37.8k
      0x8a2,  0x8a3,  0x8a4,  0x8a5,  0x8a6,  0x8a7,  0x8a8,  0x8a9,  0x1807,
9384
37.8k
      0x1820, 0x1821, 0x1822, 0x1823, 0x1824, 0x1825, 0x1826, 0x1827, 0x1828,
9385
37.8k
      0x1829, 0x182a, 0x182b, 0x182c, 0x182d, 0x182e, 0x182f, 0x1830, 0x1831,
9386
37.8k
      0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837, 0x1838, 0x1839, 0x183a,
9387
37.8k
      0x183b, 0x183c, 0x183d, 0x183e, 0x183f, 0x1840, 0x1841, 0x1842, 0x1843,
9388
37.8k
      0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x184a, 0x184b, 0x184c,
9389
37.8k
      0x184d, 0x184e, 0x184f, 0x1850, 0x1851, 0x1852, 0x1853, 0x1854, 0x1855,
9390
37.8k
      0x1856, 0x1857, 0x1858, 0x1859, 0x185a, 0x185b, 0x185c, 0x185d, 0x185e,
9391
37.8k
      0x185f, 0x1860, 0x1861, 0x1862, 0x1863, 0x1864, 0x1865, 0x1866, 0x1867,
9392
37.8k
      0x1868, 0x1869, 0x186a, 0x186b, 0x186c, 0x186d, 0x186e, 0x186f, 0x1870,
9393
37.8k
      0x1871, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, 0x1877, 0x1887, 0x1888,
9394
37.8k
      0x1889, 0x188a, 0x188b, 0x188c, 0x188d, 0x188e, 0x188f, 0x1890, 0x1891,
9395
37.8k
      0x1892, 0x1893, 0x1894, 0x1895, 0x1896, 0x1897, 0x1898, 0x1899, 0x189a,
9396
37.8k
      0x189b, 0x189c, 0x189d, 0x189e, 0x189f, 0x18a0, 0x18a1, 0x18a2, 0x18a3,
9397
37.8k
      0x18a4, 0x18a5, 0x18a6, 0x18a7, 0x18a8, 0x18aa, 0xa840, 0xa841, 0xa842,
9398
37.8k
      0xa843, 0xa844, 0xa845, 0xa846, 0xa847, 0xa848, 0xa849, 0xa84a, 0xa84b,
9399
37.8k
      0xa84c, 0xa84d, 0xa84e, 0xa84f, 0xa850, 0xa851, 0xa852, 0xa853, 0xa854,
9400
37.8k
      0xa855, 0xa856, 0xa857, 0xa858, 0xa859, 0xa85a, 0xa85b, 0xa85c, 0xa85d,
9401
37.8k
      0xa85e, 0xa85f, 0xa860, 0xa861, 0xa862, 0xa863, 0xa864, 0xa865, 0xa866,
9402
37.8k
      0xa867, 0xa868, 0xa869, 0xa86a, 0xa86b, 0xa86c, 0xa86d, 0xa86e, 0xa86f,
9403
37.8k
      0xa870, 0xa871};
9404
9405
390k
  for (size_t i = 0; i < label.size(); i++) {
9406
354k
    uint32_t c = label[i];
9407
354k
    if (c == 0x200c) {
9408
1.36k
      if (i > 0) {
9409
1.36k
        if (std::binary_search(std::begin(virama), std::end(virama),
9410
1.36k
                               label[i - 1])) {
9411
102
          return true;
9412
102
        }
9413
1.36k
      }
9414
1.26k
      if ((i == 0) || (i + 1 >= label.size())) {
9415
150
        return false;
9416
150
      }
9417
      // we go backward looking for L or D
9418
2.18k
      auto is_l_or_d = [](uint32_t code) {
9419
2.18k
        return std::binary_search(std::begin(L), std::end(L), code) ||
9420
2.12k
               std::binary_search(std::begin(D), std::end(D), code);
9421
2.18k
      };
9422
2.48k
      auto is_r_or_d = [](uint32_t code) {
9423
2.48k
        return std::binary_search(std::begin(R), std::end(R), code) ||
9424
2.20k
               std::binary_search(std::begin(D), std::end(D), code);
9425
2.48k
      };
9426
1.11k
      std::u32string_view before = label.substr(0, i);
9427
1.11k
      std::u32string_view after = label.substr(i + 1);
9428
1.11k
      return (std::find_if(before.begin(), before.end(), is_l_or_d) !=
9429
1.11k
              before.end()) &&
9430
946
             (std::find_if(after.begin(), after.end(), is_r_or_d) !=
9431
946
              after.end());
9432
353k
    } else if (c == 0x200d) {
9433
460
      if (i > 0) {
9434
446
        if (std::binary_search(std::begin(virama), std::end(virama),
9435
446
                               label[i - 1])) {
9436
322
          return true;
9437
322
        }
9438
446
      }
9439
138
      return false;
9440
460
    }
9441
354k
  }
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
36.0k
  size_t last_non_nsm_char = find_last_not_of_nsm(label);
9474
36.0k
  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
36.0k
  if (is_rtl_label(label)) {
9482
    // The first character must be a character with Bidi property L, R,
9483
    // or AL. If it has the R or AL property, it is an RTL label; if it
9484
    // has the L property, it is an LTR label.
9485
9486
2.80k
    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.34k
      for (size_t i = 0; i < last_non_nsm_char; i++) {
9492
2.83k
        const direction d = find_direction(label[i]);
9493
2.83k
        if (!(d == direction::L || d == direction::EN || d == direction::ES ||
9494
1.41k
              d == direction::CS || d == direction::ET || d == direction::ON ||
9495
814
              d == direction::BN || d == direction::NSM)) {
9496
114
          return false;
9497
114
        }
9498
9499
2.72k
        if ((i == last_non_nsm_char) &&
9500
0
            !(d == direction::L || d == direction::EN)) {
9501
0
          return false;
9502
0
        }
9503
2.72k
      }
9504
9505
514
      return true;
9506
9507
2.18k
    } else {
9508
      // Eval as RTL
9509
9510
2.18k
      bool has_an = false;
9511
2.18k
      bool has_en = false;
9512
9.18k
      for (size_t i = 0; i <= last_non_nsm_char; i++) {
9513
7.31k
        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
7.31k
        if ((d == direction::EN && ((has_en = true) && has_an)) ||
9519
7.30k
            (d == direction::AN && ((has_an = true) && has_en))) {
9520
16
          return false;
9521
16
        }
9522
        // NOLINTEND(bugprone-assignment-in-if-condition)
9523
9524
7.29k
        if (!(d == direction::R || d == direction::AL || d == direction::AN ||
9525
3.35k
              d == direction::EN || d == direction::ES || d == direction::CS ||
9526
2.17k
              d == direction::ET || d == direction::ON || d == direction::BN ||
9527
1.24k
              d == direction::NSM)) {
9528
230
          return false;
9529
230
        }
9530
9531
7.06k
        if (i == last_non_nsm_char &&
9532
1.93k
            !(d == direction::R || d == direction::AL || d == direction::AN ||
9533
296
              d == direction::EN)) {
9534
56
          return false;
9535
56
        }
9536
7.06k
      }
9537
9538
1.87k
      return true;
9539
2.18k
    }
9540
2.80k
  }
9541
9542
33.2k
  return true;
9543
36.0k
}
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
40.7k
bool constexpr is_ascii(std::u32string_view view) {
9561
67.7k
  for (uint32_t c : view) {
9562
67.7k
    if (c >= 0x80) {
9563
38.7k
      return false;
9564
38.7k
    }
9565
67.7k
  }
9566
2.04k
  return true;
9567
40.7k
}
9568
9569
17.1k
bool constexpr is_ascii(std::string_view view) {
9570
144k
  for (uint8_t c : view) {
9571
144k
    if (c >= 0x80) {
9572
10.4k
      return false;
9573
10.4k
    }
9574
144k
  }
9575
6.76k
  return true;
9576
17.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.76k
static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9603
6.76k
  static const std::string error = "";
9604
  // copy and map
9605
  // we could be more efficient by avoiding the copy when unnecessary.
9606
6.76k
  std::string mapped_string = std::string(ut8_string);
9607
6.76k
  ascii_map(mapped_string.data(), mapped_string.size());
9608
6.76k
  std::string out;
9609
6.76k
  size_t label_start = 0;
9610
9611
21.6k
  while (label_start != mapped_string.size()) {
9612
15.7k
    size_t loc_dot = mapped_string.find('.', label_start);
9613
15.7k
    bool is_last_label = (loc_dot == std::string_view::npos);
9614
15.7k
    size_t label_size = is_last_label ? mapped_string.size() - label_start
9615
15.7k
                                      : loc_dot - label_start;
9616
15.7k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9617
15.7k
    std::string_view label_view(mapped_string.data() + label_start, label_size);
9618
15.7k
    label_start += label_size_with_dot;
9619
15.7k
    if (label_size == 0) {
9620
      // empty label? Nothing to do.
9621
10.3k
    } else if (label_view.starts_with("xn--")) {
9622
      // The xn-- part is the expensive game.
9623
3.22k
      out.append(label_view);
9624
3.22k
      std::string_view puny_segment_ascii(
9625
3.22k
          out.data() + out.size() - label_view.size() + 4,
9626
3.22k
          label_view.size() - 4);
9627
3.22k
      std::u32string tmp_buffer;
9628
3.22k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9629
3.22k
      if (!is_ok) {
9630
266
        return error;
9631
266
      }
9632
      // If the input is just ASCII, it should not have been encoded
9633
      // as punycode.
9634
      // https://github.com/whatwg/url/issues/760
9635
2.96k
      if (is_ascii(tmp_buffer)) {
9636
160
        return error;
9637
160
      }
9638
2.80k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9639
2.80k
      if (tmp_buffer != post_map) {
9640
388
        return error;
9641
388
      }
9642
2.41k
      std::u32string pre_normal = post_map;
9643
2.41k
      normalize(post_map);
9644
2.41k
      if (post_map != pre_normal) {
9645
36
        return error;
9646
36
      }
9647
2.37k
      if (post_map.empty()) {
9648
0
        return error;
9649
0
      }
9650
2.37k
      if (!is_label_valid(post_map)) {
9651
38
        return error;
9652
38
      }
9653
7.11k
    } else {
9654
7.11k
      out.append(label_view);
9655
7.11k
    }
9656
14.8k
    if (!is_last_label) {
9657
9.34k
      out.push_back('.');
9658
9.34k
    }
9659
14.8k
  }
9660
5.87k
  return out;
9661
6.76k
}
9662
9663
// We return "" on error.
9664
17.1k
std::string to_ascii(std::string_view ut8_string) {
9665
17.1k
  if (is_ascii(ut8_string)) {
9666
6.76k
    return from_ascii_to_ascii(ut8_string);
9667
6.76k
  }
9668
10.4k
  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
10.4k
  size_t utf32_length =
9679
10.4k
      ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9680
10.4k
  std::u32string utf32(utf32_length, '\0');
9681
10.4k
  size_t actual_utf32_length = ada::idna::utf8_to_utf32(
9682
10.4k
      ut8_string.data(), ut8_string.size(), utf32.data());
9683
10.4k
#endif
9684
10.4k
  if (actual_utf32_length == 0) {
9685
2.24k
    return error;
9686
2.24k
  }
9687
  // mapping
9688
8.16k
  utf32 = ada::idna::map(utf32);
9689
8.16k
  normalize(utf32);
9690
8.16k
  std::string out;
9691
8.16k
  size_t label_start = 0;
9692
9693
45.6k
  while (label_start != utf32.size()) {
9694
39.2k
    size_t loc_dot = utf32.find('.', label_start);
9695
39.2k
    bool is_last_label = (loc_dot == std::string_view::npos);
9696
39.2k
    size_t label_size =
9697
39.2k
        is_last_label ? utf32.size() - label_start : loc_dot - label_start;
9698
39.2k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9699
39.2k
    std::u32string_view label_view(utf32.data() + label_start, label_size);
9700
39.2k
    label_start += label_size_with_dot;
9701
39.2k
    if (label_size == 0) {
9702
      // empty label? Nothing to do.
9703
37.9k
    } 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
45.5k
      for (char32_t c : label_view) {
9706
45.5k
        if (c >= 0x80) {
9707
18
          return error;
9708
18
        }
9709
45.4k
        out += (unsigned char)(c);
9710
45.4k
      }
9711
2.50k
      std::string_view puny_segment_ascii(
9712
2.50k
          out.data() + out.size() - label_view.size() + 4,
9713
2.50k
          label_view.size() - 4);
9714
2.50k
      std::u32string tmp_buffer;
9715
2.50k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9716
2.50k
      if (!is_ok) {
9717
114
        return error;
9718
114
      }
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.39k
      if (is_ascii(tmp_buffer)) {
9723
116
        return error;
9724
116
      }
9725
2.27k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9726
2.27k
      if (tmp_buffer != post_map) {
9727
260
        return error;
9728
260
      }
9729
2.01k
      std::u32string pre_normal = post_map;
9730
2.01k
      normalize(post_map);
9731
2.01k
      if (post_map != pre_normal) {
9732
68
        return error;
9733
68
      }
9734
1.95k
      if (post_map.empty()) {
9735
0
        return error;
9736
0
      }
9737
1.95k
      if (!is_label_valid(post_map)) {
9738
10
        return error;
9739
10
      }
9740
35.4k
    } else {
9741
      // The fast path here is an ascii label.
9742
35.4k
      if (is_ascii(label_view)) {
9743
        // no validation needed.
9744
16.8k
        for (char32_t c : label_view) {
9745
16.8k
          out += (unsigned char)(c);
9746
16.8k
        }
9747
33.6k
      } else {
9748
        // slow path.
9749
        // first check validity.
9750
33.6k
        if (!is_label_valid(label_view)) {
9751
1.15k
          return error;
9752
1.15k
        }
9753
        // It is valid! So now we must encode it as punycode...
9754
32.5k
        out.append("xn--");
9755
32.5k
        bool is_ok = ada::idna::utf32_to_punycode(label_view, out);
9756
32.5k
        if (!is_ok) {
9757
0
          return error;
9758
0
        }
9759
32.5k
      }
9760
35.4k
    }
9761
37.4k
    if (!is_last_label) {
9762
31.5k
      out.push_back('.');
9763
31.5k
    }
9764
37.4k
  }
9765
6.42k
  return out;
9766
8.16k
}
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_NEON
10448
#include <arm_neon.h>
10449
#elif ADA_SSE2
10450
#include <emmintrin.h>
10451
#elif ADA_LSX
10452
#include <lsxintrin.h>
10453
#elif ADA_RVV
10454
#include <riscv_vector.h>
10455
#endif
10456
10457
#include <ranges>
10458
10459
namespace ada::unicode {
10460
10461
203k
constexpr bool is_tabs_or_newline(char c) noexcept {
10462
203k
  return c == '\r' || c == '\n' || c == '\t';
10463
203k
}
10464
10465
112k
constexpr uint64_t broadcast(uint8_t v) noexcept {
10466
112k
  return 0x101010101010101ull * v;
10467
112k
}
10468
10469
37.6k
constexpr bool to_lower_ascii(char* input, size_t length) noexcept {
10470
37.6k
  uint64_t broadcast_80 = broadcast(0x80);
10471
37.6k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
10472
37.6k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
10473
37.6k
  uint64_t non_ascii = 0;
10474
37.6k
  size_t i = 0;
10475
10476
84.5k
  for (; i + 7 < length; i += 8) {
10477
46.9k
    uint64_t word{};
10478
46.9k
    memcpy(&word, input + i, sizeof(word));
10479
46.9k
    non_ascii |= (word & broadcast_80);
10480
46.9k
    word ^=
10481
46.9k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10482
46.9k
    memcpy(input + i, &word, sizeof(word));
10483
46.9k
  }
10484
37.6k
  if (i < length) {
10485
36.4k
    uint64_t word{};
10486
36.4k
    memcpy(&word, input + i, length - i);
10487
36.4k
    non_ascii |= (word & broadcast_80);
10488
36.4k
    word ^=
10489
36.4k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10490
36.4k
    memcpy(input + i, &word, length - i);
10491
36.4k
  }
10492
37.6k
  return non_ascii == 0;
10493
37.6k
}
10494
#if ADA_NEON
10495
ada_really_inline bool has_tabs_or_newline(
10496
    std::string_view user_input) noexcept {
10497
  // first check for short strings in which case we do it naively.
10498
  if (user_input.size() < 16) {  // slow path
10499
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10500
  }
10501
  // fast path for long strings (expected to be common)
10502
  size_t i = 0;
10503
  /**
10504
   * The fastest way to check for `\t` (==9), '\n'(== 10) and `\r` (==13) relies
10505
   * on table lookup instruction. We notice that these are all unique numbers
10506
   * between 0..15. Let's prepare a special register, where we put '\t' in the
10507
   * 9th position, '\n' - 10th and '\r' - 13th. Then we shuffle this register by
10508
   * input register. If the input had `\t` in position X then this shuffled
10509
   * register will also have '\t' in that position. Comparing input with this
10510
   * shuffled register will mark us all interesting characters in the input.
10511
   *
10512
   * credit for algorithmic idea: @aqrit, credit for description:
10513
   * @DenisYaroshevskiy
10514
   */
10515
  static uint8_t rnt_array[16] = {1, 0, 0,  0, 0, 0,  0, 0,
10516
                                  0, 9, 10, 0, 0, 13, 0, 0};
10517
  const uint8x16_t rnt = vld1q_u8(rnt_array);
10518
  // m['0xd', '0xa', '0x9']
10519
  uint8x16_t running{0};
10520
  for (; i + 15 < user_input.size(); i += 16) {
10521
    uint8x16_t word = vld1q_u8((const uint8_t*)user_input.data() + i);
10522
10523
    running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word));
10524
  }
10525
  if (i < user_input.size()) {
10526
    uint8x16_t word =
10527
        vld1q_u8((const uint8_t*)user_input.data() + user_input.length() - 16);
10528
    running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word));
10529
  }
10530
  return vmaxvq_u32(vreinterpretq_u32_u8(running)) != 0;
10531
}
10532
#elif ADA_SSE2
10533
ada_really_inline bool has_tabs_or_newline(
10534
69.8k
    std::string_view user_input) noexcept {
10535
  // first check for short strings in which case we do it naively.
10536
69.8k
  if (user_input.size() < 16) {  // slow path
10537
28.6k
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10538
28.6k
  }
10539
  // fast path for long strings (expected to be common)
10540
41.2k
  size_t i = 0;
10541
41.2k
  const __m128i mask1 = _mm_set1_epi8('\r');
10542
41.2k
  const __m128i mask2 = _mm_set1_epi8('\n');
10543
41.2k
  const __m128i mask3 = _mm_set1_epi8('\t');
10544
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10545
41.2k
  __m128i running{0};
10546
155k
  for (; i + 15 < user_input.size(); i += 16) {
10547
114k
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
10548
114k
    running = _mm_or_si128(
10549
114k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10550
114k
                                           _mm_cmpeq_epi8(word, mask2))),
10551
114k
        _mm_cmpeq_epi8(word, mask3));
10552
114k
  }
10553
41.2k
  if (i < user_input.size()) {
10554
38.3k
    __m128i word = _mm_loadu_si128(
10555
38.3k
        (const __m128i*)(user_input.data() + user_input.length() - 16));
10556
38.3k
    running = _mm_or_si128(
10557
38.3k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10558
38.3k
                                           _mm_cmpeq_epi8(word, mask2))),
10559
38.3k
        _mm_cmpeq_epi8(word, mask3));
10560
38.3k
  }
10561
41.2k
  return _mm_movemask_epi8(running) != 0;
10562
69.8k
}
10563
#elif ADA_LSX
10564
ada_really_inline bool has_tabs_or_newline(
10565
    std::string_view user_input) noexcept {
10566
  // first check for short strings in which case we do it naively.
10567
  if (user_input.size() < 16) {  // slow path
10568
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10569
  }
10570
  // fast path for long strings (expected to be common)
10571
  size_t i = 0;
10572
  const __m128i mask1 = __lsx_vrepli_b('\r');
10573
  const __m128i mask2 = __lsx_vrepli_b('\n');
10574
  const __m128i mask3 = __lsx_vrepli_b('\t');
10575
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10576
  __m128i running{0};
10577
  for (; i + 15 < user_input.size(); i += 16) {
10578
    __m128i word = __lsx_vld((const __m128i*)(user_input.data() + i), 0);
10579
    running = __lsx_vor_v(
10580
        __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1),
10581
                                         __lsx_vseq_b(word, mask2))),
10582
        __lsx_vseq_b(word, mask3));
10583
  }
10584
  if (i < user_input.size()) {
10585
    __m128i word = __lsx_vld(
10586
        (const __m128i*)(user_input.data() + user_input.length() - 16), 0);
10587
    running = __lsx_vor_v(
10588
        __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1),
10589
                                         __lsx_vseq_b(word, mask2))),
10590
        __lsx_vseq_b(word, mask3));
10591
  }
10592
  if (__lsx_bz_v(running)) return false;
10593
  return true;
10594
}
10595
#elif ADA_RVV
10596
ada_really_inline bool has_tabs_or_newline(
10597
    std::string_view user_input) noexcept {
10598
  uint8_t* src = (uint8_t*)user_input.data();
10599
  for (size_t vl, n = user_input.size(); n > 0; n -= vl, src += vl) {
10600
    vl = __riscv_vsetvl_e8m1(n);
10601
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
10602
    vbool8_t m1 = __riscv_vmseq(v, '\r', vl);
10603
    vbool8_t m2 = __riscv_vmseq(v, '\n', vl);
10604
    vbool8_t m3 = __riscv_vmseq(v, '\t', vl);
10605
    vbool8_t m = __riscv_vmor(__riscv_vmor(m1, m2, vl), m3, vl);
10606
    long idx = __riscv_vfirst(m, vl);
10607
    if (idx >= 0) return true;
10608
  }
10609
  return false;
10610
}
10611
#else
10612
ada_really_inline bool has_tabs_or_newline(
10613
    std::string_view user_input) noexcept {
10614
  auto has_zero_byte = [](uint64_t v) {
10615
    return ((v - 0x0101010101010101) & ~(v) & 0x8080808080808080);
10616
  };
10617
  size_t i = 0;
10618
  uint64_t mask1 = broadcast('\r');
10619
  uint64_t mask2 = broadcast('\n');
10620
  uint64_t mask3 = broadcast('\t');
10621
  uint64_t running{0};
10622
  for (; i + 7 < user_input.size(); i += 8) {
10623
    uint64_t word{};
10624
    memcpy(&word, user_input.data() + i, sizeof(word));
10625
    uint64_t xor1 = word ^ mask1;
10626
    uint64_t xor2 = word ^ mask2;
10627
    uint64_t xor3 = word ^ mask3;
10628
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
10629
  }
10630
  if (i < user_input.size()) {
10631
    uint64_t word{};
10632
    memcpy(&word, user_input.data() + i, user_input.size() - i);
10633
    uint64_t xor1 = word ^ mask1;
10634
    uint64_t xor2 = word ^ mask2;
10635
    uint64_t xor3 = word ^ mask3;
10636
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
10637
  }
10638
  return running;
10639
}
10640
#endif
10641
10642
// A forbidden host code point is U+0000 NULL, U+0009 TAB, U+000A LF, U+000D CR,
10643
// U+0020 SPACE, U+0023 (#), U+002F (/), U+003A (:), U+003C (<), U+003E (>),
10644
// U+003F (?), U+0040 (@), U+005B ([), U+005C (\), U+005D (]), U+005E (^), or
10645
// U+007C (|).
10646
constexpr static std::array<uint8_t, 256> is_forbidden_host_code_point_table =
10647
    []() consteval {
10648
      std::array<uint8_t, 256> result{};
10649
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10650
                        '>', '?', '@', '[', '\\', ']', '^', '|'}) {
10651
        result[c] = true;
10652
      }
10653
      return result;
10654
    }();
10655
10656
ada_really_inline constexpr bool is_forbidden_host_code_point(
10657
17.0k
    const char c) noexcept {
10658
17.0k
  return is_forbidden_host_code_point_table[uint8_t(c)];
10659
17.0k
}
10660
10661
constexpr static std::array<uint8_t, 256> is_forbidden_domain_code_point_table =
10662
    []() consteval {
10663
      std::array<uint8_t, 256> result{};
10664
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10665
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
10666
        result[c] = true;
10667
      }
10668
      for (uint8_t c = 0; c <= 32; c++) {
10669
        result[c] = true;
10670
      }
10671
      for (size_t c = 127; c < 255; c++) {
10672
        result[c] = true;
10673
      }
10674
      return result;
10675
    }();
10676
10677
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
10678
10679
ada_really_inline constexpr bool is_forbidden_domain_code_point(
10680
881k
    const char c) noexcept {
10681
881k
  return is_forbidden_domain_code_point_table[uint8_t(c)];
10682
881k
}
10683
10684
ada_really_inline constexpr bool contains_forbidden_domain_code_point(
10685
36.3k
    const char* input, size_t length) noexcept {
10686
36.3k
  size_t i = 0;
10687
36.3k
  uint8_t accumulator{};
10688
381k
  for (; i + 4 <= length; i += 4) {
10689
345k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10690
345k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 1])];
10691
345k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 2])];
10692
345k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 3])];
10693
345k
  }
10694
103k
  for (; i < length; i++) {
10695
67.0k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10696
67.0k
  }
10697
36.3k
  return accumulator;
10698
36.3k
}
10699
10700
constexpr static std::array<uint8_t, 256>
10701
    is_forbidden_domain_code_point_table_or_upper = []() consteval {
10702
      std::array<uint8_t, 256> result{};
10703
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10704
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
10705
        result[c] = 1;
10706
      }
10707
      for (uint8_t c = 'A'; c <= 'Z'; c++) {
10708
        result[c] = 2;
10709
      }
10710
      for (uint8_t c = 0; c <= 32; c++) {
10711
        result[c] = 1;
10712
      }
10713
      for (size_t c = 127; c < 255; c++) {
10714
        result[c] = 1;
10715
      }
10716
      return result;
10717
    }();
10718
10719
ada_really_inline constexpr uint8_t
10720
contains_forbidden_domain_code_point_or_upper(const char* input,
10721
24.1k
                                              size_t length) noexcept {
10722
24.1k
  size_t i = 0;
10723
24.1k
  uint8_t accumulator{};
10724
120k
  for (; i + 4 <= length; i += 4) {
10725
95.9k
    accumulator |=
10726
95.9k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10727
95.9k
    accumulator |=
10728
95.9k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 1])];
10729
95.9k
    accumulator |=
10730
95.9k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 2])];
10731
95.9k
    accumulator |=
10732
95.9k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 3])];
10733
95.9k
  }
10734
72.9k
  for (; i < length; i++) {
10735
48.8k
    accumulator |=
10736
48.8k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10737
48.8k
  }
10738
24.1k
  return accumulator;
10739
24.1k
}
10740
10741
// std::isalnum(c) || c == '+' || c == '-' || c == '.') is true for
10742
constexpr static std::array<bool, 256> is_alnum_plus_table = []() consteval {
10743
  std::array<bool, 256> result{};
10744
  for (size_t c = 0; c < 256; c++) {
10745
    result[c] = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
10746
                (c >= 'A' && c <= 'Z') || c == '+' || c == '-' || c == '.';
10747
  }
10748
  return result;
10749
}();
10750
10751
244k
ada_really_inline constexpr bool is_alnum_plus(const char c) noexcept {
10752
244k
  return is_alnum_plus_table[uint8_t(c)];
10753
  // A table is almost surely much faster than the
10754
  // following under most compilers: return
10755
  // return (std::isalnum(c) || c == '+' || c == '-' || c == '.');
10756
244k
}
10757
10758
31.2k
ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept {
10759
31.2k
  return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
10760
3.32k
         (c >= 'a' && c <= 'f');
10761
31.2k
}
10762
10763
36.5k
ada_really_inline constexpr bool is_ascii_digit(const char c) noexcept {
10764
  // An ASCII digit is a code point in the range U+0030 (0) to U+0039 (9),
10765
  // inclusive.
10766
36.5k
  return (c >= '0' && c <= '9');
10767
36.5k
}
10768
10769
0
ada_really_inline constexpr bool is_ascii(const char32_t c) noexcept {
10770
  // If code point is between U+0000 and U+007F inclusive, then return true.
10771
0
  return c <= 0x7F;
10772
0
}
10773
10774
91.0k
ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept {
10775
91.0k
  return (unsigned char)c <= ' ';
10776
91.0k
}
10777
10778
ada_really_inline constexpr bool is_ascii_tab_or_newline(
10779
3.80M
    const char c) noexcept {
10780
3.80M
  return c == '\t' || c == '\n' || c == '\r';
10781
3.80M
}
10782
10783
constexpr std::string_view table_is_double_dot_path_segment[] = {
10784
    "..", "%2e.", ".%2e", "%2e%2e"};
10785
10786
ada_really_inline constexpr bool is_double_dot_path_segment(
10787
122k
    std::string_view input) noexcept {
10788
  // This will catch most cases:
10789
  // The length must be 2,4 or 6.
10790
  // We divide by two and require
10791
  // that the result be between 1 and 3 inclusively.
10792
122k
  uint64_t half_length = uint64_t(input.size()) / 2;
10793
122k
  if (half_length - 1 > 2) {
10794
65.6k
    return false;
10795
65.6k
  }
10796
  // We have a string of length 2, 4 or 6.
10797
  // We now check the first character:
10798
57.2k
  if ((input[0] != '.') && (input[0] != '%')) {
10799
10.1k
    return false;
10800
10.1k
  }
10801
  // We are unlikely the get beyond this point.
10802
47.1k
  int hash_value = (input.size() + (unsigned)(input[0])) & 3;
10803
47.1k
  const std::string_view target = table_is_double_dot_path_segment[hash_value];
10804
47.1k
  if (target.size() != input.size()) {
10805
12.8k
    return false;
10806
12.8k
  }
10807
  // We almost never get here.
10808
  // Optimizing the rest is relatively unimportant.
10809
34.3k
  auto prefix_equal_unsafe = [](std::string_view a, std::string_view b) {
10810
34.3k
    uint16_t A, B;
10811
34.3k
    memcpy(&A, a.data(), sizeof(A));
10812
34.3k
    memcpy(&B, b.data(), sizeof(B));
10813
34.3k
    return A == B;
10814
34.3k
  };
10815
34.3k
  if (!prefix_equal_unsafe(input, target)) {
10816
2.43k
    return false;
10817
2.43k
  }
10818
39.4k
  for (size_t i = 2; i < input.size(); i++) {
10819
11.9k
    char c = input[i];
10820
11.9k
    if ((uint8_t((c | 0x20) - 0x61) <= 25 ? (c | 0x20) : c) != target[i]) {
10821
4.39k
      return false;
10822
4.39k
    }
10823
11.9k
  }
10824
27.5k
  return true;
10825
  // The above code might be a bit better than the code below. Compilers
10826
  // are not stupid and may use the fact that these strings have length 2,4 and
10827
  // 6 and other tricks.
10828
  // return input == ".." ||
10829
  //  input == ".%2e" || input == ".%2E" ||
10830
  //  input == "%2e." || input == "%2E." ||
10831
  //  input == "%2e%2e" || input == "%2E%2E" || input == "%2E%2e" || input ==
10832
  //  "%2e%2E";
10833
31.9k
}
10834
10835
ada_really_inline constexpr bool is_single_dot_path_segment(
10836
190k
    std::string_view input) noexcept {
10837
190k
  return input == "." || input == "%2e" || input == "%2E";
10838
190k
}
10839
10840
28.0k
ada_really_inline constexpr bool is_lowercase_hex(const char c) noexcept {
10841
28.0k
  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
10842
28.0k
}
10843
10844
constexpr static char hex_to_binary_table[] = {
10845
    0,  1,  2,  3,  4, 5, 6, 7, 8, 9, 0, 0,  0,  0,  0,  0,  0, 10, 11,
10846
    12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0,  0,
10847
    0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
10848
28.7k
unsigned constexpr convert_hex_to_binary(const char c) noexcept {
10849
28.7k
  return hex_to_binary_table[c - '0'];
10850
28.7k
}
10851
10852
1.19k
std::string percent_decode(const std::string_view input, size_t first_percent) {
10853
  // next line is for safety only, we expect users to avoid calling
10854
  // percent_decode when first_percent is outside the range.
10855
1.19k
  if (first_percent == std::string_view::npos) {
10856
0
    return std::string(input);
10857
0
  }
10858
1.19k
  std::string dest;
10859
1.19k
  dest.reserve(input.length());
10860
1.19k
  dest.append(input.substr(0, first_percent));
10861
1.19k
  const char* pointer = input.data() + first_percent;
10862
1.19k
  const char* end = input.data() + input.size();
10863
  // Optimization opportunity: if the following code gets
10864
  // called often, it can be optimized quite a bit.
10865
26.9k
  while (pointer < end) {
10866
25.7k
    const char ch = pointer[0];
10867
25.7k
    size_t remaining = end - pointer - 1;
10868
25.7k
    if (ch != '%' || remaining < 2 ||
10869
14.3k
        (  // ch == '%' && // It is unnecessary to check that ch == '%'.
10870
14.3k
            (!is_ascii_hex_digit(pointer[1]) ||
10871
13.8k
             !is_ascii_hex_digit(pointer[2])))) {
10872
12.3k
      dest += ch;
10873
12.3k
      pointer++;
10874
13.3k
    } else {
10875
13.3k
      unsigned a = convert_hex_to_binary(pointer[1]);
10876
13.3k
      unsigned b = convert_hex_to_binary(pointer[2]);
10877
13.3k
      char c = static_cast<char>(a * 16 + b);
10878
13.3k
      dest += c;
10879
13.3k
      pointer += 3;
10880
13.3k
    }
10881
25.7k
  }
10882
1.19k
  return dest;
10883
1.19k
}
10884
10885
std::string percent_encode(const std::string_view input,
10886
55.7k
                           const uint8_t character_set[]) {
10887
379k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10888
379k
    return character_sets::bit_at(character_set, c);
10889
379k
  });
10890
  // Optimization: Don't iterate if percent encode is not required
10891
55.7k
  if (pointer == input.end()) {
10892
23.7k
    return std::string(input);
10893
23.7k
  }
10894
10895
32.0k
  std::string result;
10896
32.0k
  result.reserve(input.length());  // in the worst case, percent encoding might
10897
                                   // produce 3 characters.
10898
32.0k
  result.append(input.substr(0, std::distance(input.begin(), pointer)));
10899
10900
1.04M
  for (; pointer != input.end(); pointer++) {
10901
1.01M
    if (character_sets::bit_at(character_set, *pointer)) {
10902
789k
      result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10903
789k
    } else {
10904
221k
      result += *pointer;
10905
221k
    }
10906
1.01M
  }
10907
10908
32.0k
  return result;
10909
55.7k
}
10910
10911
template <bool append>
10912
bool percent_encode(const std::string_view input, const uint8_t character_set[],
10913
94.0k
                    std::string& out) {
10914
94.0k
  ada_log("percent_encode ", input, " to output string while ",
10915
94.0k
          append ? "appending" : "overwriting");
10916
374k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10917
374k
    return character_sets::bit_at(character_set, c);
10918
374k
  });
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
10916
145k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10917
145k
    return character_sets::bit_at(character_set, c);
10918
145k
  });
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
10916
229k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10917
229k
    return character_sets::bit_at(character_set, c);
10918
229k
  });
10919
94.0k
  ada_log("percent_encode done checking, moved to ",
10920
94.0k
          std::distance(input.begin(), pointer));
10921
10922
  // Optimization: Don't iterate if percent encode is not required
10923
94.0k
  if (pointer == input.end()) {
10924
49.9k
    ada_log("percent_encode encoding not needed.");
10925
49.9k
    return false;
10926
49.9k
  }
10927
44.1k
  if constexpr (!append) {
10928
33.5k
    out.clear();
10929
33.5k
  }
10930
44.1k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10931
44.1k
          " bytes");
10932
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10933
44.1k
  out.append(input.data(), std::distance(input.begin(), pointer));
10934
44.1k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10935
44.1k
          " bytes");
10936
1.00M
  for (; pointer != input.end(); pointer++) {
10937
956k
    if (character_sets::bit_at(character_set, *pointer)) {
10938
768k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10939
768k
    } else {
10940
188k
      out += *pointer;
10941
188k
    }
10942
956k
  }
10943
44.1k
  return true;
10944
94.0k
}
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
10913
75.5k
                    std::string& out) {
10914
75.5k
  ada_log("percent_encode ", input, " to output string while ",
10915
75.5k
          append ? "appending" : "overwriting");
10916
75.5k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10917
75.5k
    return character_sets::bit_at(character_set, c);
10918
75.5k
  });
10919
75.5k
  ada_log("percent_encode done checking, moved to ",
10920
75.5k
          std::distance(input.begin(), pointer));
10921
10922
  // Optimization: Don't iterate if percent encode is not required
10923
75.5k
  if (pointer == input.end()) {
10924
42.0k
    ada_log("percent_encode encoding not needed.");
10925
42.0k
    return false;
10926
42.0k
  }
10927
33.5k
  if constexpr (!append) {
10928
33.5k
    out.clear();
10929
33.5k
  }
10930
33.5k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10931
33.5k
          " bytes");
10932
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10933
33.5k
  out.append(input.data(), std::distance(input.begin(), pointer));
10934
33.5k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10935
33.5k
          " bytes");
10936
597k
  for (; pointer != input.end(); pointer++) {
10937
563k
    if (character_sets::bit_at(character_set, *pointer)) {
10938
473k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10939
473k
    } else {
10940
90.6k
      out += *pointer;
10941
90.6k
    }
10942
563k
  }
10943
33.5k
  return true;
10944
75.5k
}
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
10913
18.4k
                    std::string& out) {
10914
18.4k
  ada_log("percent_encode ", input, " to output string while ",
10915
18.4k
          append ? "appending" : "overwriting");
10916
18.4k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10917
18.4k
    return character_sets::bit_at(character_set, c);
10918
18.4k
  });
10919
18.4k
  ada_log("percent_encode done checking, moved to ",
10920
18.4k
          std::distance(input.begin(), pointer));
10921
10922
  // Optimization: Don't iterate if percent encode is not required
10923
18.4k
  if (pointer == input.end()) {
10924
7.90k
    ada_log("percent_encode encoding not needed.");
10925
7.90k
    return false;
10926
7.90k
  }
10927
  if constexpr (!append) {
10928
    out.clear();
10929
  }
10930
10.5k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10931
10.5k
          " bytes");
10932
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10933
10.5k
  out.append(input.data(), std::distance(input.begin(), pointer));
10934
10.5k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10935
10.5k
          " bytes");
10936
403k
  for (; pointer != input.end(); pointer++) {
10937
393k
    if (character_sets::bit_at(character_set, *pointer)) {
10938
295k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10939
295k
    } else {
10940
98.0k
      out += *pointer;
10941
98.0k
    }
10942
393k
  }
10943
10.5k
  return true;
10944
18.4k
}
10945
10946
bool to_ascii(std::optional<std::string>& out, const std::string_view plain,
10947
17.1k
              size_t first_percent) {
10948
17.1k
  std::string percent_decoded_buffer;
10949
17.1k
  std::string_view input = plain;
10950
17.1k
  if (first_percent != std::string_view::npos) {
10951
1.19k
    percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
10952
1.19k
    input = percent_decoded_buffer;
10953
1.19k
  }
10954
  // input is a non-empty UTF-8 string, must be percent decoded
10955
17.1k
  std::string idna_ascii = ada::idna::to_ascii(input);
10956
17.1k
  if (idna_ascii.empty() || contains_forbidden_domain_code_point(
10957
12.1k
                                idna_ascii.data(), idna_ascii.size())) {
10958
8.94k
    return false;
10959
8.94k
  }
10960
8.22k
  out = std::move(idna_ascii);
10961
8.22k
  return true;
10962
17.1k
}
10963
10964
std::string percent_encode(const std::string_view input,
10965
14.4k
                           const uint8_t character_set[], size_t index) {
10966
14.4k
  std::string out;
10967
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10968
14.4k
  out.append(input.data(), index);
10969
14.4k
  auto pointer = input.begin() + index;
10970
484k
  for (; pointer != input.end(); pointer++) {
10971
470k
    if (character_sets::bit_at(character_set, *pointer)) {
10972
358k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10973
358k
    } else {
10974
111k
      out += *pointer;
10975
111k
    }
10976
470k
  }
10977
14.4k
  return out;
10978
14.4k
}
10979
10980
}  // namespace ada::unicode
10981
/* end file src/unicode.cpp */
10982
/* begin file src/serializers.cpp */
10983
#include <array>
10984
#include <charconv>
10985
#include <string>
10986
10987
namespace ada::serializers {
10988
10989
void find_longest_sequence_of_ipv6_pieces(
10990
    const std::array<uint16_t, 8>& address, size_t& compress,
10991
232
    size_t& compress_length) noexcept {
10992
776
  for (size_t i = 0; i < 8; i++) {
10993
634
    if (address[i] == 0) {
10994
302
      size_t next = i + 1;
10995
1.42k
      while (next != 8 && address[next] == 0) ++next;
10996
302
      const size_t count = next - i;
10997
302
      if (compress_length < count) {
10998
228
        compress_length = count;
10999
228
        compress = i;
11000
228
        if (next == 8) break;
11001
138
        i = next;
11002
138
      }
11003
302
    }
11004
634
  }
11005
232
}
11006
11007
232
std::string ipv6(const std::array<uint16_t, 8>& address) noexcept {
11008
232
  size_t compress_length = 0;  // The length of a long sequence of zeros.
11009
232
  size_t compress = 0;         // The start of a long sequence of zeros.
11010
232
  find_longest_sequence_of_ipv6_pieces(address, compress, compress_length);
11011
11012
232
  if (compress_length <= 1) {
11013
    // Optimization opportunity: Find a faster way then snprintf for imploding
11014
    // and return here.
11015
26
    compress = compress_length = 8;
11016
26
  }
11017
11018
232
  std::string output(4 * 8 + 7 + 2, '\0');
11019
232
  size_t piece_index = 0;
11020
232
  char* point = output.data();
11021
232
  char* point_end = output.data() + output.size();
11022
232
  *point++ = '[';
11023
660
  while (true) {
11024
660
    if (piece_index == compress) {
11025
206
      *point++ = ':';
11026
      // If we skip a value initially, we need to write '::', otherwise
11027
      // a single ':' will do since it follows a previous ':'.
11028
206
      if (piece_index == 0) {
11029
140
        *point++ = ':';
11030
140
      }
11031
206
      piece_index += compress_length;
11032
206
      if (piece_index == 8) {
11033
90
        break;
11034
90
      }
11035
206
    }
11036
570
    point = std::to_chars(point, point_end, address[piece_index], 16).ptr;
11037
570
    piece_index++;
11038
570
    if (piece_index == 8) {
11039
142
      break;
11040
142
    }
11041
428
    *point++ = ':';
11042
428
  }
11043
232
  *point++ = ']';
11044
232
  output.resize(point - output.data());
11045
232
  return output;
11046
232
}
11047
11048
3.03k
std::string ipv4(const uint64_t address) noexcept {
11049
3.03k
  std::string output(15, '\0');
11050
3.03k
  char* point = output.data();
11051
3.03k
  char* point_end = output.data() + output.size();
11052
3.03k
  point = std::to_chars(point, point_end, uint8_t(address >> 24)).ptr;
11053
12.1k
  for (int i = 2; i >= 0; i--) {
11054
9.09k
    *point++ = '.';
11055
9.09k
    point = std::to_chars(point, point_end, uint8_t(address >> (i * 8))).ptr;
11056
9.09k
  }
11057
3.03k
  output.resize(point - output.data());
11058
3.03k
  return output;
11059
3.03k
}
11060
11061
}  // namespace ada::serializers
11062
/* end file src/serializers.cpp */
11063
/* begin file src/implementation.cpp */
11064
11065
#include <string_view>
11066
11067
11068
namespace ada {
11069
11070
template <class result_type>
11071
ada_warn_unused tl::expected<result_type, errors> parse(
11072
42.9k
    std::string_view input, const result_type* base_url) {
11073
42.9k
  result_type u =
11074
42.9k
      ada::parser::parse_url_impl<result_type, true>(input, base_url);
11075
42.9k
  if (!u.is_valid) {
11076
12.1k
    return tl::unexpected(errors::type_error);
11077
12.1k
  }
11078
30.7k
  return u;
11079
42.9k
}
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
11072
21.4k
    std::string_view input, const result_type* base_url) {
11073
21.4k
  result_type u =
11074
21.4k
      ada::parser::parse_url_impl<result_type, true>(input, base_url);
11075
21.4k
  if (!u.is_valid) {
11076
6.02k
    return tl::unexpected(errors::type_error);
11077
6.02k
  }
11078
15.4k
  return u;
11079
21.4k
}
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
11072
21.4k
    std::string_view input, const result_type* base_url) {
11073
21.4k
  result_type u =
11074
21.4k
      ada::parser::parse_url_impl<result_type, true>(input, base_url);
11075
21.4k
  if (!u.is_valid) {
11076
6.16k
    return tl::unexpected(errors::type_error);
11077
6.16k
  }
11078
15.3k
  return u;
11079
21.4k
}
11080
11081
template ada::result<url> parse<url>(std::string_view input,
11082
                                     const url* base_url = nullptr);
11083
template ada::result<url_aggregator> parse<url_aggregator>(
11084
    std::string_view input, const url_aggregator* base_url = nullptr);
11085
11086
8.96k
std::string href_from_file(std::string_view input) {
11087
  // This is going to be much faster than constructing a URL.
11088
8.96k
  std::string tmp_buffer;
11089
8.96k
  std::string_view internal_input;
11090
8.96k
  if (unicode::has_tabs_or_newline(input)) {
11091
156
    tmp_buffer = input;
11092
156
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
11093
156
    internal_input = tmp_buffer;
11094
8.81k
  } else {
11095
8.81k
    internal_input = input;
11096
8.81k
  }
11097
8.96k
  std::string path;
11098
8.96k
  if (internal_input.empty()) {
11099
29
    path = "/";
11100
8.93k
  } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
11101
708
    helpers::parse_prepared_path(internal_input.substr(1),
11102
708
                                 ada::scheme::type::FILE, path);
11103
8.23k
  } else {
11104
8.23k
    helpers::parse_prepared_path(internal_input, ada::scheme::type::FILE, path);
11105
8.23k
  }
11106
8.96k
  return "file://" + path;
11107
8.96k
}
11108
11109
0
bool can_parse(std::string_view input, const std::string_view* base_input) {
11110
0
  ada::url_aggregator base_aggregator;
11111
0
  ada::url_aggregator* base_pointer = nullptr;
11112
11113
0
  if (base_input != nullptr) {
11114
0
    base_aggregator = ada::parser::parse_url_impl<ada::url_aggregator, false>(
11115
0
        *base_input, nullptr);
11116
0
    if (!base_aggregator.is_valid) {
11117
0
      return false;
11118
0
    }
11119
0
    base_pointer = &base_aggregator;
11120
0
  }
11121
11122
0
  ada::url_aggregator result =
11123
0
      ada::parser::parse_url_impl<ada::url_aggregator, false>(input,
11124
0
                                                              base_pointer);
11125
0
  return result.is_valid;
11126
0
}
11127
11128
0
ada_warn_unused std::string_view to_string(ada::encoding_type type) {
11129
0
  switch (type) {
11130
0
    case ada::encoding_type::UTF8:
11131
0
      return "UTF-8";
11132
0
    case ada::encoding_type::UTF_16LE:
11133
0
      return "UTF-16LE";
11134
0
    case ada::encoding_type::UTF_16BE:
11135
0
      return "UTF-16BE";
11136
0
    default:
11137
0
      unreachable();
11138
0
  }
11139
0
}
11140
11141
}  // namespace ada
11142
/* end file src/implementation.cpp */
11143
/* begin file src/helpers.cpp */
11144
#include <cstring>
11145
#include <sstream>
11146
11147
11148
namespace ada::helpers {
11149
11150
template <typename out_iter>
11151
97.7k
void encode_json(std::string_view view, out_iter out) {
11152
  // trivial implementation. could be faster.
11153
97.7k
  const char* hexvalues =
11154
97.7k
      "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
11155
8.02M
  for (uint8_t c : view) {
11156
8.02M
    if (c == '\\') {
11157
2.93k
      *out++ = '\\';
11158
2.93k
      *out++ = '\\';
11159
8.01M
    } else if (c == '"') {
11160
1.94k
      *out++ = '\\';
11161
1.94k
      *out++ = '"';
11162
8.01M
    } else if (c <= 0x1f) {
11163
0
      *out++ = '\\';
11164
0
      *out++ = 'u';
11165
0
      *out++ = '0';
11166
0
      *out++ = '0';
11167
0
      *out++ = hexvalues[2 * c];
11168
0
      *out++ = hexvalues[2 * c + 1];
11169
8.01M
    } else {
11170
8.01M
      *out++ = c;
11171
8.01M
    }
11172
8.02M
  }
11173
97.7k
}
11174
11175
0
ada_unused std::string get_state(ada::state s) {
11176
0
  switch (s) {
11177
0
    case ada::state::AUTHORITY:
11178
0
      return "Authority";
11179
0
    case ada::state::SCHEME_START:
11180
0
      return "Scheme Start";
11181
0
    case ada::state::SCHEME:
11182
0
      return "Scheme";
11183
0
    case ada::state::HOST:
11184
0
      return "Host";
11185
0
    case ada::state::NO_SCHEME:
11186
0
      return "No Scheme";
11187
0
    case ada::state::FRAGMENT:
11188
0
      return "Fragment";
11189
0
    case ada::state::RELATIVE_SCHEME:
11190
0
      return "Relative Scheme";
11191
0
    case ada::state::RELATIVE_SLASH:
11192
0
      return "Relative Slash";
11193
0
    case ada::state::FILE:
11194
0
      return "File";
11195
0
    case ada::state::FILE_HOST:
11196
0
      return "File Host";
11197
0
    case ada::state::FILE_SLASH:
11198
0
      return "File Slash";
11199
0
    case ada::state::PATH_OR_AUTHORITY:
11200
0
      return "Path or Authority";
11201
0
    case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES:
11202
0
      return "Special Authority Ignore Slashes";
11203
0
    case ada::state::SPECIAL_AUTHORITY_SLASHES:
11204
0
      return "Special Authority Slashes";
11205
0
    case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY:
11206
0
      return "Special Relative or Authority";
11207
0
    case ada::state::QUERY:
11208
0
      return "Query";
11209
0
    case ada::state::PATH:
11210
0
      return "Path";
11211
0
    case ada::state::PATH_START:
11212
0
      return "Path Start";
11213
0
    case ada::state::OPAQUE_PATH:
11214
0
      return "Opaque Path";
11215
0
    case ada::state::PORT:
11216
0
      return "Port";
11217
0
    default:
11218
0
      return "unknown state";
11219
0
  }
11220
0
}
11221
11222
ada_really_inline std::optional<std::string_view> prune_hash(
11223
42.9k
    std::string_view& input) noexcept {
11224
  // compiles down to 20--30 instructions including a class to memchr (C
11225
  // function). this function should be quite fast.
11226
42.9k
  size_t location_of_first = input.find('#');
11227
42.9k
  if (location_of_first == std::string_view::npos) {
11228
42.3k
    return std::nullopt;
11229
42.3k
  }
11230
618
  std::string_view hash = input;
11231
618
  hash.remove_prefix(location_of_first + 1);
11232
618
  input.remove_suffix(input.size() - location_of_first);
11233
618
  return hash;
11234
42.9k
}
11235
11236
ada_really_inline bool shorten_path(std::string& path,
11237
27.5k
                                    ada::scheme::type type) noexcept {
11238
  // Let path be url's path.
11239
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
11240
  // Windows drive letter, then return.
11241
27.5k
  if (type == ada::scheme::type::FILE &&
11242
21.1k
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11243
11.8k
    if (checkers::is_normalized_windows_drive_letter(
11244
11.8k
            helpers::substring(path, 1))) {
11245
3.51k
      return false;
11246
3.51k
    }
11247
11.8k
  }
11248
11249
  // Remove path's last item, if any.
11250
23.9k
  size_t last_delimiter = path.rfind('/');
11251
23.9k
  if (last_delimiter != std::string::npos) {
11252
15.0k
    path.erase(last_delimiter);
11253
15.0k
    return true;
11254
15.0k
  }
11255
11256
8.97k
  return false;
11257
23.9k
}
11258
11259
ada_really_inline bool shorten_path(std::string_view& path,
11260
0
                                    ada::scheme::type type) noexcept {
11261
  // Let path be url's path.
11262
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
11263
  // Windows drive letter, then return.
11264
0
  if (type == ada::scheme::type::FILE &&
11265
0
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11266
0
    if (checkers::is_normalized_windows_drive_letter(
11267
0
            helpers::substring(path, 1))) {
11268
0
      return false;
11269
0
    }
11270
0
  }
11271
11272
  // Remove path's last item, if any.
11273
0
  if (!path.empty()) {
11274
0
    size_t slash_loc = path.rfind('/');
11275
0
    if (slash_loc != std::string_view::npos) {
11276
0
      path.remove_suffix(path.size() - slash_loc);
11277
0
      return true;
11278
0
    }
11279
0
  }
11280
11281
0
  return false;
11282
0
}
11283
11284
ada_really_inline void remove_ascii_tab_or_newline(
11285
112k
    std::string& input) noexcept {
11286
  // if this ever becomes a performance issue, we could use an approach similar
11287
  // to has_tabs_or_newline
11288
112k
  std::erase_if(input, ada::unicode::is_ascii_tab_or_newline);
11289
112k
}
11290
11291
ada_really_inline constexpr std::string_view substring(std::string_view input,
11292
27.2k
                                                       size_t pos) noexcept {
11293
27.2k
  ADA_ASSERT_TRUE(pos <= input.size());
11294
  // The following is safer but unneeded if we have the above line:
11295
  // return pos > input.size() ? std::string_view() : input.substr(pos);
11296
27.2k
  return input.substr(pos);
11297
27.2k
}
11298
11299
0
ada_really_inline void resize(std::string_view& input, size_t pos) noexcept {
11300
0
  ADA_ASSERT_TRUE(pos <= input.size());
11301
0
  input.remove_suffix(input.size() - pos);
11302
0
}
11303
11304
// computes the number of trailing zeroes
11305
// this is a private inline function only defined in this source file.
11306
12.9k
ada_really_inline int trailing_zeroes(uint32_t input_num) noexcept {
11307
#ifdef ADA_REGULAR_VISUAL_STUDIO
11308
  unsigned long ret;
11309
  // Search the mask data from least significant bit (LSB)
11310
  // to the most significant bit (MSB) for a set bit (1).
11311
  _BitScanForward(&ret, input_num);
11312
  return (int)ret;
11313
#else   // ADA_REGULAR_VISUAL_STUDIO
11314
12.9k
  return __builtin_ctzl(input_num);
11315
12.9k
#endif  // ADA_REGULAR_VISUAL_STUDIO
11316
12.9k
}
11317
11318
// starting at index location, this finds the next location of a character
11319
// :, /, \\, ? or [. If none is found, view.size() is returned.
11320
// For use within get_host_delimiter_location.
11321
#if ADA_NEON
11322
// The ada_make_uint8x16_t macro is necessary because Visual Studio does not
11323
// support direct initialization of uint8x16_t. See
11324
// https://developercommunity.visualstudio.com/t/error-C2078:-too-many-initializers-whe/402911?q=backend+neon
11325
#ifndef ada_make_uint8x16_t
11326
#define ada_make_uint8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
11327
                            x13, x14, x15, x16)                                \
11328
  ([=]() {                                                                     \
11329
    static uint8_t array[16] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8,          \
11330
                                x9, x10, x11, x12, x13, x14, x15, x16};        \
11331
    return vld1q_u8(array);                                                    \
11332
  }())
11333
#endif
11334
11335
ada_really_inline size_t find_next_host_delimiter_special(
11336
    std::string_view view, size_t location) noexcept {
11337
  // first check for short strings in which case we do it naively.
11338
  if (view.size() - location < 16) {  // slow path
11339
    for (size_t i = location; i < view.size(); i++) {
11340
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11341
          view[i] == '?' || view[i] == '[') {
11342
        return i;
11343
      }
11344
    }
11345
    return size_t(view.size());
11346
  }
11347
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
11348
    uint8x16_t bit_mask =
11349
        ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
11350
                            0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
11351
    uint8x16_t minput = vandq_u8(input, bit_mask);
11352
    uint8x16_t tmp = vpaddq_u8(minput, minput);
11353
    tmp = vpaddq_u8(tmp, tmp);
11354
    tmp = vpaddq_u8(tmp, tmp);
11355
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
11356
  };
11357
11358
  // fast path for long strings (expected to be common)
11359
  size_t i = location;
11360
  uint8x16_t low_mask =
11361
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11362
                          0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
11363
  uint8x16_t high_mask =
11364
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
11365
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11366
  uint8x16_t fmask = vmovq_n_u8(0xf);
11367
  uint8x16_t zero{0};
11368
  for (; i + 15 < view.size(); i += 16) {
11369
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
11370
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11371
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11372
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11373
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11374
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11375
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11376
      return i + trailing_zeroes(is_non_zero);
11377
    }
11378
  }
11379
11380
  if (i < view.size()) {
11381
    uint8x16_t word =
11382
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
11383
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11384
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11385
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11386
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11387
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11388
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11389
      return view.length() - 16 + trailing_zeroes(is_non_zero);
11390
    }
11391
  }
11392
  return size_t(view.size());
11393
}
11394
#elif ADA_SSE2
11395
ada_really_inline size_t find_next_host_delimiter_special(
11396
59.4k
    std::string_view view, size_t location) noexcept {
11397
  // first check for short strings in which case we do it naively.
11398
59.4k
  if (view.size() - location < 16) {  // slow path
11399
395k
    for (size_t i = location; i < view.size(); i++) {
11400
366k
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11401
353k
          view[i] == '?' || view[i] == '[') {
11402
13.8k
        return i;
11403
13.8k
      }
11404
366k
    }
11405
28.8k
    return size_t(view.size());
11406
42.6k
  }
11407
  // fast path for long strings (expected to be common)
11408
16.7k
  size_t i = location;
11409
16.7k
  const __m128i mask1 = _mm_set1_epi8(':');
11410
16.7k
  const __m128i mask2 = _mm_set1_epi8('/');
11411
16.7k
  const __m128i mask3 = _mm_set1_epi8('\\');
11412
16.7k
  const __m128i mask4 = _mm_set1_epi8('?');
11413
16.7k
  const __m128i mask5 = _mm_set1_epi8('[');
11414
11415
45.2k
  for (; i + 15 < view.size(); i += 16) {
11416
39.5k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11417
39.5k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11418
39.5k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11419
39.5k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11420
39.5k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11421
39.5k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11422
39.5k
    __m128i m = _mm_or_si128(
11423
39.5k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11424
39.5k
    int mask = _mm_movemask_epi8(m);
11425
39.5k
    if (mask != 0) {
11426
11.0k
      return i + trailing_zeroes(mask);
11427
11.0k
    }
11428
39.5k
  }
11429
5.65k
  if (i < view.size()) {
11430
5.07k
    __m128i word =
11431
5.07k
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11432
5.07k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11433
5.07k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11434
5.07k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11435
5.07k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11436
5.07k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11437
5.07k
    __m128i m = _mm_or_si128(
11438
5.07k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11439
5.07k
    int mask = _mm_movemask_epi8(m);
11440
5.07k
    if (mask != 0) {
11441
1.38k
      return view.length() - 16 + trailing_zeroes(mask);
11442
1.38k
    }
11443
5.07k
  }
11444
4.27k
  return size_t(view.length());
11445
5.65k
}
11446
#elif ADA_LSX
11447
ada_really_inline size_t find_next_host_delimiter_special(
11448
    std::string_view view, size_t location) noexcept {
11449
  // first check for short strings in which case we do it naively.
11450
  if (view.size() - location < 16) {  // slow path
11451
    for (size_t i = location; i < view.size(); i++) {
11452
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11453
          view[i] == '?' || view[i] == '[') {
11454
        return i;
11455
      }
11456
    }
11457
    return size_t(view.size());
11458
  }
11459
  // fast path for long strings (expected to be common)
11460
  size_t i = location;
11461
  const __m128i mask1 = __lsx_vrepli_b(':');
11462
  const __m128i mask2 = __lsx_vrepli_b('/');
11463
  const __m128i mask3 = __lsx_vrepli_b('\\');
11464
  const __m128i mask4 = __lsx_vrepli_b('?');
11465
  const __m128i mask5 = __lsx_vrepli_b('[');
11466
11467
  for (; i + 15 < view.size(); i += 16) {
11468
    __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0);
11469
    __m128i m1 = __lsx_vseq_b(word, mask1);
11470
    __m128i m2 = __lsx_vseq_b(word, mask2);
11471
    __m128i m3 = __lsx_vseq_b(word, mask3);
11472
    __m128i m4 = __lsx_vseq_b(word, mask4);
11473
    __m128i m5 = __lsx_vseq_b(word, mask5);
11474
    __m128i m =
11475
        __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5);
11476
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11477
    if (mask != 0) {
11478
      return i + trailing_zeroes(mask);
11479
    }
11480
  }
11481
  if (i < view.size()) {
11482
    __m128i word =
11483
        __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0);
11484
    __m128i m1 = __lsx_vseq_b(word, mask1);
11485
    __m128i m2 = __lsx_vseq_b(word, mask2);
11486
    __m128i m3 = __lsx_vseq_b(word, mask3);
11487
    __m128i m4 = __lsx_vseq_b(word, mask4);
11488
    __m128i m5 = __lsx_vseq_b(word, mask5);
11489
    __m128i m =
11490
        __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5);
11491
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11492
    if (mask != 0) {
11493
      return view.length() - 16 + trailing_zeroes(mask);
11494
    }
11495
  }
11496
  return size_t(view.length());
11497
}
11498
#elif ADA_RVV
11499
ada_really_inline size_t find_next_host_delimiter_special(
11500
    std::string_view view, size_t location) noexcept {
11501
  // The LUT approach was a bit slower on the SpacemiT X60, but I could see it
11502
  // beeing faster on future hardware.
11503
#if 0
11504
  // LUT generated using: s=":/\\?["; list(zip([((ord(c)>>2)&0xF)for c in s],s))
11505
  static const uint8_t tbl[16] = {
11506
    0xF, 0, 0, 0, 0, 0, '[', '\\', 0, 0, 0, '/', 0, 0, ':', '?'
11507
  };
11508
  vuint8m1_t vtbl = __riscv_vle8_v_u8m1(tbl, 16);
11509
#endif
11510
  uint8_t* src = (uint8_t*)view.data() + location;
11511
  for (size_t vl, n = view.size() - location; n > 0;
11512
       n -= vl, src += vl, location += vl) {
11513
    vl = __riscv_vsetvl_e8m1(n);
11514
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
11515
#if 0
11516
    vuint8m1_t vidx = __riscv_vand(__riscv_vsrl(v, 2, vl), 0xF, vl);
11517
    vuint8m1_t vlut = __riscv_vrgather(vtbl, vidx, vl);
11518
    vbool8_t m = __riscv_vmseq(v, vlut, vl);
11519
#else
11520
    vbool8_t m1 = __riscv_vmseq(v, ':', vl);
11521
    vbool8_t m2 = __riscv_vmseq(v, '/', vl);
11522
    vbool8_t m3 = __riscv_vmseq(v, '?', vl);
11523
    vbool8_t m4 = __riscv_vmseq(v, '[', vl);
11524
    vbool8_t m5 = __riscv_vmseq(v, '\\', vl);
11525
    vbool8_t m = __riscv_vmor(
11526
        __riscv_vmor(__riscv_vmor(m1, m2, vl), __riscv_vmor(m3, m4, vl), vl),
11527
        m5, vl);
11528
#endif
11529
    long idx = __riscv_vfirst(m, vl);
11530
    if (idx >= 0) return location + idx;
11531
  }
11532
  return size_t(view.size());
11533
}
11534
#else
11535
// : / [ \\ ?
11536
static constexpr std::array<uint8_t, 256> special_host_delimiters =
11537
    []() consteval {
11538
      std::array<uint8_t, 256> result{};
11539
      for (int i : {':', '/', '[', '\\', '?'}) {
11540
        result[i] = 1;
11541
      }
11542
      return result;
11543
    }();
11544
// credit: @the-moisrex recommended a table-based approach
11545
ada_really_inline size_t find_next_host_delimiter_special(
11546
    std::string_view view, size_t location) noexcept {
11547
  auto const str = view.substr(location);
11548
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
11549
    if (special_host_delimiters[(uint8_t)*pos]) {
11550
      return pos - str.begin() + location;
11551
    }
11552
  }
11553
  return size_t(view.size());
11554
}
11555
#endif
11556
11557
// starting at index location, this finds the next location of a character
11558
// :, /, ? or [. If none is found, view.size() is returned.
11559
// For use within get_host_delimiter_location.
11560
#if ADA_NEON
11561
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11562
                                                  size_t location) noexcept {
11563
  // first check for short strings in which case we do it naively.
11564
  if (view.size() - location < 16) {  // slow path
11565
    for (size_t i = location; i < view.size(); i++) {
11566
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11567
          view[i] == '[') {
11568
        return i;
11569
      }
11570
    }
11571
    return size_t(view.size());
11572
  }
11573
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
11574
    uint8x16_t bit_mask =
11575
        ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
11576
                            0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
11577
    uint8x16_t minput = vandq_u8(input, bit_mask);
11578
    uint8x16_t tmp = vpaddq_u8(minput, minput);
11579
    tmp = vpaddq_u8(tmp, tmp);
11580
    tmp = vpaddq_u8(tmp, tmp);
11581
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
11582
  };
11583
11584
  // fast path for long strings (expected to be common)
11585
  size_t i = location;
11586
  uint8x16_t low_mask =
11587
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11588
                          0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
11589
  uint8x16_t high_mask =
11590
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
11591
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11592
  uint8x16_t fmask = vmovq_n_u8(0xf);
11593
  uint8x16_t zero{0};
11594
  for (; i + 15 < view.size(); i += 16) {
11595
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
11596
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11597
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11598
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11599
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11600
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11601
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11602
      return i + trailing_zeroes(is_non_zero);
11603
    }
11604
  }
11605
11606
  if (i < view.size()) {
11607
    uint8x16_t word =
11608
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
11609
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11610
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11611
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11612
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11613
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11614
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11615
      return view.length() - 16 + trailing_zeroes(is_non_zero);
11616
    }
11617
  }
11618
  return size_t(view.size());
11619
}
11620
#elif ADA_SSE2
11621
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11622
1.32k
                                                  size_t location) noexcept {
11623
  // first check for short strings in which case we do it naively.
11624
1.32k
  if (view.size() - location < 16) {  // slow path
11625
1.83k
    for (size_t i = location; i < view.size(); i++) {
11626
1.46k
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11627
1.31k
          view[i] == '[') {
11628
310
        return i;
11629
310
      }
11630
1.46k
    }
11631
370
    return size_t(view.size());
11632
680
  }
11633
  // fast path for long strings (expected to be common)
11634
646
  size_t i = location;
11635
646
  const __m128i mask1 = _mm_set1_epi8(':');
11636
646
  const __m128i mask2 = _mm_set1_epi8('/');
11637
646
  const __m128i mask4 = _mm_set1_epi8('?');
11638
646
  const __m128i mask5 = _mm_set1_epi8('[');
11639
11640
1.99k
  for (; i + 15 < view.size(); i += 16) {
11641
1.80k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11642
1.80k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11643
1.80k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11644
1.80k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11645
1.80k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11646
1.80k
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
11647
1.80k
    int mask = _mm_movemask_epi8(m);
11648
1.80k
    if (mask != 0) {
11649
460
      return i + trailing_zeroes(mask);
11650
460
    }
11651
1.80k
  }
11652
186
  if (i < view.size()) {
11653
146
    __m128i word =
11654
146
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11655
146
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11656
146
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11657
146
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11658
146
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11659
146
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
11660
146
    int mask = _mm_movemask_epi8(m);
11661
146
    if (mask != 0) {
11662
62
      return view.length() - 16 + trailing_zeroes(mask);
11663
62
    }
11664
146
  }
11665
124
  return size_t(view.length());
11666
186
}
11667
#elif ADA_LSX
11668
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11669
                                                  size_t location) noexcept {
11670
  // first check for short strings in which case we do it naively.
11671
  if (view.size() - location < 16) {  // slow path
11672
    for (size_t i = location; i < view.size(); i++) {
11673
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11674
          view[i] == '[') {
11675
        return i;
11676
      }
11677
    }
11678
    return size_t(view.size());
11679
  }
11680
  // fast path for long strings (expected to be common)
11681
  size_t i = location;
11682
  const __m128i mask1 = __lsx_vrepli_b(':');
11683
  const __m128i mask2 = __lsx_vrepli_b('/');
11684
  const __m128i mask4 = __lsx_vrepli_b('?');
11685
  const __m128i mask5 = __lsx_vrepli_b('[');
11686
11687
  for (; i + 15 < view.size(); i += 16) {
11688
    __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0);
11689
    __m128i m1 = __lsx_vseq_b(word, mask1);
11690
    __m128i m2 = __lsx_vseq_b(word, mask2);
11691
    __m128i m4 = __lsx_vseq_b(word, mask4);
11692
    __m128i m5 = __lsx_vseq_b(word, mask5);
11693
    __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5));
11694
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11695
    if (mask != 0) {
11696
      return i + trailing_zeroes(mask);
11697
    }
11698
  }
11699
  if (i < view.size()) {
11700
    __m128i word =
11701
        __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0);
11702
    __m128i m1 = __lsx_vseq_b(word, mask1);
11703
    __m128i m2 = __lsx_vseq_b(word, mask2);
11704
    __m128i m4 = __lsx_vseq_b(word, mask4);
11705
    __m128i m5 = __lsx_vseq_b(word, mask5);
11706
    __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5));
11707
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11708
    if (mask != 0) {
11709
      return view.length() - 16 + trailing_zeroes(mask);
11710
    }
11711
  }
11712
  return size_t(view.length());
11713
}
11714
#elif ADA_RVV
11715
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11716
                                                  size_t location) noexcept {
11717
  uint8_t* src = (uint8_t*)view.data() + location;
11718
  for (size_t vl, n = view.size() - location; n > 0;
11719
       n -= vl, src += vl, location += vl) {
11720
    vl = __riscv_vsetvl_e8m1(n);
11721
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
11722
    vbool8_t m1 = __riscv_vmseq(v, ':', vl);
11723
    vbool8_t m2 = __riscv_vmseq(v, '/', vl);
11724
    vbool8_t m3 = __riscv_vmseq(v, '?', vl);
11725
    vbool8_t m4 = __riscv_vmseq(v, '[', vl);
11726
    vbool8_t m =
11727
        __riscv_vmor(__riscv_vmor(m1, m2, vl), __riscv_vmor(m3, m4, vl), vl);
11728
    long idx = __riscv_vfirst(m, vl);
11729
    if (idx >= 0) return location + idx;
11730
  }
11731
  return size_t(view.size());
11732
}
11733
#else
11734
// : / [ ?
11735
static constexpr std::array<uint8_t, 256> host_delimiters = []() consteval {
11736
  std::array<uint8_t, 256> result{};
11737
  for (int i : {':', '/', '?', '['}) {
11738
    result[i] = 1;
11739
  }
11740
  return result;
11741
}();
11742
// credit: @the-moisrex recommended a table-based approach
11743
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11744
                                                  size_t location) noexcept {
11745
  auto const str = view.substr(location);
11746
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
11747
    if (host_delimiters[(uint8_t)*pos]) {
11748
      return pos - str.begin() + location;
11749
    }
11750
  }
11751
  return size_t(view.size());
11752
}
11753
#endif
11754
11755
ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
11756
56.8k
    const bool is_special, std::string_view& view) noexcept {
11757
  /**
11758
   * The spec at https://url.spec.whatwg.org/#hostname-state expects us to
11759
   * compute a variable called insideBrackets but this variable is only used
11760
   * once, to check whether a ':' character was found outside brackets. Exact
11761
   * text: "Otherwise, if c is U+003A (:) and insideBrackets is false, then:".
11762
   * It is conceptually simpler and arguably more efficient to just return a
11763
   * Boolean indicating whether ':' was found outside brackets.
11764
   */
11765
56.8k
  const size_t view_size = view.size();
11766
56.8k
  size_t location = 0;
11767
56.8k
  bool found_colon = false;
11768
  /**
11769
   * Performance analysis:
11770
   *
11771
   * We are basically seeking the end of the hostname which can be indicated
11772
   * by the end of the view, or by one of the characters ':', '/', '?', '\\'
11773
   * (where '\\' is only applicable for special URLs). However, these must
11774
   * appear outside a bracket range. E.g., if you have [something?]fd: then the
11775
   * '?' does not count.
11776
   *
11777
   * So we can skip ahead to the next delimiter, as long as we include '[' in
11778
   * the set of delimiters, and that we handle it first.
11779
   *
11780
   * So the trick is to have a fast function that locates the next delimiter.
11781
   * Unless we find '[', then it only needs to be called once! Ideally, such a
11782
   * function would be provided by the C++ standard library, but it seems that
11783
   * find_first_of is not very fast, so we are forced to roll our own.
11784
   *
11785
   * We do not break into two loops for speed, but for clarity.
11786
   */
11787
56.8k
  if (is_special) {
11788
    // We move to the next delimiter.
11789
56.0k
    location = find_next_host_delimiter_special(view, location);
11790
    // Unless we find '[' then we are going only going to have to call
11791
    // find_next_host_delimiter_special once.
11792
59.4k
    for (; location < view_size;
11793
56.0k
         location = find_next_host_delimiter_special(view, location)) {
11794
26.3k
      if (view[location] == '[') {
11795
3.65k
        location = view.find(']', location);
11796
3.65k
        if (location == std::string_view::npos) {
11797
          // performance: view.find might get translated to a memchr, which
11798
          // has no notion of std::string_view::npos, so the code does not
11799
          // reflect the assembly.
11800
276
          location = view_size;
11801
276
          break;
11802
276
        }
11803
22.6k
      } else {
11804
22.6k
        found_colon = view[location] == ':';
11805
22.6k
        break;
11806
22.6k
      }
11807
26.3k
    }
11808
56.0k
  } else {
11809
    // We move to the next delimiter.
11810
822
    location = find_next_host_delimiter(view, location);
11811
    // Unless we find '[' then we are going only going to have to call
11812
    // find_next_host_delimiter_special once.
11813
1.32k
    for (; location < view_size;
11814
832
         location = find_next_host_delimiter(view, location)) {
11815
832
      if (view[location] == '[') {
11816
542
        location = view.find(']', location);
11817
542
        if (location == std::string_view::npos) {
11818
          // performance: view.find might get translated to a memchr, which
11819
          // has no notion of std::string_view::npos, so the code does not
11820
          // reflect the assembly.
11821
38
          location = view_size;
11822
38
          break;
11823
38
        }
11824
542
      } else {
11825
290
        found_colon = view[location] == ':';
11826
290
        break;
11827
290
      }
11828
832
    }
11829
822
  }
11830
  // performance: remove_suffix may translate into a single instruction.
11831
56.8k
  view.remove_suffix(view_size - location);
11832
56.8k
  return {location, found_colon};
11833
56.8k
}
11834
11835
42.9k
void trim_c0_whitespace(std::string_view& input) noexcept {
11836
45.6k
  while (!input.empty() &&
11837
45.5k
         ada::unicode::is_c0_control_or_space(input.front())) {
11838
2.65k
    input.remove_prefix(1);
11839
2.65k
  }
11840
45.6k
  while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
11841
2.68k
    input.remove_suffix(1);
11842
2.68k
  }
11843
42.9k
}
11844
11845
ada_really_inline void parse_prepared_path(std::string_view input,
11846
                                           ada::scheme::type type,
11847
20.6k
                                           std::string& path) {
11848
20.6k
  ada_log("parse_prepared_path ", input);
11849
20.6k
  uint8_t accumulator = checkers::path_signature(input);
11850
  // Let us first detect a trivial case.
11851
  // If it is special, we check that we have no dot, no %,  no \ and no
11852
  // character needing percent encoding. Otherwise, we check that we have no %,
11853
  // no dot, and no character needing percent encoding.
11854
20.6k
  constexpr uint8_t need_encoding = 1;
11855
20.6k
  constexpr uint8_t backslash_char = 2;
11856
20.6k
  constexpr uint8_t dot_char = 4;
11857
20.6k
  constexpr uint8_t percent_char = 8;
11858
20.6k
  bool special = type != ada::scheme::NOT_SPECIAL;
11859
20.6k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
11860
10.6k
                                      checkers::is_windows_drive_letter(input));
11861
20.6k
  bool trivial_path =
11862
20.6k
      (special ? (accumulator == 0)
11863
20.6k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
11864
951
                  0)) &&
11865
3.82k
      (!may_need_slow_file_handling);
11866
20.6k
  if (accumulator == dot_char && !may_need_slow_file_handling) {
11867
    // '4' means that we have at least one dot, but nothing that requires
11868
    // percent encoding or decoding. The only part that is not trivial is
11869
    // that we may have single dots and double dots path segments.
11870
    // If we have such segments, then we either have a path that begins
11871
    // with '.' (easy to check), or we have the sequence './'.
11872
    // Note: input cannot be empty, it must at least contain one character ('.')
11873
    // Note: we know that '\' is not present.
11874
3.98k
    if (input[0] != '.') {
11875
2.96k
      size_t slashdot = 0;
11876
2.96k
      bool dot_is_file = true;
11877
13.9k
      for (;;) {
11878
13.9k
        slashdot = input.find("/.", slashdot);
11879
13.9k
        if (slashdot == std::string_view::npos) {  // common case
11880
2.96k
          break;
11881
10.9k
        } else {  // uncommon
11882
          // only three cases matter: /./, /.. or a final /
11883
10.9k
          slashdot += 2;
11884
10.9k
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
11885
2.45k
                           input[slashdot] == '/');
11886
10.9k
        }
11887
13.9k
      }
11888
2.96k
      trivial_path = dot_is_file;
11889
2.96k
    }
11890
3.98k
  }
11891
20.6k
  if (trivial_path) {
11892
4.90k
    ada_log("parse_path trivial");
11893
4.90k
    path += '/';
11894
4.90k
    path += input;
11895
4.90k
    return;
11896
4.90k
  }
11897
  // We are going to need to look a bit at the path, but let us see if we can
11898
  // ignore percent encoding *and* backslashes *and* percent characters.
11899
  // Except for the trivial case, this is likely to capture 99% of paths out
11900
  // there.
11901
15.7k
  bool fast_path =
11902
15.7k
      (special &&
11903
14.8k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
11904
2.84k
      (type != ada::scheme::type::FILE);
11905
15.7k
  if (fast_path) {
11906
1.37k
    ada_log("parse_prepared_path fast");
11907
    // Here we don't need to worry about \ or percent encoding.
11908
    // We also do not have a file protocol. We might have dots, however,
11909
    // but dots must as appear as '.', and they cannot be encoded because
11910
    // the symbol '%' is not present.
11911
1.37k
    size_t previous_location = 0;  // We start at 0.
11912
17.1k
    do {
11913
17.1k
      size_t new_location = input.find('/', previous_location);
11914
      // std::string_view path_view = input;
11915
      //  We process the last segment separately:
11916
17.1k
      if (new_location == std::string_view::npos) {
11917
1.37k
        std::string_view path_view = input.substr(previous_location);
11918
1.37k
        if (path_view == "..") {  // The path ends with ..
11919
          // e.g., if you receive ".." with an empty path, you go to "/".
11920
178
          if (path.empty()) {
11921
73
            path = '/';
11922
73
            return;
11923
73
          }
11924
          // Fast case where we have nothing to do:
11925
105
          if (path.back() == '/') {
11926
39
            return;
11927
39
          }
11928
          // If you have the path "/joe/myfriend",
11929
          // then you delete 'myfriend'.
11930
66
          path.resize(path.rfind('/') + 1);
11931
66
          return;
11932
105
        }
11933
1.20k
        path += '/';
11934
1.20k
        if (path_view != ".") {
11935
932
          path.append(path_view);
11936
932
        }
11937
1.20k
        return;
11938
15.7k
      } else {
11939
        // This is a non-final segment.
11940
15.7k
        std::string_view path_view =
11941
15.7k
            input.substr(previous_location, new_location - previous_location);
11942
15.7k
        previous_location = new_location + 1;
11943
15.7k
        if (path_view == "..") {
11944
3.57k
          size_t last_delimiter = path.rfind('/');
11945
3.57k
          if (last_delimiter != std::string::npos) {
11946
1.83k
            path.erase(last_delimiter);
11947
1.83k
          }
11948
12.1k
        } else if (path_view != ".") {
11949
10.0k
          path += '/';
11950
10.0k
          path.append(path_view);
11951
10.0k
        }
11952
15.7k
      }
11953
17.1k
    } while (true);
11954
14.3k
  } else {
11955
14.3k
    ada_log("parse_path slow");
11956
    // we have reached the general case
11957
14.3k
    bool needs_percent_encoding = (accumulator & 1);
11958
14.3k
    std::string path_buffer_tmp;
11959
78.9k
    do {
11960
78.9k
      size_t location = (special && (accumulator & 2))
11961
78.9k
                            ? input.find_first_of("/\\")
11962
78.9k
                            : input.find('/');
11963
78.9k
      std::string_view path_view = input;
11964
78.9k
      if (location != std::string_view::npos) {
11965
64.6k
        path_view.remove_suffix(path_view.size() - location);
11966
64.6k
        input.remove_prefix(location + 1);
11967
64.6k
      }
11968
      // path_buffer is either path_view or it might point at a percent encoded
11969
      // temporary file.
11970
78.9k
      std::string_view path_buffer =
11971
78.9k
          (needs_percent_encoding &&
11972
46.7k
           ada::unicode::percent_encode<false>(
11973
46.7k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
11974
78.9k
              ? path_buffer_tmp
11975
78.9k
              : path_view;
11976
78.9k
      if (unicode::is_double_dot_path_segment(path_buffer)) {
11977
17.0k
        helpers::shorten_path(path, type);
11978
17.0k
        if (location == std::string_view::npos) {
11979
1.36k
          path += '/';
11980
1.36k
        }
11981
61.9k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
11982
4.77k
                 (location == std::string_view::npos)) {
11983
419
        path += '/';
11984
419
      }
11985
      // Otherwise, if path_buffer is not a single-dot path segment, then:
11986
61.5k
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
11987
        // If url's scheme is "file", url's path is empty, and path_buffer is a
11988
        // Windows drive letter, then replace the second code point in
11989
        // path_buffer with U+003A (:).
11990
57.1k
        if (type == ada::scheme::type::FILE && path.empty() &&
11991
12.7k
            checkers::is_windows_drive_letter(path_buffer)) {
11992
831
          path += '/';
11993
831
          path += path_buffer[0];
11994
831
          path += ':';
11995
831
          path_buffer.remove_prefix(2);
11996
831
          path.append(path_buffer);
11997
56.3k
        } else {
11998
          // Append path_buffer to url's path.
11999
56.3k
          path += '/';
12000
56.3k
          path.append(path_buffer);
12001
56.3k
        }
12002
57.1k
      }
12003
78.9k
      if (location == std::string_view::npos) {
12004
14.3k
        return;
12005
14.3k
      }
12006
78.9k
    } while (true);
12007
14.3k
  }
12008
15.7k
}
12009
12010
0
bool overlaps(std::string_view input1, const std::string& input2) noexcept {
12011
0
  ada_log("helpers::overlaps check if string_view '", input1, "' [",
12012
0
          input1.size(), " bytes] is part of string '", input2, "' [",
12013
0
          input2.size(), " bytes]");
12014
0
  return !input1.empty() && !input2.empty() && input1.data() >= input2.data() &&
12015
0
         input1.data() < input2.data() + input2.size();
12016
0
}
12017
12018
template <class url_type>
12019
ada_really_inline void strip_trailing_spaces_from_opaque_path(
12020
12
    url_type& url) noexcept {
12021
12
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
12022
12
  if (!url.has_opaque_path) return;
12023
0
  if (url.has_hash()) return;
12024
0
  if (url.has_search()) return;
12025
12026
0
  auto path = std::string(url.get_pathname());
12027
0
  while (!path.empty() && path.back() == ' ') {
12028
0
    path.resize(path.size() - 1);
12029
0
  }
12030
0
  url.update_base_pathname(path);
12031
0
}
void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url>(ada::url&)
Line
Count
Source
12020
6
    url_type& url) noexcept {
12021
6
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
12022
6
  if (!url.has_opaque_path) return;
12023
0
  if (url.has_hash()) return;
12024
0
  if (url.has_search()) return;
12025
12026
0
  auto path = std::string(url.get_pathname());
12027
0
  while (!path.empty() && path.back() == ' ') {
12028
0
    path.resize(path.size() - 1);
12029
0
  }
12030
0
  url.update_base_pathname(path);
12031
0
}
void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url_aggregator>(ada::url_aggregator&)
Line
Count
Source
12020
6
    url_type& url) noexcept {
12021
6
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
12022
6
  if (!url.has_opaque_path) return;
12023
0
  if (url.has_hash()) return;
12024
0
  if (url.has_search()) return;
12025
12026
0
  auto path = std::string(url.get_pathname());
12027
0
  while (!path.empty() && path.back() == ' ') {
12028
0
    path.resize(path.size() - 1);
12029
0
  }
12030
0
  url.update_base_pathname(path);
12031
0
}
12032
12033
// @ / \\ ?
12034
static constexpr std::array<uint8_t, 256> authority_delimiter_special =
12035
    []() consteval {
12036
      std::array<uint8_t, 256> result{};
12037
      for (uint8_t i : {'@', '/', '\\', '?'}) {
12038
        result[i] = 1;
12039
      }
12040
      return result;
12041
    }();
12042
// credit: @the-moisrex recommended a table-based approach
12043
ada_really_inline size_t
12044
15.9k
find_authority_delimiter_special(std::string_view view) noexcept {
12045
  // performance note: we might be able to gain further performance
12046
  // with SIMD instrinsics.
12047
77.9k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12048
76.7k
    if (authority_delimiter_special[(uint8_t)*pos]) {
12049
14.7k
      return pos - view.begin();
12050
14.7k
    }
12051
76.7k
  }
12052
1.20k
  return size_t(view.size());
12053
15.9k
}
12054
12055
// @ / ?
12056
static constexpr std::array<uint8_t, 256> authority_delimiter = []() consteval {
12057
  std::array<uint8_t, 256> result{};
12058
  for (uint8_t i : {'@', '/', '?'}) {
12059
    result[i] = 1;
12060
  }
12061
  return result;
12062
}();
12063
// credit: @the-moisrex recommended a table-based approach
12064
ada_really_inline size_t
12065
1.97k
find_authority_delimiter(std::string_view view) noexcept {
12066
  // performance note: we might be able to gain further performance
12067
  // with SIMD instrinsics.
12068
7.44k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12069
7.28k
    if (authority_delimiter[(uint8_t)*pos]) {
12070
1.81k
      return pos - view.begin();
12071
1.81k
    }
12072
7.28k
  }
12073
154
  return size_t(view.size());
12074
1.97k
}
12075
12076
}  // namespace ada::helpers
12077
12078
namespace ada {
12079
0
ada_warn_unused std::string to_string(ada::state state) {
12080
0
  return ada::helpers::get_state(state);
12081
0
}
12082
#undef ada_make_uint8x16_t
12083
}  // namespace ada
12084
/* end file src/helpers.cpp */
12085
/* begin file src/url.cpp */
12086
12087
#include <numeric>
12088
#include <algorithm>
12089
#include <iterator>
12090
#include <ranges>
12091
#include <string>
12092
#include <string_view>
12093
12094
namespace ada {
12095
12096
273
bool url::parse_opaque_host(std::string_view input) {
12097
273
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
12098
273
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
12099
23
    return is_valid = false;
12100
23
  }
12101
12102
  // Return the result of running UTF-8 percent-encode on input using the C0
12103
  // control percent-encode set.
12104
250
  host = ada::unicode::percent_encode(
12105
250
      input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
12106
250
  return true;
12107
273
}
12108
12109
2.25k
bool url::parse_ipv4(std::string_view input) {
12110
2.25k
  ada_log("parse_ipv4 ", input, " [", input.size(), " bytes]");
12111
2.25k
  if (input.back() == '.') {
12112
29
    input.remove_suffix(1);
12113
29
  }
12114
2.25k
  size_t digit_count{0};
12115
2.25k
  int pure_decimal_count = 0;  // entries that are decimal
12116
2.25k
  std::string_view original_input =
12117
2.25k
      input;  // we might use this if pure_decimal_count == 4.
12118
2.25k
  uint64_t ipv4{0};
12119
  // we could unroll for better performance?
12120
2.70k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
12121
2.68k
    uint32_t
12122
2.68k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
12123
2.68k
    bool is_hex = checkers::has_hex_prefix(input);
12124
2.68k
    if (is_hex && ((input.length() == 2) ||
12125
899
                   ((input.length() > 2) && (input[2] == '.')))) {
12126
      // special case
12127
53
      segment_result = 0;
12128
53
      input.remove_prefix(2);
12129
2.62k
    } else {
12130
2.62k
      std::from_chars_result r{};
12131
2.62k
      if (is_hex) {
12132
879
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
12133
879
                            segment_result, 16);
12134
1.74k
      } else if ((input.length() >= 2) && input[0] == '0' &&
12135
504
                 checkers::is_digit(input[1])) {
12136
405
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
12137
405
                            segment_result, 8);
12138
1.34k
      } else {
12139
1.34k
        pure_decimal_count++;
12140
1.34k
        r = std::from_chars(input.data(), input.data() + input.size(),
12141
1.34k
                            segment_result, 10);
12142
1.34k
      }
12143
2.62k
      if (r.ec != std::errc()) {
12144
460
        return is_valid = false;
12145
460
      }
12146
2.16k
      input.remove_prefix(r.ptr - input.data());
12147
2.16k
    }
12148
2.22k
    if (input.empty()) {
12149
      // We have the last value.
12150
      // At this stage, ipv4 contains digit_count*8 bits.
12151
      // So we have 32-digit_count*8 bits left.
12152
1.57k
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
12153
47
        return is_valid = false;
12154
47
      }
12155
1.52k
      ipv4 <<= (32 - digit_count * 8);
12156
1.52k
      ipv4 |= segment_result;
12157
1.52k
      goto final;
12158
1.57k
    } else {
12159
      // There is more, so that the value must no be larger than 255
12160
      // and we must have a '.'.
12161
647
      if ((segment_result > 255) || (input[0] != '.')) {
12162
198
        return is_valid = false;
12163
198
      }
12164
449
      ipv4 <<= 8;
12165
449
      ipv4 |= segment_result;
12166
449
      input.remove_prefix(1);  // remove '.'
12167
449
    }
12168
2.22k
  }
12169
20
  if ((digit_count != 4) || (!input.empty())) {
12170
20
    return is_valid = false;
12171
20
  }
12172
1.52k
final:
12173
  // We could also check r.ptr to see where the parsing ended.
12174
1.52k
  if (pure_decimal_count == 4) {
12175
13
    host = original_input;  // The original input was already all decimal and we
12176
                            // validated it.
12177
1.51k
  } else {
12178
1.51k
    host = ada::serializers::ipv4(ipv4);  // We have to reserialize the address.
12179
1.51k
  }
12180
1.52k
  host_type = IPV4;
12181
1.52k
  return true;
12182
20
}
12183
12184
417
bool url::parse_ipv6(std::string_view input) {
12185
417
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
12186
12187
417
  if (input.empty()) {
12188
25
    return is_valid = false;
12189
25
  }
12190
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
12191
392
  std::array<uint16_t, 8> address{};
12192
12193
  // Let pieceIndex be 0.
12194
392
  int piece_index = 0;
12195
12196
  // Let compress be null.
12197
392
  std::optional<int> compress{};
12198
12199
  // Let pointer be a pointer for input.
12200
392
  std::string_view::iterator pointer = input.begin();
12201
12202
  // If c is U+003A (:), then:
12203
392
  if (input[0] == ':') {
12204
    // If remaining does not start with U+003A (:), validation error, return
12205
    // failure.
12206
88
    if (input.size() == 1 || input[1] != ':') {
12207
19
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
12208
19
      return is_valid = false;
12209
19
    }
12210
12211
    // Increase pointer by 2.
12212
69
    pointer += 2;
12213
12214
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
12215
69
    compress = ++piece_index;
12216
69
  }
12217
12218
  // While c is not the EOF code point:
12219
914
  while (pointer != input.end()) {
12220
    // If pieceIndex is 8, validation error, return failure.
12221
752
    if (piece_index == 8) {
12222
5
      ada_log("parse_ipv6 piece_index == 8");
12223
5
      return is_valid = false;
12224
5
    }
12225
12226
    // If c is U+003A (:), then:
12227
747
    if (*pointer == ':') {
12228
      // If compress is non-null, validation error, return failure.
12229
55
      if (compress.has_value()) {
12230
4
        ada_log("parse_ipv6 compress is non-null");
12231
4
        return is_valid = false;
12232
4
      }
12233
12234
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
12235
      // then continue.
12236
51
      pointer++;
12237
51
      compress = ++piece_index;
12238
51
      continue;
12239
55
    }
12240
12241
    // Let value and length be 0.
12242
692
    uint16_t value = 0, length = 0;
12243
12244
    // While length is less than 4 and c is an ASCII hex digit,
12245
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
12246
    // increase pointer and length by 1.
12247
1.75k
    while (length < 4 && pointer != input.end() &&
12248
1.57k
           unicode::is_ascii_hex_digit(*pointer)) {
12249
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12250
1.06k
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
12251
1.06k
      pointer++;
12252
1.06k
      length++;
12253
1.06k
    }
12254
12255
    // If c is U+002E (.), then:
12256
692
    if (pointer != input.end() && *pointer == '.') {
12257
      // If length is 0, validation error, return failure.
12258
87
      if (length == 0) {
12259
3
        ada_log("parse_ipv6 length is 0");
12260
3
        return is_valid = false;
12261
3
      }
12262
12263
      // Decrease pointer by length.
12264
84
      pointer -= length;
12265
12266
      // If pieceIndex is greater than 6, validation error, return failure.
12267
84
      if (piece_index > 6) {
12268
3
        ada_log("parse_ipv6 piece_index > 6");
12269
3
        return is_valid = false;
12270
3
      }
12271
12272
      // Let numbersSeen be 0.
12273
81
      int numbers_seen = 0;
12274
12275
      // While c is not the EOF code point:
12276
202
      while (pointer != input.end()) {
12277
        // Let ipv4Piece be null.
12278
188
        std::optional<uint16_t> ipv4_piece{};
12279
12280
        // If numbersSeen is greater than 0, then:
12281
188
        if (numbers_seen > 0) {
12282
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
12283
          // pointer by 1.
12284
107
          if (*pointer == '.' && numbers_seen < 4) {
12285
83
            pointer++;
12286
83
          }
12287
          // Otherwise, validation error, return failure.
12288
24
          else {
12289
24
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
12290
24
            return is_valid = false;
12291
24
          }
12292
107
        }
12293
12294
        // If c is not an ASCII digit, validation error, return failure.
12295
164
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
12296
28
          ada_log(
12297
28
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
12298
28
              "failure");
12299
28
          return is_valid = false;
12300
28
        }
12301
12302
        // While c is an ASCII digit:
12303
343
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
12304
          // Let number be c interpreted as decimal number.
12305
222
          int number = *pointer - '0';
12306
12307
          // If ipv4Piece is null, then set ipv4Piece to number.
12308
222
          if (!ipv4_piece.has_value()) {
12309
136
            ipv4_piece = number;
12310
136
          }
12311
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
12312
86
          else if (ipv4_piece == 0) {
12313
3
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
12314
3
            return is_valid = false;
12315
3
          }
12316
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
12317
83
          else {
12318
83
            ipv4_piece = *ipv4_piece * 10 + number;
12319
83
          }
12320
12321
          // If ipv4Piece is greater than 255, validation error, return failure.
12322
219
          if (ipv4_piece > 255) {
12323
12
            ada_log("parse_ipv6 ipv4_piece > 255");
12324
12
            return is_valid = false;
12325
12
          }
12326
12327
          // Increase pointer by 1.
12328
207
          pointer++;
12329
207
        }
12330
12331
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
12332
        // ipv4Piece.
12333
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12334
121
        address[piece_index] =
12335
121
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
12336
12337
        // Increase numbersSeen by 1.
12338
121
        numbers_seen++;
12339
12340
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
12341
121
        if (numbers_seen == 2 || numbers_seen == 4) {
12342
42
          piece_index++;
12343
42
        }
12344
121
      }
12345
12346
      // If numbersSeen is not 4, validation error, return failure.
12347
14
      if (numbers_seen != 4) {
12348
11
        return is_valid = false;
12349
11
      }
12350
12351
      // Break.
12352
3
      break;
12353
14
    }
12354
    // Otherwise, if c is U+003A (:):
12355
605
    else if ((pointer != input.end()) && (*pointer == ':')) {
12356
      // Increase pointer by 1.
12357
377
      pointer++;
12358
12359
      // If c is the EOF code point, validation error, return failure.
12360
377
      if (pointer == input.end()) {
12361
4
        ada_log(
12362
4
            "parse_ipv6 If c is the EOF code point, validation error, return "
12363
4
            "failure");
12364
4
        return is_valid = false;
12365
4
      }
12366
377
    }
12367
    // Otherwise, if c is not the EOF code point, validation error, return
12368
    // failure.
12369
228
    else if (pointer != input.end()) {
12370
111
      ada_log(
12371
111
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
12372
111
          "error, return failure");
12373
111
      return is_valid = false;
12374
111
    }
12375
12376
    // Set address[pieceIndex] to value.
12377
490
    address[piece_index] = value;
12378
12379
    // Increase pieceIndex by 1.
12380
490
    piece_index++;
12381
490
  }
12382
12383
  // If compress is non-null, then:
12384
165
  if (compress.has_value()) {
12385
    // Let swaps be pieceIndex - compress.
12386
108
    int swaps = piece_index - *compress;
12387
12388
    // Set pieceIndex to 7.
12389
108
    piece_index = 7;
12390
12391
    // While pieceIndex is not 0 and swaps is greater than 0,
12392
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
12393
    // decrease both pieceIndex and swaps by 1.
12394
237
    while (piece_index != 0 && swaps > 0) {
12395
129
      std::swap(address[piece_index], address[*compress + swaps - 1]);
12396
129
      piece_index--;
12397
129
      swaps--;
12398
129
    }
12399
108
  }
12400
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
12401
  // return failure.
12402
57
  else if (piece_index != 8) {
12403
49
    ada_log(
12404
49
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
12405
49
        "error, return failure");
12406
49
    return is_valid = false;
12407
49
  }
12408
116
  host = ada::serializers::ipv6(address);
12409
116
  ada_log("parse_ipv6 ", *host);
12410
116
  host_type = IPV6;
12411
116
  return true;
12412
165
}
12413
12414
template <bool has_state_override>
12415
20.1k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12416
20.1k
  auto parsed_type = ada::scheme::get_scheme_type(input);
12417
20.1k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
12418
  /**
12419
   * In the common case, we will immediately recognize a special scheme (e.g.,
12420
   *http, https), in which case, we can go really fast.
12421
   **/
12422
20.1k
  if (is_input_special) {  // fast path!!!
12423
13.4k
    if constexpr (has_state_override) {
12424
      // If url's scheme is not a special scheme and buffer is a special scheme,
12425
      // then return.
12426
1.51k
      if (is_special() != is_input_special) {
12427
0
        return false;
12428
0
      }
12429
12430
      // If url includes credentials or has a non-null port, and buffer is
12431
      // "file", then return.
12432
1.51k
      if ((has_credentials() || port.has_value()) &&
12433
0
          parsed_type == ada::scheme::type::FILE) {
12434
0
        return false;
12435
0
      }
12436
12437
      // If url's scheme is "file" and its host is an empty host, then return.
12438
      // An empty host is the empty string.
12439
1.51k
      if (type == ada::scheme::type::FILE && host.has_value() &&
12440
0
          host.value().empty()) {
12441
0
        return false;
12442
0
      }
12443
1.51k
    }
12444
12445
1.51k
    type = parsed_type;
12446
12447
13.4k
    if constexpr (has_state_override) {
12448
      // This is uncommon.
12449
1.51k
      uint16_t urls_scheme_port = get_special_port();
12450
12451
1.51k
      if (urls_scheme_port) {
12452
        // If url's port is url's scheme's default port, then set url's port to
12453
        // null.
12454
1.03k
        if (port.has_value() && *port == urls_scheme_port) {
12455
0
          port = std::nullopt;
12456
0
        }
12457
1.03k
      }
12458
1.51k
    }
12459
13.4k
  } else {  // slow path
12460
6.74k
    std::string _buffer(input);
12461
    // Next function is only valid if the input is ASCII and returns false
12462
    // otherwise, but it seems that we always have ascii content so we do not
12463
    // need to check the return value.
12464
    // bool is_ascii =
12465
6.74k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
12466
12467
6.74k
    if constexpr (has_state_override) {
12468
      // If url's scheme is a special scheme and buffer is not a special scheme,
12469
      // then return. If url's scheme is not a special scheme and buffer is a
12470
      // special scheme, then return.
12471
2.49k
      if (is_special() != ada::scheme::is_special(_buffer)) {
12472
1.82k
        return true;
12473
1.82k
      }
12474
12475
      // If url includes credentials or has a non-null port, and buffer is
12476
      // "file", then return.
12477
674
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
12478
0
        return true;
12479
0
      }
12480
12481
      // If url's scheme is "file" and its host is an empty host, then return.
12482
      // An empty host is the empty string.
12483
674
      if (type == ada::scheme::type::FILE && host.has_value() &&
12484
0
          host.value().empty()) {
12485
0
        return true;
12486
0
      }
12487
674
    }
12488
12489
674
    set_scheme(std::move(_buffer));
12490
12491
6.74k
    if constexpr (has_state_override) {
12492
      // This is uncommon.
12493
2.49k
      uint16_t urls_scheme_port = get_special_port();
12494
12495
2.49k
      if (urls_scheme_port) {
12496
        // If url's port is url's scheme's default port, then set url's port to
12497
        // null.
12498
428
        if (port.has_value() && *port == urls_scheme_port) {
12499
0
          port = std::nullopt;
12500
0
        }
12501
428
      }
12502
2.49k
    }
12503
6.74k
  }
12504
12505
0
  return true;
12506
20.1k
}
bool ada::url::parse_scheme<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
12415
4.01k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12416
4.01k
  auto parsed_type = ada::scheme::get_scheme_type(input);
12417
4.01k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
12418
  /**
12419
   * In the common case, we will immediately recognize a special scheme (e.g.,
12420
   *http, https), in which case, we can go really fast.
12421
   **/
12422
4.01k
  if (is_input_special) {  // fast path!!!
12423
1.51k
    if constexpr (has_state_override) {
12424
      // If url's scheme is not a special scheme and buffer is a special scheme,
12425
      // then return.
12426
1.51k
      if (is_special() != is_input_special) {
12427
0
        return false;
12428
0
      }
12429
12430
      // If url includes credentials or has a non-null port, and buffer is
12431
      // "file", then return.
12432
1.51k
      if ((has_credentials() || port.has_value()) &&
12433
0
          parsed_type == ada::scheme::type::FILE) {
12434
0
        return false;
12435
0
      }
12436
12437
      // If url's scheme is "file" and its host is an empty host, then return.
12438
      // An empty host is the empty string.
12439
1.51k
      if (type == ada::scheme::type::FILE && host.has_value() &&
12440
0
          host.value().empty()) {
12441
0
        return false;
12442
0
      }
12443
1.51k
    }
12444
12445
1.51k
    type = parsed_type;
12446
12447
1.51k
    if constexpr (has_state_override) {
12448
      // This is uncommon.
12449
1.51k
      uint16_t urls_scheme_port = get_special_port();
12450
12451
1.51k
      if (urls_scheme_port) {
12452
        // If url's port is url's scheme's default port, then set url's port to
12453
        // null.
12454
1.03k
        if (port.has_value() && *port == urls_scheme_port) {
12455
0
          port = std::nullopt;
12456
0
        }
12457
1.03k
      }
12458
1.51k
    }
12459
2.49k
  } else {  // slow path
12460
2.49k
    std::string _buffer(input);
12461
    // Next function is only valid if the input is ASCII and returns false
12462
    // otherwise, but it seems that we always have ascii content so we do not
12463
    // need to check the return value.
12464
    // bool is_ascii =
12465
2.49k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
12466
12467
2.49k
    if constexpr (has_state_override) {
12468
      // If url's scheme is a special scheme and buffer is not a special scheme,
12469
      // then return. If url's scheme is not a special scheme and buffer is a
12470
      // special scheme, then return.
12471
2.49k
      if (is_special() != ada::scheme::is_special(_buffer)) {
12472
1.82k
        return true;
12473
1.82k
      }
12474
12475
      // If url includes credentials or has a non-null port, and buffer is
12476
      // "file", then return.
12477
674
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
12478
0
        return true;
12479
0
      }
12480
12481
      // If url's scheme is "file" and its host is an empty host, then return.
12482
      // An empty host is the empty string.
12483
674
      if (type == ada::scheme::type::FILE && host.has_value() &&
12484
0
          host.value().empty()) {
12485
0
        return true;
12486
0
      }
12487
674
    }
12488
12489
674
    set_scheme(std::move(_buffer));
12490
12491
2.49k
    if constexpr (has_state_override) {
12492
      // This is uncommon.
12493
2.49k
      uint16_t urls_scheme_port = get_special_port();
12494
12495
2.49k
      if (urls_scheme_port) {
12496
        // If url's port is url's scheme's default port, then set url's port to
12497
        // null.
12498
428
        if (port.has_value() && *port == urls_scheme_port) {
12499
0
          port = std::nullopt;
12500
0
        }
12501
428
      }
12502
2.49k
    }
12503
2.49k
  }
12504
12505
0
  return true;
12506
4.01k
}
bool ada::url::parse_scheme<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
12415
16.1k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12416
16.1k
  auto parsed_type = ada::scheme::get_scheme_type(input);
12417
16.1k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
12418
  /**
12419
   * In the common case, we will immediately recognize a special scheme (e.g.,
12420
   *http, https), in which case, we can go really fast.
12421
   **/
12422
16.1k
  if (is_input_special) {  // fast path!!!
12423
    if constexpr (has_state_override) {
12424
      // If url's scheme is not a special scheme and buffer is a special scheme,
12425
      // then return.
12426
      if (is_special() != is_input_special) {
12427
        return false;
12428
      }
12429
12430
      // If url includes credentials or has a non-null port, and buffer is
12431
      // "file", then return.
12432
      if ((has_credentials() || port.has_value()) &&
12433
          parsed_type == ada::scheme::type::FILE) {
12434
        return false;
12435
      }
12436
12437
      // If url's scheme is "file" and its host is an empty host, then return.
12438
      // An empty host is the empty string.
12439
      if (type == ada::scheme::type::FILE && host.has_value() &&
12440
          host.value().empty()) {
12441
        return false;
12442
      }
12443
    }
12444
12445
11.8k
    type = parsed_type;
12446
12447
    if constexpr (has_state_override) {
12448
      // This is uncommon.
12449
      uint16_t urls_scheme_port = get_special_port();
12450
12451
      if (urls_scheme_port) {
12452
        // If url's port is url's scheme's default port, then set url's port to
12453
        // null.
12454
        if (port.has_value() && *port == urls_scheme_port) {
12455
          port = std::nullopt;
12456
        }
12457
      }
12458
    }
12459
11.8k
  } else {  // slow path
12460
4.24k
    std::string _buffer(input);
12461
    // Next function is only valid if the input is ASCII and returns false
12462
    // otherwise, but it seems that we always have ascii content so we do not
12463
    // need to check the return value.
12464
    // bool is_ascii =
12465
4.24k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
12466
12467
    if constexpr (has_state_override) {
12468
      // If url's scheme is a special scheme and buffer is not a special scheme,
12469
      // then return. If url's scheme is not a special scheme and buffer is a
12470
      // special scheme, then return.
12471
      if (is_special() != ada::scheme::is_special(_buffer)) {
12472
        return true;
12473
      }
12474
12475
      // If url includes credentials or has a non-null port, and buffer is
12476
      // "file", then return.
12477
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
12478
        return true;
12479
      }
12480
12481
      // If url's scheme is "file" and its host is an empty host, then return.
12482
      // An empty host is the empty string.
12483
      if (type == ada::scheme::type::FILE && host.has_value() &&
12484
          host.value().empty()) {
12485
        return true;
12486
      }
12487
    }
12488
12489
4.24k
    set_scheme(std::move(_buffer));
12490
12491
    if constexpr (has_state_override) {
12492
      // This is uncommon.
12493
      uint16_t urls_scheme_port = get_special_port();
12494
12495
      if (urls_scheme_port) {
12496
        // If url's port is url's scheme's default port, then set url's port to
12497
        // null.
12498
        if (port.has_value() && *port == urls_scheme_port) {
12499
          port = std::nullopt;
12500
        }
12501
      }
12502
    }
12503
4.24k
  }
12504
12505
16.1k
  return true;
12506
16.1k
}
12507
12508
25.1k
ada_really_inline bool url::parse_host(std::string_view input) {
12509
25.1k
  ada_log("parse_host ", input, " [", input.size(), " bytes]");
12510
25.1k
  if (input.empty()) {
12511
9
    return is_valid = false;
12512
9
  }  // technically unnecessary.
12513
  // If input starts with U+005B ([), then:
12514
25.0k
  if (input[0] == '[') {
12515
    // If input does not end with U+005D (]), validation error, return failure.
12516
689
    if (input.back() != ']') {
12517
272
      return is_valid = false;
12518
272
    }
12519
417
    ada_log("parse_host ipv6");
12520
12521
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
12522
    // trailing U+005D (]) removed.
12523
417
    input.remove_prefix(1);
12524
417
    input.remove_suffix(1);
12525
417
    return parse_ipv6(input);
12526
689
  }
12527
12528
  // If isNotSpecial is true, then return the result of opaque-host parsing
12529
  // input.
12530
24.4k
  if (!is_special()) {
12531
273
    return parse_opaque_host(input);
12532
273
  }
12533
  // Let domain be the result of running UTF-8 decode without BOM on the
12534
  // percent-decoding of input. Let asciiDomain be the result of running domain
12535
  // to ASCII with domain and false. The most common case is an ASCII input, in
12536
  // which case we do not need to call the expensive 'to_ascii' if a few
12537
  // conditions are met: no '%' and no 'xn-' subsequence.
12538
24.1k
  std::string buffer = std::string(input);
12539
  // This next function checks that the result is ascii, but we are going to
12540
  // to check anyhow with is_forbidden.
12541
  // bool is_ascii =
12542
24.1k
  unicode::to_lower_ascii(buffer.data(), buffer.size());
12543
24.1k
  bool is_forbidden = unicode::contains_forbidden_domain_code_point(
12544
24.1k
      buffer.data(), buffer.size());
12545
24.1k
  if (is_forbidden == 0 && buffer.find("xn-") == std::string_view::npos) {
12546
    // fast path
12547
16.5k
    host = std::move(buffer);
12548
16.5k
    if (checkers::is_ipv4(host.value())) {
12549
1.97k
      ada_log("parse_host fast path ipv4");
12550
1.97k
      return parse_ipv4(host.value());
12551
1.97k
    }
12552
14.5k
    ada_log("parse_host fast path ", *host);
12553
14.5k
    return true;
12554
16.5k
  }
12555
7.61k
  ada_log("parse_host calling to_ascii");
12556
7.61k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
12557
7.61k
  if (!is_valid) {
12558
4.35k
    ada_log("parse_host to_ascii returns false");
12559
4.35k
    return is_valid = false;
12560
4.35k
  }
12561
3.25k
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
12562
3.25k
          " bytes]");
12563
12564
3.25k
  if (std::any_of(host.value().begin(), host.value().end(),
12565
3.25k
                  ada::unicode::is_forbidden_domain_code_point)) {
12566
0
    host = std::nullopt;
12567
0
    return is_valid = false;
12568
0
  }
12569
12570
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
12571
  // asciiDomain.
12572
3.25k
  if (checkers::is_ipv4(host.value())) {
12573
281
    ada_log("parse_host got ipv4 ", *host);
12574
281
    return parse_ipv4(host.value());
12575
281
  }
12576
12577
2.97k
  return true;
12578
3.25k
}
12579
12580
8.96k
ada_really_inline void url::parse_path(std::string_view input) {
12581
8.96k
  ada_log("parse_path ", input);
12582
8.96k
  std::string tmp_buffer;
12583
8.96k
  std::string_view internal_input;
12584
8.96k
  if (unicode::has_tabs_or_newline(input)) {
12585
156
    tmp_buffer = input;
12586
    // Optimization opportunity: Instead of copying and then pruning, we could
12587
    // just directly build the string from user_input.
12588
156
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12589
156
    internal_input = tmp_buffer;
12590
8.81k
  } else {
12591
8.81k
    internal_input = input;
12592
8.81k
  }
12593
12594
  // If url is special, then:
12595
8.96k
  if (is_special()) {
12596
8.96k
    if (internal_input.empty()) {
12597
29
      path = "/";
12598
8.93k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
12599
708
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
12600
8.23k
    } else {
12601
8.23k
      helpers::parse_prepared_path(internal_input, type, path);
12602
8.23k
    }
12603
8.96k
  } else if (!internal_input.empty()) {
12604
0
    if (internal_input[0] == '/') {
12605
0
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
12606
0
    } else {
12607
0
      helpers::parse_prepared_path(internal_input, type, path);
12608
0
    }
12609
0
  } else {
12610
0
    if (!host.has_value()) {
12611
0
      path = "/";
12612
0
    }
12613
0
  }
12614
8.96k
}
12615
12616
8.96k
[[nodiscard]] std::string url::to_string() const {
12617
8.96k
  if (!is_valid) {
12618
2.43k
    return "null";
12619
2.43k
  }
12620
6.53k
  std::string answer;
12621
6.53k
  auto back = std::back_insert_iterator(answer);
12622
6.53k
  answer.append("{\n");
12623
6.53k
  answer.append("\t\"protocol\":\"");
12624
6.53k
  helpers::encode_json(get_protocol(), back);
12625
6.53k
  answer.append("\",\n");
12626
6.53k
  if (has_credentials()) {
12627
6.52k
    answer.append("\t\"username\":\"");
12628
6.52k
    helpers::encode_json(username, back);
12629
6.52k
    answer.append("\",\n");
12630
6.52k
    answer.append("\t\"password\":\"");
12631
6.52k
    helpers::encode_json(password, back);
12632
6.52k
    answer.append("\",\n");
12633
6.52k
  }
12634
6.53k
  if (host.has_value()) {
12635
6.53k
    answer.append("\t\"host\":\"");
12636
6.53k
    helpers::encode_json(host.value(), back);
12637
6.53k
    answer.append("\",\n");
12638
6.53k
  }
12639
6.53k
  if (port.has_value()) {
12640
900
    answer.append("\t\"port\":\"");
12641
900
    answer.append(std::to_string(port.value()));
12642
900
    answer.append("\",\n");
12643
900
  }
12644
6.53k
  answer.append("\t\"path\":\"");
12645
6.53k
  helpers::encode_json(path, back);
12646
6.53k
  answer.append("\",\n");
12647
6.53k
  answer.append("\t\"opaque path\":");
12648
6.53k
  answer.append((has_opaque_path ? "true" : "false"));
12649
6.53k
  if (has_search()) {
12650
6.52k
    answer.append(",\n");
12651
6.52k
    answer.append("\t\"query\":\"");
12652
    // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
12653
6.52k
    helpers::encode_json(query.value(), back);
12654
6.52k
    answer.append("\"");
12655
6.52k
  }
12656
6.53k
  if (hash.has_value()) {
12657
6.52k
    answer.append(",\n");
12658
6.52k
    answer.append("\t\"hash\":\"");
12659
6.52k
    helpers::encode_json(hash.value(), back);
12660
6.52k
    answer.append("\"");
12661
6.52k
  }
12662
6.53k
  answer.append("\n}");
12663
6.53k
  return answer;
12664
8.96k
}
12665
12666
0
[[nodiscard]] bool url::has_valid_domain() const noexcept {
12667
0
  if (!host.has_value()) {
12668
0
    return false;
12669
0
  }
12670
0
  return checkers::verify_dns_length(host.value());
12671
0
}
12672
12673
12.1k
[[nodiscard]] std::string url::get_origin() const noexcept {
12674
12.1k
  if (is_special()) {
12675
    // Return a new opaque origin.
12676
10.7k
    if (type == scheme::FILE) {
12677
1.37k
      return "null";
12678
1.37k
    }
12679
9.38k
    return ada::helpers::concat(get_protocol(), "//", get_host());
12680
10.7k
  }
12681
12682
1.39k
  if (non_special_scheme == "blob") {
12683
493
    if (!path.empty()) {
12684
483
      auto result = ada::parse<ada::url>(path);
12685
483
      if (result &&
12686
224
          (result->type == scheme::HTTP || result->type == scheme::HTTPS)) {
12687
        // If pathURL's scheme is not "http" and not "https", then return a
12688
        // new opaque origin.
12689
19
        return ada::helpers::concat(result->get_protocol(), "//",
12690
19
                                    result->get_host());
12691
19
      }
12692
483
    }
12693
493
  }
12694
12695
  // Return a new opaque origin.
12696
1.38k
  return "null";
12697
1.39k
}
12698
12699
37.2k
[[nodiscard]] std::string url::get_protocol() const noexcept {
12700
37.2k
  if (is_special()) {
12701
31.6k
    return helpers::concat(ada::scheme::details::is_special_list[type], ":");
12702
31.6k
  }
12703
  // We only move the 'scheme' if it is non-special.
12704
5.59k
  return helpers::concat(non_special_scheme, ":");
12705
37.2k
}
12706
12707
18.3k
[[nodiscard]] std::string url::get_host() const noexcept {
12708
  // If url's host is null, then return the empty string.
12709
  // If url's port is null, return url's host, serialized.
12710
  // Return url's host, serialized, followed by U+003A (:) and url's port,
12711
  // serialized.
12712
18.3k
  if (!host.has_value()) {
12713
0
    return "";
12714
0
  }
12715
18.3k
  if (port.has_value()) {
12716
1.86k
    return host.value() + ":" + get_port();
12717
1.86k
  }
12718
16.5k
  return host.value();
12719
18.3k
}
12720
12721
8.96k
[[nodiscard]] std::string url::get_hostname() const noexcept {
12722
8.96k
  return host.value_or("");
12723
8.96k
}
12724
12725
8.96k
[[nodiscard]] std::string url::get_search() const noexcept {
12726
  // If this's URL's query is either null or the empty string, then return the
12727
  // empty string. Return U+003F (?), followed by this's URL's query.
12728
8.96k
  return (!query.has_value() || (query.value().empty())) ? ""
12729
8.96k
                                                         : "?" + query.value();
12730
8.96k
}
12731
12732
8.96k
[[nodiscard]] const std::string& url::get_username() const noexcept {
12733
8.96k
  return username;
12734
8.96k
}
12735
12736
9.35k
[[nodiscard]] const std::string& url::get_password() const noexcept {
12737
9.35k
  return password;
12738
9.35k
}
12739
12740
11.0k
[[nodiscard]] std::string url::get_port() const noexcept {
12741
11.0k
  return port.has_value() ? std::to_string(port.value()) : "";
12742
11.0k
}
12743
12744
8.96k
[[nodiscard]] std::string url::get_hash() const noexcept {
12745
  // If this's URL's fragment is either null or the empty string, then return
12746
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
12747
8.96k
  return (!hash.has_value() || (hash.value().empty())) ? ""
12748
8.96k
                                                       : "#" + hash.value();
12749
8.96k
}
12750
12751
template <bool override_hostname>
12752
17.9k
bool url::set_host_or_hostname(const std::string_view input) {
12753
17.9k
  if (has_opaque_path) {
12754
0
    return false;
12755
0
  }
12756
12757
17.9k
  std::optional<std::string> previous_host = host;
12758
17.9k
  std::optional<uint16_t> previous_port = port;
12759
12760
17.9k
  size_t host_end_pos = input.find('#');
12761
17.9k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
12762
17.9k
                                      ? host_end_pos
12763
17.9k
                                      : input.size());
12764
17.9k
  helpers::remove_ascii_tab_or_newline(_host);
12765
17.9k
  std::string_view new_host(_host);
12766
12767
  // If url's scheme is "file", then set state to file host state, instead of
12768
  // host state.
12769
17.9k
  if (type != ada::scheme::type::FILE) {
12770
16.4k
    std::string_view host_view(_host.data(), _host.length());
12771
16.4k
    auto [location, found_colon] =
12772
16.4k
        helpers::get_host_delimiter_location(is_special(), host_view);
12773
12774
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12775
    // Note: the 'found_colon' value is true if and only if a colon was
12776
    // encountered while not inside brackets.
12777
16.4k
    if (found_colon) {
12778
      // If buffer is the empty string, host-missing validation error, return
12779
      // failure.
12780
7.38k
      std::string_view buffer = host_view.substr(0, location);
12781
7.38k
      if (buffer.empty()) {
12782
32
        return false;
12783
32
      }
12784
12785
      // If state override is given and state override is hostname state, then
12786
      // return failure.
12787
7.35k
      if constexpr (override_hostname) {
12788
3.67k
        return false;
12789
3.67k
      }
12790
12791
      // Let host be the result of host parsing buffer with url is not special.
12792
0
      bool succeeded = parse_host(buffer);
12793
7.35k
      if (!succeeded) {
12794
381
        host = std::move(previous_host);
12795
381
        update_base_port(previous_port);
12796
381
        return false;
12797
381
      }
12798
12799
      // Set url's host to host, buffer to the empty string, and state to port
12800
      // state.
12801
6.97k
      std::string_view port_buffer = new_host.substr(location + 1);
12802
6.97k
      if (!port_buffer.empty()) {
12803
2.89k
        set_port(port_buffer);
12804
2.89k
      }
12805
6.97k
      return true;
12806
7.35k
    }
12807
    // Otherwise, if one of the following is true:
12808
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12809
    // - url is special and c is U+005C (\)
12810
9.08k
    else {
12811
      // If url is special and host_view is the empty string, host-missing
12812
      // validation error, return failure.
12813
9.08k
      if (host_view.empty() && is_special()) {
12814
1.57k
        return false;
12815
1.57k
      }
12816
12817
      // Otherwise, if state override is given, host_view is the empty string,
12818
      // and either url includes credentials or url's port is non-null, then
12819
      // return failure.
12820
7.51k
      if (host_view.empty() && (has_credentials() || port.has_value())) {
12821
0
        return false;
12822
0
      }
12823
12824
      // Let host be the result of host parsing host_view with url is not
12825
      // special.
12826
7.51k
      if (host_view.empty() && !is_special()) {
12827
0
        host = "";
12828
0
        return true;
12829
0
      }
12830
12831
7.51k
      bool succeeded = parse_host(host_view);
12832
7.51k
      if (!succeeded) {
12833
3.36k
        host = std::move(previous_host);
12834
3.36k
        update_base_port(previous_port);
12835
3.36k
        return false;
12836
3.36k
      }
12837
4.14k
      return true;
12838
7.51k
    }
12839
16.4k
  }
12840
12841
1.46k
  size_t location = new_host.find_first_of("/\\?");
12842
1.46k
  if (location != std::string_view::npos) {
12843
1.31k
    new_host.remove_suffix(new_host.length() - location);
12844
1.31k
  }
12845
12846
1.46k
  if (new_host.empty()) {
12847
    // Set url's host to the empty string.
12848
0
    host = "";
12849
1.46k
  } else {
12850
    // Let host be the result of host parsing buffer with url is not special.
12851
1.46k
    if (!parse_host(new_host)) {
12852
1.45k
      host = std::move(previous_host);
12853
1.45k
      update_base_port(previous_port);
12854
1.45k
      return false;
12855
1.45k
    }
12856
12857
    // If host is "localhost", then set host to the empty string.
12858
8
    if (host == "localhost") {
12859
0
      host = "";
12860
0
    }
12861
8
  }
12862
8
  return true;
12863
1.46k
}
bool ada::url::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
12752
8.96k
bool url::set_host_or_hostname(const std::string_view input) {
12753
8.96k
  if (has_opaque_path) {
12754
0
    return false;
12755
0
  }
12756
12757
8.96k
  std::optional<std::string> previous_host = host;
12758
8.96k
  std::optional<uint16_t> previous_port = port;
12759
12760
8.96k
  size_t host_end_pos = input.find('#');
12761
8.96k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
12762
8.96k
                                      ? host_end_pos
12763
8.96k
                                      : input.size());
12764
8.96k
  helpers::remove_ascii_tab_or_newline(_host);
12765
8.96k
  std::string_view new_host(_host);
12766
12767
  // If url's scheme is "file", then set state to file host state, instead of
12768
  // host state.
12769
8.96k
  if (type != ada::scheme::type::FILE) {
12770
8.23k
    std::string_view host_view(_host.data(), _host.length());
12771
8.23k
    auto [location, found_colon] =
12772
8.23k
        helpers::get_host_delimiter_location(is_special(), host_view);
12773
12774
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12775
    // Note: the 'found_colon' value is true if and only if a colon was
12776
    // encountered while not inside brackets.
12777
8.23k
    if (found_colon) {
12778
      // If buffer is the empty string, host-missing validation error, return
12779
      // failure.
12780
3.69k
      std::string_view buffer = host_view.substr(0, location);
12781
3.69k
      if (buffer.empty()) {
12782
16
        return false;
12783
16
      }
12784
12785
      // If state override is given and state override is hostname state, then
12786
      // return failure.
12787
      if constexpr (override_hostname) {
12788
        return false;
12789
      }
12790
12791
      // Let host be the result of host parsing buffer with url is not special.
12792
3.67k
      bool succeeded = parse_host(buffer);
12793
3.67k
      if (!succeeded) {
12794
381
        host = std::move(previous_host);
12795
381
        update_base_port(previous_port);
12796
381
        return false;
12797
381
      }
12798
12799
      // Set url's host to host, buffer to the empty string, and state to port
12800
      // state.
12801
3.29k
      std::string_view port_buffer = new_host.substr(location + 1);
12802
3.29k
      if (!port_buffer.empty()) {
12803
2.89k
        set_port(port_buffer);
12804
2.89k
      }
12805
3.29k
      return true;
12806
3.67k
    }
12807
    // Otherwise, if one of the following is true:
12808
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12809
    // - url is special and c is U+005C (\)
12810
4.54k
    else {
12811
      // If url is special and host_view is the empty string, host-missing
12812
      // validation error, return failure.
12813
4.54k
      if (host_view.empty() && is_special()) {
12814
786
        return false;
12815
786
      }
12816
12817
      // Otherwise, if state override is given, host_view is the empty string,
12818
      // and either url includes credentials or url's port is non-null, then
12819
      // return failure.
12820
3.75k
      if (host_view.empty() && (has_credentials() || port.has_value())) {
12821
0
        return false;
12822
0
      }
12823
12824
      // Let host be the result of host parsing host_view with url is not
12825
      // special.
12826
3.75k
      if (host_view.empty() && !is_special()) {
12827
0
        host = "";
12828
0
        return true;
12829
0
      }
12830
12831
3.75k
      bool succeeded = parse_host(host_view);
12832
3.75k
      if (!succeeded) {
12833
1.68k
        host = std::move(previous_host);
12834
1.68k
        update_base_port(previous_port);
12835
1.68k
        return false;
12836
1.68k
      }
12837
2.07k
      return true;
12838
3.75k
    }
12839
8.23k
  }
12840
12841
731
  size_t location = new_host.find_first_of("/\\?");
12842
731
  if (location != std::string_view::npos) {
12843
658
    new_host.remove_suffix(new_host.length() - location);
12844
658
  }
12845
12846
731
  if (new_host.empty()) {
12847
    // Set url's host to the empty string.
12848
0
    host = "";
12849
731
  } else {
12850
    // Let host be the result of host parsing buffer with url is not special.
12851
731
    if (!parse_host(new_host)) {
12852
727
      host = std::move(previous_host);
12853
727
      update_base_port(previous_port);
12854
727
      return false;
12855
727
    }
12856
12857
    // If host is "localhost", then set host to the empty string.
12858
4
    if (host == "localhost") {
12859
0
      host = "";
12860
0
    }
12861
4
  }
12862
4
  return true;
12863
731
}
bool ada::url::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
12752
8.96k
bool url::set_host_or_hostname(const std::string_view input) {
12753
8.96k
  if (has_opaque_path) {
12754
0
    return false;
12755
0
  }
12756
12757
8.96k
  std::optional<std::string> previous_host = host;
12758
8.96k
  std::optional<uint16_t> previous_port = port;
12759
12760
8.96k
  size_t host_end_pos = input.find('#');
12761
8.96k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
12762
8.96k
                                      ? host_end_pos
12763
8.96k
                                      : input.size());
12764
8.96k
  helpers::remove_ascii_tab_or_newline(_host);
12765
8.96k
  std::string_view new_host(_host);
12766
12767
  // If url's scheme is "file", then set state to file host state, instead of
12768
  // host state.
12769
8.96k
  if (type != ada::scheme::type::FILE) {
12770
8.23k
    std::string_view host_view(_host.data(), _host.length());
12771
8.23k
    auto [location, found_colon] =
12772
8.23k
        helpers::get_host_delimiter_location(is_special(), host_view);
12773
12774
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12775
    // Note: the 'found_colon' value is true if and only if a colon was
12776
    // encountered while not inside brackets.
12777
8.23k
    if (found_colon) {
12778
      // If buffer is the empty string, host-missing validation error, return
12779
      // failure.
12780
3.69k
      std::string_view buffer = host_view.substr(0, location);
12781
3.69k
      if (buffer.empty()) {
12782
16
        return false;
12783
16
      }
12784
12785
      // If state override is given and state override is hostname state, then
12786
      // return failure.
12787
3.67k
      if constexpr (override_hostname) {
12788
3.67k
        return false;
12789
3.67k
      }
12790
12791
      // Let host be the result of host parsing buffer with url is not special.
12792
0
      bool succeeded = parse_host(buffer);
12793
3.67k
      if (!succeeded) {
12794
0
        host = std::move(previous_host);
12795
0
        update_base_port(previous_port);
12796
0
        return false;
12797
0
      }
12798
12799
      // Set url's host to host, buffer to the empty string, and state to port
12800
      // state.
12801
3.67k
      std::string_view port_buffer = new_host.substr(location + 1);
12802
3.67k
      if (!port_buffer.empty()) {
12803
0
        set_port(port_buffer);
12804
0
      }
12805
3.67k
      return true;
12806
3.67k
    }
12807
    // Otherwise, if one of the following is true:
12808
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12809
    // - url is special and c is U+005C (\)
12810
4.54k
    else {
12811
      // If url is special and host_view is the empty string, host-missing
12812
      // validation error, return failure.
12813
4.54k
      if (host_view.empty() && is_special()) {
12814
786
        return false;
12815
786
      }
12816
12817
      // Otherwise, if state override is given, host_view is the empty string,
12818
      // and either url includes credentials or url's port is non-null, then
12819
      // return failure.
12820
3.75k
      if (host_view.empty() && (has_credentials() || port.has_value())) {
12821
0
        return false;
12822
0
      }
12823
12824
      // Let host be the result of host parsing host_view with url is not
12825
      // special.
12826
3.75k
      if (host_view.empty() && !is_special()) {
12827
0
        host = "";
12828
0
        return true;
12829
0
      }
12830
12831
3.75k
      bool succeeded = parse_host(host_view);
12832
3.75k
      if (!succeeded) {
12833
1.68k
        host = std::move(previous_host);
12834
1.68k
        update_base_port(previous_port);
12835
1.68k
        return false;
12836
1.68k
      }
12837
2.07k
      return true;
12838
3.75k
    }
12839
8.23k
  }
12840
12841
731
  size_t location = new_host.find_first_of("/\\?");
12842
731
  if (location != std::string_view::npos) {
12843
658
    new_host.remove_suffix(new_host.length() - location);
12844
658
  }
12845
12846
731
  if (new_host.empty()) {
12847
    // Set url's host to the empty string.
12848
0
    host = "";
12849
731
  } else {
12850
    // Let host be the result of host parsing buffer with url is not special.
12851
731
    if (!parse_host(new_host)) {
12852
727
      host = std::move(previous_host);
12853
727
      update_base_port(previous_port);
12854
727
      return false;
12855
727
    }
12856
12857
    // If host is "localhost", then set host to the empty string.
12858
4
    if (host == "localhost") {
12859
0
      host = "";
12860
0
    }
12861
4
  }
12862
4
  return true;
12863
731
}
12864
12865
8.96k
bool url::set_host(const std::string_view input) {
12866
8.96k
  return set_host_or_hostname<false>(input);
12867
8.96k
}
12868
12869
8.96k
bool url::set_hostname(const std::string_view input) {
12870
8.96k
  return set_host_or_hostname<true>(input);
12871
8.96k
}
12872
12873
8.96k
bool url::set_username(const std::string_view input) {
12874
8.96k
  if (cannot_have_credentials_or_port()) {
12875
731
    return false;
12876
731
  }
12877
8.23k
  username = ada::unicode::percent_encode(
12878
8.23k
      input, character_sets::USERINFO_PERCENT_ENCODE);
12879
8.23k
  return true;
12880
8.96k
}
12881
12882
8.96k
bool url::set_password(const std::string_view input) {
12883
8.96k
  if (cannot_have_credentials_or_port()) {
12884
731
    return false;
12885
731
  }
12886
8.23k
  password = ada::unicode::percent_encode(
12887
8.23k
      input, character_sets::USERINFO_PERCENT_ENCODE);
12888
8.23k
  return true;
12889
8.96k
}
12890
12891
11.8k
bool url::set_port(const std::string_view input) {
12892
11.8k
  if (cannot_have_credentials_or_port()) {
12893
731
    return false;
12894
731
  }
12895
12896
11.1k
  if (input.empty()) {
12897
3
    port = std::nullopt;
12898
3
    return true;
12899
3
  }
12900
12901
11.1k
  std::string trimmed(input);
12902
11.1k
  helpers::remove_ascii_tab_or_newline(trimmed);
12903
12904
11.1k
  if (trimmed.empty()) {
12905
26
    return true;
12906
26
  }
12907
12908
  // Input should not start with a non-digit character.
12909
11.0k
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
12910
9.62k
    return false;
12911
9.62k
  }
12912
12913
  // Find the first non-digit character to determine the length of digits
12914
1.47k
  auto first_non_digit =
12915
1.47k
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
12916
1.47k
  std::string_view digits_to_parse =
12917
1.47k
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
12918
12919
  // Revert changes if parse_port fails.
12920
1.47k
  std::optional<uint16_t> previous_port = port;
12921
1.47k
  parse_port(digits_to_parse);
12922
1.47k
  if (is_valid) {
12923
989
    return true;
12924
989
  }
12925
484
  port = std::move(previous_port);
12926
484
  is_valid = true;
12927
484
  return false;
12928
1.47k
}
12929
12930
8.96k
void url::set_hash(const std::string_view input) {
12931
8.96k
  if (input.empty()) {
12932
3
    hash = std::nullopt;
12933
3
    helpers::strip_trailing_spaces_from_opaque_path(*this);
12934
3
    return;
12935
3
  }
12936
12937
8.96k
  std::string new_value;
12938
8.96k
  new_value = input[0] == '#' ? input.substr(1) : input;
12939
8.96k
  helpers::remove_ascii_tab_or_newline(new_value);
12940
8.96k
  hash = unicode::percent_encode(new_value,
12941
8.96k
                                 ada::character_sets::FRAGMENT_PERCENT_ENCODE);
12942
8.96k
}
12943
12944
8.96k
void url::set_search(const std::string_view input) {
12945
8.96k
  if (input.empty()) {
12946
3
    query = std::nullopt;
12947
3
    helpers::strip_trailing_spaces_from_opaque_path(*this);
12948
3
    return;
12949
3
  }
12950
12951
8.96k
  std::string new_value;
12952
8.96k
  new_value = input[0] == '?' ? input.substr(1) : input;
12953
8.96k
  helpers::remove_ascii_tab_or_newline(new_value);
12954
12955
8.96k
  auto query_percent_encode_set =
12956
8.96k
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12957
8.96k
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
12958
12959
8.96k
  query = ada::unicode::percent_encode(new_value, query_percent_encode_set);
12960
8.96k
}
12961
12962
8.96k
bool url::set_pathname(const std::string_view input) {
12963
8.96k
  if (has_opaque_path) {
12964
0
    return false;
12965
0
  }
12966
8.96k
  path.clear();
12967
8.96k
  parse_path(input);
12968
8.96k
  return true;
12969
8.96k
}
12970
12971
8.96k
bool url::set_protocol(const std::string_view input) {
12972
8.96k
  std::string view(input);
12973
8.96k
  helpers::remove_ascii_tab_or_newline(view);
12974
8.96k
  if (view.empty()) {
12975
29
    return true;
12976
29
  }
12977
12978
  // Schemes should start with alpha values.
12979
8.93k
  if (!checkers::is_alpha(view[0])) {
12980
4.30k
    return false;
12981
4.30k
  }
12982
12983
4.63k
  view.append(":");
12984
12985
4.63k
  std::string::iterator pointer =
12986
4.63k
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
12987
12988
4.63k
  if (pointer != view.end() && *pointer == ':') {
12989
4.01k
    return parse_scheme<true>(
12990
4.01k
        std::string_view(view.data(), pointer - view.begin()));
12991
4.01k
  }
12992
618
  return false;
12993
4.63k
}
12994
12995
3.05k
bool url::set_href(const std::string_view input) {
12996
3.05k
  ada::result<ada::url> out = ada::parse<ada::url>(input);
12997
12998
3.05k
  if (out) {
12999
3.05k
    *this = *out;
13000
3.05k
  }
13001
13002
3.05k
  return out.has_value();
13003
3.05k
}
13004
13005
}  // namespace ada
13006
/* end file src/url.cpp */
13007
/* begin file src/parser.cpp */
13008
13009
#include <limits>
13010
#include <ranges>
13011
13012
13013
namespace ada::parser {
13014
13015
template <class result_type, bool store_values>
13016
result_type parse_url_impl(std::string_view user_input,
13017
42.9k
                           const result_type* base_url) {
13018
  // We can specialize the implementation per type.
13019
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
13020
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
13021
  // something else } is free (at runtime). This means that ada::url_aggregator
13022
  // and ada::url **do not have to support the exact same API**.
13023
42.9k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13024
42.9k
  constexpr bool result_type_is_ada_url_aggregator =
13025
42.9k
      std::is_same_v<url_aggregator, result_type>;
13026
42.9k
  static_assert(result_type_is_ada_url ||
13027
42.9k
                result_type_is_ada_url_aggregator);  // We don't support
13028
                                                     // anything else for now.
13029
13030
42.9k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13031
42.9k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13032
42.9k
          ")");
13033
13034
42.9k
  state state = state::SCHEME_START;
13035
42.9k
  result_type url{};
13036
13037
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
13038
  // surely the result of a bug or are otherwise a security concern.
13039
42.9k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) [[unlikely]] {
13040
0
    url.is_valid = false;
13041
0
  }
13042
  // Going forward, user_input.size() is in [0,
13043
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
13044
  // base, or the optional_url was invalid, we must return.
13045
42.9k
  if (base_url != nullptr) {
13046
0
    url.is_valid &= base_url->is_valid;
13047
0
  }
13048
42.9k
  if (!url.is_valid) {
13049
0
    return url;
13050
0
  }
13051
42.9k
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
13052
    // Most of the time, we just need user_input.size().
13053
    // In some instances, we may need a bit more.
13054
    ///////////////////////////
13055
    // This is *very* important. This line should *not* be removed
13056
    // hastily. There are principled reasons why reserve is important
13057
    // for performance. If you have a benchmark with small inputs,
13058
    // it may not matter, but in other instances, it could.
13059
    ////
13060
    // This rounds up to the next power of two.
13061
    // We know that user_input.size() is in [0,
13062
    // std::numeric_limits<uint32_t>::max).
13063
21.4k
    uint32_t reserve_capacity =
13064
21.4k
        (0xFFFFFFFF >>
13065
21.4k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13066
21.4k
        1;
13067
21.4k
    url.reserve(reserve_capacity);
13068
21.4k
  }
13069
42.9k
  std::string tmp_buffer;
13070
42.9k
  std::string_view url_data;
13071
42.9k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13072
384
    tmp_buffer = user_input;
13073
    // Optimization opportunity: Instead of copying and then pruning, we could
13074
    // just directly build the string from user_input.
13075
384
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13076
384
    url_data = tmp_buffer;
13077
42.5k
  } else [[likely]] {
13078
42.5k
    url_data = user_input;
13079
42.5k
  }
13080
13081
  // Leading and trailing control characters are uncommon and easy to deal with
13082
  // (no performance concern).
13083
42.9k
  helpers::trim_c0_whitespace(url_data);
13084
13085
  // Optimization opportunity. Most websites do not have fragment.
13086
42.9k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13087
  // We add it last so that an implementation like ada::url_aggregator
13088
  // can append it last to its internal buffer, thus improving performance.
13089
13090
  // Here url_data no longer has its fragment.
13091
  // We are going to access the data from url_data (it is immutable).
13092
  // At any given time, we are pointing at byte 'input_position' in url_data.
13093
  // The input_position variable should range from 0 to input_size.
13094
  // It is illegal to access url_data at input_size.
13095
42.9k
  size_t input_position = 0;
13096
42.9k
  const size_t input_size = url_data.size();
13097
  // Keep running the following state machine by switching on state.
13098
  // If after a run pointer points to the EOF code point, go to the next step.
13099
  // Otherwise, increase pointer by 1 and continue with the state machine.
13100
  // We never decrement input_position.
13101
209k
  while (input_position <= input_size) {
13102
201k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13103
201k
            " in state ", ada::to_string(state));
13104
201k
    switch (state) {
13105
42.9k
      case state::SCHEME_START: {
13106
42.9k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13107
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13108
        // state to scheme state.
13109
42.9k
        if ((input_position != input_size) &&
13110
42.7k
            checkers::is_alpha(url_data[input_position])) {
13111
34.3k
          state = state::SCHEME;
13112
34.3k
          input_position++;
13113
34.3k
        } else {
13114
          // Otherwise, if state override is not given, set state to no scheme
13115
          // state and decrease pointer by 1.
13116
8.61k
          state = state::NO_SCHEME;
13117
8.61k
        }
13118
42.9k
        break;
13119
0
      }
13120
34.3k
      case state::SCHEME: {
13121
34.3k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13122
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13123
        // append c, lowercased, to buffer.
13124
178k
        while ((input_position != input_size) &&
13125
177k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13126
144k
          input_position++;
13127
144k
        }
13128
        // Otherwise, if c is U+003A (:), then:
13129
34.3k
        if ((input_position != input_size) &&
13130
33.5k
            (url_data[input_position] == ':')) {
13131
32.2k
          ada_log("SCHEME the scheme should be ",
13132
32.2k
                  url_data.substr(0, input_position));
13133
32.2k
          if constexpr (result_type_is_ada_url) {
13134
16.1k
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13135
0
              return url;
13136
0
            }
13137
16.1k
          } else {
13138
            // we pass the colon along instead of painfully adding it back.
13139
16.1k
            if (!url.parse_scheme_with_colon(
13140
16.1k
                    url_data.substr(0, input_position + 1))) {
13141
0
              return url;
13142
0
            }
13143
16.1k
          }
13144
32.2k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13145
13146
          // If url's scheme is "file", then:
13147
32.2k
          if (url.type == scheme::type::FILE) {
13148
            // Set state to file state.
13149
2.90k
            state = state::FILE;
13150
2.90k
          }
13151
          // Otherwise, if url is special, base is non-null, and base's scheme
13152
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13153
          // != nullptr is false.
13154
29.3k
          else if (url.is_special() && base_url != nullptr &&
13155
0
                   base_url->type == url.type) {
13156
            // Set state to special relative or authority state.
13157
0
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13158
0
          }
13159
          // Otherwise, if url is special, set state to special authority
13160
          // slashes state.
13161
29.3k
          else if (url.is_special()) {
13162
23.3k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13163
23.3k
          }
13164
          // Otherwise, if remaining starts with an U+002F (/), set state to
13165
          // path or authority state and increase pointer by 1.
13166
6.06k
          else if (input_position + 1 < input_size &&
13167
5.37k
                   url_data[input_position + 1] == '/') {
13168
2.64k
            state = state::PATH_OR_AUTHORITY;
13169
2.64k
            input_position++;
13170
2.64k
          }
13171
          // Otherwise, set url's path to the empty string and set state to
13172
          // opaque path state.
13173
3.42k
          else {
13174
3.42k
            state = state::OPAQUE_PATH;
13175
3.42k
          }
13176
32.2k
        }
13177
        // Otherwise, if state override is not given, set buffer to the empty
13178
        // string, state to no scheme state, and start over (from the first code
13179
        // point in input).
13180
2.05k
        else {
13181
2.05k
          state = state::NO_SCHEME;
13182
2.05k
          input_position = 0;
13183
2.05k
          break;
13184
2.05k
        }
13185
32.2k
        input_position++;
13186
32.2k
        break;
13187
34.3k
      }
13188
10.6k
      case state::NO_SCHEME: {
13189
10.6k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13190
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13191
        // validation error, return failure.
13192
10.6k
        if (base_url == nullptr ||
13193
10.6k
            (base_url->has_opaque_path && !fragment.has_value())) {
13194
10.6k
          ada_log("NO_SCHEME validation error");
13195
10.6k
          url.is_valid = false;
13196
10.6k
          return url;
13197
10.6k
        }
13198
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13199
        // set url's scheme to base's scheme, url's path to base's path, url's
13200
        // query to base's query, and set state to fragment state.
13201
0
        else if (base_url->has_opaque_path && fragment.has_value() &&
13202
0
                 input_position == input_size) {
13203
0
          ada_log("NO_SCHEME opaque base with fragment");
13204
0
          url.copy_scheme(*base_url);
13205
0
          url.has_opaque_path = base_url->has_opaque_path;
13206
13207
0
          if constexpr (result_type_is_ada_url) {
13208
0
            url.path = base_url->path;
13209
0
            url.query = base_url->query;
13210
0
          } else {
13211
0
            url.update_base_pathname(base_url->get_pathname());
13212
0
            url.update_base_search(base_url->get_search());
13213
0
          }
13214
0
          url.update_unencoded_base_hash(*fragment);
13215
0
          return url;
13216
0
        }
13217
        // Otherwise, if base's scheme is not "file", set state to relative
13218
        // state and decrease pointer by 1.
13219
0
        else if (base_url->type != scheme::type::FILE) {
13220
0
          ada_log("NO_SCHEME non-file relative path");
13221
0
          state = state::RELATIVE_SCHEME;
13222
0
        }
13223
        // Otherwise, set state to file state and decrease pointer by 1.
13224
0
        else {
13225
0
          ada_log("NO_SCHEME file base type");
13226
0
          state = state::FILE;
13227
0
        }
13228
0
        break;
13229
10.6k
      }
13230
24.1k
      case state::AUTHORITY: {
13231
24.1k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13232
        // most URLs have no @. Having no @ tells us that we don't have to worry
13233
        // about AUTHORITY. Of course, we could have @ and still not have to
13234
        // worry about AUTHORITY.
13235
        // TODO: Instead of just collecting a bool, collect the location of the
13236
        // '@' and do something useful with it.
13237
        // TODO: We could do various processing early on, using a single pass
13238
        // over the string to collect information about it, e.g., telling us
13239
        // whether there is a @ and if so, where (or how many).
13240
13241
        // Check if url data contains an @.
13242
24.1k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13243
22.6k
          state = state::HOST;
13244
22.6k
          break;
13245
22.6k
        }
13246
1.52k
        bool at_sign_seen{false};
13247
1.52k
        bool password_token_seen{false};
13248
        /**
13249
         * We expect something of the sort...
13250
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13251
         * --------^
13252
         */
13253
17.9k
        do {
13254
17.9k
          std::string_view view = url_data.substr(input_position);
13255
          // The delimiters are @, /, ? \\.
13256
17.9k
          size_t location =
13257
17.9k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13258
17.9k
                               : helpers::find_authority_delimiter(view);
13259
17.9k
          std::string_view authority_view = view.substr(0, location);
13260
17.9k
          size_t end_of_authority = input_position + authority_view.size();
13261
          // If c is U+0040 (@), then:
13262
17.9k
          if ((end_of_authority != input_size) &&
13263
16.5k
              (url_data[end_of_authority] == '@')) {
13264
            // If atSignSeen is true, then prepend "%40" to buffer.
13265
16.4k
            if (at_sign_seen) {
13266
14.9k
              if (password_token_seen) {
13267
6.67k
                if constexpr (result_type_is_ada_url) {
13268
3.33k
                  url.password += "%40";
13269
3.33k
                } else {
13270
3.33k
                  url.append_base_password("%40");
13271
3.33k
                }
13272
8.26k
              } else {
13273
8.26k
                if constexpr (result_type_is_ada_url) {
13274
4.13k
                  url.username += "%40";
13275
4.13k
                } else {
13276
4.13k
                  url.append_base_username("%40");
13277
4.13k
                }
13278
8.26k
              }
13279
14.9k
            }
13280
13281
16.4k
            at_sign_seen = true;
13282
13283
16.4k
            if (!password_token_seen) {
13284
9.73k
              size_t password_token_location = authority_view.find(':');
13285
9.73k
              password_token_seen =
13286
9.73k
                  password_token_location != std::string_view::npos;
13287
13288
9.73k
              if constexpr (store_values) {
13289
9.73k
                if (!password_token_seen) {
13290
9.02k
                  if constexpr (result_type_is_ada_url) {
13291
4.51k
                    url.username += unicode::percent_encode(
13292
4.51k
                        authority_view,
13293
4.51k
                        character_sets::USERINFO_PERCENT_ENCODE);
13294
4.51k
                  } else {
13295
4.51k
                    url.append_base_username(unicode::percent_encode(
13296
4.51k
                        authority_view,
13297
4.51k
                        character_sets::USERINFO_PERCENT_ENCODE));
13298
4.51k
                  }
13299
9.02k
                } else {
13300
706
                  if constexpr (result_type_is_ada_url) {
13301
353
                    url.username += unicode::percent_encode(
13302
353
                        authority_view.substr(0, password_token_location),
13303
353
                        character_sets::USERINFO_PERCENT_ENCODE);
13304
353
                    url.password += unicode::percent_encode(
13305
353
                        authority_view.substr(password_token_location + 1),
13306
353
                        character_sets::USERINFO_PERCENT_ENCODE);
13307
353
                  } else {
13308
353
                    url.append_base_username(unicode::percent_encode(
13309
353
                        authority_view.substr(0, password_token_location),
13310
353
                        character_sets::USERINFO_PERCENT_ENCODE));
13311
353
                    url.append_base_password(unicode::percent_encode(
13312
353
                        authority_view.substr(password_token_location + 1),
13313
353
                        character_sets::USERINFO_PERCENT_ENCODE));
13314
353
                  }
13315
706
                }
13316
9.73k
              }
13317
9.73k
            } else if constexpr (store_values) {
13318
6.67k
              if constexpr (result_type_is_ada_url) {
13319
3.33k
                url.password += unicode::percent_encode(
13320
3.33k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13321
3.33k
              } else {
13322
3.33k
                url.append_base_password(unicode::percent_encode(
13323
3.33k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13324
3.33k
              }
13325
6.67k
            }
13326
16.4k
          }
13327
          // Otherwise, if one of the following is true:
13328
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13329
          // - url is special and c is U+005C (\)
13330
1.52k
          else if (end_of_authority == input_size ||
13331
158
                   url_data[end_of_authority] == '/' ||
13332
56
                   url_data[end_of_authority] == '?' ||
13333
1.52k
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13334
            // If atSignSeen is true and authority_view is the empty string,
13335
            // validation error, return failure.
13336
1.52k
            if (at_sign_seen && authority_view.empty()) {
13337
228
              url.is_valid = false;
13338
228
              return url;
13339
228
            }
13340
1.29k
            state = state::HOST;
13341
1.29k
            break;
13342
1.52k
          }
13343
16.4k
          if (end_of_authority == input_size) {
13344
0
            if constexpr (store_values) {
13345
0
              if (fragment.has_value()) {
13346
0
                url.update_unencoded_base_hash(*fragment);
13347
0
              }
13348
0
            }
13349
0
            return url;
13350
0
          }
13351
16.4k
          input_position = end_of_authority + 1;
13352
16.4k
        } while (true);
13353
13354
1.29k
        break;
13355
1.52k
      }
13356
1.29k
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
13357
0
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
13358
0
                helpers::substring(url_data, input_position));
13359
13360
        // If c is U+002F (/) and remaining starts with U+002F (/),
13361
        // then set state to special authority ignore slashes state and increase
13362
        // pointer by 1.
13363
0
        if (url_data.substr(input_position, 2) == "//") {
13364
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13365
0
          input_position += 2;
13366
0
        } else {
13367
          // Otherwise, validation error, set state to relative state and
13368
          // decrease pointer by 1.
13369
0
          state = state::RELATIVE_SCHEME;
13370
0
        }
13371
13372
0
        break;
13373
1.52k
      }
13374
2.64k
      case state::PATH_OR_AUTHORITY: {
13375
2.64k
        ada_log("PATH_OR_AUTHORITY ",
13376
2.64k
                helpers::substring(url_data, input_position));
13377
13378
        // If c is U+002F (/), then set state to authority state.
13379
2.64k
        if ((input_position != input_size) &&
13380
2.63k
            (url_data[input_position] == '/')) {
13381
832
          state = state::AUTHORITY;
13382
832
          input_position++;
13383
1.80k
        } else {
13384
          // Otherwise, set state to path state, and decrease pointer by 1.
13385
1.80k
          state = state::PATH;
13386
1.80k
        }
13387
13388
2.64k
        break;
13389
1.52k
      }
13390
0
      case state::RELATIVE_SCHEME: {
13391
0
        ada_log("RELATIVE_SCHEME ",
13392
0
                helpers::substring(url_data, input_position));
13393
13394
        // Set url's scheme to base's scheme.
13395
0
        url.copy_scheme(*base_url);
13396
13397
        // If c is U+002F (/), then set state to relative slash state.
13398
0
        if ((input_position != input_size) &&
13399
            // NOLINTNEXTLINE(bugprone-branch-clone)
13400
0
            (url_data[input_position] == '/')) {
13401
0
          ada_log(
13402
0
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
13403
0
              "slash state");
13404
0
          state = state::RELATIVE_SLASH;
13405
0
        } else if (url.is_special() && (input_position != input_size) &&
13406
0
                   (url_data[input_position] == '\\')) {
13407
          // Otherwise, if url is special and c is U+005C (\), validation error,
13408
          // set state to relative slash state.
13409
0
          ada_log(
13410
0
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
13411
0
              "error, set state to relative slash state");
13412
0
          state = state::RELATIVE_SLASH;
13413
0
        } else {
13414
0
          ada_log("RELATIVE_SCHEME otherwise");
13415
          // Set url's username to base's username, url's password to base's
13416
          // password, url's host to base's host, url's port to base's port,
13417
          // url's path to a clone of base's path, and url's query to base's
13418
          // query.
13419
0
          if constexpr (result_type_is_ada_url) {
13420
0
            url.username = base_url->username;
13421
0
            url.password = base_url->password;
13422
0
            url.host = base_url->host;
13423
0
            url.port = base_url->port;
13424
            // cloning the base path includes cloning the has_opaque_path flag
13425
0
            url.has_opaque_path = base_url->has_opaque_path;
13426
0
            url.path = base_url->path;
13427
0
            url.query = base_url->query;
13428
0
          } else {
13429
0
            url.update_base_authority(base_url->get_href(),
13430
0
                                      base_url->get_components());
13431
0
            url.update_host_to_base_host(base_url->get_hostname());
13432
0
            url.update_base_port(base_url->retrieve_base_port());
13433
            // cloning the base path includes cloning the has_opaque_path flag
13434
0
            url.has_opaque_path = base_url->has_opaque_path;
13435
0
            url.update_base_pathname(base_url->get_pathname());
13436
0
            url.update_base_search(base_url->get_search());
13437
0
          }
13438
13439
0
          url.has_opaque_path = base_url->has_opaque_path;
13440
13441
          // If c is U+003F (?), then set url's query to the empty string, and
13442
          // state to query state.
13443
0
          if ((input_position != input_size) &&
13444
0
              (url_data[input_position] == '?')) {
13445
0
            state = state::QUERY;
13446
0
          }
13447
          // Otherwise, if c is not the EOF code point:
13448
0
          else if (input_position != input_size) {
13449
            // Set url's query to null.
13450
0
            url.clear_search();
13451
0
            if constexpr (result_type_is_ada_url) {
13452
              // Shorten url's path.
13453
0
              helpers::shorten_path(url.path, url.type);
13454
0
            } else {
13455
0
              std::string_view path = url.get_pathname();
13456
0
              if (helpers::shorten_path(path, url.type)) {
13457
0
                url.update_base_pathname(std::move(std::string(path)));
13458
0
              }
13459
0
            }
13460
            // Set state to path state and decrease pointer by 1.
13461
0
            state = state::PATH;
13462
0
            break;
13463
0
          }
13464
0
        }
13465
0
        input_position++;
13466
0
        break;
13467
0
      }
13468
0
      case state::RELATIVE_SLASH: {
13469
0
        ada_log("RELATIVE_SLASH ",
13470
0
                helpers::substring(url_data, input_position));
13471
13472
        // If url is special and c is U+002F (/) or U+005C (\), then:
13473
0
        if (url.is_special() && (input_position != input_size) &&
13474
0
            (url_data[input_position] == '/' ||
13475
0
             url_data[input_position] == '\\')) {
13476
          // Set state to special authority ignore slashes state.
13477
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13478
0
        }
13479
        // Otherwise, if c is U+002F (/), then set state to authority state.
13480
0
        else if ((input_position != input_size) &&
13481
0
                 (url_data[input_position] == '/')) {
13482
0
          state = state::AUTHORITY;
13483
0
        }
13484
        // Otherwise, set
13485
        // - url's username to base's username,
13486
        // - url's password to base's password,
13487
        // - url's host to base's host,
13488
        // - url's port to base's port,
13489
        // - state to path state, and then, decrease pointer by 1.
13490
0
        else {
13491
0
          if constexpr (result_type_is_ada_url) {
13492
0
            url.username = base_url->username;
13493
0
            url.password = base_url->password;
13494
0
            url.host = base_url->host;
13495
0
            url.port = base_url->port;
13496
0
          } else {
13497
0
            url.update_base_authority(base_url->get_href(),
13498
0
                                      base_url->get_components());
13499
0
            url.update_host_to_base_host(base_url->get_hostname());
13500
0
            url.update_base_port(base_url->retrieve_base_port());
13501
0
          }
13502
0
          state = state::PATH;
13503
0
          break;
13504
0
        }
13505
13506
0
        input_position++;
13507
0
        break;
13508
0
      }
13509
23.3k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13510
23.3k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13511
23.3k
                helpers::substring(url_data, input_position));
13512
13513
        // If c is U+002F (/) and remaining starts with U+002F (/),
13514
        // then set state to special authority ignore slashes state and increase
13515
        // pointer by 1.
13516
23.3k
        if (url_data.substr(input_position, 2) == "//") {
13517
17.9k
          input_position += 2;
13518
17.9k
        }
13519
13520
23.3k
        [[fallthrough]];
13521
23.3k
      }
13522
23.3k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13523
23.3k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13524
23.3k
                helpers::substring(url_data, input_position));
13525
13526
        // If c is neither U+002F (/) nor U+005C (\), then set state to
13527
        // authority state and decrease pointer by 1.
13528
24.5k
        while ((input_position != input_size) &&
13529
24.5k
               ((url_data[input_position] == '/') ||
13530
23.6k
                (url_data[input_position] == '\\'))) {
13531
1.25k
          input_position++;
13532
1.25k
        }
13533
23.3k
        state = state::AUTHORITY;
13534
13535
23.3k
        break;
13536
23.3k
      }
13537
676
      case state::QUERY: {
13538
676
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13539
676
        if constexpr (store_values) {
13540
          // Let queryPercentEncodeSet be the special-query percent-encode set
13541
          // if url is special; otherwise the query percent-encode set.
13542
676
          const uint8_t* query_percent_encode_set =
13543
676
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13544
676
                               : character_sets::QUERY_PERCENT_ENCODE;
13545
13546
          // Percent-encode after encoding, with encoding, buffer, and
13547
          // queryPercentEncodeSet, and append the result to url's query.
13548
676
          url.update_base_search(url_data.substr(input_position),
13549
676
                                 query_percent_encode_set);
13550
676
          ada_log("QUERY update_base_search completed ");
13551
676
          if (fragment.has_value()) {
13552
45
            url.update_unencoded_base_hash(*fragment);
13553
45
          }
13554
676
        }
13555
676
        return url;
13556
23.3k
      }
13557
23.9k
      case state::HOST: {
13558
23.9k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13559
13560
23.9k
        std::string_view host_view = url_data.substr(input_position);
13561
23.9k
        auto [location, found_colon] =
13562
23.9k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13563
23.9k
        input_position = (location != std::string_view::npos)
13564
23.9k
                             ? input_position + location
13565
23.9k
                             : input_size;
13566
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13567
        // Note: the 'found_colon' value is true if and only if a colon was
13568
        // encountered while not inside brackets.
13569
23.9k
        if (found_colon) {
13570
          // If buffer is the empty string, validation error, return failure.
13571
          // Let host be the result of host parsing buffer with url is not
13572
          // special.
13573
1.36k
          ada_log("HOST parsing ", host_view);
13574
1.36k
          if (!url.parse_host(host_view)) {
13575
219
            return url;
13576
219
          }
13577
1.14k
          ada_log("HOST parsing results in ", url.get_hostname());
13578
          // Set url's host to host, buffer to the empty string, and state to
13579
          // port state.
13580
1.14k
          state = state::PORT;
13581
1.14k
          input_position++;
13582
1.14k
        }
13583
        // Otherwise, if one of the following is true:
13584
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13585
        // - url is special and c is U+005C (\)
13586
        // The get_host_delimiter_location function either brings us to
13587
        // the colon outside of the bracket, or to one of those characters.
13588
22.5k
        else {
13589
          // If url is special and host_view is the empty string, validation
13590
          // error, return failure.
13591
22.5k
          if (host_view.empty() && url.is_special()) {
13592
18
            url.is_valid = false;
13593
18
            return url;
13594
18
          }
13595
22.5k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
13596
          // Let host be the result of host parsing host_view with url is not
13597
          // special.
13598
22.5k
          if (host_view.empty()) {
13599
104
            url.update_base_hostname("");
13600
22.4k
          } else if (!url.parse_host(host_view)) {
13601
674
            return url;
13602
674
          }
13603
21.8k
          ada_log("HOST parsing results in ", url.get_hostname(),
13604
21.8k
                  " href=", url.get_href());
13605
13606
          // Set url's host to host, and state to path start state.
13607
21.8k
          state = state::PATH_START;
13608
21.8k
        }
13609
13610
23.0k
        break;
13611
23.9k
      }
13612
23.0k
      case state::OPAQUE_PATH: {
13613
3.42k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13614
3.42k
        std::string_view view = url_data.substr(input_position);
13615
        // If c is U+003F (?), then set url's query to the empty string and
13616
        // state to query state.
13617
3.42k
        size_t location = view.find('?');
13618
3.42k
        if (location != std::string_view::npos) {
13619
364
          view.remove_suffix(view.size() - location);
13620
364
          state = state::QUERY;
13621
364
          input_position += location + 1;
13622
3.05k
        } else {
13623
3.05k
          input_position = input_size + 1;
13624
3.05k
        }
13625
3.42k
        url.has_opaque_path = true;
13626
13627
        // This is a really unlikely scenario in real world. We should not seek
13628
        // to optimize it.
13629
3.42k
        if (view.ends_with(' ')) {
13630
120
          std::string modified_view =
13631
120
              std::string(view.substr(0, view.size() - 1)) + "%20";
13632
120
          url.update_base_pathname(unicode::percent_encode(
13633
120
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13634
3.30k
        } else {
13635
3.30k
          url.update_base_pathname(unicode::percent_encode(
13636
3.30k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13637
3.30k
        }
13638
3.42k
        break;
13639
23.9k
      }
13640
1.14k
      case state::PORT: {
13641
1.14k
        ada_log("PORT ", helpers::substring(url_data, input_position));
13642
1.14k
        std::string_view port_view = url_data.substr(input_position);
13643
1.14k
        input_position += url.parse_port(port_view, true);
13644
1.14k
        if (!url.is_valid) {
13645
175
          return url;
13646
175
        }
13647
972
        state = state::PATH_START;
13648
972
        [[fallthrough]];
13649
972
      }
13650
23.7k
      case state::PATH_START: {
13651
23.7k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13652
13653
        // If url is special, then:
13654
23.7k
        if (url.is_special()) {
13655
          // Set state to path state.
13656
23.2k
          state = state::PATH;
13657
13658
          // Optimization: Avoiding going into PATH state improves the
13659
          // performance of urls ending with /.
13660
23.2k
          if (input_position == input_size) {
13661
21.5k
            if constexpr (store_values) {
13662
21.5k
              url.update_base_pathname("/");
13663
21.5k
              if (fragment.has_value()) {
13664
138
                url.update_unencoded_base_hash(*fragment);
13665
138
              }
13666
21.5k
            }
13667
21.5k
            return url;
13668
21.5k
          }
13669
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
13670
          // by 1. We know that (input_position == input_size) is impossible
13671
          // here, because of the previous if-check.
13672
1.67k
          if ((url_data[input_position] != '/') &&
13673
188
              (url_data[input_position] != '\\')) {
13674
159
            break;
13675
159
          }
13676
1.67k
        }
13677
        // Otherwise, if state override is not given and c is U+003F (?),
13678
        // set url's query to the empty string and state to query state.
13679
564
        else if ((input_position != input_size) &&
13680
114
                 (url_data[input_position] == '?')) {
13681
20
          state = state::QUERY;
13682
20
        }
13683
        // Otherwise, if c is not the EOF code point:
13684
544
        else if (input_position != input_size) {
13685
          // Set state to path state.
13686
94
          state = state::PATH;
13687
13688
          // If c is not U+002F (/), then decrease pointer by 1.
13689
94
          if (url_data[input_position] != '/') {
13690
0
            break;
13691
0
          }
13692
94
        }
13693
13694
2.08k
        input_position++;
13695
2.08k
        break;
13696
23.7k
      }
13697
5.33k
      case state::PATH: {
13698
5.33k
        ada_log("PATH ", helpers::substring(url_data, input_position));
13699
5.33k
        std::string_view view = url_data.substr(input_position);
13700
13701
        // Most time, we do not need percent encoding.
13702
        // Furthermore, we can immediately locate the '?'.
13703
5.33k
        size_t locofquestionmark = view.find('?');
13704
5.33k
        if (locofquestionmark != std::string_view::npos) {
13705
292
          state = state::QUERY;
13706
292
          view.remove_suffix(view.size() - locofquestionmark);
13707
292
          input_position += locofquestionmark + 1;
13708
5.04k
        } else {
13709
5.04k
          input_position = input_size + 1;
13710
5.04k
        }
13711
5.33k
        if constexpr (store_values) {
13712
5.33k
          if constexpr (result_type_is_ada_url) {
13713
2.72k
            helpers::parse_prepared_path(view, url.type, url.path);
13714
2.72k
          } else {
13715
2.61k
            url.consume_prepared_path(view);
13716
2.61k
            ADA_ASSERT_TRUE(url.validate());
13717
2.61k
          }
13718
5.33k
        }
13719
5.33k
        break;
13720
23.7k
      }
13721
1.61k
      case state::FILE_SLASH: {
13722
1.61k
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13723
13724
        // If c is U+002F (/) or U+005C (\), then:
13725
1.61k
        if ((input_position != input_size) &&
13726
1.60k
            (url_data[input_position] == '/' ||
13727
1.15k
             url_data[input_position] == '\\')) {
13728
1.15k
          ada_log("FILE_SLASH c is U+002F or U+005C");
13729
          // Set state to file host state.
13730
1.15k
          state = state::FILE_HOST;
13731
1.15k
          input_position++;
13732
1.15k
        } else {
13733
456
          ada_log("FILE_SLASH otherwise");
13734
          // If base is non-null and base's scheme is "file", then:
13735
          // Note: it is unsafe to do base_url->scheme unless you know that
13736
          // base_url_has_value() is true.
13737
456
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13738
            // Set url's host to base's host.
13739
0
            if constexpr (result_type_is_ada_url) {
13740
0
              url.host = base_url->host;
13741
0
            } else {
13742
0
              url.update_host_to_base_host(base_url->get_host());
13743
0
            }
13744
            // If the code point substring from pointer to the end of input does
13745
            // not start with a Windows drive letter and base's path[0] is a
13746
            // normalized Windows drive letter, then append base's path[0] to
13747
            // url's path.
13748
0
            if (!base_url->get_pathname().empty()) {
13749
0
              if (!checkers::is_windows_drive_letter(
13750
0
                      url_data.substr(input_position))) {
13751
0
                std::string_view first_base_url_path =
13752
0
                    base_url->get_pathname().substr(1);
13753
0
                size_t loc = first_base_url_path.find('/');
13754
0
                if (loc != std::string_view::npos) {
13755
0
                  helpers::resize(first_base_url_path, loc);
13756
0
                }
13757
0
                if (checkers::is_normalized_windows_drive_letter(
13758
0
                        first_base_url_path)) {
13759
0
                  if constexpr (result_type_is_ada_url) {
13760
0
                    url.path += '/';
13761
0
                    url.path += first_base_url_path;
13762
0
                  } else {
13763
0
                    url.append_base_pathname(
13764
0
                        helpers::concat("/", first_base_url_path));
13765
0
                  }
13766
0
                }
13767
0
              }
13768
0
            }
13769
0
          }
13770
13771
          // Set state to path state, and decrease pointer by 1.
13772
456
          state = state::PATH;
13773
456
        }
13774
13775
1.61k
        break;
13776
23.7k
      }
13777
1.15k
      case state::FILE_HOST: {
13778
1.15k
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13779
1.15k
        std::string_view view = url_data.substr(input_position);
13780
13781
1.15k
        size_t location = view.find_first_of("/\\?");
13782
1.15k
        std::string_view file_host_buffer(
13783
1.15k
            view.data(),
13784
1.15k
            (location != std::string_view::npos) ? location : view.size());
13785
13786
1.15k
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13787
10
          state = state::PATH;
13788
1.14k
        } else if (file_host_buffer.empty()) {
13789
          // Set url's host to the empty string.
13790
52
          if constexpr (result_type_is_ada_url) {
13791
26
            url.host = "";
13792
26
          } else {
13793
26
            url.update_base_hostname("");
13794
26
          }
13795
          // Set state to path start state.
13796
52
          state = state::PATH_START;
13797
1.09k
        } else {
13798
1.09k
          size_t consumed_bytes = file_host_buffer.size();
13799
1.09k
          input_position += consumed_bytes;
13800
          // Let host be the result of host parsing buffer with url is not
13801
          // special.
13802
1.09k
          if (!url.parse_host(file_host_buffer)) {
13803
222
            return url;
13804
222
          }
13805
13806
874
          if constexpr (result_type_is_ada_url) {
13807
            // If host is "localhost", then set host to the empty string.
13808
445
            if (url.host.has_value() && url.host.value() == "localhost") {
13809
3
              url.host = "";
13810
3
            }
13811
445
          } else {
13812
429
            if (url.get_hostname() == "localhost") {
13813
3
              url.update_base_hostname("");
13814
3
            }
13815
429
          }
13816
13817
          // Set buffer to the empty string and state to path start state.
13818
874
          state = state::PATH_START;
13819
874
        }
13820
13821
936
        break;
13822
1.15k
      }
13823
2.90k
      case state::FILE: {
13824
2.90k
        ada_log("FILE ", helpers::substring(url_data, input_position));
13825
2.90k
        std::string_view file_view = url_data.substr(input_position);
13826
13827
2.90k
        url.set_protocol_as_file();
13828
2.90k
        if constexpr (result_type_is_ada_url) {
13829
          // Set url's host to the empty string.
13830
1.45k
          url.host = "";
13831
1.45k
        } else {
13832
1.45k
          url.update_base_hostname("");
13833
1.45k
        }
13834
        // If c is U+002F (/) or U+005C (\), then:
13835
2.90k
        if (input_position != input_size &&
13836
2.89k
            (url_data[input_position] == '/' ||
13837
1.61k
             url_data[input_position] == '\\')) {
13838
1.61k
          ada_log("FILE c is U+002F or U+005C");
13839
          // Set state to file slash state.
13840
1.61k
          state = state::FILE_SLASH;
13841
1.61k
        }
13842
        // Otherwise, if base is non-null and base's scheme is "file":
13843
1.29k
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13844
          // Set url's host to base's host, url's path to a clone of base's
13845
          // path, and url's query to base's query.
13846
0
          ada_log("FILE base non-null");
13847
0
          if constexpr (result_type_is_ada_url) {
13848
0
            url.host = base_url->host;
13849
0
            url.path = base_url->path;
13850
0
            url.query = base_url->query;
13851
0
          } else {
13852
0
            url.update_host_to_base_host(base_url->get_hostname());
13853
0
            url.update_base_pathname(base_url->get_pathname());
13854
0
            url.update_base_search(base_url->get_search());
13855
0
          }
13856
0
          url.has_opaque_path = base_url->has_opaque_path;
13857
13858
          // If c is U+003F (?), then set url's query to the empty string and
13859
          // state to query state.
13860
0
          if (input_position != input_size && url_data[input_position] == '?') {
13861
0
            state = state::QUERY;
13862
0
          }
13863
          // Otherwise, if c is not the EOF code point:
13864
0
          else if (input_position != input_size) {
13865
            // Set url's query to null.
13866
0
            url.clear_search();
13867
            // If the code point substring from pointer to the end of input does
13868
            // not start with a Windows drive letter, then shorten url's path.
13869
0
            if (!checkers::is_windows_drive_letter(file_view)) {
13870
0
              if constexpr (result_type_is_ada_url) {
13871
0
                helpers::shorten_path(url.path, url.type);
13872
0
              } else {
13873
0
                std::string_view path = url.get_pathname();
13874
0
                if (helpers::shorten_path(path, url.type)) {
13875
0
                  url.update_base_pathname(std::move(std::string(path)));
13876
0
                }
13877
0
              }
13878
0
            }
13879
            // Otherwise:
13880
0
            else {
13881
              // Set url's path to an empty list.
13882
0
              url.clear_pathname();
13883
0
              url.has_opaque_path = true;
13884
0
            }
13885
13886
            // Set state to path state and decrease pointer by 1.
13887
0
            state = state::PATH;
13888
0
            break;
13889
0
          }
13890
0
        }
13891
        // Otherwise, set state to path state, and decrease pointer by 1.
13892
1.29k
        else {
13893
1.29k
          ada_log("FILE go to path");
13894
1.29k
          state = state::PATH;
13895
1.29k
          break;
13896
1.29k
        }
13897
13898
1.61k
        input_position++;
13899
1.61k
        break;
13900
2.90k
      }
13901
0
      default:
13902
0
        unreachable();
13903
201k
    }
13904
201k
  }
13905
8.55k
  if constexpr (store_values) {
13906
8.55k
    if (fragment.has_value()) {
13907
285
      url.update_unencoded_base_hash(*fragment);
13908
285
    }
13909
8.55k
  }
13910
8.55k
  return url;
13911
42.9k
}
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
13017
21.4k
                           const result_type* base_url) {
13018
  // We can specialize the implementation per type.
13019
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
13020
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
13021
  // something else } is free (at runtime). This means that ada::url_aggregator
13022
  // and ada::url **do not have to support the exact same API**.
13023
21.4k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13024
21.4k
  constexpr bool result_type_is_ada_url_aggregator =
13025
21.4k
      std::is_same_v<url_aggregator, result_type>;
13026
21.4k
  static_assert(result_type_is_ada_url ||
13027
21.4k
                result_type_is_ada_url_aggregator);  // We don't support
13028
                                                     // anything else for now.
13029
13030
21.4k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13031
21.4k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13032
21.4k
          ")");
13033
13034
21.4k
  state state = state::SCHEME_START;
13035
21.4k
  result_type url{};
13036
13037
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
13038
  // surely the result of a bug or are otherwise a security concern.
13039
21.4k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) [[unlikely]] {
13040
0
    url.is_valid = false;
13041
0
  }
13042
  // Going forward, user_input.size() is in [0,
13043
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
13044
  // base, or the optional_url was invalid, we must return.
13045
21.4k
  if (base_url != nullptr) {
13046
0
    url.is_valid &= base_url->is_valid;
13047
0
  }
13048
21.4k
  if (!url.is_valid) {
13049
0
    return url;
13050
0
  }
13051
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
13052
    // Most of the time, we just need user_input.size().
13053
    // In some instances, we may need a bit more.
13054
    ///////////////////////////
13055
    // This is *very* important. This line should *not* be removed
13056
    // hastily. There are principled reasons why reserve is important
13057
    // for performance. If you have a benchmark with small inputs,
13058
    // it may not matter, but in other instances, it could.
13059
    ////
13060
    // This rounds up to the next power of two.
13061
    // We know that user_input.size() is in [0,
13062
    // std::numeric_limits<uint32_t>::max).
13063
    uint32_t reserve_capacity =
13064
        (0xFFFFFFFF >>
13065
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13066
        1;
13067
    url.reserve(reserve_capacity);
13068
  }
13069
21.4k
  std::string tmp_buffer;
13070
21.4k
  std::string_view url_data;
13071
21.4k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13072
192
    tmp_buffer = user_input;
13073
    // Optimization opportunity: Instead of copying and then pruning, we could
13074
    // just directly build the string from user_input.
13075
192
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13076
192
    url_data = tmp_buffer;
13077
21.2k
  } else [[likely]] {
13078
21.2k
    url_data = user_input;
13079
21.2k
  }
13080
13081
  // Leading and trailing control characters are uncommon and easy to deal with
13082
  // (no performance concern).
13083
21.4k
  helpers::trim_c0_whitespace(url_data);
13084
13085
  // Optimization opportunity. Most websites do not have fragment.
13086
21.4k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13087
  // We add it last so that an implementation like ada::url_aggregator
13088
  // can append it last to its internal buffer, thus improving performance.
13089
13090
  // Here url_data no longer has its fragment.
13091
  // We are going to access the data from url_data (it is immutable).
13092
  // At any given time, we are pointing at byte 'input_position' in url_data.
13093
  // The input_position variable should range from 0 to input_size.
13094
  // It is illegal to access url_data at input_size.
13095
21.4k
  size_t input_position = 0;
13096
21.4k
  const size_t input_size = url_data.size();
13097
  // Keep running the following state machine by switching on state.
13098
  // If after a run pointer points to the EOF code point, go to the next step.
13099
  // Otherwise, increase pointer by 1 and continue with the state machine.
13100
  // We never decrement input_position.
13101
104k
  while (input_position <= input_size) {
13102
100k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13103
100k
            " in state ", ada::to_string(state));
13104
100k
    switch (state) {
13105
21.4k
      case state::SCHEME_START: {
13106
21.4k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13107
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13108
        // state to scheme state.
13109
21.4k
        if ((input_position != input_size) &&
13110
21.3k
            checkers::is_alpha(url_data[input_position])) {
13111
17.1k
          state = state::SCHEME;
13112
17.1k
          input_position++;
13113
17.1k
        } else {
13114
          // Otherwise, if state override is not given, set state to no scheme
13115
          // state and decrease pointer by 1.
13116
4.30k
          state = state::NO_SCHEME;
13117
4.30k
        }
13118
21.4k
        break;
13119
0
      }
13120
17.1k
      case state::SCHEME: {
13121
17.1k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13122
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13123
        // append c, lowercased, to buffer.
13124
89.2k
        while ((input_position != input_size) &&
13125
88.8k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13126
72.0k
          input_position++;
13127
72.0k
        }
13128
        // Otherwise, if c is U+003A (:), then:
13129
17.1k
        if ((input_position != input_size) &&
13130
16.7k
            (url_data[input_position] == ':')) {
13131
16.1k
          ada_log("SCHEME the scheme should be ",
13132
16.1k
                  url_data.substr(0, input_position));
13133
16.1k
          if constexpr (result_type_is_ada_url) {
13134
16.1k
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13135
0
              return url;
13136
0
            }
13137
          } else {
13138
            // we pass the colon along instead of painfully adding it back.
13139
            if (!url.parse_scheme_with_colon(
13140
                    url_data.substr(0, input_position + 1))) {
13141
              return url;
13142
            }
13143
          }
13144
16.1k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13145
13146
          // If url's scheme is "file", then:
13147
16.1k
          if (url.type == scheme::type::FILE) {
13148
            // Set state to file state.
13149
1.45k
            state = state::FILE;
13150
1.45k
          }
13151
          // Otherwise, if url is special, base is non-null, and base's scheme
13152
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13153
          // != nullptr is false.
13154
14.6k
          else if (url.is_special() && base_url != nullptr &&
13155
0
                   base_url->type == url.type) {
13156
            // Set state to special relative or authority state.
13157
0
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13158
0
          }
13159
          // Otherwise, if url is special, set state to special authority
13160
          // slashes state.
13161
14.6k
          else if (url.is_special()) {
13162
11.6k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13163
11.6k
          }
13164
          // Otherwise, if remaining starts with an U+002F (/), set state to
13165
          // path or authority state and increase pointer by 1.
13166
3.03k
          else if (input_position + 1 < input_size &&
13167
2.68k
                   url_data[input_position + 1] == '/') {
13168
1.32k
            state = state::PATH_OR_AUTHORITY;
13169
1.32k
            input_position++;
13170
1.32k
          }
13171
          // Otherwise, set url's path to the empty string and set state to
13172
          // opaque path state.
13173
1.71k
          else {
13174
1.71k
            state = state::OPAQUE_PATH;
13175
1.71k
          }
13176
16.1k
        }
13177
        // Otherwise, if state override is not given, set buffer to the empty
13178
        // string, state to no scheme state, and start over (from the first code
13179
        // point in input).
13180
1.02k
        else {
13181
1.02k
          state = state::NO_SCHEME;
13182
1.02k
          input_position = 0;
13183
1.02k
          break;
13184
1.02k
        }
13185
16.1k
        input_position++;
13186
16.1k
        break;
13187
17.1k
      }
13188
5.33k
      case state::NO_SCHEME: {
13189
5.33k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13190
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13191
        // validation error, return failure.
13192
5.33k
        if (base_url == nullptr ||
13193
5.33k
            (base_url->has_opaque_path && !fragment.has_value())) {
13194
5.33k
          ada_log("NO_SCHEME validation error");
13195
5.33k
          url.is_valid = false;
13196
5.33k
          return url;
13197
5.33k
        }
13198
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13199
        // set url's scheme to base's scheme, url's path to base's path, url's
13200
        // query to base's query, and set state to fragment state.
13201
0
        else if (base_url->has_opaque_path && fragment.has_value() &&
13202
0
                 input_position == input_size) {
13203
0
          ada_log("NO_SCHEME opaque base with fragment");
13204
0
          url.copy_scheme(*base_url);
13205
0
          url.has_opaque_path = base_url->has_opaque_path;
13206
13207
0
          if constexpr (result_type_is_ada_url) {
13208
0
            url.path = base_url->path;
13209
0
            url.query = base_url->query;
13210
          } else {
13211
            url.update_base_pathname(base_url->get_pathname());
13212
            url.update_base_search(base_url->get_search());
13213
          }
13214
0
          url.update_unencoded_base_hash(*fragment);
13215
0
          return url;
13216
0
        }
13217
        // Otherwise, if base's scheme is not "file", set state to relative
13218
        // state and decrease pointer by 1.
13219
0
        else if (base_url->type != scheme::type::FILE) {
13220
0
          ada_log("NO_SCHEME non-file relative path");
13221
0
          state = state::RELATIVE_SCHEME;
13222
0
        }
13223
        // Otherwise, set state to file state and decrease pointer by 1.
13224
0
        else {
13225
0
          ada_log("NO_SCHEME file base type");
13226
0
          state = state::FILE;
13227
0
        }
13228
0
        break;
13229
5.33k
      }
13230
12.0k
      case state::AUTHORITY: {
13231
12.0k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13232
        // most URLs have no @. Having no @ tells us that we don't have to worry
13233
        // about AUTHORITY. Of course, we could have @ and still not have to
13234
        // worry about AUTHORITY.
13235
        // TODO: Instead of just collecting a bool, collect the location of the
13236
        // '@' and do something useful with it.
13237
        // TODO: We could do various processing early on, using a single pass
13238
        // over the string to collect information about it, e.g., telling us
13239
        // whether there is a @ and if so, where (or how many).
13240
13241
        // Check if url data contains an @.
13242
12.0k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13243
11.3k
          state = state::HOST;
13244
11.3k
          break;
13245
11.3k
        }
13246
760
        bool at_sign_seen{false};
13247
760
        bool password_token_seen{false};
13248
        /**
13249
         * We expect something of the sort...
13250
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13251
         * --------^
13252
         */
13253
8.96k
        do {
13254
8.96k
          std::string_view view = url_data.substr(input_position);
13255
          // The delimiters are @, /, ? \\.
13256
8.96k
          size_t location =
13257
8.96k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13258
8.96k
                               : helpers::find_authority_delimiter(view);
13259
8.96k
          std::string_view authority_view = view.substr(0, location);
13260
8.96k
          size_t end_of_authority = input_position + authority_view.size();
13261
          // If c is U+0040 (@), then:
13262
8.96k
          if ((end_of_authority != input_size) &&
13263
8.28k
              (url_data[end_of_authority] == '@')) {
13264
            // If atSignSeen is true, then prepend "%40" to buffer.
13265
8.20k
            if (at_sign_seen) {
13266
7.47k
              if (password_token_seen) {
13267
3.33k
                if constexpr (result_type_is_ada_url) {
13268
3.33k
                  url.password += "%40";
13269
                } else {
13270
                  url.append_base_password("%40");
13271
                }
13272
4.13k
              } else {
13273
4.13k
                if constexpr (result_type_is_ada_url) {
13274
4.13k
                  url.username += "%40";
13275
                } else {
13276
                  url.append_base_username("%40");
13277
                }
13278
4.13k
              }
13279
7.47k
            }
13280
13281
8.20k
            at_sign_seen = true;
13282
13283
8.20k
            if (!password_token_seen) {
13284
4.86k
              size_t password_token_location = authority_view.find(':');
13285
4.86k
              password_token_seen =
13286
4.86k
                  password_token_location != std::string_view::npos;
13287
13288
4.86k
              if constexpr (store_values) {
13289
4.86k
                if (!password_token_seen) {
13290
4.51k
                  if constexpr (result_type_is_ada_url) {
13291
4.51k
                    url.username += unicode::percent_encode(
13292
4.51k
                        authority_view,
13293
4.51k
                        character_sets::USERINFO_PERCENT_ENCODE);
13294
                  } else {
13295
                    url.append_base_username(unicode::percent_encode(
13296
                        authority_view,
13297
                        character_sets::USERINFO_PERCENT_ENCODE));
13298
                  }
13299
4.51k
                } else {
13300
353
                  if constexpr (result_type_is_ada_url) {
13301
353
                    url.username += unicode::percent_encode(
13302
353
                        authority_view.substr(0, password_token_location),
13303
353
                        character_sets::USERINFO_PERCENT_ENCODE);
13304
353
                    url.password += unicode::percent_encode(
13305
353
                        authority_view.substr(password_token_location + 1),
13306
353
                        character_sets::USERINFO_PERCENT_ENCODE);
13307
                  } else {
13308
                    url.append_base_username(unicode::percent_encode(
13309
                        authority_view.substr(0, password_token_location),
13310
                        character_sets::USERINFO_PERCENT_ENCODE));
13311
                    url.append_base_password(unicode::percent_encode(
13312
                        authority_view.substr(password_token_location + 1),
13313
                        character_sets::USERINFO_PERCENT_ENCODE));
13314
                  }
13315
353
                }
13316
4.86k
              }
13317
4.86k
            } else if constexpr (store_values) {
13318
3.33k
              if constexpr (result_type_is_ada_url) {
13319
3.33k
                url.password += unicode::percent_encode(
13320
3.33k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13321
              } else {
13322
                url.append_base_password(unicode::percent_encode(
13323
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13324
              }
13325
3.33k
            }
13326
8.20k
          }
13327
          // Otherwise, if one of the following is true:
13328
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13329
          // - url is special and c is U+005C (\)
13330
760
          else if (end_of_authority == input_size ||
13331
79
                   url_data[end_of_authority] == '/' ||
13332
28
                   url_data[end_of_authority] == '?' ||
13333
760
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13334
            // If atSignSeen is true and authority_view is the empty string,
13335
            // validation error, return failure.
13336
760
            if (at_sign_seen && authority_view.empty()) {
13337
114
              url.is_valid = false;
13338
114
              return url;
13339
114
            }
13340
646
            state = state::HOST;
13341
646
            break;
13342
760
          }
13343
8.20k
          if (end_of_authority == input_size) {
13344
0
            if constexpr (store_values) {
13345
0
              if (fragment.has_value()) {
13346
0
                url.update_unencoded_base_hash(*fragment);
13347
0
              }
13348
0
            }
13349
0
            return url;
13350
0
          }
13351
8.20k
          input_position = end_of_authority + 1;
13352
8.20k
        } while (true);
13353
13354
646
        break;
13355
760
      }
13356
646
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
13357
0
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
13358
0
                helpers::substring(url_data, input_position));
13359
13360
        // If c is U+002F (/) and remaining starts with U+002F (/),
13361
        // then set state to special authority ignore slashes state and increase
13362
        // pointer by 1.
13363
0
        if (url_data.substr(input_position, 2) == "//") {
13364
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13365
0
          input_position += 2;
13366
0
        } else {
13367
          // Otherwise, validation error, set state to relative state and
13368
          // decrease pointer by 1.
13369
0
          state = state::RELATIVE_SCHEME;
13370
0
        }
13371
13372
0
        break;
13373
760
      }
13374
1.32k
      case state::PATH_OR_AUTHORITY: {
13375
1.32k
        ada_log("PATH_OR_AUTHORITY ",
13376
1.32k
                helpers::substring(url_data, input_position));
13377
13378
        // If c is U+002F (/), then set state to authority state.
13379
1.32k
        if ((input_position != input_size) &&
13380
1.31k
            (url_data[input_position] == '/')) {
13381
416
          state = state::AUTHORITY;
13382
416
          input_position++;
13383
904
        } else {
13384
          // Otherwise, set state to path state, and decrease pointer by 1.
13385
904
          state = state::PATH;
13386
904
        }
13387
13388
1.32k
        break;
13389
760
      }
13390
0
      case state::RELATIVE_SCHEME: {
13391
0
        ada_log("RELATIVE_SCHEME ",
13392
0
                helpers::substring(url_data, input_position));
13393
13394
        // Set url's scheme to base's scheme.
13395
0
        url.copy_scheme(*base_url);
13396
13397
        // If c is U+002F (/), then set state to relative slash state.
13398
0
        if ((input_position != input_size) &&
13399
            // NOLINTNEXTLINE(bugprone-branch-clone)
13400
0
            (url_data[input_position] == '/')) {
13401
0
          ada_log(
13402
0
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
13403
0
              "slash state");
13404
0
          state = state::RELATIVE_SLASH;
13405
0
        } else if (url.is_special() && (input_position != input_size) &&
13406
0
                   (url_data[input_position] == '\\')) {
13407
          // Otherwise, if url is special and c is U+005C (\), validation error,
13408
          // set state to relative slash state.
13409
0
          ada_log(
13410
0
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
13411
0
              "error, set state to relative slash state");
13412
0
          state = state::RELATIVE_SLASH;
13413
0
        } else {
13414
0
          ada_log("RELATIVE_SCHEME otherwise");
13415
          // Set url's username to base's username, url's password to base's
13416
          // password, url's host to base's host, url's port to base's port,
13417
          // url's path to a clone of base's path, and url's query to base's
13418
          // query.
13419
0
          if constexpr (result_type_is_ada_url) {
13420
0
            url.username = base_url->username;
13421
0
            url.password = base_url->password;
13422
0
            url.host = base_url->host;
13423
0
            url.port = base_url->port;
13424
            // cloning the base path includes cloning the has_opaque_path flag
13425
0
            url.has_opaque_path = base_url->has_opaque_path;
13426
0
            url.path = base_url->path;
13427
0
            url.query = base_url->query;
13428
          } else {
13429
            url.update_base_authority(base_url->get_href(),
13430
                                      base_url->get_components());
13431
            url.update_host_to_base_host(base_url->get_hostname());
13432
            url.update_base_port(base_url->retrieve_base_port());
13433
            // cloning the base path includes cloning the has_opaque_path flag
13434
            url.has_opaque_path = base_url->has_opaque_path;
13435
            url.update_base_pathname(base_url->get_pathname());
13436
            url.update_base_search(base_url->get_search());
13437
          }
13438
13439
0
          url.has_opaque_path = base_url->has_opaque_path;
13440
13441
          // If c is U+003F (?), then set url's query to the empty string, and
13442
          // state to query state.
13443
0
          if ((input_position != input_size) &&
13444
0
              (url_data[input_position] == '?')) {
13445
0
            state = state::QUERY;
13446
0
          }
13447
          // Otherwise, if c is not the EOF code point:
13448
0
          else if (input_position != input_size) {
13449
            // Set url's query to null.
13450
0
            url.clear_search();
13451
0
            if constexpr (result_type_is_ada_url) {
13452
              // Shorten url's path.
13453
0
              helpers::shorten_path(url.path, url.type);
13454
            } else {
13455
              std::string_view path = url.get_pathname();
13456
              if (helpers::shorten_path(path, url.type)) {
13457
                url.update_base_pathname(std::move(std::string(path)));
13458
              }
13459
            }
13460
            // Set state to path state and decrease pointer by 1.
13461
0
            state = state::PATH;
13462
0
            break;
13463
0
          }
13464
0
        }
13465
0
        input_position++;
13466
0
        break;
13467
0
      }
13468
0
      case state::RELATIVE_SLASH: {
13469
0
        ada_log("RELATIVE_SLASH ",
13470
0
                helpers::substring(url_data, input_position));
13471
13472
        // If url is special and c is U+002F (/) or U+005C (\), then:
13473
0
        if (url.is_special() && (input_position != input_size) &&
13474
0
            (url_data[input_position] == '/' ||
13475
0
             url_data[input_position] == '\\')) {
13476
          // Set state to special authority ignore slashes state.
13477
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13478
0
        }
13479
        // Otherwise, if c is U+002F (/), then set state to authority state.
13480
0
        else if ((input_position != input_size) &&
13481
0
                 (url_data[input_position] == '/')) {
13482
0
          state = state::AUTHORITY;
13483
0
        }
13484
        // Otherwise, set
13485
        // - url's username to base's username,
13486
        // - url's password to base's password,
13487
        // - url's host to base's host,
13488
        // - url's port to base's port,
13489
        // - state to path state, and then, decrease pointer by 1.
13490
0
        else {
13491
0
          if constexpr (result_type_is_ada_url) {
13492
0
            url.username = base_url->username;
13493
0
            url.password = base_url->password;
13494
0
            url.host = base_url->host;
13495
0
            url.port = base_url->port;
13496
          } else {
13497
            url.update_base_authority(base_url->get_href(),
13498
                                      base_url->get_components());
13499
            url.update_host_to_base_host(base_url->get_hostname());
13500
            url.update_base_port(base_url->retrieve_base_port());
13501
          }
13502
0
          state = state::PATH;
13503
0
          break;
13504
0
        }
13505
13506
0
        input_position++;
13507
0
        break;
13508
0
      }
13509
11.6k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13510
11.6k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13511
11.6k
                helpers::substring(url_data, input_position));
13512
13513
        // If c is U+002F (/) and remaining starts with U+002F (/),
13514
        // then set state to special authority ignore slashes state and increase
13515
        // pointer by 1.
13516
11.6k
        if (url_data.substr(input_position, 2) == "//") {
13517
8.98k
          input_position += 2;
13518
8.98k
        }
13519
13520
11.6k
        [[fallthrough]];
13521
11.6k
      }
13522
11.6k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13523
11.6k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13524
11.6k
                helpers::substring(url_data, input_position));
13525
13526
        // If c is neither U+002F (/) nor U+005C (\), then set state to
13527
        // authority state and decrease pointer by 1.
13528
12.2k
        while ((input_position != input_size) &&
13529
12.2k
               ((url_data[input_position] == '/') ||
13530
11.8k
                (url_data[input_position] == '\\'))) {
13531
625
          input_position++;
13532
625
        }
13533
11.6k
        state = state::AUTHORITY;
13534
13535
11.6k
        break;
13536
11.6k
      }
13537
342
      case state::QUERY: {
13538
342
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13539
342
        if constexpr (store_values) {
13540
          // Let queryPercentEncodeSet be the special-query percent-encode set
13541
          // if url is special; otherwise the query percent-encode set.
13542
342
          const uint8_t* query_percent_encode_set =
13543
342
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13544
342
                               : character_sets::QUERY_PERCENT_ENCODE;
13545
13546
          // Percent-encode after encoding, with encoding, buffer, and
13547
          // queryPercentEncodeSet, and append the result to url's query.
13548
342
          url.update_base_search(url_data.substr(input_position),
13549
342
                                 query_percent_encode_set);
13550
342
          ada_log("QUERY update_base_search completed ");
13551
342
          if (fragment.has_value()) {
13552
23
            url.update_unencoded_base_hash(*fragment);
13553
23
          }
13554
342
        }
13555
342
        return url;
13556
11.6k
      }
13557
11.9k
      case state::HOST: {
13558
11.9k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13559
13560
11.9k
        std::string_view host_view = url_data.substr(input_position);
13561
11.9k
        auto [location, found_colon] =
13562
11.9k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13563
11.9k
        input_position = (location != std::string_view::npos)
13564
11.9k
                             ? input_position + location
13565
11.9k
                             : input_size;
13566
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13567
        // Note: the 'found_colon' value is true if and only if a colon was
13568
        // encountered while not inside brackets.
13569
11.9k
        if (found_colon) {
13570
          // If buffer is the empty string, validation error, return failure.
13571
          // Let host be the result of host parsing buffer with url is not
13572
          // special.
13573
683
          ada_log("HOST parsing ", host_view);
13574
683
          if (!url.parse_host(host_view)) {
13575
101
            return url;
13576
101
          }
13577
582
          ada_log("HOST parsing results in ", url.get_hostname());
13578
          // Set url's host to host, buffer to the empty string, and state to
13579
          // port state.
13580
582
          state = state::PORT;
13581
582
          input_position++;
13582
582
        }
13583
        // Otherwise, if one of the following is true:
13584
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13585
        // - url is special and c is U+005C (\)
13586
        // The get_host_delimiter_location function either brings us to
13587
        // the colon outside of the bracket, or to one of those characters.
13588
11.2k
        else {
13589
          // If url is special and host_view is the empty string, validation
13590
          // error, return failure.
13591
11.2k
          if (host_view.empty() && url.is_special()) {
13592
9
            url.is_valid = false;
13593
9
            return url;
13594
9
          }
13595
11.2k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
13596
          // Let host be the result of host parsing host_view with url is not
13597
          // special.
13598
11.2k
          if (host_view.empty()) {
13599
52
            url.update_base_hostname("");
13600
11.2k
          } else if (!url.parse_host(host_view)) {
13601
281
            return url;
13602
281
          }
13603
10.9k
          ada_log("HOST parsing results in ", url.get_hostname(),
13604
10.9k
                  " href=", url.get_href());
13605
13606
          // Set url's host to host, and state to path start state.
13607
10.9k
          state = state::PATH_START;
13608
10.9k
        }
13609
13610
11.5k
        break;
13611
11.9k
      }
13612
11.5k
      case state::OPAQUE_PATH: {
13613
1.71k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13614
1.71k
        std::string_view view = url_data.substr(input_position);
13615
        // If c is U+003F (?), then set url's query to the empty string and
13616
        // state to query state.
13617
1.71k
        size_t location = view.find('?');
13618
1.71k
        if (location != std::string_view::npos) {
13619
182
          view.remove_suffix(view.size() - location);
13620
182
          state = state::QUERY;
13621
182
          input_position += location + 1;
13622
1.52k
        } else {
13623
1.52k
          input_position = input_size + 1;
13624
1.52k
        }
13625
1.71k
        url.has_opaque_path = true;
13626
13627
        // This is a really unlikely scenario in real world. We should not seek
13628
        // to optimize it.
13629
1.71k
        if (view.ends_with(' ')) {
13630
60
          std::string modified_view =
13631
60
              std::string(view.substr(0, view.size() - 1)) + "%20";
13632
60
          url.update_base_pathname(unicode::percent_encode(
13633
60
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13634
1.65k
        } else {
13635
1.65k
          url.update_base_pathname(unicode::percent_encode(
13636
1.65k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13637
1.65k
        }
13638
1.71k
        break;
13639
11.9k
      }
13640
582
      case state::PORT: {
13641
582
        ada_log("PORT ", helpers::substring(url_data, input_position));
13642
582
        std::string_view port_view = url_data.substr(input_position);
13643
582
        input_position += url.parse_port(port_view, true);
13644
582
        if (!url.is_valid) {
13645
90
          return url;
13646
90
        }
13647
492
        state = state::PATH_START;
13648
492
        [[fallthrough]];
13649
492
      }
13650
11.9k
      case state::PATH_START: {
13651
11.9k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13652
13653
        // If url is special, then:
13654
11.9k
        if (url.is_special()) {
13655
          // Set state to path state.
13656
11.6k
          state = state::PATH;
13657
13658
          // Optimization: Avoiding going into PATH state improves the
13659
          // performance of urls ending with /.
13660
11.6k
          if (input_position == input_size) {
13661
10.7k
            if constexpr (store_values) {
13662
10.7k
              url.update_base_pathname("/");
13663
10.7k
              if (fragment.has_value()) {
13664
70
                url.update_unencoded_base_hash(*fragment);
13665
70
              }
13666
10.7k
            }
13667
10.7k
            return url;
13668
10.7k
          }
13669
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
13670
          // by 1. We know that (input_position == input_size) is impossible
13671
          // here, because of the previous if-check.
13672
897
          if ((url_data[input_position] != '/') &&
13673
98
              (url_data[input_position] != '\\')) {
13674
83
            break;
13675
83
          }
13676
897
        }
13677
        // Otherwise, if state override is not given and c is U+003F (?),
13678
        // set url's query to the empty string and state to query state.
13679
282
        else if ((input_position != input_size) &&
13680
57
                 (url_data[input_position] == '?')) {
13681
10
          state = state::QUERY;
13682
10
        }
13683
        // Otherwise, if c is not the EOF code point:
13684
272
        else if (input_position != input_size) {
13685
          // Set state to path state.
13686
47
          state = state::PATH;
13687
13688
          // If c is not U+002F (/), then decrease pointer by 1.
13689
47
          if (url_data[input_position] != '/') {
13690
0
            break;
13691
0
          }
13692
47
        }
13693
13694
1.09k
        input_position++;
13695
1.09k
        break;
13696
11.9k
      }
13697
2.72k
      case state::PATH: {
13698
2.72k
        ada_log("PATH ", helpers::substring(url_data, input_position));
13699
2.72k
        std::string_view view = url_data.substr(input_position);
13700
13701
        // Most time, we do not need percent encoding.
13702
        // Furthermore, we can immediately locate the '?'.
13703
2.72k
        size_t locofquestionmark = view.find('?');
13704
2.72k
        if (locofquestionmark != std::string_view::npos) {
13705
150
          state = state::QUERY;
13706
150
          view.remove_suffix(view.size() - locofquestionmark);
13707
150
          input_position += locofquestionmark + 1;
13708
2.57k
        } else {
13709
2.57k
          input_position = input_size + 1;
13710
2.57k
        }
13711
2.72k
        if constexpr (store_values) {
13712
2.72k
          if constexpr (result_type_is_ada_url) {
13713
2.72k
            helpers::parse_prepared_path(view, url.type, url.path);
13714
          } else {
13715
            url.consume_prepared_path(view);
13716
            ADA_ASSERT_TRUE(url.validate());
13717
          }
13718
2.72k
        }
13719
2.72k
        break;
13720
11.9k
      }
13721
807
      case state::FILE_SLASH: {
13722
807
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13723
13724
        // If c is U+002F (/) or U+005C (\), then:
13725
807
        if ((input_position != input_size) &&
13726
802
            (url_data[input_position] == '/' ||
13727
579
             url_data[input_position] == '\\')) {
13728
579
          ada_log("FILE_SLASH c is U+002F or U+005C");
13729
          // Set state to file host state.
13730
579
          state = state::FILE_HOST;
13731
579
          input_position++;
13732
579
        } else {
13733
228
          ada_log("FILE_SLASH otherwise");
13734
          // If base is non-null and base's scheme is "file", then:
13735
          // Note: it is unsafe to do base_url->scheme unless you know that
13736
          // base_url_has_value() is true.
13737
228
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13738
            // Set url's host to base's host.
13739
0
            if constexpr (result_type_is_ada_url) {
13740
0
              url.host = base_url->host;
13741
            } else {
13742
              url.update_host_to_base_host(base_url->get_host());
13743
            }
13744
            // If the code point substring from pointer to the end of input does
13745
            // not start with a Windows drive letter and base's path[0] is a
13746
            // normalized Windows drive letter, then append base's path[0] to
13747
            // url's path.
13748
0
            if (!base_url->get_pathname().empty()) {
13749
0
              if (!checkers::is_windows_drive_letter(
13750
0
                      url_data.substr(input_position))) {
13751
0
                std::string_view first_base_url_path =
13752
0
                    base_url->get_pathname().substr(1);
13753
0
                size_t loc = first_base_url_path.find('/');
13754
0
                if (loc != std::string_view::npos) {
13755
0
                  helpers::resize(first_base_url_path, loc);
13756
0
                }
13757
0
                if (checkers::is_normalized_windows_drive_letter(
13758
0
                        first_base_url_path)) {
13759
0
                  if constexpr (result_type_is_ada_url) {
13760
0
                    url.path += '/';
13761
0
                    url.path += first_base_url_path;
13762
                  } else {
13763
                    url.append_base_pathname(
13764
                        helpers::concat("/", first_base_url_path));
13765
                  }
13766
0
                }
13767
0
              }
13768
0
            }
13769
0
          }
13770
13771
          // Set state to path state, and decrease pointer by 1.
13772
228
          state = state::PATH;
13773
228
        }
13774
13775
807
        break;
13776
11.9k
      }
13777
579
      case state::FILE_HOST: {
13778
579
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13779
579
        std::string_view view = url_data.substr(input_position);
13780
13781
579
        size_t location = view.find_first_of("/\\?");
13782
579
        std::string_view file_host_buffer(
13783
579
            view.data(),
13784
579
            (location != std::string_view::npos) ? location : view.size());
13785
13786
579
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13787
5
          state = state::PATH;
13788
574
        } else if (file_host_buffer.empty()) {
13789
          // Set url's host to the empty string.
13790
26
          if constexpr (result_type_is_ada_url) {
13791
26
            url.host = "";
13792
          } else {
13793
            url.update_base_hostname("");
13794
          }
13795
          // Set state to path start state.
13796
26
          state = state::PATH_START;
13797
548
        } else {
13798
548
          size_t consumed_bytes = file_host_buffer.size();
13799
548
          input_position += consumed_bytes;
13800
          // Let host be the result of host parsing buffer with url is not
13801
          // special.
13802
548
          if (!url.parse_host(file_host_buffer)) {
13803
103
            return url;
13804
103
          }
13805
13806
445
          if constexpr (result_type_is_ada_url) {
13807
            // If host is "localhost", then set host to the empty string.
13808
445
            if (url.host.has_value() && url.host.value() == "localhost") {
13809
3
              url.host = "";
13810
3
            }
13811
          } else {
13812
            if (url.get_hostname() == "localhost") {
13813
              url.update_base_hostname("");
13814
            }
13815
          }
13816
13817
          // Set buffer to the empty string and state to path start state.
13818
445
          state = state::PATH_START;
13819
445
        }
13820
13821
476
        break;
13822
579
      }
13823
1.45k
      case state::FILE: {
13824
1.45k
        ada_log("FILE ", helpers::substring(url_data, input_position));
13825
1.45k
        std::string_view file_view = url_data.substr(input_position);
13826
13827
1.45k
        url.set_protocol_as_file();
13828
1.45k
        if constexpr (result_type_is_ada_url) {
13829
          // Set url's host to the empty string.
13830
1.45k
          url.host = "";
13831
        } else {
13832
          url.update_base_hostname("");
13833
        }
13834
        // If c is U+002F (/) or U+005C (\), then:
13835
1.45k
        if (input_position != input_size &&
13836
1.44k
            (url_data[input_position] == '/' ||
13837
807
             url_data[input_position] == '\\')) {
13838
807
          ada_log("FILE c is U+002F or U+005C");
13839
          // Set state to file slash state.
13840
807
          state = state::FILE_SLASH;
13841
807
        }
13842
        // Otherwise, if base is non-null and base's scheme is "file":
13843
646
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13844
          // Set url's host to base's host, url's path to a clone of base's
13845
          // path, and url's query to base's query.
13846
0
          ada_log("FILE base non-null");
13847
0
          if constexpr (result_type_is_ada_url) {
13848
0
            url.host = base_url->host;
13849
0
            url.path = base_url->path;
13850
0
            url.query = base_url->query;
13851
          } else {
13852
            url.update_host_to_base_host(base_url->get_hostname());
13853
            url.update_base_pathname(base_url->get_pathname());
13854
            url.update_base_search(base_url->get_search());
13855
          }
13856
0
          url.has_opaque_path = base_url->has_opaque_path;
13857
13858
          // If c is U+003F (?), then set url's query to the empty string and
13859
          // state to query state.
13860
0
          if (input_position != input_size && url_data[input_position] == '?') {
13861
0
            state = state::QUERY;
13862
0
          }
13863
          // Otherwise, if c is not the EOF code point:
13864
0
          else if (input_position != input_size) {
13865
            // Set url's query to null.
13866
0
            url.clear_search();
13867
            // If the code point substring from pointer to the end of input does
13868
            // not start with a Windows drive letter, then shorten url's path.
13869
0
            if (!checkers::is_windows_drive_letter(file_view)) {
13870
0
              if constexpr (result_type_is_ada_url) {
13871
0
                helpers::shorten_path(url.path, url.type);
13872
              } else {
13873
                std::string_view path = url.get_pathname();
13874
                if (helpers::shorten_path(path, url.type)) {
13875
                  url.update_base_pathname(std::move(std::string(path)));
13876
                }
13877
              }
13878
0
            }
13879
            // Otherwise:
13880
0
            else {
13881
              // Set url's path to an empty list.
13882
0
              url.clear_pathname();
13883
0
              url.has_opaque_path = true;
13884
0
            }
13885
13886
            // Set state to path state and decrease pointer by 1.
13887
0
            state = state::PATH;
13888
0
            break;
13889
0
          }
13890
0
        }
13891
        // Otherwise, set state to path state, and decrease pointer by 1.
13892
646
        else {
13893
646
          ada_log("FILE go to path");
13894
646
          state = state::PATH;
13895
646
          break;
13896
646
        }
13897
13898
807
        input_position++;
13899
807
        break;
13900
1.45k
      }
13901
0
      default:
13902
0
        unreachable();
13903
100k
    }
13904
100k
  }
13905
4.33k
  if constexpr (store_values) {
13906
4.33k
    if (fragment.has_value()) {
13907
143
      url.update_unencoded_base_hash(*fragment);
13908
143
    }
13909
4.33k
  }
13910
4.33k
  return url;
13911
21.4k
}
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
13017
21.4k
                           const result_type* base_url) {
13018
  // We can specialize the implementation per type.
13019
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
13020
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
13021
  // something else } is free (at runtime). This means that ada::url_aggregator
13022
  // and ada::url **do not have to support the exact same API**.
13023
21.4k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13024
21.4k
  constexpr bool result_type_is_ada_url_aggregator =
13025
21.4k
      std::is_same_v<url_aggregator, result_type>;
13026
21.4k
  static_assert(result_type_is_ada_url ||
13027
21.4k
                result_type_is_ada_url_aggregator);  // We don't support
13028
                                                     // anything else for now.
13029
13030
21.4k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13031
21.4k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13032
21.4k
          ")");
13033
13034
21.4k
  state state = state::SCHEME_START;
13035
21.4k
  result_type url{};
13036
13037
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
13038
  // surely the result of a bug or are otherwise a security concern.
13039
21.4k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) [[unlikely]] {
13040
0
    url.is_valid = false;
13041
0
  }
13042
  // Going forward, user_input.size() is in [0,
13043
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
13044
  // base, or the optional_url was invalid, we must return.
13045
21.4k
  if (base_url != nullptr) {
13046
0
    url.is_valid &= base_url->is_valid;
13047
0
  }
13048
21.4k
  if (!url.is_valid) {
13049
0
    return url;
13050
0
  }
13051
21.4k
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
13052
    // Most of the time, we just need user_input.size().
13053
    // In some instances, we may need a bit more.
13054
    ///////////////////////////
13055
    // This is *very* important. This line should *not* be removed
13056
    // hastily. There are principled reasons why reserve is important
13057
    // for performance. If you have a benchmark with small inputs,
13058
    // it may not matter, but in other instances, it could.
13059
    ////
13060
    // This rounds up to the next power of two.
13061
    // We know that user_input.size() is in [0,
13062
    // std::numeric_limits<uint32_t>::max).
13063
21.4k
    uint32_t reserve_capacity =
13064
21.4k
        (0xFFFFFFFF >>
13065
21.4k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13066
21.4k
        1;
13067
21.4k
    url.reserve(reserve_capacity);
13068
21.4k
  }
13069
21.4k
  std::string tmp_buffer;
13070
21.4k
  std::string_view url_data;
13071
21.4k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13072
192
    tmp_buffer = user_input;
13073
    // Optimization opportunity: Instead of copying and then pruning, we could
13074
    // just directly build the string from user_input.
13075
192
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13076
192
    url_data = tmp_buffer;
13077
21.2k
  } else [[likely]] {
13078
21.2k
    url_data = user_input;
13079
21.2k
  }
13080
13081
  // Leading and trailing control characters are uncommon and easy to deal with
13082
  // (no performance concern).
13083
21.4k
  helpers::trim_c0_whitespace(url_data);
13084
13085
  // Optimization opportunity. Most websites do not have fragment.
13086
21.4k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13087
  // We add it last so that an implementation like ada::url_aggregator
13088
  // can append it last to its internal buffer, thus improving performance.
13089
13090
  // Here url_data no longer has its fragment.
13091
  // We are going to access the data from url_data (it is immutable).
13092
  // At any given time, we are pointing at byte 'input_position' in url_data.
13093
  // The input_position variable should range from 0 to input_size.
13094
  // It is illegal to access url_data at input_size.
13095
21.4k
  size_t input_position = 0;
13096
21.4k
  const size_t input_size = url_data.size();
13097
  // Keep running the following state machine by switching on state.
13098
  // If after a run pointer points to the EOF code point, go to the next step.
13099
  // Otherwise, increase pointer by 1 and continue with the state machine.
13100
  // We never decrement input_position.
13101
104k
  while (input_position <= input_size) {
13102
100k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13103
100k
            " in state ", ada::to_string(state));
13104
100k
    switch (state) {
13105
21.4k
      case state::SCHEME_START: {
13106
21.4k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13107
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13108
        // state to scheme state.
13109
21.4k
        if ((input_position != input_size) &&
13110
21.3k
            checkers::is_alpha(url_data[input_position])) {
13111
17.1k
          state = state::SCHEME;
13112
17.1k
          input_position++;
13113
17.1k
        } else {
13114
          // Otherwise, if state override is not given, set state to no scheme
13115
          // state and decrease pointer by 1.
13116
4.30k
          state = state::NO_SCHEME;
13117
4.30k
        }
13118
21.4k
        break;
13119
0
      }
13120
17.1k
      case state::SCHEME: {
13121
17.1k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13122
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13123
        // append c, lowercased, to buffer.
13124
89.2k
        while ((input_position != input_size) &&
13125
88.8k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13126
72.0k
          input_position++;
13127
72.0k
        }
13128
        // Otherwise, if c is U+003A (:), then:
13129
17.1k
        if ((input_position != input_size) &&
13130
16.7k
            (url_data[input_position] == ':')) {
13131
16.1k
          ada_log("SCHEME the scheme should be ",
13132
16.1k
                  url_data.substr(0, input_position));
13133
          if constexpr (result_type_is_ada_url) {
13134
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13135
              return url;
13136
            }
13137
16.1k
          } else {
13138
            // we pass the colon along instead of painfully adding it back.
13139
16.1k
            if (!url.parse_scheme_with_colon(
13140
16.1k
                    url_data.substr(0, input_position + 1))) {
13141
0
              return url;
13142
0
            }
13143
16.1k
          }
13144
16.1k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13145
13146
          // If url's scheme is "file", then:
13147
16.1k
          if (url.type == scheme::type::FILE) {
13148
            // Set state to file state.
13149
1.45k
            state = state::FILE;
13150
1.45k
          }
13151
          // Otherwise, if url is special, base is non-null, and base's scheme
13152
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13153
          // != nullptr is false.
13154
14.6k
          else if (url.is_special() && base_url != nullptr &&
13155
0
                   base_url->type == url.type) {
13156
            // Set state to special relative or authority state.
13157
0
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13158
0
          }
13159
          // Otherwise, if url is special, set state to special authority
13160
          // slashes state.
13161
14.6k
          else if (url.is_special()) {
13162
11.6k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13163
11.6k
          }
13164
          // Otherwise, if remaining starts with an U+002F (/), set state to
13165
          // path or authority state and increase pointer by 1.
13166
3.03k
          else if (input_position + 1 < input_size &&
13167
2.68k
                   url_data[input_position + 1] == '/') {
13168
1.32k
            state = state::PATH_OR_AUTHORITY;
13169
1.32k
            input_position++;
13170
1.32k
          }
13171
          // Otherwise, set url's path to the empty string and set state to
13172
          // opaque path state.
13173
1.71k
          else {
13174
1.71k
            state = state::OPAQUE_PATH;
13175
1.71k
          }
13176
16.1k
        }
13177
        // Otherwise, if state override is not given, set buffer to the empty
13178
        // string, state to no scheme state, and start over (from the first code
13179
        // point in input).
13180
1.02k
        else {
13181
1.02k
          state = state::NO_SCHEME;
13182
1.02k
          input_position = 0;
13183
1.02k
          break;
13184
1.02k
        }
13185
16.1k
        input_position++;
13186
16.1k
        break;
13187
17.1k
      }
13188
5.33k
      case state::NO_SCHEME: {
13189
5.33k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13190
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13191
        // validation error, return failure.
13192
5.33k
        if (base_url == nullptr ||
13193
5.33k
            (base_url->has_opaque_path && !fragment.has_value())) {
13194
5.33k
          ada_log("NO_SCHEME validation error");
13195
5.33k
          url.is_valid = false;
13196
5.33k
          return url;
13197
5.33k
        }
13198
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13199
        // set url's scheme to base's scheme, url's path to base's path, url's
13200
        // query to base's query, and set state to fragment state.
13201
0
        else if (base_url->has_opaque_path && fragment.has_value() &&
13202
0
                 input_position == input_size) {
13203
0
          ada_log("NO_SCHEME opaque base with fragment");
13204
0
          url.copy_scheme(*base_url);
13205
0
          url.has_opaque_path = base_url->has_opaque_path;
13206
13207
          if constexpr (result_type_is_ada_url) {
13208
            url.path = base_url->path;
13209
            url.query = base_url->query;
13210
0
          } else {
13211
0
            url.update_base_pathname(base_url->get_pathname());
13212
0
            url.update_base_search(base_url->get_search());
13213
0
          }
13214
0
          url.update_unencoded_base_hash(*fragment);
13215
0
          return url;
13216
0
        }
13217
        // Otherwise, if base's scheme is not "file", set state to relative
13218
        // state and decrease pointer by 1.
13219
0
        else if (base_url->type != scheme::type::FILE) {
13220
0
          ada_log("NO_SCHEME non-file relative path");
13221
0
          state = state::RELATIVE_SCHEME;
13222
0
        }
13223
        // Otherwise, set state to file state and decrease pointer by 1.
13224
0
        else {
13225
0
          ada_log("NO_SCHEME file base type");
13226
0
          state = state::FILE;
13227
0
        }
13228
0
        break;
13229
5.33k
      }
13230
12.0k
      case state::AUTHORITY: {
13231
12.0k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13232
        // most URLs have no @. Having no @ tells us that we don't have to worry
13233
        // about AUTHORITY. Of course, we could have @ and still not have to
13234
        // worry about AUTHORITY.
13235
        // TODO: Instead of just collecting a bool, collect the location of the
13236
        // '@' and do something useful with it.
13237
        // TODO: We could do various processing early on, using a single pass
13238
        // over the string to collect information about it, e.g., telling us
13239
        // whether there is a @ and if so, where (or how many).
13240
13241
        // Check if url data contains an @.
13242
12.0k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13243
11.3k
          state = state::HOST;
13244
11.3k
          break;
13245
11.3k
        }
13246
760
        bool at_sign_seen{false};
13247
760
        bool password_token_seen{false};
13248
        /**
13249
         * We expect something of the sort...
13250
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13251
         * --------^
13252
         */
13253
8.96k
        do {
13254
8.96k
          std::string_view view = url_data.substr(input_position);
13255
          // The delimiters are @, /, ? \\.
13256
8.96k
          size_t location =
13257
8.96k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13258
8.96k
                               : helpers::find_authority_delimiter(view);
13259
8.96k
          std::string_view authority_view = view.substr(0, location);
13260
8.96k
          size_t end_of_authority = input_position + authority_view.size();
13261
          // If c is U+0040 (@), then:
13262
8.96k
          if ((end_of_authority != input_size) &&
13263
8.28k
              (url_data[end_of_authority] == '@')) {
13264
            // If atSignSeen is true, then prepend "%40" to buffer.
13265
8.20k
            if (at_sign_seen) {
13266
7.47k
              if (password_token_seen) {
13267
                if constexpr (result_type_is_ada_url) {
13268
                  url.password += "%40";
13269
3.33k
                } else {
13270
3.33k
                  url.append_base_password("%40");
13271
3.33k
                }
13272
4.13k
              } else {
13273
                if constexpr (result_type_is_ada_url) {
13274
                  url.username += "%40";
13275
4.13k
                } else {
13276
4.13k
                  url.append_base_username("%40");
13277
4.13k
                }
13278
4.13k
              }
13279
7.47k
            }
13280
13281
8.20k
            at_sign_seen = true;
13282
13283
8.20k
            if (!password_token_seen) {
13284
4.86k
              size_t password_token_location = authority_view.find(':');
13285
4.86k
              password_token_seen =
13286
4.86k
                  password_token_location != std::string_view::npos;
13287
13288
4.86k
              if constexpr (store_values) {
13289
4.86k
                if (!password_token_seen) {
13290
                  if constexpr (result_type_is_ada_url) {
13291
                    url.username += unicode::percent_encode(
13292
                        authority_view,
13293
                        character_sets::USERINFO_PERCENT_ENCODE);
13294
4.51k
                  } else {
13295
4.51k
                    url.append_base_username(unicode::percent_encode(
13296
4.51k
                        authority_view,
13297
4.51k
                        character_sets::USERINFO_PERCENT_ENCODE));
13298
4.51k
                  }
13299
4.51k
                } else {
13300
                  if constexpr (result_type_is_ada_url) {
13301
                    url.username += unicode::percent_encode(
13302
                        authority_view.substr(0, password_token_location),
13303
                        character_sets::USERINFO_PERCENT_ENCODE);
13304
                    url.password += unicode::percent_encode(
13305
                        authority_view.substr(password_token_location + 1),
13306
                        character_sets::USERINFO_PERCENT_ENCODE);
13307
353
                  } else {
13308
353
                    url.append_base_username(unicode::percent_encode(
13309
353
                        authority_view.substr(0, password_token_location),
13310
353
                        character_sets::USERINFO_PERCENT_ENCODE));
13311
353
                    url.append_base_password(unicode::percent_encode(
13312
353
                        authority_view.substr(password_token_location + 1),
13313
353
                        character_sets::USERINFO_PERCENT_ENCODE));
13314
353
                  }
13315
353
                }
13316
4.86k
              }
13317
4.86k
            } else if constexpr (store_values) {
13318
              if constexpr (result_type_is_ada_url) {
13319
                url.password += unicode::percent_encode(
13320
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13321
3.33k
              } else {
13322
3.33k
                url.append_base_password(unicode::percent_encode(
13323
3.33k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13324
3.33k
              }
13325
3.33k
            }
13326
8.20k
          }
13327
          // Otherwise, if one of the following is true:
13328
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13329
          // - url is special and c is U+005C (\)
13330
760
          else if (end_of_authority == input_size ||
13331
79
                   url_data[end_of_authority] == '/' ||
13332
28
                   url_data[end_of_authority] == '?' ||
13333
760
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13334
            // If atSignSeen is true and authority_view is the empty string,
13335
            // validation error, return failure.
13336
760
            if (at_sign_seen && authority_view.empty()) {
13337
114
              url.is_valid = false;
13338
114
              return url;
13339
114
            }
13340
646
            state = state::HOST;
13341
646
            break;
13342
760
          }
13343
8.20k
          if (end_of_authority == input_size) {
13344
0
            if constexpr (store_values) {
13345
0
              if (fragment.has_value()) {
13346
0
                url.update_unencoded_base_hash(*fragment);
13347
0
              }
13348
0
            }
13349
0
            return url;
13350
0
          }
13351
8.20k
          input_position = end_of_authority + 1;
13352
8.20k
        } while (true);
13353
13354
646
        break;
13355
760
      }
13356
646
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
13357
0
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
13358
0
                helpers::substring(url_data, input_position));
13359
13360
        // If c is U+002F (/) and remaining starts with U+002F (/),
13361
        // then set state to special authority ignore slashes state and increase
13362
        // pointer by 1.
13363
0
        if (url_data.substr(input_position, 2) == "//") {
13364
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13365
0
          input_position += 2;
13366
0
        } else {
13367
          // Otherwise, validation error, set state to relative state and
13368
          // decrease pointer by 1.
13369
0
          state = state::RELATIVE_SCHEME;
13370
0
        }
13371
13372
0
        break;
13373
760
      }
13374
1.32k
      case state::PATH_OR_AUTHORITY: {
13375
1.32k
        ada_log("PATH_OR_AUTHORITY ",
13376
1.32k
                helpers::substring(url_data, input_position));
13377
13378
        // If c is U+002F (/), then set state to authority state.
13379
1.32k
        if ((input_position != input_size) &&
13380
1.31k
            (url_data[input_position] == '/')) {
13381
416
          state = state::AUTHORITY;
13382
416
          input_position++;
13383
904
        } else {
13384
          // Otherwise, set state to path state, and decrease pointer by 1.
13385
904
          state = state::PATH;
13386
904
        }
13387
13388
1.32k
        break;
13389
760
      }
13390
0
      case state::RELATIVE_SCHEME: {
13391
0
        ada_log("RELATIVE_SCHEME ",
13392
0
                helpers::substring(url_data, input_position));
13393
13394
        // Set url's scheme to base's scheme.
13395
0
        url.copy_scheme(*base_url);
13396
13397
        // If c is U+002F (/), then set state to relative slash state.
13398
0
        if ((input_position != input_size) &&
13399
            // NOLINTNEXTLINE(bugprone-branch-clone)
13400
0
            (url_data[input_position] == '/')) {
13401
0
          ada_log(
13402
0
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
13403
0
              "slash state");
13404
0
          state = state::RELATIVE_SLASH;
13405
0
        } else if (url.is_special() && (input_position != input_size) &&
13406
0
                   (url_data[input_position] == '\\')) {
13407
          // Otherwise, if url is special and c is U+005C (\), validation error,
13408
          // set state to relative slash state.
13409
0
          ada_log(
13410
0
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
13411
0
              "error, set state to relative slash state");
13412
0
          state = state::RELATIVE_SLASH;
13413
0
        } else {
13414
0
          ada_log("RELATIVE_SCHEME otherwise");
13415
          // Set url's username to base's username, url's password to base's
13416
          // password, url's host to base's host, url's port to base's port,
13417
          // url's path to a clone of base's path, and url's query to base's
13418
          // query.
13419
          if constexpr (result_type_is_ada_url) {
13420
            url.username = base_url->username;
13421
            url.password = base_url->password;
13422
            url.host = base_url->host;
13423
            url.port = base_url->port;
13424
            // cloning the base path includes cloning the has_opaque_path flag
13425
            url.has_opaque_path = base_url->has_opaque_path;
13426
            url.path = base_url->path;
13427
            url.query = base_url->query;
13428
0
          } else {
13429
0
            url.update_base_authority(base_url->get_href(),
13430
0
                                      base_url->get_components());
13431
0
            url.update_host_to_base_host(base_url->get_hostname());
13432
0
            url.update_base_port(base_url->retrieve_base_port());
13433
            // cloning the base path includes cloning the has_opaque_path flag
13434
0
            url.has_opaque_path = base_url->has_opaque_path;
13435
0
            url.update_base_pathname(base_url->get_pathname());
13436
0
            url.update_base_search(base_url->get_search());
13437
0
          }
13438
13439
0
          url.has_opaque_path = base_url->has_opaque_path;
13440
13441
          // If c is U+003F (?), then set url's query to the empty string, and
13442
          // state to query state.
13443
0
          if ((input_position != input_size) &&
13444
0
              (url_data[input_position] == '?')) {
13445
0
            state = state::QUERY;
13446
0
          }
13447
          // Otherwise, if c is not the EOF code point:
13448
0
          else if (input_position != input_size) {
13449
            // Set url's query to null.
13450
0
            url.clear_search();
13451
            if constexpr (result_type_is_ada_url) {
13452
              // Shorten url's path.
13453
              helpers::shorten_path(url.path, url.type);
13454
0
            } else {
13455
0
              std::string_view path = url.get_pathname();
13456
0
              if (helpers::shorten_path(path, url.type)) {
13457
0
                url.update_base_pathname(std::move(std::string(path)));
13458
0
              }
13459
0
            }
13460
            // Set state to path state and decrease pointer by 1.
13461
0
            state = state::PATH;
13462
0
            break;
13463
0
          }
13464
0
        }
13465
0
        input_position++;
13466
0
        break;
13467
0
      }
13468
0
      case state::RELATIVE_SLASH: {
13469
0
        ada_log("RELATIVE_SLASH ",
13470
0
                helpers::substring(url_data, input_position));
13471
13472
        // If url is special and c is U+002F (/) or U+005C (\), then:
13473
0
        if (url.is_special() && (input_position != input_size) &&
13474
0
            (url_data[input_position] == '/' ||
13475
0
             url_data[input_position] == '\\')) {
13476
          // Set state to special authority ignore slashes state.
13477
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13478
0
        }
13479
        // Otherwise, if c is U+002F (/), then set state to authority state.
13480
0
        else if ((input_position != input_size) &&
13481
0
                 (url_data[input_position] == '/')) {
13482
0
          state = state::AUTHORITY;
13483
0
        }
13484
        // Otherwise, set
13485
        // - url's username to base's username,
13486
        // - url's password to base's password,
13487
        // - url's host to base's host,
13488
        // - url's port to base's port,
13489
        // - state to path state, and then, decrease pointer by 1.
13490
0
        else {
13491
          if constexpr (result_type_is_ada_url) {
13492
            url.username = base_url->username;
13493
            url.password = base_url->password;
13494
            url.host = base_url->host;
13495
            url.port = base_url->port;
13496
0
          } else {
13497
0
            url.update_base_authority(base_url->get_href(),
13498
0
                                      base_url->get_components());
13499
0
            url.update_host_to_base_host(base_url->get_hostname());
13500
0
            url.update_base_port(base_url->retrieve_base_port());
13501
0
          }
13502
0
          state = state::PATH;
13503
0
          break;
13504
0
        }
13505
13506
0
        input_position++;
13507
0
        break;
13508
0
      }
13509
11.6k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13510
11.6k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13511
11.6k
                helpers::substring(url_data, input_position));
13512
13513
        // If c is U+002F (/) and remaining starts with U+002F (/),
13514
        // then set state to special authority ignore slashes state and increase
13515
        // pointer by 1.
13516
11.6k
        if (url_data.substr(input_position, 2) == "//") {
13517
8.98k
          input_position += 2;
13518
8.98k
        }
13519
13520
11.6k
        [[fallthrough]];
13521
11.6k
      }
13522
11.6k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13523
11.6k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13524
11.6k
                helpers::substring(url_data, input_position));
13525
13526
        // If c is neither U+002F (/) nor U+005C (\), then set state to
13527
        // authority state and decrease pointer by 1.
13528
12.2k
        while ((input_position != input_size) &&
13529
12.2k
               ((url_data[input_position] == '/') ||
13530
11.8k
                (url_data[input_position] == '\\'))) {
13531
625
          input_position++;
13532
625
        }
13533
11.6k
        state = state::AUTHORITY;
13534
13535
11.6k
        break;
13536
11.6k
      }
13537
334
      case state::QUERY: {
13538
334
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13539
334
        if constexpr (store_values) {
13540
          // Let queryPercentEncodeSet be the special-query percent-encode set
13541
          // if url is special; otherwise the query percent-encode set.
13542
334
          const uint8_t* query_percent_encode_set =
13543
334
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13544
334
                               : character_sets::QUERY_PERCENT_ENCODE;
13545
13546
          // Percent-encode after encoding, with encoding, buffer, and
13547
          // queryPercentEncodeSet, and append the result to url's query.
13548
334
          url.update_base_search(url_data.substr(input_position),
13549
334
                                 query_percent_encode_set);
13550
334
          ada_log("QUERY update_base_search completed ");
13551
334
          if (fragment.has_value()) {
13552
22
            url.update_unencoded_base_hash(*fragment);
13553
22
          }
13554
334
        }
13555
334
        return url;
13556
11.6k
      }
13557
11.9k
      case state::HOST: {
13558
11.9k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13559
13560
11.9k
        std::string_view host_view = url_data.substr(input_position);
13561
11.9k
        auto [location, found_colon] =
13562
11.9k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13563
11.9k
        input_position = (location != std::string_view::npos)
13564
11.9k
                             ? input_position + location
13565
11.9k
                             : input_size;
13566
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13567
        // Note: the 'found_colon' value is true if and only if a colon was
13568
        // encountered while not inside brackets.
13569
11.9k
        if (found_colon) {
13570
          // If buffer is the empty string, validation error, return failure.
13571
          // Let host be the result of host parsing buffer with url is not
13572
          // special.
13573
683
          ada_log("HOST parsing ", host_view);
13574
683
          if (!url.parse_host(host_view)) {
13575
118
            return url;
13576
118
          }
13577
565
          ada_log("HOST parsing results in ", url.get_hostname());
13578
          // Set url's host to host, buffer to the empty string, and state to
13579
          // port state.
13580
565
          state = state::PORT;
13581
565
          input_position++;
13582
565
        }
13583
        // Otherwise, if one of the following is true:
13584
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13585
        // - url is special and c is U+005C (\)
13586
        // The get_host_delimiter_location function either brings us to
13587
        // the colon outside of the bracket, or to one of those characters.
13588
11.2k
        else {
13589
          // If url is special and host_view is the empty string, validation
13590
          // error, return failure.
13591
11.2k
          if (host_view.empty() && url.is_special()) {
13592
9
            url.is_valid = false;
13593
9
            return url;
13594
9
          }
13595
11.2k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
13596
          // Let host be the result of host parsing host_view with url is not
13597
          // special.
13598
11.2k
          if (host_view.empty()) {
13599
52
            url.update_base_hostname("");
13600
11.2k
          } else if (!url.parse_host(host_view)) {
13601
393
            return url;
13602
393
          }
13603
10.8k
          ada_log("HOST parsing results in ", url.get_hostname(),
13604
10.8k
                  " href=", url.get_href());
13605
13606
          // Set url's host to host, and state to path start state.
13607
10.8k
          state = state::PATH_START;
13608
10.8k
        }
13609
13610
11.4k
        break;
13611
11.9k
      }
13612
11.4k
      case state::OPAQUE_PATH: {
13613
1.71k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13614
1.71k
        std::string_view view = url_data.substr(input_position);
13615
        // If c is U+003F (?), then set url's query to the empty string and
13616
        // state to query state.
13617
1.71k
        size_t location = view.find('?');
13618
1.71k
        if (location != std::string_view::npos) {
13619
182
          view.remove_suffix(view.size() - location);
13620
182
          state = state::QUERY;
13621
182
          input_position += location + 1;
13622
1.52k
        } else {
13623
1.52k
          input_position = input_size + 1;
13624
1.52k
        }
13625
1.71k
        url.has_opaque_path = true;
13626
13627
        // This is a really unlikely scenario in real world. We should not seek
13628
        // to optimize it.
13629
1.71k
        if (view.ends_with(' ')) {
13630
60
          std::string modified_view =
13631
60
              std::string(view.substr(0, view.size() - 1)) + "%20";
13632
60
          url.update_base_pathname(unicode::percent_encode(
13633
60
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13634
1.65k
        } else {
13635
1.65k
          url.update_base_pathname(unicode::percent_encode(
13636
1.65k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13637
1.65k
        }
13638
1.71k
        break;
13639
11.9k
      }
13640
565
      case state::PORT: {
13641
565
        ada_log("PORT ", helpers::substring(url_data, input_position));
13642
565
        std::string_view port_view = url_data.substr(input_position);
13643
565
        input_position += url.parse_port(port_view, true);
13644
565
        if (!url.is_valid) {
13645
85
          return url;
13646
85
        }
13647
480
        state = state::PATH_START;
13648
480
        [[fallthrough]];
13649
480
      }
13650
11.8k
      case state::PATH_START: {
13651
11.8k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13652
13653
        // If url is special, then:
13654
11.8k
        if (url.is_special()) {
13655
          // Set state to path state.
13656
11.5k
          state = state::PATH;
13657
13658
          // Optimization: Avoiding going into PATH state improves the
13659
          // performance of urls ending with /.
13660
11.5k
          if (input_position == input_size) {
13661
10.7k
            if constexpr (store_values) {
13662
10.7k
              url.update_base_pathname("/");
13663
10.7k
              if (fragment.has_value()) {
13664
68
                url.update_unencoded_base_hash(*fragment);
13665
68
              }
13666
10.7k
            }
13667
10.7k
            return url;
13668
10.7k
          }
13669
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
13670
          // by 1. We know that (input_position == input_size) is impossible
13671
          // here, because of the previous if-check.
13672
782
          if ((url_data[input_position] != '/') &&
13673
90
              (url_data[input_position] != '\\')) {
13674
76
            break;
13675
76
          }
13676
782
        }
13677
        // Otherwise, if state override is not given and c is U+003F (?),
13678
        // set url's query to the empty string and state to query state.
13679
282
        else if ((input_position != input_size) &&
13680
57
                 (url_data[input_position] == '?')) {
13681
10
          state = state::QUERY;
13682
10
        }
13683
        // Otherwise, if c is not the EOF code point:
13684
272
        else if (input_position != input_size) {
13685
          // Set state to path state.
13686
47
          state = state::PATH;
13687
13688
          // If c is not U+002F (/), then decrease pointer by 1.
13689
47
          if (url_data[input_position] != '/') {
13690
0
            break;
13691
0
          }
13692
47
        }
13693
13694
988
        input_position++;
13695
988
        break;
13696
11.8k
      }
13697
2.61k
      case state::PATH: {
13698
2.61k
        ada_log("PATH ", helpers::substring(url_data, input_position));
13699
2.61k
        std::string_view view = url_data.substr(input_position);
13700
13701
        // Most time, we do not need percent encoding.
13702
        // Furthermore, we can immediately locate the '?'.
13703
2.61k
        size_t locofquestionmark = view.find('?');
13704
2.61k
        if (locofquestionmark != std::string_view::npos) {
13705
142
          state = state::QUERY;
13706
142
          view.remove_suffix(view.size() - locofquestionmark);
13707
142
          input_position += locofquestionmark + 1;
13708
2.47k
        } else {
13709
2.47k
          input_position = input_size + 1;
13710
2.47k
        }
13711
2.61k
        if constexpr (store_values) {
13712
          if constexpr (result_type_is_ada_url) {
13713
            helpers::parse_prepared_path(view, url.type, url.path);
13714
2.61k
          } else {
13715
2.61k
            url.consume_prepared_path(view);
13716
2.61k
            ADA_ASSERT_TRUE(url.validate());
13717
2.61k
          }
13718
2.61k
        }
13719
2.61k
        break;
13720
11.8k
      }
13721
807
      case state::FILE_SLASH: {
13722
807
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13723
13724
        // If c is U+002F (/) or U+005C (\), then:
13725
807
        if ((input_position != input_size) &&
13726
802
            (url_data[input_position] == '/' ||
13727
579
             url_data[input_position] == '\\')) {
13728
579
          ada_log("FILE_SLASH c is U+002F or U+005C");
13729
          // Set state to file host state.
13730
579
          state = state::FILE_HOST;
13731
579
          input_position++;
13732
579
        } else {
13733
228
          ada_log("FILE_SLASH otherwise");
13734
          // If base is non-null and base's scheme is "file", then:
13735
          // Note: it is unsafe to do base_url->scheme unless you know that
13736
          // base_url_has_value() is true.
13737
228
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13738
            // Set url's host to base's host.
13739
            if constexpr (result_type_is_ada_url) {
13740
              url.host = base_url->host;
13741
0
            } else {
13742
0
              url.update_host_to_base_host(base_url->get_host());
13743
0
            }
13744
            // If the code point substring from pointer to the end of input does
13745
            // not start with a Windows drive letter and base's path[0] is a
13746
            // normalized Windows drive letter, then append base's path[0] to
13747
            // url's path.
13748
0
            if (!base_url->get_pathname().empty()) {
13749
0
              if (!checkers::is_windows_drive_letter(
13750
0
                      url_data.substr(input_position))) {
13751
0
                std::string_view first_base_url_path =
13752
0
                    base_url->get_pathname().substr(1);
13753
0
                size_t loc = first_base_url_path.find('/');
13754
0
                if (loc != std::string_view::npos) {
13755
0
                  helpers::resize(first_base_url_path, loc);
13756
0
                }
13757
0
                if (checkers::is_normalized_windows_drive_letter(
13758
0
                        first_base_url_path)) {
13759
                  if constexpr (result_type_is_ada_url) {
13760
                    url.path += '/';
13761
                    url.path += first_base_url_path;
13762
0
                  } else {
13763
0
                    url.append_base_pathname(
13764
0
                        helpers::concat("/", first_base_url_path));
13765
0
                  }
13766
0
                }
13767
0
              }
13768
0
            }
13769
0
          }
13770
13771
          // Set state to path state, and decrease pointer by 1.
13772
228
          state = state::PATH;
13773
228
        }
13774
13775
807
        break;
13776
11.8k
      }
13777
579
      case state::FILE_HOST: {
13778
579
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13779
579
        std::string_view view = url_data.substr(input_position);
13780
13781
579
        size_t location = view.find_first_of("/\\?");
13782
579
        std::string_view file_host_buffer(
13783
579
            view.data(),
13784
579
            (location != std::string_view::npos) ? location : view.size());
13785
13786
579
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13787
5
          state = state::PATH;
13788
574
        } else if (file_host_buffer.empty()) {
13789
          // Set url's host to the empty string.
13790
          if constexpr (result_type_is_ada_url) {
13791
            url.host = "";
13792
26
          } else {
13793
26
            url.update_base_hostname("");
13794
26
          }
13795
          // Set state to path start state.
13796
26
          state = state::PATH_START;
13797
548
        } else {
13798
548
          size_t consumed_bytes = file_host_buffer.size();
13799
548
          input_position += consumed_bytes;
13800
          // Let host be the result of host parsing buffer with url is not
13801
          // special.
13802
548
          if (!url.parse_host(file_host_buffer)) {
13803
119
            return url;
13804
119
          }
13805
13806
          if constexpr (result_type_is_ada_url) {
13807
            // If host is "localhost", then set host to the empty string.
13808
            if (url.host.has_value() && url.host.value() == "localhost") {
13809
              url.host = "";
13810
            }
13811
429
          } else {
13812
429
            if (url.get_hostname() == "localhost") {
13813
3
              url.update_base_hostname("");
13814
3
            }
13815
429
          }
13816
13817
          // Set buffer to the empty string and state to path start state.
13818
429
          state = state::PATH_START;
13819
429
        }
13820
13821
460
        break;
13822
579
      }
13823
1.45k
      case state::FILE: {
13824
1.45k
        ada_log("FILE ", helpers::substring(url_data, input_position));
13825
1.45k
        std::string_view file_view = url_data.substr(input_position);
13826
13827
1.45k
        url.set_protocol_as_file();
13828
        if constexpr (result_type_is_ada_url) {
13829
          // Set url's host to the empty string.
13830
          url.host = "";
13831
1.45k
        } else {
13832
1.45k
          url.update_base_hostname("");
13833
1.45k
        }
13834
        // If c is U+002F (/) or U+005C (\), then:
13835
1.45k
        if (input_position != input_size &&
13836
1.44k
            (url_data[input_position] == '/' ||
13837
807
             url_data[input_position] == '\\')) {
13838
807
          ada_log("FILE c is U+002F or U+005C");
13839
          // Set state to file slash state.
13840
807
          state = state::FILE_SLASH;
13841
807
        }
13842
        // Otherwise, if base is non-null and base's scheme is "file":
13843
646
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13844
          // Set url's host to base's host, url's path to a clone of base's
13845
          // path, and url's query to base's query.
13846
0
          ada_log("FILE base non-null");
13847
          if constexpr (result_type_is_ada_url) {
13848
            url.host = base_url->host;
13849
            url.path = base_url->path;
13850
            url.query = base_url->query;
13851
0
          } else {
13852
0
            url.update_host_to_base_host(base_url->get_hostname());
13853
0
            url.update_base_pathname(base_url->get_pathname());
13854
0
            url.update_base_search(base_url->get_search());
13855
0
          }
13856
0
          url.has_opaque_path = base_url->has_opaque_path;
13857
13858
          // If c is U+003F (?), then set url's query to the empty string and
13859
          // state to query state.
13860
0
          if (input_position != input_size && url_data[input_position] == '?') {
13861
0
            state = state::QUERY;
13862
0
          }
13863
          // Otherwise, if c is not the EOF code point:
13864
0
          else if (input_position != input_size) {
13865
            // Set url's query to null.
13866
0
            url.clear_search();
13867
            // If the code point substring from pointer to the end of input does
13868
            // not start with a Windows drive letter, then shorten url's path.
13869
0
            if (!checkers::is_windows_drive_letter(file_view)) {
13870
              if constexpr (result_type_is_ada_url) {
13871
                helpers::shorten_path(url.path, url.type);
13872
0
              } else {
13873
0
                std::string_view path = url.get_pathname();
13874
0
                if (helpers::shorten_path(path, url.type)) {
13875
0
                  url.update_base_pathname(std::move(std::string(path)));
13876
0
                }
13877
0
              }
13878
0
            }
13879
            // Otherwise:
13880
0
            else {
13881
              // Set url's path to an empty list.
13882
0
              url.clear_pathname();
13883
0
              url.has_opaque_path = true;
13884
0
            }
13885
13886
            // Set state to path state and decrease pointer by 1.
13887
0
            state = state::PATH;
13888
0
            break;
13889
0
          }
13890
0
        }
13891
        // Otherwise, set state to path state, and decrease pointer by 1.
13892
646
        else {
13893
646
          ada_log("FILE go to path");
13894
646
          state = state::PATH;
13895
646
          break;
13896
646
        }
13897
13898
807
        input_position++;
13899
807
        break;
13900
1.45k
      }
13901
0
      default:
13902
0
        unreachable();
13903
100k
    }
13904
100k
  }
13905
4.22k
  if constexpr (store_values) {
13906
4.22k
    if (fragment.has_value()) {
13907
142
      url.update_unencoded_base_hash(*fragment);
13908
142
    }
13909
4.22k
  }
13910
4.22k
  return url;
13911
21.4k
}
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*)
13912
13913
template url parse_url_impl(std::string_view user_input,
13914
                            const url* base_url = nullptr);
13915
template url_aggregator parse_url_impl(
13916
    std::string_view user_input, const url_aggregator* base_url = nullptr);
13917
13918
template <class result_type>
13919
result_type parse_url(std::string_view user_input,
13920
0
                      const result_type* base_url) {
13921
0
  return parse_url_impl<result_type, true>(user_input, base_url);
13922
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*)
13923
13924
template url parse_url<url>(std::string_view user_input,
13925
                            const url* base_url = nullptr);
13926
template url_aggregator parse_url<url_aggregator>(
13927
    std::string_view user_input, const url_aggregator* base_url = nullptr);
13928
}  // namespace ada::parser
13929
/* end file src/parser.cpp */
13930
/* begin file src/url_components.cpp */
13931
13932
#include <iterator>
13933
#include <string>
13934
13935
namespace ada {
13936
13937
0
[[nodiscard]] std::string url_components::to_string() const {
13938
0
  std::string answer;
13939
0
  auto back = std::back_insert_iterator(answer);
13940
0
  answer.append("{\n");
13941
13942
0
  answer.append("\t\"protocol_end\":\"");
13943
0
  helpers::encode_json(std::to_string(protocol_end), back);
13944
0
  answer.append("\",\n");
13945
13946
0
  answer.append("\t\"username_end\":\"");
13947
0
  helpers::encode_json(std::to_string(username_end), back);
13948
0
  answer.append("\",\n");
13949
13950
0
  answer.append("\t\"host_start\":\"");
13951
0
  helpers::encode_json(std::to_string(host_start), back);
13952
0
  answer.append("\",\n");
13953
13954
0
  answer.append("\t\"host_end\":\"");
13955
0
  helpers::encode_json(std::to_string(host_end), back);
13956
0
  answer.append("\",\n");
13957
13958
0
  answer.append("\t\"port\":\"");
13959
0
  helpers::encode_json(std::to_string(port), back);
13960
0
  answer.append("\",\n");
13961
13962
0
  answer.append("\t\"pathname_start\":\"");
13963
0
  helpers::encode_json(std::to_string(pathname_start), back);
13964
0
  answer.append("\",\n");
13965
13966
0
  answer.append("\t\"search_start\":\"");
13967
0
  helpers::encode_json(std::to_string(search_start), back);
13968
0
  answer.append("\",\n");
13969
13970
0
  answer.append("\t\"hash_start\":\"");
13971
0
  helpers::encode_json(std::to_string(hash_start), back);
13972
0
  answer.append("\",\n");
13973
13974
0
  answer.append("\n}");
13975
0
  return answer;
13976
0
}
13977
13978
}  // namespace ada
13979
/* end file src/url_components.cpp */
13980
/* begin file src/url_aggregator.cpp */
13981
13982
#include <iterator>
13983
#include <ranges>
13984
#include <string>
13985
#include <string_view>
13986
13987
namespace ada {
13988
template <bool has_state_override>
13989
[[nodiscard]] ada_really_inline bool url_aggregator::parse_scheme_with_colon(
13990
20.1k
    const std::string_view input_with_colon) {
13991
20.1k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
13992
20.1k
  ADA_ASSERT_TRUE(validate());
13993
20.1k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
13994
20.1k
  std::string_view input{input_with_colon};
13995
20.1k
  input.remove_suffix(1);
13996
20.1k
  auto parsed_type = ada::scheme::get_scheme_type(input);
13997
20.1k
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
13998
  /**
13999
   * In the common case, we will immediately recognize a special scheme (e.g.,
14000
   *http, https), in which case, we can go really fast.
14001
   **/
14002
20.1k
  if (is_input_special) {  // fast path!!!
14003
13.4k
    if constexpr (has_state_override) {
14004
      // If url's scheme is not a special scheme and buffer is a special scheme,
14005
      // then return.
14006
1.51k
      if (is_special() != is_input_special) {
14007
0
        return false;
14008
0
      }
14009
14010
      // If url includes credentials or has a non-null port, and buffer is
14011
      // "file", then return.
14012
1.51k
      if ((has_credentials() || components.port != url_components::omitted) &&
14013
0
          parsed_type == ada::scheme::type::FILE) {
14014
0
        return false;
14015
0
      }
14016
14017
      // If url's scheme is "file" and its host is an empty host, then return.
14018
      // An empty host is the empty string.
14019
1.51k
      if (type == ada::scheme::type::FILE &&
14020
0
          components.host_start == components.host_end) {
14021
0
        return false;
14022
0
      }
14023
1.51k
    }
14024
14025
1.51k
    type = parsed_type;
14026
13.4k
    set_scheme_from_view_with_colon(input_with_colon);
14027
14028
13.4k
    if constexpr (has_state_override) {
14029
      // This is uncommon.
14030
1.51k
      uint16_t urls_scheme_port = get_special_port();
14031
14032
      // If url's port is url's scheme's default port, then set url's port to
14033
      // null.
14034
1.51k
      if (components.port == urls_scheme_port) {
14035
0
        clear_port();
14036
0
      }
14037
1.51k
    }
14038
13.4k
  } else {  // slow path
14039
6.74k
    std::string _buffer(input);
14040
    // Next function is only valid if the input is ASCII and returns false
14041
    // otherwise, but it seems that we always have ascii content so we do not
14042
    // need to check the return value.
14043
6.74k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14044
14045
6.74k
    if constexpr (has_state_override) {
14046
      // If url's scheme is a special scheme and buffer is not a special scheme,
14047
      // then return. If url's scheme is not a special scheme and buffer is a
14048
      // special scheme, then return.
14049
2.49k
      if (is_special() != ada::scheme::is_special(_buffer)) {
14050
1.82k
        return true;
14051
1.82k
      }
14052
14053
      // If url includes credentials or has a non-null port, and buffer is
14054
      // "file", then return.
14055
674
      if ((has_credentials() || components.port != url_components::omitted) &&
14056
0
          _buffer == "file") {
14057
0
        return true;
14058
0
      }
14059
14060
      // If url's scheme is "file" and its host is an empty host, then return.
14061
      // An empty host is the empty string.
14062
674
      if (type == ada::scheme::type::FILE &&
14063
0
          components.host_start == components.host_end) {
14064
0
        return true;
14065
0
      }
14066
674
    }
14067
14068
674
    set_scheme(_buffer);
14069
14070
6.74k
    if constexpr (has_state_override) {
14071
      // This is uncommon.
14072
2.49k
      uint16_t urls_scheme_port = get_special_port();
14073
14074
      // If url's port is url's scheme's default port, then set url's port to
14075
      // null.
14076
2.49k
      if (components.port == urls_scheme_port) {
14077
0
        clear_port();
14078
0
      }
14079
2.49k
    }
14080
6.74k
  }
14081
0
  ADA_ASSERT_TRUE(validate());
14082
20.1k
  return true;
14083
20.1k
}
bool ada::url_aggregator::parse_scheme_with_colon<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
13990
16.1k
    const std::string_view input_with_colon) {
13991
16.1k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
13992
16.1k
  ADA_ASSERT_TRUE(validate());
13993
16.1k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
13994
16.1k
  std::string_view input{input_with_colon};
13995
16.1k
  input.remove_suffix(1);
13996
16.1k
  auto parsed_type = ada::scheme::get_scheme_type(input);
13997
16.1k
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
13998
  /**
13999
   * In the common case, we will immediately recognize a special scheme (e.g.,
14000
   *http, https), in which case, we can go really fast.
14001
   **/
14002
16.1k
  if (is_input_special) {  // fast path!!!
14003
    if constexpr (has_state_override) {
14004
      // If url's scheme is not a special scheme and buffer is a special scheme,
14005
      // then return.
14006
      if (is_special() != is_input_special) {
14007
        return false;
14008
      }
14009
14010
      // If url includes credentials or has a non-null port, and buffer is
14011
      // "file", then return.
14012
      if ((has_credentials() || components.port != url_components::omitted) &&
14013
          parsed_type == ada::scheme::type::FILE) {
14014
        return false;
14015
      }
14016
14017
      // If url's scheme is "file" and its host is an empty host, then return.
14018
      // An empty host is the empty string.
14019
      if (type == ada::scheme::type::FILE &&
14020
          components.host_start == components.host_end) {
14021
        return false;
14022
      }
14023
    }
14024
14025
11.8k
    type = parsed_type;
14026
11.8k
    set_scheme_from_view_with_colon(input_with_colon);
14027
14028
    if constexpr (has_state_override) {
14029
      // This is uncommon.
14030
      uint16_t urls_scheme_port = get_special_port();
14031
14032
      // If url's port is url's scheme's default port, then set url's port to
14033
      // null.
14034
      if (components.port == urls_scheme_port) {
14035
        clear_port();
14036
      }
14037
    }
14038
11.8k
  } else {  // slow path
14039
4.24k
    std::string _buffer(input);
14040
    // Next function is only valid if the input is ASCII and returns false
14041
    // otherwise, but it seems that we always have ascii content so we do not
14042
    // need to check the return value.
14043
4.24k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14044
14045
    if constexpr (has_state_override) {
14046
      // If url's scheme is a special scheme and buffer is not a special scheme,
14047
      // then return. If url's scheme is not a special scheme and buffer is a
14048
      // special scheme, then return.
14049
      if (is_special() != ada::scheme::is_special(_buffer)) {
14050
        return true;
14051
      }
14052
14053
      // If url includes credentials or has a non-null port, and buffer is
14054
      // "file", then return.
14055
      if ((has_credentials() || components.port != url_components::omitted) &&
14056
          _buffer == "file") {
14057
        return true;
14058
      }
14059
14060
      // If url's scheme is "file" and its host is an empty host, then return.
14061
      // An empty host is the empty string.
14062
      if (type == ada::scheme::type::FILE &&
14063
          components.host_start == components.host_end) {
14064
        return true;
14065
      }
14066
    }
14067
14068
4.24k
    set_scheme(_buffer);
14069
14070
    if constexpr (has_state_override) {
14071
      // This is uncommon.
14072
      uint16_t urls_scheme_port = get_special_port();
14073
14074
      // If url's port is url's scheme's default port, then set url's port to
14075
      // null.
14076
      if (components.port == urls_scheme_port) {
14077
        clear_port();
14078
      }
14079
    }
14080
4.24k
  }
14081
16.1k
  ADA_ASSERT_TRUE(validate());
14082
16.1k
  return true;
14083
16.1k
}
bool ada::url_aggregator::parse_scheme_with_colon<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
13990
4.01k
    const std::string_view input_with_colon) {
13991
4.01k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
13992
4.01k
  ADA_ASSERT_TRUE(validate());
13993
4.01k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
13994
4.01k
  std::string_view input{input_with_colon};
13995
4.01k
  input.remove_suffix(1);
13996
4.01k
  auto parsed_type = ada::scheme::get_scheme_type(input);
13997
4.01k
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
13998
  /**
13999
   * In the common case, we will immediately recognize a special scheme (e.g.,
14000
   *http, https), in which case, we can go really fast.
14001
   **/
14002
4.01k
  if (is_input_special) {  // fast path!!!
14003
1.51k
    if constexpr (has_state_override) {
14004
      // If url's scheme is not a special scheme and buffer is a special scheme,
14005
      // then return.
14006
1.51k
      if (is_special() != is_input_special) {
14007
0
        return false;
14008
0
      }
14009
14010
      // If url includes credentials or has a non-null port, and buffer is
14011
      // "file", then return.
14012
1.51k
      if ((has_credentials() || components.port != url_components::omitted) &&
14013
0
          parsed_type == ada::scheme::type::FILE) {
14014
0
        return false;
14015
0
      }
14016
14017
      // If url's scheme is "file" and its host is an empty host, then return.
14018
      // An empty host is the empty string.
14019
1.51k
      if (type == ada::scheme::type::FILE &&
14020
0
          components.host_start == components.host_end) {
14021
0
        return false;
14022
0
      }
14023
1.51k
    }
14024
14025
1.51k
    type = parsed_type;
14026
1.51k
    set_scheme_from_view_with_colon(input_with_colon);
14027
14028
1.51k
    if constexpr (has_state_override) {
14029
      // This is uncommon.
14030
1.51k
      uint16_t urls_scheme_port = get_special_port();
14031
14032
      // If url's port is url's scheme's default port, then set url's port to
14033
      // null.
14034
1.51k
      if (components.port == urls_scheme_port) {
14035
0
        clear_port();
14036
0
      }
14037
1.51k
    }
14038
2.49k
  } else {  // slow path
14039
2.49k
    std::string _buffer(input);
14040
    // Next function is only valid if the input is ASCII and returns false
14041
    // otherwise, but it seems that we always have ascii content so we do not
14042
    // need to check the return value.
14043
2.49k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14044
14045
2.49k
    if constexpr (has_state_override) {
14046
      // If url's scheme is a special scheme and buffer is not a special scheme,
14047
      // then return. If url's scheme is not a special scheme and buffer is a
14048
      // special scheme, then return.
14049
2.49k
      if (is_special() != ada::scheme::is_special(_buffer)) {
14050
1.82k
        return true;
14051
1.82k
      }
14052
14053
      // If url includes credentials or has a non-null port, and buffer is
14054
      // "file", then return.
14055
674
      if ((has_credentials() || components.port != url_components::omitted) &&
14056
0
          _buffer == "file") {
14057
0
        return true;
14058
0
      }
14059
14060
      // If url's scheme is "file" and its host is an empty host, then return.
14061
      // An empty host is the empty string.
14062
674
      if (type == ada::scheme::type::FILE &&
14063
0
          components.host_start == components.host_end) {
14064
0
        return true;
14065
0
      }
14066
674
    }
14067
14068
674
    set_scheme(_buffer);
14069
14070
2.49k
    if constexpr (has_state_override) {
14071
      // This is uncommon.
14072
2.49k
      uint16_t urls_scheme_port = get_special_port();
14073
14074
      // If url's port is url's scheme's default port, then set url's port to
14075
      // null.
14076
2.49k
      if (components.port == urls_scheme_port) {
14077
0
        clear_port();
14078
0
      }
14079
2.49k
    }
14080
2.49k
  }
14081
0
  ADA_ASSERT_TRUE(validate());
14082
4.01k
  return true;
14083
4.01k
}
14084
14085
0
inline void url_aggregator::copy_scheme(const url_aggregator& u) noexcept {
14086
0
  ada_log("url_aggregator::copy_scheme ", u.buffer);
14087
0
  ADA_ASSERT_TRUE(validate());
14088
  // next line could overflow but unsigned arithmetic has well-defined
14089
  // overflows.
14090
0
  uint32_t new_difference = u.components.protocol_end - components.protocol_end;
14091
0
  type = u.type;
14092
0
  buffer.erase(0, components.protocol_end);
14093
0
  buffer.insert(0, u.get_protocol());
14094
0
  components.protocol_end = u.components.protocol_end;
14095
14096
  // No need to update the components
14097
0
  if (new_difference == 0) {
14098
0
    return;
14099
0
  }
14100
14101
  // Update the rest of the components.
14102
0
  components.username_end += new_difference;
14103
0
  components.host_start += new_difference;
14104
0
  components.host_end += new_difference;
14105
0
  components.pathname_start += new_difference;
14106
0
  if (components.search_start != url_components::omitted) {
14107
0
    components.search_start += new_difference;
14108
0
  }
14109
0
  if (components.hash_start != url_components::omitted) {
14110
0
    components.hash_start += new_difference;
14111
0
  }
14112
0
  ADA_ASSERT_TRUE(validate());
14113
0
}
14114
14115
inline void url_aggregator::set_scheme_from_view_with_colon(
14116
13.4k
    std::string_view new_scheme_with_colon) noexcept {
14117
13.4k
  ada_log("url_aggregator::set_scheme_from_view_with_colon ",
14118
13.4k
          new_scheme_with_colon);
14119
13.4k
  ADA_ASSERT_TRUE(validate());
14120
13.4k
  ADA_ASSERT_TRUE(!new_scheme_with_colon.empty() &&
14121
13.4k
                  new_scheme_with_colon.back() == ':');
14122
  // next line could overflow but unsigned arithmetic has well-defined
14123
  // overflows.
14124
13.4k
  uint32_t new_difference =
14125
13.4k
      uint32_t(new_scheme_with_colon.size()) - components.protocol_end;
14126
14127
13.4k
  if (buffer.empty()) {
14128
11.8k
    buffer.append(new_scheme_with_colon);
14129
11.8k
  } else {
14130
1.51k
    buffer.erase(0, components.protocol_end);
14131
1.51k
    buffer.insert(0, new_scheme_with_colon);
14132
1.51k
  }
14133
13.4k
  components.protocol_end += new_difference;
14134
14135
  // Update the rest of the components.
14136
13.4k
  components.username_end += new_difference;
14137
13.4k
  components.host_start += new_difference;
14138
13.4k
  components.host_end += new_difference;
14139
13.4k
  components.pathname_start += new_difference;
14140
13.4k
  if (components.search_start != url_components::omitted) {
14141
0
    components.search_start += new_difference;
14142
0
  }
14143
13.4k
  if (components.hash_start != url_components::omitted) {
14144
0
    components.hash_start += new_difference;
14145
0
  }
14146
13.4k
  ADA_ASSERT_TRUE(validate());
14147
13.4k
}
14148
14149
4.92k
inline void url_aggregator::set_scheme(std::string_view new_scheme) noexcept {
14150
4.92k
  ada_log("url_aggregator::set_scheme ", new_scheme);
14151
4.92k
  ADA_ASSERT_TRUE(validate());
14152
4.92k
  ADA_ASSERT_TRUE(new_scheme.empty() || new_scheme.back() != ':');
14153
  // next line could overflow but unsigned arithmetic has well-defined
14154
  // overflows.
14155
4.92k
  uint32_t new_difference =
14156
4.92k
      uint32_t(new_scheme.size()) - components.protocol_end + 1;
14157
14158
4.92k
  type = ada::scheme::get_scheme_type(new_scheme);
14159
4.92k
  if (buffer.empty()) {
14160
4.24k
    buffer.append(helpers::concat(new_scheme, ":"));
14161
4.24k
  } else {
14162
674
    buffer.erase(0, components.protocol_end);
14163
674
    buffer.insert(0, helpers::concat(new_scheme, ":"));
14164
674
  }
14165
4.92k
  components.protocol_end = uint32_t(new_scheme.size() + 1);
14166
14167
  // Update the rest of the components.
14168
4.92k
  components.username_end += new_difference;
14169
4.92k
  components.host_start += new_difference;
14170
4.92k
  components.host_end += new_difference;
14171
4.92k
  components.pathname_start += new_difference;
14172
4.92k
  if (components.search_start != url_components::omitted) {
14173
0
    components.search_start += new_difference;
14174
0
  }
14175
4.92k
  if (components.hash_start != url_components::omitted) {
14176
0
    components.hash_start += new_difference;
14177
0
  }
14178
4.92k
  ADA_ASSERT_TRUE(validate());
14179
4.92k
}
14180
14181
8.96k
bool url_aggregator::set_protocol(const std::string_view input) {
14182
8.96k
  ada_log("url_aggregator::set_protocol ", input);
14183
8.96k
  ADA_ASSERT_TRUE(validate());
14184
8.96k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14185
8.96k
  std::string view(input);
14186
8.96k
  helpers::remove_ascii_tab_or_newline(view);
14187
8.96k
  if (view.empty()) {
14188
29
    return true;
14189
29
  }
14190
14191
  // Schemes should start with alpha values.
14192
8.93k
  if (!checkers::is_alpha(view[0])) {
14193
4.30k
    return false;
14194
4.30k
  }
14195
14196
4.63k
  view.append(":");
14197
14198
4.63k
  std::string::iterator pointer =
14199
4.63k
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
14200
14201
4.63k
  if (pointer != view.end() && *pointer == ':') {
14202
4.01k
    return parse_scheme_with_colon<true>(
14203
4.01k
        view.substr(0, pointer - view.begin() + 1));
14204
4.01k
  }
14205
618
  return false;
14206
4.63k
}
14207
14208
8.96k
bool url_aggregator::set_username(const std::string_view input) {
14209
8.96k
  ada_log("url_aggregator::set_username '", input, "' ");
14210
8.96k
  ADA_ASSERT_TRUE(validate());
14211
8.96k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14212
8.96k
  if (cannot_have_credentials_or_port()) {
14213
731
    return false;
14214
731
  }
14215
8.23k
  size_t idx = ada::unicode::percent_encode_index(
14216
8.23k
      input, character_sets::USERINFO_PERCENT_ENCODE);
14217
8.23k
  if (idx == input.size()) {
14218
1.06k
    update_base_username(input);
14219
7.17k
  } else {
14220
    // We only create a temporary string if we have to!
14221
7.17k
    update_base_username(ada::unicode::percent_encode(
14222
7.17k
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14223
7.17k
  }
14224
8.23k
  ADA_ASSERT_TRUE(validate());
14225
8.23k
  return true;
14226
8.96k
}
14227
14228
8.96k
bool url_aggregator::set_password(const std::string_view input) {
14229
8.96k
  ada_log("url_aggregator::set_password '", input, "'");
14230
8.96k
  ADA_ASSERT_TRUE(validate());
14231
8.96k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14232
8.96k
  if (cannot_have_credentials_or_port()) {
14233
731
    return false;
14234
731
  }
14235
8.23k
  size_t idx = ada::unicode::percent_encode_index(
14236
8.23k
      input, character_sets::USERINFO_PERCENT_ENCODE);
14237
8.23k
  if (idx == input.size()) {
14238
1.06k
    update_base_password(input);
14239
7.17k
  } else {
14240
    // We only create a temporary string if we have to!
14241
7.17k
    update_base_password(ada::unicode::percent_encode(
14242
7.17k
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14243
7.17k
  }
14244
8.23k
  ADA_ASSERT_TRUE(validate());
14245
8.23k
  return true;
14246
8.96k
}
14247
14248
11.8k
bool url_aggregator::set_port(const std::string_view input) {
14249
11.8k
  ada_log("url_aggregator::set_port ", input);
14250
11.8k
  ADA_ASSERT_TRUE(validate());
14251
11.8k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14252
11.8k
  if (cannot_have_credentials_or_port()) {
14253
731
    return false;
14254
731
  }
14255
14256
11.1k
  if (input.empty()) {
14257
3
    clear_port();
14258
3
    return true;
14259
3
  }
14260
14261
11.1k
  std::string trimmed(input);
14262
11.1k
  helpers::remove_ascii_tab_or_newline(trimmed);
14263
14264
11.1k
  if (trimmed.empty()) {
14265
26
    return true;
14266
26
  }
14267
14268
  // Input should not start with a non-digit character.
14269
11.0k
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
14270
9.62k
    return false;
14271
9.62k
  }
14272
14273
  // Find the first non-digit character to determine the length of digits
14274
1.45k
  auto first_non_digit =
14275
1.45k
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
14276
1.45k
  std::string_view digits_to_parse =
14277
1.45k
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
14278
14279
  // Revert changes if parse_port fails.
14280
1.45k
  uint32_t previous_port = components.port;
14281
1.45k
  parse_port(digits_to_parse);
14282
1.45k
  if (is_valid) {
14283
964
    return true;
14284
964
  }
14285
491
  update_base_port(previous_port);
14286
491
  is_valid = true;
14287
491
  ADA_ASSERT_TRUE(validate());
14288
491
  return false;
14289
1.45k
}
14290
14291
8.96k
bool url_aggregator::set_pathname(const std::string_view input) {
14292
8.96k
  ada_log("url_aggregator::set_pathname ", input);
14293
8.96k
  ADA_ASSERT_TRUE(validate());
14294
8.96k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14295
8.96k
  if (has_opaque_path) {
14296
0
    return false;
14297
0
  }
14298
8.96k
  clear_pathname();
14299
8.96k
  parse_path(input);
14300
8.96k
  if (get_pathname().starts_with("//") && !has_authority() && !has_dash_dot()) {
14301
0
    buffer.insert(components.pathname_start, "/.");
14302
0
    components.pathname_start += 2;
14303
0
  }
14304
8.96k
  ADA_ASSERT_TRUE(validate());
14305
8.96k
  return true;
14306
8.96k
}
14307
14308
8.96k
ada_really_inline void url_aggregator::parse_path(std::string_view input) {
14309
8.96k
  ada_log("url_aggregator::parse_path ", input);
14310
8.96k
  ADA_ASSERT_TRUE(validate());
14311
8.96k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14312
8.96k
  std::string tmp_buffer;
14313
8.96k
  std::string_view internal_input;
14314
8.96k
  if (unicode::has_tabs_or_newline(input)) {
14315
156
    tmp_buffer = input;
14316
    // Optimization opportunity: Instead of copying and then pruning, we could
14317
    // just directly build the string from user_input.
14318
156
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
14319
156
    internal_input = tmp_buffer;
14320
8.81k
  } else {
14321
8.81k
    internal_input = input;
14322
8.81k
  }
14323
14324
  // If url is special, then:
14325
8.96k
  if (is_special()) {
14326
8.96k
    if (internal_input.empty()) {
14327
29
      update_base_pathname("/");
14328
8.93k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
14329
708
      consume_prepared_path(internal_input.substr(1));
14330
8.23k
    } else {
14331
8.23k
      consume_prepared_path(internal_input);
14332
8.23k
    }
14333
8.96k
  } else if (!internal_input.empty()) {
14334
0
    if (internal_input[0] == '/') {
14335
0
      consume_prepared_path(internal_input.substr(1));
14336
0
    } else {
14337
0
      consume_prepared_path(internal_input);
14338
0
    }
14339
0
  } else {
14340
    // Non-special URLs with an empty host can have their paths erased
14341
    // Path-only URLs cannot have their paths erased
14342
0
    if (components.host_start == components.host_end && !has_authority()) {
14343
0
      update_base_pathname("/");
14344
0
    }
14345
0
  }
14346
8.96k
  ADA_ASSERT_TRUE(validate());
14347
8.96k
}
14348
14349
8.96k
void url_aggregator::set_search(const std::string_view input) {
14350
8.96k
  ada_log("url_aggregator::set_search ", input);
14351
8.96k
  ADA_ASSERT_TRUE(validate());
14352
8.96k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14353
8.96k
  if (input.empty()) {
14354
3
    clear_search();
14355
3
    helpers::strip_trailing_spaces_from_opaque_path(*this);
14356
3
    return;
14357
3
  }
14358
14359
8.96k
  std::string new_value;
14360
8.96k
  new_value = input[0] == '?' ? input.substr(1) : input;
14361
8.96k
  helpers::remove_ascii_tab_or_newline(new_value);
14362
14363
8.96k
  auto query_percent_encode_set =
14364
8.96k
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
14365
8.96k
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
14366
14367
8.96k
  update_base_search(new_value, query_percent_encode_set);
14368
8.96k
  ADA_ASSERT_TRUE(validate());
14369
8.96k
}
14370
14371
8.96k
void url_aggregator::set_hash(const std::string_view input) {
14372
8.96k
  ada_log("url_aggregator::set_hash ", input);
14373
8.96k
  ADA_ASSERT_TRUE(validate());
14374
8.96k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14375
8.96k
  if (input.empty()) {
14376
3
    if (components.hash_start != url_components::omitted) {
14377
0
      buffer.resize(components.hash_start);
14378
0
      components.hash_start = url_components::omitted;
14379
0
    }
14380
3
    helpers::strip_trailing_spaces_from_opaque_path(*this);
14381
3
    return;
14382
3
  }
14383
14384
8.96k
  std::string new_value;
14385
8.96k
  new_value = input[0] == '#' ? input.substr(1) : input;
14386
8.96k
  helpers::remove_ascii_tab_or_newline(new_value);
14387
8.96k
  update_unencoded_base_hash(new_value);
14388
8.96k
  ADA_ASSERT_TRUE(validate());
14389
8.96k
}
14390
14391
3.05k
bool url_aggregator::set_href(const std::string_view input) {
14392
3.05k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14393
3.05k
  ada_log("url_aggregator::set_href ", input, " [", input.size(), " bytes]");
14394
3.05k
  ada::result<url_aggregator> out = ada::parse<url_aggregator>(input);
14395
3.05k
  ada_log("url_aggregator::set_href, success :", out.has_value());
14396
14397
3.05k
  if (out) {
14398
3.05k
    ada_log("url_aggregator::set_href, parsed ", out->to_string());
14399
    // TODO: Figure out why the following line puts test to never finish.
14400
3.05k
    *this = *out;
14401
3.05k
  }
14402
14403
3.05k
  return out.has_value();
14404
3.05k
}
14405
14406
25.1k
ada_really_inline bool url_aggregator::parse_host(std::string_view input) {
14407
25.1k
  ada_log("url_aggregator:parse_host \"", input, "\" [", input.size(),
14408
25.1k
          " bytes]");
14409
25.1k
  ADA_ASSERT_TRUE(validate());
14410
25.1k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14411
25.1k
  if (input.empty()) {
14412
9
    return is_valid = false;
14413
9
  }  // technically unnecessary.
14414
  // If input starts with U+005B ([), then:
14415
25.0k
  if (input[0] == '[') {
14416
    // If input does not end with U+005D (]), validation error, return failure.
14417
689
    if (input.back() != ']') {
14418
272
      return is_valid = false;
14419
272
    }
14420
417
    ada_log("parse_host ipv6");
14421
14422
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
14423
    // trailing U+005D (]) removed.
14424
417
    input.remove_prefix(1);
14425
417
    input.remove_suffix(1);
14426
417
    return parse_ipv6(input);
14427
689
  }
14428
14429
  // If isNotSpecial is true, then return the result of opaque-host parsing
14430
  // input.
14431
24.4k
  if (!is_special()) {
14432
273
    return parse_opaque_host(input);
14433
273
  }
14434
  // Let domain be the result of running UTF-8 decode without BOM on the
14435
  // percent-decoding of input. Let asciiDomain be the result of running domain
14436
  // to ASCII with domain and false. The most common case is an ASCII input, in
14437
  // which case we do not need to call the expensive 'to_ascii' if a few
14438
  // conditions are met: no '%' and no 'xn-' subsequence.
14439
14440
  // Often, the input does not contain any forbidden code points, and no upper
14441
  // case ASCII letter, then we can just copy it to the buffer. We want to
14442
  // optimize for such a common case.
14443
24.1k
  uint8_t is_forbidden_or_upper =
14444
24.1k
      unicode::contains_forbidden_domain_code_point_or_upper(input.data(),
14445
24.1k
                                                             input.size());
14446
  // Minor optimization opportunity:
14447
  // contains_forbidden_domain_code_point_or_upper could be extend to check for
14448
  // the presence of characters that cannot appear in the ipv4 address and we
14449
  // could also check whether x and n and - are present, and so we could skip
14450
  // some of the checks below. However, the gains are likely to be small, and
14451
  // the code would be more complex.
14452
24.1k
  if (is_forbidden_or_upper == 0 &&
14453
14.8k
      input.find("xn-") == std::string_view::npos) {
14454
    // fast path
14455
14.5k
    update_base_hostname(input);
14456
14.5k
    if (checkers::is_ipv4(get_hostname())) {
14457
1.53k
      ada_log("parse_host fast path ipv4");
14458
1.53k
      return parse_ipv4(get_hostname(), true);
14459
1.53k
    }
14460
13.0k
    ada_log("parse_host fast path ", get_hostname());
14461
13.0k
    return true;
14462
14.5k
  }
14463
  // We have encountered at least one forbidden code point or the input contains
14464
  // 'xn-' (case insensitive), so we need to call 'to_ascii' to perform the full
14465
  // conversion.
14466
14467
9.56k
  ada_log("parse_host calling to_ascii");
14468
9.56k
  std::optional<std::string> host = std::string(get_hostname());
14469
9.56k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
14470
9.56k
  if (!is_valid) {
14471
4.59k
    ada_log("parse_host to_ascii returns false");
14472
4.59k
    return is_valid = false;
14473
4.59k
  }
14474
4.97k
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
14475
4.97k
          " bytes]");
14476
14477
4.97k
  if (std::ranges::any_of(host.value(),
14478
4.97k
                          ada::unicode::is_forbidden_domain_code_point)) {
14479
0
    return is_valid = false;
14480
0
  }
14481
14482
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
14483
  // asciiDomain.
14484
4.97k
  if (checkers::is_ipv4(host.value())) {
14485
690
    ada_log("parse_host got ipv4 ", *host);
14486
690
    return parse_ipv4(host.value(), false);
14487
690
  }
14488
14489
4.28k
  update_base_hostname(host.value());
14490
4.28k
  ADA_ASSERT_TRUE(validate());
14491
4.28k
  return true;
14492
4.97k
}
14493
14494
template <bool override_hostname>
14495
17.9k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14496
17.9k
  ada_log("url_aggregator::set_host_or_hostname ", input);
14497
17.9k
  ADA_ASSERT_TRUE(validate());
14498
17.9k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14499
17.9k
  if (has_opaque_path) {
14500
0
    return false;
14501
0
  }
14502
14503
17.9k
  std::string previous_host(get_hostname());
14504
17.9k
  uint32_t previous_port = components.port;
14505
14506
17.9k
  size_t host_end_pos = input.find('#');
14507
17.9k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14508
17.9k
                                      ? host_end_pos
14509
17.9k
                                      : input.size());
14510
17.9k
  helpers::remove_ascii_tab_or_newline(_host);
14511
17.9k
  std::string_view new_host(_host);
14512
14513
  // If url's scheme is "file", then set state to file host state, instead of
14514
  // host state.
14515
17.9k
  if (type != ada::scheme::type::FILE) {
14516
16.4k
    std::string_view host_view(_host.data(), _host.length());
14517
16.4k
    auto [location, found_colon] =
14518
16.4k
        helpers::get_host_delimiter_location(is_special(), host_view);
14519
14520
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14521
    // Note: the 'found_colon' value is true if and only if a colon was
14522
    // encountered while not inside brackets.
14523
16.4k
    if (found_colon) {
14524
      // If buffer is the empty string, host-missing validation error, return
14525
      // failure.
14526
7.38k
      std::string_view host_buffer = host_view.substr(0, location);
14527
7.38k
      if (host_buffer.empty()) {
14528
32
        return false;
14529
32
      }
14530
14531
      // If state override is given and state override is hostname state, then
14532
      // return failure.
14533
7.35k
      if constexpr (override_hostname) {
14534
3.67k
        return false;
14535
3.67k
      }
14536
14537
      // Let host be the result of host parsing buffer with url is not special.
14538
0
      bool succeeded = parse_host(host_buffer);
14539
7.35k
      if (!succeeded) {
14540
411
        update_base_hostname(previous_host);
14541
411
        update_base_port(previous_port);
14542
411
        return false;
14543
411
      }
14544
14545
      // Set url's host to host, buffer to the empty string, and state to port
14546
      // state.
14547
6.94k
      std::string_view port_buffer = new_host.substr(location + 1);
14548
6.94k
      if (!port_buffer.empty()) {
14549
2.87k
        set_port(port_buffer);
14550
2.87k
      }
14551
6.94k
      return true;
14552
7.35k
    }
14553
    // Otherwise, if one of the following is true:
14554
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14555
    // - url is special and c is U+005C (\)
14556
9.08k
    else {
14557
      // If url is special and host_view is the empty string, host-missing
14558
      // validation error, return failure.
14559
9.08k
      if (host_view.empty() && is_special()) {
14560
1.57k
        return false;
14561
1.57k
      }
14562
14563
      // Otherwise, if state override is given, host_view is the empty string,
14564
      // and either url includes credentials or url's port is non-null, then
14565
      // return failure.
14566
7.51k
      if (host_view.empty() && (has_credentials() || has_port())) {
14567
0
        return false;
14568
0
      }
14569
14570
      // Let host be the result of host parsing host_view with url is not
14571
      // special.
14572
7.51k
      if (host_view.empty() && !is_special()) {
14573
0
        if (has_hostname()) {
14574
0
          clear_hostname();  // easy!
14575
0
        } else if (has_dash_dot()) {
14576
0
          add_authority_slashes_if_needed();
14577
0
          delete_dash_dot();
14578
0
        }
14579
0
        return true;
14580
0
      }
14581
14582
7.51k
      bool succeeded = parse_host(host_view);
14583
7.51k
      if (!succeeded) {
14584
3.40k
        update_base_hostname(previous_host);
14585
3.40k
        update_base_port(previous_port);
14586
3.40k
        return false;
14587
4.11k
      } else if (has_dash_dot()) {
14588
        // Should remove dash_dot from pathname
14589
0
        delete_dash_dot();
14590
0
      }
14591
4.11k
      return true;
14592
7.51k
    }
14593
16.4k
  }
14594
14595
1.46k
  size_t location = new_host.find_first_of("/\\?");
14596
1.46k
  if (location != std::string_view::npos) {
14597
1.31k
    new_host.remove_suffix(new_host.length() - location);
14598
1.31k
  }
14599
14600
1.46k
  if (new_host.empty()) {
14601
    // Set url's host to the empty string.
14602
0
    clear_hostname();
14603
1.46k
  } else {
14604
    // Let host be the result of host parsing buffer with url is not special.
14605
1.46k
    if (!parse_host(new_host)) {
14606
1.45k
      update_base_hostname(previous_host);
14607
1.45k
      update_base_port(previous_port);
14608
1.45k
      return false;
14609
1.45k
    }
14610
14611
    // If host is "localhost", then set host to the empty string.
14612
8
    if (helpers::substring(buffer, components.host_start,
14613
8
                           components.host_end) == "localhost") {
14614
0
      clear_hostname();
14615
0
    }
14616
8
  }
14617
8
  ADA_ASSERT_TRUE(validate());
14618
8
  return true;
14619
1.46k
}
bool ada::url_aggregator::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14495
8.96k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14496
8.96k
  ada_log("url_aggregator::set_host_or_hostname ", input);
14497
8.96k
  ADA_ASSERT_TRUE(validate());
14498
8.96k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14499
8.96k
  if (has_opaque_path) {
14500
0
    return false;
14501
0
  }
14502
14503
8.96k
  std::string previous_host(get_hostname());
14504
8.96k
  uint32_t previous_port = components.port;
14505
14506
8.96k
  size_t host_end_pos = input.find('#');
14507
8.96k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14508
8.96k
                                      ? host_end_pos
14509
8.96k
                                      : input.size());
14510
8.96k
  helpers::remove_ascii_tab_or_newline(_host);
14511
8.96k
  std::string_view new_host(_host);
14512
14513
  // If url's scheme is "file", then set state to file host state, instead of
14514
  // host state.
14515
8.96k
  if (type != ada::scheme::type::FILE) {
14516
8.23k
    std::string_view host_view(_host.data(), _host.length());
14517
8.23k
    auto [location, found_colon] =
14518
8.23k
        helpers::get_host_delimiter_location(is_special(), host_view);
14519
14520
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14521
    // Note: the 'found_colon' value is true if and only if a colon was
14522
    // encountered while not inside brackets.
14523
8.23k
    if (found_colon) {
14524
      // If buffer is the empty string, host-missing validation error, return
14525
      // failure.
14526
3.69k
      std::string_view host_buffer = host_view.substr(0, location);
14527
3.69k
      if (host_buffer.empty()) {
14528
16
        return false;
14529
16
      }
14530
14531
      // If state override is given and state override is hostname state, then
14532
      // return failure.
14533
      if constexpr (override_hostname) {
14534
        return false;
14535
      }
14536
14537
      // Let host be the result of host parsing buffer with url is not special.
14538
3.67k
      bool succeeded = parse_host(host_buffer);
14539
3.67k
      if (!succeeded) {
14540
411
        update_base_hostname(previous_host);
14541
411
        update_base_port(previous_port);
14542
411
        return false;
14543
411
      }
14544
14545
      // Set url's host to host, buffer to the empty string, and state to port
14546
      // state.
14547
3.26k
      std::string_view port_buffer = new_host.substr(location + 1);
14548
3.26k
      if (!port_buffer.empty()) {
14549
2.87k
        set_port(port_buffer);
14550
2.87k
      }
14551
3.26k
      return true;
14552
3.67k
    }
14553
    // Otherwise, if one of the following is true:
14554
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14555
    // - url is special and c is U+005C (\)
14556
4.54k
    else {
14557
      // If url is special and host_view is the empty string, host-missing
14558
      // validation error, return failure.
14559
4.54k
      if (host_view.empty() && is_special()) {
14560
786
        return false;
14561
786
      }
14562
14563
      // Otherwise, if state override is given, host_view is the empty string,
14564
      // and either url includes credentials or url's port is non-null, then
14565
      // return failure.
14566
3.75k
      if (host_view.empty() && (has_credentials() || has_port())) {
14567
0
        return false;
14568
0
      }
14569
14570
      // Let host be the result of host parsing host_view with url is not
14571
      // special.
14572
3.75k
      if (host_view.empty() && !is_special()) {
14573
0
        if (has_hostname()) {
14574
0
          clear_hostname();  // easy!
14575
0
        } else if (has_dash_dot()) {
14576
0
          add_authority_slashes_if_needed();
14577
0
          delete_dash_dot();
14578
0
        }
14579
0
        return true;
14580
0
      }
14581
14582
3.75k
      bool succeeded = parse_host(host_view);
14583
3.75k
      if (!succeeded) {
14584
1.70k
        update_base_hostname(previous_host);
14585
1.70k
        update_base_port(previous_port);
14586
1.70k
        return false;
14587
2.05k
      } else if (has_dash_dot()) {
14588
        // Should remove dash_dot from pathname
14589
0
        delete_dash_dot();
14590
0
      }
14591
2.05k
      return true;
14592
3.75k
    }
14593
8.23k
  }
14594
14595
731
  size_t location = new_host.find_first_of("/\\?");
14596
731
  if (location != std::string_view::npos) {
14597
658
    new_host.remove_suffix(new_host.length() - location);
14598
658
  }
14599
14600
731
  if (new_host.empty()) {
14601
    // Set url's host to the empty string.
14602
0
    clear_hostname();
14603
731
  } else {
14604
    // Let host be the result of host parsing buffer with url is not special.
14605
731
    if (!parse_host(new_host)) {
14606
727
      update_base_hostname(previous_host);
14607
727
      update_base_port(previous_port);
14608
727
      return false;
14609
727
    }
14610
14611
    // If host is "localhost", then set host to the empty string.
14612
4
    if (helpers::substring(buffer, components.host_start,
14613
4
                           components.host_end) == "localhost") {
14614
0
      clear_hostname();
14615
0
    }
14616
4
  }
14617
4
  ADA_ASSERT_TRUE(validate());
14618
4
  return true;
14619
731
}
bool ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14495
8.96k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14496
8.96k
  ada_log("url_aggregator::set_host_or_hostname ", input);
14497
8.96k
  ADA_ASSERT_TRUE(validate());
14498
8.96k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14499
8.96k
  if (has_opaque_path) {
14500
0
    return false;
14501
0
  }
14502
14503
8.96k
  std::string previous_host(get_hostname());
14504
8.96k
  uint32_t previous_port = components.port;
14505
14506
8.96k
  size_t host_end_pos = input.find('#');
14507
8.96k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14508
8.96k
                                      ? host_end_pos
14509
8.96k
                                      : input.size());
14510
8.96k
  helpers::remove_ascii_tab_or_newline(_host);
14511
8.96k
  std::string_view new_host(_host);
14512
14513
  // If url's scheme is "file", then set state to file host state, instead of
14514
  // host state.
14515
8.96k
  if (type != ada::scheme::type::FILE) {
14516
8.23k
    std::string_view host_view(_host.data(), _host.length());
14517
8.23k
    auto [location, found_colon] =
14518
8.23k
        helpers::get_host_delimiter_location(is_special(), host_view);
14519
14520
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14521
    // Note: the 'found_colon' value is true if and only if a colon was
14522
    // encountered while not inside brackets.
14523
8.23k
    if (found_colon) {
14524
      // If buffer is the empty string, host-missing validation error, return
14525
      // failure.
14526
3.69k
      std::string_view host_buffer = host_view.substr(0, location);
14527
3.69k
      if (host_buffer.empty()) {
14528
16
        return false;
14529
16
      }
14530
14531
      // If state override is given and state override is hostname state, then
14532
      // return failure.
14533
3.67k
      if constexpr (override_hostname) {
14534
3.67k
        return false;
14535
3.67k
      }
14536
14537
      // Let host be the result of host parsing buffer with url is not special.
14538
0
      bool succeeded = parse_host(host_buffer);
14539
3.67k
      if (!succeeded) {
14540
0
        update_base_hostname(previous_host);
14541
0
        update_base_port(previous_port);
14542
0
        return false;
14543
0
      }
14544
14545
      // Set url's host to host, buffer to the empty string, and state to port
14546
      // state.
14547
3.67k
      std::string_view port_buffer = new_host.substr(location + 1);
14548
3.67k
      if (!port_buffer.empty()) {
14549
0
        set_port(port_buffer);
14550
0
      }
14551
3.67k
      return true;
14552
3.67k
    }
14553
    // Otherwise, if one of the following is true:
14554
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14555
    // - url is special and c is U+005C (\)
14556
4.54k
    else {
14557
      // If url is special and host_view is the empty string, host-missing
14558
      // validation error, return failure.
14559
4.54k
      if (host_view.empty() && is_special()) {
14560
786
        return false;
14561
786
      }
14562
14563
      // Otherwise, if state override is given, host_view is the empty string,
14564
      // and either url includes credentials or url's port is non-null, then
14565
      // return failure.
14566
3.75k
      if (host_view.empty() && (has_credentials() || has_port())) {
14567
0
        return false;
14568
0
      }
14569
14570
      // Let host be the result of host parsing host_view with url is not
14571
      // special.
14572
3.75k
      if (host_view.empty() && !is_special()) {
14573
0
        if (has_hostname()) {
14574
0
          clear_hostname();  // easy!
14575
0
        } else if (has_dash_dot()) {
14576
0
          add_authority_slashes_if_needed();
14577
0
          delete_dash_dot();
14578
0
        }
14579
0
        return true;
14580
0
      }
14581
14582
3.75k
      bool succeeded = parse_host(host_view);
14583
3.75k
      if (!succeeded) {
14584
1.70k
        update_base_hostname(previous_host);
14585
1.70k
        update_base_port(previous_port);
14586
1.70k
        return false;
14587
2.05k
      } else if (has_dash_dot()) {
14588
        // Should remove dash_dot from pathname
14589
0
        delete_dash_dot();
14590
0
      }
14591
2.05k
      return true;
14592
3.75k
    }
14593
8.23k
  }
14594
14595
731
  size_t location = new_host.find_first_of("/\\?");
14596
731
  if (location != std::string_view::npos) {
14597
658
    new_host.remove_suffix(new_host.length() - location);
14598
658
  }
14599
14600
731
  if (new_host.empty()) {
14601
    // Set url's host to the empty string.
14602
0
    clear_hostname();
14603
731
  } else {
14604
    // Let host be the result of host parsing buffer with url is not special.
14605
731
    if (!parse_host(new_host)) {
14606
727
      update_base_hostname(previous_host);
14607
727
      update_base_port(previous_port);
14608
727
      return false;
14609
727
    }
14610
14611
    // If host is "localhost", then set host to the empty string.
14612
4
    if (helpers::substring(buffer, components.host_start,
14613
4
                           components.host_end) == "localhost") {
14614
0
      clear_hostname();
14615
0
    }
14616
4
  }
14617
4
  ADA_ASSERT_TRUE(validate());
14618
4
  return true;
14619
731
}
14620
14621
8.96k
bool url_aggregator::set_host(const std::string_view input) {
14622
8.96k
  ada_log("url_aggregator::set_host '", input, "'");
14623
8.96k
  ADA_ASSERT_TRUE(validate());
14624
8.96k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14625
8.96k
  return set_host_or_hostname<false>(input);
14626
8.96k
}
14627
14628
8.96k
bool url_aggregator::set_hostname(const std::string_view input) {
14629
8.96k
  ada_log("url_aggregator::set_hostname '", input, "'");
14630
8.96k
  ADA_ASSERT_TRUE(validate());
14631
8.96k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14632
8.96k
  return set_host_or_hostname<true>(input);
14633
8.96k
}
14634
14635
12.0k
[[nodiscard]] std::string url_aggregator::get_origin() const noexcept {
14636
12.0k
  ada_log("url_aggregator::get_origin");
14637
12.0k
  if (is_special()) {
14638
    // Return a new opaque origin.
14639
10.6k
    if (type == scheme::FILE) {
14640
1.36k
      return "null";
14641
1.36k
    }
14642
14643
9.26k
    return helpers::concat(get_protocol(), "//", get_host());
14644
10.6k
  }
14645
14646
1.39k
  if (get_protocol() == "blob:") {
14647
493
    std::string_view path = get_pathname();
14648
493
    if (!path.empty()) {
14649
483
      auto out = ada::parse<ada::url_aggregator>(path);
14650
483
      if (out && (out->type == scheme::HTTP || out->type == scheme::HTTPS)) {
14651
        // If pathURL's scheme is not "http" and not "https", then return a
14652
        // new opaque origin.
14653
19
        return helpers::concat(out->get_protocol(), "//", out->get_host());
14654
19
      }
14655
483
    }
14656
493
  }
14657
14658
  // Return a new opaque origin.
14659
1.38k
  return "null";
14660
1.39k
}
14661
14662
[[nodiscard]] std::string_view url_aggregator::get_username() const noexcept
14663
15.4k
    ada_lifetime_bound {
14664
15.4k
  ada_log("url_aggregator::get_username");
14665
15.4k
  if (has_non_empty_username()) {
14666
14.7k
    return helpers::substring(buffer, components.protocol_end + 2,
14667
14.7k
                              components.username_end);
14668
14.7k
  }
14669
734
  return "";
14670
15.4k
}
14671
14672
[[nodiscard]] std::string_view url_aggregator::get_password() const noexcept
14673
15.4k
    ada_lifetime_bound {
14674
15.4k
  ada_log("url_aggregator::get_password");
14675
15.4k
  if (has_non_empty_password()) {
14676
14.7k
    return helpers::substring(buffer, components.username_end + 1,
14677
14.7k
                              components.host_start);
14678
14.7k
  }
14679
734
  return "";
14680
15.4k
}
14681
14682
[[nodiscard]] std::string_view url_aggregator::get_port() const noexcept
14683
8.96k
    ada_lifetime_bound {
14684
8.96k
  ada_log("url_aggregator::get_port");
14685
8.96k
  if (components.port == url_components::omitted) {
14686
8.08k
    return "";
14687
8.08k
  }
14688
880
  return helpers::substring(buffer, components.host_end + 1,
14689
880
                            components.pathname_start);
14690
8.96k
}
14691
14692
[[nodiscard]] std::string_view url_aggregator::get_hash() const noexcept
14693
15.4k
    ada_lifetime_bound {
14694
15.4k
  ada_log("url_aggregator::get_hash");
14695
  // If this's URL's fragment is either null or the empty string, then return
14696
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
14697
15.4k
  if (components.hash_start == url_components::omitted) {
14698
3
    return "";
14699
3
  }
14700
15.4k
  if (buffer.size() - components.hash_start <= 1) {
14701
56
    return "";
14702
56
  }
14703
15.4k
  return helpers::substring(buffer, components.hash_start);
14704
15.4k
}
14705
14706
[[nodiscard]] std::string_view url_aggregator::get_host() const noexcept
14707
24.7k
    ada_lifetime_bound {
14708
24.7k
  ada_log("url_aggregator::get_host");
14709
  // Technically, we should check if there is a hostname, but
14710
  // the code below works even if there isn't.
14711
  // if(!has_hostname()) { return ""; }
14712
24.7k
  size_t start = components.host_start;
14713
24.7k
  if (components.host_end > components.host_start &&
14714
24.7k
      buffer[components.host_start] == '@') {
14715
23.2k
    start++;
14716
23.2k
  }
14717
  // if we have an empty host, then the space between components.host_end and
14718
  // components.pathname_start may be occupied by /.
14719
24.7k
  if (start == components.host_end) {
14720
0
    return {};
14721
0
  }
14722
24.7k
  return helpers::substring(buffer, start, components.pathname_start);
14723
24.7k
}
14724
14725
[[nodiscard]] std::string_view url_aggregator::get_hostname() const noexcept
14726
53.0k
    ada_lifetime_bound {
14727
53.0k
  ada_log("url_aggregator::get_hostname");
14728
  // Technically, we should check if there is a hostname, but
14729
  // the code below works even if there isn't.
14730
  // if(!has_hostname()) { return ""; }
14731
53.0k
  size_t start = components.host_start;
14732
  // So host_start is not where the host begins.
14733
53.0k
  if (components.host_end > components.host_start &&
14734
51.6k
      buffer[components.host_start] == '@') {
14735
37.1k
    start++;
14736
37.1k
  }
14737
53.0k
  return helpers::substring(buffer, start, components.host_end);
14738
53.0k
}
14739
14740
[[nodiscard]] std::string_view url_aggregator::get_search() const noexcept
14741
15.4k
    ada_lifetime_bound {
14742
15.4k
  ada_log("url_aggregator::get_search");
14743
  // If this's URL's query is either null or the empty string, then return the
14744
  // empty string. Return U+003F (?), followed by this's URL's query.
14745
15.4k
  if (components.search_start == url_components::omitted) {
14746
3
    return "";
14747
3
  }
14748
15.4k
  auto ending_index = uint32_t(buffer.size());
14749
15.4k
  if (components.hash_start != url_components::omitted) {
14750
15.4k
    ending_index = components.hash_start;
14751
15.4k
  }
14752
15.4k
  if (ending_index - components.search_start <= 1) {
14753
54
    return "";
14754
54
  }
14755
15.4k
  return helpers::substring(buffer, components.search_start, ending_index);
14756
15.4k
}
14757
14758
[[nodiscard]] std::string_view url_aggregator::get_protocol() const noexcept
14759
29.2k
    ada_lifetime_bound {
14760
29.2k
  ada_log("url_aggregator::get_protocol");
14761
29.2k
  return helpers::substring(buffer, 0, components.protocol_end);
14762
29.2k
}
14763
14764
8.96k
[[nodiscard]] std::string ada::url_aggregator::to_string() const {
14765
8.96k
  ada_log("url_aggregator::to_string buffer:", buffer, " [", buffer.size(),
14766
8.96k
          " bytes]");
14767
8.96k
  if (!is_valid) {
14768
2.46k
    return "null";
14769
2.46k
  }
14770
14771
6.50k
  std::string answer;
14772
6.50k
  auto back = std::back_insert_iterator(answer);
14773
6.50k
  answer.append("{\n");
14774
14775
6.50k
  answer.append("\t\"buffer\":\"");
14776
6.50k
  helpers::encode_json(buffer, back);
14777
6.50k
  answer.append("\",\n");
14778
14779
6.50k
  answer.append("\t\"protocol\":\"");
14780
6.50k
  helpers::encode_json(get_protocol(), back);
14781
6.50k
  answer.append("\",\n");
14782
14783
6.50k
  if (has_credentials()) {
14784
6.49k
    answer.append("\t\"username\":\"");
14785
6.49k
    helpers::encode_json(get_username(), back);
14786
6.49k
    answer.append("\",\n");
14787
6.49k
    answer.append("\t\"password\":\"");
14788
6.49k
    helpers::encode_json(get_password(), back);
14789
6.49k
    answer.append("\",\n");
14790
6.49k
  }
14791
14792
6.50k
  answer.append("\t\"host\":\"");
14793
6.50k
  helpers::encode_json(get_host(), back);
14794
6.50k
  answer.append("\",\n");
14795
14796
6.50k
  answer.append("\t\"path\":\"");
14797
6.50k
  helpers::encode_json(get_pathname(), back);
14798
6.50k
  answer.append("\",\n");
14799
6.50k
  answer.append("\t\"opaque path\":");
14800
6.50k
  answer.append((has_opaque_path ? "true" : "false"));
14801
6.50k
  answer.append(",\n");
14802
14803
6.50k
  if (components.search_start != url_components::omitted) {
14804
6.49k
    answer.append("\t\"query\":\"");
14805
6.49k
    helpers::encode_json(get_search(), back);
14806
6.49k
    answer.append("\",\n");
14807
6.49k
  }
14808
6.50k
  if (components.hash_start != url_components::omitted) {
14809
6.49k
    answer.append("\t\"fragment\":\"");
14810
6.49k
    helpers::encode_json(get_hash(), back);
14811
6.49k
    answer.append("\",\n");
14812
6.49k
  }
14813
14814
52.0k
  auto convert_offset_to_string = [](uint32_t offset) -> std::string {
14815
52.0k
    if (offset == url_components::omitted) {
14816
5.62k
      return "null";
14817
46.3k
    } else {
14818
46.3k
      return std::to_string(offset);
14819
46.3k
    }
14820
52.0k
  };
14821
14822
6.50k
  answer.append("\t\"protocol_end\":");
14823
6.50k
  answer.append(convert_offset_to_string(components.protocol_end));
14824
6.50k
  answer.append(",\n");
14825
14826
6.50k
  answer.append("\t\"username_end\":");
14827
6.50k
  answer.append(convert_offset_to_string(components.username_end));
14828
6.50k
  answer.append(",\n");
14829
14830
6.50k
  answer.append("\t\"host_start\":");
14831
6.50k
  answer.append(convert_offset_to_string(components.host_start));
14832
6.50k
  answer.append(",\n");
14833
14834
6.50k
  answer.append("\t\"host_end\":");
14835
6.50k
  answer.append(convert_offset_to_string(components.host_end));
14836
6.50k
  answer.append(",\n");
14837
14838
6.50k
  answer.append("\t\"port\":");
14839
6.50k
  answer.append(convert_offset_to_string(components.port));
14840
6.50k
  answer.append(",\n");
14841
14842
6.50k
  answer.append("\t\"pathname_start\":");
14843
6.50k
  answer.append(convert_offset_to_string(components.pathname_start));
14844
6.50k
  answer.append(",\n");
14845
14846
6.50k
  answer.append("\t\"search_start\":");
14847
6.50k
  answer.append(convert_offset_to_string(components.search_start));
14848
6.50k
  answer.append(",\n");
14849
14850
6.50k
  answer.append("\t\"hash_start\":");
14851
6.50k
  answer.append(convert_offset_to_string(components.hash_start));
14852
6.50k
  answer.append("\n}");
14853
14854
6.50k
  return answer;
14855
8.96k
}
14856
14857
0
[[nodiscard]] bool url_aggregator::has_valid_domain() const noexcept {
14858
0
  if (components.host_start == components.host_end) {
14859
0
    return false;
14860
0
  }
14861
0
  return checkers::verify_dns_length(get_hostname());
14862
0
}
14863
14864
2.22k
bool url_aggregator::parse_ipv4(std::string_view input, bool in_place) {
14865
2.22k
  ada_log("parse_ipv4 ", input, " [", input.size(),
14866
2.22k
          " bytes], overlaps with buffer: ",
14867
2.22k
          helpers::overlaps(input, buffer) ? "yes" : "no");
14868
2.22k
  ADA_ASSERT_TRUE(validate());
14869
2.22k
  const bool trailing_dot = (input.back() == '.');
14870
2.22k
  if (trailing_dot) {
14871
29
    input.remove_suffix(1);
14872
29
  }
14873
2.22k
  size_t digit_count{0};
14874
2.22k
  int pure_decimal_count = 0;  // entries that are decimal
14875
2.22k
  uint64_t ipv4{0};
14876
  // we could unroll for better performance?
14877
2.66k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
14878
2.64k
    uint32_t
14879
2.64k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
14880
2.64k
    bool is_hex = checkers::has_hex_prefix(input);
14881
2.64k
    if (is_hex && ((input.length() == 2) ||
14882
899
                   ((input.length() > 2) && (input[2] == '.')))) {
14883
      // special case
14884
53
      segment_result = 0;
14885
53
      input.remove_prefix(2);
14886
2.59k
    } else {
14887
2.59k
      std::from_chars_result r{};
14888
2.59k
      if (is_hex) {
14889
879
        ada_log("parse_ipv4 trying to parse hex number");
14890
879
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
14891
879
                            segment_result, 16);
14892
1.71k
      } else if ((input.length() >= 2) && input[0] == '0' &&
14893
497
                 checkers::is_digit(input[1])) {
14894
404
        ada_log("parse_ipv4 trying to parse octal number");
14895
404
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
14896
404
                            segment_result, 8);
14897
1.30k
      } else {
14898
1.30k
        ada_log("parse_ipv4 trying to parse decimal number");
14899
1.30k
        pure_decimal_count++;
14900
1.30k
        r = std::from_chars(input.data(), input.data() + input.size(),
14901
1.30k
                            segment_result, 10);
14902
1.30k
      }
14903
2.59k
      if (r.ec != std::errc()) {
14904
450
        ada_log("parse_ipv4 parsing failed");
14905
450
        return is_valid = false;
14906
450
      }
14907
2.14k
      ada_log("parse_ipv4 parsed ", segment_result);
14908
2.14k
      input.remove_prefix(r.ptr - input.data());
14909
2.14k
    }
14910
2.19k
    if (input.empty()) {
14911
      // We have the last value.
14912
      // At this stage, ipv4 contains digit_count*8 bits.
14913
      // So we have 32-digit_count*8 bits left.
14914
1.57k
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
14915
47
        return is_valid = false;
14916
47
      }
14917
1.52k
      ipv4 <<= (32 - digit_count * 8);
14918
1.52k
      ipv4 |= segment_result;
14919
1.52k
      goto final;
14920
1.57k
    } else {
14921
      // There is more, so that the value must no be larger than 255
14922
      // and we must have a '.'.
14923
622
      if ((segment_result > 255) || (input[0] != '.')) {
14924
183
        return is_valid = false;
14925
183
      }
14926
439
      ipv4 <<= 8;
14927
439
      ipv4 |= segment_result;
14928
439
      input.remove_prefix(1);  // remove '.'
14929
439
    }
14930
2.19k
  }
14931
20
  if ((digit_count != 4) || (!input.empty())) {
14932
20
    ada_log("parse_ipv4 found invalid (more than 4 numbers or empty) ");
14933
20
    return is_valid = false;
14934
20
  }
14935
1.52k
final:
14936
1.52k
  ada_log("url_aggregator::parse_ipv4 completed ", get_href(),
14937
1.52k
          " host: ", get_host());
14938
14939
  // We could also check r.ptr to see where the parsing ended.
14940
1.52k
  if (in_place && pure_decimal_count == 4 && !trailing_dot) {
14941
9
    ada_log(
14942
9
        "url_aggregator::parse_ipv4 completed and was already correct in the "
14943
9
        "buffer");
14944
    // The original input was already all decimal and we validated it. So we
14945
    // don't need to do anything.
14946
1.51k
  } else {
14947
1.51k
    ada_log("url_aggregator::parse_ipv4 completed and we need to update it");
14948
    // Optimization opportunity: Get rid of unnecessary string return in ipv4
14949
    // serializer.
14950
    // TODO: This is likely a bug because it goes back update_base_hostname, not
14951
    // what we want to do.
14952
1.51k
    update_base_hostname(
14953
1.51k
        ada::serializers::ipv4(ipv4));  // We have to reserialize the address.
14954
1.51k
  }
14955
1.52k
  host_type = IPV4;
14956
1.52k
  ADA_ASSERT_TRUE(validate());
14957
1.52k
  return true;
14958
20
}
14959
14960
417
bool url_aggregator::parse_ipv6(std::string_view input) {
14961
  // TODO: Implement in_place optimization: we know that input points
14962
  // in the buffer, so we can just check whether the buffer is already
14963
  // well formatted.
14964
  // TODO: Find a way to merge parse_ipv6 with url.cpp implementation.
14965
417
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
14966
417
  ADA_ASSERT_TRUE(validate());
14967
417
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14968
417
  if (input.empty()) {
14969
25
    return is_valid = false;
14970
25
  }
14971
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
14972
392
  std::array<uint16_t, 8> address{};
14973
14974
  // Let pieceIndex be 0.
14975
392
  int piece_index = 0;
14976
14977
  // Let compress be null.
14978
392
  std::optional<int> compress{};
14979
14980
  // Let pointer be a pointer for input.
14981
392
  std::string_view::iterator pointer = input.begin();
14982
14983
  // If c is U+003A (:), then:
14984
392
  if (input[0] == ':') {
14985
    // If remaining does not start with U+003A (:), validation error, return
14986
    // failure.
14987
88
    if (input.size() == 1 || input[1] != ':') {
14988
19
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
14989
19
      return is_valid = false;
14990
19
    }
14991
14992
    // Increase pointer by 2.
14993
69
    pointer += 2;
14994
14995
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
14996
69
    compress = ++piece_index;
14997
69
  }
14998
14999
  // While c is not the EOF code point:
15000
914
  while (pointer != input.end()) {
15001
    // If pieceIndex is 8, validation error, return failure.
15002
752
    if (piece_index == 8) {
15003
5
      ada_log("parse_ipv6 piece_index == 8");
15004
5
      return is_valid = false;
15005
5
    }
15006
15007
    // If c is U+003A (:), then:
15008
747
    if (*pointer == ':') {
15009
      // If compress is non-null, validation error, return failure.
15010
55
      if (compress.has_value()) {
15011
4
        ada_log("parse_ipv6 compress is non-null");
15012
4
        return is_valid = false;
15013
4
      }
15014
15015
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
15016
      // then continue.
15017
51
      pointer++;
15018
51
      compress = ++piece_index;
15019
51
      continue;
15020
55
    }
15021
15022
    // Let value and length be 0.
15023
692
    uint16_t value = 0, length = 0;
15024
15025
    // While length is less than 4 and c is an ASCII hex digit,
15026
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
15027
    // increase pointer and length by 1.
15028
1.75k
    while (length < 4 && pointer != input.end() &&
15029
1.57k
           unicode::is_ascii_hex_digit(*pointer)) {
15030
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
15031
1.06k
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
15032
1.06k
      pointer++;
15033
1.06k
      length++;
15034
1.06k
    }
15035
15036
    // If c is U+002E (.), then:
15037
692
    if (pointer != input.end() && *pointer == '.') {
15038
      // If length is 0, validation error, return failure.
15039
87
      if (length == 0) {
15040
3
        ada_log("parse_ipv6 length is 0");
15041
3
        return is_valid = false;
15042
3
      }
15043
15044
      // Decrease pointer by length.
15045
84
      pointer -= length;
15046
15047
      // If pieceIndex is greater than 6, validation error, return failure.
15048
84
      if (piece_index > 6) {
15049
3
        ada_log("parse_ipv6 piece_index > 6");
15050
3
        return is_valid = false;
15051
3
      }
15052
15053
      // Let numbersSeen be 0.
15054
81
      int numbers_seen = 0;
15055
15056
      // While c is not the EOF code point:
15057
202
      while (pointer != input.end()) {
15058
        // Let ipv4Piece be null.
15059
188
        std::optional<uint16_t> ipv4_piece{};
15060
15061
        // If numbersSeen is greater than 0, then:
15062
188
        if (numbers_seen > 0) {
15063
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
15064
          // pointer by 1.
15065
107
          if (*pointer == '.' && numbers_seen < 4) {
15066
83
            pointer++;
15067
83
          } else {
15068
            // Otherwise, validation error, return failure.
15069
24
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
15070
24
            return is_valid = false;
15071
24
          }
15072
107
        }
15073
15074
        // If c is not an ASCII digit, validation error, return failure.
15075
164
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
15076
28
          ada_log(
15077
28
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
15078
28
              "failure");
15079
28
          return is_valid = false;
15080
28
        }
15081
15082
        // While c is an ASCII digit:
15083
343
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
15084
          // Let number be c interpreted as decimal number.
15085
222
          int number = *pointer - '0';
15086
15087
          // If ipv4Piece is null, then set ipv4Piece to number.
15088
222
          if (!ipv4_piece.has_value()) {
15089
136
            ipv4_piece = number;
15090
136
          }
15091
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
15092
86
          else if (ipv4_piece == 0) {
15093
3
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
15094
3
            return is_valid = false;
15095
3
          }
15096
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
15097
83
          else {
15098
83
            ipv4_piece = *ipv4_piece * 10 + number;
15099
83
          }
15100
15101
          // If ipv4Piece is greater than 255, validation error, return failure.
15102
219
          if (ipv4_piece > 255) {
15103
12
            ada_log("parse_ipv6 ipv4_piece > 255");
15104
12
            return is_valid = false;
15105
12
          }
15106
15107
          // Increase pointer by 1.
15108
207
          pointer++;
15109
207
        }
15110
15111
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
15112
        // ipv4Piece.
15113
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
15114
121
        address[piece_index] =
15115
121
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
15116
15117
        // Increase numbersSeen by 1.
15118
121
        numbers_seen++;
15119
15120
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
15121
121
        if (numbers_seen == 2 || numbers_seen == 4) {
15122
42
          piece_index++;
15123
42
        }
15124
121
      }
15125
15126
      // If numbersSeen is not 4, validation error, return failure.
15127
14
      if (numbers_seen != 4) {
15128
11
        return is_valid = false;
15129
11
      }
15130
15131
      // Break.
15132
3
      break;
15133
14
    }
15134
    // Otherwise, if c is U+003A (:):
15135
605
    else if ((pointer != input.end()) && (*pointer == ':')) {
15136
      // Increase pointer by 1.
15137
377
      pointer++;
15138
15139
      // If c is the EOF code point, validation error, return failure.
15140
377
      if (pointer == input.end()) {
15141
4
        ada_log(
15142
4
            "parse_ipv6 If c is the EOF code point, validation error, return "
15143
4
            "failure");
15144
4
        return is_valid = false;
15145
4
      }
15146
377
    }
15147
    // Otherwise, if c is not the EOF code point, validation error, return
15148
    // failure.
15149
228
    else if (pointer != input.end()) {
15150
111
      ada_log(
15151
111
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
15152
111
          "error, return failure");
15153
111
      return is_valid = false;
15154
111
    }
15155
15156
    // Set address[pieceIndex] to value.
15157
490
    address[piece_index] = value;
15158
15159
    // Increase pieceIndex by 1.
15160
490
    piece_index++;
15161
490
  }
15162
15163
  // If compress is non-null, then:
15164
165
  if (compress.has_value()) {
15165
    // Let swaps be pieceIndex - compress.
15166
108
    int swaps = piece_index - *compress;
15167
15168
    // Set pieceIndex to 7.
15169
108
    piece_index = 7;
15170
15171
    // While pieceIndex is not 0 and swaps is greater than 0,
15172
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
15173
    // decrease both pieceIndex and swaps by 1.
15174
237
    while (piece_index != 0 && swaps > 0) {
15175
129
      std::swap(address[piece_index], address[*compress + swaps - 1]);
15176
129
      piece_index--;
15177
129
      swaps--;
15178
129
    }
15179
108
  }
15180
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
15181
  // return failure.
15182
57
  else if (piece_index != 8) {
15183
49
    ada_log(
15184
49
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
15185
49
        "error, return failure");
15186
49
    return is_valid = false;
15187
49
  }
15188
  // TODO: Optimization opportunity: Get rid of unnecessary string creation.
15189
  // TODO: This is likely a bug because it goes back update_base_hostname, not
15190
  // what we want to do.
15191
116
  update_base_hostname(ada::serializers::ipv6(address));
15192
116
  ada_log("parse_ipv6 ", get_hostname());
15193
116
  ADA_ASSERT_TRUE(validate());
15194
116
  host_type = IPV6;
15195
116
  return true;
15196
165
}
15197
15198
273
bool url_aggregator::parse_opaque_host(std::string_view input) {
15199
273
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
15200
273
  ADA_ASSERT_TRUE(validate());
15201
273
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15202
273
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
15203
23
    return is_valid = false;
15204
23
  }
15205
15206
  // Return the result of running UTF-8 percent-encode on input using the C0
15207
  // control percent-encode set.
15208
250
  size_t idx = ada::unicode::percent_encode_index(
15209
250
      input, character_sets::C0_CONTROL_PERCENT_ENCODE);
15210
250
  if (idx == input.size()) {
15211
141
    update_base_hostname(input);
15212
141
  } else {
15213
    // We only create a temporary string if we need to.
15214
109
    update_base_hostname(ada::unicode::percent_encode(
15215
109
        input, character_sets::C0_CONTROL_PERCENT_ENCODE, idx));
15216
109
  }
15217
250
  ADA_ASSERT_TRUE(validate());
15218
250
  return true;
15219
273
}
15220
15221
8.96k
[[nodiscard]] std::string url_aggregator::to_diagram() const {
15222
8.96k
  if (!is_valid) {
15223
2.46k
    return "invalid";
15224
2.46k
  }
15225
6.50k
  std::string answer;
15226
6.50k
  answer.append(buffer);
15227
6.50k
  answer.append(" [");
15228
6.50k
  answer.append(std::to_string(buffer.size()));
15229
6.50k
  answer.append(" bytes]");
15230
6.50k
  answer.append("\n");
15231
  // first line
15232
6.50k
  std::string line1;
15233
6.50k
  line1.resize(buffer.size(), ' ');
15234
6.50k
  if (components.hash_start != url_components::omitted) {
15235
6.49k
    line1[components.hash_start] = '|';
15236
6.49k
  }
15237
6.50k
  if (components.search_start != url_components::omitted) {
15238
6.49k
    line1[components.search_start] = '|';
15239
6.49k
  }
15240
6.50k
  if (components.pathname_start != buffer.size()) {
15241
6.50k
    line1[components.pathname_start] = '|';
15242
6.50k
  }
15243
6.50k
  if (components.host_end != buffer.size()) {
15244
6.50k
    line1[components.host_end] = '|';
15245
6.50k
  }
15246
6.50k
  if (components.host_start != buffer.size()) {
15247
6.50k
    line1[components.host_start] = '|';
15248
6.50k
  }
15249
6.50k
  if (components.username_end != buffer.size()) {
15250
6.50k
    line1[components.username_end] = '|';
15251
6.50k
  }
15252
6.50k
  if (components.protocol_end != buffer.size()) {
15253
6.50k
    line1[components.protocol_end] = '|';
15254
6.50k
  }
15255
6.50k
  answer.append(line1);
15256
6.50k
  answer.append("\n");
15257
15258
6.50k
  std::string line2 = line1;
15259
6.50k
  if (components.hash_start != url_components::omitted) {
15260
6.49k
    line2[components.hash_start] = '`';
15261
6.49k
    line1[components.hash_start] = ' ';
15262
15263
459k
    for (size_t i = components.hash_start + 1; i < line2.size(); i++) {
15264
453k
      line2[i] = '-';
15265
453k
    }
15266
6.49k
    line2.append(" hash_start");
15267
6.49k
    answer.append(line2);
15268
6.49k
    answer.append("\n");
15269
6.49k
  }
15270
15271
6.50k
  std::string line3 = line1;
15272
6.50k
  if (components.search_start != url_components::omitted) {
15273
6.49k
    line3[components.search_start] = '`';
15274
6.49k
    line1[components.search_start] = ' ';
15275
15276
921k
    for (size_t i = components.search_start + 1; i < line3.size(); i++) {
15277
915k
      line3[i] = '-';
15278
915k
    }
15279
6.49k
    line3.append(" search_start ");
15280
6.49k
    line3.append(std::to_string(components.search_start));
15281
6.49k
    answer.append(line3);
15282
6.49k
    answer.append("\n");
15283
6.49k
  }
15284
15285
6.50k
  std::string line4 = line1;
15286
6.50k
  if (components.pathname_start != buffer.size()) {
15287
6.50k
    line4[components.pathname_start] = '`';
15288
6.50k
    line1[components.pathname_start] = ' ';
15289
1.35M
    for (size_t i = components.pathname_start + 1; i < line4.size(); i++) {
15290
1.34M
      line4[i] = '-';
15291
1.34M
    }
15292
6.50k
    line4.append(" pathname_start ");
15293
6.50k
    line4.append(std::to_string(components.pathname_start));
15294
6.50k
    answer.append(line4);
15295
6.50k
    answer.append("\n");
15296
6.50k
  }
15297
15298
6.50k
  std::string line5 = line1;
15299
6.50k
  if (components.host_end != buffer.size()) {
15300
6.50k
    line5[components.host_end] = '`';
15301
6.50k
    line1[components.host_end] = ' ';
15302
15303
1.35M
    for (size_t i = components.host_end + 1; i < line5.size(); i++) {
15304
1.34M
      line5[i] = '-';
15305
1.34M
    }
15306
6.50k
    line5.append(" host_end ");
15307
6.50k
    line5.append(std::to_string(components.host_end));
15308
6.50k
    answer.append(line5);
15309
6.50k
    answer.append("\n");
15310
6.50k
  }
15311
15312
6.50k
  std::string line6 = line1;
15313
6.50k
  if (components.host_start != buffer.size()) {
15314
6.50k
    line6[components.host_start] = '`';
15315
6.50k
    line1[components.host_start] = ' ';
15316
15317
1.57M
    for (size_t i = components.host_start + 1; i < line6.size(); i++) {
15318
1.56M
      line6[i] = '-';
15319
1.56M
    }
15320
6.50k
    line6.append(" host_start ");
15321
6.50k
    line6.append(std::to_string(components.host_start));
15322
6.50k
    answer.append(line6);
15323
6.50k
    answer.append("\n");
15324
6.50k
  }
15325
15326
6.50k
  std::string line7 = line1;
15327
6.50k
  if (components.username_end != buffer.size()) {
15328
6.50k
    line7[components.username_end] = '`';
15329
6.50k
    line1[components.username_end] = ' ';
15330
15331
2.11M
    for (size_t i = components.username_end + 1; i < line7.size(); i++) {
15332
2.10M
      line7[i] = '-';
15333
2.10M
    }
15334
6.50k
    line7.append(" username_end ");
15335
6.50k
    line7.append(std::to_string(components.username_end));
15336
6.50k
    answer.append(line7);
15337
6.50k
    answer.append("\n");
15338
6.50k
  }
15339
15340
6.50k
  std::string line8 = line1;
15341
6.50k
  if (components.protocol_end != buffer.size()) {
15342
6.50k
    line8[components.protocol_end] = '`';
15343
6.50k
    line1[components.protocol_end] = ' ';
15344
15345
2.66M
    for (size_t i = components.protocol_end + 1; i < line8.size(); i++) {
15346
2.65M
      line8[i] = '-';
15347
2.65M
    }
15348
6.50k
    line8.append(" protocol_end ");
15349
6.50k
    line8.append(std::to_string(components.protocol_end));
15350
6.50k
    answer.append(line8);
15351
6.50k
    answer.append("\n");
15352
6.50k
  }
15353
15354
6.50k
  if (components.hash_start == url_components::omitted) {
15355
3
    answer.append("note: hash omitted\n");
15356
3
  }
15357
6.50k
  if (components.search_start == url_components::omitted) {
15358
3
    answer.append("note: search omitted\n");
15359
3
  }
15360
6.50k
  if (components.protocol_end > buffer.size()) {
15361
0
    answer.append("warning: protocol_end overflows\n");
15362
0
  }
15363
6.50k
  if (components.username_end > buffer.size()) {
15364
0
    answer.append("warning: username_end overflows\n");
15365
0
  }
15366
6.50k
  if (components.host_start > buffer.size()) {
15367
0
    answer.append("warning: host_start overflows\n");
15368
0
  }
15369
6.50k
  if (components.host_end > buffer.size()) {
15370
0
    answer.append("warning: host_end overflows\n");
15371
0
  }
15372
6.50k
  if (components.pathname_start > buffer.size()) {
15373
0
    answer.append("warning: pathname_start overflows\n");
15374
0
  }
15375
6.50k
  return answer;
15376
8.96k
}
15377
15378
0
void url_aggregator::delete_dash_dot() {
15379
0
  ada_log("url_aggregator::delete_dash_dot");
15380
0
  ADA_ASSERT_TRUE(validate());
15381
0
  ADA_ASSERT_TRUE(has_dash_dot());
15382
0
  buffer.erase(components.host_end, 2);
15383
0
  components.pathname_start -= 2;
15384
0
  if (components.search_start != url_components::omitted) {
15385
0
    components.search_start -= 2;
15386
0
  }
15387
0
  if (components.hash_start != url_components::omitted) {
15388
0
    components.hash_start -= 2;
15389
0
  }
15390
0
  ADA_ASSERT_TRUE(validate());
15391
0
  ADA_ASSERT_TRUE(!has_dash_dot());
15392
0
}
15393
15394
11.5k
inline void url_aggregator::consume_prepared_path(std::string_view input) {
15395
11.5k
  ada_log("url_aggregator::consume_prepared_path ", input);
15396
  /***
15397
   * This is largely duplicated code from helpers::parse_prepared_path, which is
15398
   * unfortunate. This particular function is nearly identical, except that it
15399
   * is a method on url_aggregator. The idea is that the trivial path (which is
15400
   * very common) merely appends to the buffer. This is the same trivial path as
15401
   * with helpers::parse_prepared_path, except that we have the additional check
15402
   * for is_at_path(). Otherwise, we grab a copy of the current path and we
15403
   * modify it, and then insert it back into the buffer.
15404
   */
15405
11.5k
  uint8_t accumulator = checkers::path_signature(input);
15406
  // Let us first detect a trivial case.
15407
  // If it is special, we check that we have no dot, no %,  no \ and no
15408
  // character needing percent encoding. Otherwise, we check that we have no %,
15409
  // no dot, and no character needing percent encoding.
15410
11.5k
  constexpr uint8_t need_encoding = 1;
15411
11.5k
  constexpr uint8_t backslash_char = 2;
15412
11.5k
  constexpr uint8_t dot_char = 4;
15413
11.5k
  constexpr uint8_t percent_char = 8;
15414
11.5k
  bool special = type != ada::scheme::NOT_SPECIAL;
15415
11.5k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
15416
1.65k
                                      checkers::is_windows_drive_letter(input));
15417
11.5k
  bool trivial_path =
15418
11.5k
      (special ? (accumulator == 0)
15419
11.5k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
15420
951
                  0)) &&
15421
2.02k
      (!may_need_slow_file_handling);
15422
11.5k
  if (accumulator == dot_char && !may_need_slow_file_handling) {
15423
    // '4' means that we have at least one dot, but nothing that requires
15424
    // percent encoding or decoding. The only part that is not trivial is
15425
    // that we may have single dots and double dots path segments.
15426
    // If we have such segments, then we either have a path that begins
15427
    // with '.' (easy to check), or we have the sequence './'.
15428
    // Note: input cannot be empty, it must at least contain one character ('.')
15429
    // Note: we know that '\' is not present.
15430
2.52k
    if (input[0] != '.') {
15431
1.75k
      size_t slashdot = 0;
15432
1.75k
      bool dot_is_file = true;
15433
8.75k
      for (;;) {
15434
8.75k
        slashdot = input.find("/.", slashdot);
15435
8.75k
        if (slashdot == std::string_view::npos) {  // common case
15436
1.75k
          break;
15437
7.00k
        } else {  // uncommon
15438
          // only three cases matter: /./, /.. or a final /
15439
7.00k
          slashdot += 2;
15440
7.00k
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
15441
1.71k
                           input[slashdot] == '/');
15442
7.00k
        }
15443
8.75k
      }
15444
1.75k
      trivial_path = dot_is_file;
15445
1.75k
    }
15446
2.52k
  }
15447
11.5k
  if (trivial_path && is_at_path()) {
15448
2.63k
    ada_log("parse_path trivial");
15449
2.63k
    buffer += '/';
15450
2.63k
    buffer += input;
15451
2.63k
    return;
15452
2.63k
  }
15453
8.92k
  std::string path = std::string(get_pathname());
15454
  // We are going to need to look a bit at the path, but let us see if we can
15455
  // ignore percent encoding *and* backslashes *and* percent characters.
15456
  // Except for the trivial case, this is likely to capture 99% of paths out
15457
  // there.
15458
8.92k
  bool fast_path =
15459
8.92k
      (special &&
15460
8.04k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
15461
1.74k
      (type != ada::scheme::type::FILE);
15462
8.92k
  if (fast_path) {
15463
1.34k
    ada_log("parse_prepared_path fast");
15464
    // Here we don't need to worry about \ or percent encoding.
15465
    // We also do not have a file protocol. We might have dots, however,
15466
    // but dots must as appear as '.', and they cannot be encoded because
15467
    // the symbol '%' is not present.
15468
1.34k
    size_t previous_location = 0;  // We start at 0.
15469
16.9k
    do {
15470
16.9k
      size_t new_location = input.find('/', previous_location);
15471
      // std::string_view path_view = input;
15472
      //  We process the last segment separately:
15473
16.9k
      if (new_location == std::string_view::npos) {
15474
1.34k
        std::string_view path_view = input.substr(previous_location);
15475
1.34k
        if (path_view == "..") {  // The path ends with ..
15476
          // e.g., if you receive ".." with an empty path, you go to "/".
15477
171
          if (path.empty()) {
15478
70
            path = '/';
15479
70
            update_base_pathname(path);
15480
70
            return;
15481
70
          }
15482
          // Fast case where we have nothing to do:
15483
101
          if (path.back() == '/') {
15484
38
            update_base_pathname(path);
15485
38
            return;
15486
38
          }
15487
          // If you have the path "/joe/myfriend",
15488
          // then you delete 'myfriend'.
15489
63
          path.resize(path.rfind('/') + 1);
15490
63
          update_base_pathname(path);
15491
63
          return;
15492
101
        }
15493
1.17k
        path += '/';
15494
1.17k
        if (path_view != ".") {
15495
908
          path.append(path_view);
15496
908
        }
15497
1.17k
        update_base_pathname(path);
15498
1.17k
        return;
15499
15.6k
      } else {
15500
        // This is a non-final segment.
15501
15.6k
        std::string_view path_view =
15502
15.6k
            input.substr(previous_location, new_location - previous_location);
15503
15.6k
        previous_location = new_location + 1;
15504
15.6k
        if (path_view == "..") {
15505
3.56k
          size_t last_delimiter = path.rfind('/');
15506
3.56k
          if (last_delimiter != std::string::npos) {
15507
1.82k
            path.erase(last_delimiter);
15508
1.82k
          }
15509
12.0k
        } else if (path_view != ".") {
15510
9.97k
          path += '/';
15511
9.97k
          path.append(path_view);
15512
9.97k
        }
15513
15.6k
      }
15514
16.9k
    } while (true);
15515
7.57k
  } else {
15516
7.57k
    ada_log("parse_path slow");
15517
    // we have reached the general case
15518
7.57k
    bool needs_percent_encoding = (accumulator & 1);
15519
7.57k
    std::string path_buffer_tmp;
15520
43.9k
    do {
15521
43.9k
      size_t location = (special && (accumulator & 2))
15522
43.9k
                            ? input.find_first_of("/\\")
15523
43.9k
                            : input.find('/');
15524
43.9k
      std::string_view path_view = input;
15525
43.9k
      if (location != std::string_view::npos) {
15526
36.3k
        path_view.remove_suffix(path_view.size() - location);
15527
36.3k
        input.remove_prefix(location + 1);
15528
36.3k
      }
15529
      // path_buffer is either path_view or it might point at a percent encoded
15530
      // temporary string.
15531
43.9k
      std::string_view path_buffer =
15532
43.9k
          (needs_percent_encoding &&
15533
28.8k
           ada::unicode::percent_encode<false>(
15534
28.8k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
15535
43.9k
              ? path_buffer_tmp
15536
43.9k
              : path_view;
15537
43.9k
      if (unicode::is_double_dot_path_segment(path_buffer)) {
15538
10.4k
        helpers::shorten_path(path, type);
15539
10.4k
        if (location == std::string_view::npos) {
15540
843
          path += '/';
15541
843
        }
15542
33.4k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
15543
2.10k
                 (location == std::string_view::npos)) {
15544
166
        path += '/';
15545
166
      }
15546
      // Otherwise, if path_buffer is not a single-dot path segment, then:
15547
33.2k
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
15548
        // If url's scheme is "file", url's path is empty, and path_buffer is a
15549
        // Windows drive letter, then replace the second code point in
15550
        // path_buffer with U+003A (:).
15551
31.3k
        if (type == ada::scheme::type::FILE && path.empty() &&
15552
4.14k
            checkers::is_windows_drive_letter(path_buffer)) {
15553
174
          path += '/';
15554
174
          path += path_buffer[0];
15555
174
          path += ':';
15556
174
          path_buffer.remove_prefix(2);
15557
174
          path.append(path_buffer);
15558
31.1k
        } else {
15559
          // Append path_buffer to url's path.
15560
31.1k
          path += '/';
15561
31.1k
          path.append(path_buffer);
15562
31.1k
        }
15563
31.3k
      }
15564
43.9k
      if (location == std::string_view::npos) {
15565
7.57k
        update_base_pathname(path);
15566
7.57k
        return;
15567
7.57k
      }
15568
43.9k
    } while (true);
15569
7.57k
  }
15570
8.92k
}
15571
}  // namespace ada
15572
/* end file src/url_aggregator.cpp */
15573
15574
#if ADA_INCLUDE_URL_PATTERN
15575
/* begin file src/url_pattern.cpp */
15576
#if ADA_INCLUDE_URL_PATTERN
15577
15578
15579
#include <algorithm>
15580
#include <optional>
15581
#include <string>
15582
15583
namespace ada {
15584
15585
tl::expected<url_pattern_init, errors> url_pattern_init::process(
15586
    const url_pattern_init& init, url_pattern_init::process_type type,
15587
    std::optional<std::string_view> protocol,
15588
    std::optional<std::string_view> username,
15589
    std::optional<std::string_view> password,
15590
    std::optional<std::string_view> hostname,
15591
    std::optional<std::string_view> port,
15592
    std::optional<std::string_view> pathname,
15593
    std::optional<std::string_view> search,
15594
0
    std::optional<std::string_view> hash) {
15595
  // Let result be the result of creating a new URLPatternInit.
15596
0
  auto result = url_pattern_init{};
15597
15598
  // If protocol is not null, set result["protocol"] to protocol.
15599
0
  if (protocol.has_value()) result.protocol = *protocol;
15600
15601
  // If username is not null, set result["username"] to username.
15602
0
  if (username.has_value()) result.username = *username;
15603
15604
  // If password is not null, set result["password"] to password.
15605
0
  if (password.has_value()) result.password = *password;
15606
15607
  // If hostname is not null, set result["hostname"] to hostname.
15608
0
  if (hostname.has_value()) result.hostname = *hostname;
15609
15610
  // If port is not null, set result["port"] to port.
15611
0
  if (port.has_value()) result.port = *port;
15612
15613
  // If pathname is not null, set result["pathname"] to pathname.
15614
0
  if (pathname.has_value()) result.pathname = *pathname;
15615
15616
  // If search is not null, set result["search"] to search.
15617
0
  if (search.has_value()) result.search = *search;
15618
15619
  // If hash is not null, set result["hash"] to hash.
15620
0
  if (hash.has_value()) result.hash = *hash;
15621
15622
  // Let baseURL be null.
15623
0
  std::optional<url_aggregator> base_url{};
15624
15625
  // If init["baseURL"] exists:
15626
0
  if (init.base_url.has_value()) {
15627
    // Set baseURL to the result of parsing init["baseURL"].
15628
0
    auto parsing_result = ada::parse<url_aggregator>(*init.base_url);
15629
    // If baseURL is failure, then throw a TypeError.
15630
0
    if (!parsing_result) {
15631
0
      return tl::unexpected(errors::type_error);
15632
0
    }
15633
0
    base_url = std::move(*parsing_result);
15634
15635
    // If init["protocol"] does not exist, then set result["protocol"] to the
15636
    // result of processing a base URL string given baseURL's scheme and type.
15637
0
    if (!init.protocol.has_value()) {
15638
0
      ADA_ASSERT_TRUE(base_url.has_value());
15639
0
      std::string_view base_url_protocol = base_url->get_protocol();
15640
0
      if (base_url_protocol.ends_with(":")) base_url_protocol.remove_suffix(1);
15641
0
      result.protocol =
15642
0
          url_pattern_helpers::process_base_url_string(base_url_protocol, type);
15643
0
    }
15644
15645
    // If type is not "pattern" and init contains none of "protocol",
15646
    // "hostname", "port" and "username", then set result["username"] to the
15647
    // result of processing a base URL string given baseURL's username and type.
15648
0
    if (type != process_type::pattern && !init.protocol && !init.hostname &&
15649
0
        !init.port && !init.username) {
15650
0
      result.username = url_pattern_helpers::process_base_url_string(
15651
0
          base_url->get_username(), type);
15652
0
    }
15653
15654
    // TODO: Optimization opportunity: Merge this with the previous check.
15655
    // If type is not "pattern" and init contains none of "protocol",
15656
    // "hostname", "port", "username" and "password", then set
15657
    // result["password"] to the result of processing a base URL string given
15658
    // baseURL's password and type.
15659
0
    if (type != process_type::pattern && !init.protocol && !init.hostname &&
15660
0
        !init.port && !init.username && !init.password) {
15661
0
      result.password = url_pattern_helpers::process_base_url_string(
15662
0
          base_url->get_password(), type);
15663
0
    }
15664
15665
    // If init contains neither "protocol" nor "hostname", then:
15666
0
    if (!init.protocol && !init.hostname) {
15667
      // Let baseHost be baseURL's host.
15668
      // If baseHost is null, then set baseHost to the empty string.
15669
0
      auto base_host = base_url->get_hostname();
15670
      // Set result["hostname"] to the result of processing a base URL string
15671
      // given baseHost and type.
15672
0
      result.hostname =
15673
0
          url_pattern_helpers::process_base_url_string(base_host, type);
15674
0
    }
15675
15676
    // If init contains none of "protocol", "hostname", and "port", then:
15677
0
    if (!init.protocol && !init.hostname && !init.port) {
15678
      // If baseURL's port is null, then set result["port"] to the empty string.
15679
      // Otherwise, set result["port"] to baseURL's port, serialized.
15680
0
      result.port = base_url->get_port();
15681
0
    }
15682
15683
    // If init contains none of "protocol", "hostname", "port", and "pathname",
15684
    // then set result["pathname"] to the result of processing a base URL string
15685
    // given the result of URL path serializing baseURL and type.
15686
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname) {
15687
0
      result.pathname = url_pattern_helpers::process_base_url_string(
15688
0
          base_url->get_pathname(), type);
15689
0
    }
15690
15691
    // If init contains none of "protocol", "hostname", "port", "pathname", and
15692
    // "search", then:
15693
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname &&
15694
0
        !init.search) {
15695
      // Let baseQuery be baseURL's query.
15696
      // Set result["search"] to the result of processing a base URL string
15697
      // given baseQuery and type.
15698
0
      result.search = url_pattern_helpers::process_base_url_string(
15699
0
          base_url->get_search(), type);
15700
0
    }
15701
15702
    // If init contains none of "protocol", "hostname", "port", "pathname",
15703
    // "search", and "hash", then:
15704
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname &&
15705
0
        !init.search && !init.hash) {
15706
      // Let baseFragment be baseURL's fragment.
15707
      // Set result["hash"] to the result of processing a base URL string given
15708
      // baseFragment and type.
15709
0
      result.hash = url_pattern_helpers::process_base_url_string(
15710
0
          base_url->get_hash(), type);
15711
0
    }
15712
0
  }
15713
15714
  // If init["protocol"] exists, then set result["protocol"] to the result of
15715
  // process protocol for init given init["protocol"] and type.
15716
0
  if (init.protocol) {
15717
0
    auto process_result = process_protocol(*init.protocol, type);
15718
0
    if (!process_result) {
15719
0
      return tl::unexpected(process_result.error());
15720
0
    }
15721
0
    result.protocol = std::move(*process_result);
15722
0
  }
15723
15724
  // If init["username"] exists, then set result["username"] to the result of
15725
  // process username for init given init["username"] and type.
15726
0
  if (init.username.has_value()) {
15727
0
    auto process_result = process_username(*init.username, type);
15728
0
    if (!process_result) {
15729
0
      return tl::unexpected(process_result.error());
15730
0
    }
15731
0
    result.username = std::move(*process_result);
15732
0
  }
15733
15734
  // If init["password"] exists, then set result["password"] to the result of
15735
  // process password for init given init["password"] and type.
15736
0
  if (init.password.has_value()) {
15737
0
    auto process_result = process_password(*init.password, type);
15738
0
    if (!process_result) {
15739
0
      return tl::unexpected(process_result.error());
15740
0
    }
15741
0
    result.password = std::move(*process_result);
15742
0
  }
15743
15744
  // If init["hostname"] exists, then set result["hostname"] to the result of
15745
  // process hostname for init given init["hostname"] and type.
15746
0
  if (init.hostname.has_value()) {
15747
0
    auto process_result = process_hostname(*init.hostname, type);
15748
0
    if (!process_result) {
15749
0
      return tl::unexpected(process_result.error());
15750
0
    }
15751
0
    result.hostname = std::move(*process_result);
15752
0
  }
15753
15754
  // If init["port"] exists, then set result["port"] to the result of process
15755
  // port for init given init["port"], result["protocol"], and type.
15756
0
  if (init.port) {
15757
0
    auto process_result =
15758
0
        process_port(*init.port, result.protocol.value_or("fake"), type);
15759
0
    if (!process_result) {
15760
0
      return tl::unexpected(process_result.error());
15761
0
    }
15762
0
    result.port = std::move(*process_result);
15763
0
  }
15764
15765
  // If init["pathname"] exists:
15766
0
  if (init.pathname.has_value()) {
15767
    // Set result["pathname"] to init["pathname"].
15768
0
    result.pathname = init.pathname;
15769
15770
    // If the following are all true:
15771
    // - baseURL is not null;
15772
    // - baseURL has an opaque path; and
15773
    // - the result of running is an absolute pathname given result["pathname"]
15774
    // and type is false,
15775
0
    if (base_url && !base_url->has_opaque_path &&
15776
0
        !url_pattern_helpers::is_absolute_pathname(*result.pathname, type)) {
15777
      // Let baseURLPath be the result of running process a base URL string
15778
      // given the result of URL path serializing baseURL and type.
15779
      // TODO: Optimization opportunity: Avoid returning a string if no slash
15780
      // exist.
15781
0
      std::string base_url_path = url_pattern_helpers::process_base_url_string(
15782
0
          base_url->get_pathname(), type);
15783
15784
      // Let slash index be the index of the last U+002F (/) code point found in
15785
      // baseURLPath, interpreted as a sequence of code points, or null if there
15786
      // are no instances of the code point.
15787
0
      auto slash_index = base_url_path.find_last_of('/');
15788
15789
      // If slash index is not null:
15790
0
      if (slash_index != std::string::npos) {
15791
        // Let new pathname be the code point substring from 0 to slash index +
15792
        // 1 within baseURLPath.
15793
0
        base_url_path.resize(slash_index + 1);
15794
        // Append result["pathname"] to the end of new pathname.
15795
0
        ADA_ASSERT_TRUE(result.pathname.has_value());
15796
0
        base_url_path.append(std::move(*result.pathname));
15797
        // Set result["pathname"] to new pathname.
15798
0
        result.pathname = std::move(base_url_path);
15799
0
      }
15800
0
    }
15801
15802
    // Set result["pathname"] to the result of process pathname for init given
15803
    // result["pathname"], result["protocol"], and type.
15804
0
    auto pathname_processing_result =
15805
0
        process_pathname(*result.pathname, result.protocol.value_or(""), type);
15806
0
    if (!pathname_processing_result) {
15807
0
      return tl::unexpected(pathname_processing_result.error());
15808
0
    }
15809
0
    result.pathname = std::move(*pathname_processing_result);
15810
0
  }
15811
15812
  // If init["search"] exists then set result["search"] to the result of process
15813
  // search for init given init["search"] and type.
15814
0
  if (init.search) {
15815
0
    auto process_result = process_search(*init.search, type);
15816
0
    if (!process_result) {
15817
0
      return tl::unexpected(process_result.error());
15818
0
    }
15819
0
    result.search = std::move(*process_result);
15820
0
  }
15821
15822
  // If init["hash"] exists then set result["hash"] to the result of process
15823
  // hash for init given init["hash"] and type.
15824
0
  if (init.hash) {
15825
0
    auto process_result = process_hash(*init.hash, type);
15826
0
    if (!process_result) {
15827
0
      return tl::unexpected(process_result.error());
15828
0
    }
15829
0
    result.hash = std::move(*process_result);
15830
0
  }
15831
  // Return result.
15832
0
  return result;
15833
0
}
15834
15835
tl::expected<std::string, errors> url_pattern_init::process_protocol(
15836
0
    std::string_view value, process_type type) {
15837
0
  ada_log("process_protocol=", value, " [", type, "]");
15838
  // Let strippedValue be the given value with a single trailing U+003A (:)
15839
  // removed, if any.
15840
0
  if (value.ends_with(":")) {
15841
0
    value.remove_suffix(1);
15842
0
  }
15843
  // If type is "pattern" then return strippedValue.
15844
0
  if (type == process_type::pattern) {
15845
0
    return std::string(value);
15846
0
  }
15847
  // Return the result of running canonicalize a protocol given strippedValue.
15848
0
  return url_pattern_helpers::canonicalize_protocol(value);
15849
0
}
15850
15851
tl::expected<std::string, errors> url_pattern_init::process_username(
15852
0
    std::string_view value, process_type type) {
15853
  // If type is "pattern" then return value.
15854
0
  if (type == process_type::pattern) {
15855
0
    return std::string(value);
15856
0
  }
15857
  // Return the result of running canonicalize a username given value.
15858
0
  return url_pattern_helpers::canonicalize_username(value);
15859
0
}
15860
15861
tl::expected<std::string, errors> url_pattern_init::process_password(
15862
0
    std::string_view value, process_type type) {
15863
  // If type is "pattern" then return value.
15864
0
  if (type == process_type::pattern) {
15865
0
    return std::string(value);
15866
0
  }
15867
  // Return the result of running canonicalize a password given value.
15868
0
  return url_pattern_helpers::canonicalize_password(value);
15869
0
}
15870
15871
tl::expected<std::string, errors> url_pattern_init::process_hostname(
15872
0
    std::string_view value, process_type type) {
15873
0
  ada_log("process_hostname value=", value, " type=", type);
15874
  // If type is "pattern" then return value.
15875
0
  if (type == process_type::pattern) {
15876
0
    return std::string(value);
15877
0
  }
15878
  // Return the result of running canonicalize a hostname given value.
15879
0
  return url_pattern_helpers::canonicalize_hostname(value);
15880
0
}
15881
15882
tl::expected<std::string, errors> url_pattern_init::process_port(
15883
0
    std::string_view port, std::string_view protocol, process_type type) {
15884
  // If type is "pattern" then return portValue.
15885
0
  if (type == process_type::pattern) {
15886
0
    return std::string(port);
15887
0
  }
15888
  // Return the result of running canonicalize a port given portValue and
15889
  // protocolValue.
15890
0
  return url_pattern_helpers::canonicalize_port_with_protocol(port, protocol);
15891
0
}
15892
15893
tl::expected<std::string, errors> url_pattern_init::process_pathname(
15894
0
    std::string_view value, std::string_view protocol, process_type type) {
15895
  // If type is "pattern" then return pathnameValue.
15896
0
  if (type == process_type::pattern) {
15897
0
    return std::string(value);
15898
0
  }
15899
15900
  // If protocolValue is a special scheme or the empty string, then return the
15901
  // result of running canonicalize a pathname given pathnameValue.
15902
0
  if (protocol.empty() || scheme::is_special(protocol)) {
15903
0
    return url_pattern_helpers::canonicalize_pathname(value);
15904
0
  }
15905
15906
  // Return the result of running canonicalize an opaque pathname given
15907
  // pathnameValue.
15908
0
  return url_pattern_helpers::canonicalize_opaque_pathname(value);
15909
0
}
15910
15911
tl::expected<std::string, errors> url_pattern_init::process_search(
15912
0
    std::string_view value, process_type type) {
15913
  // Let strippedValue be the given value with a single leading U+003F (?)
15914
  // removed, if any.
15915
0
  if (value.starts_with("?")) {
15916
0
    value.remove_prefix(1);
15917
0
  }
15918
  // We cannot assert that the value is no longer starting with a single
15919
  // question mark because technically it can start. The question is whether or
15920
  // not we should remove the first question mark. Ref:
15921
  // https://github.com/ada-url/ada/pull/992 The spec is not clear on this.
15922
15923
  // If type is "pattern" then return strippedValue.
15924
0
  if (type == process_type::pattern) {
15925
0
    return std::string(value);
15926
0
  }
15927
  // Return the result of running canonicalize a search given strippedValue.
15928
0
  return url_pattern_helpers::canonicalize_search(value);
15929
0
}
15930
15931
tl::expected<std::string, errors> url_pattern_init::process_hash(
15932
0
    std::string_view value, process_type type) {
15933
  // Let strippedValue be the given value with a single leading U+0023 (#)
15934
  // removed, if any.
15935
0
  if (value.starts_with("#")) {
15936
0
    value.remove_prefix(1);
15937
0
  }
15938
0
  ADA_ASSERT_TRUE(!value.starts_with("#"));
15939
  // If type is "pattern" then return strippedValue.
15940
0
  if (type == process_type::pattern) {
15941
0
    return std::string(value);
15942
0
  }
15943
  // Return the result of running canonicalize a hash given strippedValue.
15944
0
  return url_pattern_helpers::canonicalize_hash(value);
15945
0
}
15946
15947
}  // namespace ada
15948
15949
#endif  // ADA_INCLUDE_URL_PATTERN
15950
/* end file src/url_pattern.cpp */
15951
/* begin file src/url_pattern_helpers.cpp */
15952
#if ADA_INCLUDE_URL_PATTERN
15953
15954
#include <algorithm>
15955
#include <optional>
15956
#include <string>
15957
15958
namespace ada::url_pattern_helpers {
15959
15960
std::tuple<std::string, std::vector<std::string>>
15961
generate_regular_expression_and_name_list(
15962
    const std::vector<url_pattern_part>& part_list,
15963
0
    url_pattern_compile_component_options options) {
15964
  // Let result be "^"
15965
0
  std::string result = "^";
15966
15967
  // Let name list be a new list
15968
0
  std::vector<std::string> name_list{};
15969
15970
  // For each part of part list:
15971
0
  for (const url_pattern_part& part : part_list) {
15972
    // If part's type is "fixed-text":
15973
0
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
15974
      // If part's modifier is "none"
15975
0
      if (part.modifier == url_pattern_part_modifier::none) {
15976
        // Append the result of running escape a regexp string given part's
15977
        // value
15978
0
        result += escape_regexp_string(part.value);
15979
0
      } else {
15980
        // A "fixed-text" part with a modifier uses a non capturing group
15981
        // (?:<fixed text>)<modifier>
15982
        // Append "(?:" to the end of result.
15983
0
        result.append("(?:");
15984
        // Append the result of running escape a regexp string given part's
15985
        // value to the end of result.
15986
0
        result.append(escape_regexp_string(part.value));
15987
        // Append ")" to the end of result.
15988
0
        result.append(")");
15989
        // Append the result of running convert a modifier to a string given
15990
        // part's modifier to the end of result.
15991
0
        result.append(convert_modifier_to_string(part.modifier));
15992
0
      }
15993
0
      continue;
15994
0
    }
15995
15996
    // Assert: part's name is not the empty string
15997
0
    ADA_ASSERT_TRUE(!part.name.empty());
15998
15999
    // Append part's name to name list
16000
0
    name_list.push_back(part.name);
16001
16002
    // Let regexp value be part's value
16003
0
    std::string regexp_value = part.value;
16004
16005
    // If part's type is "segment-wildcard"
16006
0
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD) {
16007
      // then set regexp value to the result of running generate a segment
16008
      // wildcard regexp given options.
16009
0
      regexp_value = generate_segment_wildcard_regexp(options);
16010
0
    }
16011
    // Otherwise if part's type is "full-wildcard"
16012
0
    else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
16013
      // then set regexp value to full wildcard regexp value.
16014
0
      regexp_value = ".*";
16015
0
    }
16016
16017
    // If part's prefix is the empty string and part's suffix is the empty
16018
    // string
16019
0
    if (part.prefix.empty() && part.suffix.empty()) {
16020
      // If part's modifier is "none" or "optional"
16021
0
      if (part.modifier == url_pattern_part_modifier::none ||
16022
0
          part.modifier == url_pattern_part_modifier::optional) {
16023
        // (<regexp value>)<modifier>
16024
0
        result += "(" + regexp_value + ")" +
16025
0
                  convert_modifier_to_string(part.modifier);
16026
0
      } else {
16027
        // ((?:<regexp value>)<modifier>)
16028
0
        result += "((?:" + regexp_value + ")" +
16029
0
                  convert_modifier_to_string(part.modifier) + ")";
16030
0
      }
16031
0
      continue;
16032
0
    }
16033
16034
    // If part's modifier is "none" or "optional"
16035
0
    if (part.modifier == url_pattern_part_modifier::none ||
16036
0
        part.modifier == url_pattern_part_modifier::optional) {
16037
      // (?:<prefix>(<regexp value>)<suffix>)<modifier>
16038
0
      result += "(?:" + escape_regexp_string(part.prefix) + "(" + regexp_value +
16039
0
                ")" + escape_regexp_string(part.suffix) + ")" +
16040
0
                convert_modifier_to_string(part.modifier);
16041
0
      continue;
16042
0
    }
16043
16044
    // Assert: part's modifier is "zero-or-more" or "one-or-more"
16045
0
    ADA_ASSERT_TRUE(part.modifier == url_pattern_part_modifier::zero_or_more ||
16046
0
                    part.modifier == url_pattern_part_modifier::one_or_more);
16047
16048
    // Assert: part's prefix is not the empty string or part's suffix is not the
16049
    // empty string
16050
0
    ADA_ASSERT_TRUE(!part.prefix.empty() || !part.suffix.empty());
16051
16052
    // (?:<prefix>((?:<regexp value>)(?:<suffix><prefix>(?:<regexp
16053
    // value>))*)<suffix>)?
16054
    // Append "(?:" to the end of result.
16055
0
    result.append("(?:");
16056
    // Append the result of running escape a regexp string given part's prefix
16057
    // to the end of result.
16058
0
    result.append(escape_regexp_string(part.prefix));
16059
    // Append "((?:" to the end of result.
16060
0
    result.append("((?:");
16061
    // Append regexp value to the end of result.
16062
0
    result.append(regexp_value);
16063
    // Append ")(?:" to the end of result.
16064
0
    result.append(")(?:");
16065
    // Append the result of running escape a regexp string given part's suffix
16066
    // to the end of result.
16067
0
    result.append(escape_regexp_string(part.suffix));
16068
    // Append the result of running escape a regexp string given part's prefix
16069
    // to the end of result.
16070
0
    result.append(escape_regexp_string(part.prefix));
16071
    // Append "(?:" to the end of result.
16072
0
    result.append("(?:");
16073
    // Append regexp value to the end of result.
16074
0
    result.append(regexp_value);
16075
    // Append "))*)" to the end of result.
16076
0
    result.append("))*)");
16077
    // Append the result of running escape a regexp string given part's suffix
16078
    // to the end of result.
16079
0
    result.append(escape_regexp_string(part.suffix));
16080
    // Append ")" to the end of result.
16081
0
    result.append(")");
16082
16083
    // If part's modifier is "zero-or-more" then append "?" to the end of result
16084
0
    if (part.modifier == url_pattern_part_modifier::zero_or_more) {
16085
0
      result += "?";
16086
0
    }
16087
0
  }
16088
16089
  // Append "$" to the end of result
16090
0
  result += "$";
16091
16092
  // Return (result, name list)
16093
0
  return {std::move(result), std::move(name_list)};
16094
0
}
16095
16096
0
bool is_ipv6_address(std::string_view input) noexcept {
16097
  // If input's code point length is less than 2, then return false.
16098
0
  if (input.size() < 2) return false;
16099
16100
  // Let input code points be input interpreted as a list of code points.
16101
  // If input code points[0] is U+005B ([), then return true.
16102
0
  if (input.front() == '[') return true;
16103
  // If input code points[0] is U+007B ({) and input code points[1] is U+005B
16104
  // ([), then return true.
16105
0
  if (input.starts_with("{[")) return true;
16106
  // If input code points[0] is U+005C (\) and input code points[1] is U+005B
16107
  // ([), then return true.
16108
0
  return input.starts_with("\\[");
16109
0
}
16110
16111
0
std::string convert_modifier_to_string(url_pattern_part_modifier modifier) {
16112
  // TODO: Optimize this.
16113
0
  switch (modifier) {
16114
      // If modifier is "zero-or-more", then return "*".
16115
0
    case url_pattern_part_modifier::zero_or_more:
16116
0
      return "*";
16117
    // If modifier is "optional", then return "?".
16118
0
    case url_pattern_part_modifier::optional:
16119
0
      return "?";
16120
    // If modifier is "one-or-more", then return "+".
16121
0
    case url_pattern_part_modifier::one_or_more:
16122
0
      return "+";
16123
    // Return the empty string.
16124
0
    default:
16125
0
      return "";
16126
0
  }
16127
0
}
16128
16129
std::string generate_segment_wildcard_regexp(
16130
0
    url_pattern_compile_component_options options) {
16131
  // Let result be "[^".
16132
0
  std::string result = "[^";
16133
  // Append the result of running escape a regexp string given options's
16134
  // delimiter code point to the end of result.
16135
0
  result.append(escape_regexp_string(options.get_delimiter()));
16136
  // Append "]+?" to the end of result.
16137
0
  result.append("]+?");
16138
  // Return result.
16139
0
  ada_log("generate_segment_wildcard_regexp result: ", result);
16140
0
  return result;
16141
0
}
16142
16143
tl::expected<std::string, errors> canonicalize_protocol(
16144
0
    std::string_view input) {
16145
0
  ada_log("canonicalize_protocol called with input=", input);
16146
  // If value is the empty string, return value.
16147
0
  if (input.empty()) [[unlikely]] {
16148
0
    return "";
16149
0
  }
16150
16151
  // IMPORTANT: Deviation from the spec. We remove the trailing ':' here.
16152
0
  if (input.ends_with(":")) {
16153
0
    input.remove_suffix(1);
16154
0
  }
16155
16156
  // Let dummyURL be a new URL record.
16157
  // Let parseResult be the result of running the basic URL parser given value
16158
  // followed by "://dummy.test", with dummyURL as url.
16159
0
  if (auto dummy_url = ada::parse<url_aggregator>(
16160
0
          std::string(input) + "://dummy.test", nullptr)) {
16161
    // IMPORTANT: Deviation from the spec. We remove the trailing ':' here.
16162
    // Since URL parser always return protocols ending with `:`
16163
0
    auto protocol = dummy_url->get_protocol();
16164
0
    protocol.remove_suffix(1);
16165
0
    return std::string(protocol);
16166
0
  }
16167
  // If parseResult is failure, then throw a TypeError.
16168
0
  return tl::unexpected(errors::type_error);
16169
0
}
16170
16171
tl::expected<std::string, errors> canonicalize_username(
16172
0
    std::string_view input) {
16173
  // If value is the empty string, return value.
16174
0
  if (input.empty()) [[unlikely]] {
16175
0
    return "";
16176
0
  }
16177
  // Let dummyURL be a new URL record.
16178
0
  auto url = ada::parse<url_aggregator>("fake://dummy.test", nullptr);
16179
0
  ADA_ASSERT_TRUE(url.has_value());
16180
  // Set the username given dummyURL and value.
16181
0
  if (!url->set_username(input)) {
16182
0
    return tl::unexpected(errors::type_error);
16183
0
  }
16184
  // Return dummyURL's username.
16185
0
  return std::string(url->get_username());
16186
0
}
16187
16188
tl::expected<std::string, errors> canonicalize_password(
16189
0
    std::string_view input) {
16190
  // If value is the empty string, return value.
16191
0
  if (input.empty()) [[unlikely]] {
16192
0
    return "";
16193
0
  }
16194
  // Let dummyURL be a new URL record.
16195
  // Set the password given dummyURL and value.
16196
0
  auto url = ada::parse<url_aggregator>("fake://dummy.test", nullptr);
16197
16198
0
  ADA_ASSERT_TRUE(url.has_value());
16199
0
  if (!url->set_password(input)) {
16200
0
    return tl::unexpected(errors::type_error);
16201
0
  }
16202
  // Return dummyURL's password.
16203
0
  return std::string(url->get_password());
16204
0
}
16205
16206
tl::expected<std::string, errors> canonicalize_hostname(
16207
0
    std::string_view input) {
16208
0
  ada_log("canonicalize_hostname input=", input);
16209
  // If value is the empty string, return value.
16210
0
  if (input.empty()) [[unlikely]] {
16211
0
    return "";
16212
0
  }
16213
  // Let dummyURL be a new URL record.
16214
  // Let parseResult be the result of running the basic URL parser given value
16215
  // with dummyURL as url and hostname state as state override.
16216
16217
  // IMPORTANT: The protocol needs to be a special protocol, otherwise the
16218
  // hostname will not be converted using IDNA.
16219
0
  auto url = ada::parse<url_aggregator>("https://dummy.test", nullptr);
16220
0
  ADA_ASSERT_TRUE(url);
16221
  // if (!isValidHostnameInput(hostname)) return kj::none;
16222
0
  if (!url->set_hostname(input)) {
16223
    // If parseResult is failure, then throw a TypeError.
16224
0
    return tl::unexpected(errors::type_error);
16225
0
  }
16226
  // Return dummyURL's host, serialized, or empty string if it is null.
16227
0
  return std::string(url->get_hostname());
16228
0
}
16229
16230
tl::expected<std::string, errors> canonicalize_ipv6_hostname(
16231
0
    std::string_view input) {
16232
0
  ada_log("canonicalize_ipv6_hostname input=", input);
16233
  // TODO: Optimization opportunity: Use lookup table to speed up checking
16234
0
  if (std::ranges::any_of(input, [](char c) {
16235
0
        return c != '[' && c != ']' && c != ':' &&
16236
0
               !unicode::is_ascii_hex_digit(c);
16237
0
      })) {
16238
0
    return tl::unexpected(errors::type_error);
16239
0
  }
16240
  // Append the result of running ASCII lowercase given code point to the end of
16241
  // result.
16242
0
  auto hostname = std::string(input);
16243
0
  unicode::to_lower_ascii(hostname.data(), hostname.size());
16244
0
  return hostname;
16245
0
}
16246
16247
tl::expected<std::string, errors> canonicalize_port(
16248
0
    std::string_view port_value) {
16249
  // If portValue is the empty string, return portValue.
16250
0
  if (port_value.empty()) [[unlikely]] {
16251
0
    return "";
16252
0
  }
16253
  // Let dummyURL be a new URL record.
16254
  // If protocolValue was given, then set dummyURL's scheme to protocolValue.
16255
  // Let parseResult be the result of running basic URL parser given portValue
16256
  // with dummyURL as url and port state as state override.
16257
0
  auto url = ada::parse<url_aggregator>("fake://dummy.test", nullptr);
16258
0
  ADA_ASSERT_TRUE(url);
16259
0
  if (url->set_port(port_value)) {
16260
    // Return dummyURL's port, serialized, or empty string if it is null.
16261
0
    return std::string(url->get_port());
16262
0
  }
16263
  // If parseResult is failure, then throw a TypeError.
16264
0
  return tl::unexpected(errors::type_error);
16265
0
}
16266
16267
tl::expected<std::string, errors> canonicalize_port_with_protocol(
16268
0
    std::string_view port_value, std::string_view protocol) {
16269
  // If portValue is the empty string, return portValue.
16270
0
  if (port_value.empty()) [[unlikely]] {
16271
0
    return "";
16272
0
  }
16273
16274
  // TODO: Remove this
16275
  // We have an empty protocol because get_protocol() returns an empty string
16276
  // We should handle this in the caller rather than here.
16277
0
  if (protocol.empty()) {
16278
0
    protocol = "fake";
16279
0
  } else if (protocol.ends_with(":")) {
16280
0
    protocol.remove_suffix(1);
16281
0
  }
16282
  // Let dummyURL be a new URL record.
16283
  // If protocolValue was given, then set dummyURL's scheme to protocolValue.
16284
  // Let parseResult be the result of running basic URL parser given portValue
16285
  // with dummyURL as url and port state as state override.
16286
0
  auto url = ada::parse<url_aggregator>(std::string(protocol) + "://dummy.test",
16287
0
                                        nullptr);
16288
  // TODO: Remove has_port() check.
16289
  // This is actually a bug with url parser where set_port() returns true for
16290
  // "invalid80" port value.
16291
0
  if (url && url->set_port(port_value) && url->has_port()) {
16292
    // Return dummyURL's port, serialized, or empty string if it is null.
16293
0
    return std::string(url->get_port());
16294
0
  }
16295
  // TODO: Remove this once the previous has_port() check is removed.
16296
0
  if (url) {
16297
0
    if (scheme::is_special(protocol) && url->get_port().empty()) {
16298
0
      return "";
16299
0
    }
16300
0
  }
16301
  // If parseResult is failure, then throw a TypeError.
16302
0
  return tl::unexpected(errors::type_error);
16303
0
}
16304
16305
tl::expected<std::string, errors> canonicalize_pathname(
16306
0
    std::string_view input) {
16307
  // If value is the empty string, then return value.
16308
0
  if (input.empty()) [[unlikely]] {
16309
0
    return "";
16310
0
  }
16311
  // Let leading slash be true if the first code point in value is U+002F (/)
16312
  // and otherwise false.
16313
0
  const bool leading_slash = input.starts_with("/");
16314
  // Let modified value be "/-" if leading slash is false and otherwise the
16315
  // empty string.
16316
0
  const auto modified_value = leading_slash ? "" : "/-";
16317
0
  const auto full_url =
16318
0
      std::string("fake://fake-url") + modified_value + std::string(input);
16319
0
  if (auto url = ada::parse<url_aggregator>(full_url, nullptr)) {
16320
0
    const auto pathname = url->get_pathname();
16321
    // If leading slash is false, then set result to the code point substring
16322
    // from 2 to the end of the string within result.
16323
0
    return leading_slash ? std::string(pathname)
16324
0
                         : std::string(pathname.substr(2));
16325
0
  }
16326
  // If parseResult is failure, then throw a TypeError.
16327
0
  return tl::unexpected(errors::type_error);
16328
0
}
16329
16330
tl::expected<std::string, errors> canonicalize_opaque_pathname(
16331
0
    std::string_view input) {
16332
  // If value is the empty string, return value.
16333
0
  if (input.empty()) [[unlikely]] {
16334
0
    return "";
16335
0
  }
16336
  // Let dummyURL be a new URL record.
16337
  // Set dummyURL's path to the empty string.
16338
  // Let parseResult be the result of running URL parsing given value with
16339
  // dummyURL as url and opaque path state as state override.
16340
0
  if (auto url =
16341
0
          ada::parse<url_aggregator>("fake:" + std::string(input), nullptr)) {
16342
    // Return the result of URL path serializing dummyURL.
16343
0
    return std::string(url->get_pathname());
16344
0
  }
16345
  // If parseResult is failure, then throw a TypeError.
16346
0
  return tl::unexpected(errors::type_error);
16347
0
}
16348
16349
0
tl::expected<std::string, errors> canonicalize_search(std::string_view input) {
16350
  // If value is the empty string, return value.
16351
0
  if (input.empty()) [[unlikely]] {
16352
0
    return "";
16353
0
  }
16354
  // Let dummyURL be a new URL record.
16355
  // Set dummyURL's query to the empty string.
16356
  // Let parseResult be the result of running basic URL parser given value with
16357
  // dummyURL as url and query state as state override.
16358
0
  auto url = ada::parse<url_aggregator>("fake://dummy.test", nullptr);
16359
0
  ADA_ASSERT_TRUE(url.has_value());
16360
0
  url->set_search(input);
16361
0
  if (url->has_search()) {
16362
0
    const auto search = url->get_search();
16363
0
    if (!search.empty()) {
16364
0
      return std::string(search.substr(1));
16365
0
    }
16366
0
    return "";
16367
0
  }
16368
0
  return tl::unexpected(errors::type_error);
16369
0
}
16370
16371
0
tl::expected<std::string, errors> canonicalize_hash(std::string_view input) {
16372
  // If value is the empty string, return value.
16373
0
  if (input.empty()) [[unlikely]] {
16374
0
    return "";
16375
0
  }
16376
  // Let dummyURL be a new URL record.
16377
  // Set dummyURL's fragment to the empty string.
16378
  // Let parseResult be the result of running basic URL parser given value with
16379
  // dummyURL as url and fragment state as state override.
16380
0
  auto url = ada::parse<url_aggregator>("fake://dummy.test", nullptr);
16381
0
  ADA_ASSERT_TRUE(url.has_value());
16382
0
  url->set_hash(input);
16383
  // Return dummyURL's fragment.
16384
0
  if (url->has_hash()) {
16385
0
    const auto hash = url->get_hash();
16386
0
    if (!hash.empty()) {
16387
0
      return std::string(hash.substr(1));
16388
0
    }
16389
0
    return "";
16390
0
  }
16391
0
  return tl::unexpected(errors::type_error);
16392
0
}
16393
16394
tl::expected<std::vector<token>, errors> tokenize(std::string_view input,
16395
0
                                                  token_policy policy) {
16396
0
  ada_log("tokenize input: ", input);
16397
  // Let tokenizer be a new tokenizer.
16398
  // Set tokenizer's input to input.
16399
  // Set tokenizer's policy to policy.
16400
0
  auto tokenizer = Tokenizer(input, policy);
16401
  // While tokenizer's index is less than tokenizer's input's code point length:
16402
0
  while (tokenizer.index < tokenizer.input.size()) {
16403
    // Run seek and get the next code point given tokenizer and tokenizer's
16404
    // index.
16405
0
    tokenizer.seek_and_get_next_code_point(tokenizer.index);
16406
16407
    // If tokenizer's code point is U+002A (*):
16408
0
    if (tokenizer.code_point == '*') {
16409
      // Run add a token with default position and length given tokenizer and
16410
      // "asterisk".
16411
0
      tokenizer.add_token_with_defaults(token_type::ASTERISK);
16412
0
      ada_log("add ASTERISK token");
16413
      // Continue.
16414
0
      continue;
16415
0
    }
16416
16417
    // If tokenizer's code point is U+002B (+) or U+003F (?):
16418
0
    if (tokenizer.code_point == '+' || tokenizer.code_point == '?') {
16419
      // Run add a token with default position and length given tokenizer and
16420
      // "other-modifier".
16421
0
      tokenizer.add_token_with_defaults(token_type::OTHER_MODIFIER);
16422
      // Continue.
16423
0
      continue;
16424
0
    }
16425
16426
    // If tokenizer's code point is U+005C (\):
16427
0
    if (tokenizer.code_point == '\\') {
16428
      // If tokenizer's index is equal to tokenizer's input's code point length
16429
      // - 1:
16430
0
      if (tokenizer.index == tokenizer.input.size() - 1) {
16431
        // Run process a tokenizing error given tokenizer, tokenizer's next
16432
        // index, and tokenizer's index.
16433
0
        if (auto error = tokenizer.process_tokenizing_error(
16434
0
                tokenizer.next_index, tokenizer.index)) {
16435
0
          ada_log("process_tokenizing_error failed");
16436
0
          return tl::unexpected(*error);
16437
0
        }
16438
0
        continue;
16439
0
      }
16440
16441
      // Let escaped index be tokenizer's next index.
16442
0
      auto escaped_index = tokenizer.next_index;
16443
      // Run get the next code point given tokenizer.
16444
0
      tokenizer.get_next_code_point();
16445
      // Run add a token with default length given tokenizer, "escaped-char",
16446
      // tokenizer's next index, and escaped index.
16447
0
      tokenizer.add_token_with_default_length(
16448
0
          token_type::ESCAPED_CHAR, tokenizer.next_index, escaped_index);
16449
0
      ada_log("add ESCAPED_CHAR token on next_index ", tokenizer.next_index,
16450
0
              " with escaped index ", escaped_index);
16451
      // Continue.
16452
0
      continue;
16453
0
    }
16454
16455
    // If tokenizer's code point is U+007B ({):
16456
0
    if (tokenizer.code_point == '{') {
16457
      // Run add a token with default position and length given tokenizer and
16458
      // "open".
16459
0
      tokenizer.add_token_with_defaults(token_type::OPEN);
16460
0
      ada_log("add OPEN token");
16461
0
      continue;
16462
0
    }
16463
16464
    // If tokenizer's code point is U+007D (}):
16465
0
    if (tokenizer.code_point == '}') {
16466
      // Run add a token with default position and length given tokenizer and
16467
      // "close".
16468
0
      tokenizer.add_token_with_defaults(token_type::CLOSE);
16469
0
      ada_log("add CLOSE token");
16470
0
      continue;
16471
0
    }
16472
16473
    // If tokenizer's code point is U+003A (:):
16474
0
    if (tokenizer.code_point == ':') {
16475
      // Let name position be tokenizer's next index.
16476
0
      auto name_position = tokenizer.next_index;
16477
      // Let name start be name position.
16478
0
      auto name_start = name_position;
16479
      // While name position is less than tokenizer's input's code point length:
16480
0
      while (name_position < tokenizer.input.size()) {
16481
        // Run seek and get the next code point given tokenizer and name
16482
        // position.
16483
0
        tokenizer.seek_and_get_next_code_point(name_position);
16484
        // Let first code point be true if name position equals name start and
16485
        // false otherwise.
16486
0
        bool first_code_point = name_position == name_start;
16487
        // Let valid code point be the result of running is a valid name code
16488
        // point given tokenizer's code point and first code point.
16489
0
        auto valid_code_point =
16490
0
            idna::valid_name_code_point(tokenizer.code_point, first_code_point);
16491
0
        ada_log("tokenizer.code_point=", uint32_t(tokenizer.code_point),
16492
0
                " first_code_point=", first_code_point,
16493
0
                " valid_code_point=", valid_code_point);
16494
        // If valid code point is false break.
16495
0
        if (!valid_code_point) break;
16496
        // Set name position to tokenizer's next index.
16497
0
        name_position = tokenizer.next_index;
16498
0
      }
16499
16500
      // If name position is less than or equal to name start:
16501
0
      if (name_position <= name_start) {
16502
        // Run process a tokenizing error given tokenizer, name start, and
16503
        // tokenizer's index.
16504
0
        if (auto error = tokenizer.process_tokenizing_error(name_start,
16505
0
                                                            tokenizer.index)) {
16506
0
          ada_log("process_tokenizing_error failed");
16507
0
          return tl::unexpected(*error);
16508
0
        }
16509
        // Continue
16510
0
        continue;
16511
0
      }
16512
16513
      // Run add a token with default length given tokenizer, "name", name
16514
      // position, and name start.
16515
0
      tokenizer.add_token_with_default_length(token_type::NAME, name_position,
16516
0
                                              name_start);
16517
0
      continue;
16518
0
    }
16519
16520
    // If tokenizer's code point is U+0028 (():
16521
0
    if (tokenizer.code_point == '(') {
16522
      // Let depth be 1.
16523
0
      size_t depth = 1;
16524
      // Let regexp position be tokenizer's next index.
16525
0
      auto regexp_position = tokenizer.next_index;
16526
      // Let regexp start be regexp position.
16527
0
      auto regexp_start = regexp_position;
16528
      // Let error be false.
16529
0
      bool error = false;
16530
16531
      // While regexp position is less than tokenizer's input's code point
16532
      // length:
16533
0
      while (regexp_position < tokenizer.input.size()) {
16534
        // Run seek and get the next code point given tokenizer and regexp
16535
        // position.
16536
0
        tokenizer.seek_and_get_next_code_point(regexp_position);
16537
16538
        // TODO: Optimization opportunity: The next 2 if statements can be
16539
        // merged. If the result of running is ASCII given tokenizer's code
16540
        // point is false:
16541
0
        if (!unicode::is_ascii(tokenizer.code_point)) {
16542
          // Run process a tokenizing error given tokenizer, regexp start, and
16543
          // tokenizer's index.
16544
0
          if (auto process_error = tokenizer.process_tokenizing_error(
16545
0
                  regexp_start, tokenizer.index)) {
16546
0
            return tl::unexpected(*process_error);
16547
0
          }
16548
          // Set error to true.
16549
0
          error = true;
16550
0
          break;
16551
0
        }
16552
16553
        // If regexp position equals regexp start and tokenizer's code point is
16554
        // U+003F (?):
16555
0
        if (regexp_position == regexp_start && tokenizer.code_point == '?') {
16556
          // Run process a tokenizing error given tokenizer, regexp start, and
16557
          // tokenizer's index.
16558
0
          if (auto process_error = tokenizer.process_tokenizing_error(
16559
0
                  regexp_start, tokenizer.index)) {
16560
0
            return tl::unexpected(*process_error);
16561
0
          }
16562
          // Set error to true;
16563
0
          error = true;
16564
0
          break;
16565
0
        }
16566
16567
        // If tokenizer's code point is U+005C (\):
16568
0
        if (tokenizer.code_point == '\\') {
16569
          // If regexp position equals tokenizer's input's code point length - 1
16570
0
          if (regexp_position == tokenizer.input.size() - 1) {
16571
            // Run process a tokenizing error given tokenizer, regexp start, and
16572
            // tokenizer's index.
16573
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16574
0
                    regexp_start, tokenizer.index)) {
16575
0
              return tl::unexpected(*process_error);
16576
0
            }
16577
            // Set error to true.
16578
0
            error = true;
16579
0
            break;
16580
0
          }
16581
          // Run get the next code point given tokenizer.
16582
0
          tokenizer.get_next_code_point();
16583
          // If the result of running is ASCII given tokenizer's code point is
16584
          // false:
16585
0
          if (!unicode::is_ascii(tokenizer.code_point)) {
16586
            // Run process a tokenizing error given tokenizer, regexp start, and
16587
            // tokenizer's index.
16588
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16589
0
                    regexp_start, tokenizer.index);
16590
0
                process_error.has_value()) {
16591
0
              return tl::unexpected(*process_error);
16592
0
            }
16593
            // Set error to true.
16594
0
            error = true;
16595
0
            break;
16596
0
          }
16597
          // Set regexp position to tokenizer's next index.
16598
0
          regexp_position = tokenizer.next_index;
16599
0
          continue;
16600
0
        }
16601
16602
        // If tokenizer's code point is U+0029 ()):
16603
0
        if (tokenizer.code_point == ')') {
16604
          // Decrement depth by 1.
16605
0
          depth--;
16606
          // If depth is 0:
16607
0
          if (depth == 0) {
16608
            // Set regexp position to tokenizer's next index.
16609
0
            regexp_position = tokenizer.next_index;
16610
            // Break.
16611
0
            break;
16612
0
          }
16613
0
        } else if (tokenizer.code_point == '(') {
16614
          // Otherwise if tokenizer's code point is U+0028 (():
16615
          // Increment depth by 1.
16616
0
          depth++;
16617
          // If regexp position equals tokenizer's input's code point length -
16618
          // 1:
16619
0
          if (regexp_position == tokenizer.input.size() - 1) {
16620
            // Run process a tokenizing error given tokenizer, regexp start, and
16621
            // tokenizer's index.
16622
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16623
0
                    regexp_start, tokenizer.index)) {
16624
0
              return tl::unexpected(*process_error);
16625
0
            }
16626
            // Set error to true.
16627
0
            error = true;
16628
0
            break;
16629
0
          }
16630
          // Let temporary position be tokenizer's next index.
16631
0
          auto temporary_position = tokenizer.next_index;
16632
          // Run get the next code point given tokenizer.
16633
0
          tokenizer.get_next_code_point();
16634
          // If tokenizer's code point is not U+003F (?):
16635
0
          if (tokenizer.code_point != '?') {
16636
            // Run process a tokenizing error given tokenizer, regexp start, and
16637
            // tokenizer's index.
16638
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16639
0
                    regexp_start, tokenizer.index)) {
16640
0
              return tl::unexpected(*process_error);
16641
0
            }
16642
            // Set error to true.
16643
0
            error = true;
16644
0
            break;
16645
0
          }
16646
          // Set tokenizer's next index to temporary position.
16647
0
          tokenizer.next_index = temporary_position;
16648
0
        }
16649
        // Set regexp position to tokenizer's next index.
16650
0
        regexp_position = tokenizer.next_index;
16651
0
      }
16652
16653
      // If error is true continue.
16654
0
      if (error) continue;
16655
      // If depth is not zero:
16656
0
      if (depth != 0) {
16657
        // Run process a tokenizing error given tokenizer, regexp start, and
16658
        // tokenizer's index.
16659
0
        if (auto process_error = tokenizer.process_tokenizing_error(
16660
0
                regexp_start, tokenizer.index)) {
16661
0
          return tl::unexpected(*process_error);
16662
0
        }
16663
0
        continue;
16664
0
      }
16665
      // Let regexp length be regexp position - regexp start - 1.
16666
0
      auto regexp_length = regexp_position - regexp_start - 1;
16667
      // If regexp length is zero:
16668
0
      if (regexp_length == 0) {
16669
        // Run process a tokenizing error given tokenizer, regexp start, and
16670
        // tokenizer's index.
16671
0
        if (auto process_error = tokenizer.process_tokenizing_error(
16672
0
                regexp_start, tokenizer.index)) {
16673
0
          ada_log("process_tokenizing_error failed");
16674
0
          return tl::unexpected(*process_error);
16675
0
        }
16676
0
        continue;
16677
0
      }
16678
      // Run add a token given tokenizer, "regexp", regexp position, regexp
16679
      // start, and regexp length.
16680
0
      tokenizer.add_token(token_type::REGEXP, regexp_position, regexp_start,
16681
0
                          regexp_length);
16682
0
      continue;
16683
0
    }
16684
    // Run add a token with default position and length given tokenizer and
16685
    // "char".
16686
0
    tokenizer.add_token_with_defaults(token_type::CHAR);
16687
0
  }
16688
  // Run add a token with default length given tokenizer, "end", tokenizer's
16689
  // index, and tokenizer's index.
16690
0
  tokenizer.add_token_with_default_length(token_type::END, tokenizer.index,
16691
0
                                          tokenizer.index);
16692
16693
0
  ada_log("tokenizer.token_list size is: ", tokenizer.token_list.size());
16694
  // Return tokenizer's token list.
16695
0
  return tokenizer.token_list;
16696
0
}
16697
16698
0
std::string escape_pattern_string(std::string_view input) {
16699
0
  ada_log("escape_pattern_string called with input=", input);
16700
0
  if (input.empty()) [[unlikely]] {
16701
0
    return "";
16702
0
  }
16703
  // Assert: input is an ASCII string.
16704
0
  ADA_ASSERT_TRUE(ada::idna::is_ascii(input));
16705
  // Let result be the empty string.
16706
0
  std::string result{};
16707
0
  result.reserve(input.size());
16708
16709
  // TODO: Optimization opportunity: Use a lookup table
16710
0
  constexpr auto should_escape = [](const char c) {
16711
0
    return c == '+' || c == '*' || c == '?' || c == ':' || c == '{' ||
16712
0
           c == '}' || c == '(' || c == ')' || c == '\\';
16713
0
  };
16714
16715
  // While index is less than input's length:
16716
0
  for (const auto& c : input) {
16717
0
    if (should_escape(c)) {
16718
      // then append U+005C (\) to the end of result.
16719
0
      result.append("\\");
16720
0
    }
16721
16722
    // Append c to the end of result.
16723
0
    result += c;
16724
0
  }
16725
  // Return result.
16726
0
  return result;
16727
0
}
16728
16729
namespace {
16730
constexpr std::array<uint8_t, 256> escape_regexp_table = []() consteval {
16731
  std::array<uint8_t, 256> out{};
16732
  for (auto& c : {'.', '+', '*', '?', '^', '$', '{', '}', '(', ')', '[', ']',
16733
                  '|', '/', '\\'}) {
16734
    out[c] = 1;
16735
  }
16736
  return out;
16737
}();
16738
16739
0
constexpr bool should_escape_regexp_char(char c) {
16740
0
  return escape_regexp_table[(uint8_t)c];
16741
0
}
16742
}  // namespace
16743
16744
0
std::string escape_regexp_string(std::string_view input) {
16745
  // Assert: input is an ASCII string.
16746
0
  ADA_ASSERT_TRUE(idna::is_ascii(input));
16747
  // Let result be the empty string.
16748
0
  std::string result{};
16749
0
  result.reserve(input.size());
16750
0
  for (const auto& c : input) {
16751
    // TODO: Optimize this even further
16752
0
    if (should_escape_regexp_char(c)) {
16753
0
      result.append(std::string("\\") + c);
16754
0
    } else {
16755
0
      result.push_back(c);
16756
0
    }
16757
0
  }
16758
0
  return result;
16759
0
}
16760
16761
std::string process_base_url_string(std::string_view input,
16762
0
                                    url_pattern_init::process_type type) {
16763
  // If type is not "pattern" return input.
16764
0
  if (type != url_pattern_init::process_type::pattern) {
16765
0
    return std::string(input);
16766
0
  }
16767
  // Return the result of escaping a pattern string given input.
16768
0
  return escape_pattern_string(input);
16769
0
}
16770
16771
constexpr bool is_absolute_pathname(
16772
0
    std::string_view input, url_pattern_init::process_type type) noexcept {
16773
  // If input is the empty string, then return false.
16774
0
  if (input.empty()) [[unlikely]] {
16775
0
    return false;
16776
0
  }
16777
  // If input[0] is U+002F (/), then return true.
16778
0
  if (input.starts_with("/")) return true;
16779
  // If type is "url", then return false.
16780
0
  if (type == url_pattern_init::process_type::url) return false;
16781
  // If input's code point length is less than 2, then return false.
16782
0
  if (input.size() < 2) return false;
16783
  // If input[0] is U+005C (\) and input[1] is U+002F (/), then return true.
16784
  // If input[0] is U+007B ({) and input[1] is U+002F (/), then return true.
16785
  // Return false.
16786
0
  return input[1] == '/' && (input[0] == '\\' || input[0] == '{');
16787
0
}
16788
16789
std::string generate_pattern_string(
16790
    std::vector<url_pattern_part>& part_list,
16791
0
    url_pattern_compile_component_options& options) {
16792
  // Let result be the empty string.
16793
0
  std::string result{};
16794
  // Let index list be the result of getting the indices for part list.
16795
  // For each index of index list:
16796
0
  for (size_t index = 0; index < part_list.size(); index++) {
16797
    // Let part be part list[index].
16798
0
    auto part = part_list[index];
16799
    // Let previous part be part list[index - 1] if index is greater than 0,
16800
    // otherwise let it be null.
16801
    // TODO: Optimization opportunity. Find a way to avoid making a copy here.
16802
0
    std::optional<url_pattern_part> previous_part =
16803
0
        index == 0 ? std::nullopt : std::optional(part_list[index - 1]);
16804
    // Let next part be part list[index + 1] if index is less than index list's
16805
    // size - 1, otherwise let it be null.
16806
0
    std::optional<url_pattern_part> next_part =
16807
0
        index < part_list.size() - 1 ? std::optional(part_list[index + 1])
16808
0
                                     : std::nullopt;
16809
    // If part's type is "fixed-text" then:
16810
0
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
16811
      // If part's modifier is "none" then:
16812
0
      if (part.modifier == url_pattern_part_modifier::none) {
16813
        // Append the result of running escape a pattern string given part's
16814
        // value to the end of result.
16815
0
        result.append(escape_pattern_string(part.value));
16816
0
        continue;
16817
0
      }
16818
      // Append "{" to the end of result.
16819
0
      result += "{";
16820
      // Append the result of running escape a pattern string given part's value
16821
      // to the end of result.
16822
0
      result.append(escape_pattern_string(part.value));
16823
      // Append "}" to the end of result.
16824
0
      result += "}";
16825
      // Append the result of running convert a modifier to a string given
16826
      // part's modifier to the end of result.
16827
0
      result.append(convert_modifier_to_string(part.modifier));
16828
0
      continue;
16829
0
    }
16830
    // Let custom name be true if part's name[0] is not an ASCII digit;
16831
    // otherwise false.
16832
0
    bool custom_name = !unicode::is_ascii_digit(part.name[0]);
16833
    // Let needs grouping be true if at least one of the following are true,
16834
    // otherwise let it be false:
16835
    // - part's suffix is not the empty string.
16836
    // - part's prefix is not the empty string and is not options's prefix code
16837
    // point.
16838
0
    bool needs_grouping =
16839
0
        !part.suffix.empty() ||
16840
0
        (!part.prefix.empty() && part.prefix[0] != options.get_prefix()[0]);
16841
16842
    // If all of the following are true:
16843
    // - needs grouping is false; and
16844
    // - custom name is true; and
16845
    // - part's type is "segment-wildcard"; and
16846
    // - part's modifier is "none"; and
16847
    // - next part is not null; and
16848
    // - next part's prefix is the empty string; and
16849
    // - next part's suffix is the empty string
16850
0
    if (!needs_grouping && custom_name &&
16851
0
        part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
16852
0
        part.modifier == url_pattern_part_modifier::none &&
16853
0
        next_part.has_value() && next_part->prefix.empty() &&
16854
0
        next_part->suffix.empty()) {
16855
      // If next part's type is "fixed-text":
16856
0
      if (next_part->type == url_pattern_part_type::FIXED_TEXT) {
16857
        // Set needs grouping to true if the result of running is a valid name
16858
        // code point given next part's value's first code point and the boolean
16859
        // false is true.
16860
0
        if (idna::valid_name_code_point(next_part->value[0], false)) {
16861
0
          needs_grouping = true;
16862
0
        }
16863
0
      } else {
16864
        // Set needs grouping to true if next part's name[0] is an ASCII digit.
16865
0
        needs_grouping = !next_part->name.empty() &&
16866
0
                         unicode::is_ascii_digit(next_part->name[0]);
16867
0
      }
16868
0
    }
16869
16870
    // If all of the following are true:
16871
    // - needs grouping is false; and
16872
    // - part's prefix is the empty string; and
16873
    // - previous part is not null; and
16874
    // - previous part's type is "fixed-text"; and
16875
    // - previous part's value's last code point is options's prefix code point.
16876
    // then set needs grouping to true.
16877
0
    if (!needs_grouping && part.prefix.empty() && previous_part.has_value() &&
16878
0
        previous_part->type == url_pattern_part_type::FIXED_TEXT &&
16879
0
        !options.get_prefix().empty() &&
16880
0
        previous_part->value.at(previous_part->value.size() - 1) ==
16881
0
            options.get_prefix()[0]) {
16882
0
      needs_grouping = true;
16883
0
    }
16884
16885
    // Assert: part's name is not the empty string or null.
16886
0
    ADA_ASSERT_TRUE(!part.name.empty());
16887
16888
    // If needs grouping is true, then append "{" to the end of result.
16889
0
    if (needs_grouping) {
16890
0
      result.append("{");
16891
0
    }
16892
16893
    // Append the result of running escape a pattern string given part's prefix
16894
    // to the end of result.
16895
0
    result.append(escape_pattern_string(part.prefix));
16896
16897
    // If custom name is true:
16898
0
    if (custom_name) {
16899
      // Append ":" to the end of result.
16900
0
      result.append(":");
16901
      // Append part's name to the end of result.
16902
0
      result.append(part.name);
16903
0
    }
16904
16905
    // If part's type is "regexp" then:
16906
0
    if (part.type == url_pattern_part_type::REGEXP) {
16907
      // Append "(" to the end of result.
16908
0
      result.append("(");
16909
      // Append part's value to the end of result.
16910
0
      result.append(part.value);
16911
      // Append ")" to the end of result.
16912
0
      result.append(")");
16913
0
    } else if (part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
16914
0
               !custom_name) {
16915
      // Otherwise if part's type is "segment-wildcard" and custom name is
16916
      // false: Append "(" to the end of result.
16917
0
      result.append("(");
16918
      // Append the result of running generate a segment wildcard regexp given
16919
      // options to the end of result.
16920
0
      result.append(generate_segment_wildcard_regexp(options));
16921
      // Append ")" to the end of result.
16922
0
      result.append(")");
16923
0
    } else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
16924
      // Otherwise if part's type is "full-wildcard":
16925
      // If custom name is false and one of the following is true:
16926
      // - previous part is null; or
16927
      // - previous part's type is "fixed-text"; or
16928
      // - previous part's modifier is not "none"; or
16929
      // - needs grouping is true; or
16930
      // - part's prefix is not the empty string
16931
      // - then append "*" to the end of result.
16932
0
      if (!custom_name &&
16933
0
          (!previous_part.has_value() ||
16934
0
           previous_part->type == url_pattern_part_type::FIXED_TEXT ||
16935
0
           previous_part->modifier != url_pattern_part_modifier::none ||
16936
0
           needs_grouping || !part.prefix.empty())) {
16937
0
        result.append("*");
16938
0
      } else {
16939
        // Append "(" to the end of result.
16940
        // Append full wildcard regexp value to the end of result.
16941
        // Append ")" to the end of result.
16942
0
        result.append("(.*)");
16943
0
      }
16944
0
    }
16945
16946
    // If all of the following are true:
16947
    // - part's type is "segment-wildcard"; and
16948
    // - custom name is true; and
16949
    // - part's suffix is not the empty string; and
16950
    // - The result of running is a valid name code point given part's suffix's
16951
    // first code point and the boolean false is true then append U+005C (\) to
16952
    // the end of result.
16953
0
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD && custom_name &&
16954
0
        !part.suffix.empty() &&
16955
0
        idna::valid_name_code_point(part.suffix[0], false)) {
16956
0
      result.append("\\");
16957
0
    }
16958
16959
    // Append the result of running escape a pattern string given part's suffix
16960
    // to the end of result.
16961
0
    result.append(escape_pattern_string(part.suffix));
16962
    // If needs grouping is true, then append "}" to the end of result.
16963
0
    if (needs_grouping) result.append("}");
16964
    // Append the result of running convert a modifier to a string given part's
16965
    // modifier to the end of result.
16966
0
    result.append(convert_modifier_to_string(part.modifier));
16967
0
  }
16968
  // Return result.
16969
0
  return result;
16970
0
}
16971
}  // namespace ada::url_pattern_helpers
16972
16973
#endif  // ADA_INCLUDE_URL_PATTERN
16974
/* end file src/url_pattern_helpers.cpp */
16975
/* begin file src/url_pattern_regex.cpp */
16976
#if ADA_INCLUDE_URL_PATTERN
16977
16978
16979
namespace ada::url_pattern_regex {
16980
16981
#ifdef ADA_USE_UNSAFE_STD_REGEX_PROVIDER
16982
std::optional<std::regex> std_regex_provider::create_instance(
16983
    std::string_view pattern, bool ignore_case) {
16984
  // Let flags be an empty string.
16985
  // If options's ignore case is true then set flags to "vi".
16986
  // Otherwise set flags to "v"
16987
  auto flags = ignore_case
16988
                   ? std::regex::icase | std::regex_constants::ECMAScript
16989
                   : std::regex_constants::ECMAScript;
16990
  try {
16991
    return std::regex(pattern.data(), pattern.size(), flags);
16992
  } catch (const std::regex_error& e) {
16993
    (void)e;
16994
    ada_log("std_regex_provider::create_instance failed:", e.what());
16995
    return std::nullopt;
16996
  }
16997
}
16998
16999
std::optional<std::vector<std::optional<std::string>>>
17000
std_regex_provider::regex_search(std::string_view input,
17001
                                 const std::regex& pattern) {
17002
  std::string input_str(
17003
      input.begin(),
17004
      input.end());  // Convert string_view to string for regex_search
17005
  std::smatch match_result;
17006
  if (!std::regex_search(input_str, match_result, pattern,
17007
                         std::regex_constants::match_any)) {
17008
    return std::nullopt;
17009
  }
17010
  std::vector<std::optional<std::string>> matches;
17011
  // If input is empty, let's assume the result will be empty as well.
17012
  if (input.empty() || match_result.empty()) {
17013
    return matches;
17014
  }
17015
  matches.reserve(match_result.size());
17016
  for (size_t i = 1; i < match_result.size(); ++i) {
17017
    if (auto entry = match_result[i]; entry.matched) {
17018
      matches.emplace_back(entry.str());
17019
    }
17020
  }
17021
  return matches;
17022
}
17023
17024
bool std_regex_provider::regex_match(std::string_view input,
17025
                                     const std::regex& pattern) {
17026
  return std::regex_match(input.begin(), input.end(), pattern);
17027
}
17028
17029
#endif  // ADA_USE_UNSAFE_STD_REGEX_PROVIDER
17030
17031
}  // namespace ada::url_pattern_regex
17032
17033
#endif  // ADA_INCLUDE_URL_PATTERN
17034
/* end file src/url_pattern_regex.cpp */
17035
#endif  // ADA_INCLUDE_URL_PATTERN
17036
17037
/* begin file src/ada_c.cpp */
17038
17039
0
ada::result<ada::url_aggregator>& get_instance(void* result) noexcept {
17040
0
  return *(ada::result<ada::url_aggregator>*)result;
17041
0
}
17042
17043
extern "C" {
17044
typedef void* ada_url;
17045
typedef void* ada_url_search_params;
17046
typedef void* ada_strings;
17047
typedef void* ada_url_search_params_keys_iter;
17048
typedef void* ada_url_search_params_values_iter;
17049
typedef void* ada_url_search_params_entries_iter;
17050
17051
struct ada_string {
17052
  const char* data;
17053
  size_t length;
17054
};
17055
17056
struct ada_owned_string {
17057
  const char* data;
17058
  size_t length;
17059
};
17060
17061
struct ada_string_pair {
17062
  ada_string key;
17063
  ada_string value;
17064
};
17065
17066
0
ada_string ada_string_create(const char* data, size_t length) {
17067
0
  ada_string out{};
17068
0
  out.data = data;
17069
0
  out.length = length;
17070
0
  return out;
17071
0
}
17072
17073
struct ada_url_components {
17074
  /*
17075
   * By using 32-bit integers, we implicitly assume that the URL string
17076
   * cannot exceed 4 GB.
17077
   *
17078
   * https://user:pass@example.com:1234/foo/bar?baz#quux
17079
   *       |     |    |          | ^^^^|       |   |
17080
   *       |     |    |          | |   |       |   `----- hash_start
17081
   *       |     |    |          | |   |       `--------- search_start
17082
   *       |     |    |          | |   `----------------- pathname_start
17083
   *       |     |    |          | `--------------------- port
17084
   *       |     |    |          `----------------------- host_end
17085
   *       |     |    `---------------------------------- host_start
17086
   *       |     `--------------------------------------- username_end
17087
   *       `--------------------------------------------- protocol_end
17088
   */
17089
  uint32_t protocol_end;
17090
  /**
17091
   * Username end is not `omitted` by default (-1) to make username and password
17092
   * getters less costly to implement.
17093
   */
17094
  uint32_t username_end;
17095
  uint32_t host_start;
17096
  uint32_t host_end;
17097
  uint32_t port;
17098
  uint32_t pathname_start;
17099
  uint32_t search_start;
17100
  uint32_t hash_start;
17101
};
17102
17103
0
ada_url ada_parse(const char* input, size_t length) noexcept {
17104
0
  return new ada::result<ada::url_aggregator>(
17105
0
      ada::parse<ada::url_aggregator>(std::string_view(input, length)));
17106
0
}
17107
17108
ada_url ada_parse_with_base(const char* input, size_t input_length,
17109
0
                            const char* base, size_t base_length) noexcept {
17110
0
  auto base_out =
17111
0
      ada::parse<ada::url_aggregator>(std::string_view(base, base_length));
17112
17113
0
  if (!base_out) {
17114
0
    return new ada::result<ada::url_aggregator>(base_out);
17115
0
  }
17116
17117
0
  return new ada::result<ada::url_aggregator>(ada::parse<ada::url_aggregator>(
17118
0
      std::string_view(input, input_length), &base_out.value()));
17119
0
}
17120
17121
0
bool ada_can_parse(const char* input, size_t length) noexcept {
17122
0
  return ada::can_parse(std::string_view(input, length));
17123
0
}
17124
17125
bool ada_can_parse_with_base(const char* input, size_t input_length,
17126
0
                             const char* base, size_t base_length) noexcept {
17127
0
  std::string_view base_view(base, base_length);
17128
0
  return ada::can_parse(std::string_view(input, input_length), &base_view);
17129
0
}
17130
17131
0
void ada_free(ada_url result) noexcept {
17132
0
  auto* r = (ada::result<ada::url_aggregator>*)result;
17133
0
  delete r;
17134
0
}
17135
17136
0
ada_url ada_copy(ada_url input) noexcept {
17137
0
  ada::result<ada::url_aggregator>& r = get_instance(input);
17138
0
  return new ada::result<ada::url_aggregator>(r);
17139
0
}
17140
17141
0
bool ada_is_valid(ada_url result) noexcept {
17142
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17143
0
  return r.has_value();
17144
0
}
17145
17146
// caller must free the result with ada_free_owned_string
17147
0
ada_owned_string ada_get_origin(ada_url result) noexcept {
17148
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17149
0
  ada_owned_string owned{};
17150
0
  if (!r) {
17151
0
    owned.data = nullptr;
17152
0
    owned.length = 0;
17153
0
    return owned;
17154
0
  }
17155
0
  std::string out = r->get_origin();
17156
0
  owned.length = out.size();
17157
0
  owned.data = new char[owned.length];
17158
0
  memcpy((void*)owned.data, out.data(), owned.length);
17159
0
  return owned;
17160
0
}
17161
17162
0
void ada_free_owned_string(ada_owned_string owned) noexcept {
17163
0
  delete[] owned.data;
17164
0
}
17165
17166
0
ada_string ada_get_href(ada_url result) noexcept {
17167
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17168
0
  if (!r) {
17169
0
    return ada_string_create(nullptr, 0);
17170
0
  }
17171
0
  std::string_view out = r->get_href();
17172
0
  return ada_string_create(out.data(), out.length());
17173
0
}
17174
17175
0
ada_string ada_get_username(ada_url result) noexcept {
17176
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17177
0
  if (!r) {
17178
0
    return ada_string_create(nullptr, 0);
17179
0
  }
17180
0
  std::string_view out = r->get_username();
17181
0
  return ada_string_create(out.data(), out.length());
17182
0
}
17183
17184
0
ada_string ada_get_password(ada_url result) noexcept {
17185
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17186
0
  if (!r) {
17187
0
    return ada_string_create(nullptr, 0);
17188
0
  }
17189
0
  std::string_view out = r->get_password();
17190
0
  return ada_string_create(out.data(), out.length());
17191
0
}
17192
17193
0
ada_string ada_get_port(ada_url result) noexcept {
17194
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17195
0
  if (!r) {
17196
0
    return ada_string_create(nullptr, 0);
17197
0
  }
17198
0
  std::string_view out = r->get_port();
17199
0
  return ada_string_create(out.data(), out.length());
17200
0
}
17201
17202
0
ada_string ada_get_hash(ada_url result) noexcept {
17203
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17204
0
  if (!r) {
17205
0
    return ada_string_create(nullptr, 0);
17206
0
  }
17207
0
  std::string_view out = r->get_hash();
17208
0
  return ada_string_create(out.data(), out.length());
17209
0
}
17210
17211
0
ada_string ada_get_host(ada_url result) noexcept {
17212
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17213
0
  if (!r) {
17214
0
    return ada_string_create(nullptr, 0);
17215
0
  }
17216
0
  std::string_view out = r->get_host();
17217
0
  return ada_string_create(out.data(), out.length());
17218
0
}
17219
17220
0
ada_string ada_get_hostname(ada_url result) noexcept {
17221
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17222
0
  if (!r) {
17223
0
    return ada_string_create(nullptr, 0);
17224
0
  }
17225
0
  std::string_view out = r->get_hostname();
17226
0
  return ada_string_create(out.data(), out.length());
17227
0
}
17228
17229
0
ada_string ada_get_pathname(ada_url result) noexcept {
17230
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17231
0
  if (!r) {
17232
0
    return ada_string_create(nullptr, 0);
17233
0
  }
17234
0
  std::string_view out = r->get_pathname();
17235
0
  return ada_string_create(out.data(), out.length());
17236
0
}
17237
17238
0
ada_string ada_get_search(ada_url result) noexcept {
17239
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17240
0
  if (!r) {
17241
0
    return ada_string_create(nullptr, 0);
17242
0
  }
17243
0
  std::string_view out = r->get_search();
17244
0
  return ada_string_create(out.data(), out.length());
17245
0
}
17246
17247
0
ada_string ada_get_protocol(ada_url result) noexcept {
17248
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17249
0
  if (!r) {
17250
0
    return ada_string_create(nullptr, 0);
17251
0
  }
17252
0
  std::string_view out = r->get_protocol();
17253
0
  return ada_string_create(out.data(), out.length());
17254
0
}
17255
17256
0
uint8_t ada_get_host_type(ada_url result) noexcept {
17257
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17258
0
  if (!r) {
17259
0
    return 0;
17260
0
  }
17261
0
  return r->host_type;
17262
0
}
17263
17264
0
uint8_t ada_get_scheme_type(ada_url result) noexcept {
17265
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17266
0
  if (!r) {
17267
0
    return 0;
17268
0
  }
17269
0
  return r->type;
17270
0
}
17271
17272
0
bool ada_set_href(ada_url result, const char* input, size_t length) noexcept {
17273
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17274
0
  if (!r) {
17275
0
    return false;
17276
0
  }
17277
0
  return r->set_href(std::string_view(input, length));
17278
0
}
17279
17280
0
bool ada_set_host(ada_url result, const char* input, size_t length) noexcept {
17281
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17282
0
  if (!r) {
17283
0
    return false;
17284
0
  }
17285
0
  return r->set_host(std::string_view(input, length));
17286
0
}
17287
17288
bool ada_set_hostname(ada_url result, const char* input,
17289
0
                      size_t length) noexcept {
17290
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17291
0
  if (!r) {
17292
0
    return false;
17293
0
  }
17294
0
  return r->set_hostname(std::string_view(input, length));
17295
0
}
17296
17297
bool ada_set_protocol(ada_url result, const char* input,
17298
0
                      size_t length) noexcept {
17299
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17300
0
  if (!r) {
17301
0
    return false;
17302
0
  }
17303
0
  return r->set_protocol(std::string_view(input, length));
17304
0
}
17305
17306
bool ada_set_username(ada_url result, const char* input,
17307
0
                      size_t length) noexcept {
17308
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17309
0
  if (!r) {
17310
0
    return false;
17311
0
  }
17312
0
  return r->set_username(std::string_view(input, length));
17313
0
}
17314
17315
bool ada_set_password(ada_url result, const char* input,
17316
0
                      size_t length) noexcept {
17317
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17318
0
  if (!r) {
17319
0
    return false;
17320
0
  }
17321
0
  return r->set_password(std::string_view(input, length));
17322
0
}
17323
17324
0
bool ada_set_port(ada_url result, const char* input, size_t length) noexcept {
17325
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17326
0
  if (!r) {
17327
0
    return false;
17328
0
  }
17329
0
  return r->set_port(std::string_view(input, length));
17330
0
}
17331
17332
bool ada_set_pathname(ada_url result, const char* input,
17333
0
                      size_t length) noexcept {
17334
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17335
0
  if (!r) {
17336
0
    return false;
17337
0
  }
17338
0
  return r->set_pathname(std::string_view(input, length));
17339
0
}
17340
17341
/**
17342
 * Update the search/query of the URL.
17343
 *
17344
 * If a URL has `?` as the search value, passing empty string to this function
17345
 * does not remove the attribute. If you need to remove it, please use
17346
 * `ada_clear_search` method.
17347
 */
17348
0
void ada_set_search(ada_url result, const char* input, size_t length) noexcept {
17349
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17350
0
  if (r) {
17351
0
    r->set_search(std::string_view(input, length));
17352
0
  }
17353
0
}
17354
17355
/**
17356
 * Update the hash/fragment of the URL.
17357
 *
17358
 * If a URL has `#` as the hash value, passing empty string to this function
17359
 * does not remove the attribute. If you need to remove it, please use
17360
 * `ada_clear_hash` method.
17361
 */
17362
0
void ada_set_hash(ada_url result, const char* input, size_t length) noexcept {
17363
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17364
0
  if (r) {
17365
0
    r->set_hash(std::string_view(input, length));
17366
0
  }
17367
0
}
17368
17369
0
void ada_clear_port(ada_url result) noexcept {
17370
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17371
0
  if (r) {
17372
0
    r->clear_port();
17373
0
  }
17374
0
}
17375
17376
/**
17377
 * Removes the hash of the URL.
17378
 *
17379
 * Despite `ada_set_hash` method, this function allows the complete
17380
 * removal of the hash attribute, even if it has a value of `#`.
17381
 */
17382
0
void ada_clear_hash(ada_url result) noexcept {
17383
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17384
0
  if (r) {
17385
0
    r->clear_hash();
17386
0
  }
17387
0
}
17388
17389
/**
17390
 * Removes the search of the URL.
17391
 *
17392
 * Despite `ada_set_search` method, this function allows the complete
17393
 * removal of the search attribute, even if it has a value of `?`.
17394
 */
17395
0
void ada_clear_search(ada_url result) noexcept {
17396
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17397
0
  if (r) {
17398
0
    r->clear_search();
17399
0
  }
17400
0
}
17401
17402
0
bool ada_has_credentials(ada_url result) noexcept {
17403
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17404
0
  if (!r) {
17405
0
    return false;
17406
0
  }
17407
0
  return r->has_credentials();
17408
0
}
17409
17410
0
bool ada_has_empty_hostname(ada_url result) noexcept {
17411
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17412
0
  if (!r) {
17413
0
    return false;
17414
0
  }
17415
0
  return r->has_empty_hostname();
17416
0
}
17417
17418
0
bool ada_has_hostname(ada_url result) noexcept {
17419
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17420
0
  if (!r) {
17421
0
    return false;
17422
0
  }
17423
0
  return r->has_hostname();
17424
0
}
17425
17426
0
bool ada_has_non_empty_username(ada_url result) noexcept {
17427
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17428
0
  if (!r) {
17429
0
    return false;
17430
0
  }
17431
0
  return r->has_non_empty_username();
17432
0
}
17433
17434
0
bool ada_has_non_empty_password(ada_url result) noexcept {
17435
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17436
0
  if (!r) {
17437
0
    return false;
17438
0
  }
17439
0
  return r->has_non_empty_password();
17440
0
}
17441
17442
0
bool ada_has_port(ada_url result) noexcept {
17443
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17444
0
  if (!r) {
17445
0
    return false;
17446
0
  }
17447
0
  return r->has_port();
17448
0
}
17449
17450
0
bool ada_has_password(ada_url result) noexcept {
17451
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17452
0
  if (!r) {
17453
0
    return false;
17454
0
  }
17455
0
  return r->has_password();
17456
0
}
17457
17458
0
bool ada_has_hash(ada_url result) noexcept {
17459
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17460
0
  if (!r) {
17461
0
    return false;
17462
0
  }
17463
0
  return r->has_hash();
17464
0
}
17465
17466
0
bool ada_has_search(ada_url result) noexcept {
17467
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17468
0
  if (!r) {
17469
0
    return false;
17470
0
  }
17471
0
  return r->has_search();
17472
0
}
17473
17474
// returns a pointer to the internal url_aggregator::url_components
17475
0
const ada_url_components* ada_get_components(ada_url result) noexcept {
17476
0
  static_assert(sizeof(ada_url_components) == sizeof(ada::url_components));
17477
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17478
0
  if (!r) {
17479
0
    return nullptr;
17480
0
  }
17481
0
  return reinterpret_cast<const ada_url_components*>(&r->get_components());
17482
0
}
17483
17484
0
ada_owned_string ada_idna_to_unicode(const char* input, size_t length) {
17485
0
  std::string out = ada::idna::to_unicode(std::string_view(input, length));
17486
0
  ada_owned_string owned{};
17487
0
  owned.length = out.length();
17488
0
  owned.data = new char[owned.length];
17489
0
  memcpy((void*)owned.data, out.data(), owned.length);
17490
0
  return owned;
17491
0
}
17492
17493
0
ada_owned_string ada_idna_to_ascii(const char* input, size_t length) {
17494
0
  std::string out = ada::idna::to_ascii(std::string_view(input, length));
17495
0
  ada_owned_string owned{};
17496
0
  owned.length = out.size();
17497
0
  owned.data = new char[owned.length];
17498
0
  memcpy((void*)owned.data, out.data(), owned.length);
17499
0
  return owned;
17500
0
}
17501
17502
ada_url_search_params ada_parse_search_params(const char* input,
17503
0
                                              size_t length) {
17504
0
  return new ada::result<ada::url_search_params>(
17505
0
      ada::url_search_params(std::string_view(input, length)));
17506
0
}
17507
17508
0
void ada_free_search_params(ada_url_search_params result) {
17509
0
  auto* r = (ada::result<ada::url_search_params>*)result;
17510
0
  delete r;
17511
0
}
17512
17513
0
ada_owned_string ada_search_params_to_string(ada_url_search_params result) {
17514
0
  ada::result<ada::url_search_params>& r =
17515
0
      *(ada::result<ada::url_search_params>*)result;
17516
0
  if (!r) return ada_owned_string{nullptr, 0};
17517
0
  std::string out = r->to_string();
17518
0
  ada_owned_string owned{};
17519
0
  owned.length = out.size();
17520
0
  owned.data = new char[owned.length];
17521
0
  memcpy((void*)owned.data, out.data(), owned.length);
17522
0
  return owned;
17523
0
}
17524
17525
0
size_t ada_search_params_size(ada_url_search_params result) {
17526
0
  ada::result<ada::url_search_params>& r =
17527
0
      *(ada::result<ada::url_search_params>*)result;
17528
0
  if (!r) {
17529
0
    return 0;
17530
0
  }
17531
0
  return r->size();
17532
0
}
17533
17534
0
void ada_search_params_sort(ada_url_search_params result) {
17535
0
  ada::result<ada::url_search_params>& r =
17536
0
      *(ada::result<ada::url_search_params>*)result;
17537
0
  if (r) {
17538
0
    r->sort();
17539
0
  }
17540
0
}
17541
17542
void ada_search_params_reset(ada_url_search_params result, const char* input,
17543
0
                             size_t length) {
17544
0
  ada::result<ada::url_search_params>& r =
17545
0
      *(ada::result<ada::url_search_params>*)result;
17546
0
  if (r) {
17547
0
    r->reset(std::string_view(input, length));
17548
0
  }
17549
0
}
17550
17551
void ada_search_params_append(ada_url_search_params result, const char* key,
17552
                              size_t key_length, const char* value,
17553
0
                              size_t value_length) {
17554
0
  ada::result<ada::url_search_params>& r =
17555
0
      *(ada::result<ada::url_search_params>*)result;
17556
0
  if (r) {
17557
0
    r->append(std::string_view(key, key_length),
17558
0
              std::string_view(value, value_length));
17559
0
  }
17560
0
}
17561
17562
void ada_search_params_set(ada_url_search_params result, const char* key,
17563
                           size_t key_length, const char* value,
17564
0
                           size_t value_length) {
17565
0
  ada::result<ada::url_search_params>& r =
17566
0
      *(ada::result<ada::url_search_params>*)result;
17567
0
  if (r) {
17568
0
    r->set(std::string_view(key, key_length),
17569
0
           std::string_view(value, value_length));
17570
0
  }
17571
0
}
17572
17573
void ada_search_params_remove(ada_url_search_params result, const char* key,
17574
0
                              size_t key_length) {
17575
0
  ada::result<ada::url_search_params>& r =
17576
0
      *(ada::result<ada::url_search_params>*)result;
17577
0
  if (r) {
17578
0
    r->remove(std::string_view(key, key_length));
17579
0
  }
17580
0
}
17581
17582
void ada_search_params_remove_value(ada_url_search_params result,
17583
                                    const char* key, size_t key_length,
17584
0
                                    const char* value, size_t value_length) {
17585
0
  ada::result<ada::url_search_params>& r =
17586
0
      *(ada::result<ada::url_search_params>*)result;
17587
0
  if (r) {
17588
0
    r->remove(std::string_view(key, key_length),
17589
0
              std::string_view(value, value_length));
17590
0
  }
17591
0
}
17592
17593
bool ada_search_params_has(ada_url_search_params result, const char* key,
17594
0
                           size_t key_length) {
17595
0
  ada::result<ada::url_search_params>& r =
17596
0
      *(ada::result<ada::url_search_params>*)result;
17597
0
  if (!r) {
17598
0
    return false;
17599
0
  }
17600
0
  return r->has(std::string_view(key, key_length));
17601
0
}
17602
17603
bool ada_search_params_has_value(ada_url_search_params result, const char* key,
17604
                                 size_t key_length, const char* value,
17605
0
                                 size_t value_length) {
17606
0
  ada::result<ada::url_search_params>& r =
17607
0
      *(ada::result<ada::url_search_params>*)result;
17608
0
  if (!r) {
17609
0
    return false;
17610
0
  }
17611
0
  return r->has(std::string_view(key, key_length),
17612
0
                std::string_view(value, value_length));
17613
0
}
17614
17615
ada_string ada_search_params_get(ada_url_search_params result, const char* key,
17616
0
                                 size_t key_length) {
17617
0
  ada::result<ada::url_search_params>& r =
17618
0
      *(ada::result<ada::url_search_params>*)result;
17619
0
  if (!r) {
17620
0
    return ada_string_create(nullptr, 0);
17621
0
  }
17622
0
  auto found = r->get(std::string_view(key, key_length));
17623
0
  if (!found.has_value()) {
17624
0
    return ada_string_create(nullptr, 0);
17625
0
  }
17626
0
  return ada_string_create(found->data(), found->length());
17627
0
}
17628
17629
ada_strings ada_search_params_get_all(ada_url_search_params result,
17630
0
                                      const char* key, size_t key_length) {
17631
0
  ada::result<ada::url_search_params>& r =
17632
0
      *(ada::result<ada::url_search_params>*)result;
17633
0
  if (!r) {
17634
0
    return new ada::result<std::vector<std::string>>(
17635
0
        std::vector<std::string>());
17636
0
  }
17637
0
  return new ada::result<std::vector<std::string>>(
17638
0
      r->get_all(std::string_view(key, key_length)));
17639
0
}
17640
17641
ada_url_search_params_keys_iter ada_search_params_get_keys(
17642
0
    ada_url_search_params result) {
17643
0
  ada::result<ada::url_search_params>& r =
17644
0
      *(ada::result<ada::url_search_params>*)result;
17645
0
  if (!r) {
17646
0
    return new ada::result<ada::url_search_params_keys_iter>(
17647
0
        ada::url_search_params_keys_iter());
17648
0
  }
17649
0
  return new ada::result<ada::url_search_params_keys_iter>(r->get_keys());
17650
0
}
17651
17652
ada_url_search_params_values_iter ada_search_params_get_values(
17653
0
    ada_url_search_params result) {
17654
0
  ada::result<ada::url_search_params>& r =
17655
0
      *(ada::result<ada::url_search_params>*)result;
17656
0
  if (!r) {
17657
0
    return new ada::result<ada::url_search_params_values_iter>(
17658
0
        ada::url_search_params_values_iter());
17659
0
  }
17660
0
  return new ada::result<ada::url_search_params_values_iter>(r->get_values());
17661
0
}
17662
17663
ada_url_search_params_entries_iter ada_search_params_get_entries(
17664
0
    ada_url_search_params result) {
17665
0
  ada::result<ada::url_search_params>& r =
17666
0
      *(ada::result<ada::url_search_params>*)result;
17667
0
  if (!r) {
17668
0
    return new ada::result<ada::url_search_params_entries_iter>(
17669
0
        ada::url_search_params_entries_iter());
17670
0
  }
17671
0
  return new ada::result<ada::url_search_params_entries_iter>(r->get_entries());
17672
0
}
17673
17674
0
void ada_free_strings(ada_strings result) {
17675
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
17676
0
  delete r;
17677
0
}
17678
17679
0
size_t ada_strings_size(ada_strings result) {
17680
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
17681
0
  if (!r) {
17682
0
    return 0;
17683
0
  }
17684
0
  return (*r)->size();
17685
0
}
17686
17687
0
ada_string ada_strings_get(ada_strings result, size_t index) {
17688
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
17689
0
  if (!r) {
17690
0
    return ada_string_create(nullptr, 0);
17691
0
  }
17692
0
  std::string_view view = (*r)->at(index);
17693
0
  return ada_string_create(view.data(), view.length());
17694
0
}
17695
17696
0
void ada_free_search_params_keys_iter(ada_url_search_params_keys_iter result) {
17697
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
17698
0
  delete r;
17699
0
}
17700
17701
ada_string ada_search_params_keys_iter_next(
17702
0
    ada_url_search_params_keys_iter result) {
17703
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
17704
0
  if (!r) {
17705
0
    return ada_string_create(nullptr, 0);
17706
0
  }
17707
0
  auto next = (*r)->next();
17708
0
  if (!next.has_value()) {
17709
0
    return ada_string_create(nullptr, 0);
17710
0
  }
17711
0
  return ada_string_create(next->data(), next->length());
17712
0
}
17713
17714
bool ada_search_params_keys_iter_has_next(
17715
0
    ada_url_search_params_keys_iter result) {
17716
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
17717
0
  if (!r) {
17718
0
    return false;
17719
0
  }
17720
0
  return (*r)->has_next();
17721
0
}
17722
17723
void ada_free_search_params_values_iter(
17724
0
    ada_url_search_params_values_iter result) {
17725
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
17726
0
  delete r;
17727
0
}
17728
17729
ada_string ada_search_params_values_iter_next(
17730
0
    ada_url_search_params_values_iter result) {
17731
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
17732
0
  if (!r) {
17733
0
    return ada_string_create(nullptr, 0);
17734
0
  }
17735
0
  auto next = (*r)->next();
17736
0
  if (!next.has_value()) {
17737
0
    return ada_string_create(nullptr, 0);
17738
0
  }
17739
0
  return ada_string_create(next->data(), next->length());
17740
0
}
17741
17742
bool ada_search_params_values_iter_has_next(
17743
0
    ada_url_search_params_values_iter result) {
17744
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
17745
0
  if (!r) {
17746
0
    return false;
17747
0
  }
17748
0
  return (*r)->has_next();
17749
0
}
17750
17751
void ada_free_search_params_entries_iter(
17752
0
    ada_url_search_params_entries_iter result) {
17753
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
17754
0
  delete r;
17755
0
}
17756
17757
ada_string_pair ada_search_params_entries_iter_next(
17758
0
    ada_url_search_params_entries_iter result) {
17759
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
17760
0
  if (!r) return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)};
17761
0
  auto next = (*r)->next();
17762
0
  if (!next.has_value()) {
17763
0
    return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)};
17764
0
  }
17765
0
  return ada_string_pair{
17766
0
      ada_string_create(next->first.data(), next->first.length()),
17767
0
      ada_string_create(next->second.data(), next->second.length())};
17768
0
}
17769
17770
bool ada_search_params_entries_iter_has_next(
17771
0
    ada_url_search_params_entries_iter result) {
17772
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
17773
0
  if (!r) {
17774
0
    return false;
17775
0
  }
17776
0
  return (*r)->has_next();
17777
0
}
17778
17779
}  // extern "C"
17780
/* end file src/ada_c.cpp */
17781
/* end file src/ada.cpp */