Coverage Report

Created: 2023-11-27 06:36

/src/ada-url/build/singleheader/ada.cpp
Line
Count
Source (jump to first uncovered line)
1
/* auto-generated on 2023-11-25 19:25:01 -0500. Do not edit! */
2
/* begin file src/ada.cpp */
3
#include "ada.h"
4
/* begin file src/checkers.cpp */
5
#include <algorithm>
6
7
namespace ada::checkers {
8
9
19.5k
ada_really_inline ada_constexpr bool is_ipv4(std::string_view view) noexcept {
10
  // The string is not empty and does not contain upper case ASCII characters.
11
  //
12
  // Optimization. To be considered as a possible ipv4, the string must end
13
  // with 'x' or a lowercase hex character.
14
  // Most of the time, this will be false so this simple check will save a lot
15
  // of effort.
16
19.5k
  char last_char = view.back();
17
  // If the address ends with a dot, we need to prune it (special case).
18
19.5k
  if (last_char == '.') {
19
1.95k
    view.remove_suffix(1);
20
1.95k
    if (view.empty()) {
21
1.32k
      return false;
22
1.32k
    }
23
634
    last_char = view.back();
24
634
  }
25
18.2k
  bool possible_ipv4 = (last_char >= '0' && last_char <= '9') ||
26
18.2k
                       (last_char >= 'a' && last_char <= 'f') ||
27
18.2k
                       last_char == 'x';
28
18.2k
  if (!possible_ipv4) {
29
6.92k
    return false;
30
6.92k
  }
31
  // From the last character, find the last dot.
32
11.3k
  size_t last_dot = view.rfind('.');
33
11.3k
  if (last_dot != std::string_view::npos) {
34
    // We have at least one dot.
35
2.75k
    view = view.substr(last_dot + 1);
36
2.75k
  }
37
  /** Optimization opportunity: we have basically identified the last number of
38
     the ipv4 if we return true here. We might as well parse it and have at
39
     least one number parsed when we get to parse_ipv4. */
40
11.3k
  if (std::all_of(view.begin(), view.end(), ada::checkers::is_digit)) {
41
4.34k
    return true;
42
4.34k
  }
43
  // It could be hex (0x), but not if there is a single character.
44
6.97k
  if (view.size() == 1) {
45
1.67k
    return false;
46
1.67k
  }
47
  // It must start with 0x.
48
5.29k
  if (!std::equal(view.begin(), view.begin() + 2, "0x")) {
49
3.09k
    return false;
50
3.09k
  }
51
  // We must allow "0x".
52
2.20k
  if (view.size() == 2) {
53
130
    return true;
54
130
  }
55
  // We have 0x followed by some characters, we need to check that they are
56
  // hexadecimals.
57
2.07k
  return std::all_of(view.begin() + 2, view.end(),
58
2.07k
                     ada::unicode::is_lowercase_hex);
59
2.20k
}
60
61
// for use with path_signature, we include all characters that need percent
62
// encoding.
63
static constexpr std::array<uint8_t, 256> path_signature_table =
64
    []() constexpr {
65
      std::array<uint8_t, 256> result{};
66
      for (size_t i = 0; i < 256; i++) {
67
        if (i <= 0x20 || i == 0x22 || i == 0x23 || i == 0x3c || i == 0x3e ||
68
            i == 0x3f || i == 0x60 || i == 0x7b || i == 0x7b || i == 0x7d ||
69
            i > 0x7e) {
70
          result[i] = 1;
71
        } else if (i == 0x25) {
72
          result[i] = 8;
73
        } else if (i == 0x2e) {
74
          result[i] = 4;
75
        } else if (i == 0x5c) {
76
          result[i] = 2;
77
        } else {
78
          result[i] = 0;
79
        }
80
      }
81
      return result;
82
    }();
83
84
ada_really_inline constexpr uint8_t path_signature(
85
26.8k
    std::string_view input) noexcept {
86
  // The path percent-encode set is the query percent-encode set and U+003F (?),
87
  // U+0060 (`), U+007B ({), and U+007D (}). The query percent-encode set is the
88
  // C0 control percent-encode set and U+0020 SPACE, U+0022 ("), U+0023 (#),
89
  // U+003C (<), and U+003E (>). The C0 control percent-encode set are the C0
90
  // controls and all code points greater than U+007E (~).
91
26.8k
  size_t i = 0;
92
26.8k
  uint8_t accumulator{};
93
75.6k
  for (; i + 7 < input.size(); i += 8) {
94
48.8k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])] |
95
48.8k
                           path_signature_table[uint8_t(input[i + 1])] |
96
48.8k
                           path_signature_table[uint8_t(input[i + 2])] |
97
48.8k
                           path_signature_table[uint8_t(input[i + 3])] |
98
48.8k
                           path_signature_table[uint8_t(input[i + 4])] |
99
48.8k
                           path_signature_table[uint8_t(input[i + 5])] |
100
48.8k
                           path_signature_table[uint8_t(input[i + 6])] |
101
48.8k
                           path_signature_table[uint8_t(input[i + 7])]);
102
48.8k
  }
103
95.7k
  for (; i < input.size(); i++) {
104
68.9k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])]);
105
68.9k
  }
106
26.8k
  return accumulator;
107
26.8k
}
108
109
ada_really_inline constexpr bool verify_dns_length(
110
0
    std::string_view input) noexcept {
111
0
  if (input.back() == '.') {
112
0
    if (input.size() > 254) return false;
113
0
  } else if (input.size() > 253)
114
0
    return false;
115
116
0
  size_t start = 0;
117
0
  while (start < input.size()) {
118
0
    auto dot_location = input.find('.', start);
119
    // If not found, it's likely the end of the domain
120
0
    if (dot_location == std::string_view::npos) dot_location = input.size();
121
122
0
    auto label_size = dot_location - start;
123
0
    if (label_size > 63 || label_size == 0) return false;
124
125
0
    start = dot_location + 1;
126
0
  }
127
128
0
  return true;
129
0
}
130
}  // namespace ada::checkers
131
/* end file src/checkers.cpp */
132
/* begin file src/unicode.cpp */
133
134
ADA_PUSH_DISABLE_ALL_WARNINGS
135
/* begin file src/ada_idna.cpp */
136
/* auto-generated on 2023-09-19 15:58:51 -0400. Do not edit! */
137
/* begin file src/idna.cpp */
138
/* begin file src/unicode_transcoding.cpp */
139
140
#include <algorithm>
141
#include <cstdint>
142
#include <cstring>
143
144
namespace ada::idna {
145
146
9.89k
size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) {
147
9.89k
  const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
148
9.89k
  size_t pos = 0;
149
9.89k
  char32_t* start{utf32_output};
150
126k
  while (pos < len) {
151
    // try to convert the next block of 16 ASCII bytes
152
119k
    if (pos + 16 <= len) {  // if it is safe to read 16 more
153
                            // bytes, check that they are ascii
154
76.9k
      uint64_t v1;
155
76.9k
      std::memcpy(&v1, data + pos, sizeof(uint64_t));
156
76.9k
      uint64_t v2;
157
76.9k
      std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
158
76.9k
      uint64_t v{v1 | v2};
159
76.9k
      if ((v & 0x8080808080808080) == 0) {
160
2.12k
        size_t final_pos = pos + 16;
161
36.1k
        while (pos < final_pos) {
162
34.0k
          *utf32_output++ = char32_t(buf[pos]);
163
34.0k
          pos++;
164
34.0k
        }
165
2.12k
        continue;
166
2.12k
      }
167
76.9k
    }
168
117k
    uint8_t leading_byte = data[pos];  // leading byte
169
117k
    if (leading_byte < 0b10000000) {
170
      // converting one ASCII byte !!!
171
68.1k
      *utf32_output++ = char32_t(leading_byte);
172
68.1k
      pos++;
173
68.1k
    } else if ((leading_byte & 0b11100000) == 0b11000000) {
174
      // We have a two-byte UTF-8
175
8.68k
      if (pos + 1 >= len) {
176
205
        return 0;
177
205
      }  // minimal bound checking
178
8.47k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
179
365
        return 0;
180
365
      }
181
      // range check
182
8.11k
      uint32_t code_point =
183
8.11k
          (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
184
8.11k
      if (code_point < 0x80 || 0x7ff < code_point) {
185
32
        return 0;
186
32
      }
187
8.07k
      *utf32_output++ = char32_t(code_point);
188
8.07k
      pos += 2;
189
40.3k
    } else if ((leading_byte & 0b11110000) == 0b11100000) {
190
      // We have a three-byte UTF-8
191
37.5k
      if (pos + 2 >= len) {
192
67
        return 0;
193
67
      }  // minimal bound checking
194
195
37.4k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
196
159
        return 0;
197
159
      }
198
37.2k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
199
39
        return 0;
200
39
      }
201
      // range check
202
37.2k
      uint32_t code_point = (leading_byte & 0b00001111) << 12 |
203
37.2k
                            (data[pos + 1] & 0b00111111) << 6 |
204
37.2k
                            (data[pos + 2] & 0b00111111);
205
37.2k
      if (code_point < 0x800 || 0xffff < code_point ||
206
37.2k
          (0xd7ff < code_point && code_point < 0xe000)) {
207
47
        return 0;
208
47
      }
209
37.2k
      *utf32_output++ = char32_t(code_point);
210
37.2k
      pos += 3;
211
37.2k
    } else if ((leading_byte & 0b11111000) == 0b11110000) {  // 0b11110000
212
      // we have a 4-byte UTF-8 word.
213
953
      if (pos + 3 >= len) {
214
77
        return 0;
215
77
      }  // minimal bound checking
216
876
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
217
87
        return 0;
218
87
      }
219
789
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
220
27
        return 0;
221
27
      }
222
762
      if ((data[pos + 3] & 0b11000000) != 0b10000000) {
223
23
        return 0;
224
23
      }
225
226
      // range check
227
739
      uint32_t code_point = (leading_byte & 0b00000111) << 18 |
228
739
                            (data[pos + 1] & 0b00111111) << 12 |
229
739
                            (data[pos + 2] & 0b00111111) << 6 |
230
739
                            (data[pos + 3] & 0b00111111);
231
739
      if (code_point <= 0xffff || 0x10ffff < code_point) {
232
51
        return 0;
233
51
      }
234
688
      *utf32_output++ = char32_t(code_point);
235
688
      pos += 4;
236
1.91k
    } else {
237
1.91k
      return 0;
238
1.91k
    }
239
117k
  }
240
6.79k
  return utf32_output - start;
241
9.89k
}
242
243
1.36k
size_t utf8_length_from_utf32(const char32_t* buf, size_t len) {
244
  // We are not BOM aware.
245
1.36k
  const uint32_t* p = reinterpret_cast<const uint32_t*>(buf);
246
1.36k
  size_t counter{0};
247
6.29k
  for (size_t i = 0; i != len; ++i) {
248
4.92k
    ++counter;                                      // ASCII
249
4.92k
    counter += static_cast<size_t>(p[i] > 0x7F);    // two-byte
250
4.92k
    counter += static_cast<size_t>(p[i] > 0x7FF);   // three-byte
251
4.92k
    counter += static_cast<size_t>(p[i] > 0xFFFF);  // four-bytes
252
4.92k
  }
253
1.36k
  return counter;
254
1.36k
}
255
256
9.89k
size_t utf32_length_from_utf8(const char* buf, size_t len) {
257
9.89k
  const int8_t* p = reinterpret_cast<const int8_t*>(buf);
258
324k
  return std::count_if(p, std::next(p, len), [](int8_t c) {
259
    // -65 is 0b10111111, anything larger in two-complement's
260
    // should start a new code point.
261
324k
    return c > -65;
262
324k
  });
263
9.89k
}
264
265
1.36k
size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) {
266
1.36k
  const uint32_t* data = reinterpret_cast<const uint32_t*>(buf);
267
1.36k
  size_t pos = 0;
268
1.36k
  char* start{utf8_output};
269
5.12k
  while (pos < len) {
270
    // try to convert the next block of 2 ASCII characters
271
3.94k
    if (pos + 2 <= len) {  // if it is safe to read 8 more
272
                           // bytes, check that they are ascii
273
2.93k
      uint64_t v;
274
2.93k
      std::memcpy(&v, data + pos, sizeof(uint64_t));
275
2.93k
      if ((v & 0xFFFFFF80FFFFFF80) == 0) {
276
863
        *utf8_output++ = char(buf[pos]);
277
863
        *utf8_output++ = char(buf[pos + 1]);
278
863
        pos += 2;
279
863
        continue;
280
863
      }
281
2.93k
    }
282
3.08k
    uint32_t word = data[pos];
283
3.08k
    if ((word & 0xFFFFFF80) == 0) {
284
      // will generate one UTF-8 bytes
285
463
      *utf8_output++ = char(word);
286
463
      pos++;
287
2.62k
    } else if ((word & 0xFFFFF800) == 0) {
288
      // will generate two UTF-8 bytes
289
      // we have 0b110XXXXX 0b10XXXXXX
290
780
      *utf8_output++ = char((word >> 6) | 0b11000000);
291
780
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
292
780
      pos++;
293
1.84k
    } else if ((word & 0xFFFF0000) == 0) {
294
      // will generate three UTF-8 bytes
295
      // we have 0b1110XXXX 0b10XXXXXX 0b10XXXXXX
296
966
      if (word >= 0xD800 && word <= 0xDFFF) {
297
43
        return 0;
298
43
      }
299
923
      *utf8_output++ = char((word >> 12) | 0b11100000);
300
923
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
301
923
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
302
923
      pos++;
303
923
    } else {
304
      // will generate four UTF-8 bytes
305
      // we have 0b11110XXX 0b10XXXXXX 0b10XXXXXX
306
      // 0b10XXXXXX
307
877
      if (word > 0x10FFFF) {
308
144
        return 0;
309
144
      }
310
733
      *utf8_output++ = char((word >> 18) | 0b11110000);
311
733
      *utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
312
733
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
313
733
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
314
733
      pos++;
315
733
    }
316
3.08k
  }
317
1.17k
  return utf8_output - start;
318
1.36k
}
319
}  // namespace ada::idna
320
/* end file src/unicode_transcoding.cpp */
321
/* begin file src/mapping.cpp */
322
323
#include <algorithm>
324
#include <array>
325
#include <string>
326
327
/* begin file src/mapping_tables.cpp */
328
// IDNA  15.0.0
329
330
// clang-format off
331
#ifndef ADA_IDNA_TABLES_H
332
#define ADA_IDNA_TABLES_H
333
#include <cstdint>
334
335
namespace ada::idna {
336
337
const uint32_t mappings[5164] =
338
{
339
  97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
340
  114, 115, 116, 117, 118, 119, 120, 121, 122, 32, 32, 776, 32, 772, 50, 51, 32, 769,
341
  956, 32, 807, 49, 49, 8260, 52, 49, 8260, 50, 51, 8260, 52, 224, 225, 226, 227,
342
  228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
343
  244, 245, 246, 248, 249, 250, 251, 252, 253, 254, 257, 259, 261, 263, 265, 267,
344
  269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299,
345
  301, 303, 105, 775, 309, 311, 314, 316, 318, 108, 183, 322, 324, 326, 328, 700,
346
  110, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359,
347
  361, 363, 365, 367, 369, 371, 373, 375, 255, 378, 380, 382, 595, 387, 389, 596,
348
  392, 598, 599, 396, 477, 601, 603, 402, 608, 611, 617, 616, 409, 623, 626, 629,
349
  417, 419, 421, 640, 424, 643, 429, 648, 432, 650, 651, 436, 438, 658, 441, 445,
350
  100, 382, 108, 106, 110, 106, 462, 464, 466, 468, 470, 472, 474, 476, 479, 481,
351
  483, 485, 487, 489, 491, 493, 495, 100, 122, 501, 405, 447, 505, 507, 509, 511,
352
  513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535, 537, 539, 541, 543,
353
  414, 547, 549, 551, 553, 555, 557, 559, 561, 563, 11365, 572, 410, 11366, 578, 384,
354
  649, 652, 583, 585, 587, 589, 591, 614, 633, 635, 641, 32, 774, 32, 775, 32, 778,
355
  32, 808, 32, 771, 32, 779, 661, 768, 787, 776, 769, 953, 881, 883, 697, 887, 32,
356
  953, 59, 1011, 32, 776, 769, 940, 941, 942, 943, 972, 973, 974, 945, 946, 947, 948,
357
  949, 950, 951, 952, 954, 955, 957, 958, 959, 960, 961, 963, 964, 965, 966, 967,
358
  968, 969, 970, 971, 983, 985, 987, 989, 991, 993, 995, 997, 999, 1001, 1003, 1005,
359
  1007, 1016, 1019, 891, 892, 893, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111,
360
  1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1072, 1073, 1074, 1075, 1076, 1077,
361
  1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091,
362
  1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1121, 1123,
363
  1125, 1127, 1129, 1131, 1133, 1135, 1137, 1139, 1141, 1143, 1145, 1147, 1149, 1151,
364
  1153, 1163, 1165, 1167, 1169, 1171, 1173, 1175, 1177, 1179, 1181, 1183, 1185, 1187,
365
  1189, 1191, 1193, 1195, 1197, 1199, 1201, 1203, 1205, 1207, 1209, 1211, 1213, 1215,
366
  1218, 1220, 1222, 1224, 1226, 1228, 1230, 1233, 1235, 1237, 1239, 1241, 1243, 1245,
367
  1247, 1249, 1251, 1253, 1255, 1257, 1259, 1261, 1263, 1265, 1267, 1269, 1271, 1273,
368
  1275, 1277, 1279, 1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, 1297, 1299, 1301,
369
  1303, 1305, 1307, 1309, 1311, 1313, 1315, 1317, 1319, 1321, 1323, 1325, 1327, 1377,
370
  1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391,
371
  1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405,
372
  1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1381, 1410, 1575, 1652, 1608,
373
  1652, 1735, 1652, 1610, 1652, 2325, 2364, 2326, 2364, 2327, 2364, 2332, 2364, 2337,
374
  2364, 2338, 2364, 2347, 2364, 2351, 2364, 2465, 2492, 2466, 2492, 2479, 2492, 2610,
375
  2620, 2616, 2620, 2582, 2620, 2583, 2620, 2588, 2620, 2603, 2620, 2849, 2876, 2850,
376
  2876, 3661, 3634, 3789, 3762, 3755, 3737, 3755, 3745, 3851, 3906, 4023, 3916, 4023,
377
  3921, 4023, 3926, 4023, 3931, 4023, 3904, 4021, 3953, 3954, 3953, 3956, 4018, 3968,
378
  4018, 3953, 3968, 4019, 3968, 4019, 3953, 3968, 3986, 4023, 3996, 4023, 4001, 4023,
379
  4006, 4023, 4011, 4023, 3984, 4021, 11559, 11565, 4316, 5104, 5105, 5106, 5107,
380
  5108, 5109, 42571, 4304, 4305, 4306, 4307, 4308, 4309, 4310, 4311, 4312, 4313, 4314,
381
  4315, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329,
382
  4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343,
383
  4344, 4345, 4346, 4349, 4350, 4351, 592, 593, 7426, 604, 7446, 7447, 7453, 7461,
384
  594, 597, 607, 609, 613, 618, 7547, 669, 621, 7557, 671, 625, 624, 627, 628, 632,
385
  642, 427, 7452, 656, 657, 7681, 7683, 7685, 7687, 7689, 7691, 7693, 7695, 7697,
386
  7699, 7701, 7703, 7705, 7707, 7709, 7711, 7713, 7715, 7717, 7719, 7721, 7723, 7725,
387
  7727, 7729, 7731, 7733, 7735, 7737, 7739, 7741, 7743, 7745, 7747, 7749, 7751, 7753,
388
  7755, 7757, 7759, 7761, 7763, 7765, 7767, 7769, 7771, 7773, 7775, 7777, 7779, 7781,
389
  7783, 7785, 7787, 7789, 7791, 7793, 7795, 7797, 7799, 7801, 7803, 7805, 7807, 7809,
390
  7811, 7813, 7815, 7817, 7819, 7821, 7823, 7825, 7827, 7829, 97, 702, 115, 115, 7841,
391
  7843, 7845, 7847, 7849, 7851, 7853, 7855, 7857, 7859, 7861, 7863, 7865, 7867, 7869,
392
  7871, 7873, 7875, 7877, 7879, 7881, 7883, 7885, 7887, 7889, 7891, 7893, 7895, 7897,
393
  7899, 7901, 7903, 7905, 7907, 7909, 7911, 7913, 7915, 7917, 7919, 7921, 7923, 7925,
394
  7927, 7929, 7931, 7933, 7935, 7936, 7937, 7938, 7939, 7940, 7941, 7942, 7943, 7952,
395
  7953, 7954, 7955, 7956, 7957, 7968, 7969, 7970, 7971, 7972, 7973, 7974, 7975, 7984,
396
  7985, 7986, 7987, 7988, 7989, 7990, 7991, 8000, 8001, 8002, 8003, 8004, 8005, 8017,
397
  8019, 8021, 8023, 8032, 8033, 8034, 8035, 8036, 8037, 8038, 8039, 7936, 953, 7937,
398
  953, 7938, 953, 7939, 953, 7940, 953, 7941, 953, 7942, 953, 7943, 953, 7968, 953,
399
  7969, 953, 7970, 953, 7971, 953, 7972, 953, 7973, 953, 7974, 953, 7975, 953, 8032,
400
  953, 8033, 953, 8034, 953, 8035, 953, 8036, 953, 8037, 953, 8038, 953, 8039, 953,
401
  8048, 953, 945, 953, 940, 953, 8118, 953, 8112, 8113, 32, 787, 32, 834, 32, 776,
402
  834, 8052, 953, 951, 953, 942, 953, 8134, 953, 8050, 32, 787, 768, 32, 787, 769,
403
  32, 787, 834, 912, 8144, 8145, 8054, 32, 788, 768, 32, 788, 769, 32, 788, 834, 944,
404
  8160, 8161, 8058, 8165, 32, 776, 768, 96, 8060, 953, 969, 953, 974, 953, 8182, 953,
405
  8056, 8208, 32, 819, 8242, 8242, 8242, 8242, 8242, 8245, 8245, 8245, 8245, 8245,
406
  33, 33, 32, 773, 63, 63, 63, 33, 33, 63, 48, 53, 54, 55, 56, 57, 43, 8722, 61, 40,
407
  41, 97, 47, 99, 97, 47, 115, 176, 99, 99, 47, 111, 99, 47, 117, 176, 102, 115, 109,
408
  116, 101, 108, 116, 109, 1488, 1489, 1490, 1491, 102, 97, 120, 8721, 49, 8260, 55,
409
  49, 8260, 57, 49, 8260, 49, 48, 49, 8260, 51, 50, 8260, 51, 49, 8260, 53, 50, 8260,
410
  53, 51, 8260, 53, 52, 8260, 53, 49, 8260, 54, 53, 8260, 54, 49, 8260, 56, 51, 8260,
411
  56, 53, 8260, 56, 55, 8260, 56, 105, 105, 105, 105, 105, 105, 118, 118, 105, 118,
412
  105, 105, 118, 105, 105, 105, 105, 120, 120, 105, 120, 105, 105, 48, 8260, 51, 8747,
413
  8747, 8747, 8747, 8747, 8750, 8750, 8750, 8750, 8750, 12296, 12297, 49, 50, 49,
414
  51, 49, 52, 49, 53, 49, 54, 49, 55, 49, 56, 49, 57, 50, 48, 40, 49, 41, 40, 50,
415
  41, 40, 51, 41, 40, 52, 41, 40, 53, 41, 40, 54, 41, 40, 55, 41, 40, 56, 41, 40,
416
  57, 41, 40, 49, 48, 41, 40, 49, 49, 41, 40, 49, 50, 41, 40, 49, 51, 41, 40, 49,
417
  52, 41, 40, 49, 53, 41, 40, 49, 54, 41, 40, 49, 55, 41, 40, 49, 56, 41, 40, 49,
418
  57, 41, 40, 50, 48, 41, 40, 97, 41, 40, 98, 41, 40, 99, 41, 40, 100, 41, 40, 101,
419
  41, 40, 102, 41, 40, 103, 41, 40, 104, 41, 40, 105, 41, 40, 106, 41, 40, 107, 41,
420
  40, 108, 41, 40, 109, 41, 40, 110, 41, 40, 111, 41, 40, 112, 41, 40, 113, 41, 40,
421
  114, 41, 40, 115, 41, 40, 116, 41, 40, 117, 41, 40, 118, 41, 40, 119, 41, 40, 120,
422
  41, 40, 121, 41, 40, 122, 41, 58, 58, 61, 61, 61, 10973, 824, 11312, 11313, 11314,
423
  11315, 11316, 11317, 11318, 11319, 11320, 11321, 11322, 11323, 11324, 11325, 11326,
424
  11327, 11328, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 11337, 11338,
425
  11339, 11340, 11341, 11342, 11343, 11344, 11345, 11346, 11347, 11348, 11349, 11350,
426
  11351, 11352, 11353, 11354, 11355, 11356, 11357, 11358, 11359, 11361, 619, 7549,
427
  637, 11368, 11370, 11372, 11379, 11382, 575, 576, 11393, 11395, 11397, 11399, 11401,
428
  11403, 11405, 11407, 11409, 11411, 11413, 11415, 11417, 11419, 11421, 11423, 11425,
429
  11427, 11429, 11431, 11433, 11435, 11437, 11439, 11441, 11443, 11445, 11447, 11449,
430
  11451, 11453, 11455, 11457, 11459, 11461, 11463, 11465, 11467, 11469, 11471, 11473,
431
  11475, 11477, 11479, 11481, 11483, 11485, 11487, 11489, 11491, 11500, 11502, 11507,
432
  11617, 27597, 40863, 19968, 20008, 20022, 20031, 20057, 20101, 20108, 20128, 20154,
433
  20799, 20837, 20843, 20866, 20886, 20907, 20960, 20981, 20992, 21147, 21241, 21269,
434
  21274, 21304, 21313, 21340, 21353, 21378, 21430, 21448, 21475, 22231, 22303, 22763,
435
  22786, 22794, 22805, 22823, 22899, 23376, 23424, 23544, 23567, 23586, 23608, 23662,
436
  23665, 24027, 24037, 24049, 24062, 24178, 24186, 24191, 24308, 24318, 24331, 24339,
437
  24400, 24417, 24435, 24515, 25096, 25142, 25163, 25903, 25908, 25991, 26007, 26020,
438
  26041, 26080, 26085, 26352, 26376, 26408, 27424, 27490, 27513, 27571, 27595, 27604,
439
  27611, 27663, 27668, 27700, 28779, 29226, 29238, 29243, 29247, 29255, 29273, 29275,
440
  29356, 29572, 29577, 29916, 29926, 29976, 29983, 29992, 30000, 30091, 30098, 30326,
441
  30333, 30382, 30399, 30446, 30683, 30690, 30707, 31034, 31160, 31166, 31348, 31435,
442
  31481, 31859, 31992, 32566, 32593, 32650, 32701, 32769, 32780, 32786, 32819, 32895,
443
  32905, 33251, 33258, 33267, 33276, 33292, 33307, 33311, 33390, 33394, 33400, 34381,
444
  34411, 34880, 34892, 34915, 35198, 35211, 35282, 35328, 35895, 35910, 35925, 35960,
445
  35997, 36196, 36208, 36275, 36523, 36554, 36763, 36784, 36789, 37009, 37193, 37318,
446
  37324, 37329, 38263, 38272, 38428, 38582, 38585, 38632, 38737, 38750, 38754, 38761,
447
  38859, 38893, 38899, 38913, 39080, 39131, 39135, 39318, 39321, 39340, 39592, 39640,
448
  39647, 39717, 39727, 39730, 39740, 39770, 40165, 40565, 40575, 40613, 40635, 40643,
449
  40653, 40657, 40697, 40701, 40718, 40723, 40736, 40763, 40778, 40786, 40845, 40860,
450
  40864, 46, 12306, 21316, 21317, 32, 12441, 32, 12442, 12424, 12426, 12467, 12488,
451
  4352, 4353, 4522, 4354, 4524, 4525, 4355, 4356, 4357, 4528, 4529, 4530, 4531, 4532,
452
  4533, 4378, 4358, 4359, 4360, 4385, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368,
453
  4369, 4370, 4449, 4450, 4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460,
454
  4461, 4462, 4463, 4464, 4465, 4466, 4467, 4468, 4469, 4372, 4373, 4551, 4552, 4556,
455
  4558, 4563, 4567, 4569, 4380, 4573, 4575, 4381, 4382, 4384, 4386, 4387, 4391, 4393,
456
  4395, 4396, 4397, 4398, 4399, 4402, 4406, 4416, 4423, 4428, 4593, 4594, 4439, 4440,
457
  4441, 4484, 4485, 4488, 4497, 4498, 4500, 4510, 4513, 19977, 22235, 19978, 20013,
458
  19979, 30002, 19993, 19969, 22825, 22320, 40, 4352, 41, 40, 4354, 41, 40, 4355,
459
  41, 40, 4357, 41, 40, 4358, 41, 40, 4359, 41, 40, 4361, 41, 40, 4363, 41, 40, 4364,
460
  41, 40, 4366, 41, 40, 4367, 41, 40, 4368, 41, 40, 4369, 41, 40, 4370, 41, 40, 44032,
461
  41, 40, 45208, 41, 40, 45796, 41, 40, 46972, 41, 40, 47560, 41, 40, 48148, 41, 40,
462
  49324, 41, 40, 50500, 41, 40, 51088, 41, 40, 52264, 41, 40, 52852, 41, 40, 53440,
463
  41, 40, 54028, 41, 40, 54616, 41, 40, 51452, 41, 40, 50724, 51204, 41, 40, 50724,
464
  54980, 41, 40, 19968, 41, 40, 20108, 41, 40, 19977, 41, 40, 22235, 41, 40, 20116,
465
  41, 40, 20845, 41, 40, 19971, 41, 40, 20843, 41, 40, 20061, 41, 40, 21313, 41, 40,
466
  26376, 41, 40, 28779, 41, 40, 27700, 41, 40, 26408, 41, 40, 37329, 41, 40, 22303,
467
  41, 40, 26085, 41, 40, 26666, 41, 40, 26377, 41, 40, 31038, 41, 40, 21517, 41, 40,
468
  29305, 41, 40, 36001, 41, 40, 31069, 41, 40, 21172, 41, 40, 20195, 41, 40, 21628,
469
  41, 40, 23398, 41, 40, 30435, 41, 40, 20225, 41, 40, 36039, 41, 40, 21332, 41, 40,
470
  31085, 41, 40, 20241, 41, 40, 33258, 41, 40, 33267, 41, 21839, 24188, 31631, 112,
471
  116, 101, 50, 50, 50, 52, 50, 53, 50, 54, 50, 55, 50, 56, 50, 57, 51, 48, 51, 51,
472
  51, 52, 51, 53, 52280, 44256, 51452, 51032, 50864, 31192, 30007, 36969, 20778, 21360,
473
  27880, 38917, 20889, 27491, 24038, 21491, 21307, 23447, 22812, 51, 54, 51, 55, 51,
474
  56, 51, 57, 52, 48, 52, 52, 52, 53, 52, 54, 52, 55, 52, 56, 52, 57, 53, 48, 49,
475
  26376, 50, 26376, 51, 26376, 52, 26376, 53, 26376, 54, 26376, 55, 26376, 56, 26376,
476
  57, 26376, 49, 48, 26376, 49, 49, 26376, 49, 50, 26376, 104, 103, 101, 114, 103,
477
  101, 118, 108, 116, 100, 12450, 12452, 12454, 12456, 12458, 12459, 12461, 12463,
478
  12465, 12469, 12471, 12473, 12475, 12477, 12479, 12481, 12484, 12486, 12490, 12491,
479
  12492, 12493, 12494, 12495, 12498, 12501, 12504, 12507, 12510, 12511, 12512, 12513,
480
  12514, 12516, 12518, 12520, 12521, 12522, 12523, 12524, 12525, 12527, 12528, 12529,
481
  12530, 20196, 21644, 12450, 12497, 12540, 12488, 12450, 12523, 12501, 12449, 12450,
482
  12531, 12506, 12450, 12450, 12540, 12523, 12452, 12491, 12531, 12464, 12452, 12531,
483
  12481, 12454, 12457, 12531, 12456, 12473, 12463, 12540, 12489, 12456, 12540, 12459,
484
  12540, 12458, 12531, 12473, 12458, 12540, 12512, 12459, 12452, 12522, 12459, 12521,
485
  12483, 12488, 12459, 12525, 12522, 12540, 12460, 12525, 12531, 12460, 12531, 12510,
486
  12462, 12460, 12462, 12491, 12540, 12461, 12517, 12522, 12540, 12462, 12523, 12480,
487
  12540, 12461, 12525, 12461, 12525, 12464, 12521, 12512, 12461, 12525, 12513, 12540,
488
  12488, 12523, 12461, 12525, 12527, 12483, 12488, 12464, 12521, 12512, 12488, 12531,
489
  12463, 12523, 12476, 12452, 12525, 12463, 12525, 12540, 12493, 12465, 12540, 12473,
490
  12467, 12523, 12490, 12467, 12540, 12509, 12469, 12452, 12463, 12523, 12469, 12531,
491
  12481, 12540, 12512, 12471, 12522, 12531, 12464, 12475, 12531, 12481, 12475, 12531,
492
  12488, 12480, 12540, 12473, 12487, 12471, 12489, 12523, 12490, 12494, 12494, 12483,
493
  12488, 12495, 12452, 12484, 12497, 12540, 12475, 12531, 12488, 12497, 12540, 12484,
494
  12496, 12540, 12524, 12523, 12500, 12450, 12473, 12488, 12523, 12500, 12463, 12523,
495
  12500, 12467, 12499, 12523, 12501, 12449, 12521, 12483, 12489, 12501, 12451, 12540,
496
  12488, 12502, 12483, 12471, 12455, 12523, 12501, 12521, 12531, 12504, 12463, 12479,
497
  12540, 12523, 12506, 12477, 12506, 12491, 12498, 12504, 12523, 12484, 12506, 12531,
498
  12473, 12506, 12540, 12472, 12505, 12540, 12479, 12509, 12452, 12531, 12488, 12508,
499
  12523, 12488, 12507, 12531, 12509, 12531, 12489, 12507, 12540, 12523, 12507, 12540,
500
  12531, 12510, 12452, 12463, 12525, 12510, 12452, 12523, 12510, 12483, 12495, 12510,
501
  12523, 12463, 12510, 12531, 12471, 12519, 12531, 12511, 12463, 12525, 12531, 12511,
502
  12522, 12511, 12522, 12496, 12540, 12523, 12513, 12460, 12513, 12460, 12488, 12531,
503
  12516, 12540, 12489, 12516, 12540, 12523, 12518, 12450, 12531, 12522, 12483, 12488,
504
  12523, 12522, 12521, 12523, 12500, 12540, 12523, 12540, 12502, 12523, 12524, 12512,
505
  12524, 12531, 12488, 12466, 12531, 48, 28857, 49, 28857, 50, 28857, 51, 28857, 52,
506
  28857, 53, 28857, 54, 28857, 55, 28857, 56, 28857, 57, 28857, 49, 48, 28857, 49,
507
  49, 28857, 49, 50, 28857, 49, 51, 28857, 49, 52, 28857, 49, 53, 28857, 49, 54, 28857,
508
  49, 55, 28857, 49, 56, 28857, 49, 57, 28857, 50, 48, 28857, 50, 49, 28857, 50, 50,
509
  28857, 50, 51, 28857, 50, 52, 28857, 104, 112, 97, 100, 97, 97, 117, 98, 97, 114,
510
  111, 118, 112, 99, 100, 109, 100, 109, 50, 100, 109, 51, 105, 117, 24179, 25104,
511
  26157, 21644, 22823, 27491, 26126, 27835, 26666, 24335, 20250, 31038, 110, 97, 956,
512
  97, 109, 97, 107, 97, 107, 98, 109, 98, 103, 98, 99, 97, 108, 107, 99, 97, 108,
513
  112, 102, 110, 102, 956, 102, 956, 103, 109, 103, 107, 103, 104, 122, 107, 104,
514
  122, 109, 104, 122, 116, 104, 122, 956, 108, 109, 108, 100, 108, 102, 109, 110,
515
  109, 956, 109, 109, 109, 99, 109, 107, 109, 109, 109, 50, 99, 109, 50, 107, 109,
516
  50, 109, 109, 51, 99, 109, 51, 107, 109, 51, 109, 8725, 115, 109, 8725, 115, 50,
517
  107, 112, 97, 109, 112, 97, 103, 112, 97, 114, 97, 100, 114, 97, 100, 8725, 115,
518
  114, 97, 100, 8725, 115, 50, 112, 115, 110, 115, 956, 115, 109, 115, 112, 118, 110,
519
  118, 956, 118, 109, 118, 107, 118, 112, 119, 110, 119, 956, 119, 109, 119, 107,
520
  119, 107, 969, 109, 969, 98, 113, 99, 8725, 107, 103, 100, 98, 103, 121, 104, 97,
521
  105, 110, 107, 107, 107, 116, 108, 110, 108, 111, 103, 108, 120, 109, 105, 108,
522
  109, 111, 108, 112, 104, 112, 112, 109, 112, 114, 115, 118, 119, 98, 118, 8725,
523
  109, 97, 8725, 109, 49, 26085, 50, 26085, 51, 26085, 52, 26085, 53, 26085, 54, 26085,
524
  55, 26085, 56, 26085, 57, 26085, 49, 48, 26085, 49, 49, 26085, 49, 50, 26085, 49,
525
  51, 26085, 49, 52, 26085, 49, 53, 26085, 49, 54, 26085, 49, 55, 26085, 49, 56, 26085,
526
  49, 57, 26085, 50, 48, 26085, 50, 49, 26085, 50, 50, 26085, 50, 51, 26085, 50, 52,
527
  26085, 50, 53, 26085, 50, 54, 26085, 50, 55, 26085, 50, 56, 26085, 50, 57, 26085,
528
  51, 48, 26085, 51, 49, 26085, 103, 97, 108, 42561, 42563, 42565, 42567, 42569, 42573,
529
  42575, 42577, 42579, 42581, 42583, 42585, 42587, 42589, 42591, 42593, 42595, 42597,
530
  42599, 42601, 42603, 42605, 42625, 42627, 42629, 42631, 42633, 42635, 42637, 42639,
531
  42641, 42643, 42645, 42647, 42649, 42651, 42787, 42789, 42791, 42793, 42795, 42797,
532
  42799, 42803, 42805, 42807, 42809, 42811, 42813, 42815, 42817, 42819, 42821, 42823,
533
  42825, 42827, 42829, 42831, 42833, 42835, 42837, 42839, 42841, 42843, 42845, 42847,
534
  42849, 42851, 42853, 42855, 42857, 42859, 42861, 42863, 42874, 42876, 7545, 42879,
535
  42881, 42883, 42885, 42887, 42892, 42897, 42899, 42903, 42905, 42907, 42909, 42911,
536
  42913, 42915, 42917, 42919, 42921, 620, 670, 647, 43859, 42933, 42935, 42937, 42939,
537
  42941, 42943, 42945, 42947, 42900, 7566, 42952, 42954, 42961, 42967, 42969, 42998,
538
  43831, 43858, 653, 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034,
539
  5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044, 5045, 5046, 5047, 5048,
540
  5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058, 5059, 5060, 5061, 5062,
541
  5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072, 5073, 5074, 5075, 5076,
542
  5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086, 5087, 5088, 5089, 5090,
543
  5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103, 35912,
544
  26356, 36040, 28369, 20018, 21477, 22865, 21895, 22856, 25078, 30313, 32645, 34367,
545
  34746, 35064, 37007, 27138, 27931, 28889, 29662, 33853, 37226, 39409, 20098, 21365,
546
  27396, 29211, 34349, 40478, 23888, 28651, 34253, 35172, 25289, 33240, 34847, 24266,
547
  26391, 28010, 29436, 37070, 20358, 20919, 21214, 25796, 27347, 29200, 30439, 34310,
548
  34396, 36335, 38706, 39791, 40442, 30860, 31103, 32160, 33737, 37636, 35542, 22751,
549
  24324, 31840, 32894, 29282, 30922, 36034, 38647, 22744, 23650, 27155, 28122, 28431,
550
  32047, 32311, 38475, 21202, 32907, 20956, 20940, 31260, 32190, 33777, 38517, 35712,
551
  25295, 35582, 20025, 23527, 24594, 29575, 30064, 21271, 30971, 20415, 24489, 19981,
552
  27852, 25976, 32034, 21443, 22622, 30465, 33865, 35498, 27578, 27784, 25342, 33509,
553
  25504, 30053, 20142, 20841, 20937, 26753, 31975, 33391, 35538, 37327, 21237, 21570,
554
  24300, 26053, 28670, 31018, 38317, 39530, 40599, 40654, 26310, 27511, 36706, 24180,
555
  24976, 25088, 25754, 28451, 29001, 29833, 31178, 32244, 32879, 36646, 34030, 36899,
556
  37706, 21015, 21155, 21693, 28872, 35010, 24265, 24565, 25467, 27566, 31806, 29557,
557
  22265, 23994, 24604, 29618, 29801, 32666, 32838, 37428, 38646, 38728, 38936, 20363,
558
  31150, 37300, 38584, 24801, 20102, 20698, 23534, 23615, 26009, 29134, 30274, 34044,
559
  36988, 26248, 38446, 21129, 26491, 26611, 27969, 28316, 29705, 30041, 30827, 32016,
560
  39006, 25134, 38520, 20523, 23833, 28138, 36650, 24459, 24900, 26647, 38534, 21033,
561
  21519, 23653, 26131, 26446, 26792, 27877, 29702, 30178, 32633, 35023, 35041, 38626,
562
  21311, 28346, 21533, 29136, 29848, 34298, 38563, 40023, 40607, 26519, 28107, 33256,
563
  31520, 31890, 29376, 28825, 35672, 20160, 33590, 21050, 20999, 24230, 25299, 31958,
564
  23429, 27934, 26292, 36667, 38477, 24275, 20800, 21952, 22618, 26228, 20958, 29482,
565
  30410, 31036, 31070, 31077, 31119, 38742, 31934, 34322, 35576, 36920, 37117, 39151,
566
  39164, 39208, 40372, 37086, 38583, 20398, 20711, 20813, 21193, 21220, 21329, 21917,
567
  22022, 22120, 22592, 22696, 23652, 24724, 24936, 24974, 25074, 25935, 26082, 26257,
568
  26757, 28023, 28186, 28450, 29038, 29227, 29730, 30865, 31049, 31048, 31056, 31062,
569
  31117, 31118, 31296, 31361, 31680, 32265, 32321, 32626, 32773, 33261, 33401, 33879,
570
  35088, 35222, 35585, 35641, 36051, 36104, 36790, 38627, 38911, 38971, 24693, 148206,
571
  33304, 20006, 20917, 20840, 20352, 20805, 20864, 21191, 21242, 21845, 21913, 21986,
572
  22707, 22852, 22868, 23138, 23336, 24274, 24281, 24425, 24493, 24792, 24910, 24840,
573
  24928, 25140, 25540, 25628, 25682, 25942, 26395, 26454, 28379, 28363, 28702, 30631,
574
  29237, 29359, 29809, 29958, 30011, 30237, 30239, 30427, 30452, 30538, 30528, 30924,
575
  31409, 31867, 32091, 32574, 33618, 33775, 34681, 35137, 35206, 35519, 35531, 35565,
576
  35722, 36664, 36978, 37273, 37494, 38524, 38875, 38923, 39698, 141386, 141380, 144341,
577
  15261, 16408, 16441, 152137, 154832, 163539, 40771, 40846, 102, 102, 102, 105, 102,
578
  108, 102, 102, 108, 1396, 1398, 1396, 1381, 1396, 1387, 1406, 1398, 1396, 1389,
579
  1497, 1460, 1522, 1463, 1506, 1492, 1499, 1500, 1501, 1512, 1514, 1513, 1473, 1513,
580
  1474, 1513, 1468, 1473, 1513, 1468, 1474, 1488, 1463, 1488, 1464, 1488, 1468, 1489,
581
  1468, 1490, 1468, 1491, 1468, 1492, 1468, 1493, 1468, 1494, 1468, 1496, 1468, 1497,
582
  1468, 1498, 1468, 1499, 1468, 1500, 1468, 1502, 1468, 1504, 1468, 1505, 1468, 1507,
583
  1468, 1508, 1468, 1510, 1468, 1511, 1468, 1512, 1468, 1514, 1468, 1493, 1465, 1489,
584
  1471, 1499, 1471, 1508, 1471, 1488, 1500, 1649, 1659, 1662, 1664, 1658, 1663, 1657,
585
  1700, 1702, 1668, 1667, 1670, 1671, 1677, 1676, 1678, 1672, 1688, 1681, 1705, 1711,
586
  1715, 1713, 1722, 1723, 1728, 1729, 1726, 1746, 1747, 1709, 1734, 1736, 1739, 1733,
587
  1737, 1744, 1609, 1574, 1575, 1574, 1749, 1574, 1608, 1574, 1735, 1574, 1734, 1574,
588
  1736, 1574, 1744, 1574, 1609, 1740, 1574, 1580, 1574, 1581, 1574, 1605, 1574, 1610,
589
  1576, 1580, 1576, 1581, 1576, 1582, 1576, 1605, 1576, 1609, 1576, 1610, 1578, 1580,
590
  1578, 1581, 1578, 1582, 1578, 1605, 1578, 1609, 1578, 1610, 1579, 1580, 1579, 1605,
591
  1579, 1609, 1579, 1610, 1580, 1581, 1580, 1605, 1581, 1605, 1582, 1580, 1582, 1581,
592
  1582, 1605, 1587, 1580, 1587, 1581, 1587, 1582, 1587, 1605, 1589, 1581, 1589, 1605,
593
  1590, 1580, 1590, 1581, 1590, 1582, 1590, 1605, 1591, 1581, 1591, 1605, 1592, 1605,
594
  1593, 1580, 1593, 1605, 1594, 1580, 1594, 1605, 1601, 1580, 1601, 1581, 1601, 1582,
595
  1601, 1605, 1601, 1609, 1601, 1610, 1602, 1581, 1602, 1605, 1602, 1609, 1602, 1610,
596
  1603, 1575, 1603, 1580, 1603, 1581, 1603, 1582, 1603, 1604, 1603, 1605, 1603, 1609,
597
  1603, 1610, 1604, 1580, 1604, 1581, 1604, 1582, 1604, 1605, 1604, 1609, 1604, 1610,
598
  1605, 1580, 1605, 1605, 1605, 1609, 1605, 1610, 1606, 1580, 1606, 1581, 1606, 1582,
599
  1606, 1605, 1606, 1609, 1606, 1610, 1607, 1580, 1607, 1605, 1607, 1609, 1607, 1610,
600
  1610, 1581, 1610, 1582, 1610, 1609, 1584, 1648, 1585, 1648, 1609, 1648, 32, 1612,
601
  1617, 32, 1613, 1617, 32, 1614, 1617, 32, 1615, 1617, 32, 1616, 1617, 32, 1617,
602
  1648, 1574, 1585, 1574, 1586, 1574, 1606, 1576, 1585, 1576, 1586, 1576, 1606, 1578,
603
  1585, 1578, 1586, 1578, 1606, 1579, 1585, 1579, 1586, 1579, 1606, 1605, 1575, 1606,
604
  1585, 1606, 1586, 1606, 1606, 1610, 1585, 1610, 1586, 1574, 1582, 1574, 1607, 1576,
605
  1607, 1578, 1607, 1589, 1582, 1604, 1607, 1606, 1607, 1607, 1648, 1579, 1607, 1587,
606
  1607, 1588, 1605, 1588, 1607, 1600, 1614, 1617, 1600, 1615, 1617, 1600, 1616, 1617,
607
  1591, 1609, 1591, 1610, 1593, 1609, 1593, 1610, 1594, 1609, 1594, 1610, 1587, 1609,
608
  1587, 1610, 1588, 1609, 1588, 1610, 1581, 1609, 1580, 1609, 1580, 1610, 1582, 1609,
609
  1589, 1609, 1589, 1610, 1590, 1609, 1590, 1610, 1588, 1580, 1588, 1581, 1588, 1582,
610
  1588, 1585, 1587, 1585, 1589, 1585, 1590, 1585, 1575, 1611, 1578, 1580, 1605, 1578,
611
  1581, 1580, 1578, 1581, 1605, 1578, 1582, 1605, 1578, 1605, 1580, 1578, 1605, 1581,
612
  1578, 1605, 1582, 1581, 1605, 1610, 1581, 1605, 1609, 1587, 1581, 1580, 1587, 1580,
613
  1581, 1587, 1580, 1609, 1587, 1605, 1581, 1587, 1605, 1580, 1587, 1605, 1605, 1589,
614
  1581, 1581, 1589, 1605, 1605, 1588, 1581, 1605, 1588, 1580, 1610, 1588, 1605, 1582,
615
  1588, 1605, 1605, 1590, 1581, 1609, 1590, 1582, 1605, 1591, 1605, 1581, 1591, 1605,
616
  1605, 1591, 1605, 1610, 1593, 1580, 1605, 1593, 1605, 1605, 1593, 1605, 1609, 1594,
617
  1605, 1605, 1594, 1605, 1610, 1594, 1605, 1609, 1601, 1582, 1605, 1602, 1605, 1581,
618
  1602, 1605, 1605, 1604, 1581, 1605, 1604, 1581, 1610, 1604, 1581, 1609, 1604, 1580,
619
  1580, 1604, 1582, 1605, 1604, 1605, 1581, 1605, 1581, 1580, 1605, 1581, 1610, 1605,
620
  1580, 1581, 1605, 1582, 1605, 1605, 1580, 1582, 1607, 1605, 1580, 1607, 1605, 1605,
621
  1606, 1581, 1605, 1606, 1581, 1609, 1606, 1580, 1605, 1606, 1580, 1609, 1606, 1605,
622
  1610, 1606, 1605, 1609, 1610, 1605, 1605, 1576, 1582, 1610, 1578, 1580, 1610, 1578,
623
  1580, 1609, 1578, 1582, 1610, 1578, 1582, 1609, 1578, 1605, 1610, 1578, 1605, 1609,
624
  1580, 1605, 1610, 1580, 1581, 1609, 1580, 1605, 1609, 1587, 1582, 1609, 1589, 1581,
625
  1610, 1588, 1581, 1610, 1590, 1581, 1610, 1604, 1580, 1610, 1604, 1605, 1610, 1610,
626
  1580, 1610, 1610, 1605, 1610, 1605, 1605, 1610, 1602, 1605, 1610, 1606, 1581, 1610,
627
  1593, 1605, 1610, 1603, 1605, 1610, 1606, 1580, 1581, 1605, 1582, 1610, 1604, 1580,
628
  1605, 1603, 1605, 1605, 1580, 1581, 1610, 1581, 1580, 1610, 1605, 1580, 1610, 1601,
629
  1605, 1610, 1576, 1581, 1610, 1587, 1582, 1610, 1606, 1580, 1610, 1589, 1604, 1746,
630
  1602, 1604, 1746, 1575, 1604, 1604, 1607, 1575, 1603, 1576, 1585, 1605, 1581, 1605,
631
  1583, 1589, 1604, 1593, 1605, 1585, 1587, 1608, 1604, 1593, 1604, 1610, 1607, 1608,
632
  1587, 1604, 1605, 1589, 1604, 1609, 1589, 1604, 1609, 32, 1575, 1604, 1604, 1607,
633
  32, 1593, 1604, 1610, 1607, 32, 1608, 1587, 1604, 1605, 1580, 1604, 32, 1580, 1604,
634
  1575, 1604, 1607, 1585, 1740, 1575, 1604, 44, 12289, 12310, 12311, 8212, 8211, 95,
635
  123, 125, 12308, 12309, 12304, 12305, 12298, 12299, 12300, 12301, 12302, 12303,
636
  91, 93, 35, 38, 42, 45, 60, 62, 92, 36, 37, 64, 32, 1611, 1600, 1611, 1600, 1617,
637
  32, 1618, 1600, 1618, 1569, 1570, 1571, 1572, 1573, 1577, 1604, 1570, 1604, 1571,
638
  1604, 1573, 34, 39, 94, 124, 126, 10629, 10630, 12539, 12453, 12515, 162, 163, 172,
639
  166, 165, 8361, 9474, 8592, 8593, 8594, 8595, 9632, 9675, 66600, 66601, 66602, 66603,
640
  66604, 66605, 66606, 66607, 66608, 66609, 66610, 66611, 66612, 66613, 66614, 66615,
641
  66616, 66617, 66618, 66619, 66620, 66621, 66622, 66623, 66624, 66625, 66626, 66627,
642
  66628, 66629, 66630, 66631, 66632, 66633, 66634, 66635, 66636, 66637, 66638, 66639,
643
  66776, 66777, 66778, 66779, 66780, 66781, 66782, 66783, 66784, 66785, 66786, 66787,
644
  66788, 66789, 66790, 66791, 66792, 66793, 66794, 66795, 66796, 66797, 66798, 66799,
645
  66800, 66801, 66802, 66803, 66804, 66805, 66806, 66807, 66808, 66809, 66810, 66811,
646
  66967, 66968, 66969, 66970, 66971, 66972, 66973, 66974, 66975, 66976, 66977, 66979,
647
  66980, 66981, 66982, 66983, 66984, 66985, 66986, 66987, 66988, 66989, 66990, 66991,
648
  66992, 66993, 66995, 66996, 66997, 66998, 66999, 67000, 67001, 67003, 67004, 720,
649
  721, 665, 675, 43878, 677, 676, 7569, 600, 606, 681, 612, 610, 667, 668, 615, 644,
650
  682, 683, 122628, 42894, 622, 122629, 654, 122630, 630, 631, 634, 122632, 638, 680,
651
  678, 43879, 679, 11377, 655, 673, 674, 664, 448, 449, 450, 122634, 122654, 68800,
652
  68801, 68802, 68803, 68804, 68805, 68806, 68807, 68808, 68809, 68810, 68811, 68812,
653
  68813, 68814, 68815, 68816, 68817, 68818, 68819, 68820, 68821, 68822, 68823, 68824,
654
  68825, 68826, 68827, 68828, 68829, 68830, 68831, 68832, 68833, 68834, 68835, 68836,
655
  68837, 68838, 68839, 68840, 68841, 68842, 68843, 68844, 68845, 68846, 68847, 68848,
656
  68849, 68850, 71872, 71873, 71874, 71875, 71876, 71877, 71878, 71879, 71880, 71881,
657
  71882, 71883, 71884, 71885, 71886, 71887, 71888, 71889, 71890, 71891, 71892, 71893,
658
  71894, 71895, 71896, 71897, 71898, 71899, 71900, 71901, 71902, 71903, 93792, 93793,
659
  93794, 93795, 93796, 93797, 93798, 93799, 93800, 93801, 93802, 93803, 93804, 93805,
660
  93806, 93807, 93808, 93809, 93810, 93811, 93812, 93813, 93814, 93815, 93816, 93817,
661
  93818, 93819, 93820, 93821, 93822, 93823, 119127, 119141, 119128, 119141, 119128,
662
  119141, 119150, 119128, 119141, 119151, 119128, 119141, 119152, 119128, 119141,
663
  119153, 119128, 119141, 119154, 119225, 119141, 119226, 119141, 119225, 119141,
664
  119150, 119226, 119141, 119150, 119225, 119141, 119151, 119226, 119141, 119151,
665
  305, 567, 8711, 8706, 1231, 125218, 125219, 125220, 125221, 125222, 125223, 125224,
666
  125225, 125226, 125227, 125228, 125229, 125230, 125231, 125232, 125233, 125234,
667
  125235, 125236, 125237, 125238, 125239, 125240, 125241, 125242, 125243, 125244,
668
  125245, 125246, 125247, 125248, 125249, 125250, 125251, 1646, 1697, 1647, 48, 44,
669
  49, 44, 50, 44, 51, 44, 52, 44, 53, 44, 54, 44, 55, 44, 56, 44, 57, 44, 12308, 115,
670
  12309, 119, 122, 104, 118, 115, 100, 112, 112, 118, 119, 99, 109, 114, 100, 106,
671
  12411, 12363, 12467, 12467, 23383, 21452, 22810, 35299, 20132, 26144, 28961, 21069,
672
  24460, 20877, 26032, 21021, 32066, 36009, 22768, 21561, 28436, 25237, 25429, 36938,
673
  25351, 25171, 31105, 31354, 21512, 28288, 30003, 21106, 21942, 37197, 12308, 26412,
674
  12309, 12308, 19977, 12309, 12308, 20108, 12309, 12308, 23433, 12309, 12308, 28857,
675
  12309, 12308, 25171, 12309, 12308, 30423, 12309, 12308, 21213, 12309, 12308, 25943,
676
  12309, 24471, 21487, 20029, 20024, 20033, 131362, 20320, 20411, 20482, 20602, 20633,
677
  20687, 13470, 132666, 20820, 20836, 20855, 132380, 13497, 20839, 132427, 20887,
678
  20900, 20172, 20908, 168415, 20995, 13535, 21051, 21062, 21111, 13589, 21253, 21254,
679
  21321, 21338, 21363, 21373, 21375, 133676, 28784, 21450, 21471, 133987, 21483, 21489,
680
  21510, 21662, 21560, 21576, 21608, 21666, 21750, 21776, 21843, 21859, 21892, 21931,
681
  21939, 21954, 22294, 22295, 22097, 22132, 22766, 22478, 22516, 22541, 22411, 22578,
682
  22577, 22700, 136420, 22770, 22775, 22790, 22818, 22882, 136872, 136938, 23020,
683
  23067, 23079, 23000, 23142, 14062, 23304, 23358, 137672, 23491, 23512, 23539, 138008,
684
  23551, 23558, 14209, 23648, 23744, 23693, 138724, 23875, 138726, 23918, 23915, 23932,
685
  24033, 24034, 14383, 24061, 24104, 24125, 24169, 14434, 139651, 14460, 24240, 24243,
686
  24246, 172946, 140081, 33281, 24354, 14535, 144056, 156122, 24418, 24427, 14563,
687
  24474, 24525, 24535, 24569, 24705, 14650, 14620, 141012, 24775, 24904, 24908, 24954,
688
  25010, 24996, 25007, 25054, 25115, 25181, 25265, 25300, 25424, 142092, 25405, 25340,
689
  25448, 25475, 25572, 142321, 25634, 25541, 25513, 14894, 25705, 25726, 25757, 25719,
690
  14956, 25964, 143370, 26083, 26360, 26185, 15129, 15112, 15076, 20882, 20885, 26368,
691
  26268, 32941, 17369, 26401, 26462, 26451, 144323, 15177, 26618, 26501, 26706, 144493,
692
  26766, 26655, 26900, 26946, 27043, 27114, 27304, 145059, 27355, 15384, 27425, 145575,
693
  27476, 15438, 27506, 27551, 27579, 146061, 138507, 146170, 27726, 146620, 27839,
694
  27853, 27751, 27926, 27966, 28009, 28024, 28037, 146718, 27956, 28207, 28270, 15667,
695
  28359, 147153, 28153, 28526, 147294, 147342, 28614, 28729, 28699, 15766, 28746,
696
  28797, 28791, 28845, 132389, 28997, 148067, 29084, 29224, 29264, 149000, 29312,
697
  29333, 149301, 149524, 29562, 29579, 16044, 29605, 16056, 29767, 29788, 29829, 29898,
698
  16155, 29988, 150582, 30014, 150674, 139679, 30224, 151457, 151480, 151620, 16380,
699
  16392, 151795, 151794, 151833, 151859, 30494, 30495, 30603, 16454, 16534, 152605,
700
  30798, 16611, 153126, 153242, 153285, 31211, 16687, 31306, 31311, 153980, 154279,
701
  16898, 154539, 31686, 31689, 16935, 154752, 31954, 17056, 31976, 31971, 32000, 155526,
702
  32099, 17153, 32199, 32258, 32325, 17204, 156200, 156231, 17241, 156377, 32634,
703
  156478, 32661, 32762, 156890, 156963, 32864, 157096, 32880, 144223, 17365, 32946,
704
  33027, 17419, 33086, 23221, 157607, 157621, 144275, 144284, 33284, 36766, 17515,
705
  33425, 33419, 33437, 21171, 33457, 33459, 33469, 33510, 158524, 33565, 33635, 33709,
706
  33571, 33725, 33767, 33619, 33738, 33740, 33756, 158774, 159083, 158933, 17707,
707
  34033, 34035, 34070, 160714, 34148, 159532, 17757, 17761, 159665, 159954, 17771,
708
  34384, 34407, 34409, 34473, 34440, 34574, 34530, 34600, 34667, 34694, 34785, 34817,
709
  17913, 34912, 161383, 35031, 35038, 17973, 35066, 13499, 161966, 162150, 18110,
710
  18119, 35488, 162984, 36011, 36033, 36123, 36215, 163631, 133124, 36299, 36284,
711
  36336, 133342, 36564, 165330, 165357, 37012, 37105, 37137, 165678, 37147, 37432,
712
  37591, 37592, 37500, 37881, 37909, 166906, 38283, 18837, 38327, 167287, 18918, 38595,
713
  23986, 38691, 168261, 168474, 19054, 19062, 38880, 168970, 19122, 169110, 38953,
714
  169398, 39138, 19251, 39209, 39335, 39362, 39422, 19406, 170800, 40000, 40189, 19662,
715
  19693, 40295, 172238, 19704, 172293, 172558, 172689, 19798, 40702, 40709, 40719,
716
  40726, 173568,
717
718
};
719
const uint32_t table[8000][2] =
720
{
721
  {0, 1}, {65, 16777219}, {66, 16777475}, {67, 16777731},
722
  {68, 16777987}, {69, 16778243}, {70, 16778499}, {71, 16778755},
723
  {72, 16779011}, {73, 16779267}, {74, 16779523}, {75, 16779779},
724
  {76, 16780035}, {77, 16780291}, {78, 16780547}, {79, 16780803},
725
  {80, 16781059}, {81, 16781315}, {82, 16781571}, {83, 16781827},
726
  {84, 16782083}, {85, 16782339}, {86, 16782595}, {87, 16782851},
727
  {88, 16783107}, {89, 16783363}, {90, 16783619}, {91, 1},
728
  {128, 2}, {160, 16783875}, {161, 1}, {168, 33561347},
729
  {169, 1}, {170, 16777219}, {171, 1}, {173, 0},
730
  {174, 1}, {175, 33561859}, {176, 1}, {178, 16785155},
731
  {179, 16785411}, {180, 33562883}, {181, 16786179}, {182, 1},
732
  {184, 33563651}, {185, 16786947}, {186, 16780803}, {187, 1},
733
  {188, 50341635}, {189, 50342403}, {190, 50343171}, {191, 1},
734
  {192, 16789507}, {193, 16789763}, {194, 16790019}, {195, 16790275},
735
  {196, 16790531}, {197, 16790787}, {198, 16791043}, {199, 16791299},
736
  {200, 16791555}, {201, 16791811}, {202, 16792067}, {203, 16792323},
737
  {204, 16792579}, {205, 16792835}, {206, 16793091}, {207, 16793347},
738
  {208, 16793603}, {209, 16793859}, {210, 16794115}, {211, 16794371},
739
  {212, 16794627}, {213, 16794883}, {214, 16795139}, {215, 1},
740
  {216, 16795395}, {217, 16795651}, {218, 16795907}, {219, 16796163},
741
  {220, 16796419}, {221, 16796675}, {222, 16796931}, {223, 1},
742
  {256, 16797187}, {257, 1}, {258, 16797443}, {259, 1},
743
  {260, 16797699}, {261, 1}, {262, 16797955}, {263, 1},
744
  {264, 16798211}, {265, 1}, {266, 16798467}, {267, 1},
745
  {268, 16798723}, {269, 1}, {270, 16798979}, {271, 1},
746
  {272, 16799235}, {273, 1}, {274, 16799491}, {275, 1},
747
  {276, 16799747}, {277, 1}, {278, 16800003}, {279, 1},
748
  {280, 16800259}, {281, 1}, {282, 16800515}, {283, 1},
749
  {284, 16800771}, {285, 1}, {286, 16801027}, {287, 1},
750
  {288, 16801283}, {289, 1}, {290, 16801539}, {291, 1},
751
  {292, 16801795}, {293, 1}, {294, 16802051}, {295, 1},
752
  {296, 16802307}, {297, 1}, {298, 16802563}, {299, 1},
753
  {300, 16802819}, {301, 1}, {302, 16803075}, {303, 1},
754
  {304, 33580547}, {305, 1}, {306, 33556483}, {308, 16803843},
755
  {309, 1}, {310, 16804099}, {311, 1}, {313, 16804355},
756
  {314, 1}, {315, 16804611}, {316, 1}, {317, 16804867},
757
  {318, 1}, {319, 33582339}, {321, 16805635}, {322, 1},
758
  {323, 16805891}, {324, 1}, {325, 16806147}, {326, 1},
759
  {327, 16806403}, {328, 1}, {329, 33583875}, {330, 16807171},
760
  {331, 1}, {332, 16807427}, {333, 1}, {334, 16807683},
761
  {335, 1}, {336, 16807939}, {337, 1}, {338, 16808195},
762
  {339, 1}, {340, 16808451}, {341, 1}, {342, 16808707},
763
  {343, 1}, {344, 16808963}, {345, 1}, {346, 16809219},
764
  {347, 1}, {348, 16809475}, {349, 1}, {350, 16809731},
765
  {351, 1}, {352, 16809987}, {353, 1}, {354, 16810243},
766
  {355, 1}, {356, 16810499}, {357, 1}, {358, 16810755},
767
  {359, 1}, {360, 16811011}, {361, 1}, {362, 16811267},
768
  {363, 1}, {364, 16811523}, {365, 1}, {366, 16811779},
769
  {367, 1}, {368, 16812035}, {369, 1}, {370, 16812291},
770
  {371, 1}, {372, 16812547}, {373, 1}, {374, 16812803},
771
  {375, 1}, {376, 16813059}, {377, 16813315}, {378, 1},
772
  {379, 16813571}, {380, 1}, {381, 16813827}, {382, 1},
773
  {383, 16781827}, {384, 1}, {385, 16814083}, {386, 16814339},
774
  {387, 1}, {388, 16814595}, {389, 1}, {390, 16814851},
775
  {391, 16815107}, {392, 1}, {393, 16815363}, {394, 16815619},
776
  {395, 16815875}, {396, 1}, {398, 16816131}, {399, 16816387},
777
  {400, 16816643}, {401, 16816899}, {402, 1}, {403, 16817155},
778
  {404, 16817411}, {405, 1}, {406, 16817667}, {407, 16817923},
779
  {408, 16818179}, {409, 1}, {412, 16818435}, {413, 16818691},
780
  {414, 1}, {415, 16818947}, {416, 16819203}, {417, 1},
781
  {418, 16819459}, {419, 1}, {420, 16819715}, {421, 1},
782
  {422, 16819971}, {423, 16820227}, {424, 1}, {425, 16820483},
783
  {426, 1}, {428, 16820739}, {429, 1}, {430, 16820995},
784
  {431, 16821251}, {432, 1}, {433, 16821507}, {434, 16821763},
785
  {435, 16822019}, {436, 1}, {437, 16822275}, {438, 1},
786
  {439, 16822531}, {440, 16822787}, {441, 1}, {444, 16823043},
787
  {445, 1}, {452, 33600515}, {455, 33601027}, {458, 33601539},
788
  {461, 16824835}, {462, 1}, {463, 16825091}, {464, 1},
789
  {465, 16825347}, {466, 1}, {467, 16825603}, {468, 1},
790
  {469, 16825859}, {470, 1}, {471, 16826115}, {472, 1},
791
  {473, 16826371}, {474, 1}, {475, 16826627}, {476, 1},
792
  {478, 16826883}, {479, 1}, {480, 16827139}, {481, 1},
793
  {482, 16827395}, {483, 1}, {484, 16827651}, {485, 1},
794
  {486, 16827907}, {487, 1}, {488, 16828163}, {489, 1},
795
  {490, 16828419}, {491, 1}, {492, 16828675}, {493, 1},
796
  {494, 16828931}, {495, 1}, {497, 33606403}, {500, 16829699},
797
  {501, 1}, {502, 16829955}, {503, 16830211}, {504, 16830467},
798
  {505, 1}, {506, 16830723}, {507, 1}, {508, 16830979},
799
  {509, 1}, {510, 16831235}, {511, 1}, {512, 16831491},
800
  {513, 1}, {514, 16831747}, {515, 1}, {516, 16832003},
801
  {517, 1}, {518, 16832259}, {519, 1}, {520, 16832515},
802
  {521, 1}, {522, 16832771}, {523, 1}, {524, 16833027},
803
  {525, 1}, {526, 16833283}, {527, 1}, {528, 16833539},
804
  {529, 1}, {530, 16833795}, {531, 1}, {532, 16834051},
805
  {533, 1}, {534, 16834307}, {535, 1}, {536, 16834563},
806
  {537, 1}, {538, 16834819}, {539, 1}, {540, 16835075},
807
  {541, 1}, {542, 16835331}, {543, 1}, {544, 16835587},
808
  {545, 1}, {546, 16835843}, {547, 1}, {548, 16836099},
809
  {549, 1}, {550, 16836355}, {551, 1}, {552, 16836611},
810
  {553, 1}, {554, 16836867}, {555, 1}, {556, 16837123},
811
  {557, 1}, {558, 16837379}, {559, 1}, {560, 16837635},
812
  {561, 1}, {562, 16837891}, {563, 1}, {570, 16838147},
813
  {571, 16838403}, {572, 1}, {573, 16838659}, {574, 16838915},
814
  {575, 1}, {577, 16839171}, {578, 1}, {579, 16839427},
815
  {580, 16839683}, {581, 16839939}, {582, 16840195}, {583, 1},
816
  {584, 16840451}, {585, 1}, {586, 16840707}, {587, 1},
817
  {588, 16840963}, {589, 1}, {590, 16841219}, {591, 1},
818
  {688, 16779011}, {689, 16841475}, {690, 16779523}, {691, 16781571},
819
  {692, 16841731}, {693, 16841987}, {694, 16842243}, {695, 16782851},
820
  {696, 16783363}, {697, 1}, {728, 33619715}, {729, 33620227},
821
  {730, 33620739}, {731, 33621251}, {732, 33621763}, {733, 33622275},
822
  {734, 1}, {736, 16817411}, {737, 16780035}, {738, 16781827},
823
  {739, 16783107}, {740, 16845571}, {741, 1}, {832, 16845827},
824
  {833, 16785923}, {834, 1}, {835, 16846083}, {836, 33623555},
825
  {837, 16846851}, {838, 1}, {847, 0}, {848, 1},
826
  {880, 16847107}, {881, 1}, {882, 16847363}, {883, 1},
827
  {884, 16847619}, {885, 1}, {886, 16847875}, {887, 1},
828
  {888, 2}, {890, 33625347}, {891, 1}, {894, 16848643},
829
  {895, 16848899}, {896, 2}, {900, 33562883}, {901, 50403587},
830
  {902, 16849923}, {903, 16805379}, {904, 16850179}, {905, 16850435},
831
  {906, 16850691}, {907, 2}, {908, 16850947}, {909, 2},
832
  {910, 16851203}, {911, 16851459}, {912, 1}, {913, 16851715},
833
  {914, 16851971}, {915, 16852227}, {916, 16852483}, {917, 16852739},
834
  {918, 16852995}, {919, 16853251}, {920, 16853507}, {921, 16846851},
835
  {922, 16853763}, {923, 16854019}, {924, 16786179}, {925, 16854275},
836
  {926, 16854531}, {927, 16854787}, {928, 16855043}, {929, 16855299},
837
  {930, 2}, {931, 16855555}, {932, 16855811}, {933, 16856067},
838
  {934, 16856323}, {935, 16856579}, {936, 16856835}, {937, 16857091},
839
  {938, 16857347}, {939, 16857603}, {940, 1}, {975, 16857859},
840
  {976, 16851971}, {977, 16853507}, {978, 16856067}, {979, 16851203},
841
  {980, 16857603}, {981, 16856323}, {982, 16855043}, {983, 1},
842
  {984, 16858115}, {985, 1}, {986, 16858371}, {987, 1},
843
  {988, 16858627}, {989, 1}, {990, 16858883}, {991, 1},
844
  {992, 16859139}, {993, 1}, {994, 16859395}, {995, 1},
845
  {996, 16859651}, {997, 1}, {998, 16859907}, {999, 1},
846
  {1000, 16860163}, {1001, 1}, {1002, 16860419}, {1003, 1},
847
  {1004, 16860675}, {1005, 1}, {1006, 16860931}, {1007, 1},
848
  {1008, 16853763}, {1009, 16855299}, {1010, 16855555}, {1011, 1},
849
  {1012, 16853507}, {1013, 16852739}, {1014, 1}, {1015, 16861187},
850
  {1016, 1}, {1017, 16855555}, {1018, 16861443}, {1019, 1},
851
  {1021, 16861699}, {1022, 16861955}, {1023, 16862211}, {1024, 16862467},
852
  {1025, 16862723}, {1026, 16862979}, {1027, 16863235}, {1028, 16863491},
853
  {1029, 16863747}, {1030, 16864003}, {1031, 16864259}, {1032, 16864515},
854
  {1033, 16864771}, {1034, 16865027}, {1035, 16865283}, {1036, 16865539},
855
  {1037, 16865795}, {1038, 16866051}, {1039, 16866307}, {1040, 16866563},
856
  {1041, 16866819}, {1042, 16867075}, {1043, 16867331}, {1044, 16867587},
857
  {1045, 16867843}, {1046, 16868099}, {1047, 16868355}, {1048, 16868611},
858
  {1049, 16868867}, {1050, 16869123}, {1051, 16869379}, {1052, 16869635},
859
  {1053, 16869891}, {1054, 16870147}, {1055, 16870403}, {1056, 16870659},
860
  {1057, 16870915}, {1058, 16871171}, {1059, 16871427}, {1060, 16871683},
861
  {1061, 16871939}, {1062, 16872195}, {1063, 16872451}, {1064, 16872707},
862
  {1065, 16872963}, {1066, 16873219}, {1067, 16873475}, {1068, 16873731},
863
  {1069, 16873987}, {1070, 16874243}, {1071, 16874499}, {1072, 1},
864
  {1120, 16874755}, {1121, 1}, {1122, 16875011}, {1123, 1},
865
  {1124, 16875267}, {1125, 1}, {1126, 16875523}, {1127, 1},
866
  {1128, 16875779}, {1129, 1}, {1130, 16876035}, {1131, 1},
867
  {1132, 16876291}, {1133, 1}, {1134, 16876547}, {1135, 1},
868
  {1136, 16876803}, {1137, 1}, {1138, 16877059}, {1139, 1},
869
  {1140, 16877315}, {1141, 1}, {1142, 16877571}, {1143, 1},
870
  {1144, 16877827}, {1145, 1}, {1146, 16878083}, {1147, 1},
871
  {1148, 16878339}, {1149, 1}, {1150, 16878595}, {1151, 1},
872
  {1152, 16878851}, {1153, 1}, {1162, 16879107}, {1163, 1},
873
  {1164, 16879363}, {1165, 1}, {1166, 16879619}, {1167, 1},
874
  {1168, 16879875}, {1169, 1}, {1170, 16880131}, {1171, 1},
875
  {1172, 16880387}, {1173, 1}, {1174, 16880643}, {1175, 1},
876
  {1176, 16880899}, {1177, 1}, {1178, 16881155}, {1179, 1},
877
  {1180, 16881411}, {1181, 1}, {1182, 16881667}, {1183, 1},
878
  {1184, 16881923}, {1185, 1}, {1186, 16882179}, {1187, 1},
879
  {1188, 16882435}, {1189, 1}, {1190, 16882691}, {1191, 1},
880
  {1192, 16882947}, {1193, 1}, {1194, 16883203}, {1195, 1},
881
  {1196, 16883459}, {1197, 1}, {1198, 16883715}, {1199, 1},
882
  {1200, 16883971}, {1201, 1}, {1202, 16884227}, {1203, 1},
883
  {1204, 16884483}, {1205, 1}, {1206, 16884739}, {1207, 1},
884
  {1208, 16884995}, {1209, 1}, {1210, 16885251}, {1211, 1},
885
  {1212, 16885507}, {1213, 1}, {1214, 16885763}, {1215, 1},
886
  {1216, 2}, {1217, 16886019}, {1218, 1}, {1219, 16886275},
887
  {1220, 1}, {1221, 16886531}, {1222, 1}, {1223, 16886787},
888
  {1224, 1}, {1225, 16887043}, {1226, 1}, {1227, 16887299},
889
  {1228, 1}, {1229, 16887555}, {1230, 1}, {1232, 16887811},
890
  {1233, 1}, {1234, 16888067}, {1235, 1}, {1236, 16888323},
891
  {1237, 1}, {1238, 16888579}, {1239, 1}, {1240, 16888835},
892
  {1241, 1}, {1242, 16889091}, {1243, 1}, {1244, 16889347},
893
  {1245, 1}, {1246, 16889603}, {1247, 1}, {1248, 16889859},
894
  {1249, 1}, {1250, 16890115}, {1251, 1}, {1252, 16890371},
895
  {1253, 1}, {1254, 16890627}, {1255, 1}, {1256, 16890883},
896
  {1257, 1}, {1258, 16891139}, {1259, 1}, {1260, 16891395},
897
  {1261, 1}, {1262, 16891651}, {1263, 1}, {1264, 16891907},
898
  {1265, 1}, {1266, 16892163}, {1267, 1}, {1268, 16892419},
899
  {1269, 1}, {1270, 16892675}, {1271, 1}, {1272, 16892931},
900
  {1273, 1}, {1274, 16893187}, {1275, 1}, {1276, 16893443},
901
  {1277, 1}, {1278, 16893699}, {1279, 1}, {1280, 16893955},
902
  {1281, 1}, {1282, 16894211}, {1283, 1}, {1284, 16894467},
903
  {1285, 1}, {1286, 16894723}, {1287, 1}, {1288, 16894979},
904
  {1289, 1}, {1290, 16895235}, {1291, 1}, {1292, 16895491},
905
  {1293, 1}, {1294, 16895747}, {1295, 1}, {1296, 16896003},
906
  {1297, 1}, {1298, 16896259}, {1299, 1}, {1300, 16896515},
907
  {1301, 1}, {1302, 16896771}, {1303, 1}, {1304, 16897027},
908
  {1305, 1}, {1306, 16897283}, {1307, 1}, {1308, 16897539},
909
  {1309, 1}, {1310, 16897795}, {1311, 1}, {1312, 16898051},
910
  {1313, 1}, {1314, 16898307}, {1315, 1}, {1316, 16898563},
911
  {1317, 1}, {1318, 16898819}, {1319, 1}, {1320, 16899075},
912
  {1321, 1}, {1322, 16899331}, {1323, 1}, {1324, 16899587},
913
  {1325, 1}, {1326, 16899843}, {1327, 1}, {1328, 2},
914
  {1329, 16900099}, {1330, 16900355}, {1331, 16900611}, {1332, 16900867},
915
  {1333, 16901123}, {1334, 16901379}, {1335, 16901635}, {1336, 16901891},
916
  {1337, 16902147}, {1338, 16902403}, {1339, 16902659}, {1340, 16902915},
917
  {1341, 16903171}, {1342, 16903427}, {1343, 16903683}, {1344, 16903939},
918
  {1345, 16904195}, {1346, 16904451}, {1347, 16904707}, {1348, 16904963},
919
  {1349, 16905219}, {1350, 16905475}, {1351, 16905731}, {1352, 16905987},
920
  {1353, 16906243}, {1354, 16906499}, {1355, 16906755}, {1356, 16907011},
921
  {1357, 16907267}, {1358, 16907523}, {1359, 16907779}, {1360, 16908035},
922
  {1361, 16908291}, {1362, 16908547}, {1363, 16908803}, {1364, 16909059},
923
  {1365, 16909315}, {1366, 16909571}, {1367, 2}, {1369, 1},
924
  {1415, 33687043}, {1416, 1}, {1419, 2}, {1421, 1},
925
  {1424, 2}, {1425, 1}, {1480, 2}, {1488, 1},
926
  {1515, 2}, {1519, 1}, {1525, 2}, {1542, 1},
927
  {1564, 2}, {1565, 1}, {1653, 33687555}, {1654, 33688067},
928
  {1655, 33688579}, {1656, 33689091}, {1657, 1}, {1757, 2},
929
  {1758, 1}, {1806, 2}, {1808, 1}, {1867, 2},
930
  {1869, 1}, {1970, 2}, {1984, 1}, {2043, 2},
931
  {2045, 1}, {2094, 2}, {2096, 1}, {2111, 2},
932
  {2112, 1}, {2140, 2}, {2142, 1}, {2143, 2},
933
  {2144, 1}, {2155, 2}, {2160, 1}, {2191, 2},
934
  {2200, 1}, {2274, 2}, {2275, 1}, {2392, 33689603},
935
  {2393, 33690115}, {2394, 33690627}, {2395, 33691139}, {2396, 33691651},
936
  {2397, 33692163}, {2398, 33692675}, {2399, 33693187}, {2400, 1},
937
  {2436, 2}, {2437, 1}, {2445, 2}, {2447, 1},
938
  {2449, 2}, {2451, 1}, {2473, 2}, {2474, 1},
939
  {2481, 2}, {2482, 1}, {2483, 2}, {2486, 1},
940
  {2490, 2}, {2492, 1}, {2501, 2}, {2503, 1},
941
  {2505, 2}, {2507, 1}, {2511, 2}, {2519, 1},
942
  {2520, 2}, {2524, 33693699}, {2525, 33694211}, {2526, 2},
943
  {2527, 33694723}, {2528, 1}, {2532, 2}, {2534, 1},
944
  {2559, 2}, {2561, 1}, {2564, 2}, {2565, 1},
945
  {2571, 2}, {2575, 1}, {2577, 2}, {2579, 1},
946
  {2601, 2}, {2602, 1}, {2609, 2}, {2610, 1},
947
  {2611, 33695235}, {2612, 2}, {2613, 1}, {2614, 33695747},
948
  {2615, 2}, {2616, 1}, {2618, 2}, {2620, 1},
949
  {2621, 2}, {2622, 1}, {2627, 2}, {2631, 1},
950
  {2633, 2}, {2635, 1}, {2638, 2}, {2641, 1},
951
  {2642, 2}, {2649, 33696259}, {2650, 33696771}, {2651, 33697283},
952
  {2652, 1}, {2653, 2}, {2654, 33697795}, {2655, 2},
953
  {2662, 1}, {2679, 2}, {2689, 1}, {2692, 2},
954
  {2693, 1}, {2702, 2}, {2703, 1}, {2706, 2},
955
  {2707, 1}, {2729, 2}, {2730, 1}, {2737, 2},
956
  {2738, 1}, {2740, 2}, {2741, 1}, {2746, 2},
957
  {2748, 1}, {2758, 2}, {2759, 1}, {2762, 2},
958
  {2763, 1}, {2766, 2}, {2768, 1}, {2769, 2},
959
  {2784, 1}, {2788, 2}, {2790, 1}, {2802, 2},
960
  {2809, 1}, {2816, 2}, {2817, 1}, {2820, 2},
961
  {2821, 1}, {2829, 2}, {2831, 1}, {2833, 2},
962
  {2835, 1}, {2857, 2}, {2858, 1}, {2865, 2},
963
  {2866, 1}, {2868, 2}, {2869, 1}, {2874, 2},
964
  {2876, 1}, {2885, 2}, {2887, 1}, {2889, 2},
965
  {2891, 1}, {2894, 2}, {2901, 1}, {2904, 2},
966
  {2908, 33698307}, {2909, 33698819}, {2910, 2}, {2911, 1},
967
  {2916, 2}, {2918, 1}, {2936, 2}, {2946, 1},
968
  {2948, 2}, {2949, 1}, {2955, 2}, {2958, 1},
969
  {2961, 2}, {2962, 1}, {2966, 2}, {2969, 1},
970
  {2971, 2}, {2972, 1}, {2973, 2}, {2974, 1},
971
  {2976, 2}, {2979, 1}, {2981, 2}, {2984, 1},
972
  {2987, 2}, {2990, 1}, {3002, 2}, {3006, 1},
973
  {3011, 2}, {3014, 1}, {3017, 2}, {3018, 1},
974
  {3022, 2}, {3024, 1}, {3025, 2}, {3031, 1},
975
  {3032, 2}, {3046, 1}, {3067, 2}, {3072, 1},
976
  {3085, 2}, {3086, 1}, {3089, 2}, {3090, 1},
977
  {3113, 2}, {3114, 1}, {3130, 2}, {3132, 1},
978
  {3141, 2}, {3142, 1}, {3145, 2}, {3146, 1},
979
  {3150, 2}, {3157, 1}, {3159, 2}, {3160, 1},
980
  {3163, 2}, {3165, 1}, {3166, 2}, {3168, 1},
981
  {3172, 2}, {3174, 1}, {3184, 2}, {3191, 1},
982
  {3213, 2}, {3214, 1}, {3217, 2}, {3218, 1},
983
  {3241, 2}, {3242, 1}, {3252, 2}, {3253, 1},
984
  {3258, 2}, {3260, 1}, {3269, 2}, {3270, 1},
985
  {3273, 2}, {3274, 1}, {3278, 2}, {3285, 1},
986
  {3287, 2}, {3293, 1}, {3295, 2}, {3296, 1},
987
  {3300, 2}, {3302, 1}, {3312, 2}, {3313, 1},
988
  {3316, 2}, {3328, 1}, {3341, 2}, {3342, 1},
989
  {3345, 2}, {3346, 1}, {3397, 2}, {3398, 1},
990
  {3401, 2}, {3402, 1}, {3408, 2}, {3412, 1},
991
  {3428, 2}, {3430, 1}, {3456, 2}, {3457, 1},
992
  {3460, 2}, {3461, 1}, {3479, 2}, {3482, 1},
993
  {3506, 2}, {3507, 1}, {3516, 2}, {3517, 1},
994
  {3518, 2}, {3520, 1}, {3527, 2}, {3530, 1},
995
  {3531, 2}, {3535, 1}, {3541, 2}, {3542, 1},
996
  {3543, 2}, {3544, 1}, {3552, 2}, {3558, 1},
997
  {3568, 2}, {3570, 1}, {3573, 2}, {3585, 1},
998
  {3635, 33699331}, {3636, 1}, {3643, 2}, {3647, 1},
999
  {3676, 2}, {3713, 1}, {3715, 2}, {3716, 1},
1000
  {3717, 2}, {3718, 1}, {3723, 2}, {3724, 1},
1001
  {3748, 2}, {3749, 1}, {3750, 2}, {3751, 1},
1002
  {3763, 33699843}, {3764, 1}, {3774, 2}, {3776, 1},
1003
  {3781, 2}, {3782, 1}, {3783, 2}, {3784, 1},
1004
  {3791, 2}, {3792, 1}, {3802, 2}, {3804, 33700355},
1005
  {3805, 33700867}, {3806, 1}, {3808, 2}, {3840, 1},
1006
  {3852, 16924163}, {3853, 1}, {3907, 33701635}, {3908, 1},
1007
  {3912, 2}, {3913, 1}, {3917, 33702147}, {3918, 1},
1008
  {3922, 33702659}, {3923, 1}, {3927, 33703171}, {3928, 1},
1009
  {3932, 33703683}, {3933, 1}, {3945, 33704195}, {3946, 1},
1010
  {3949, 2}, {3953, 1}, {3955, 33704707}, {3956, 1},
1011
  {3957, 33705219}, {3958, 33705731}, {3959, 50483459}, {3960, 33707011},
1012
  {3961, 50484739}, {3962, 1}, {3969, 33706499}, {3970, 1},
1013
  {3987, 33708291}, {3988, 1}, {3992, 2}, {3993, 1},
1014
  {3997, 33708803}, {3998, 1}, {4002, 33709315}, {4003, 1},
1015
  {4007, 33709827}, {4008, 1}, {4012, 33710339}, {4013, 1},
1016
  {4025, 33710851}, {4026, 1}, {4029, 2}, {4030, 1},
1017
  {4045, 2}, {4046, 1}, {4059, 2}, {4096, 1},
1018
  {4256, 2}, {4295, 16934147}, {4296, 2}, {4301, 16934403},
1019
  {4302, 2}, {4304, 1}, {4348, 16934659}, {4349, 1},
1020
  {4447, 2}, {4449, 1}, {4681, 2}, {4682, 1},
1021
  {4686, 2}, {4688, 1}, {4695, 2}, {4696, 1},
1022
  {4697, 2}, {4698, 1}, {4702, 2}, {4704, 1},
1023
  {4745, 2}, {4746, 1}, {4750, 2}, {4752, 1},
1024
  {4785, 2}, {4786, 1}, {4790, 2}, {4792, 1},
1025
  {4799, 2}, {4800, 1}, {4801, 2}, {4802, 1},
1026
  {4806, 2}, {4808, 1}, {4823, 2}, {4824, 1},
1027
  {4881, 2}, {4882, 1}, {4886, 2}, {4888, 1},
1028
  {4955, 2}, {4957, 1}, {4989, 2}, {4992, 1},
1029
  {5018, 2}, {5024, 1}, {5110, 2}, {5112, 16934915},
1030
  {5113, 16935171}, {5114, 16935427}, {5115, 16935683}, {5116, 16935939},
1031
  {5117, 16936195}, {5118, 2}, {5120, 1}, {5760, 2},
1032
  {5761, 1}, {5789, 2}, {5792, 1}, {5881, 2},
1033
  {5888, 1}, {5910, 2}, {5919, 1}, {5943, 2},
1034
  {5952, 1}, {5972, 2}, {5984, 1}, {5997, 2},
1035
  {5998, 1}, {6001, 2}, {6002, 1}, {6004, 2},
1036
  {6016, 1}, {6068, 2}, {6070, 1}, {6110, 2},
1037
  {6112, 1}, {6122, 2}, {6128, 1}, {6138, 2},
1038
  {6144, 1}, {6150, 2}, {6151, 1}, {6155, 0},
1039
  {6158, 2}, {6159, 0}, {6160, 1}, {6170, 2},
1040
  {6176, 1}, {6265, 2}, {6272, 1}, {6315, 2},
1041
  {6320, 1}, {6390, 2}, {6400, 1}, {6431, 2},
1042
  {6432, 1}, {6444, 2}, {6448, 1}, {6460, 2},
1043
  {6464, 1}, {6465, 2}, {6468, 1}, {6510, 2},
1044
  {6512, 1}, {6517, 2}, {6528, 1}, {6572, 2},
1045
  {6576, 1}, {6602, 2}, {6608, 1}, {6619, 2},
1046
  {6622, 1}, {6684, 2}, {6686, 1}, {6751, 2},
1047
  {6752, 1}, {6781, 2}, {6783, 1}, {6794, 2},
1048
  {6800, 1}, {6810, 2}, {6816, 1}, {6830, 2},
1049
  {6832, 1}, {6863, 2}, {6912, 1}, {6989, 2},
1050
  {6992, 1}, {7039, 2}, {7040, 1}, {7156, 2},
1051
  {7164, 1}, {7224, 2}, {7227, 1}, {7242, 2},
1052
  {7245, 1}, {7296, 16867075}, {7297, 16867587}, {7298, 16870147},
1053
  {7299, 16870915}, {7300, 16871171}, {7302, 16873219}, {7303, 16875011},
1054
  {7304, 16936451}, {7305, 2}, {7312, 16936707}, {7313, 16936963},
1055
  {7314, 16937219}, {7315, 16937475}, {7316, 16937731}, {7317, 16937987},
1056
  {7318, 16938243}, {7319, 16938499}, {7320, 16938755}, {7321, 16939011},
1057
  {7322, 16939267}, {7323, 16939523}, {7324, 16934659}, {7325, 16939779},
1058
  {7326, 16940035}, {7327, 16940291}, {7328, 16940547}, {7329, 16940803},
1059
  {7330, 16941059}, {7331, 16941315}, {7332, 16941571}, {7333, 16941827},
1060
  {7334, 16942083}, {7335, 16942339}, {7336, 16942595}, {7337, 16942851},
1061
  {7338, 16943107}, {7339, 16943363}, {7340, 16943619}, {7341, 16943875},
1062
  {7342, 16944131}, {7343, 16944387}, {7344, 16944643}, {7345, 16944899},
1063
  {7346, 16945155}, {7347, 16945411}, {7348, 16945667}, {7349, 16945923},
1064
  {7350, 16946179}, {7351, 16946435}, {7352, 16946691}, {7353, 16946947},
1065
  {7354, 16947203}, {7355, 2}, {7357, 16947459}, {7358, 16947715},
1066
  {7359, 16947971}, {7360, 1}, {7368, 2}, {7376, 1},
1067
  {7419, 2}, {7424, 1}, {7468, 16777219}, {7469, 16791043},
1068
  {7470, 16777475}, {7471, 1}, {7472, 16777987}, {7473, 16778243},
1069
  {7474, 16816131}, {7475, 16778755}, {7476, 16779011}, {7477, 16779267},
1070
  {7478, 16779523}, {7479, 16779779}, {7480, 16780035}, {7481, 16780291},
1071
  {7482, 16780547}, {7483, 1}, {7484, 16780803}, {7485, 16835843},
1072
  {7486, 16781059}, {7487, 16781571}, {7488, 16782083}, {7489, 16782339},
1073
  {7490, 16782851}, {7491, 16777219}, {7492, 16948227}, {7493, 16948483},
1074
  {7494, 16948739}, {7495, 16777475}, {7496, 16777987}, {7497, 16778243},
1075
  {7498, 16816387}, {7499, 16816643}, {7500, 16948995}, {7501, 16778755},
1076
  {7502, 1}, {7503, 16779779}, {7504, 16780291}, {7505, 16807171},
1077
  {7506, 16780803}, {7507, 16814851}, {7508, 16949251}, {7509, 16949507},
1078
  {7510, 16781059}, {7511, 16782083}, {7512, 16782339}, {7513, 16949763},
1079
  {7514, 16818435}, {7515, 16782595}, {7516, 16950019}, {7517, 16851971},
1080
  {7518, 16852227}, {7519, 16852483}, {7520, 16856323}, {7521, 16856579},
1081
  {7522, 16779267}, {7523, 16781571}, {7524, 16782339}, {7525, 16782595},
1082
  {7526, 16851971}, {7527, 16852227}, {7528, 16855299}, {7529, 16856323},
1083
  {7530, 16856579}, {7531, 1}, {7544, 16869891}, {7545, 1},
1084
  {7579, 16950275}, {7580, 16777731}, {7581, 16950531}, {7582, 16793603},
1085
  {7583, 16948995}, {7584, 16778499}, {7585, 16950787}, {7586, 16951043},
1086
  {7587, 16951299}, {7588, 16817923}, {7589, 16817667}, {7590, 16951555},
1087
  {7591, 16951811}, {7592, 16952067}, {7593, 16952323}, {7594, 16952579},
1088
  {7595, 16952835}, {7596, 16953091}, {7597, 16953347}, {7598, 16818691},
1089
  {7599, 16953603}, {7600, 16953859}, {7601, 16818947}, {7602, 16954115},
1090
  {7603, 16954371}, {7604, 16820483}, {7605, 16954627}, {7606, 16839683},
1091
  {7607, 16821507}, {7608, 16954883}, {7609, 16821763}, {7610, 16839939},
1092
  {7611, 16783619}, {7612, 16955139}, {7613, 16955395}, {7614, 16822531},
1093
  {7615, 16853507}, {7616, 1}, {7680, 16955651}, {7681, 1},
1094
  {7682, 16955907}, {7683, 1}, {7684, 16956163}, {7685, 1},
1095
  {7686, 16956419}, {7687, 1}, {7688, 16956675}, {7689, 1},
1096
  {7690, 16956931}, {7691, 1}, {7692, 16957187}, {7693, 1},
1097
  {7694, 16957443}, {7695, 1}, {7696, 16957699}, {7697, 1},
1098
  {7698, 16957955}, {7699, 1}, {7700, 16958211}, {7701, 1},
1099
  {7702, 16958467}, {7703, 1}, {7704, 16958723}, {7705, 1},
1100
  {7706, 16958979}, {7707, 1}, {7708, 16959235}, {7709, 1},
1101
  {7710, 16959491}, {7711, 1}, {7712, 16959747}, {7713, 1},
1102
  {7714, 16960003}, {7715, 1}, {7716, 16960259}, {7717, 1},
1103
  {7718, 16960515}, {7719, 1}, {7720, 16960771}, {7721, 1},
1104
  {7722, 16961027}, {7723, 1}, {7724, 16961283}, {7725, 1},
1105
  {7726, 16961539}, {7727, 1}, {7728, 16961795}, {7729, 1},
1106
  {7730, 16962051}, {7731, 1}, {7732, 16962307}, {7733, 1},
1107
  {7734, 16962563}, {7735, 1}, {7736, 16962819}, {7737, 1},
1108
  {7738, 16963075}, {7739, 1}, {7740, 16963331}, {7741, 1},
1109
  {7742, 16963587}, {7743, 1}, {7744, 16963843}, {7745, 1},
1110
  {7746, 16964099}, {7747, 1}, {7748, 16964355}, {7749, 1},
1111
  {7750, 16964611}, {7751, 1}, {7752, 16964867}, {7753, 1},
1112
  {7754, 16965123}, {7755, 1}, {7756, 16965379}, {7757, 1},
1113
  {7758, 16965635}, {7759, 1}, {7760, 16965891}, {7761, 1},
1114
  {7762, 16966147}, {7763, 1}, {7764, 16966403}, {7765, 1},
1115
  {7766, 16966659}, {7767, 1}, {7768, 16966915}, {7769, 1},
1116
  {7770, 16967171}, {7771, 1}, {7772, 16967427}, {7773, 1},
1117
  {7774, 16967683}, {7775, 1}, {7776, 16967939}, {7777, 1},
1118
  {7778, 16968195}, {7779, 1}, {7780, 16968451}, {7781, 1},
1119
  {7782, 16968707}, {7783, 1}, {7784, 16968963}, {7785, 1},
1120
  {7786, 16969219}, {7787, 1}, {7788, 16969475}, {7789, 1},
1121
  {7790, 16969731}, {7791, 1}, {7792, 16969987}, {7793, 1},
1122
  {7794, 16970243}, {7795, 1}, {7796, 16970499}, {7797, 1},
1123
  {7798, 16970755}, {7799, 1}, {7800, 16971011}, {7801, 1},
1124
  {7802, 16971267}, {7803, 1}, {7804, 16971523}, {7805, 1},
1125
  {7806, 16971779}, {7807, 1}, {7808, 16972035}, {7809, 1},
1126
  {7810, 16972291}, {7811, 1}, {7812, 16972547}, {7813, 1},
1127
  {7814, 16972803}, {7815, 1}, {7816, 16973059}, {7817, 1},
1128
  {7818, 16973315}, {7819, 1}, {7820, 16973571}, {7821, 1},
1129
  {7822, 16973827}, {7823, 1}, {7824, 16974083}, {7825, 1},
1130
  {7826, 16974339}, {7827, 1}, {7828, 16974595}, {7829, 1},
1131
  {7834, 33752067}, {7835, 16967939}, {7836, 1}, {7838, 33752579},
1132
  {7839, 1}, {7840, 16975875}, {7841, 1}, {7842, 16976131},
1133
  {7843, 1}, {7844, 16976387}, {7845, 1}, {7846, 16976643},
1134
  {7847, 1}, {7848, 16976899}, {7849, 1}, {7850, 16977155},
1135
  {7851, 1}, {7852, 16977411}, {7853, 1}, {7854, 16977667},
1136
  {7855, 1}, {7856, 16977923}, {7857, 1}, {7858, 16978179},
1137
  {7859, 1}, {7860, 16978435}, {7861, 1}, {7862, 16978691},
1138
  {7863, 1}, {7864, 16978947}, {7865, 1}, {7866, 16979203},
1139
  {7867, 1}, {7868, 16979459}, {7869, 1}, {7870, 16979715},
1140
  {7871, 1}, {7872, 16979971}, {7873, 1}, {7874, 16980227},
1141
  {7875, 1}, {7876, 16980483}, {7877, 1}, {7878, 16980739},
1142
  {7879, 1}, {7880, 16980995}, {7881, 1}, {7882, 16981251},
1143
  {7883, 1}, {7884, 16981507}, {7885, 1}, {7886, 16981763},
1144
  {7887, 1}, {7888, 16982019}, {7889, 1}, {7890, 16982275},
1145
  {7891, 1}, {7892, 16982531}, {7893, 1}, {7894, 16982787},
1146
  {7895, 1}, {7896, 16983043}, {7897, 1}, {7898, 16983299},
1147
  {7899, 1}, {7900, 16983555}, {7901, 1}, {7902, 16983811},
1148
  {7903, 1}, {7904, 16984067}, {7905, 1}, {7906, 16984323},
1149
  {7907, 1}, {7908, 16984579}, {7909, 1}, {7910, 16984835},
1150
  {7911, 1}, {7912, 16985091}, {7913, 1}, {7914, 16985347},
1151
  {7915, 1}, {7916, 16985603}, {7917, 1}, {7918, 16985859},
1152
  {7919, 1}, {7920, 16986115}, {7921, 1}, {7922, 16986371},
1153
  {7923, 1}, {7924, 16986627}, {7925, 1}, {7926, 16986883},
1154
  {7927, 1}, {7928, 16987139}, {7929, 1}, {7930, 16987395},
1155
  {7931, 1}, {7932, 16987651}, {7933, 1}, {7934, 16987907},
1156
  {7935, 1}, {7944, 16988163}, {7945, 16988419}, {7946, 16988675},
1157
  {7947, 16988931}, {7948, 16989187}, {7949, 16989443}, {7950, 16989699},
1158
  {7951, 16989955}, {7952, 1}, {7958, 2}, {7960, 16990211},
1159
  {7961, 16990467}, {7962, 16990723}, {7963, 16990979}, {7964, 16991235},
1160
  {7965, 16991491}, {7966, 2}, {7968, 1}, {7976, 16991747},
1161
  {7977, 16992003}, {7978, 16992259}, {7979, 16992515}, {7980, 16992771},
1162
  {7981, 16993027}, {7982, 16993283}, {7983, 16993539}, {7984, 1},
1163
  {7992, 16993795}, {7993, 16994051}, {7994, 16994307}, {7995, 16994563},
1164
  {7996, 16994819}, {7997, 16995075}, {7998, 16995331}, {7999, 16995587},
1165
  {8000, 1}, {8006, 2}, {8008, 16995843}, {8009, 16996099},
1166
  {8010, 16996355}, {8011, 16996611}, {8012, 16996867}, {8013, 16997123},
1167
  {8014, 2}, {8016, 1}, {8024, 2}, {8025, 16997379},
1168
  {8026, 2}, {8027, 16997635}, {8028, 2}, {8029, 16997891},
1169
  {8030, 2}, {8031, 16998147}, {8032, 1}, {8040, 16998403},
1170
  {8041, 16998659}, {8042, 16998915}, {8043, 16999171}, {8044, 16999427},
1171
  {8045, 16999683}, {8046, 16999939}, {8047, 17000195}, {8048, 1},
1172
  {8049, 16849923}, {8050, 1}, {8051, 16850179}, {8052, 1},
1173
  {8053, 16850435}, {8054, 1}, {8055, 16850691}, {8056, 1},
1174
  {8057, 16850947}, {8058, 1}, {8059, 16851203}, {8060, 1},
1175
  {8061, 16851459}, {8062, 2}, {8064, 33777667}, {8065, 33778179},
1176
  {8066, 33778691}, {8067, 33779203}, {8068, 33779715}, {8069, 33780227},
1177
  {8070, 33780739}, {8071, 33781251}, {8072, 33777667}, {8073, 33778179},
1178
  {8074, 33778691}, {8075, 33779203}, {8076, 33779715}, {8077, 33780227},
1179
  {8078, 33780739}, {8079, 33781251}, {8080, 33781763}, {8081, 33782275},
1180
  {8082, 33782787}, {8083, 33783299}, {8084, 33783811}, {8085, 33784323},
1181
  {8086, 33784835}, {8087, 33785347}, {8088, 33781763}, {8089, 33782275},
1182
  {8090, 33782787}, {8091, 33783299}, {8092, 33783811}, {8093, 33784323},
1183
  {8094, 33784835}, {8095, 33785347}, {8096, 33785859}, {8097, 33786371},
1184
  {8098, 33786883}, {8099, 33787395}, {8100, 33787907}, {8101, 33788419},
1185
  {8102, 33788931}, {8103, 33789443}, {8104, 33785859}, {8105, 33786371},
1186
  {8106, 33786883}, {8107, 33787395}, {8108, 33787907}, {8109, 33788419},
1187
  {8110, 33788931}, {8111, 33789443}, {8112, 1}, {8114, 33789955},
1188
  {8115, 33790467}, {8116, 33790979}, {8117, 2}, {8118, 1},
1189
  {8119, 33791491}, {8120, 17014787}, {8121, 17015043}, {8122, 17012739},
1190
  {8123, 16849923}, {8124, 33790467}, {8125, 33792515}, {8126, 16846851},
1191
  {8127, 33792515}, {8128, 33793027}, {8129, 50570755}, {8130, 33794307},
1192
  {8131, 33794819}, {8132, 33795331}, {8133, 2}, {8134, 1},
1193
  {8135, 33795843}, {8136, 17019139}, {8137, 16850179}, {8138, 17017091},
1194
  {8139, 16850435}, {8140, 33794819}, {8141, 50573827}, {8142, 50574595},
1195
  {8143, 50575363}, {8144, 1}, {8147, 17021699}, {8148, 2},
1196
  {8150, 1}, {8152, 17021955}, {8153, 17022211}, {8154, 17022467},
1197
  {8155, 16850691}, {8156, 2}, {8157, 50577155}, {8158, 50577923},
1198
  {8159, 50578691}, {8160, 1}, {8163, 17025027}, {8164, 1},
1199
  {8168, 17025283}, {8169, 17025539}, {8170, 17025795}, {8171, 16851203},
1200
  {8172, 17026051}, {8173, 50580739}, {8174, 50403587}, {8175, 17027075},
1201
  {8176, 2}, {8178, 33804547}, {8179, 33805059}, {8180, 33805571},
1202
  {8181, 2}, {8182, 1}, {8183, 33806083}, {8184, 17029379},
1203
  {8185, 16850947}, {8186, 17027331}, {8187, 16851459}, {8188, 33805059},
1204
  {8189, 33562883}, {8190, 33799939}, {8191, 2}, {8192, 16783875},
1205
  {8203, 0}, {8204, 1}, {8206, 2}, {8208, 1},
1206
  {8209, 17029635}, {8210, 1}, {8215, 33807107}, {8216, 1},
1207
  {8228, 2}, {8231, 1}, {8232, 2}, {8239, 16783875},
1208
  {8240, 1}, {8243, 33807619}, {8244, 50585347}, {8245, 1},
1209
  {8246, 33808899}, {8247, 50586627}, {8248, 1}, {8252, 33810179},
1210
  {8253, 1}, {8254, 33810691}, {8255, 1}, {8263, 33811203},
1211
  {8264, 33811715}, {8265, 33812227}, {8266, 1}, {8279, 67362051},
1212
  {8280, 1}, {8287, 16783875}, {8288, 0}, {8289, 2},
1213
  {8292, 0}, {8293, 2}, {8304, 17035523}, {8305, 16779267},
1214
  {8306, 2}, {8308, 16787715}, {8309, 17035779}, {8310, 17036035},
1215
  {8311, 17036291}, {8312, 17036547}, {8313, 17036803}, {8314, 17037059},
1216
  {8315, 17037315}, {8316, 17037571}, {8317, 17037827}, {8318, 17038083},
1217
  {8319, 16780547}, {8320, 17035523}, {8321, 16786947}, {8322, 16785155},
1218
  {8323, 16785411}, {8324, 16787715}, {8325, 17035779}, {8326, 17036035},
1219
  {8327, 17036291}, {8328, 17036547}, {8329, 17036803}, {8330, 17037059},
1220
  {8331, 17037315}, {8332, 17037571}, {8333, 17037827}, {8334, 17038083},
1221
  {8335, 2}, {8336, 16777219}, {8337, 16778243}, {8338, 16780803},
1222
  {8339, 16783107}, {8340, 16816387}, {8341, 16779011}, {8342, 16779779},
1223
  {8343, 16780035}, {8344, 16780291}, {8345, 16780547}, {8346, 16781059},
1224
  {8347, 16781827}, {8348, 16782083}, {8349, 2}, {8352, 1},
1225
  {8360, 33558787}, {8361, 1}, {8385, 2}, {8400, 1},
1226
  {8433, 2}, {8448, 50592771}, {8449, 50593539}, {8450, 16777731},
1227
  {8451, 33817091}, {8452, 1}, {8453, 50594819}, {8454, 50595587},
1228
  {8455, 16816643}, {8456, 1}, {8457, 33819139}, {8458, 16778755},
1229
  {8459, 16779011}, {8463, 16802051}, {8464, 16779267}, {8466, 16780035},
1230
  {8468, 1}, {8469, 16780547}, {8470, 33557763}, {8471, 1},
1231
  {8473, 16781059}, {8474, 16781315}, {8475, 16781571}, {8478, 1},
1232
  {8480, 33819651}, {8481, 50597379}, {8482, 33820931}, {8483, 1},
1233
  {8484, 16783619}, {8485, 1}, {8486, 16857091}, {8487, 1},
1234
  {8488, 16783619}, {8489, 1}, {8490, 16779779}, {8491, 16790787},
1235
  {8492, 16777475}, {8493, 16777731}, {8494, 1}, {8495, 16778243},
1236
  {8497, 16778499}, {8498, 2}, {8499, 16780291}, {8500, 16780803},
1237
  {8501, 17044227}, {8502, 17044483}, {8503, 17044739}, {8504, 17044995},
1238
  {8505, 16779267}, {8506, 1}, {8507, 50599683}, {8508, 16855043},
1239
  {8509, 16852227}, {8511, 16855043}, {8512, 17046019}, {8513, 1},
1240
  {8517, 16777987}, {8519, 16778243}, {8520, 16779267}, {8521, 16779523},
1241
  {8522, 1}, {8528, 50600707}, {8529, 50601475}, {8530, 67379459},
1242
  {8531, 50603267}, {8532, 50604035}, {8533, 50604803}, {8534, 50605571},
1243
  {8535, 50606339}, {8536, 50607107}, {8537, 50607875}, {8538, 50608643},
1244
  {8539, 50609411}, {8540, 50610179}, {8541, 50610947}, {8542, 50611715},
1245
  {8543, 33564419}, {8544, 16779267}, {8545, 33835267}, {8546, 50612995},
1246
  {8547, 33836547}, {8548, 16782595}, {8549, 33837059}, {8550, 50614787},
1247
  {8551, 67392771}, {8552, 33839363}, {8553, 16783107}, {8554, 33839875},
1248
  {8555, 50617603}, {8556, 16780035}, {8557, 16777731}, {8558, 16777987},
1249
  {8559, 16780291}, {8560, 16779267}, {8561, 33835267}, {8562, 50612483},
1250
  {8563, 33836547}, {8564, 16782595}, {8565, 33837059}, {8566, 50614787},
1251
  {8567, 67392771}, {8568, 33839363}, {8569, 16783107}, {8570, 33839875},
1252
  {8571, 50617603}, {8572, 16780035}, {8573, 16777731}, {8574, 16777987},
1253
  {8575, 16780291}, {8576, 1}, {8579, 2}, {8580, 1},
1254
  {8585, 50618371}, {8586, 1}, {8588, 2}, {8592, 1},
1255
  {8748, 33841923}, {8749, 50619651}, {8750, 1}, {8751, 33843203},
1256
  {8752, 50620931}, {8753, 1}, {9001, 17067267}, {9002, 17067523},
1257
  {9003, 1}, {9255, 2}, {9280, 1}, {9291, 2},
1258
  {9312, 16786947}, {9313, 16785155}, {9314, 16785411}, {9315, 16787715},
1259
  {9316, 17035779}, {9317, 17036035}, {9318, 17036291}, {9319, 17036547},
1260
  {9320, 17036803}, {9321, 33825539}, {9322, 33564163}, {9323, 33844995},
1261
  {9324, 33845507}, {9325, 33846019}, {9326, 33846531}, {9327, 33847043},
1262
  {9328, 33847555}, {9329, 33848067}, {9330, 33848579}, {9331, 33849091},
1263
  {9332, 50626819}, {9333, 50627587}, {9334, 50628355}, {9335, 50629123},
1264
  {9336, 50629891}, {9337, 50630659}, {9338, 50631427}, {9339, 50632195},
1265
  {9340, 50632963}, {9341, 67410947}, {9342, 67411971}, {9343, 67412995},
1266
  {9344, 67414019}, {9345, 67415043}, {9346, 67416067}, {9347, 67417091},
1267
  {9348, 67418115}, {9349, 67419139}, {9350, 67420163}, {9351, 67421187},
1268
  {9352, 2}, {9372, 50644995}, {9373, 50645763}, {9374, 50646531},
1269
  {9375, 50647299}, {9376, 50648067}, {9377, 50648835}, {9378, 50649603},
1270
  {9379, 50650371}, {9380, 50651139}, {9381, 50651907}, {9382, 50652675},
1271
  {9383, 50653443}, {9384, 50654211}, {9385, 50654979}, {9386, 50655747},
1272
  {9387, 50656515}, {9388, 50657283}, {9389, 50658051}, {9390, 50658819},
1273
  {9391, 50659587}, {9392, 50660355}, {9393, 50661123}, {9394, 50661891},
1274
  {9395, 50662659}, {9396, 50663427}, {9397, 50664195}, {9398, 16777219},
1275
  {9399, 16777475}, {9400, 16777731}, {9401, 16777987}, {9402, 16778243},
1276
  {9403, 16778499}, {9404, 16778755}, {9405, 16779011}, {9406, 16779267},
1277
  {9407, 16779523}, {9408, 16779779}, {9409, 16780035}, {9410, 16780291},
1278
  {9411, 16780547}, {9412, 16780803}, {9413, 16781059}, {9414, 16781315},
1279
  {9415, 16781571}, {9416, 16781827}, {9417, 16782083}, {9418, 16782339},
1280
  {9419, 16782595}, {9420, 16782851}, {9421, 16783107}, {9422, 16783363},
1281
  {9423, 16783619}, {9424, 16777219}, {9425, 16777475}, {9426, 16777731},
1282
  {9427, 16777987}, {9428, 16778243}, {9429, 16778499}, {9430, 16778755},
1283
  {9431, 16779011}, {9432, 16779267}, {9433, 16779523}, {9434, 16779779},
1284
  {9435, 16780035}, {9436, 16780291}, {9437, 16780547}, {9438, 16780803},
1285
  {9439, 16781059}, {9440, 16781315}, {9441, 16781571}, {9442, 16781827},
1286
  {9443, 16782083}, {9444, 16782339}, {9445, 16782595}, {9446, 16782851},
1287
  {9447, 16783107}, {9448, 16783363}, {9449, 16783619}, {9450, 17035523},
1288
  {9451, 1}, {10764, 67396355}, {10765, 1}, {10868, 50664963},
1289
  {10869, 33888515}, {10870, 50665475}, {10871, 1}, {10972, 33889027},
1290
  {10973, 1}, {11124, 2}, {11126, 1}, {11158, 2},
1291
  {11159, 1}, {11264, 17112323}, {11265, 17112579}, {11266, 17112835},
1292
  {11267, 17113091}, {11268, 17113347}, {11269, 17113603}, {11270, 17113859},
1293
  {11271, 17114115}, {11272, 17114371}, {11273, 17114627}, {11274, 17114883},
1294
  {11275, 17115139}, {11276, 17115395}, {11277, 17115651}, {11278, 17115907},
1295
  {11279, 17116163}, {11280, 17116419}, {11281, 17116675}, {11282, 17116931},
1296
  {11283, 17117187}, {11284, 17117443}, {11285, 17117699}, {11286, 17117955},
1297
  {11287, 17118211}, {11288, 17118467}, {11289, 17118723}, {11290, 17118979},
1298
  {11291, 17119235}, {11292, 17119491}, {11293, 17119747}, {11294, 17120003},
1299
  {11295, 17120259}, {11296, 17120515}, {11297, 17120771}, {11298, 17121027},
1300
  {11299, 17121283}, {11300, 17121539}, {11301, 17121795}, {11302, 17122051},
1301
  {11303, 17122307}, {11304, 17122563}, {11305, 17122819}, {11306, 17123075},
1302
  {11307, 17123331}, {11308, 17123587}, {11309, 17123843}, {11310, 17124099},
1303
  {11311, 17124355}, {11312, 1}, {11360, 17124611}, {11361, 1},
1304
  {11362, 17124867}, {11363, 17125123}, {11364, 17125379}, {11365, 1},
1305
  {11367, 17125635}, {11368, 1}, {11369, 17125891}, {11370, 1},
1306
  {11371, 17126147}, {11372, 1}, {11373, 16948483}, {11374, 16953091},
1307
  {11375, 16948227}, {11376, 16950275}, {11377, 1}, {11378, 17126403},
1308
  {11379, 1}, {11381, 17126659}, {11382, 1}, {11388, 16779523},
1309
  {11389, 16782595}, {11390, 17126915}, {11391, 17127171}, {11392, 17127427},
1310
  {11393, 1}, {11394, 17127683}, {11395, 1}, {11396, 17127939},
1311
  {11397, 1}, {11398, 17128195}, {11399, 1}, {11400, 17128451},
1312
  {11401, 1}, {11402, 17128707}, {11403, 1}, {11404, 17128963},
1313
  {11405, 1}, {11406, 17129219}, {11407, 1}, {11408, 17129475},
1314
  {11409, 1}, {11410, 17129731}, {11411, 1}, {11412, 17129987},
1315
  {11413, 1}, {11414, 17130243}, {11415, 1}, {11416, 17130499},
1316
  {11417, 1}, {11418, 17130755}, {11419, 1}, {11420, 17131011},
1317
  {11421, 1}, {11422, 17131267}, {11423, 1}, {11424, 17131523},
1318
  {11425, 1}, {11426, 17131779}, {11427, 1}, {11428, 17132035},
1319
  {11429, 1}, {11430, 17132291}, {11431, 1}, {11432, 17132547},
1320
  {11433, 1}, {11434, 17132803}, {11435, 1}, {11436, 17133059},
1321
  {11437, 1}, {11438, 17133315}, {11439, 1}, {11440, 17133571},
1322
  {11441, 1}, {11442, 17133827}, {11443, 1}, {11444, 17134083},
1323
  {11445, 1}, {11446, 17134339}, {11447, 1}, {11448, 17134595},
1324
  {11449, 1}, {11450, 17134851}, {11451, 1}, {11452, 17135107},
1325
  {11453, 1}, {11454, 17135363}, {11455, 1}, {11456, 17135619},
1326
  {11457, 1}, {11458, 17135875}, {11459, 1}, {11460, 17136131},
1327
  {11461, 1}, {11462, 17136387}, {11463, 1}, {11464, 17136643},
1328
  {11465, 1}, {11466, 17136899}, {11467, 1}, {11468, 17137155},
1329
  {11469, 1}, {11470, 17137411}, {11471, 1}, {11472, 17137667},
1330
  {11473, 1}, {11474, 17137923}, {11475, 1}, {11476, 17138179},
1331
  {11477, 1}, {11478, 17138435}, {11479, 1}, {11480, 17138691},
1332
  {11481, 1}, {11482, 17138947}, {11483, 1}, {11484, 17139203},
1333
  {11485, 1}, {11486, 17139459}, {11487, 1}, {11488, 17139715},
1334
  {11489, 1}, {11490, 17139971}, {11491, 1}, {11499, 17140227},
1335
  {11500, 1}, {11501, 17140483}, {11502, 1}, {11506, 17140739},
1336
  {11507, 1}, {11508, 2}, {11513, 1}, {11558, 2},
1337
  {11559, 1}, {11560, 2}, {11565, 1}, {11566, 2},
1338
  {11568, 1}, {11624, 2}, {11631, 17140995}, {11632, 1},
1339
  {11633, 2}, {11647, 1}, {11671, 2}, {11680, 1},
1340
  {11687, 2}, {11688, 1}, {11695, 2}, {11696, 1},
1341
  {11703, 2}, {11704, 1}, {11711, 2}, {11712, 1},
1342
  {11719, 2}, {11720, 1}, {11727, 2}, {11728, 1},
1343
  {11735, 2}, {11736, 1}, {11743, 2}, {11744, 1},
1344
  {11870, 2}, {11904, 1}, {11930, 2}, {11931, 1},
1345
  {11935, 17141251}, {11936, 1}, {12019, 17141507}, {12020, 2},
1346
  {12032, 17141763}, {12033, 17142019}, {12034, 17142275}, {12035, 17142531},
1347
  {12036, 17142787}, {12037, 17143043}, {12038, 17143299}, {12039, 17143555},
1348
  {12040, 17143811}, {12041, 17144067}, {12042, 17144323}, {12043, 17144579},
1349
  {12044, 17144835}, {12045, 17145091}, {12046, 17145347}, {12047, 17145603},
1350
  {12048, 17145859}, {12049, 17146115}, {12050, 17146371}, {12051, 17146627},
1351
  {12052, 17146883}, {12053, 17147139}, {12054, 17147395}, {12055, 17147651},
1352
  {12056, 17147907}, {12057, 17148163}, {12058, 17148419}, {12059, 17148675},
1353
  {12060, 17148931}, {12061, 17149187}, {12062, 17149443}, {12063, 17149699},
1354
  {12064, 17149955}, {12065, 17150211}, {12066, 17150467}, {12067, 17150723},
1355
  {12068, 17150979}, {12069, 17151235}, {12070, 17151491}, {12071, 17151747},
1356
  {12072, 17152003}, {12073, 17152259}, {12074, 17152515}, {12075, 17152771},
1357
  {12076, 17153027}, {12077, 17153283}, {12078, 17153539}, {12079, 17153795},
1358
  {12080, 17154051}, {12081, 17154307}, {12082, 17154563}, {12083, 17154819},
1359
  {12084, 17155075}, {12085, 17155331}, {12086, 17155587}, {12087, 17155843},
1360
  {12088, 17156099}, {12089, 17156355}, {12090, 17156611}, {12091, 17156867},
1361
  {12092, 17157123}, {12093, 17157379}, {12094, 17157635}, {12095, 17157891},
1362
  {12096, 17158147}, {12097, 17158403}, {12098, 17158659}, {12099, 17158915},
1363
  {12100, 17159171}, {12101, 17159427}, {12102, 17159683}, {12103, 17159939},
1364
  {12104, 17160195}, {12105, 17160451}, {12106, 17160707}, {12107, 17160963},
1365
  {12108, 17161219}, {12109, 17161475}, {12110, 17161731}, {12111, 17161987},
1366
  {12112, 17162243}, {12113, 17162499}, {12114, 17162755}, {12115, 17163011},
1367
  {12116, 17163267}, {12117, 17163523}, {12118, 17163779}, {12119, 17164035},
1368
  {12120, 17164291}, {12121, 17164547}, {12122, 17164803}, {12123, 17165059},
1369
  {12124, 17165315}, {12125, 17165571}, {12126, 17165827}, {12127, 17166083},
1370
  {12128, 17166339}, {12129, 17166595}, {12130, 17166851}, {12131, 17167107},
1371
  {12132, 17167363}, {12133, 17167619}, {12134, 17167875}, {12135, 17168131},
1372
  {12136, 17168387}, {12137, 17168643}, {12138, 17168899}, {12139, 17169155},
1373
  {12140, 17169411}, {12141, 17169667}, {12142, 17169923}, {12143, 17170179},
1374
  {12144, 17170435}, {12145, 17170691}, {12146, 17170947}, {12147, 17171203},
1375
  {12148, 17171459}, {12149, 17171715}, {12150, 17171971}, {12151, 17172227},
1376
  {12152, 17172483}, {12153, 17172739}, {12154, 17172995}, {12155, 17173251},
1377
  {12156, 17173507}, {12157, 17173763}, {12158, 17174019}, {12159, 17174275},
1378
  {12160, 17174531}, {12161, 17174787}, {12162, 17175043}, {12163, 17175299},
1379
  {12164, 17175555}, {12165, 17175811}, {12166, 17176067}, {12167, 17176323},
1380
  {12168, 17176579}, {12169, 17176835}, {12170, 17177091}, {12171, 17177347},
1381
  {12172, 17177603}, {12173, 17177859}, {12174, 17178115}, {12175, 17178371},
1382
  {12176, 17178627}, {12177, 17178883}, {12178, 17179139}, {12179, 17179395},
1383
  {12180, 17179651}, {12181, 17179907}, {12182, 17180163}, {12183, 17180419},
1384
  {12184, 17180675}, {12185, 17180931}, {12186, 17181187}, {12187, 17181443},
1385
  {12188, 17181699}, {12189, 17181955}, {12190, 17182211}, {12191, 17182467},
1386
  {12192, 17182723}, {12193, 17182979}, {12194, 17183235}, {12195, 17183491},
1387
  {12196, 17183747}, {12197, 17184003}, {12198, 17184259}, {12199, 17184515},
1388
  {12200, 17184771}, {12201, 17185027}, {12202, 17185283}, {12203, 17185539},
1389
  {12204, 17185795}, {12205, 17186051}, {12206, 17186307}, {12207, 17186563},
1390
  {12208, 17186819}, {12209, 17187075}, {12210, 17187331}, {12211, 17187587},
1391
  {12212, 17187843}, {12213, 17188099}, {12214, 17188355}, {12215, 17188611},
1392
  {12216, 17188867}, {12217, 17189123}, {12218, 17189379}, {12219, 17189635},
1393
  {12220, 17189891}, {12221, 17190147}, {12222, 17190403}, {12223, 17190659},
1394
  {12224, 17190915}, {12225, 17191171}, {12226, 17191427}, {12227, 17191683},
1395
  {12228, 17191939}, {12229, 17192195}, {12230, 17192451}, {12231, 17192707},
1396
  {12232, 17192963}, {12233, 17193219}, {12234, 17193475}, {12235, 17193731},
1397
  {12236, 17193987}, {12237, 17194243}, {12238, 17194499}, {12239, 17194755},
1398
  {12240, 17195011}, {12241, 17195267}, {12242, 17195523}, {12243, 17195779},
1399
  {12244, 17196035}, {12245, 17196291}, {12246, 2}, {12288, 16783875},
1400
  {12289, 1}, {12290, 17196547}, {12291, 1}, {12342, 17196803},
1401
  {12343, 1}, {12344, 17147651}, {12345, 17197059}, {12346, 17197315},
1402
  {12347, 1}, {12352, 2}, {12353, 1}, {12439, 2},
1403
  {12441, 1}, {12443, 33974787}, {12444, 33975299}, {12445, 1},
1404
  {12447, 33975811}, {12448, 1}, {12543, 33976323}, {12544, 2},
1405
  {12549, 1}, {12592, 2}, {12593, 17199619}, {12594, 17199875},
1406
  {12595, 17200131}, {12596, 17200387}, {12597, 17200643}, {12598, 17200899},
1407
  {12599, 17201155}, {12600, 17201411}, {12601, 17201667}, {12602, 17201923},
1408
  {12603, 17202179}, {12604, 17202435}, {12605, 17202691}, {12606, 17202947},
1409
  {12607, 17203203}, {12608, 17203459}, {12609, 17203715}, {12610, 17203971},
1410
  {12611, 17204227}, {12612, 17204483}, {12613, 17204739}, {12614, 17204995},
1411
  {12615, 17205251}, {12616, 17205507}, {12617, 17205763}, {12618, 17206019},
1412
  {12619, 17206275}, {12620, 17206531}, {12621, 17206787}, {12622, 17207043},
1413
  {12623, 17207299}, {12624, 17207555}, {12625, 17207811}, {12626, 17208067},
1414
  {12627, 17208323}, {12628, 17208579}, {12629, 17208835}, {12630, 17209091},
1415
  {12631, 17209347}, {12632, 17209603}, {12633, 17209859}, {12634, 17210115},
1416
  {12635, 17210371}, {12636, 17210627}, {12637, 17210883}, {12638, 17211139},
1417
  {12639, 17211395}, {12640, 17211651}, {12641, 17211907}, {12642, 17212163},
1418
  {12643, 17212419}, {12644, 2}, {12645, 17212675}, {12646, 17212931},
1419
  {12647, 17213187}, {12648, 17213443}, {12649, 17213699}, {12650, 17213955},
1420
  {12651, 17214211}, {12652, 17214467}, {12653, 17214723}, {12654, 17214979},
1421
  {12655, 17215235}, {12656, 17215491}, {12657, 17215747}, {12658, 17216003},
1422
  {12659, 17216259}, {12660, 17216515}, {12661, 17216771}, {12662, 17217027},
1423
  {12663, 17217283}, {12664, 17217539}, {12665, 17217795}, {12666, 17218051},
1424
  {12667, 17218307}, {12668, 17218563}, {12669, 17218819}, {12670, 17219075},
1425
  {12671, 17219331}, {12672, 17219587}, {12673, 17219843}, {12674, 17220099},
1426
  {12675, 17220355}, {12676, 17220611}, {12677, 17220867}, {12678, 17221123},
1427
  {12679, 17221379}, {12680, 17221635}, {12681, 17221891}, {12682, 17222147},
1428
  {12683, 17222403}, {12684, 17222659}, {12685, 17222915}, {12686, 17223171},
1429
  {12687, 2}, {12688, 1}, {12690, 17141763}, {12691, 17143299},
1430
  {12692, 17223427}, {12693, 17223683}, {12694, 17223939}, {12695, 17224195},
1431
  {12696, 17224451}, {12697, 17224707}, {12698, 17142787}, {12699, 17224963},
1432
  {12700, 17225219}, {12701, 17225475}, {12702, 17225731}, {12703, 17143811},
1433
  {12704, 1}, {12772, 2}, {12784, 1}, {12800, 50780419},
1434
  {12801, 50781187}, {12802, 50781955}, {12803, 50782723}, {12804, 50783491},
1435
  {12805, 50784259}, {12806, 50785027}, {12807, 50785795}, {12808, 50786563},
1436
  {12809, 50787331}, {12810, 50788099}, {12811, 50788867}, {12812, 50789635},
1437
  {12813, 50790403}, {12814, 50791171}, {12815, 50791939}, {12816, 50792707},
1438
  {12817, 50793475}, {12818, 50794243}, {12819, 50795011}, {12820, 50795779},
1439
  {12821, 50796547}, {12822, 50797315}, {12823, 50798083}, {12824, 50798851},
1440
  {12825, 50799619}, {12826, 50800387}, {12827, 50801155}, {12828, 50801923},
1441
  {12829, 67579907}, {12830, 67580931}, {12831, 2}, {12832, 50804739},
1442
  {12833, 50805507}, {12834, 50806275}, {12835, 50807043}, {12836, 50807811},
1443
  {12837, 50808579}, {12838, 50809347}, {12839, 50810115}, {12840, 50810883},
1444
  {12841, 50811651}, {12842, 50812419}, {12843, 50813187}, {12844, 50813955},
1445
  {12845, 50814723}, {12846, 50815491}, {12847, 50816259}, {12848, 50817027},
1446
  {12849, 50817795}, {12850, 50818563}, {12851, 50819331}, {12852, 50820099},
1447
  {12853, 50820867}, {12854, 50821635}, {12855, 50822403}, {12856, 50823171},
1448
  {12857, 50823939}, {12858, 50824707}, {12859, 50825475}, {12860, 50826243},
1449
  {12861, 50827011}, {12862, 50827779}, {12863, 50828547}, {12864, 50829315},
1450
  {12865, 50830083}, {12866, 50830851}, {12867, 50831619}, {12868, 17277955},
1451
  {12869, 17278211}, {12870, 17158659}, {12871, 17278467}, {12872, 1},
1452
  {12880, 50833155}, {12881, 33845251}, {12882, 34056707}, {12883, 33562371},
1453
  {12884, 34057219}, {12885, 34057731}, {12886, 34058243}, {12887, 34058755},
1454
  {12888, 34059267}, {12889, 34059779}, {12890, 34060291}, {12891, 33827331},
1455
  {12892, 33826563}, {12893, 34060803}, {12894, 34061315}, {12895, 34061827},
1456
  {12896, 17199619}, {12897, 17200387}, {12898, 17201155}, {12899, 17201667},
1457
  {12900, 17203715}, {12901, 17203971}, {12902, 17204739}, {12903, 17205251},
1458
  {12904, 17205507}, {12905, 17206019}, {12906, 17206275}, {12907, 17206531},
1459
  {12908, 17206787}, {12909, 17207043}, {12910, 17236995}, {12911, 17237763},
1460
  {12912, 17238531}, {12913, 17239299}, {12914, 17240067}, {12915, 17240835},
1461
  {12916, 17241603}, {12917, 17242371}, {12918, 17243139}, {12919, 17243907},
1462
  {12920, 17244675}, {12921, 17245443}, {12922, 17246211}, {12923, 17246979},
1463
  {12924, 34062339}, {12925, 34062851}, {12926, 17286147}, {12927, 1},
1464
  {12928, 17141763}, {12929, 17143299}, {12930, 17223427}, {12931, 17223683},
1465
  {12932, 17253635}, {12933, 17254403}, {12934, 17255171}, {12935, 17144579},
1466
  {12936, 17256707}, {12937, 17147651}, {12938, 17160451}, {12939, 17163523},
1467
  {12940, 17163267}, {12941, 17160707}, {12942, 17184259}, {12943, 17149699},
1468
  {12944, 17159939}, {12945, 17263619}, {12946, 17264387}, {12947, 17265155},
1469
  {12948, 17265923}, {12949, 17266691}, {12950, 17267459}, {12951, 17268227},
1470
  {12952, 17268995}, {12953, 17286403}, {12954, 17286659}, {12955, 17151235},
1471
  {12956, 17286915}, {12957, 17287171}, {12958, 17287427}, {12959, 17287683},
1472
  {12960, 17287939}, {12961, 17275907}, {12962, 17288195}, {12963, 17288451},
1473
  {12964, 17223939}, {12965, 17224195}, {12966, 17224451}, {12967, 17288707},
1474
  {12968, 17288963}, {12969, 17289219}, {12970, 17289475}, {12971, 17271299},
1475
  {12972, 17272067}, {12973, 17272835}, {12974, 17273603}, {12975, 17274371},
1476
  {12976, 17289731}, {12977, 34067203}, {12978, 34067715}, {12979, 34068227},
1477
  {12980, 34068739}, {12981, 34069251}, {12982, 33564931}, {12983, 34057475},
1478
  {12984, 34061571}, {12985, 34069763}, {12986, 34070275}, {12987, 34070787},
1479
  {12988, 34071299}, {12989, 34071811}, {12990, 34072323}, {12991, 34072835},
1480
  {12992, 34073347}, {12993, 34073859}, {12994, 34074371}, {12995, 34074883},
1481
  {12996, 34075395}, {12997, 34075907}, {12998, 34076419}, {12999, 34076931},
1482
  {13000, 34077443}, {13001, 50855171}, {13002, 50855939}, {13003, 50856707},
1483
  {13004, 34080259}, {13005, 50857987}, {13006, 34081539}, {13007, 50859267},
1484
  {13008, 17305603}, {13009, 17305859}, {13010, 17306115}, {13011, 17306371},
1485
  {13012, 17306627}, {13013, 17306883}, {13014, 17307139}, {13015, 17307395},
1486
  {13016, 17307651}, {13017, 17199107}, {13018, 17307907}, {13019, 17308163},
1487
  {13020, 17308419}, {13021, 17308675}, {13022, 17308931}, {13023, 17309187},
1488
  {13024, 17309443}, {13025, 17309699}, {13026, 17309955}, {13027, 17199363},
1489
  {13028, 17310211}, {13029, 17310467}, {13030, 17310723}, {13031, 17310979},
1490
  {13032, 17311235}, {13033, 17311491}, {13034, 17311747}, {13035, 17312003},
1491
  {13036, 17312259}, {13037, 17312515}, {13038, 17312771}, {13039, 17313027},
1492
  {13040, 17313283}, {13041, 17313539}, {13042, 17313795}, {13043, 17314051},
1493
  {13044, 17314307}, {13045, 17314563}, {13046, 17314819}, {13047, 17315075},
1494
  {13048, 17315331}, {13049, 17315587}, {13050, 17315843}, {13051, 17316099},
1495
  {13052, 17316355}, {13053, 17316611}, {13054, 17316867}, {13055, 34094339},
1496
  {13056, 67649283}, {13057, 67650307}, {13058, 67651331}, {13059, 50875139},
1497
  {13060, 67653123}, {13061, 50876931}, {13062, 50877699}, {13063, 84432899},
1498
  {13064, 67656963}, {13065, 50880771}, {13066, 50881539}, {13067, 50882307},
1499
  {13068, 67660291}, {13069, 67661315}, {13070, 50885123}, {13071, 50885891},
1500
  {13072, 34109443}, {13073, 50887171}, {13074, 67665155}, {13075, 67666179},
1501
  {13076, 34112771}, {13077, 84444931}, {13078, 101223427}, {13079, 84447747},
1502
  {13080, 50891011}, {13081, 84449027}, {13082, 84450307}, {13083, 67674371},
1503
  {13084, 50898179}, {13085, 50898947}, {13086, 50899715}, {13087, 67677699},
1504
  {13088, 84455939}, {13089, 67680003}, {13090, 50903811}, {13091, 50904579},
1505
  {13092, 50905347}, {13093, 34128899}, {13094, 34129411}, {13095, 34118147},
1506
  {13096, 34129923}, {13097, 50907651}, {13098, 50908419}, {13099, 84463619},
1507
  {13100, 50910467}, {13101, 67688451}, {13102, 84466691}, {13103, 50913539},
1508
  {13104, 34137091}, {13105, 34137603}, {13106, 84469763}, {13107, 67693827},
1509
  {13108, 84472067}, {13109, 50918915}, {13110, 84474115}, {13111, 34143747},
1510
  {13112, 50921475}, {13113, 50922243}, {13114, 50923011}, {13115, 50923779},
1511
  {13116, 50924547}, {13117, 67702531}, {13118, 50926339}, {13119, 34149891},
1512
  {13120, 50927619}, {13121, 50928387}, {13122, 50929155}, {13123, 67707139},
1513
  {13124, 50930947}, {13125, 50931715}, {13126, 50932483}, {13127, 84487683},
1514
  {13128, 67711747}, {13129, 34158339}, {13130, 84490499}, {13131, 34160131},
1515
  {13132, 67715075}, {13133, 67669507}, {13134, 50938883}, {13135, 50939651},
1516
  {13136, 50940419}, {13137, 67718403}, {13138, 34164995}, {13139, 50942723},
1517
  {13140, 67720707}, {13141, 34167299}, {13142, 84499459}, {13143, 50893827},
1518
  {13144, 34169091}, {13145, 34169603}, {13146, 34170115}, {13147, 34170627},
1519
  {13148, 34171139}, {13149, 34171651}, {13150, 34172163}, {13151, 34172675},
1520
  {13152, 34173187}, {13153, 34173699}, {13154, 50951427}, {13155, 50952195},
1521
  {13156, 50952963}, {13157, 50953731}, {13158, 50954499}, {13159, 50955267},
1522
  {13160, 50956035}, {13161, 50956803}, {13162, 50957571}, {13163, 50958339},
1523
  {13164, 50959107}, {13165, 50959875}, {13166, 50960643}, {13167, 50961411},
1524
  {13168, 50962179}, {13169, 50962947}, {13170, 34186499}, {13171, 34187011},
1525
  {13172, 50964739}, {13173, 34188291}, {13174, 34188803}, {13175, 34189315},
1526
  {13176, 50967043}, {13177, 50967811}, {13178, 34191363}, {13179, 34191875},
1527
  {13180, 34192387}, {13181, 34192899}, {13182, 34193411}, {13183, 67748355},
1528
  {13184, 34185987}, {13185, 34194947}, {13186, 34195459}, {13187, 34195971},
1529
  {13188, 34196483}, {13189, 34196995}, {13190, 34197507}, {13191, 34198019},
1530
  {13192, 50975747}, {13193, 67753731}, {13194, 34200323}, {13195, 34200835},
1531
  {13196, 34201347}, {13197, 34201859}, {13198, 34202371}, {13199, 34202883},
1532
  {13200, 34203395}, {13201, 50981123}, {13202, 50981891}, {13203, 50980355},
1533
  {13204, 50982659}, {13205, 34206211}, {13206, 34206723}, {13207, 34207235},
1534
  {13208, 33556995}, {13209, 34207747}, {13210, 34208259}, {13211, 34208771},
1535
  {13212, 34209283}, {13213, 34209795}, {13214, 34210307}, {13215, 50988035},
1536
  {13216, 50988803}, {13217, 34190083}, {13218, 50989571}, {13219, 50990339},
1537
  {13220, 50991107}, {13221, 34190851}, {13222, 50991875}, {13223, 50992643},
1538
  {13224, 67770627}, {13225, 34185987}, {13226, 50994435}, {13227, 50995203},
1539
  {13228, 50995971}, {13229, 50996739}, {13230, 84551939}, {13231, 101330435},
1540
  {13232, 34223107}, {13233, 34223619}, {13234, 34224131}, {13235, 34224643},
1541
  {13236, 34225155}, {13237, 34225667}, {13238, 34226179}, {13239, 34226691},
1542
  {13240, 34227203}, {13241, 34226691}, {13242, 34227715}, {13243, 34228227},
1543
  {13244, 34228739}, {13245, 34229251}, {13246, 34229763}, {13247, 34229251},
1544
  {13248, 34230275}, {13249, 34230787}, {13250, 2}, {13251, 34231299},
1545
  {13252, 33817347}, {13253, 33554947}, {13254, 67786243}, {13255, 2},
1546
  {13256, 34232835}, {13257, 34233347}, {13258, 34233859}, {13259, 34185731},
1547
  {13260, 34234371}, {13261, 34234883}, {13262, 34210307}, {13263, 34235395},
1548
  {13264, 33557251}, {13265, 34235907}, {13266, 51013635}, {13267, 34237187},
1549
  {13268, 34197507}, {13269, 51014915}, {13270, 51015683}, {13271, 34239235},
1550
  {13272, 2}, {13273, 51016963}, {13274, 34240515}, {13275, 34221315},
1551
  {13276, 34241027}, {13277, 34241539}, {13278, 51019267}, {13279, 51020035},
1552
  {13280, 34243587}, {13281, 34244099}, {13282, 34244611}, {13283, 34245123},
1553
  {13284, 34245635}, {13285, 34246147}, {13286, 34246659}, {13287, 34247171},
1554
  {13288, 34247683}, {13289, 51025411}, {13290, 51026179}, {13291, 51026947},
1555
  {13292, 51027715}, {13293, 51028483}, {13294, 51029251}, {13295, 51030019},
1556
  {13296, 51030787}, {13297, 51031555}, {13298, 51032323}, {13299, 51033091},
1557
  {13300, 51033859}, {13301, 51034627}, {13302, 51035395}, {13303, 51036163},
1558
  {13304, 51036931}, {13305, 51037699}, {13306, 51038467}, {13307, 51039235},
1559
  {13308, 51040003}, {13309, 51040771}, {13310, 51041539}, {13311, 51042307},
1560
  {13312, 1}, {42125, 2}, {42128, 1}, {42183, 2},
1561
  {42192, 1}, {42540, 2}, {42560, 17488643}, {42561, 1},
1562
  {42562, 17488899}, {42563, 1}, {42564, 17489155}, {42565, 1},
1563
  {42566, 17489411}, {42567, 1}, {42568, 17489667}, {42569, 1},
1564
  {42570, 16936451}, {42571, 1}, {42572, 17489923}, {42573, 1},
1565
  {42574, 17490179}, {42575, 1}, {42576, 17490435}, {42577, 1},
1566
  {42578, 17490691}, {42579, 1}, {42580, 17490947}, {42581, 1},
1567
  {42582, 17491203}, {42583, 1}, {42584, 17491459}, {42585, 1},
1568
  {42586, 17491715}, {42587, 1}, {42588, 17491971}, {42589, 1},
1569
  {42590, 17492227}, {42591, 1}, {42592, 17492483}, {42593, 1},
1570
  {42594, 17492739}, {42595, 1}, {42596, 17492995}, {42597, 1},
1571
  {42598, 17493251}, {42599, 1}, {42600, 17493507}, {42601, 1},
1572
  {42602, 17493763}, {42603, 1}, {42604, 17494019}, {42605, 1},
1573
  {42624, 17494275}, {42625, 1}, {42626, 17494531}, {42627, 1},
1574
  {42628, 17494787}, {42629, 1}, {42630, 17495043}, {42631, 1},
1575
  {42632, 17495299}, {42633, 1}, {42634, 17495555}, {42635, 1},
1576
  {42636, 17495811}, {42637, 1}, {42638, 17496067}, {42639, 1},
1577
  {42640, 17496323}, {42641, 1}, {42642, 17496579}, {42643, 1},
1578
  {42644, 17496835}, {42645, 1}, {42646, 17497091}, {42647, 1},
1579
  {42648, 17497347}, {42649, 1}, {42650, 17497603}, {42651, 1},
1580
  {42652, 16873219}, {42653, 16873731}, {42654, 1}, {42744, 2},
1581
  {42752, 1}, {42786, 17497859}, {42787, 1}, {42788, 17498115},
1582
  {42789, 1}, {42790, 17498371}, {42791, 1}, {42792, 17498627},
1583
  {42793, 1}, {42794, 17498883}, {42795, 1}, {42796, 17499139},
1584
  {42797, 1}, {42798, 17499395}, {42799, 1}, {42802, 17499651},
1585
  {42803, 1}, {42804, 17499907}, {42805, 1}, {42806, 17500163},
1586
  {42807, 1}, {42808, 17500419}, {42809, 1}, {42810, 17500675},
1587
  {42811, 1}, {42812, 17500931}, {42813, 1}, {42814, 17501187},
1588
  {42815, 1}, {42816, 17501443}, {42817, 1}, {42818, 17501699},
1589
  {42819, 1}, {42820, 17501955}, {42821, 1}, {42822, 17502211},
1590
  {42823, 1}, {42824, 17502467}, {42825, 1}, {42826, 17502723},
1591
  {42827, 1}, {42828, 17502979}, {42829, 1}, {42830, 17503235},
1592
  {42831, 1}, {42832, 17503491}, {42833, 1}, {42834, 17503747},
1593
  {42835, 1}, {42836, 17504003}, {42837, 1}, {42838, 17504259},
1594
  {42839, 1}, {42840, 17504515}, {42841, 1}, {42842, 17504771},
1595
  {42843, 1}, {42844, 17505027}, {42845, 1}, {42846, 17505283},
1596
  {42847, 1}, {42848, 17505539}, {42849, 1}, {42850, 17505795},
1597
  {42851, 1}, {42852, 17506051}, {42853, 1}, {42854, 17506307},
1598
  {42855, 1}, {42856, 17506563}, {42857, 1}, {42858, 17506819},
1599
  {42859, 1}, {42860, 17507075}, {42861, 1}, {42862, 17507331},
1600
  {42863, 1}, {42864, 17507331}, {42865, 1}, {42873, 17507587},
1601
  {42874, 1}, {42875, 17507843}, {42876, 1}, {42877, 17508099},
1602
  {42878, 17508355}, {42879, 1}, {42880, 17508611}, {42881, 1},
1603
  {42882, 17508867}, {42883, 1}, {42884, 17509123}, {42885, 1},
1604
  {42886, 17509379}, {42887, 1}, {42891, 17509635}, {42892, 1},
1605
  {42893, 16951299}, {42894, 1}, {42896, 17509891}, {42897, 1},
1606
  {42898, 17510147}, {42899, 1}, {42902, 17510403}, {42903, 1},
1607
  {42904, 17510659}, {42905, 1}, {42906, 17510915}, {42907, 1},
1608
  {42908, 17511171}, {42909, 1}, {42910, 17511427}, {42911, 1},
1609
  {42912, 17511683}, {42913, 1}, {42914, 17511939}, {42915, 1},
1610
  {42916, 17512195}, {42917, 1}, {42918, 17512451}, {42919, 1},
1611
  {42920, 17512707}, {42921, 1}, {42922, 16841475}, {42923, 16948995},
1612
  {42924, 16951043}, {42925, 17512963}, {42926, 16951555}, {42927, 1},
1613
  {42928, 17513219}, {42929, 17513475}, {42930, 16952067}, {42931, 17513731},
1614
  {42932, 17513987}, {42933, 1}, {42934, 17514243}, {42935, 1},
1615
  {42936, 17514499}, {42937, 1}, {42938, 17514755}, {42939, 1},
1616
  {42940, 17515011}, {42941, 1}, {42942, 17515267}, {42943, 1},
1617
  {42944, 17515523}, {42945, 1}, {42946, 17515779}, {42947, 1},
1618
  {42948, 17516035}, {42949, 16954371}, {42950, 17516291}, {42951, 17516547},
1619
  {42952, 1}, {42953, 17516803}, {42954, 1}, {42955, 2},
1620
  {42960, 17517059}, {42961, 1}, {42962, 2}, {42963, 1},
1621
  {42964, 2}, {42965, 1}, {42966, 17517315}, {42967, 1},
1622
  {42968, 17517571}, {42969, 1}, {42970, 2}, {42994, 16777731},
1623
  {42995, 16778499}, {42996, 16781315}, {42997, 17517827}, {42998, 1},
1624
  {43000, 16802051}, {43001, 16808195}, {43002, 1}, {43053, 2},
1625
  {43056, 1}, {43066, 2}, {43072, 1}, {43128, 2},
1626
  {43136, 1}, {43206, 2}, {43214, 1}, {43226, 2},
1627
  {43232, 1}, {43348, 2}, {43359, 1}, {43389, 2},
1628
  {43392, 1}, {43470, 2}, {43471, 1}, {43482, 2},
1629
  {43486, 1}, {43519, 2}, {43520, 1}, {43575, 2},
1630
  {43584, 1}, {43598, 2}, {43600, 1}, {43610, 2},
1631
  {43612, 1}, {43715, 2}, {43739, 1}, {43767, 2},
1632
  {43777, 1}, {43783, 2}, {43785, 1}, {43791, 2},
1633
  {43793, 1}, {43799, 2}, {43808, 1}, {43815, 2},
1634
  {43816, 1}, {43823, 2}, {43824, 1}, {43868, 17498371},
1635
  {43869, 17518083}, {43870, 17124867}, {43871, 17518339}, {43872, 1},
1636
  {43881, 17518595}, {43882, 1}, {43884, 2}, {43888, 17518851},
1637
  {43889, 17519107}, {43890, 17519363}, {43891, 17519619}, {43892, 17519875},
1638
  {43893, 17520131}, {43894, 17520387}, {43895, 17520643}, {43896, 17520899},
1639
  {43897, 17521155}, {43898, 17521411}, {43899, 17521667}, {43900, 17521923},
1640
  {43901, 17522179}, {43902, 17522435}, {43903, 17522691}, {43904, 17522947},
1641
  {43905, 17523203}, {43906, 17523459}, {43907, 17523715}, {43908, 17523971},
1642
  {43909, 17524227}, {43910, 17524483}, {43911, 17524739}, {43912, 17524995},
1643
  {43913, 17525251}, {43914, 17525507}, {43915, 17525763}, {43916, 17526019},
1644
  {43917, 17526275}, {43918, 17526531}, {43919, 17526787}, {43920, 17527043},
1645
  {43921, 17527299}, {43922, 17527555}, {43923, 17527811}, {43924, 17528067},
1646
  {43925, 17528323}, {43926, 17528579}, {43927, 17528835}, {43928, 17529091},
1647
  {43929, 17529347}, {43930, 17529603}, {43931, 17529859}, {43932, 17530115},
1648
  {43933, 17530371}, {43934, 17530627}, {43935, 17530883}, {43936, 17531139},
1649
  {43937, 17531395}, {43938, 17531651}, {43939, 17531907}, {43940, 17532163},
1650
  {43941, 17532419}, {43942, 17532675}, {43943, 17532931}, {43944, 17533187},
1651
  {43945, 17533443}, {43946, 17533699}, {43947, 17533955}, {43948, 17534211},
1652
  {43949, 17534467}, {43950, 17534723}, {43951, 17534979}, {43952, 17535235},
1653
  {43953, 17535491}, {43954, 17535747}, {43955, 17536003}, {43956, 17536259},
1654
  {43957, 17536515}, {43958, 17536771}, {43959, 17537027}, {43960, 17537283},
1655
  {43961, 17537539}, {43962, 17537795}, {43963, 17538051}, {43964, 17538307},
1656
  {43965, 17538563}, {43966, 17538819}, {43967, 17539075}, {43968, 1},
1657
  {44014, 2}, {44016, 1}, {44026, 2}, {44032, 1},
1658
  {55204, 2}, {55216, 1}, {55239, 2}, {55243, 1},
1659
  {55292, 2}, {63744, 17539331}, {63745, 17539587}, {63746, 17182211},
1660
  {63747, 17539843}, {63748, 17540099}, {63749, 17540355}, {63750, 17540611},
1661
  {63751, 17196035}, {63753, 17540867}, {63754, 17184259}, {63755, 17541123},
1662
  {63756, 17541379}, {63757, 17541635}, {63758, 17541891}, {63759, 17542147},
1663
  {63760, 17542403}, {63761, 17542659}, {63762, 17542915}, {63763, 17543171},
1664
  {63764, 17543427}, {63765, 17543683}, {63766, 17543939}, {63767, 17544195},
1665
  {63768, 17544451}, {63769, 17544707}, {63770, 17544963}, {63771, 17545219},
1666
  {63772, 17545475}, {63773, 17545731}, {63774, 17545987}, {63775, 17546243},
1667
  {63776, 17546499}, {63777, 17546755}, {63778, 17547011}, {63779, 17547267},
1668
  {63780, 17547523}, {63781, 17547779}, {63782, 17548035}, {63783, 17548291},
1669
  {63784, 17548547}, {63785, 17548803}, {63786, 17549059}, {63787, 17549315},
1670
  {63788, 17549571}, {63789, 17549827}, {63790, 17550083}, {63791, 17550339},
1671
  {63792, 17550595}, {63793, 17550851}, {63794, 17551107}, {63795, 17551363},
1672
  {63796, 17173507}, {63797, 17551619}, {63798, 17551875}, {63799, 17552131},
1673
  {63800, 17552387}, {63801, 17552643}, {63802, 17552899}, {63803, 17553155},
1674
  {63804, 17553411}, {63805, 17553667}, {63806, 17553923}, {63807, 17554179},
1675
  {63808, 17192195}, {63809, 17554435}, {63810, 17554691}, {63811, 17554947},
1676
  {63812, 17555203}, {63813, 17555459}, {63814, 17555715}, {63815, 17555971},
1677
  {63816, 17556227}, {63817, 17556483}, {63818, 17556739}, {63819, 17556995},
1678
  {63820, 17557251}, {63821, 17557507}, {63822, 17557763}, {63823, 17558019},
1679
  {63824, 17558275}, {63825, 17558531}, {63826, 17558787}, {63827, 17559043},
1680
  {63828, 17559299}, {63829, 17559555}, {63830, 17559811}, {63831, 17560067},
1681
  {63832, 17560323}, {63833, 17560579}, {63834, 17560835}, {63835, 17561091},
1682
  {63836, 17543427}, {63837, 17561347}, {63838, 17561603}, {63839, 17561859},
1683
  {63840, 17562115}, {63841, 17562371}, {63842, 17562627}, {63843, 17562883},
1684
  {63844, 17563139}, {63845, 17563395}, {63846, 17563651}, {63847, 17563907},
1685
  {63848, 17564163}, {63849, 17564419}, {63850, 17564675}, {63851, 17564931},
1686
  {63852, 17565187}, {63853, 17565443}, {63854, 17565699}, {63855, 17565955},
1687
  {63856, 17566211}, {63857, 17182723}, {63858, 17566467}, {63859, 17566723},
1688
  {63860, 17566979}, {63861, 17567235}, {63862, 17567491}, {63863, 17567747},
1689
  {63864, 17568003}, {63865, 17568259}, {63866, 17568515}, {63867, 17568771},
1690
  {63868, 17569027}, {63869, 17569283}, {63870, 17569539}, {63871, 17569795},
1691
  {63872, 17570051}, {63873, 17151235}, {63874, 17570307}, {63875, 17570563},
1692
  {63876, 17570819}, {63877, 17571075}, {63878, 17571331}, {63879, 17571587},
1693
  {63880, 17571843}, {63881, 17572099}, {63882, 17146371}, {63883, 17572355},
1694
  {63884, 17572611}, {63885, 17572867}, {63886, 17573123}, {63887, 17573379},
1695
  {63888, 17573635}, {63889, 17573891}, {63890, 17574147}, {63891, 17574403},
1696
  {63892, 17574659}, {63893, 17574915}, {63894, 17575171}, {63895, 17575427},
1697
  {63896, 17575683}, {63897, 17575939}, {63898, 17576195}, {63899, 17576451},
1698
  {63900, 17576707}, {63901, 17576963}, {63902, 17577219}, {63903, 17577475},
1699
  {63904, 17577731}, {63905, 17565955}, {63906, 17577987}, {63907, 17578243},
1700
  {63908, 17578499}, {63909, 17578755}, {63910, 17579011}, {63911, 17579267},
1701
  {63912, 17317123}, {63913, 17579523}, {63914, 17561859}, {63915, 17579779},
1702
  {63916, 17580035}, {63917, 17580291}, {63918, 17580547}, {63919, 17580803},
1703
  {63920, 17581059}, {63921, 17581315}, {63922, 17581571}, {63923, 17581827},
1704
  {63924, 17582083}, {63925, 17582339}, {63926, 17582595}, {63927, 17582851},
1705
  {63928, 17583107}, {63929, 17583363}, {63930, 17583619}, {63931, 17583875},
1706
  {63932, 17584131}, {63933, 17584387}, {63934, 17584643}, {63935, 17543427},
1707
  {63936, 17584899}, {63937, 17585155}, {63938, 17585411}, {63939, 17585667},
1708
  {63940, 17195779}, {63941, 17585923}, {63942, 17586179}, {63943, 17586435},
1709
  {63944, 17586691}, {63945, 17586947}, {63946, 17587203}, {63947, 17587459},
1710
  {63948, 17587715}, {63949, 17587971}, {63950, 17588227}, {63951, 17588483},
1711
  {63952, 17588739}, {63953, 17254403}, {63954, 17588995}, {63955, 17589251},
1712
  {63956, 17589507}, {63957, 17589763}, {63958, 17590019}, {63959, 17590275},
1713
  {63960, 17590531}, {63961, 17590787}, {63962, 17591043}, {63963, 17562371},
1714
  {63964, 17591299}, {63965, 17591555}, {63966, 17591811}, {63967, 17592067},
1715
  {63968, 17592323}, {63969, 17592579}, {63970, 17592835}, {63971, 17593091},
1716
  {63972, 17593347}, {63973, 17593603}, {63974, 17593859}, {63975, 17594115},
1717
  {63976, 17594371}, {63977, 17184003}, {63978, 17594627}, {63979, 17594883},
1718
  {63980, 17595139}, {63981, 17595395}, {63982, 17595651}, {63983, 17595907},
1719
  {63984, 17596163}, {63985, 17596419}, {63986, 17596675}, {63987, 17596931},
1720
  {63988, 17597187}, {63989, 17597443}, {63990, 17597699}, {63991, 17171459},
1721
  {63992, 17597955}, {63993, 17598211}, {63994, 17598467}, {63995, 17598723},
1722
  {63996, 17598979}, {63997, 17599235}, {63998, 17599491}, {63999, 17599747},
1723
  {64000, 17600003}, {64001, 17600259}, {64002, 17600515}, {64003, 17600771},
1724
  {64004, 17601027}, {64005, 17601283}, {64006, 17601539}, {64007, 17601795},
1725
  {64008, 17178371}, {64009, 17602051}, {64010, 17179139}, {64011, 17602307},
1726
  {64012, 17602563}, {64013, 17602819}, {64014, 1}, {64016, 17603075},
1727
  {64017, 1}, {64018, 17603331}, {64019, 1}, {64021, 17603587},
1728
  {64022, 17603843}, {64023, 17604099}, {64024, 17604355}, {64025, 17604611},
1729
  {64026, 17604867}, {64027, 17605123}, {64028, 17605379}, {64029, 17605635},
1730
  {64030, 17173251}, {64031, 1}, {64032, 17605891}, {64033, 1},
1731
  {64034, 17606147}, {64035, 1}, {64037, 17606403}, {64038, 17606659},
1732
  {64039, 1}, {64042, 17606915}, {64043, 17607171}, {64044, 17607427},
1733
  {64045, 17607683}, {64046, 17607939}, {64047, 17608195}, {64048, 17608451},
1734
  {64049, 17608707}, {64050, 17608963}, {64051, 17609219}, {64052, 17609475},
1735
  {64053, 17609731}, {64054, 17609987}, {64055, 17610243}, {64056, 17610499},
1736
  {64057, 17610755}, {64058, 17611011}, {64059, 17611267}, {64060, 17153027},
1737
  {64061, 17611523}, {64062, 17611779}, {64063, 17612035}, {64064, 17612291},
1738
  {64065, 17612547}, {64066, 17612803}, {64067, 17613059}, {64068, 17613315},
1739
  {64069, 17613571}, {64070, 17613827}, {64071, 17614083}, {64072, 17614339},
1740
  {64073, 17614595}, {64074, 17614851}, {64075, 17615107}, {64076, 17265155},
1741
  {64077, 17615363}, {64078, 17615619}, {64079, 17615875}, {64080, 17616131},
1742
  {64081, 17268227}, {64082, 17616387}, {64083, 17616643}, {64084, 17616899},
1743
  {64085, 17617155}, {64086, 17617411}, {64087, 17575171}, {64088, 17617667},
1744
  {64089, 17617923}, {64090, 17618179}, {64091, 17618435}, {64092, 17618691},
1745
  {64093, 17618947}, {64095, 17619203}, {64096, 17619459}, {64097, 17619715},
1746
  {64098, 17619971}, {64099, 17620227}, {64100, 17620483}, {64101, 17620739},
1747
  {64102, 17620995}, {64103, 17606403}, {64104, 17621251}, {64105, 17621507},
1748
  {64106, 17621763}, {64107, 17622019}, {64108, 17622275}, {64109, 17622531},
1749
  {64110, 2}, {64112, 17622787}, {64113, 17623043}, {64114, 17623299},
1750
  {64115, 17623555}, {64116, 17623811}, {64117, 17624067}, {64118, 17624323},
1751
  {64119, 17624579}, {64120, 17609987}, {64121, 17624835}, {64122, 17625091},
1752
  {64123, 17625347}, {64124, 17603075}, {64125, 17625603}, {64126, 17625859},
1753
  {64127, 17626115}, {64128, 17626371}, {64129, 17626627}, {64130, 17626883},
1754
  {64131, 17627139}, {64132, 17627395}, {64133, 17627651}, {64134, 17627907},
1755
  {64135, 17628163}, {64136, 17628419}, {64137, 17612035}, {64138, 17628675},
1756
  {64139, 17612291}, {64140, 17628931}, {64141, 17629187}, {64142, 17629443},
1757
  {64143, 17629699}, {64144, 17629955}, {64145, 17603331}, {64146, 17548803},
1758
  {64147, 17630211}, {64148, 17630467}, {64149, 17161475}, {64150, 17566211},
1759
  {64151, 17587203}, {64152, 17630723}, {64153, 17630979}, {64154, 17614083},
1760
  {64155, 17631235}, {64156, 17614339}, {64157, 17631491}, {64158, 17631747},
1761
  {64159, 17632003}, {64160, 17603843}, {64161, 17632259}, {64162, 17632515},
1762
  {64163, 17632771}, {64164, 17633027}, {64165, 17633283}, {64166, 17604099},
1763
  {64167, 17633539}, {64168, 17633795}, {64169, 17634051}, {64170, 17634307},
1764
  {64171, 17634563}, {64172, 17634819}, {64173, 17617411}, {64174, 17635075},
1765
  {64175, 17635331}, {64176, 17575171}, {64177, 17635587}, {64178, 17618435},
1766
  {64179, 17635843}, {64180, 17636099}, {64181, 17636355}, {64182, 17636611},
1767
  {64183, 17636867}, {64184, 17619715}, {64185, 17637123}, {64186, 17606147},
1768
  {64187, 17637379}, {64188, 17619971}, {64189, 17561347}, {64190, 17637635},
1769
  {64191, 17620227}, {64192, 17637891}, {64193, 17620739}, {64194, 17638147},
1770
  {64195, 17638403}, {64196, 17638659}, {64197, 17638915}, {64198, 17639171},
1771
  {64199, 17621251}, {64200, 17605379}, {64201, 17639427}, {64202, 17621507},
1772
  {64203, 17639683}, {64204, 17621763}, {64205, 17639939}, {64206, 17196035},
1773
  {64207, 17640195}, {64208, 17640451}, {64209, 17640707}, {64210, 17640963},
1774
  {64211, 17641219}, {64212, 17641475}, {64213, 17641731}, {64214, 17641987},
1775
  {64215, 17642243}, {64216, 17642499}, {64217, 17642755}, {64218, 2},
1776
  {64256, 34420227}, {64257, 34420739}, {64258, 34421251}, {64259, 51197699},
1777
  {64260, 51198979}, {64261, 33559043}, {64263, 2}, {64275, 34422531},
1778
  {64276, 34423043}, {64277, 34423555}, {64278, 34424067}, {64279, 34424579},
1779
  {64280, 2}, {64285, 34425091}, {64286, 1}, {64287, 34425603},
1780
  {64288, 17648899}, {64289, 17044227}, {64290, 17044995}, {64291, 17649155},
1781
  {64292, 17649411}, {64293, 17649667}, {64294, 17649923}, {64295, 17650179},
1782
  {64296, 17650435}, {64297, 17037059}, {64298, 34427907}, {64299, 34428419},
1783
  {64300, 51206147}, {64301, 51206915}, {64302, 34430467}, {64303, 34430979},
1784
  {64304, 34431491}, {64305, 34432003}, {64306, 34432515}, {64307, 34433027},
1785
  {64308, 34433539}, {64309, 34434051}, {64310, 34434563}, {64311, 2},
1786
  {64312, 34435075}, {64313, 34435587}, {64314, 34436099}, {64315, 34436611},
1787
  {64316, 34437123}, {64317, 2}, {64318, 34437635}, {64319, 2},
1788
  {64320, 34438147}, {64321, 34438659}, {64322, 2}, {64323, 34439171},
1789
  {64324, 34439683}, {64325, 2}, {64326, 34440195}, {64327, 34440707},
1790
  {64328, 34441219}, {64329, 34428931}, {64330, 34441731}, {64331, 34442243},
1791
  {64332, 34442755}, {64333, 34443267}, {64334, 34443779}, {64335, 34444291},
1792
  {64336, 17667587}, {64338, 17667843}, {64342, 17668099}, {64346, 17668355},
1793
  {64350, 17668611}, {64354, 17668867}, {64358, 17669123}, {64362, 17669379},
1794
  {64366, 17669635}, {64370, 17669891}, {64374, 17670147}, {64378, 17670403},
1795
  {64382, 17670659}, {64386, 17670915}, {64388, 17671171}, {64390, 17671427},
1796
  {64392, 17671683}, {64394, 17671939}, {64396, 17672195}, {64398, 17672451},
1797
  {64402, 17672707}, {64406, 17672963}, {64410, 17673219}, {64414, 17673475},
1798
  {64416, 17673731}, {64420, 17673987}, {64422, 17674243}, {64426, 17674499},
1799
  {64430, 17674755}, {64432, 17675011}, {64434, 1}, {64451, 2},
1800
  {64467, 17675267}, {64471, 16911363}, {64473, 17675523}, {64475, 17675779},
1801
  {64477, 33688579}, {64478, 17676035}, {64480, 17676291}, {64482, 17676547},
1802
  {64484, 17676803}, {64488, 17677059}, {64490, 34454531}, {64492, 34455043},
1803
  {64494, 34455555}, {64496, 34456067}, {64498, 34456579}, {64500, 34457091},
1804
  {64502, 34457603}, {64505, 34458115}, {64508, 17681411}, {64512, 34458883},
1805
  {64513, 34459395}, {64514, 34459907}, {64515, 34458115}, {64516, 34460419},
1806
  {64517, 34460931}, {64518, 34461443}, {64519, 34461955}, {64520, 34462467},
1807
  {64521, 34462979}, {64522, 34463491}, {64523, 34464003}, {64524, 34464515},
1808
  {64525, 34465027}, {64526, 34465539}, {64527, 34466051}, {64528, 34466563},
1809
  {64529, 34467075}, {64530, 34467587}, {64531, 34468099}, {64532, 34468611},
1810
  {64533, 34469123}, {64534, 34469635}, {64535, 34469379}, {64536, 34470147},
1811
  {64537, 34470659}, {64538, 34471171}, {64539, 34471683}, {64540, 34472195},
1812
  {64541, 34472707}, {64542, 34473219}, {64543, 34473731}, {64544, 34474243},
1813
  {64545, 34474755}, {64546, 34475267}, {64547, 34475779}, {64548, 34476291},
1814
  {64549, 34476803}, {64550, 34477315}, {64551, 34477827}, {64552, 34478339},
1815
  {64553, 34478851}, {64554, 34479363}, {64555, 34479875}, {64556, 34480387},
1816
  {64557, 34480899}, {64558, 34481411}, {64559, 34481923}, {64560, 34482435},
1817
  {64561, 34482947}, {64562, 34483459}, {64563, 34483971}, {64564, 34484483},
1818
  {64565, 34484995}, {64566, 34485507}, {64567, 34486019}, {64568, 34486531},
1819
  {64569, 34487043}, {64570, 34487555}, {64571, 34488067}, {64572, 34488579},
1820
  {64573, 34489091}, {64574, 34489603}, {64575, 34490115}, {64576, 34490627},
1821
  {64577, 34491139}, {64578, 34491651}, {64579, 34492163}, {64580, 34492675},
1822
  {64581, 34493187}, {64582, 34469891}, {64583, 34470403}, {64584, 34493699},
1823
  {64585, 34494211}, {64586, 34494723}, {64587, 34495235}, {64588, 34495747},
1824
  {64589, 34496259}, {64590, 34496771}, {64591, 34497283}, {64592, 34497795},
1825
  {64593, 34498307}, {64594, 34498819}, {64595, 34499331}, {64596, 34499843},
1826
  {64597, 34468867}, {64598, 34500355}, {64599, 34500867}, {64600, 34492931},
1827
  {64601, 34501379}, {64602, 34500099}, {64603, 34501891}, {64604, 34502403},
1828
  {64605, 34502915}, {64606, 51280643}, {64607, 51281411}, {64608, 51282179},
1829
  {64609, 51282947}, {64610, 51283715}, {64611, 51284483}, {64612, 34508035},
1830
  {64613, 34508547}, {64614, 34459907}, {64615, 34509059}, {64616, 34458115},
1831
  {64617, 34460419}, {64618, 34509571}, {64619, 34510083}, {64620, 34462467},
1832
  {64621, 34510595}, {64622, 34462979}, {64623, 34463491}, {64624, 34511107},
1833
  {64625, 34511619}, {64626, 34465539}, {64627, 34512131}, {64628, 34466051},
1834
  {64629, 34466563}, {64630, 34512643}, {64631, 34513155}, {64632, 34467587},
1835
  {64633, 34513667}, {64634, 34468099}, {64635, 34468611}, {64636, 34482947},
1836
  {64637, 34483459}, {64638, 34484995}, {64639, 34485507}, {64640, 34486019},
1837
  {64641, 34488067}, {64642, 34488579}, {64643, 34489091}, {64644, 34489603},
1838
  {64645, 34491651}, {64646, 34492163}, {64647, 34492675}, {64648, 34514179},
1839
  {64649, 34493699}, {64650, 34514691}, {64651, 34515203}, {64652, 34496771},
1840
  {64653, 34515715}, {64654, 34497283}, {64655, 34497795}, {64656, 34502915},
1841
  {64657, 34516227}, {64658, 34516739}, {64659, 34492931}, {64660, 34494979},
1842
  {64661, 34501379}, {64662, 34500099}, {64663, 34458883}, {64664, 34459395},
1843
  {64665, 34517251}, {64666, 34459907}, {64667, 34517763}, {64668, 34460931},
1844
  {64669, 34461443}, {64670, 34461955}, {64671, 34462467}, {64672, 34518275},
1845
  {64673, 34464003}, {64674, 34464515}, {64675, 34465027}, {64676, 34465539},
1846
  {64677, 34518787}, {64678, 34467587}, {64679, 34469123}, {64680, 34469635},
1847
  {64681, 34469379}, {64682, 34470147}, {64683, 34470659}, {64684, 34471683},
1848
  {64685, 34472195}, {64686, 34472707}, {64687, 34473219}, {64688, 34473731},
1849
  {64689, 34474243}, {64690, 34519299}, {64691, 34474755}, {64692, 34475267},
1850
  {64693, 34475779}, {64694, 34476291}, {64695, 34476803}, {64696, 34477315},
1851
  {64697, 34478339}, {64698, 34478851}, {64699, 34479363}, {64700, 34479875},
1852
  {64701, 34480387}, {64702, 34480899}, {64703, 34481411}, {64704, 34481923},
1853
  {64705, 34482435}, {64706, 34483971}, {64707, 34484483}, {64708, 34486531},
1854
  {64709, 34487043}, {64710, 34487555}, {64711, 34488067}, {64712, 34488579},
1855
  {64713, 34490115}, {64714, 34490627}, {64715, 34491139}, {64716, 34491651},
1856
  {64717, 34519811}, {64718, 34493187}, {64719, 34469891}, {64720, 34470403},
1857
  {64721, 34493699}, {64722, 34495235}, {64723, 34495747}, {64724, 34496259},
1858
  {64725, 34496771}, {64726, 34520323}, {64727, 34498307}, {64728, 34498819},
1859
  {64729, 34520835}, {64730, 34468867}, {64731, 34500355}, {64732, 34500867},
1860
  {64733, 34492931}, {64734, 34498051}, {64735, 34459907}, {64736, 34517763},
1861
  {64737, 34462467}, {64738, 34518275}, {64739, 34465539}, {64740, 34518787},
1862
  {64741, 34467587}, {64742, 34521347}, {64743, 34473731}, {64744, 34521859},
1863
  {64745, 34522371}, {64746, 34522883}, {64747, 34488067}, {64748, 34488579},
1864
  {64749, 34491651}, {64750, 34496771}, {64751, 34520323}, {64752, 34492931},
1865
  {64753, 34498051}, {64754, 51300611}, {64755, 51301379}, {64756, 51302147},
1866
  {64757, 34525699}, {64758, 34526211}, {64759, 34526723}, {64760, 34527235},
1867
  {64761, 34527747}, {64762, 34528259}, {64763, 34528771}, {64764, 34529283},
1868
  {64765, 34529795}, {64766, 34530307}, {64767, 34530819}, {64768, 34500611},
1869
  {64769, 34531331}, {64770, 34531843}, {64771, 34532355}, {64772, 34501123},
1870
  {64773, 34532867}, {64774, 34533379}, {64775, 34533891}, {64776, 34534403},
1871
  {64777, 34534915}, {64778, 34535427}, {64779, 34535939}, {64780, 34522371},
1872
  {64781, 34536451}, {64782, 34536963}, {64783, 34537475}, {64784, 34537987},
1873
  {64785, 34525699}, {64786, 34526211}, {64787, 34526723}, {64788, 34527235},
1874
  {64789, 34527747}, {64790, 34528259}, {64791, 34528771}, {64792, 34529283},
1875
  {64793, 34529795}, {64794, 34530307}, {64795, 34530819}, {64796, 34500611},
1876
  {64797, 34531331}, {64798, 34531843}, {64799, 34532355}, {64800, 34501123},
1877
  {64801, 34532867}, {64802, 34533379}, {64803, 34533891}, {64804, 34534403},
1878
  {64805, 34534915}, {64806, 34535427}, {64807, 34535939}, {64808, 34522371},
1879
  {64809, 34536451}, {64810, 34536963}, {64811, 34537475}, {64812, 34537987},
1880
  {64813, 34534915}, {64814, 34535427}, {64815, 34535939}, {64816, 34522371},
1881
  {64817, 34521859}, {64818, 34522883}, {64819, 34477827}, {64820, 34472195},
1882
  {64821, 34472707}, {64822, 34473219}, {64823, 34534915}, {64824, 34535427},
1883
  {64825, 34535939}, {64826, 34477827}, {64827, 34478339}, {64828, 34538499},
1884
  {64830, 1}, {64848, 51316227}, {64849, 51316995}, {64851, 51317763},
1885
  {64852, 51318531}, {64853, 51319299}, {64854, 51320067}, {64855, 51320835},
1886
  {64856, 51246851}, {64858, 51321603}, {64859, 51322371}, {64860, 51323139},
1887
  {64861, 51323907}, {64862, 51324675}, {64863, 51325443}, {64865, 51326211},
1888
  {64866, 51326979}, {64868, 51327747}, {64870, 51328515}, {64871, 51329283},
1889
  {64873, 51330051}, {64874, 51330819}, {64876, 51331587}, {64878, 51332355},
1890
  {64879, 51333123}, {64881, 51333891}, {64883, 51334659}, {64884, 51335427},
1891
  {64885, 51336195}, {64886, 51336963}, {64888, 51337731}, {64889, 51338499},
1892
  {64890, 51339267}, {64891, 51340035}, {64892, 51340803}, {64894, 51341571},
1893
  {64895, 51342339}, {64896, 51343107}, {64897, 51343875}, {64898, 51344643},
1894
  {64899, 51345411}, {64901, 51346179}, {64903, 51346947}, {64905, 51347715},
1895
  {64906, 51247107}, {64907, 51348483}, {64908, 51349251}, {64909, 51270403},
1896
  {64910, 51247619}, {64911, 51350019}, {64912, 2}, {64914, 51350787},
1897
  {64915, 51351555}, {64916, 51352323}, {64917, 51353091}, {64918, 51353859},
1898
  {64919, 51354627}, {64921, 51355395}, {64922, 51356163}, {64923, 51356931},
1899
  {64924, 51357699}, {64926, 51358467}, {64927, 51359235}, {64928, 51360003},
1900
  {64929, 51360771}, {64930, 51361539}, {64931, 51362307}, {64932, 51363075},
1901
  {64933, 51363843}, {64934, 51364611}, {64935, 51365379}, {64936, 51366147},
1902
  {64937, 51366915}, {64938, 51367683}, {64939, 51368451}, {64940, 51369219},
1903
  {64941, 51369987}, {64942, 51277571}, {64943, 51370755}, {64944, 51371523},
1904
  {64945, 51372291}, {64946, 51373059}, {64947, 51373827}, {64948, 51341571},
1905
  {64949, 51343107}, {64950, 51374595}, {64951, 51375363}, {64952, 51376131},
1906
  {64953, 51376899}, {64954, 51377667}, {64955, 51378435}, {64956, 51377667},
1907
  {64957, 51376131}, {64958, 51379203}, {64959, 51379971}, {64960, 51380739},
1908
  {64961, 51381507}, {64962, 51382275}, {64963, 51378435}, {64964, 51336195},
1909
  {64965, 51328515}, {64966, 51383043}, {64967, 51383811}, {64968, 2},
1910
  {64975, 1}, {64976, 2}, {65008, 51384579}, {65009, 51385347},
1911
  {65010, 68163331}, {65011, 68164355}, {65012, 68165379}, {65013, 68166403},
1912
  {65014, 68167427}, {65015, 68168451}, {65016, 68169475}, {65017, 51393283},
1913
  {65018, 303052291}, {65019, 135284739}, {65020, 68177923}, {65021, 1},
1914
  {65024, 0}, {65040, 17847299}, {65041, 17847555}, {65042, 2},
1915
  {65043, 17110531}, {65044, 16848643}, {65045, 17032963}, {65046, 17033987},
1916
  {65047, 17847811}, {65048, 17848067}, {65049, 2}, {65056, 1},
1917
  {65072, 2}, {65073, 17848323}, {65074, 17848579}, {65075, 17848835},
1918
  {65077, 17037827}, {65078, 17038083}, {65079, 17849091}, {65080, 17849347},
1919
  {65081, 17849603}, {65082, 17849859}, {65083, 17850115}, {65084, 17850371},
1920
  {65085, 17850627}, {65086, 17850883}, {65087, 17067267}, {65088, 17067523},
1921
  {65089, 17851139}, {65090, 17851395}, {65091, 17851651}, {65092, 17851907},
1922
  {65093, 1}, {65095, 17852163}, {65096, 17852419}, {65097, 33810691},
1923
  {65101, 17848835}, {65104, 17847299}, {65105, 17847555}, {65106, 2},
1924
  {65108, 16848643}, {65109, 17110531}, {65110, 17033987}, {65111, 17032963},
1925
  {65112, 17848323}, {65113, 17037827}, {65114, 17038083}, {65115, 17849091},
1926
  {65116, 17849347}, {65117, 17849603}, {65118, 17849859}, {65119, 17852675},
1927
  {65120, 17852931}, {65121, 17853187}, {65122, 17037059}, {65123, 17853443},
1928
  {65124, 17853699}, {65125, 17853955}, {65126, 17037571}, {65127, 2},
1929
  {65128, 17854211}, {65129, 17854467}, {65130, 17854723}, {65131, 17854979},
1930
  {65132, 2}, {65136, 34632451}, {65137, 34632963}, {65138, 34503427},
1931
  {65139, 1}, {65140, 34504195}, {65141, 2}, {65142, 34504963},
1932
  {65143, 34523395}, {65144, 34505731}, {65145, 34524163}, {65146, 34506499},
1933
  {65147, 34524931}, {65148, 34507267}, {65149, 34633475}, {65150, 34633987},
1934
  {65151, 34634499}, {65152, 17857795}, {65153, 17858051}, {65155, 17858307},
1935
  {65157, 17858563}, {65159, 17858819}, {65161, 17677315}, {65165, 16910339},
1936
  {65167, 17683715}, {65171, 17859075}, {65173, 17686787}, {65177, 17689859},
1937
  {65181, 17681923}, {65185, 17682435}, {65189, 17684995}, {65193, 17834499},
1938
  {65195, 17724675}, {65197, 17725187}, {65199, 17731587}, {65201, 17694979},
1939
  {65205, 17745155}, {65209, 17697027}, {65213, 17698051}, {65217, 17700099},
1940
  {65221, 17701123}, {65225, 17701635}, {65229, 17702659}, {65233, 17703683},
1941
  {65237, 17706755}, {65241, 17708803}, {65245, 17711107}, {65249, 17682947},
1942
  {65253, 17718019}, {65257, 17721091}, {65261, 16910851}, {65263, 17677059},
1943
  {65265, 16911875}, {65269, 34636547}, {65271, 34637059}, {65273, 34637571},
1944
  {65275, 34622467}, {65277, 2}, {65279, 0}, {65280, 2},
1945
  {65281, 17032963}, {65282, 17860867}, {65283, 17852675}, {65284, 17854467},
1946
  {65285, 17854723}, {65286, 17852931}, {65287, 17861123}, {65288, 17037827},
1947
  {65289, 17038083}, {65290, 17853187}, {65291, 17037059}, {65292, 17847299},
1948
  {65293, 17853443}, {65294, 17196547}, {65295, 17038595}, {65296, 17035523},
1949
  {65297, 16786947}, {65298, 16785155}, {65299, 16785411}, {65300, 16787715},
1950
  {65301, 17035779}, {65302, 17036035}, {65303, 17036291}, {65304, 17036547},
1951
  {65305, 17036803}, {65306, 17110531}, {65307, 16848643}, {65308, 17853699},
1952
  {65309, 17037571}, {65310, 17853955}, {65311, 17033987}, {65312, 17854979},
1953
  {65313, 16777219}, {65314, 16777475}, {65315, 16777731}, {65316, 16777987},
1954
  {65317, 16778243}, {65318, 16778499}, {65319, 16778755}, {65320, 16779011},
1955
  {65321, 16779267}, {65322, 16779523}, {65323, 16779779}, {65324, 16780035},
1956
  {65325, 16780291}, {65326, 16780547}, {65327, 16780803}, {65328, 16781059},
1957
  {65329, 16781315}, {65330, 16781571}, {65331, 16781827}, {65332, 16782083},
1958
  {65333, 16782339}, {65334, 16782595}, {65335, 16782851}, {65336, 16783107},
1959
  {65337, 16783363}, {65338, 16783619}, {65339, 17852163}, {65340, 17854211},
1960
  {65341, 17852419}, {65342, 17861379}, {65343, 17848835}, {65344, 17027075},
1961
  {65345, 16777219}, {65346, 16777475}, {65347, 16777731}, {65348, 16777987},
1962
  {65349, 16778243}, {65350, 16778499}, {65351, 16778755}, {65352, 16779011},
1963
  {65353, 16779267}, {65354, 16779523}, {65355, 16779779}, {65356, 16780035},
1964
  {65357, 16780291}, {65358, 16780547}, {65359, 16780803}, {65360, 16781059},
1965
  {65361, 16781315}, {65362, 16781571}, {65363, 16781827}, {65364, 16782083},
1966
  {65365, 16782339}, {65366, 16782595}, {65367, 16782851}, {65368, 16783107},
1967
  {65369, 16783363}, {65370, 16783619}, {65371, 17849091}, {65372, 17861635},
1968
  {65373, 17849347}, {65374, 17861891}, {65375, 17862147}, {65376, 17862403},
1969
  {65377, 17196547}, {65378, 17851139}, {65379, 17851395}, {65380, 17847555},
1970
  {65381, 17862659}, {65382, 17316867}, {65383, 17319427}, {65384, 17362435},
1971
  {65385, 17862915}, {65386, 17363971}, {65387, 17323523}, {65388, 17863171},
1972
  {65389, 17333763}, {65390, 17379587}, {65391, 17329155}, {65392, 17318147},
1973
  {65393, 17305603}, {65394, 17305859}, {65395, 17306115}, {65396, 17306371},
1974
  {65397, 17306627}, {65398, 17306883}, {65399, 17307139}, {65400, 17307395},
1975
  {65401, 17307651}, {65402, 17199107}, {65403, 17307907}, {65404, 17308163},
1976
  {65405, 17308419}, {65406, 17308675}, {65407, 17308931}, {65408, 17309187},
1977
  {65409, 17309443}, {65410, 17309699}, {65411, 17309955}, {65412, 17199363},
1978
  {65413, 17310211}, {65414, 17310467}, {65415, 17310723}, {65416, 17310979},
1979
  {65417, 17311235}, {65418, 17311491}, {65419, 17311747}, {65420, 17312003},
1980
  {65421, 17312259}, {65422, 17312515}, {65423, 17312771}, {65424, 17313027},
1981
  {65425, 17313283}, {65426, 17313539}, {65427, 17313795}, {65428, 17314051},
1982
  {65429, 17314307}, {65430, 17314563}, {65431, 17314819}, {65432, 17315075},
1983
  {65433, 17315331}, {65434, 17315587}, {65435, 17315843}, {65436, 17316099},
1984
  {65437, 17319939}, {65438, 17197827}, {65439, 17198339}, {65440, 2},
1985
  {65441, 17199619}, {65442, 17199875}, {65443, 17200131}, {65444, 17200387},
1986
  {65445, 17200643}, {65446, 17200899}, {65447, 17201155}, {65448, 17201411},
1987
  {65449, 17201667}, {65450, 17201923}, {65451, 17202179}, {65452, 17202435},
1988
  {65453, 17202691}, {65454, 17202947}, {65455, 17203203}, {65456, 17203459},
1989
  {65457, 17203715}, {65458, 17203971}, {65459, 17204227}, {65460, 17204483},
1990
  {65461, 17204739}, {65462, 17204995}, {65463, 17205251}, {65464, 17205507},
1991
  {65465, 17205763}, {65466, 17206019}, {65467, 17206275}, {65468, 17206531},
1992
  {65469, 17206787}, {65470, 17207043}, {65471, 2}, {65474, 17207299},
1993
  {65475, 17207555}, {65476, 17207811}, {65477, 17208067}, {65478, 17208323},
1994
  {65479, 17208579}, {65480, 2}, {65482, 17208835}, {65483, 17209091},
1995
  {65484, 17209347}, {65485, 17209603}, {65486, 17209859}, {65487, 17210115},
1996
  {65488, 2}, {65490, 17210371}, {65491, 17210627}, {65492, 17210883},
1997
  {65493, 17211139}, {65494, 17211395}, {65495, 17211651}, {65496, 2},
1998
  {65498, 17211907}, {65499, 17212163}, {65500, 17212419}, {65501, 2},
1999
  {65504, 17863427}, {65505, 17863683}, {65506, 17863939}, {65507, 33561859},
2000
  {65508, 17864195}, {65509, 17864451}, {65510, 17864707}, {65511, 2},
2001
  {65512, 17864963}, {65513, 17865219}, {65514, 17865475}, {65515, 17865731},
2002
  {65516, 17865987}, {65517, 17866243}, {65518, 17866499}, {65519, 2},
2003
  {65536, 1}, {65548, 2}, {65549, 1}, {65575, 2},
2004
  {65576, 1}, {65595, 2}, {65596, 1}, {65598, 2},
2005
  {65599, 1}, {65614, 2}, {65616, 1}, {65630, 2},
2006
  {65664, 1}, {65787, 2}, {65792, 1}, {65795, 2},
2007
  {65799, 1}, {65844, 2}, {65847, 1}, {65935, 2},
2008
  {65936, 1}, {65949, 2}, {65952, 1}, {65953, 2},
2009
  {66000, 1}, {66046, 2}, {66176, 1}, {66205, 2},
2010
  {66208, 1}, {66257, 2}, {66272, 1}, {66300, 2},
2011
  {66304, 1}, {66340, 2}, {66349, 1}, {66379, 2},
2012
  {66384, 1}, {66427, 2}, {66432, 1}, {66462, 2},
2013
  {66463, 1}, {66500, 2}, {66504, 1}, {66518, 2},
2014
  {66560, 17866755}, {66561, 17867011}, {66562, 17867267}, {66563, 17867523},
2015
  {66564, 17867779}, {66565, 17868035}, {66566, 17868291}, {66567, 17868547},
2016
  {66568, 17868803}, {66569, 17869059}, {66570, 17869315}, {66571, 17869571},
2017
  {66572, 17869827}, {66573, 17870083}, {66574, 17870339}, {66575, 17870595},
2018
  {66576, 17870851}, {66577, 17871107}, {66578, 17871363}, {66579, 17871619},
2019
  {66580, 17871875}, {66581, 17872131}, {66582, 17872387}, {66583, 17872643},
2020
  {66584, 17872899}, {66585, 17873155}, {66586, 17873411}, {66587, 17873667},
2021
  {66588, 17873923}, {66589, 17874179}, {66590, 17874435}, {66591, 17874691},
2022
  {66592, 17874947}, {66593, 17875203}, {66594, 17875459}, {66595, 17875715},
2023
  {66596, 17875971}, {66597, 17876227}, {66598, 17876483}, {66599, 17876739},
2024
  {66600, 1}, {66718, 2}, {66720, 1}, {66730, 2},
2025
  {66736, 17876995}, {66737, 17877251}, {66738, 17877507}, {66739, 17877763},
2026
  {66740, 17878019}, {66741, 17878275}, {66742, 17878531}, {66743, 17878787},
2027
  {66744, 17879043}, {66745, 17879299}, {66746, 17879555}, {66747, 17879811},
2028
  {66748, 17880067}, {66749, 17880323}, {66750, 17880579}, {66751, 17880835},
2029
  {66752, 17881091}, {66753, 17881347}, {66754, 17881603}, {66755, 17881859},
2030
  {66756, 17882115}, {66757, 17882371}, {66758, 17882627}, {66759, 17882883},
2031
  {66760, 17883139}, {66761, 17883395}, {66762, 17883651}, {66763, 17883907},
2032
  {66764, 17884163}, {66765, 17884419}, {66766, 17884675}, {66767, 17884931},
2033
  {66768, 17885187}, {66769, 17885443}, {66770, 17885699}, {66771, 17885955},
2034
  {66772, 2}, {66776, 1}, {66812, 2}, {66816, 1},
2035
  {66856, 2}, {66864, 1}, {66916, 2}, {66927, 1},
2036
  {66928, 17886211}, {66929, 17886467}, {66930, 17886723}, {66931, 17886979},
2037
  {66932, 17887235}, {66933, 17887491}, {66934, 17887747}, {66935, 17888003},
2038
  {66936, 17888259}, {66937, 17888515}, {66938, 17888771}, {66939, 2},
2039
  {66940, 17889027}, {66941, 17889283}, {66942, 17889539}, {66943, 17889795},
2040
  {66944, 17890051}, {66945, 17890307}, {66946, 17890563}, {66947, 17890819},
2041
  {66948, 17891075}, {66949, 17891331}, {66950, 17891587}, {66951, 17891843},
2042
  {66952, 17892099}, {66953, 17892355}, {66954, 17892611}, {66955, 2},
2043
  {66956, 17892867}, {66957, 17893123}, {66958, 17893379}, {66959, 17893635},
2044
  {66960, 17893891}, {66961, 17894147}, {66962, 17894403}, {66963, 2},
2045
  {66964, 17894659}, {66965, 17894915}, {66966, 2}, {66967, 1},
2046
  {66978, 2}, {66979, 1}, {66994, 2}, {66995, 1},
2047
  {67002, 2}, {67003, 1}, {67005, 2}, {67072, 1},
2048
  {67383, 2}, {67392, 1}, {67414, 2}, {67424, 1},
2049
  {67432, 2}, {67456, 1}, {67457, 17895171}, {67458, 17895427},
2050
  {67459, 16791043}, {67460, 17895683}, {67461, 16814083}, {67462, 2},
2051
  {67463, 17895939}, {67464, 17896195}, {67465, 17896451}, {67466, 17896707},
2052
  {67467, 16815363}, {67468, 16815619}, {67469, 17896963}, {67470, 17897219},
2053
  {67471, 17897475}, {67472, 17897731}, {67473, 17897987}, {67474, 17898243},
2054
  {67475, 16817155}, {67476, 17898499}, {67477, 16802051}, {67478, 17898755},
2055
  {67479, 17899011}, {67480, 17899267}, {67481, 17899523}, {67482, 17899779},
2056
  {67483, 17512963}, {67484, 17900035}, {67485, 17900291}, {67486, 17900547},
2057
  {67487, 17900803}, {67488, 17901059}, {67489, 17901315}, {67490, 16795395},
2058
  {67491, 17901571}, {67492, 17901827}, {67493, 16781315}, {67494, 17902083},
2059
  {67495, 17902339}, {67496, 17125379}, {67497, 17902595}, {67498, 16819971},
2060
  {67499, 17902851}, {67500, 17903107}, {67501, 17903363}, {67502, 17903619},
2061
  {67503, 16820995}, {67504, 17903875}, {67505, 2}, {67506, 17904131},
2062
  {67507, 17904387}, {67508, 17904643}, {67509, 17904899}, {67510, 17905155},
2063
  {67511, 17905411}, {67512, 17905667}, {67513, 17905923}, {67514, 17906179},
2064
  {67515, 2}, {67584, 1}, {67590, 2}, {67592, 1},
2065
  {67593, 2}, {67594, 1}, {67638, 2}, {67639, 1},
2066
  {67641, 2}, {67644, 1}, {67645, 2}, {67647, 1},
2067
  {67670, 2}, {67671, 1}, {67743, 2}, {67751, 1},
2068
  {67760, 2}, {67808, 1}, {67827, 2}, {67828, 1},
2069
  {67830, 2}, {67835, 1}, {67868, 2}, {67871, 1},
2070
  {67898, 2}, {67903, 1}, {67904, 2}, {67968, 1},
2071
  {68024, 2}, {68028, 1}, {68048, 2}, {68050, 1},
2072
  {68100, 2}, {68101, 1}, {68103, 2}, {68108, 1},
2073
  {68116, 2}, {68117, 1}, {68120, 2}, {68121, 1},
2074
  {68150, 2}, {68152, 1}, {68155, 2}, {68159, 1},
2075
  {68169, 2}, {68176, 1}, {68185, 2}, {68192, 1},
2076
  {68256, 2}, {68288, 1}, {68327, 2}, {68331, 1},
2077
  {68343, 2}, {68352, 1}, {68406, 2}, {68409, 1},
2078
  {68438, 2}, {68440, 1}, {68467, 2}, {68472, 1},
2079
  {68498, 2}, {68505, 1}, {68509, 2}, {68521, 1},
2080
  {68528, 2}, {68608, 1}, {68681, 2}, {68736, 17906435},
2081
  {68737, 17906691}, {68738, 17906947}, {68739, 17907203}, {68740, 17907459},
2082
  {68741, 17907715}, {68742, 17907971}, {68743, 17908227}, {68744, 17908483},
2083
  {68745, 17908739}, {68746, 17908995}, {68747, 17909251}, {68748, 17909507},
2084
  {68749, 17909763}, {68750, 17910019}, {68751, 17910275}, {68752, 17910531},
2085
  {68753, 17910787}, {68754, 17911043}, {68755, 17911299}, {68756, 17911555},
2086
  {68757, 17911811}, {68758, 17912067}, {68759, 17912323}, {68760, 17912579},
2087
  {68761, 17912835}, {68762, 17913091}, {68763, 17913347}, {68764, 17913603},
2088
  {68765, 17913859}, {68766, 17914115}, {68767, 17914371}, {68768, 17914627},
2089
  {68769, 17914883}, {68770, 17915139}, {68771, 17915395}, {68772, 17915651},
2090
  {68773, 17915907}, {68774, 17916163}, {68775, 17916419}, {68776, 17916675},
2091
  {68777, 17916931}, {68778, 17917187}, {68779, 17917443}, {68780, 17917699},
2092
  {68781, 17917955}, {68782, 17918211}, {68783, 17918467}, {68784, 17918723},
2093
  {68785, 17918979}, {68786, 17919235}, {68787, 2}, {68800, 1},
2094
  {68851, 2}, {68858, 1}, {68904, 2}, {68912, 1},
2095
  {68922, 2}, {69216, 1}, {69247, 2}, {69248, 1},
2096
  {69290, 2}, {69291, 1}, {69294, 2}, {69296, 1},
2097
  {69298, 2}, {69373, 1}, {69416, 2}, {69424, 1},
2098
  {69466, 2}, {69488, 1}, {69514, 2}, {69552, 1},
2099
  {69580, 2}, {69600, 1}, {69623, 2}, {69632, 1},
2100
  {69710, 2}, {69714, 1}, {69750, 2}, {69759, 1},
2101
  {69821, 2}, {69822, 1}, {69827, 2}, {69840, 1},
2102
  {69865, 2}, {69872, 1}, {69882, 2}, {69888, 1},
2103
  {69941, 2}, {69942, 1}, {69960, 2}, {69968, 1},
2104
  {70007, 2}, {70016, 1}, {70112, 2}, {70113, 1},
2105
  {70133, 2}, {70144, 1}, {70162, 2}, {70163, 1},
2106
  {70210, 2}, {70272, 1}, {70279, 2}, {70280, 1},
2107
  {70281, 2}, {70282, 1}, {70286, 2}, {70287, 1},
2108
  {70302, 2}, {70303, 1}, {70314, 2}, {70320, 1},
2109
  {70379, 2}, {70384, 1}, {70394, 2}, {70400, 1},
2110
  {70404, 2}, {70405, 1}, {70413, 2}, {70415, 1},
2111
  {70417, 2}, {70419, 1}, {70441, 2}, {70442, 1},
2112
  {70449, 2}, {70450, 1}, {70452, 2}, {70453, 1},
2113
  {70458, 2}, {70459, 1}, {70469, 2}, {70471, 1},
2114
  {70473, 2}, {70475, 1}, {70478, 2}, {70480, 1},
2115
  {70481, 2}, {70487, 1}, {70488, 2}, {70493, 1},
2116
  {70500, 2}, {70502, 1}, {70509, 2}, {70512, 1},
2117
  {70517, 2}, {70656, 1}, {70748, 2}, {70749, 1},
2118
  {70754, 2}, {70784, 1}, {70856, 2}, {70864, 1},
2119
  {70874, 2}, {71040, 1}, {71094, 2}, {71096, 1},
2120
  {71134, 2}, {71168, 1}, {71237, 2}, {71248, 1},
2121
  {71258, 2}, {71264, 1}, {71277, 2}, {71296, 1},
2122
  {71354, 2}, {71360, 1}, {71370, 2}, {71424, 1},
2123
  {71451, 2}, {71453, 1}, {71468, 2}, {71472, 1},
2124
  {71495, 2}, {71680, 1}, {71740, 2}, {71840, 17919491},
2125
  {71841, 17919747}, {71842, 17920003}, {71843, 17920259}, {71844, 17920515},
2126
  {71845, 17920771}, {71846, 17921027}, {71847, 17921283}, {71848, 17921539},
2127
  {71849, 17921795}, {71850, 17922051}, {71851, 17922307}, {71852, 17922563},
2128
  {71853, 17922819}, {71854, 17923075}, {71855, 17923331}, {71856, 17923587},
2129
  {71857, 17923843}, {71858, 17924099}, {71859, 17924355}, {71860, 17924611},
2130
  {71861, 17924867}, {71862, 17925123}, {71863, 17925379}, {71864, 17925635},
2131
  {71865, 17925891}, {71866, 17926147}, {71867, 17926403}, {71868, 17926659},
2132
  {71869, 17926915}, {71870, 17927171}, {71871, 17927427}, {71872, 1},
2133
  {71923, 2}, {71935, 1}, {71943, 2}, {71945, 1},
2134
  {71946, 2}, {71948, 1}, {71956, 2}, {71957, 1},
2135
  {71959, 2}, {71960, 1}, {71990, 2}, {71991, 1},
2136
  {71993, 2}, {71995, 1}, {72007, 2}, {72016, 1},
2137
  {72026, 2}, {72096, 1}, {72104, 2}, {72106, 1},
2138
  {72152, 2}, {72154, 1}, {72165, 2}, {72192, 1},
2139
  {72264, 2}, {72272, 1}, {72355, 2}, {72368, 1},
2140
  {72441, 2}, {72448, 1}, {72458, 2}, {72704, 1},
2141
  {72713, 2}, {72714, 1}, {72759, 2}, {72760, 1},
2142
  {72774, 2}, {72784, 1}, {72813, 2}, {72816, 1},
2143
  {72848, 2}, {72850, 1}, {72872, 2}, {72873, 1},
2144
  {72887, 2}, {72960, 1}, {72967, 2}, {72968, 1},
2145
  {72970, 2}, {72971, 1}, {73015, 2}, {73018, 1},
2146
  {73019, 2}, {73020, 1}, {73022, 2}, {73023, 1},
2147
  {73032, 2}, {73040, 1}, {73050, 2}, {73056, 1},
2148
  {73062, 2}, {73063, 1}, {73065, 2}, {73066, 1},
2149
  {73103, 2}, {73104, 1}, {73106, 2}, {73107, 1},
2150
  {73113, 2}, {73120, 1}, {73130, 2}, {73440, 1},
2151
  {73465, 2}, {73472, 1}, {73489, 2}, {73490, 1},
2152
  {73531, 2}, {73534, 1}, {73562, 2}, {73648, 1},
2153
  {73649, 2}, {73664, 1}, {73714, 2}, {73727, 1},
2154
  {74650, 2}, {74752, 1}, {74863, 2}, {74864, 1},
2155
  {74869, 2}, {74880, 1}, {75076, 2}, {77712, 1},
2156
  {77811, 2}, {77824, 1}, {78896, 2}, {78912, 1},
2157
  {78934, 2}, {82944, 1}, {83527, 2}, {92160, 1},
2158
  {92729, 2}, {92736, 1}, {92767, 2}, {92768, 1},
2159
  {92778, 2}, {92782, 1}, {92863, 2}, {92864, 1},
2160
  {92874, 2}, {92880, 1}, {92910, 2}, {92912, 1},
2161
  {92918, 2}, {92928, 1}, {92998, 2}, {93008, 1},
2162
  {93018, 2}, {93019, 1}, {93026, 2}, {93027, 1},
2163
  {93048, 2}, {93053, 1}, {93072, 2}, {93760, 17927683},
2164
  {93761, 17927939}, {93762, 17928195}, {93763, 17928451}, {93764, 17928707},
2165
  {93765, 17928963}, {93766, 17929219}, {93767, 17929475}, {93768, 17929731},
2166
  {93769, 17929987}, {93770, 17930243}, {93771, 17930499}, {93772, 17930755},
2167
  {93773, 17931011}, {93774, 17931267}, {93775, 17931523}, {93776, 17931779},
2168
  {93777, 17932035}, {93778, 17932291}, {93779, 17932547}, {93780, 17932803},
2169
  {93781, 17933059}, {93782, 17933315}, {93783, 17933571}, {93784, 17933827},
2170
  {93785, 17934083}, {93786, 17934339}, {93787, 17934595}, {93788, 17934851},
2171
  {93789, 17935107}, {93790, 17935363}, {93791, 17935619}, {93792, 1},
2172
  {93851, 2}, {93952, 1}, {94027, 2}, {94031, 1},
2173
  {94088, 2}, {94095, 1}, {94112, 2}, {94176, 1},
2174
  {94181, 2}, {94192, 1}, {94194, 2}, {94208, 1},
2175
  {100344, 2}, {100352, 1}, {101590, 2}, {101632, 1},
2176
  {101641, 2}, {110576, 1}, {110580, 2}, {110581, 1},
2177
  {110588, 2}, {110589, 1}, {110591, 2}, {110592, 1},
2178
  {110883, 2}, {110898, 1}, {110899, 2}, {110928, 1},
2179
  {110931, 2}, {110933, 1}, {110934, 2}, {110948, 1},
2180
  {110952, 2}, {110960, 1}, {111356, 2}, {113664, 1},
2181
  {113771, 2}, {113776, 1}, {113789, 2}, {113792, 1},
2182
  {113801, 2}, {113808, 1}, {113818, 2}, {113820, 1},
2183
  {113824, 0}, {113828, 2}, {118528, 1}, {118574, 2},
2184
  {118576, 1}, {118599, 2}, {118608, 1}, {118724, 2},
2185
  {118784, 1}, {119030, 2}, {119040, 1}, {119079, 2},
2186
  {119081, 1}, {119134, 34713091}, {119135, 34713603}, {119136, 51491331},
2187
  {119137, 51492099}, {119138, 51492867}, {119139, 51493635}, {119140, 51494403},
2188
  {119141, 1}, {119155, 2}, {119163, 1}, {119227, 34717955},
2189
  {119228, 34718467}, {119229, 51496195}, {119230, 51496963}, {119231, 51497731},
2190
  {119232, 51498499}, {119233, 1}, {119275, 2}, {119296, 1},
2191
  {119366, 2}, {119488, 1}, {119508, 2}, {119520, 1},
2192
  {119540, 2}, {119552, 1}, {119639, 2}, {119648, 1},
2193
  {119673, 2}, {119808, 16777219}, {119809, 16777475}, {119810, 16777731},
2194
  {119811, 16777987}, {119812, 16778243}, {119813, 16778499}, {119814, 16778755},
2195
  {119815, 16779011}, {119816, 16779267}, {119817, 16779523}, {119818, 16779779},
2196
  {119819, 16780035}, {119820, 16780291}, {119821, 16780547}, {119822, 16780803},
2197
  {119823, 16781059}, {119824, 16781315}, {119825, 16781571}, {119826, 16781827},
2198
  {119827, 16782083}, {119828, 16782339}, {119829, 16782595}, {119830, 16782851},
2199
  {119831, 16783107}, {119832, 16783363}, {119833, 16783619}, {119834, 16777219},
2200
  {119835, 16777475}, {119836, 16777731}, {119837, 16777987}, {119838, 16778243},
2201
  {119839, 16778499}, {119840, 16778755}, {119841, 16779011}, {119842, 16779267},
2202
  {119843, 16779523}, {119844, 16779779}, {119845, 16780035}, {119846, 16780291},
2203
  {119847, 16780547}, {119848, 16780803}, {119849, 16781059}, {119850, 16781315},
2204
  {119851, 16781571}, {119852, 16781827}, {119853, 16782083}, {119854, 16782339},
2205
  {119855, 16782595}, {119856, 16782851}, {119857, 16783107}, {119858, 16783363},
2206
  {119859, 16783619}, {119860, 16777219}, {119861, 16777475}, {119862, 16777731},
2207
  {119863, 16777987}, {119864, 16778243}, {119865, 16778499}, {119866, 16778755},
2208
  {119867, 16779011}, {119868, 16779267}, {119869, 16779523}, {119870, 16779779},
2209
  {119871, 16780035}, {119872, 16780291}, {119873, 16780547}, {119874, 16780803},
2210
  {119875, 16781059}, {119876, 16781315}, {119877, 16781571}, {119878, 16781827},
2211
  {119879, 16782083}, {119880, 16782339}, {119881, 16782595}, {119882, 16782851},
2212
  {119883, 16783107}, {119884, 16783363}, {119885, 16783619}, {119886, 16777219},
2213
  {119887, 16777475}, {119888, 16777731}, {119889, 16777987}, {119890, 16778243},
2214
  {119891, 16778499}, {119892, 16778755}, {119893, 2}, {119894, 16779267},
2215
  {119895, 16779523}, {119896, 16779779}, {119897, 16780035}, {119898, 16780291},
2216
  {119899, 16780547}, {119900, 16780803}, {119901, 16781059}, {119902, 16781315},
2217
  {119903, 16781571}, {119904, 16781827}, {119905, 16782083}, {119906, 16782339},
2218
  {119907, 16782595}, {119908, 16782851}, {119909, 16783107}, {119910, 16783363},
2219
  {119911, 16783619}, {119912, 16777219}, {119913, 16777475}, {119914, 16777731},
2220
  {119915, 16777987}, {119916, 16778243}, {119917, 16778499}, {119918, 16778755},
2221
  {119919, 16779011}, {119920, 16779267}, {119921, 16779523}, {119922, 16779779},
2222
  {119923, 16780035}, {119924, 16780291}, {119925, 16780547}, {119926, 16780803},
2223
  {119927, 16781059}, {119928, 16781315}, {119929, 16781571}, {119930, 16781827},
2224
  {119931, 16782083}, {119932, 16782339}, {119933, 16782595}, {119934, 16782851},
2225
  {119935, 16783107}, {119936, 16783363}, {119937, 16783619}, {119938, 16777219},
2226
  {119939, 16777475}, {119940, 16777731}, {119941, 16777987}, {119942, 16778243},
2227
  {119943, 16778499}, {119944, 16778755}, {119945, 16779011}, {119946, 16779267},
2228
  {119947, 16779523}, {119948, 16779779}, {119949, 16780035}, {119950, 16780291},
2229
  {119951, 16780547}, {119952, 16780803}, {119953, 16781059}, {119954, 16781315},
2230
  {119955, 16781571}, {119956, 16781827}, {119957, 16782083}, {119958, 16782339},
2231
  {119959, 16782595}, {119960, 16782851}, {119961, 16783107}, {119962, 16783363},
2232
  {119963, 16783619}, {119964, 16777219}, {119965, 2}, {119966, 16777731},
2233
  {119967, 16777987}, {119968, 2}, {119970, 16778755}, {119971, 2},
2234
  {119973, 16779523}, {119974, 16779779}, {119975, 2}, {119977, 16780547},
2235
  {119978, 16780803}, {119979, 16781059}, {119980, 16781315}, {119981, 2},
2236
  {119982, 16781827}, {119983, 16782083}, {119984, 16782339}, {119985, 16782595},
2237
  {119986, 16782851}, {119987, 16783107}, {119988, 16783363}, {119989, 16783619},
2238
  {119990, 16777219}, {119991, 16777475}, {119992, 16777731}, {119993, 16777987},
2239
  {119994, 2}, {119995, 16778499}, {119996, 2}, {119997, 16779011},
2240
  {119998, 16779267}, {119999, 16779523}, {120000, 16779779}, {120001, 16780035},
2241
  {120002, 16780291}, {120003, 16780547}, {120004, 2}, {120005, 16781059},
2242
  {120006, 16781315}, {120007, 16781571}, {120008, 16781827}, {120009, 16782083},
2243
  {120010, 16782339}, {120011, 16782595}, {120012, 16782851}, {120013, 16783107},
2244
  {120014, 16783363}, {120015, 16783619}, {120016, 16777219}, {120017, 16777475},
2245
  {120018, 16777731}, {120019, 16777987}, {120020, 16778243}, {120021, 16778499},
2246
  {120022, 16778755}, {120023, 16779011}, {120024, 16779267}, {120025, 16779523},
2247
  {120026, 16779779}, {120027, 16780035}, {120028, 16780291}, {120029, 16780547},
2248
  {120030, 16780803}, {120031, 16781059}, {120032, 16781315}, {120033, 16781571},
2249
  {120034, 16781827}, {120035, 16782083}, {120036, 16782339}, {120037, 16782595},
2250
  {120038, 16782851}, {120039, 16783107}, {120040, 16783363}, {120041, 16783619},
2251
  {120042, 16777219}, {120043, 16777475}, {120044, 16777731}, {120045, 16777987},
2252
  {120046, 16778243}, {120047, 16778499}, {120048, 16778755}, {120049, 16779011},
2253
  {120050, 16779267}, {120051, 16779523}, {120052, 16779779}, {120053, 16780035},
2254
  {120054, 16780291}, {120055, 16780547}, {120056, 16780803}, {120057, 16781059},
2255
  {120058, 16781315}, {120059, 16781571}, {120060, 16781827}, {120061, 16782083},
2256
  {120062, 16782339}, {120063, 16782595}, {120064, 16782851}, {120065, 16783107},
2257
  {120066, 16783363}, {120067, 16783619}, {120068, 16777219}, {120069, 16777475},
2258
  {120070, 2}, {120071, 16777987}, {120072, 16778243}, {120073, 16778499},
2259
  {120074, 16778755}, {120075, 2}, {120077, 16779523}, {120078, 16779779},
2260
  {120079, 16780035}, {120080, 16780291}, {120081, 16780547}, {120082, 16780803},
2261
  {120083, 16781059}, {120084, 16781315}, {120085, 2}, {120086, 16781827},
2262
  {120087, 16782083}, {120088, 16782339}, {120089, 16782595}, {120090, 16782851},
2263
  {120091, 16783107}, {120092, 16783363}, {120093, 2}, {120094, 16777219},
2264
  {120095, 16777475}, {120096, 16777731}, {120097, 16777987}, {120098, 16778243},
2265
  {120099, 16778499}, {120100, 16778755}, {120101, 16779011}, {120102, 16779267},
2266
  {120103, 16779523}, {120104, 16779779}, {120105, 16780035}, {120106, 16780291},
2267
  {120107, 16780547}, {120108, 16780803}, {120109, 16781059}, {120110, 16781315},
2268
  {120111, 16781571}, {120112, 16781827}, {120113, 16782083}, {120114, 16782339},
2269
  {120115, 16782595}, {120116, 16782851}, {120117, 16783107}, {120118, 16783363},
2270
  {120119, 16783619}, {120120, 16777219}, {120121, 16777475}, {120122, 2},
2271
  {120123, 16777987}, {120124, 16778243}, {120125, 16778499}, {120126, 16778755},
2272
  {120127, 2}, {120128, 16779267}, {120129, 16779523}, {120130, 16779779},
2273
  {120131, 16780035}, {120132, 16780291}, {120133, 2}, {120134, 16780803},
2274
  {120135, 2}, {120138, 16781827}, {120139, 16782083}, {120140, 16782339},
2275
  {120141, 16782595}, {120142, 16782851}, {120143, 16783107}, {120144, 16783363},
2276
  {120145, 2}, {120146, 16777219}, {120147, 16777475}, {120148, 16777731},
2277
  {120149, 16777987}, {120150, 16778243}, {120151, 16778499}, {120152, 16778755},
2278
  {120153, 16779011}, {120154, 16779267}, {120155, 16779523}, {120156, 16779779},
2279
  {120157, 16780035}, {120158, 16780291}, {120159, 16780547}, {120160, 16780803},
2280
  {120161, 16781059}, {120162, 16781315}, {120163, 16781571}, {120164, 16781827},
2281
  {120165, 16782083}, {120166, 16782339}, {120167, 16782595}, {120168, 16782851},
2282
  {120169, 16783107}, {120170, 16783363}, {120171, 16783619}, {120172, 16777219},
2283
  {120173, 16777475}, {120174, 16777731}, {120175, 16777987}, {120176, 16778243},
2284
  {120177, 16778499}, {120178, 16778755}, {120179, 16779011}, {120180, 16779267},
2285
  {120181, 16779523}, {120182, 16779779}, {120183, 16780035}, {120184, 16780291},
2286
  {120185, 16780547}, {120186, 16780803}, {120187, 16781059}, {120188, 16781315},
2287
  {120189, 16781571}, {120190, 16781827}, {120191, 16782083}, {120192, 16782339},
2288
  {120193, 16782595}, {120194, 16782851}, {120195, 16783107}, {120196, 16783363},
2289
  {120197, 16783619}, {120198, 16777219}, {120199, 16777475}, {120200, 16777731},
2290
  {120201, 16777987}, {120202, 16778243}, {120203, 16778499}, {120204, 16778755},
2291
  {120205, 16779011}, {120206, 16779267}, {120207, 16779523}, {120208, 16779779},
2292
  {120209, 16780035}, {120210, 16780291}, {120211, 16780547}, {120212, 16780803},
2293
  {120213, 16781059}, {120214, 16781315}, {120215, 16781571}, {120216, 16781827},
2294
  {120217, 16782083}, {120218, 16782339}, {120219, 16782595}, {120220, 16782851},
2295
  {120221, 16783107}, {120222, 16783363}, {120223, 16783619}, {120224, 16777219},
2296
  {120225, 16777475}, {120226, 16777731}, {120227, 16777987}, {120228, 16778243},
2297
  {120229, 16778499}, {120230, 16778755}, {120231, 16779011}, {120232, 16779267},
2298
  {120233, 16779523}, {120234, 16779779}, {120235, 16780035}, {120236, 16780291},
2299
  {120237, 16780547}, {120238, 16780803}, {120239, 16781059}, {120240, 16781315},
2300
  {120241, 16781571}, {120242, 16781827}, {120243, 16782083}, {120244, 16782339},
2301
  {120245, 16782595}, {120246, 16782851}, {120247, 16783107}, {120248, 16783363},
2302
  {120249, 16783619}, {120250, 16777219}, {120251, 16777475}, {120252, 16777731},
2303
  {120253, 16777987}, {120254, 16778243}, {120255, 16778499}, {120256, 16778755},
2304
  {120257, 16779011}, {120258, 16779267}, {120259, 16779523}, {120260, 16779779},
2305
  {120261, 16780035}, {120262, 16780291}, {120263, 16780547}, {120264, 16780803},
2306
  {120265, 16781059}, {120266, 16781315}, {120267, 16781571}, {120268, 16781827},
2307
  {120269, 16782083}, {120270, 16782339}, {120271, 16782595}, {120272, 16782851},
2308
  {120273, 16783107}, {120274, 16783363}, {120275, 16783619}, {120276, 16777219},
2309
  {120277, 16777475}, {120278, 16777731}, {120279, 16777987}, {120280, 16778243},
2310
  {120281, 16778499}, {120282, 16778755}, {120283, 16779011}, {120284, 16779267},
2311
  {120285, 16779523}, {120286, 16779779}, {120287, 16780035}, {120288, 16780291},
2312
  {120289, 16780547}, {120290, 16780803}, {120291, 16781059}, {120292, 16781315},
2313
  {120293, 16781571}, {120294, 16781827}, {120295, 16782083}, {120296, 16782339},
2314
  {120297, 16782595}, {120298, 16782851}, {120299, 16783107}, {120300, 16783363},
2315
  {120301, 16783619}, {120302, 16777219}, {120303, 16777475}, {120304, 16777731},
2316
  {120305, 16777987}, {120306, 16778243}, {120307, 16778499}, {120308, 16778755},
2317
  {120309, 16779011}, {120310, 16779267}, {120311, 16779523}, {120312, 16779779},
2318
  {120313, 16780035}, {120314, 16780291}, {120315, 16780547}, {120316, 16780803},
2319
  {120317, 16781059}, {120318, 16781315}, {120319, 16781571}, {120320, 16781827},
2320
  {120321, 16782083}, {120322, 16782339}, {120323, 16782595}, {120324, 16782851},
2321
  {120325, 16783107}, {120326, 16783363}, {120327, 16783619}, {120328, 16777219},
2322
  {120329, 16777475}, {120330, 16777731}, {120331, 16777987}, {120332, 16778243},
2323
  {120333, 16778499}, {120334, 16778755}, {120335, 16779011}, {120336, 16779267},
2324
  {120337, 16779523}, {120338, 16779779}, {120339, 16780035}, {120340, 16780291},
2325
  {120341, 16780547}, {120342, 16780803}, {120343, 16781059}, {120344, 16781315},
2326
  {120345, 16781571}, {120346, 16781827}, {120347, 16782083}, {120348, 16782339},
2327
  {120349, 16782595}, {120350, 16782851}, {120351, 16783107}, {120352, 16783363},
2328
  {120353, 16783619}, {120354, 16777219}, {120355, 16777475}, {120356, 16777731},
2329
  {120357, 16777987}, {120358, 16778243}, {120359, 16778499}, {120360, 16778755},
2330
  {120361, 16779011}, {120362, 16779267}, {120363, 16779523}, {120364, 16779779},
2331
  {120365, 16780035}, {120366, 16780291}, {120367, 16780547}, {120368, 16780803},
2332
  {120369, 16781059}, {120370, 16781315}, {120371, 16781571}, {120372, 16781827},
2333
  {120373, 16782083}, {120374, 16782339}, {120375, 16782595}, {120376, 16782851},
2334
  {120377, 16783107}, {120378, 16783363}, {120379, 16783619}, {120380, 16777219},
2335
  {120381, 16777475}, {120382, 16777731}, {120383, 16777987}, {120384, 16778243},
2336
  {120385, 16778499}, {120386, 16778755}, {120387, 16779011}, {120388, 16779267},
2337
  {120389, 16779523}, {120390, 16779779}, {120391, 16780035}, {120392, 16780291},
2338
  {120393, 16780547}, {120394, 16780803}, {120395, 16781059}, {120396, 16781315},
2339
  {120397, 16781571}, {120398, 16781827}, {120399, 16782083}, {120400, 16782339},
2340
  {120401, 16782595}, {120402, 16782851}, {120403, 16783107}, {120404, 16783363},
2341
  {120405, 16783619}, {120406, 16777219}, {120407, 16777475}, {120408, 16777731},
2342
  {120409, 16777987}, {120410, 16778243}, {120411, 16778499}, {120412, 16778755},
2343
  {120413, 16779011}, {120414, 16779267}, {120415, 16779523}, {120416, 16779779},
2344
  {120417, 16780035}, {120418, 16780291}, {120419, 16780547}, {120420, 16780803},
2345
  {120421, 16781059}, {120422, 16781315}, {120423, 16781571}, {120424, 16781827},
2346
  {120425, 16782083}, {120426, 16782339}, {120427, 16782595}, {120428, 16782851},
2347
  {120429, 16783107}, {120430, 16783363}, {120431, 16783619}, {120432, 16777219},
2348
  {120433, 16777475}, {120434, 16777731}, {120435, 16777987}, {120436, 16778243},
2349
  {120437, 16778499}, {120438, 16778755}, {120439, 16779011}, {120440, 16779267},
2350
  {120441, 16779523}, {120442, 16779779}, {120443, 16780035}, {120444, 16780291},
2351
  {120445, 16780547}, {120446, 16780803}, {120447, 16781059}, {120448, 16781315},
2352
  {120449, 16781571}, {120450, 16781827}, {120451, 16782083}, {120452, 16782339},
2353
  {120453, 16782595}, {120454, 16782851}, {120455, 16783107}, {120456, 16783363},
2354
  {120457, 16783619}, {120458, 16777219}, {120459, 16777475}, {120460, 16777731},
2355
  {120461, 16777987}, {120462, 16778243}, {120463, 16778499}, {120464, 16778755},
2356
  {120465, 16779011}, {120466, 16779267}, {120467, 16779523}, {120468, 16779779},
2357
  {120469, 16780035}, {120470, 16780291}, {120471, 16780547}, {120472, 16780803},
2358
  {120473, 16781059}, {120474, 16781315}, {120475, 16781571}, {120476, 16781827},
2359
  {120477, 16782083}, {120478, 16782339}, {120479, 16782595}, {120480, 16782851},
2360
  {120481, 16783107}, {120482, 16783363}, {120483, 16783619}, {120484, 17944835},
2361
  {120485, 17945091}, {120486, 2}, {120488, 16851715}, {120489, 16851971},
2362
  {120490, 16852227}, {120491, 16852483}, {120492, 16852739}, {120493, 16852995},
2363
  {120494, 16853251}, {120495, 16853507}, {120496, 16846851}, {120497, 16853763},
2364
  {120498, 16854019}, {120499, 16786179}, {120500, 16854275}, {120501, 16854531},
2365
  {120502, 16854787}, {120503, 16855043}, {120504, 16855299}, {120505, 16853507},
2366
  {120506, 16855555}, {120507, 16855811}, {120508, 16856067}, {120509, 16856323},
2367
  {120510, 16856579}, {120511, 16856835}, {120512, 16857091}, {120513, 17945347},
2368
  {120514, 16851715}, {120515, 16851971}, {120516, 16852227}, {120517, 16852483},
2369
  {120518, 16852739}, {120519, 16852995}, {120520, 16853251}, {120521, 16853507},
2370
  {120522, 16846851}, {120523, 16853763}, {120524, 16854019}, {120525, 16786179},
2371
  {120526, 16854275}, {120527, 16854531}, {120528, 16854787}, {120529, 16855043},
2372
  {120530, 16855299}, {120531, 16855555}, {120533, 16855811}, {120534, 16856067},
2373
  {120535, 16856323}, {120536, 16856579}, {120537, 16856835}, {120538, 16857091},
2374
  {120539, 17945603}, {120540, 16852739}, {120541, 16853507}, {120542, 16853763},
2375
  {120543, 16856323}, {120544, 16855299}, {120545, 16855043}, {120546, 16851715},
2376
  {120547, 16851971}, {120548, 16852227}, {120549, 16852483}, {120550, 16852739},
2377
  {120551, 16852995}, {120552, 16853251}, {120553, 16853507}, {120554, 16846851},
2378
  {120555, 16853763}, {120556, 16854019}, {120557, 16786179}, {120558, 16854275},
2379
  {120559, 16854531}, {120560, 16854787}, {120561, 16855043}, {120562, 16855299},
2380
  {120563, 16853507}, {120564, 16855555}, {120565, 16855811}, {120566, 16856067},
2381
  {120567, 16856323}, {120568, 16856579}, {120569, 16856835}, {120570, 16857091},
2382
  {120571, 17945347}, {120572, 16851715}, {120573, 16851971}, {120574, 16852227},
2383
  {120575, 16852483}, {120576, 16852739}, {120577, 16852995}, {120578, 16853251},
2384
  {120579, 16853507}, {120580, 16846851}, {120581, 16853763}, {120582, 16854019},
2385
  {120583, 16786179}, {120584, 16854275}, {120585, 16854531}, {120586, 16854787},
2386
  {120587, 16855043}, {120588, 16855299}, {120589, 16855555}, {120591, 16855811},
2387
  {120592, 16856067}, {120593, 16856323}, {120594, 16856579}, {120595, 16856835},
2388
  {120596, 16857091}, {120597, 17945603}, {120598, 16852739}, {120599, 16853507},
2389
  {120600, 16853763}, {120601, 16856323}, {120602, 16855299}, {120603, 16855043},
2390
  {120604, 16851715}, {120605, 16851971}, {120606, 16852227}, {120607, 16852483},
2391
  {120608, 16852739}, {120609, 16852995}, {120610, 16853251}, {120611, 16853507},
2392
  {120612, 16846851}, {120613, 16853763}, {120614, 16854019}, {120615, 16786179},
2393
  {120616, 16854275}, {120617, 16854531}, {120618, 16854787}, {120619, 16855043},
2394
  {120620, 16855299}, {120621, 16853507}, {120622, 16855555}, {120623, 16855811},
2395
  {120624, 16856067}, {120625, 16856323}, {120626, 16856579}, {120627, 16856835},
2396
  {120628, 16857091}, {120629, 17945347}, {120630, 16851715}, {120631, 16851971},
2397
  {120632, 16852227}, {120633, 16852483}, {120634, 16852739}, {120635, 16852995},
2398
  {120636, 16853251}, {120637, 16853507}, {120638, 16846851}, {120639, 16853763},
2399
  {120640, 16854019}, {120641, 16786179}, {120642, 16854275}, {120643, 16854531},
2400
  {120644, 16854787}, {120645, 16855043}, {120646, 16855299}, {120647, 16855555},
2401
  {120649, 16855811}, {120650, 16856067}, {120651, 16856323}, {120652, 16856579},
2402
  {120653, 16856835}, {120654, 16857091}, {120655, 17945603}, {120656, 16852739},
2403
  {120657, 16853507}, {120658, 16853763}, {120659, 16856323}, {120660, 16855299},
2404
  {120661, 16855043}, {120662, 16851715}, {120663, 16851971}, {120664, 16852227},
2405
  {120665, 16852483}, {120666, 16852739}, {120667, 16852995}, {120668, 16853251},
2406
  {120669, 16853507}, {120670, 16846851}, {120671, 16853763}, {120672, 16854019},
2407
  {120673, 16786179}, {120674, 16854275}, {120675, 16854531}, {120676, 16854787},
2408
  {120677, 16855043}, {120678, 16855299}, {120679, 16853507}, {120680, 16855555},
2409
  {120681, 16855811}, {120682, 16856067}, {120683, 16856323}, {120684, 16856579},
2410
  {120685, 16856835}, {120686, 16857091}, {120687, 17945347}, {120688, 16851715},
2411
  {120689, 16851971}, {120690, 16852227}, {120691, 16852483}, {120692, 16852739},
2412
  {120693, 16852995}, {120694, 16853251}, {120695, 16853507}, {120696, 16846851},
2413
  {120697, 16853763}, {120698, 16854019}, {120699, 16786179}, {120700, 16854275},
2414
  {120701, 16854531}, {120702, 16854787}, {120703, 16855043}, {120704, 16855299},
2415
  {120705, 16855555}, {120707, 16855811}, {120708, 16856067}, {120709, 16856323},
2416
  {120710, 16856579}, {120711, 16856835}, {120712, 16857091}, {120713, 17945603},
2417
  {120714, 16852739}, {120715, 16853507}, {120716, 16853763}, {120717, 16856323},
2418
  {120718, 16855299}, {120719, 16855043}, {120720, 16851715}, {120721, 16851971},
2419
  {120722, 16852227}, {120723, 16852483}, {120724, 16852739}, {120725, 16852995},
2420
  {120726, 16853251}, {120727, 16853507}, {120728, 16846851}, {120729, 16853763},
2421
  {120730, 16854019}, {120731, 16786179}, {120732, 16854275}, {120733, 16854531},
2422
  {120734, 16854787}, {120735, 16855043}, {120736, 16855299}, {120737, 16853507},
2423
  {120738, 16855555}, {120739, 16855811}, {120740, 16856067}, {120741, 16856323},
2424
  {120742, 16856579}, {120743, 16856835}, {120744, 16857091}, {120745, 17945347},
2425
  {120746, 16851715}, {120747, 16851971}, {120748, 16852227}, {120749, 16852483},
2426
  {120750, 16852739}, {120751, 16852995}, {120752, 16853251}, {120753, 16853507},
2427
  {120754, 16846851}, {120755, 16853763}, {120756, 16854019}, {120757, 16786179},
2428
  {120758, 16854275}, {120759, 16854531}, {120760, 16854787}, {120761, 16855043},
2429
  {120762, 16855299}, {120763, 16855555}, {120765, 16855811}, {120766, 16856067},
2430
  {120767, 16856323}, {120768, 16856579}, {120769, 16856835}, {120770, 16857091},
2431
  {120771, 17945603}, {120772, 16852739}, {120773, 16853507}, {120774, 16853763},
2432
  {120775, 16856323}, {120776, 16855299}, {120777, 16855043}, {120778, 16858627},
2433
  {120780, 2}, {120782, 17035523}, {120783, 16786947}, {120784, 16785155},
2434
  {120785, 16785411}, {120786, 16787715}, {120787, 17035779}, {120788, 17036035},
2435
  {120789, 17036291}, {120790, 17036547}, {120791, 17036803}, {120792, 17035523},
2436
  {120793, 16786947}, {120794, 16785155}, {120795, 16785411}, {120796, 16787715},
2437
  {120797, 17035779}, {120798, 17036035}, {120799, 17036291}, {120800, 17036547},
2438
  {120801, 17036803}, {120802, 17035523}, {120803, 16786947}, {120804, 16785155},
2439
  {120805, 16785411}, {120806, 16787715}, {120807, 17035779}, {120808, 17036035},
2440
  {120809, 17036291}, {120810, 17036547}, {120811, 17036803}, {120812, 17035523},
2441
  {120813, 16786947}, {120814, 16785155}, {120815, 16785411}, {120816, 16787715},
2442
  {120817, 17035779}, {120818, 17036035}, {120819, 17036291}, {120820, 17036547},
2443
  {120821, 17036803}, {120822, 17035523}, {120823, 16786947}, {120824, 16785155},
2444
  {120825, 16785411}, {120826, 16787715}, {120827, 17035779}, {120828, 17036035},
2445
  {120829, 17036291}, {120830, 17036547}, {120831, 17036803}, {120832, 1},
2446
  {121484, 2}, {121499, 1}, {121504, 2}, {121505, 1},
2447
  {121520, 2}, {122624, 1}, {122655, 2}, {122661, 1},
2448
  {122667, 2}, {122880, 1}, {122887, 2}, {122888, 1},
2449
  {122905, 2}, {122907, 1}, {122914, 2}, {122915, 1},
2450
  {122917, 2}, {122918, 1}, {122923, 2}, {122928, 16866563},
2451
  {122929, 16866819}, {122930, 16867075}, {122931, 16867331}, {122932, 16867587},
2452
  {122933, 16867843}, {122934, 16868099}, {122935, 16868355}, {122936, 16868611},
2453
  {122937, 16869123}, {122938, 16869379}, {122939, 16869635}, {122940, 16870147},
2454
  {122941, 16870403}, {122942, 16870659}, {122943, 16870915}, {122944, 16871171},
2455
  {122945, 16871427}, {122946, 16871683}, {122947, 16871939}, {122948, 16872195},
2456
  {122949, 16872451}, {122950, 16872707}, {122951, 16873475}, {122952, 16873987},
2457
  {122953, 16874243}, {122954, 17495299}, {122955, 16888835}, {122956, 16864003},
2458
  {122957, 16864515}, {122958, 16890883}, {122959, 16883715}, {122960, 17945859},
2459
  {122961, 16866563}, {122962, 16866819}, {122963, 16867075}, {122964, 16867331},
2460
  {122965, 16867587}, {122966, 16867843}, {122967, 16868099}, {122968, 16868355},
2461
  {122969, 16868611}, {122970, 16869123}, {122971, 16869379}, {122972, 16870147},
2462
  {122973, 16870403}, {122974, 16870915}, {122975, 16871427}, {122976, 16871683},
2463
  {122977, 16871939}, {122978, 16872195}, {122979, 16872451}, {122980, 16872707},
2464
  {122981, 16873219}, {122982, 16873475}, {122983, 16879875}, {122984, 16864003},
2465
  {122985, 16863747}, {122986, 16866307}, {122987, 16883203}, {122988, 17490435},
2466
  {122989, 16883971}, {122990, 2}, {123023, 1}, {123024, 2},
2467
  {123136, 1}, {123181, 2}, {123184, 1}, {123198, 2},
2468
  {123200, 1}, {123210, 2}, {123214, 1}, {123216, 2},
2469
  {123536, 1}, {123567, 2}, {123584, 1}, {123642, 2},
2470
  {123647, 1}, {123648, 2}, {124112, 1}, {124154, 2},
2471
  {124896, 1}, {124903, 2}, {124904, 1}, {124908, 2},
2472
  {124909, 1}, {124911, 2}, {124912, 1}, {124927, 2},
2473
  {124928, 1}, {125125, 2}, {125127, 1}, {125143, 2},
2474
  {125184, 17946115}, {125185, 17946371}, {125186, 17946627}, {125187, 17946883},
2475
  {125188, 17947139}, {125189, 17947395}, {125190, 17947651}, {125191, 17947907},
2476
  {125192, 17948163}, {125193, 17948419}, {125194, 17948675}, {125195, 17948931},
2477
  {125196, 17949187}, {125197, 17949443}, {125198, 17949699}, {125199, 17949955},
2478
  {125200, 17950211}, {125201, 17950467}, {125202, 17950723}, {125203, 17950979},
2479
  {125204, 17951235}, {125205, 17951491}, {125206, 17951747}, {125207, 17952003},
2480
  {125208, 17952259}, {125209, 17952515}, {125210, 17952771}, {125211, 17953027},
2481
  {125212, 17953283}, {125213, 17953539}, {125214, 17953795}, {125215, 17954051},
2482
  {125216, 17954307}, {125217, 17954563}, {125218, 1}, {125260, 2},
2483
  {125264, 1}, {125274, 2}, {125278, 1}, {125280, 2},
2484
  {126065, 1}, {126133, 2}, {126209, 1}, {126270, 2},
2485
  {126464, 16910339}, {126465, 17683715}, {126466, 17681923}, {126467, 17834499},
2486
  {126468, 2}, {126469, 16910851}, {126470, 17731587}, {126471, 17682435},
2487
  {126472, 17700099}, {126473, 16911875}, {126474, 17708803}, {126475, 17711107},
2488
  {126476, 17682947}, {126477, 17718019}, {126478, 17694979}, {126479, 17701635},
2489
  {126480, 17703683}, {126481, 17697027}, {126482, 17706755}, {126483, 17725187},
2490
  {126484, 17745155}, {126485, 17686787}, {126486, 17689859}, {126487, 17684995},
2491
  {126488, 17724675}, {126489, 17698051}, {126490, 17701123}, {126491, 17702659},
2492
  {126492, 17954819}, {126493, 17673475}, {126494, 17955075}, {126495, 17955331},
2493
  {126496, 2}, {126497, 17683715}, {126498, 17681923}, {126499, 2},
2494
  {126500, 17721091}, {126501, 2}, {126503, 17682435}, {126504, 2},
2495
  {126505, 16911875}, {126506, 17708803}, {126507, 17711107}, {126508, 17682947},
2496
  {126509, 17718019}, {126510, 17694979}, {126511, 17701635}, {126512, 17703683},
2497
  {126513, 17697027}, {126514, 17706755}, {126515, 2}, {126516, 17745155},
2498
  {126517, 17686787}, {126518, 17689859}, {126519, 17684995}, {126520, 2},
2499
  {126521, 17698051}, {126522, 2}, {126523, 17702659}, {126524, 2},
2500
  {126530, 17681923}, {126531, 2}, {126535, 17682435}, {126536, 2},
2501
  {126537, 16911875}, {126538, 2}, {126539, 17711107}, {126540, 2},
2502
  {126541, 17718019}, {126542, 17694979}, {126543, 17701635}, {126544, 2},
2503
  {126545, 17697027}, {126546, 17706755}, {126547, 2}, {126548, 17745155},
2504
  {126549, 2}, {126551, 17684995}, {126552, 2}, {126553, 17698051},
2505
  {126554, 2}, {126555, 17702659}, {126556, 2}, {126557, 17673475},
2506
  {126558, 2}, {126559, 17955331}, {126560, 2}, {126561, 17683715},
2507
  {126562, 17681923}, {126563, 2}, {126564, 17721091}, {126565, 2},
2508
  {126567, 17682435}, {126568, 17700099}, {126569, 16911875}, {126570, 17708803},
2509
  {126571, 2}, {126572, 17682947}, {126573, 17718019}, {126574, 17694979},
2510
  {126575, 17701635}, {126576, 17703683}, {126577, 17697027}, {126578, 17706755},
2511
  {126579, 2}, {126580, 17745155}, {126581, 17686787}, {126582, 17689859},
2512
  {126583, 17684995}, {126584, 2}, {126585, 17698051}, {126586, 17701123},
2513
  {126587, 17702659}, {126588, 17954819}, {126589, 2}, {126590, 17955075},
2514
  {126591, 2}, {126592, 16910339}, {126593, 17683715}, {126594, 17681923},
2515
  {126595, 17834499}, {126596, 17721091}, {126597, 16910851}, {126598, 17731587},
2516
  {126599, 17682435}, {126600, 17700099}, {126601, 16911875}, {126602, 2},
2517
  {126603, 17711107}, {126604, 17682947}, {126605, 17718019}, {126606, 17694979},
2518
  {126607, 17701635}, {126608, 17703683}, {126609, 17697027}, {126610, 17706755},
2519
  {126611, 17725187}, {126612, 17745155}, {126613, 17686787}, {126614, 17689859},
2520
  {126615, 17684995}, {126616, 17724675}, {126617, 17698051}, {126618, 17701123},
2521
  {126619, 17702659}, {126620, 2}, {126625, 17683715}, {126626, 17681923},
2522
  {126627, 17834499}, {126628, 2}, {126629, 16910851}, {126630, 17731587},
2523
  {126631, 17682435}, {126632, 17700099}, {126633, 16911875}, {126634, 2},
2524
  {126635, 17711107}, {126636, 17682947}, {126637, 17718019}, {126638, 17694979},
2525
  {126639, 17701635}, {126640, 17703683}, {126641, 17697027}, {126642, 17706755},
2526
  {126643, 17725187}, {126644, 17745155}, {126645, 17686787}, {126646, 17689859},
2527
  {126647, 17684995}, {126648, 17724675}, {126649, 17698051}, {126650, 17701123},
2528
  {126651, 17702659}, {126652, 2}, {126704, 1}, {126706, 2},
2529
  {126976, 1}, {127020, 2}, {127024, 1}, {127124, 2},
2530
  {127136, 1}, {127151, 2}, {127153, 1}, {127168, 2},
2531
  {127169, 1}, {127184, 2}, {127185, 1}, {127222, 2},
2532
  {127233, 34732803}, {127234, 34733315}, {127235, 34733827}, {127236, 34734339},
2533
  {127237, 34734851}, {127238, 34735363}, {127239, 34735875}, {127240, 34736387},
2534
  {127241, 34736899}, {127242, 34737411}, {127243, 1}, {127248, 50644995},
2535
  {127249, 50645763}, {127250, 50646531}, {127251, 50647299}, {127252, 50648067},
2536
  {127253, 50648835}, {127254, 50649603}, {127255, 50650371}, {127256, 50651139},
2537
  {127257, 50651907}, {127258, 50652675}, {127259, 50653443}, {127260, 50654211},
2538
  {127261, 50654979}, {127262, 50655747}, {127263, 50656515}, {127264, 50657283},
2539
  {127265, 50658051}, {127266, 50658819}, {127267, 50659587}, {127268, 50660355},
2540
  {127269, 50661123}, {127270, 50661891}, {127271, 50662659}, {127272, 50663427},
2541
  {127273, 50664195}, {127274, 51515139}, {127275, 16777731}, {127276, 16781571},
2542
  {127277, 33554947}, {127278, 34738691}, {127279, 1}, {127280, 16777219},
2543
  {127281, 16777475}, {127282, 16777731}, {127283, 16777987}, {127284, 16778243},
2544
  {127285, 16778499}, {127286, 16778755}, {127287, 16779011}, {127288, 16779267},
2545
  {127289, 16779523}, {127290, 16779779}, {127291, 16780035}, {127292, 16780291},
2546
  {127293, 16780547}, {127294, 16780803}, {127295, 16781059}, {127296, 16781315},
2547
  {127297, 16781571}, {127298, 16781827}, {127299, 16782083}, {127300, 16782339},
2548
  {127301, 16782595}, {127302, 16782851}, {127303, 16783107}, {127304, 16783363},
2549
  {127305, 16783619}, {127306, 34739203}, {127307, 34226691}, {127308, 34739715},
2550
  {127309, 33752579}, {127310, 51517443}, {127311, 34740995}, {127312, 1},
2551
  {127338, 34209539}, {127339, 34189571}, {127340, 34741507}, {127341, 1},
2552
  {127376, 34742019}, {127377, 1}, {127406, 2}, {127462, 1},
2553
  {127488, 34742531}, {127489, 34743043}, {127490, 17307907}, {127491, 2},
2554
  {127504, 17157891}, {127505, 17966339}, {127506, 17966595}, {127507, 17351683},
2555
  {127508, 17143299}, {127509, 17966851}, {127510, 17967107}, {127511, 17225475},
2556
  {127512, 17967363}, {127513, 17967619}, {127514, 17967875}, {127515, 17584643},
2557
  {127516, 17968131}, {127517, 17968387}, {127518, 17968643}, {127519, 17968899},
2558
  {127520, 17969155}, {127521, 17969411}, {127522, 17167107}, {127523, 17969667},
2559
  {127524, 17969923}, {127525, 17970179}, {127526, 17970435}, {127527, 17970691},
2560
  {127528, 17970947}, {127529, 17141763}, {127530, 17223427}, {127531, 17971203},
2561
  {127532, 17288707}, {127533, 17224195}, {127534, 17288963}, {127535, 17971459},
2562
  {127536, 17181443}, {127537, 17971715}, {127538, 17971971}, {127539, 17972227},
2563
  {127540, 17972483}, {127541, 17972739}, {127542, 17264387}, {127543, 17160451},
2564
  {127544, 17972995}, {127545, 17973251}, {127546, 17973507}, {127547, 17973763},
2565
  {127548, 2}, {127552, 51528451}, {127553, 51529219}, {127554, 51529987},
2566
  {127555, 51530755}, {127556, 51531523}, {127557, 51532291}, {127558, 51533059},
2567
  {127559, 51533827}, {127560, 51534595}, {127561, 2}, {127568, 17980931},
2568
  {127569, 17981187}, {127570, 2}, {127584, 1}, {127590, 2},
2569
  {127744, 1}, {128728, 2}, {128732, 1}, {128749, 2},
2570
  {128752, 1}, {128765, 2}, {128768, 1}, {128887, 2},
2571
  {128891, 1}, {128986, 2}, {128992, 1}, {129004, 2},
2572
  {129008, 1}, {129009, 2}, {129024, 1}, {129036, 2},
2573
  {129040, 1}, {129096, 2}, {129104, 1}, {129114, 2},
2574
  {129120, 1}, {129160, 2}, {129168, 1}, {129198, 2},
2575
  {129200, 1}, {129202, 2}, {129280, 1}, {129620, 2},
2576
  {129632, 1}, {129646, 2}, {129648, 1}, {129661, 2},
2577
  {129664, 1}, {129673, 2}, {129680, 1}, {129726, 2},
2578
  {129727, 1}, {129734, 2}, {129742, 1}, {129756, 2},
2579
  {129760, 1}, {129769, 2}, {129776, 1}, {129785, 2},
2580
  {129792, 1}, {129939, 2}, {129940, 1}, {129995, 2},
2581
  {130032, 17035523}, {130033, 16786947}, {130034, 16785155}, {130035, 16785411},
2582
  {130036, 16787715}, {130037, 17035779}, {130038, 17036035}, {130039, 17036291},
2583
  {130040, 17036547}, {130041, 17036803}, {130042, 2}, {131072, 1},
2584
  {173792, 2}, {173824, 1}, {177978, 2}, {177984, 1},
2585
  {178206, 2}, {178208, 1}, {183970, 2}, {183984, 1},
2586
  {191457, 2}, {194560, 17981443}, {194561, 17981699}, {194562, 17981955},
2587
  {194563, 17982211}, {194564, 17982467}, {194565, 17608451}, {194566, 17982723},
2588
  {194567, 17982979}, {194568, 17983235}, {194569, 17983491}, {194570, 17608707},
2589
  {194571, 17983747}, {194572, 17984003}, {194573, 17984259}, {194574, 17608963},
2590
  {194575, 17984515}, {194576, 17984771}, {194577, 17985027}, {194578, 17985283},
2591
  {194579, 17985539}, {194580, 17985795}, {194581, 17968643}, {194582, 17986051},
2592
  {194583, 17986307}, {194584, 17986563}, {194585, 17986819}, {194586, 17987075},
2593
  {194587, 17623043}, {194588, 17987331}, {194589, 17145859}, {194590, 17987587},
2594
  {194591, 17987843}, {194592, 17988099}, {194593, 17988355}, {194594, 17973251},
2595
  {194595, 17988611}, {194596, 17988867}, {194597, 17624323}, {194598, 17609219},
2596
  {194599, 17609475}, {194600, 17624579}, {194601, 17989123}, {194602, 17989379},
2597
  {194603, 17562883}, {194604, 17989635}, {194605, 17609731}, {194606, 17989891},
2598
  {194607, 17990147}, {194608, 17990403}, {194609, 17990659}, {194612, 17990915},
2599
  {194613, 17991171}, {194614, 17991427}, {194615, 17991683}, {194616, 17991939},
2600
  {194617, 17992195}, {194618, 17992451}, {194619, 17992707}, {194620, 17992963},
2601
  {194621, 17993219}, {194622, 17993475}, {194623, 17993731}, {194624, 17993987},
2602
  {194625, 17994243}, {194626, 17994499}, {194627, 17994755}, {194628, 17995011},
2603
  {194629, 17995267}, {194631, 17625091}, {194632, 17995523}, {194633, 17995779},
2604
  {194634, 17996035}, {194635, 17996291}, {194636, 17610243}, {194637, 17996547},
2605
  {194638, 17996803}, {194639, 17997059}, {194640, 17600003}, {194641, 17997315},
2606
  {194642, 17997571}, {194643, 17997827}, {194644, 17998083}, {194645, 17998339},
2607
  {194646, 17998595}, {194647, 17998851}, {194648, 17999107}, {194649, 17999363},
2608
  {194650, 17999619}, {194651, 17999875}, {194652, 18000131}, {194653, 17966851},
2609
  {194654, 18000387}, {194655, 18000643}, {194656, 18000899}, {194657, 18001155},
2610
  {194658, 18001411}, {194659, 18001667}, {194660, 18001923}, {194661, 18002179},
2611
  {194662, 18002435}, {194663, 18002691}, {194664, 2}, {194665, 18002947},
2612
  {194666, 18003203}, {194668, 18003459}, {194669, 18003715}, {194670, 18003971},
2613
  {194671, 17561859}, {194672, 18004227}, {194673, 18004483}, {194674, 18004739},
2614
  {194675, 18004995}, {194676, 2}, {194677, 17152515}, {194678, 18005251},
2615
  {194679, 18005507}, {194680, 17153027}, {194681, 18005763}, {194682, 18006019},
2616
  {194683, 18006275}, {194684, 18006531}, {194685, 18006787}, {194686, 18007043},
2617
  {194687, 18007299}, {194688, 18007555}, {194689, 18007811}, {194690, 18008067},
2618
  {194691, 18008323}, {194692, 18008579}, {194693, 18008835}, {194694, 18009091},
2619
  {194695, 18009347}, {194696, 18009603}, {194697, 18009859}, {194698, 18010115},
2620
  {194699, 18010371}, {194700, 18010627}, {194701, 18010883}, {194702, 17548547},
2621
  {194703, 18011139}, {194704, 17155587}, {194705, 18011395}, {194707, 18011651},
2622
  {194708, 18011907}, {194710, 18012163}, {194711, 18012419}, {194712, 18012675},
2623
  {194713, 18012931}, {194714, 18013187}, {194715, 18013443}, {194716, 18013699},
2624
  {194717, 18013955}, {194718, 18014211}, {194719, 18014467}, {194720, 18014723},
2625
  {194721, 18014979}, {194722, 18015235}, {194723, 17611523}, {194724, 18015491},
2626
  {194725, 18015747}, {194726, 18016003}, {194727, 18016259}, {194728, 17628163},
2627
  {194729, 18016259}, {194730, 18016515}, {194731, 17612035}, {194732, 18016771},
2628
  {194733, 18017027}, {194734, 18017283}, {194735, 18017539}, {194736, 17612291},
2629
  {194737, 17541635}, {194738, 17414915}, {194739, 18017795}, {194740, 18018051},
2630
  {194741, 18018307}, {194742, 18018563}, {194743, 18018819}, {194744, 18019075},
2631
  {194745, 18019331}, {194746, 18019587}, {194747, 18019843}, {194748, 18020099},
2632
  {194749, 18020355}, {194750, 18020611}, {194751, 18020867}, {194752, 18021123},
2633
  {194753, 18021379}, {194754, 18021635}, {194755, 18021891}, {194756, 18022147},
2634
  {194757, 18022403}, {194758, 18022659}, {194759, 18022915}, {194760, 17612547},
2635
  {194761, 18023171}, {194762, 18023427}, {194763, 18023683}, {194764, 18023939},
2636
  {194765, 18024195}, {194766, 18024451}, {194767, 17613059}, {194768, 18024707},
2637
  {194769, 18024963}, {194770, 18025219}, {194771, 18025475}, {194772, 18025731},
2638
  {194773, 18025987}, {194774, 18026243}, {194775, 18026499}, {194776, 17548803},
2639
  {194777, 17630211}, {194778, 18026755}, {194779, 18027011}, {194780, 18027267},
2640
  {194781, 18027523}, {194782, 18027779}, {194783, 18028035}, {194784, 18028291},
2641
  {194785, 18028547}, {194786, 17613315}, {194787, 18028803}, {194788, 18029059},
2642
  {194789, 18029315}, {194790, 18029571}, {194791, 17640963}, {194792, 18029827},
2643
  {194793, 18030083}, {194794, 18030339}, {194795, 18030595}, {194796, 18030851},
2644
  {194797, 18031107}, {194798, 18031363}, {194799, 18031619}, {194800, 18031875},
2645
  {194801, 18032131}, {194802, 18032387}, {194803, 18032643}, {194804, 18032899},
2646
  {194805, 17566211}, {194806, 18033155}, {194807, 18033411}, {194808, 18033667},
2647
  {194809, 18033923}, {194810, 18034179}, {194811, 18034435}, {194812, 18034691},
2648
  {194813, 18034947}, {194814, 18035203}, {194815, 18035459}, {194816, 18035715},
2649
  {194817, 17613571}, {194818, 17587203}, {194819, 18035971}, {194820, 18036227},
2650
  {194821, 18036483}, {194822, 18036739}, {194823, 18036995}, {194824, 18037251},
2651
  {194825, 18037507}, {194826, 18037763}, {194827, 17630979}, {194828, 18038019},
2652
  {194829, 18038275}, {194830, 18038531}, {194831, 18038787}, {194832, 18039043},
2653
  {194833, 18039299}, {194834, 18039555}, {194835, 18039811}, {194836, 17631235},
2654
  {194837, 18040067}, {194838, 18040323}, {194839, 18040579}, {194840, 18040835},
2655
  {194841, 18041091}, {194842, 18041347}, {194843, 18041603}, {194844, 18041859},
2656
  {194845, 18042115}, {194846, 18042371}, {194847, 2}, {194848, 18042627},
2657
  {194849, 17631747}, {194850, 18042883}, {194851, 18043139}, {194852, 18043395},
2658
  {194853, 18043651}, {194854, 18043907}, {194855, 18044163}, {194856, 18044419},
2659
  {194857, 18044675}, {194858, 18044931}, {194859, 18045187}, {194860, 18045443},
2660
  {194862, 18045699}, {194863, 18045955}, {194864, 17632259}, {194865, 18046211},
2661
  {194866, 18046467}, {194867, 18046723}, {194868, 18046979}, {194869, 18047235},
2662
  {194870, 18047491}, {194871, 18047747}, {194872, 17562627}, {194873, 18048003},
2663
  {194874, 18048259}, {194875, 18048515}, {194876, 18048771}, {194877, 18049027},
2664
  {194878, 18049283}, {194879, 18049539}, {194880, 17633795}, {194881, 18049795},
2665
  {194882, 18050051}, {194883, 18050307}, {194884, 18050563}, {194885, 18050819},
2666
  {194886, 18051075}, {194888, 17634051}, {194889, 17641475}, {194890, 18051331},
2667
  {194891, 18051587}, {194892, 18051843}, {194893, 18052099}, {194894, 18052355},
2668
  {194895, 17553155}, {194896, 17634563}, {194897, 18052611}, {194898, 18052867},
2669
  {194899, 17616131}, {194900, 18053123}, {194901, 18053379}, {194902, 17605123},
2670
  {194903, 18053635}, {194904, 18053891}, {194905, 17616899}, {194906, 18054147},
2671
  {194907, 18054403}, {194908, 18054659}, {194909, 18054915}, {194911, 2},
2672
  {194912, 18055171}, {194913, 18055427}, {194914, 18055683}, {194915, 18055939},
2673
  {194916, 18056195}, {194917, 18056451}, {194918, 18056707}, {194919, 18056963},
2674
  {194920, 18057219}, {194921, 18057475}, {194922, 18057731}, {194923, 18057987},
2675
  {194924, 18058243}, {194925, 18058499}, {194926, 18058755}, {194927, 18059011},
2676
  {194928, 18059267}, {194929, 18059523}, {194930, 18059779}, {194931, 18060035},
2677
  {194932, 18060291}, {194933, 18060547}, {194934, 18060803}, {194935, 18061059},
2678
  {194936, 18061315}, {194937, 18061571}, {194938, 17618435}, {194939, 18061827},
2679
  {194940, 18062083}, {194941, 18062339}, {194942, 18062595}, {194943, 18062851},
2680
  {194944, 18063107}, {194945, 18063363}, {194946, 18063619}, {194947, 18063875},
2681
  {194948, 18064131}, {194949, 18064387}, {194950, 18064643}, {194951, 18064899},
2682
  {194952, 18065155}, {194953, 18065411}, {194954, 18065667}, {194955, 18011651},
2683
  {194956, 18065923}, {194957, 18066179}, {194958, 18066435}, {194959, 18066691},
2684
  {194960, 18066947}, {194961, 18067203}, {194962, 18067459}, {194963, 18067715},
2685
  {194964, 18067971}, {194965, 18068227}, {194966, 18068483}, {194967, 18068739},
2686
  {194968, 17566979}, {194969, 18068995}, {194970, 18069251}, {194971, 18069507},
2687
  {194972, 18069763}, {194973, 18070019}, {194974, 18070275}, {194975, 17619203},
2688
  {194976, 18070531}, {194977, 18070787}, {194978, 18071043}, {194979, 18071299},
2689
  {194980, 18071555}, {194981, 18071811}, {194982, 18072067}, {194983, 18072323},
2690
  {194984, 18072579}, {194985, 18072835}, {194986, 18073091}, {194987, 18073347},
2691
  {194988, 18073603}, {194989, 18073859}, {194990, 18074115}, {194991, 18074371},
2692
  {194992, 18074627}, {194993, 18074883}, {194994, 18075139}, {194995, 18075395},
2693
  {194996, 17551875}, {194997, 18075651}, {194998, 18075907}, {194999, 18076163},
2694
  {195000, 18076419}, {195001, 18076675}, {195002, 18076931}, {195003, 17636355},
2695
  {195004, 18077187}, {195005, 18077443}, {195006, 18077699}, {195007, 2},
2696
  {195008, 18077955}, {195009, 18078211}, {195010, 18078467}, {195011, 18078723},
2697
  {195012, 17178627}, {195013, 18078979}, {195014, 18079235}, {195015, 18079491},
2698
  {195016, 18079747}, {195017, 18080003}, {195018, 18080259}, {195019, 18080515},
2699
  {195020, 18080771}, {195021, 18081027}, {195022, 18081283}, {195023, 18081539},
2700
  {195024, 17637635}, {195025, 17637891}, {195026, 17180419}, {195027, 18081795},
2701
  {195028, 18082051}, {195029, 18082307}, {195030, 18082563}, {195031, 18082819},
2702
  {195032, 18083075}, {195033, 18083331}, {195034, 18083587}, {195035, 18083843},
2703
  {195036, 18084099}, {195037, 18084355}, {195038, 18084611}, {195039, 17638147},
2704
  {195040, 18084867}, {195041, 18085123}, {195042, 18085379}, {195043, 18085635},
2705
  {195044, 18085891}, {195045, 18086147}, {195046, 18086403}, {195047, 18086659},
2706
  {195048, 18086915}, {195049, 18087171}, {195050, 18087427}, {195051, 18087683},
2707
  {195052, 18087939}, {195053, 18088195}, {195054, 18088451}, {195055, 18088707},
2708
  {195056, 18088963}, {195057, 18089219}, {195058, 18089475}, {195059, 18089731},
2709
  {195060, 18089987}, {195061, 18090243}, {195062, 18090499}, {195063, 18090755},
2710
  {195064, 18091011}, {195065, 18091267}, {195066, 18091523}, {195067, 18091779},
2711
  {195068, 18092035}, {195069, 18092291}, {195070, 17639683}, {195072, 18092547},
2712
  {195073, 18092803}, {195074, 18093059}, {195075, 18093315}, {195076, 18093571},
2713
  {195077, 18093827}, {195078, 18094083}, {195079, 18094339}, {195080, 18094595},
2714
  {195081, 18094851}, {195082, 17639939}, {195083, 18095107}, {195084, 18095363},
2715
  {195085, 18095619}, {195086, 18095875}, {195087, 18096131}, {195088, 18096387},
2716
  {195089, 18096643}, {195090, 18096899}, {195091, 18097155}, {195092, 18097411},
2717
  {195093, 17192707}, {195094, 18097667}, {195095, 17193731}, {195096, 18097923},
2718
  {195097, 18098179}, {195098, 18098435}, {195099, 18098691}, {195100, 17195011},
2719
  {195101, 18098947}, {195102, 2}, {196608, 1}, {201547, 2},
2720
  {201552, 1}, {205744, 2}, {917760, 0}, {918000, 2}
2721
};
2722
2723
2724
} // namespace ada::idna
2725
#endif // ADA_IDNA_TABLES_H
2726
2727
/* end file src/mapping_tables.cpp */
2728
2729
namespace ada::idna {
2730
2731
// This can be greatly accelerated. For now we just use a simply
2732
// binary search. In practice, you should *not* do that.
2733
174k
uint32_t find_range_index(uint32_t key) {
2734
  ////////////////
2735
  // This could be implemented with std::lower_bound, but we roll our own
2736
  // because we want to allow further optimizations in the future.
2737
  ////////////////
2738
174k
  uint32_t len = std::size(table);
2739
174k
  uint32_t low = 0;
2740
174k
  uint32_t high = len - 1;
2741
2.32M
  while (low <= high) {
2742
2.20M
    uint32_t middle_index = (low + high) >> 1;  // cannot overflow
2743
2.20M
    uint32_t middle_value = table[middle_index][0];
2744
2.20M
    if (middle_value < key) {
2745
668k
      low = middle_index + 1;
2746
1.53M
    } else if (middle_value > key) {
2747
1.47M
      high = middle_index - 1;
2748
1.47M
    } else {
2749
54.0k
      return middle_index;  // perfect match
2750
54.0k
    }
2751
2.20M
  }
2752
120k
  return low == 0 ? 0 : low - 1;
2753
174k
}
2754
2755
0
bool ascii_has_upper_case(char* input, size_t length) {
2756
0
  auto broadcast = [](uint8_t v) -> uint64_t {
2757
0
    return 0x101010101010101ull * v;
2758
0
  };
2759
0
  uint64_t broadcast_80 = broadcast(0x80);
2760
0
  uint64_t broadcast_Ap = broadcast(128 - 'A');
2761
0
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2762
0
  size_t i = 0;
2763
2764
0
  uint64_t runner{0};
2765
2766
0
  for (; i + 7 < length; i += 8) {
2767
0
    uint64_t word{};
2768
0
    memcpy(&word, input + i, sizeof(word));
2769
0
    runner |= (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80);
2770
0
  }
2771
0
  if (i < length) {
2772
0
    uint64_t word{};
2773
0
    memcpy(&word, input + i, length - i);
2774
0
    runner |= (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80);
2775
0
  }
2776
0
  return runner != 0;
2777
0
}
2778
2779
14.2k
void ascii_map(char* input, size_t length) {
2780
42.7k
  auto broadcast = [](uint8_t v) -> uint64_t {
2781
42.7k
    return 0x101010101010101ull * v;
2782
42.7k
  };
2783
14.2k
  uint64_t broadcast_80 = broadcast(0x80);
2784
14.2k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
2785
14.2k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2786
14.2k
  size_t i = 0;
2787
2788
39.6k
  for (; i + 7 < length; i += 8) {
2789
25.3k
    uint64_t word{};
2790
25.3k
    memcpy(&word, input + i, sizeof(word));
2791
25.3k
    word ^=
2792
25.3k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2793
25.3k
    memcpy(input + i, &word, sizeof(word));
2794
25.3k
  }
2795
14.2k
  if (i < length) {
2796
12.2k
    uint64_t word{};
2797
12.2k
    memcpy(&word, input + i, length - i);
2798
12.2k
    word ^=
2799
12.2k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2800
12.2k
    memcpy(input + i, &word, length - i);
2801
12.2k
  }
2802
14.2k
}
2803
2804
// Map the characters according to IDNA, returning the empty string on error.
2805
16.6k
std::u32string map(std::u32string_view input) {
2806
  //  [Map](https://www.unicode.org/reports/tr46/#ProcessingStepMap).
2807
  //  For each code point in the domain_name string, look up the status
2808
  //  value in Section 5, [IDNA Mapping
2809
  //  Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table),
2810
  //  and take the following actions:
2811
  //    * disallowed: Leave the code point unchanged in the string, and
2812
  //    record that there was an error.
2813
  //    * ignored: Remove the code point from the string. This is
2814
  //    equivalent to mapping the code point to an empty string.
2815
  //    * mapped: Replace the code point in the string by the value for
2816
  //    the mapping in Section 5, [IDNA Mapping
2817
  //    Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table).
2818
  //    * valid: Leave the code point unchanged in the string.
2819
16.6k
  static std::u32string error = U"";
2820
16.6k
  std::u32string answer;
2821
16.6k
  answer.reserve(input.size());
2822
174k
  for (char32_t x : input) {
2823
174k
    size_t index = find_range_index(x);
2824
174k
    uint32_t descriptor = table[index][1];
2825
174k
    uint8_t code = uint8_t(descriptor);
2826
174k
    switch (code) {
2827
227
      case 0:
2828
227
        break;  // nothing to do, ignored
2829
126k
      case 1:
2830
126k
        answer.push_back(x);  // valid, we just copy it to output
2831
126k
        break;
2832
430
      case 2:
2833
430
        return error;  // disallowed
2834
      // case 3 :
2835
47.2k
      default:
2836
        // We have a mapping
2837
47.2k
        {
2838
47.2k
          size_t char_count = (descriptor >> 24);
2839
47.2k
          uint16_t char_index = uint16_t(descriptor >> 8);
2840
269k
          for (size_t idx = char_index; idx < char_index + char_count; idx++) {
2841
221k
            answer.push_back(mappings[idx]);
2842
221k
          }
2843
47.2k
        }
2844
174k
    }
2845
174k
  }
2846
16.2k
  return answer;
2847
16.6k
}
2848
}  // namespace ada::idna
2849
/* end file src/mapping.cpp */
2850
/* begin file src/normalization.cpp */
2851
/* begin file src/normalization_tables.cpp */
2852
// IDNA  15.0.0
2853
2854
// clang-format off
2855
#ifndef ADA_IDNA_NORMALIZATION_TABLES_H
2856
#define ADA_IDNA_NORMALIZATION_TABLES_H
2857
#include <cstdint>
2858
2859
/**
2860
 * Unicode Standard Annex #15
2861
 *
2862
 * UNICODE NORMALIZATION FORMS
2863
 * https://www.unicode.org/reports/tr15/
2864
 *
2865
 * See https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/data/data_norm.h for reference.
2866
 */
2867
2868
namespace ada::idna {
2869
2870
const uint8_t decomposition_index[4352] = {
2871
    0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  9,  10, 11, 12, 13, 14, 15, 7,  7,
2872
    7,  7,  7,  7,  7,  7,  7,  7,  16, 7,  17, 18, 19, 20, 21, 22, 23, 24, 7,
2873
    7,  7,  7,  7,  25, 7,  26, 27, 28, 29, 30, 31, 32, 33, 7,  7,  7,  7,  7,
2874
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2875
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2876
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2877
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2878
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2879
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  34, 35, 7,  7,  7,
2880
    36, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2881
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2882
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2883
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2884
    7,  7,  37, 38, 39, 40, 41, 42, 43, 7,  7,  7,  7,  7,  7,  7,  44, 7,  7,
2885
    7,  7,  7,  7,  7,  7,  45, 46, 7,  47, 48, 49, 7,  7,  7,  50, 7,  7,  7,
2886
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2887
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2888
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2889
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2890
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2891
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2892
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2893
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2894
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2895
    7,  7,  7,  7,  7,  7,  7,  7,  7,  51, 7,  52, 53, 54, 55, 56, 7,  7,  7,
2896
    7,  7,  7,  7,  7,  57, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  58,
2897
    59, 7,  60, 61, 62, 7,  7,  7,  7,  7,  7,  7,  7,  63, 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,  7,  7,  7,  7,  7,
2902
    7,  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,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2907
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  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
    64, 65, 66, 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,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2918
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2919
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2920
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2921
    7,  7,  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
    7,  7,  7,  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};
3101
3102
const uint16_t decomposition_block[67][257] = {
3103
    {4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3104
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3105
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3106
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3107
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3108
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3109
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3110
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3111
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3112
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3113
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   5,   8,   8,   8,   8,
3114
     8,   8,   8,   9,   16,  17,  20,  20,  20,  20,  21,  28,  28,  29,  33,
3115
     37,  45,  48,  48,  49,  57,  61,  64,  65,  77,  89,  100, 100, 108, 116,
3116
     124, 132, 140, 148, 148, 156, 164, 172, 180, 188, 196, 204, 212, 220, 220,
3117
     228, 236, 244, 252, 260, 268, 268, 268, 276, 284, 292, 300, 308, 308, 308,
3118
     316, 324, 332, 340, 348, 356, 356, 364, 372, 380, 388, 396, 404, 412, 420,
3119
     428, 428, 436, 444, 452, 460, 468, 476, 476, 476, 484, 492, 500, 508, 516,
3120
     516, 524},
3121
    {524,  532,  540,  548,  556,  564,  572,  580,  588,  596,  604,  612,
3122
     620,  628,  636,  644,  652,  652,  652,  660,  668,  676,  684,  692,
3123
     700,  708,  716,  724,  732,  740,  748,  756,  764,  772,  780,  788,
3124
     796,  804,  812,  812,  812,  820,  828,  836,  844,  852,  860,  868,
3125
     876,  884,  885,  893,  900,  908,  916,  924,  932,  932,  940,  948,
3126
     956,  964,  972,  981,  989,  996,  996,  996,  1004, 1012, 1020, 1028,
3127
     1036, 1045, 1052, 1052, 1052, 1060, 1068, 1076, 1084, 1092, 1100, 1100,
3128
     1100, 1108, 1116, 1124, 1132, 1140, 1148, 1156, 1164, 1172, 1180, 1188,
3129
     1196, 1204, 1212, 1220, 1228, 1236, 1244, 1244, 1244, 1252, 1260, 1268,
3130
     1276, 1284, 1292, 1300, 1308, 1316, 1324, 1332, 1340, 1348, 1356, 1364,
3131
     1372, 1380, 1388, 1396, 1404, 1412, 1420, 1429, 1432, 1432, 1432, 1432,
3132
     1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3133
     1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3134
     1432, 1432, 1432, 1432, 1432, 1440, 1448, 1448, 1448, 1448, 1448, 1448,
3135
     1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1456, 1464, 1464, 1464,
3136
     1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464,
3137
     1464, 1464, 1464, 1464, 1465, 1477, 1489, 1501, 1509, 1517, 1525, 1533,
3138
     1541, 1548, 1556, 1564, 1572, 1580, 1588, 1596, 1604, 1612, 1624, 1636,
3139
     1648, 1660, 1672, 1684, 1696, 1708, 1708, 1720, 1732, 1744, 1756, 1764,
3140
     1772, 1772, 1772, 1780, 1788, 1796, 1804, 1812, 1820, 1832, 1844, 1852,
3141
     1860, 1869, 1877, 1885, 1892, 1900, 1908, 1908, 1908, 1916, 1924, 1936,
3142
     1948, 1956, 1964, 1972, 1980},
3143
    {1980, 1988, 1996, 2004, 2012, 2020, 2028, 2036, 2044, 2052, 2060, 2068,
3144
     2076, 2084, 2092, 2100, 2108, 2116, 2124, 2132, 2140, 2148, 2156, 2164,
3145
     2172, 2180, 2188, 2196, 2204, 2204, 2204, 2212, 2220, 2220, 2220, 2220,
3146
     2220, 2220, 2220, 2228, 2236, 2244, 2252, 2264, 2276, 2288, 2300, 2308,
3147
     2316, 2328, 2340, 2348, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3148
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3149
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3150
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3151
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3152
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3153
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3154
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3155
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3156
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3157
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2357, 2361, 2365, 2369,
3158
     2373, 2377, 2381, 2385, 2389, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3159
     2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3160
     2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3161
     2393, 2401, 2409, 2417, 2425, 2433, 2440, 2440, 2441, 2445, 2449, 2453,
3162
     2457, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3163
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3164
     2460, 2460, 2460, 2460, 2460},
3165
    {2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3166
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3167
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3168
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3169
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3170
     2460, 2460, 2460, 2460, 2460, 2464, 2468, 2468, 2472, 2480, 2480, 2480,
3171
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3172
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3173
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3174
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2484, 2484, 2484,
3175
     2484, 2484, 2485, 2492, 2492, 2492, 2492, 2496, 2496, 2496, 2496, 2496,
3176
     2497, 2506, 2512, 2520, 2524, 2532, 2540, 2548, 2548, 2556, 2556, 2564,
3177
     2572, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3178
     2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3179
     2584, 2584, 2584, 2592, 2600, 2608, 2616, 2624, 2632, 2644, 2644, 2644,
3180
     2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644,
3181
     2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2652,
3182
     2660, 2668, 2676, 2684, 2685, 2689, 2693, 2698, 2706, 2713, 2717, 2720,
3183
     2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3184
     2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3185
     2721, 2725, 2729, 2732, 2733, 2737, 2740, 2740, 2740, 2741, 2744, 2744,
3186
     2744, 2744, 2744, 2744, 2744},
3187
    {2744, 2752, 2760, 2760, 2768, 2768, 2768, 2768, 2776, 2776, 2776, 2776,
3188
     2776, 2784, 2792, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800,
3189
     2800, 2800, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3190
     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3191
     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2816, 2816,
3192
     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816,
3193
     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2824, 2832, 2832,
3194
     2840, 2840, 2840, 2840, 2848, 2848, 2848, 2848, 2848, 2856, 2864, 2872,
3195
     2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872,
3196
     2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2880,
3197
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3198
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3199
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3200
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3201
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3202
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3203
     2888, 2888, 2896, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904,
3204
     2904, 2904, 2904, 2904, 2904, 2912, 2920, 2928, 2936, 2936, 2936, 2944,
3205
     2952, 2952, 2952, 2960, 2968, 2976, 2984, 2992, 3000, 3000, 3000, 3008,
3206
     3016, 3024, 3032, 3040, 3048, 3048, 3048, 3056, 3064, 3072, 3080, 3088,
3207
     3096, 3104, 3112, 3120, 3128, 3136, 3144, 3144, 3144, 3152, 3160, 3160,
3208
     3160, 3160, 3160, 3160, 3160},
3209
    {3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3210
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3211
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3212
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3213
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3214
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3215
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3216
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3217
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3218
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3219
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3220
     3160, 3160, 3160, 3161, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3221
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3222
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3223
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3224
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3225
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3226
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3227
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3228
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3229
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3230
     3168, 3168, 3168, 3168, 3168},
3231
    {3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3232
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3233
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3176,
3234
     3184, 3192, 3200, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3235
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3236
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3237
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3238
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3239
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3240
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3209, 3217, 3225,
3241
     3233, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3242
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3243
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3244
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3245
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3246
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3247
     3240, 3248, 3248, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256,
3248
     3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3264, 3264, 3264, 3264,
3249
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3250
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3251
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3252
     3264, 3264, 3264, 3264, 3264},
3253
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3254
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3255
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3256
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3257
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3258
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3259
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3260
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3261
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3262
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3263
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
3264
    {3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3265
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3266
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3267
     3264, 3264, 3264, 3264, 3264, 3264, 3272, 3272, 3272, 3272, 3272, 3272,
3268
     3272, 3272, 3280, 3280, 3280, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3269
     3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3270
     3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3271
     3288, 3288, 3288, 3288, 3288, 3296, 3304, 3312, 3320, 3328, 3336, 3344,
3272
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3273
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3274
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3275
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3276
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3277
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3278
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3279
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3280
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3281
     3360, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368,
3282
     3368, 3368, 3368, 3368, 3368, 3376, 3384, 3384, 3392, 3392, 3392, 3392,
3283
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3284
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3285
     3392, 3392, 3392, 3392, 3392},
3286
    {3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3287
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3288
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3289
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3290
     3392, 3392, 3392, 3392, 3400, 3400, 3400, 3408, 3408, 3408, 3408, 3408,
3291
     3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3292
     3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3293
     3408, 3408, 3408, 3408, 3408, 3408, 3416, 3424, 3432, 3432, 3432, 3440,
3294
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3295
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3296
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3297
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3298
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3299
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3300
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3301
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3302
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3303
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3304
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3305
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3306
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3307
     3440, 3440, 3440, 3440, 3440},
3308
    {3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3309
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3310
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3311
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3312
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3313
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3314
     3440, 3448, 3448, 3448, 3456, 3464, 3464, 3464, 3464, 3464, 3464, 3464,
3315
     3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3472, 3480, 3480,
3316
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3317
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3318
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3319
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3320
     3480, 3480, 3480, 3480, 3480, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3321
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3322
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3323
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3324
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3496,
3325
     3504, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3326
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3327
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3328
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3329
     3512, 3512, 3512, 3512, 3512},
3330
    {3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3331
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3332
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3333
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3334
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3335
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3336
     3512, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3337
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3338
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3339
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3340
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3341
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3342
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3343
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3344
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3345
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3346
     3520, 3528, 3528, 3528, 3528, 3528, 3528, 3528, 3536, 3544, 3544, 3552,
3347
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3348
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3349
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3350
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3351
     3564, 3564, 3564, 3564, 3564},
3352
    {3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3353
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3354
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3355
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3356
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3357
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3358
     3564, 3564, 3564, 3572, 3580, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3359
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3360
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3361
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3362
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3363
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3364
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3365
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3366
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3367
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3368
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3369
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3370
     3588, 3588, 3588, 3596, 3596, 3604, 3616, 3624, 3624, 3624, 3624, 3624,
3371
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3372
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3373
     3624, 3624, 3624, 3624, 3624},
3374
    {3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3375
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3376
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3377
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3378
     3624, 3624, 3624, 3625, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3379
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3380
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3381
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3382
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3383
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3384
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3385
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3386
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3387
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3388
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3633,
3389
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3390
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3391
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3392
     3640, 3640, 3640, 3640, 3641, 3649, 3656, 3656, 3656, 3656, 3656, 3656,
3393
     3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3394
     3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3395
     3656, 3656, 3656, 3656, 3656},
3396
    {3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3397
     3657, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3398
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3399
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3400
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3401
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3668, 3668, 3668, 3668,
3402
     3668, 3668, 3668, 3668, 3668, 3668, 3676, 3676, 3676, 3676, 3676, 3684,
3403
     3684, 3684, 3684, 3684, 3692, 3692, 3692, 3692, 3692, 3700, 3700, 3700,
3404
     3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3708, 3708,
3405
     3708, 3708, 3708, 3708, 3708, 3708, 3708, 3708, 3716, 3716, 3724, 3733,
3406
     3744, 3753, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3772, 3772,
3407
     3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772,
3408
     3772, 3772, 3772, 3772, 3780, 3780, 3780, 3780, 3780, 3780, 3780, 3780,
3409
     3780, 3780, 3788, 3788, 3788, 3788, 3788, 3796, 3796, 3796, 3796, 3796,
3410
     3804, 3804, 3804, 3804, 3804, 3812, 3812, 3812, 3812, 3812, 3812, 3812,
3411
     3812, 3812, 3812, 3812, 3812, 3812, 3820, 3820, 3820, 3820, 3820, 3820,
3412
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3413
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3414
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3415
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3416
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3417
     3820, 3820, 3820, 3820, 3820},
3418
    {3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3419
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3420
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3421
     3820, 3820, 3820, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3422
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3423
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3424
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3425
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3426
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3427
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3428
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3429
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3430
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3431
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3432
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3433
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3434
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3435
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3436
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3437
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3438
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3439
     3829, 3832, 3832, 3832, 3832},
3440
    {3832, 3832, 3832, 3832, 3832, 3832, 3832, 3840, 3840, 3848, 3848, 3856,
3441
     3856, 3864, 3864, 3872, 3872, 3872, 3872, 3880, 3880, 3880, 3880, 3880,
3442
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3443
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3444
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3445
     3888, 3888, 3896, 3896, 3896, 3904, 3912, 3912, 3920, 3920, 3920, 3920,
3446
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3447
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3448
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3449
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3450
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3451
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3452
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3453
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3454
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3455
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3456
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3457
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3458
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3459
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3460
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3461
     3920, 3920, 3920, 3920, 3920},
3462
    {3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3463
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3464
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3465
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3921, 3925, 3929, 3932,
3466
     3933, 3937, 3941, 3945, 3949, 3953, 3957, 3961, 3965, 3969, 3973, 3976,
3467
     3977, 3981, 3985, 3989, 3993, 3997, 4001, 4005, 4009, 4013, 4017, 4021,
3468
     4025, 4029, 4033, 4037, 4041, 4045, 4048, 4049, 4053, 4057, 4061, 4065,
3469
     4069, 4073, 4077, 4081, 4085, 4089, 4093, 4097, 4101, 4105, 4109, 4113,
3470
     4117, 4121, 4125, 4129, 4133, 4137, 4141, 4145, 4149, 4153, 4157, 4160,
3471
     4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160,
3472
     4161, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3473
     4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3474
     4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4165,
3475
     4169, 4173, 4177, 4181, 4185, 4189, 4193, 4197, 4201, 4205, 4209, 4213,
3476
     4217, 4221, 4225, 4229, 4233, 4237, 4241, 4245, 4249, 4253, 4257, 4261,
3477
     4265, 4269, 4273, 4277, 4281, 4285, 4289, 4293, 4297, 4301, 4305, 4309,
3478
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3479
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3480
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3481
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3482
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3483
     4312, 4312, 4312, 4312, 4312},
3484
    {4312, 4320, 4328, 4336, 4344, 4352, 4360, 4368, 4376, 4388, 4400, 4408,
3485
     4416, 4424, 4432, 4440, 4448, 4456, 4464, 4472, 4480, 4492, 4504, 4516,
3486
     4528, 4536, 4544, 4552, 4560, 4572, 4584, 4592, 4600, 4608, 4616, 4624,
3487
     4632, 4640, 4648, 4656, 4664, 4672, 4680, 4688, 4696, 4704, 4712, 4724,
3488
     4736, 4744, 4752, 4760, 4768, 4776, 4784, 4792, 4800, 4812, 4824, 4832,
3489
     4840, 4848, 4856, 4864, 4872, 4880, 4888, 4896, 4904, 4912, 4920, 4928,
3490
     4936, 4944, 4952, 4960, 4968, 4980, 4992, 5004, 5016, 5028, 5040, 5052,
3491
     5064, 5072, 5080, 5088, 5096, 5104, 5112, 5120, 5128, 5140, 5152, 5160,
3492
     5168, 5176, 5184, 5192, 5200, 5212, 5224, 5236, 5248, 5260, 5272, 5280,
3493
     5288, 5296, 5304, 5312, 5320, 5328, 5336, 5344, 5352, 5360, 5368, 5376,
3494
     5384, 5396, 5408, 5420, 5432, 5440, 5448, 5456, 5464, 5472, 5480, 5488,
3495
     5496, 5504, 5512, 5520, 5528, 5536, 5544, 5552, 5560, 5568, 5576, 5584,
3496
     5592, 5600, 5608, 5616, 5624, 5632, 5640, 5648, 5656, 5664, 5673, 5682,
3497
     5688, 5688, 5688, 5688, 5688, 5696, 5704, 5712, 5720, 5732, 5744, 5756,
3498
     5768, 5780, 5792, 5804, 5816, 5828, 5840, 5852, 5864, 5876, 5888, 5900,
3499
     5912, 5924, 5936, 5948, 5960, 5968, 5976, 5984, 5992, 6000, 6008, 6020,
3500
     6032, 6044, 6056, 6068, 6080, 6092, 6104, 6116, 6128, 6136, 6144, 6152,
3501
     6160, 6168, 6176, 6184, 6192, 6204, 6216, 6228, 6240, 6252, 6264, 6276,
3502
     6288, 6300, 6312, 6324, 6336, 6348, 6360, 6372, 6384, 6396, 6408, 6420,
3503
     6432, 6440, 6448, 6456, 6464, 6476, 6488, 6500, 6512, 6524, 6536, 6548,
3504
     6560, 6572, 6584, 6592, 6600, 6608, 6616, 6624, 6632, 6640, 6648, 6648,
3505
     6648, 6648, 6648, 6648, 6648},
3506
    {6648, 6656, 6664, 6676, 6688, 6700, 6712, 6724, 6736, 6744, 6752, 6764,
3507
     6776, 6788, 6800, 6812, 6824, 6832, 6840, 6852, 6864, 6876, 6888, 6888,
3508
     6888, 6896, 6904, 6916, 6928, 6940, 6952, 6952, 6952, 6960, 6968, 6980,
3509
     6992, 7004, 7016, 7028, 7040, 7048, 7056, 7068, 7080, 7092, 7104, 7116,
3510
     7128, 7136, 7144, 7156, 7168, 7180, 7192, 7204, 7216, 7224, 7232, 7244,
3511
     7256, 7268, 7280, 7292, 7304, 7312, 7320, 7332, 7344, 7356, 7368, 7368,
3512
     7368, 7376, 7384, 7396, 7408, 7420, 7432, 7432, 7432, 7440, 7448, 7460,
3513
     7472, 7484, 7496, 7508, 7520, 7520, 7528, 7528, 7540, 7540, 7552, 7552,
3514
     7564, 7572, 7580, 7592, 7604, 7616, 7628, 7640, 7652, 7660, 7668, 7680,
3515
     7692, 7704, 7716, 7728, 7740, 7748, 7756, 7764, 7772, 7780, 7788, 7796,
3516
     7804, 7812, 7820, 7828, 7836, 7844, 7852, 7852, 7852, 7864, 7876, 7892,
3517
     7908, 7924, 7940, 7956, 7972, 7984, 7996, 8012, 8028, 8044, 8060, 8076,
3518
     8092, 8104, 8116, 8132, 8148, 8164, 8180, 8196, 8212, 8224, 8236, 8252,
3519
     8268, 8284, 8300, 8316, 8332, 8344, 8356, 8372, 8388, 8404, 8420, 8436,
3520
     8452, 8464, 8476, 8492, 8508, 8524, 8540, 8556, 8572, 8580, 8588, 8600,
3521
     8608, 8620, 8620, 8628, 8640, 8648, 8656, 8664, 8672, 8681, 8688, 8693,
3522
     8701, 8710, 8716, 8728, 8736, 8748, 8748, 8756, 8768, 8776, 8784, 8792,
3523
     8800, 8810, 8818, 8826, 8832, 8840, 8848, 8860, 8872, 8872, 8872, 8880,
3524
     8892, 8900, 8908, 8916, 8924, 8926, 8934, 8942, 8948, 8956, 8964, 8976,
3525
     8988, 8996, 9004, 9012, 9024, 9032, 9040, 9048, 9056, 9066, 9074, 9080,
3526
     9084, 9084, 9084, 9096, 9104, 9116, 9116, 9124, 9136, 9144, 9152, 9160,
3527
     9168, 9178, 9181, 9188, 9190},
3528
    {9190, 9194, 9197, 9201, 9205, 9209, 9213, 9217, 9221, 9225, 9229, 9232,
3529
     9232, 9232, 9232, 9232, 9232, 9233, 9236, 9236, 9236, 9236, 9236, 9237,
3530
     9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244,
3531
     9245, 9249, 9257, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9269,
3532
     9272, 9272, 9272, 9273, 9281, 9292, 9293, 9301, 9312, 9312, 9312, 9312,
3533
     9313, 9320, 9321, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9329,
3534
     9337, 9345, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352,
3535
     9352, 9352, 9352, 9353, 9368, 9368, 9368, 9368, 9368, 9368, 9368, 9369,
3536
     9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372,
3537
     9372, 9372, 9372, 9372, 9373, 9377, 9380, 9380, 9381, 9385, 9389, 9393,
3538
     9397, 9401, 9405, 9409, 9413, 9417, 9421, 9425, 9429, 9433, 9437, 9441,
3539
     9445, 9449, 9453, 9457, 9461, 9465, 9469, 9473, 9477, 9481, 9485, 9488,
3540
     9489, 9493, 9497, 9501, 9505, 9509, 9513, 9517, 9521, 9525, 9529, 9533,
3541
     9537, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540,
3542
     9541, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3543
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3544
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3545
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3546
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3547
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3548
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3549
     9548, 9548, 9548, 9548, 9549},
3550
    {9549,  9561,  9573,  9577,  9584,  9585,  9597,  9609,  9612,  9613,
3551
     9621,  9625,  9629,  9633,  9637,  9641,  9645,  9649,  9653,  9657,
3552
     9660,  9661,  9665,  9672,  9672,  9673,  9677,  9681,  9685,  9689,
3553
     9692,  9692,  9693,  9701,  9713,  9720,  9721,  9724,  9724,  9728,
3554
     9729,  9732,  9732,  9736,  9745,  9749,  9752,  9753,  9757,  9761,
3555
     9764,  9765,  9769,  9773,  9777,  9781,  9785,  9789,  9792,  9793,
3556
     9805,  9809,  9813,  9817,  9821,  9824,  9824,  9824,  9824,  9825,
3557
     9829,  9833,  9837,  9841,  9844,  9844,  9844,  9844,  9844,  9844,
3558
     9845,  9857,  9869,  9885,  9897,  9909,  9921,  9933,  9945,  9957,
3559
     9969,  9981,  9993,  10005, 10017, 10029, 10037, 10041, 10049, 10061,
3560
     10069, 10073, 10081, 10093, 10109, 10117, 10121, 10129, 10141, 10145,
3561
     10149, 10153, 10157, 10161, 10169, 10181, 10189, 10193, 10201, 10213,
3562
     10229, 10237, 10241, 10249, 10261, 10265, 10269, 10273, 10276, 10276,
3563
     10276, 10276, 10276, 10276, 10276, 10276, 10276, 10277, 10288, 10288,
3564
     10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288,
3565
     10288, 10288, 10288, 10288, 10288, 10296, 10304, 10304, 10304, 10304,
3566
     10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304,
3567
     10304, 10304, 10304, 10304, 10304, 10312, 10312, 10312, 10312, 10312,
3568
     10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3569
     10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3570
     10312, 10312, 10312, 10312, 10312, 10312, 10320, 10328, 10336, 10336,
3571
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3572
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3573
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3574
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3575
     10336, 10336, 10336, 10336, 10336, 10336, 10336},
3576
    {10336, 10336, 10336, 10336, 10336, 10344, 10344, 10344, 10344, 10344,
3577
     10352, 10352, 10352, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3578
     10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3579
     10360, 10360, 10360, 10360, 10360, 10360, 10360, 10368, 10368, 10376,
3580
     10376, 10376, 10376, 10376, 10377, 10385, 10396, 10397, 10405, 10416,
3581
     10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416,
3582
     10416, 10416, 10416, 10416, 10416, 10416, 10424, 10424, 10424, 10432,
3583
     10432, 10432, 10440, 10440, 10448, 10448, 10448, 10448, 10448, 10448,
3584
     10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448,
3585
     10448, 10448, 10448, 10448, 10448, 10448, 10448, 10456, 10456, 10464,
3586
     10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464,
3587
     10472, 10480, 10488, 10496, 10504, 10504, 10504, 10512, 10520, 10520,
3588
     10520, 10528, 10536, 10536, 10536, 10536, 10536, 10536, 10536, 10544,
3589
     10552, 10552, 10552, 10560, 10568, 10568, 10568, 10576, 10584, 10584,
3590
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3591
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3592
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3593
     10584, 10584, 10584, 10592, 10600, 10608, 10616, 10616, 10616, 10616,
3594
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3595
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3596
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3597
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3598
     10616, 10616, 10616, 10616, 10616, 10624, 10632, 10640, 10648, 10648,
3599
     10648, 10648, 10648, 10648, 10648, 10656, 10664, 10672, 10680, 10680,
3600
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3601
     10680, 10680, 10680, 10680, 10680, 10680, 10680},
3602
    {10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3603
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3604
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3605
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3606
     10680, 10680, 10684, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3607
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3608
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3609
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3610
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3611
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3612
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3613
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3614
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3615
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3616
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3617
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3618
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3619
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3620
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3621
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3622
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3623
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3624
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3625
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3626
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3627
     10688, 10688, 10688, 10688, 10688, 10688, 10688},
3628
    {10688, 10688, 10688, 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, 10689, 10693, 10697, 10701,
3638
     10705, 10709, 10713, 10717, 10721, 10725, 10733, 10741, 10749, 10757,
3639
     10765, 10773, 10781, 10789, 10797, 10805, 10813, 10825, 10837, 10849,
3640
     10861, 10873, 10885, 10897, 10909, 10921, 10937, 10953, 10969, 10985,
3641
     11001, 11017, 11033, 11049, 11065, 11081, 11097, 11105, 11113, 11121,
3642
     11129, 11137, 11145, 11153, 11161, 11169, 11181, 11193, 11205, 11217,
3643
     11229, 11241, 11253, 11265, 11277, 11289, 11301, 11313, 11325, 11337,
3644
     11349, 11361, 11373, 11385, 11397, 11409, 11421, 11433, 11445, 11457,
3645
     11469, 11481, 11493, 11505, 11517, 11529, 11541, 11553, 11565, 11577,
3646
     11589, 11601, 11613, 11617, 11621, 11625, 11629, 11633, 11637, 11641,
3647
     11645, 11649, 11653, 11657, 11661, 11665, 11669, 11673, 11677, 11681,
3648
     11685, 11689, 11693, 11697, 11701, 11705, 11709, 11713, 11717, 11721,
3649
     11725, 11729, 11733, 11737, 11741, 11745, 11749, 11753, 11757, 11761,
3650
     11765, 11769, 11773, 11777, 11781, 11785, 11789, 11793, 11797, 11801,
3651
     11805, 11809, 11813, 11817, 11821, 11824, 11824, 11824, 11824, 11824,
3652
     11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3653
     11824, 11824, 11824, 11824, 11824, 11824, 11824},
3654
    {11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3655
     11824, 11824, 11825, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3656
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3657
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3658
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3659
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3660
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3661
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3662
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3663
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3664
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3665
     11840, 11840, 11840, 11840, 11840, 11840, 11841, 11853, 11861, 11872,
3666
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3667
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3668
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3669
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3670
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3671
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3672
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3673
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3674
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3675
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3676
     11872, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3677
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3678
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3679
     11880, 11880, 11880, 11880, 11880, 11880, 11880},
3680
    {11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3681
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3682
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3683
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3684
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3685
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3686
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3687
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3688
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3689
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3690
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3691
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3692
     11880, 11880, 11880, 11880, 11881, 11885, 11888, 11888, 11888, 11888,
3693
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3694
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3695
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3696
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3697
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3698
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3699
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3700
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3701
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3702
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3703
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3704
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3705
     11888, 11888, 11888, 11888, 11888, 11888, 11888},
3706
    {11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3707
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3708
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3709
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3710
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3711
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3712
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3713
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3714
     11888, 11888, 11888, 11888, 11888, 11888, 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, 11889, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3718
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3719
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3720
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3721
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3722
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3723
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3724
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3725
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3726
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3727
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3728
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3729
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3730
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3731
     11892, 11892, 11892, 11892, 11892, 11892, 11892},
3732
    {11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3733
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3734
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3735
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3736
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3737
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3738
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3739
     11892, 11892, 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, 11893,
3748
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3749
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3750
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3751
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3752
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3753
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3754
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3755
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3756
     11896, 11896, 11896, 11897, 11900, 11900, 11900, 11900, 11900, 11900,
3757
     11900, 11900, 11900, 11900, 11900, 11900, 11901},
3758
    {11901, 11905, 11909, 11913, 11917, 11921, 11925, 11929, 11933, 11937,
3759
     11941, 11945, 11949, 11953, 11957, 11961, 11965, 11969, 11973, 11977,
3760
     11981, 11985, 11989, 11993, 11997, 12001, 12005, 12009, 12013, 12017,
3761
     12021, 12025, 12029, 12033, 12037, 12041, 12045, 12049, 12053, 12057,
3762
     12061, 12065, 12069, 12073, 12077, 12081, 12085, 12089, 12093, 12097,
3763
     12101, 12105, 12109, 12113, 12117, 12121, 12125, 12129, 12133, 12137,
3764
     12141, 12145, 12149, 12153, 12157, 12161, 12165, 12169, 12173, 12177,
3765
     12181, 12185, 12189, 12193, 12197, 12201, 12205, 12209, 12213, 12217,
3766
     12221, 12225, 12229, 12233, 12237, 12241, 12245, 12249, 12253, 12257,
3767
     12261, 12265, 12269, 12273, 12277, 12281, 12285, 12289, 12293, 12297,
3768
     12301, 12305, 12309, 12313, 12317, 12321, 12325, 12329, 12333, 12337,
3769
     12341, 12345, 12349, 12353, 12357, 12361, 12365, 12369, 12373, 12377,
3770
     12381, 12385, 12389, 12393, 12397, 12401, 12405, 12409, 12413, 12417,
3771
     12421, 12425, 12429, 12433, 12437, 12441, 12445, 12449, 12453, 12457,
3772
     12461, 12465, 12469, 12473, 12477, 12481, 12485, 12489, 12493, 12497,
3773
     12501, 12505, 12509, 12513, 12517, 12521, 12525, 12529, 12533, 12537,
3774
     12541, 12545, 12549, 12553, 12557, 12561, 12565, 12569, 12573, 12577,
3775
     12581, 12585, 12589, 12593, 12597, 12601, 12605, 12609, 12613, 12617,
3776
     12621, 12625, 12629, 12633, 12637, 12641, 12645, 12649, 12653, 12657,
3777
     12661, 12665, 12669, 12673, 12677, 12681, 12685, 12689, 12693, 12697,
3778
     12701, 12705, 12709, 12713, 12717, 12721, 12725, 12729, 12733, 12737,
3779
     12741, 12745, 12749, 12753, 12756, 12756, 12756, 12756, 12756, 12756,
3780
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3781
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3782
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3783
     12756, 12756, 12756, 12756, 12756, 12756, 12757},
3784
    {12757, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3785
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3786
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3787
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3788
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3789
     12760, 12760, 12760, 12760, 12761, 12764, 12765, 12769, 12773, 12776,
3790
     12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776,
3791
     12776, 12776, 12776, 12776, 12776, 12776, 12776, 12784, 12784, 12792,
3792
     12792, 12800, 12800, 12808, 12808, 12816, 12816, 12824, 12824, 12832,
3793
     12832, 12840, 12840, 12848, 12848, 12856, 12856, 12864, 12864, 12872,
3794
     12872, 12872, 12880, 12880, 12888, 12888, 12896, 12896, 12896, 12896,
3795
     12896, 12896, 12896, 12904, 12912, 12912, 12920, 12928, 12928, 12936,
3796
     12944, 12944, 12952, 12960, 12960, 12968, 12976, 12976, 12976, 12976,
3797
     12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976,
3798
     12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12984,
3799
     12984, 12984, 12984, 12984, 12984, 12985, 12993, 13000, 13000, 13009,
3800
     13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016,
3801
     13016, 13016, 13016, 13024, 13024, 13032, 13032, 13040, 13040, 13048,
3802
     13048, 13056, 13056, 13064, 13064, 13072, 13072, 13080, 13080, 13088,
3803
     13088, 13096, 13096, 13104, 13104, 13112, 13112, 13112, 13120, 13120,
3804
     13128, 13128, 13136, 13136, 13136, 13136, 13136, 13136, 13136, 13144,
3805
     13152, 13152, 13160, 13168, 13168, 13176, 13184, 13184, 13192, 13200,
3806
     13200, 13208, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3807
     13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3808
     13216, 13216, 13216, 13216, 13216, 13224, 13224, 13224, 13232, 13240,
3809
     13248, 13256, 13256, 13256, 13256, 13265, 13272},
3810
    {13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3811
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3812
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3813
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3814
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13273,
3815
     13277, 13281, 13285, 13289, 13293, 13297, 13301, 13305, 13309, 13313,
3816
     13317, 13321, 13325, 13329, 13333, 13337, 13341, 13345, 13349, 13353,
3817
     13357, 13361, 13365, 13369, 13373, 13377, 13381, 13385, 13389, 13393,
3818
     13397, 13401, 13405, 13409, 13413, 13417, 13421, 13425, 13429, 13433,
3819
     13437, 13441, 13445, 13449, 13453, 13457, 13461, 13465, 13469, 13473,
3820
     13477, 13481, 13485, 13489, 13493, 13497, 13501, 13505, 13509, 13513,
3821
     13517, 13521, 13525, 13529, 13533, 13537, 13541, 13545, 13549, 13553,
3822
     13557, 13561, 13565, 13569, 13573, 13577, 13581, 13585, 13589, 13593,
3823
     13597, 13601, 13605, 13609, 13613, 13617, 13621, 13625, 13629, 13633,
3824
     13637, 13641, 13645, 13648, 13648, 13648, 13649, 13653, 13657, 13661,
3825
     13665, 13669, 13673, 13677, 13681, 13685, 13689, 13693, 13697, 13701,
3826
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3827
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3828
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3829
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3830
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3831
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3832
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3833
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3834
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3835
     13704, 13704, 13704, 13704, 13704, 13704, 13705},
3836
    {13705, 13717, 13729, 13741, 13753, 13765, 13777, 13789, 13801, 13813,
3837
     13825, 13837, 13849, 13861, 13873, 13889, 13905, 13921, 13937, 13953,
3838
     13969, 13985, 14001, 14017, 14033, 14049, 14065, 14081, 14097, 14113,
3839
     14141, 14164, 14165, 14177, 14189, 14201, 14213, 14225, 14237, 14249,
3840
     14261, 14273, 14285, 14297, 14309, 14321, 14333, 14345, 14357, 14369,
3841
     14381, 14393, 14405, 14417, 14429, 14441, 14453, 14465, 14477, 14489,
3842
     14501, 14513, 14525, 14537, 14549, 14561, 14573, 14585, 14597, 14601,
3843
     14605, 14609, 14612, 14612, 14612, 14612, 14612, 14612, 14612, 14612,
3844
     14613, 14625, 14633, 14641, 14649, 14657, 14665, 14673, 14681, 14689,
3845
     14697, 14705, 14713, 14721, 14729, 14737, 14745, 14749, 14753, 14757,
3846
     14761, 14765, 14769, 14773, 14777, 14781, 14785, 14789, 14793, 14797,
3847
     14801, 14809, 14817, 14825, 14833, 14841, 14849, 14857, 14865, 14873,
3848
     14881, 14889, 14897, 14905, 14913, 14933, 14949, 14956, 14957, 14961,
3849
     14965, 14969, 14973, 14977, 14981, 14985, 14989, 14993, 14997, 15001,
3850
     15005, 15009, 15013, 15017, 15021, 15025, 15029, 15033, 15037, 15041,
3851
     15045, 15049, 15053, 15057, 15061, 15065, 15069, 15073, 15077, 15081,
3852
     15085, 15089, 15093, 15097, 15101, 15105, 15109, 15113, 15117, 15121,
3853
     15125, 15129, 15133, 15137, 15141, 15145, 15149, 15153, 15161, 15169,
3854
     15177, 15185, 15193, 15201, 15209, 15217, 15225, 15233, 15241, 15249,
3855
     15257, 15265, 15273, 15281, 15289, 15297, 15305, 15313, 15321, 15329,
3856
     15337, 15345, 15357, 15369, 15381, 15389, 15401, 15409, 15421, 15425,
3857
     15429, 15433, 15437, 15441, 15445, 15449, 15453, 15457, 15461, 15465,
3858
     15469, 15473, 15477, 15481, 15485, 15489, 15493, 15497, 15501, 15505,
3859
     15509, 15513, 15517, 15521, 15525, 15529, 15533, 15537, 15541, 15545,
3860
     15549, 15553, 15557, 15561, 15565, 15569, 15573, 15577, 15581, 15585,
3861
     15589, 15593, 15597, 15601, 15605, 15609, 15617},
3862
    {15617, 15637, 15653, 15673, 15685, 15705, 15717, 15729, 15753, 15769,
3863
     15781, 15793, 15805, 15821, 15837, 15853, 15869, 15885, 15901, 15917,
3864
     15941, 15949, 15973, 15997, 16017, 16033, 16057, 16081, 16097, 16109,
3865
     16121, 16137, 16153, 16173, 16193, 16205, 16217, 16233, 16245, 16257,
3866
     16265, 16273, 16285, 16297, 16321, 16337, 16357, 16381, 16397, 16409,
3867
     16421, 16445, 16461, 16485, 16497, 16517, 16529, 16545, 16557, 16573,
3868
     16593, 16609, 16629, 16645, 16653, 16673, 16685, 16697, 16713, 16725,
3869
     16737, 16749, 16769, 16785, 16793, 16817, 16829, 16849, 16865, 16881,
3870
     16893, 16905, 16921, 16929, 16945, 16965, 16973, 16997, 17009, 17017,
3871
     17025, 17033, 17041, 17049, 17057, 17065, 17073, 17081, 17089, 17101,
3872
     17113, 17125, 17137, 17149, 17161, 17173, 17185, 17197, 17209, 17221,
3873
     17233, 17245, 17257, 17269, 17281, 17289, 17297, 17309, 17317, 17325,
3874
     17333, 17345, 17357, 17365, 17373, 17381, 17389, 17397, 17413, 17421,
3875
     17429, 17437, 17445, 17453, 17461, 17469, 17477, 17489, 17505, 17513,
3876
     17521, 17529, 17537, 17545, 17553, 17561, 17573, 17585, 17597, 17609,
3877
     17617, 17625, 17633, 17641, 17649, 17657, 17665, 17673, 17681, 17689,
3878
     17701, 17713, 17721, 17733, 17745, 17757, 17765, 17777, 17789, 17805,
3879
     17813, 17825, 17837, 17849, 17861, 17881, 17905, 17913, 17921, 17929,
3880
     17937, 17945, 17953, 17961, 17969, 17977, 17985, 17993, 18001, 18009,
3881
     18017, 18025, 18033, 18041, 18049, 18065, 18073, 18081, 18089, 18105,
3882
     18117, 18125, 18133, 18141, 18149, 18157, 18165, 18173, 18181, 18189,
3883
     18197, 18209, 18217, 18225, 18237, 18249, 18257, 18273, 18285, 18293,
3884
     18301, 18309, 18317, 18329, 18341, 18349, 18357, 18365, 18373, 18381,
3885
     18389, 18397, 18405, 18413, 18425, 18437, 18449, 18461, 18473, 18485,
3886
     18497, 18509, 18521, 18533, 18545, 18557, 18569, 18581, 18593, 18605,
3887
     18617, 18629, 18641, 18653, 18665, 18677, 18688},
3888
    {18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3889
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3890
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3891
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3892
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3893
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3894
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3895
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3896
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3897
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3898
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3899
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3900
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3901
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3902
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3903
     18688, 18688, 18688, 18688, 18688, 18688, 18689, 18693, 18696, 18696,
3904
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3905
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3906
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3907
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3908
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3909
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3910
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3911
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3912
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3913
     18696, 18696, 18696, 18696, 18696, 18696, 18696},
3914
    {18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3915
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3916
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3917
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3918
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3919
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3920
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3921
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3922
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3923
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3924
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3925
     18696, 18696, 18697, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3926
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3927
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3928
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3929
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3930
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3931
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3932
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3933
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3934
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3935
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3936
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3937
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3938
     18700, 18700, 18701, 18705, 18709, 18712, 18712, 18712, 18713, 18717,
3939
     18720, 18720, 18720, 18720, 18720, 18720, 18720},
3940
    {18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3941
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3942
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3943
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3944
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3945
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3946
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3947
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3948
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3949
     18720, 18720, 18721, 18725, 18729, 18733, 18736, 18736, 18736, 18736,
3950
     18736, 18736, 18736, 18736, 18736, 18737, 18740, 18740, 18740, 18740,
3951
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3952
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3953
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3954
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3955
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3956
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3957
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3958
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3959
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3960
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3961
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3962
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3963
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3964
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3965
     18740, 18740, 18740, 18740, 18740, 18740, 18740},
3966
    {18740, 18744, 18748, 18752, 18756, 18760, 18764, 18768, 18772, 18776,
3967
     18780, 18784, 18788, 18792, 18796, 18800, 18804, 18808, 18812, 18816,
3968
     18820, 18824, 18828, 18832, 18836, 18840, 18844, 18848, 18852, 18856,
3969
     18860, 18864, 18868, 18872, 18876, 18880, 18884, 18888, 18892, 18896,
3970
     18900, 18904, 18908, 18912, 18916, 18920, 18924, 18928, 18932, 18936,
3971
     18940, 18944, 18948, 18952, 18956, 18960, 18964, 18968, 18972, 18976,
3972
     18980, 18984, 18988, 18992, 18996, 19000, 19004, 19008, 19012, 19016,
3973
     19020, 19024, 19028, 19032, 19036, 19040, 19044, 19048, 19052, 19056,
3974
     19060, 19064, 19068, 19072, 19076, 19080, 19084, 19088, 19092, 19096,
3975
     19100, 19104, 19108, 19112, 19116, 19120, 19124, 19128, 19132, 19136,
3976
     19140, 19144, 19148, 19152, 19156, 19160, 19164, 19168, 19172, 19176,
3977
     19180, 19184, 19188, 19192, 19196, 19200, 19204, 19208, 19212, 19216,
3978
     19220, 19224, 19228, 19232, 19236, 19240, 19244, 19248, 19252, 19256,
3979
     19260, 19264, 19268, 19272, 19276, 19280, 19284, 19288, 19292, 19296,
3980
     19300, 19304, 19308, 19312, 19316, 19320, 19324, 19328, 19332, 19336,
3981
     19340, 19344, 19348, 19352, 19356, 19360, 19364, 19368, 19372, 19376,
3982
     19380, 19384, 19388, 19392, 19396, 19400, 19404, 19408, 19412, 19416,
3983
     19420, 19424, 19428, 19432, 19436, 19440, 19444, 19448, 19452, 19456,
3984
     19460, 19464, 19468, 19472, 19476, 19480, 19484, 19488, 19492, 19496,
3985
     19500, 19504, 19508, 19512, 19516, 19520, 19524, 19528, 19532, 19536,
3986
     19540, 19544, 19548, 19552, 19556, 19560, 19564, 19568, 19572, 19576,
3987
     19580, 19584, 19588, 19592, 19596, 19600, 19604, 19608, 19612, 19616,
3988
     19620, 19624, 19628, 19632, 19636, 19640, 19644, 19648, 19652, 19656,
3989
     19660, 19664, 19668, 19672, 19676, 19680, 19684, 19688, 19692, 19696,
3990
     19700, 19704, 19708, 19712, 19716, 19720, 19724, 19728, 19732, 19736,
3991
     19740, 19744, 19748, 19752, 19756, 19760, 19764},
3992
    {19764, 19768, 19772, 19776, 19780, 19784, 19788, 19792, 19796, 19800,
3993
     19804, 19808, 19812, 19816, 19820, 19820, 19820, 19824, 19824, 19828,
3994
     19828, 19828, 19832, 19836, 19840, 19844, 19848, 19852, 19856, 19860,
3995
     19864, 19868, 19868, 19872, 19872, 19876, 19876, 19876, 19880, 19884,
3996
     19884, 19884, 19884, 19888, 19892, 19896, 19900, 19904, 19908, 19912,
3997
     19916, 19920, 19924, 19928, 19932, 19936, 19940, 19944, 19948, 19952,
3998
     19956, 19960, 19964, 19968, 19972, 19976, 19980, 19984, 19988, 19992,
3999
     19996, 20000, 20004, 20008, 20012, 20016, 20020, 20024, 20028, 20032,
4000
     20036, 20040, 20044, 20048, 20052, 20056, 20060, 20064, 20068, 20072,
4001
     20076, 20080, 20084, 20088, 20092, 20096, 20100, 20104, 20108, 20112,
4002
     20116, 20120, 20124, 20128, 20132, 20136, 20140, 20144, 20148, 20152,
4003
     20156, 20156, 20156, 20160, 20164, 20168, 20172, 20176, 20180, 20184,
4004
     20188, 20192, 20196, 20200, 20204, 20208, 20212, 20216, 20220, 20224,
4005
     20228, 20232, 20236, 20240, 20244, 20248, 20252, 20256, 20260, 20264,
4006
     20268, 20272, 20276, 20280, 20284, 20288, 20292, 20296, 20300, 20304,
4007
     20308, 20312, 20316, 20320, 20324, 20328, 20332, 20336, 20340, 20344,
4008
     20348, 20352, 20356, 20360, 20364, 20368, 20372, 20376, 20380, 20384,
4009
     20388, 20392, 20396, 20400, 20404, 20408, 20412, 20416, 20420, 20424,
4010
     20428, 20432, 20436, 20440, 20444, 20448, 20452, 20456, 20460, 20464,
4011
     20468, 20472, 20476, 20480, 20484, 20488, 20492, 20496, 20500, 20504,
4012
     20508, 20512, 20516, 20520, 20524, 20528, 20532, 20536, 20540, 20544,
4013
     20548, 20552, 20556, 20560, 20564, 20568, 20572, 20576, 20580, 20580,
4014
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4015
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4016
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4017
     20580, 20580, 20580, 20580, 20580, 20580, 20581},
4018
    {20581, 20589, 20597, 20605, 20617, 20629, 20637, 20644, 20644, 20644,
4019
     20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20645,
4020
     20653, 20661, 20669, 20677, 20684, 20684, 20684, 20684, 20684, 20684,
4021
     20692, 20692, 20701, 20705, 20709, 20713, 20717, 20721, 20725, 20729,
4022
     20733, 20737, 20740, 20748, 20756, 20768, 20780, 20788, 20796, 20804,
4023
     20812, 20820, 20828, 20836, 20844, 20852, 20852, 20860, 20868, 20876,
4024
     20884, 20892, 20892, 20900, 20900, 20908, 20916, 20916, 20924, 20932,
4025
     20932, 20940, 20948, 20956, 20964, 20972, 20980, 20988, 20996, 21005,
4026
     21013, 21017, 21021, 21025, 21029, 21033, 21037, 21041, 21045, 21049,
4027
     21053, 21057, 21061, 21065, 21069, 21073, 21077, 21081, 21085, 21089,
4028
     21093, 21097, 21101, 21105, 21109, 21113, 21117, 21121, 21125, 21129,
4029
     21133, 21137, 21141, 21145, 21149, 21153, 21157, 21161, 21165, 21169,
4030
     21173, 21177, 21181, 21185, 21189, 21193, 21197, 21201, 21205, 21209,
4031
     21213, 21217, 21221, 21225, 21229, 21233, 21237, 21241, 21245, 21249,
4032
     21253, 21257, 21261, 21265, 21269, 21273, 21277, 21281, 21285, 21289,
4033
     21293, 21297, 21301, 21305, 21309, 21313, 21317, 21321, 21325, 21329,
4034
     21333, 21337, 21341, 21345, 21349, 21357, 21365, 21369, 21373, 21377,
4035
     21381, 21385, 21389, 21393, 21397, 21401, 21405, 21413, 21420, 21420,
4036
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4037
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4038
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4039
     21420, 21421, 21425, 21429, 21433, 21437, 21441, 21445, 21449, 21453,
4040
     21457, 21461, 21469, 21473, 21477, 21481, 21485, 21489, 21493, 21497,
4041
     21501, 21505, 21509, 21513, 21517, 21529, 21541, 21553, 21565, 21577,
4042
     21589, 21601, 21613, 21625, 21637, 21649, 21661, 21673, 21685, 21697,
4043
     21709, 21721, 21733, 21737, 21741, 21745, 21749},
4044
    {21749, 21761, 21773, 21785, 21797, 21809, 21817, 21825, 21833, 21841,
4045
     21849, 21857, 21865, 21873, 21881, 21889, 21897, 21905, 21913, 21921,
4046
     21929, 21937, 21945, 21953, 21961, 21969, 21977, 21985, 21993, 22001,
4047
     22009, 22017, 22025, 22033, 22041, 22049, 22057, 22065, 22073, 22081,
4048
     22089, 22097, 22105, 22113, 22121, 22129, 22137, 22145, 22153, 22161,
4049
     22169, 22177, 22185, 22193, 22201, 22209, 22217, 22225, 22233, 22241,
4050
     22249, 22257, 22265, 22273, 22281, 22289, 22297, 22305, 22313, 22321,
4051
     22329, 22337, 22345, 22353, 22361, 22369, 22377, 22385, 22393, 22401,
4052
     22409, 22417, 22425, 22433, 22441, 22449, 22457, 22465, 22473, 22481,
4053
     22489, 22497, 22505, 22513, 22521, 22533, 22545, 22557, 22569, 22581,
4054
     22593, 22605, 22617, 22629, 22641, 22653, 22665, 22673, 22681, 22689,
4055
     22697, 22705, 22713, 22721, 22729, 22737, 22745, 22753, 22761, 22769,
4056
     22777, 22785, 22793, 22801, 22809, 22817, 22825, 22833, 22841, 22849,
4057
     22857, 22865, 22873, 22881, 22889, 22897, 22905, 22913, 22921, 22929,
4058
     22937, 22945, 22953, 22961, 22969, 22977, 22985, 22993, 23001, 23009,
4059
     23017, 23025, 23037, 23049, 23061, 23073, 23085, 23093, 23101, 23109,
4060
     23117, 23125, 23133, 23141, 23149, 23157, 23165, 23173, 23181, 23189,
4061
     23197, 23205, 23213, 23221, 23229, 23237, 23245, 23253, 23261, 23269,
4062
     23277, 23285, 23293, 23301, 23309, 23317, 23325, 23333, 23341, 23349,
4063
     23357, 23365, 23373, 23381, 23389, 23397, 23405, 23413, 23421, 23429,
4064
     23437, 23445, 23453, 23461, 23469, 23477, 23485, 23493, 23501, 23509,
4065
     23517, 23525, 23533, 23541, 23549, 23557, 23565, 23573, 23581, 23589,
4066
     23597, 23605, 23613, 23621, 23633, 23645, 23653, 23661, 23669, 23677,
4067
     23685, 23693, 23701, 23709, 23717, 23725, 23733, 23741, 23749, 23757,
4068
     23765, 23773, 23781, 23793, 23805, 23817, 23825, 23833, 23841, 23849,
4069
     23857, 23865, 23873, 23881, 23889, 23897, 23905},
4070
    {23905, 23913, 23921, 23929, 23937, 23945, 23953, 23961, 23969, 23977,
4071
     23985, 23993, 24001, 24009, 24017, 24025, 24033, 24041, 24049, 24057,
4072
     24065, 24073, 24081, 24089, 24097, 24105, 24113, 24121, 24129, 24137,
4073
     24145, 24153, 24161, 24169, 24177, 24185, 24193, 24201, 24209, 24217,
4074
     24225, 24233, 24241, 24249, 24257, 24265, 24273, 24281, 24289, 24297,
4075
     24305, 24313, 24321, 24329, 24337, 24345, 24353, 24361, 24369, 24377,
4076
     24385, 24393, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4077
     24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4078
     24401, 24413, 24425, 24437, 24449, 24461, 24473, 24485, 24497, 24509,
4079
     24521, 24533, 24545, 24557, 24569, 24581, 24593, 24605, 24617, 24629,
4080
     24641, 24653, 24665, 24677, 24689, 24701, 24713, 24725, 24737, 24749,
4081
     24761, 24773, 24785, 24797, 24809, 24821, 24833, 24845, 24857, 24869,
4082
     24881, 24893, 24905, 24917, 24929, 24941, 24953, 24965, 24977, 24989,
4083
     25001, 25013, 25025, 25037, 25049, 25061, 25073, 25085, 25097, 25109,
4084
     25121, 25133, 25145, 25157, 25168, 25168, 25169, 25181, 25193, 25205,
4085
     25217, 25229, 25241, 25253, 25265, 25277, 25289, 25301, 25313, 25325,
4086
     25337, 25349, 25361, 25373, 25385, 25397, 25409, 25421, 25433, 25445,
4087
     25457, 25469, 25481, 25493, 25505, 25517, 25529, 25541, 25553, 25565,
4088
     25577, 25589, 25601, 25613, 25625, 25637, 25649, 25661, 25673, 25685,
4089
     25697, 25709, 25721, 25733, 25745, 25757, 25769, 25781, 25793, 25805,
4090
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4091
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4092
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4093
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4094
     25817, 25829, 25841, 25857, 25873, 25889, 25905, 25921, 25937, 25953,
4095
     25965, 26037, 26069, 26084, 26084, 26084, 26084},
4096
    {26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084,
4097
     26084, 26084, 26084, 26084, 26084, 26084, 26085, 26089, 26093, 26097,
4098
     26101, 26105, 26109, 26113, 26117, 26121, 26132, 26132, 26132, 26132,
4099
     26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132,
4100
     26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26133, 26141,
4101
     26145, 26149, 26153, 26157, 26161, 26165, 26169, 26173, 26177, 26181,
4102
     26185, 26189, 26193, 26197, 26201, 26205, 26209, 26213, 26217, 26220,
4103
     26220, 26221, 26225, 26229, 26237, 26245, 26253, 26261, 26265, 26269,
4104
     26273, 26277, 26281, 26284, 26285, 26289, 26293, 26297, 26301, 26305,
4105
     26309, 26313, 26317, 26321, 26325, 26329, 26333, 26337, 26341, 26345,
4106
     26349, 26353, 26357, 26360, 26361, 26365, 26369, 26373, 26376, 26376,
4107
     26376, 26376, 26377, 26385, 26393, 26400, 26401, 26408, 26409, 26417,
4108
     26425, 26433, 26441, 26449, 26457, 26465, 26473, 26481, 26489, 26493,
4109
     26501, 26509, 26517, 26525, 26533, 26541, 26549, 26557, 26565, 26573,
4110
     26581, 26589, 26593, 26597, 26601, 26605, 26609, 26613, 26617, 26621,
4111
     26625, 26629, 26633, 26637, 26641, 26645, 26649, 26653, 26657, 26661,
4112
     26665, 26669, 26673, 26677, 26681, 26685, 26689, 26693, 26697, 26701,
4113
     26705, 26709, 26713, 26717, 26721, 26725, 26729, 26733, 26737, 26741,
4114
     26745, 26749, 26753, 26757, 26761, 26765, 26769, 26773, 26777, 26781,
4115
     26785, 26789, 26793, 26797, 26801, 26805, 26809, 26813, 26817, 26821,
4116
     26825, 26829, 26833, 26837, 26841, 26845, 26849, 26853, 26857, 26861,
4117
     26865, 26869, 26873, 26877, 26881, 26885, 26889, 26893, 26897, 26901,
4118
     26905, 26909, 26913, 26917, 26921, 26925, 26929, 26933, 26937, 26941,
4119
     26945, 26949, 26953, 26957, 26961, 26965, 26969, 26973, 26977, 26981,
4120
     26985, 26989, 26993, 26997, 27001, 27005, 27017, 27029, 27041, 27053,
4121
     27065, 27077, 27085, 27092, 27092, 27092, 27092},
4122
    {27092, 27093, 27097, 27101, 27105, 27109, 27113, 27117, 27121, 27125,
4123
     27129, 27133, 27137, 27141, 27145, 27149, 27153, 27157, 27161, 27165,
4124
     27169, 27173, 27177, 27181, 27185, 27189, 27193, 27197, 27201, 27205,
4125
     27209, 27213, 27217, 27221, 27225, 27229, 27233, 27237, 27241, 27245,
4126
     27249, 27253, 27257, 27261, 27265, 27269, 27273, 27277, 27281, 27285,
4127
     27289, 27293, 27297, 27301, 27305, 27309, 27313, 27317, 27321, 27325,
4128
     27329, 27333, 27337, 27341, 27345, 27349, 27353, 27357, 27361, 27365,
4129
     27369, 27373, 27377, 27381, 27385, 27389, 27393, 27397, 27401, 27405,
4130
     27409, 27413, 27417, 27421, 27425, 27429, 27433, 27437, 27441, 27445,
4131
     27449, 27453, 27457, 27461, 27465, 27469, 27473, 27477, 27481, 27485,
4132
     27489, 27493, 27497, 27501, 27505, 27509, 27513, 27517, 27521, 27525,
4133
     27529, 27533, 27537, 27541, 27545, 27549, 27553, 27557, 27561, 27565,
4134
     27569, 27573, 27577, 27581, 27585, 27589, 27593, 27597, 27601, 27605,
4135
     27609, 27613, 27617, 27621, 27625, 27629, 27633, 27637, 27641, 27645,
4136
     27649, 27653, 27657, 27661, 27665, 27669, 27673, 27677, 27681, 27685,
4137
     27689, 27693, 27697, 27701, 27705, 27709, 27713, 27717, 27721, 27725,
4138
     27729, 27733, 27737, 27741, 27745, 27749, 27753, 27757, 27761, 27765,
4139
     27769, 27773, 27777, 27781, 27785, 27789, 27793, 27797, 27801, 27805,
4140
     27809, 27813, 27817, 27821, 27825, 27829, 27833, 27837, 27841, 27845,
4141
     27849, 27852, 27852, 27852, 27853, 27857, 27861, 27865, 27869, 27873,
4142
     27876, 27876, 27877, 27881, 27885, 27889, 27893, 27897, 27900, 27900,
4143
     27901, 27905, 27909, 27913, 27917, 27921, 27924, 27924, 27925, 27929,
4144
     27933, 27936, 27936, 27936, 27937, 27941, 27945, 27949, 27957, 27961,
4145
     27965, 27968, 27969, 27973, 27977, 27981, 27985, 27989, 27993, 27996,
4146
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4147
     27996, 27996, 27996, 27996, 27996, 27996, 27996},
4148
    {27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4149
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4150
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4151
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4152
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4153
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4154
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4155
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4156
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4157
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4158
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4159
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4160
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27997,
4161
     28001, 28005, 28009, 28013, 28016, 28017, 28021, 28025, 28029, 28033,
4162
     28037, 28041, 28045, 28049, 28053, 28057, 28061, 28065, 28069, 28073,
4163
     28077, 28081, 28085, 28089, 28093, 28097, 28101, 28105, 28109, 28113,
4164
     28117, 28121, 28125, 28129, 28133, 28137, 28141, 28145, 28149, 28153,
4165
     28157, 28161, 28165, 28169, 28173, 28177, 28181, 28184, 28185, 28189,
4166
     28193, 28197, 28201, 28205, 28209, 28213, 28217, 28220, 28220, 28220,
4167
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4168
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4169
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4170
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4171
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4172
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4173
     28220, 28220, 28220, 28220, 28220, 28220, 28220},
4174
    {28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4175
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4176
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4177
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4178
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4179
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4180
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4181
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4182
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4183
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4184
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4185
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4186
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4187
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4188
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4189
     28220, 28220, 28220, 28220, 28220, 28228, 28228, 28236, 28236, 28236,
4190
     28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236,
4191
     28236, 28236, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4192
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4193
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4194
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4195
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4196
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4197
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4198
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4199
     28244, 28244, 28244, 28244, 28244, 28244, 28244},
4200
    {28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4201
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4202
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4203
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4204
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28252, 28260, 28260,
4205
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4206
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4207
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4208
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4209
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4210
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4211
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4212
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4213
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4214
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4215
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4216
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4217
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4218
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4219
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4220
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4221
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4222
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4223
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4224
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4225
     28260, 28260, 28260, 28260, 28260, 28260, 28260},
4226
    {28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 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, 28268, 28276, 28276, 28276,
4234
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4235
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4236
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4237
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4238
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4239
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4240
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4241
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4242
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4243
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4244
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4245
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4246
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4247
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4248
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4249
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4250
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4251
     28276, 28276, 28276, 28276, 28276, 28276, 28276},
4252
    {28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4253
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4254
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4255
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 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, 28284, 28292,
4271
     28292, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4272
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4273
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4274
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4275
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4276
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4277
     28300, 28300, 28300, 28300, 28300, 28300, 28300},
4278
    {28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4279
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4280
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4281
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4282
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4283
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4284
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4285
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4286
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4287
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4288
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4289
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4290
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4291
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4292
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4293
     28300, 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, 28308, 28316, 28316,
4297
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4298
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4299
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4300
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4301
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4302
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4303
     28316, 28316, 28316, 28316, 28316, 28316, 28316},
4304
    {28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4305
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4306
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4307
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4308
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4309
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28324, 28324, 28324,
4310
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4311
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4312
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4313
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4314
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4315
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4316
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4317
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4318
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4319
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4320
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4321
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4322
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4323
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4324
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4325
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4326
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4327
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4328
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4329
     28324, 28324, 28324, 28324, 28324, 28324, 28324},
4330
    {28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4331
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 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, 28332, 28340, 28352, 28364, 28376,
4340
     28388, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4341
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4342
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4343
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4344
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4345
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4346
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4347
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4348
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28408, 28416,
4349
     28428, 28440, 28452, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4350
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4351
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4352
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4353
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4354
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4355
     28464, 28464, 28464, 28464, 28464, 28464, 28464},
4356
    {28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4357
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4358
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4359
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4360
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4361
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4362
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4363
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4364
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4365
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4366
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4367
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4368
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4369
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4370
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4371
     28464, 28464, 28464, 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, 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, 28465},
4382
    {28465, 28469, 28473, 28477, 28481, 28485, 28489, 28493, 28497, 28501,
4383
     28505, 28509, 28513, 28517, 28521, 28525, 28529, 28533, 28537, 28541,
4384
     28545, 28549, 28553, 28557, 28561, 28565, 28569, 28573, 28577, 28581,
4385
     28585, 28589, 28593, 28597, 28601, 28605, 28609, 28613, 28617, 28621,
4386
     28625, 28629, 28633, 28637, 28641, 28645, 28649, 28653, 28657, 28661,
4387
     28665, 28669, 28673, 28677, 28681, 28685, 28689, 28693, 28697, 28701,
4388
     28705, 28709, 28713, 28717, 28721, 28725, 28729, 28733, 28737, 28741,
4389
     28745, 28749, 28753, 28757, 28761, 28765, 28769, 28773, 28777, 28781,
4390
     28785, 28789, 28793, 28797, 28801, 28804, 28805, 28809, 28813, 28817,
4391
     28821, 28825, 28829, 28833, 28837, 28841, 28845, 28849, 28853, 28857,
4392
     28861, 28865, 28869, 28873, 28877, 28881, 28885, 28889, 28893, 28897,
4393
     28901, 28905, 28909, 28913, 28917, 28921, 28925, 28929, 28933, 28937,
4394
     28941, 28945, 28949, 28953, 28957, 28961, 28965, 28969, 28973, 28977,
4395
     28981, 28985, 28989, 28993, 28997, 29001, 29005, 29009, 29013, 29017,
4396
     29021, 29025, 29029, 29033, 29037, 29041, 29045, 29049, 29053, 29057,
4397
     29061, 29065, 29069, 29073, 29077, 29081, 29085, 29088, 29089, 29093,
4398
     29096, 29096, 29097, 29100, 29100, 29101, 29105, 29108, 29108, 29109,
4399
     29113, 29117, 29121, 29124, 29125, 29129, 29133, 29137, 29141, 29145,
4400
     29149, 29153, 29157, 29161, 29165, 29169, 29172, 29173, 29176, 29177,
4401
     29181, 29185, 29189, 29193, 29197, 29201, 29204, 29205, 29209, 29213,
4402
     29217, 29221, 29225, 29229, 29233, 29237, 29241, 29245, 29249, 29253,
4403
     29257, 29261, 29265, 29269, 29273, 29277, 29281, 29285, 29289, 29293,
4404
     29297, 29301, 29305, 29309, 29313, 29317, 29321, 29325, 29329, 29333,
4405
     29337, 29341, 29345, 29349, 29353, 29357, 29361, 29365, 29369, 29373,
4406
     29377, 29381, 29385, 29389, 29393, 29397, 29401, 29405, 29409, 29413,
4407
     29417, 29421, 29425, 29429, 29433, 29437, 29441},
4408
    {29441, 29445, 29449, 29453, 29457, 29461, 29464, 29465, 29469, 29473,
4409
     29477, 29480, 29480, 29481, 29485, 29489, 29493, 29497, 29501, 29505,
4410
     29509, 29512, 29513, 29517, 29521, 29525, 29529, 29533, 29537, 29540,
4411
     29541, 29545, 29549, 29553, 29557, 29561, 29565, 29569, 29573, 29577,
4412
     29581, 29585, 29589, 29593, 29597, 29601, 29605, 29609, 29613, 29617,
4413
     29621, 29625, 29629, 29633, 29637, 29641, 29645, 29649, 29652, 29653,
4414
     29657, 29661, 29665, 29668, 29669, 29673, 29677, 29681, 29685, 29688,
4415
     29689, 29692, 29692, 29692, 29693, 29697, 29701, 29705, 29709, 29713,
4416
     29717, 29720, 29721, 29725, 29729, 29733, 29737, 29741, 29745, 29749,
4417
     29753, 29757, 29761, 29765, 29769, 29773, 29777, 29781, 29785, 29789,
4418
     29793, 29797, 29801, 29805, 29809, 29813, 29817, 29821, 29825, 29829,
4419
     29833, 29837, 29841, 29845, 29849, 29853, 29857, 29861, 29865, 29869,
4420
     29873, 29877, 29881, 29885, 29889, 29893, 29897, 29901, 29905, 29909,
4421
     29913, 29917, 29921, 29925, 29929, 29933, 29937, 29941, 29945, 29949,
4422
     29953, 29957, 29961, 29965, 29969, 29973, 29977, 29981, 29985, 29989,
4423
     29993, 29997, 30001, 30005, 30009, 30013, 30017, 30021, 30025, 30029,
4424
     30033, 30037, 30041, 30045, 30049, 30053, 30057, 30061, 30065, 30069,
4425
     30073, 30077, 30081, 30085, 30089, 30093, 30097, 30101, 30105, 30109,
4426
     30113, 30117, 30121, 30125, 30129, 30133, 30137, 30141, 30145, 30149,
4427
     30153, 30157, 30161, 30165, 30169, 30173, 30177, 30181, 30185, 30189,
4428
     30193, 30197, 30201, 30205, 30209, 30213, 30217, 30221, 30225, 30229,
4429
     30233, 30237, 30241, 30245, 30249, 30253, 30257, 30261, 30265, 30269,
4430
     30273, 30277, 30281, 30285, 30289, 30293, 30297, 30301, 30305, 30309,
4431
     30313, 30317, 30321, 30325, 30329, 30333, 30337, 30341, 30345, 30349,
4432
     30353, 30357, 30361, 30365, 30369, 30373, 30377, 30381, 30385, 30389,
4433
     30393, 30397, 30401, 30405, 30409, 30413, 30417},
4434
    {30417, 30421, 30425, 30429, 30433, 30437, 30441, 30445, 30449, 30453,
4435
     30457, 30461, 30465, 30469, 30473, 30477, 30481, 30485, 30489, 30493,
4436
     30497, 30501, 30505, 30509, 30513, 30517, 30521, 30525, 30529, 30533,
4437
     30537, 30541, 30545, 30549, 30553, 30557, 30561, 30565, 30569, 30573,
4438
     30577, 30581, 30585, 30589, 30593, 30597, 30601, 30605, 30609, 30613,
4439
     30617, 30621, 30625, 30629, 30633, 30637, 30641, 30645, 30649, 30653,
4440
     30657, 30661, 30665, 30669, 30673, 30677, 30681, 30685, 30689, 30693,
4441
     30697, 30701, 30705, 30709, 30713, 30717, 30721, 30725, 30729, 30733,
4442
     30737, 30741, 30745, 30749, 30753, 30757, 30761, 30765, 30769, 30773,
4443
     30777, 30781, 30785, 30789, 30793, 30797, 30801, 30805, 30809, 30813,
4444
     30817, 30821, 30825, 30829, 30833, 30837, 30841, 30845, 30849, 30853,
4445
     30857, 30861, 30865, 30869, 30873, 30877, 30881, 30885, 30889, 30893,
4446
     30897, 30901, 30905, 30909, 30913, 30917, 30921, 30925, 30929, 30933,
4447
     30937, 30941, 30945, 30949, 30953, 30957, 30961, 30965, 30969, 30973,
4448
     30977, 30981, 30985, 30989, 30993, 30997, 31001, 31005, 31009, 31013,
4449
     31017, 31021, 31025, 31029, 31033, 31037, 31041, 31045, 31049, 31053,
4450
     31057, 31061, 31065, 31069, 31073, 31077, 31080, 31080, 31081, 31085,
4451
     31089, 31093, 31097, 31101, 31105, 31109, 31113, 31117, 31121, 31125,
4452
     31129, 31133, 31137, 31141, 31145, 31149, 31153, 31157, 31161, 31165,
4453
     31169, 31173, 31177, 31181, 31185, 31189, 31193, 31197, 31201, 31205,
4454
     31209, 31213, 31217, 31221, 31225, 31229, 31233, 31237, 31241, 31245,
4455
     31249, 31253, 31257, 31261, 31265, 31269, 31273, 31277, 31281, 31285,
4456
     31289, 31293, 31297, 31301, 31305, 31309, 31313, 31317, 31321, 31325,
4457
     31329, 31333, 31337, 31341, 31345, 31349, 31353, 31357, 31361, 31365,
4458
     31369, 31373, 31377, 31381, 31385, 31389, 31393, 31397, 31401, 31405,
4459
     31409, 31413, 31417, 31421, 31425, 31429, 31433},
4460
    {31433, 31437, 31441, 31445, 31449, 31453, 31457, 31461, 31465, 31469,
4461
     31473, 31477, 31481, 31485, 31489, 31493, 31497, 31501, 31505, 31509,
4462
     31513, 31517, 31521, 31525, 31529, 31533, 31537, 31541, 31545, 31549,
4463
     31553, 31557, 31561, 31565, 31569, 31573, 31577, 31581, 31585, 31589,
4464
     31593, 31597, 31601, 31605, 31609, 31613, 31617, 31621, 31625, 31629,
4465
     31633, 31637, 31641, 31645, 31649, 31653, 31657, 31661, 31665, 31669,
4466
     31673, 31677, 31681, 31685, 31689, 31693, 31697, 31701, 31705, 31709,
4467
     31713, 31717, 31721, 31725, 31729, 31733, 31737, 31741, 31745, 31749,
4468
     31753, 31757, 31761, 31765, 31769, 31773, 31777, 31781, 31785, 31789,
4469
     31793, 31797, 31801, 31805, 31809, 31813, 31817, 31821, 31825, 31829,
4470
     31833, 31837, 31841, 31845, 31849, 31853, 31857, 31861, 31865, 31869,
4471
     31873, 31877, 31881, 31885, 31889, 31893, 31897, 31901, 31905, 31909,
4472
     31913, 31917, 31921, 31925, 31929, 31933, 31937, 31941, 31945, 31949,
4473
     31953, 31957, 31961, 31965, 31969, 31973, 31977, 31981, 31985, 31989,
4474
     31993, 31997, 32001, 32005, 32009, 32013, 32017, 32021, 32025, 32029,
4475
     32033, 32037, 32041, 32045, 32049, 32053, 32057, 32061, 32065, 32069,
4476
     32073, 32077, 32081, 32085, 32089, 32093, 32097, 32101, 32105, 32109,
4477
     32113, 32117, 32121, 32125, 32129, 32133, 32137, 32141, 32145, 32149,
4478
     32153, 32157, 32161, 32165, 32169, 32173, 32177, 32181, 32185, 32189,
4479
     32193, 32197, 32201, 32205, 32209, 32213, 32217, 32221, 32225, 32229,
4480
     32233, 32237, 32241, 32245, 32248, 32248, 32249, 32253, 32257, 32261,
4481
     32265, 32269, 32273, 32277, 32281, 32285, 32289, 32293, 32297, 32301,
4482
     32305, 32309, 32313, 32317, 32321, 32325, 32329, 32333, 32337, 32341,
4483
     32345, 32349, 32353, 32357, 32361, 32365, 32369, 32373, 32377, 32381,
4484
     32385, 32389, 32393, 32397, 32401, 32405, 32409, 32413, 32417, 32421,
4485
     32425, 32429, 32433, 32437, 32441, 32445, 32448},
4486
    {32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4487
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4488
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4489
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4490
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32449, 32453,
4491
     32457, 32461, 32465, 32469, 32473, 32477, 32481, 32485, 32489, 32493,
4492
     32497, 32501, 32505, 32509, 32513, 32517, 32521, 32525, 32529, 32533,
4493
     32537, 32541, 32545, 32549, 32553, 32557, 32561, 32565, 32569, 32573,
4494
     32577, 32581, 32585, 32589, 32593, 32597, 32601, 32605, 32609, 32613,
4495
     32617, 32621, 32625, 32629, 32633, 32637, 32641, 32645, 32649, 32653,
4496
     32657, 32661, 32665, 32669, 32673, 32677, 32681, 32685, 32689, 32693,
4497
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4498
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4499
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4500
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4501
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4502
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4503
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4504
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4505
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4506
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4507
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4508
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4509
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4510
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4511
     32696, 32696, 32696, 32696, 32696, 32696, 32696},
4512
    {32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4513
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4514
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4515
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4516
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4517
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4518
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
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, 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, 32697},
4538
    {32697, 32701, 32705, 32709, 32712, 32713, 32717, 32721, 32725, 32729,
4539
     32733, 32737, 32741, 32745, 32749, 32753, 32757, 32761, 32765, 32769,
4540
     32773, 32777, 32781, 32785, 32789, 32793, 32797, 32801, 32805, 32809,
4541
     32813, 32817, 32820, 32821, 32825, 32828, 32829, 32832, 32832, 32833,
4542
     32836, 32837, 32841, 32845, 32849, 32853, 32857, 32861, 32865, 32869,
4543
     32873, 32876, 32877, 32881, 32885, 32889, 32892, 32893, 32896, 32897,
4544
     32900, 32900, 32900, 32900, 32900, 32900, 32901, 32904, 32904, 32904,
4545
     32904, 32905, 32908, 32909, 32912, 32913, 32916, 32917, 32921, 32925,
4546
     32928, 32929, 32933, 32936, 32937, 32940, 32940, 32941, 32944, 32945,
4547
     32948, 32949, 32952, 32953, 32956, 32957, 32960, 32961, 32965, 32968,
4548
     32969, 32972, 32972, 32973, 32977, 32981, 32985, 32988, 32989, 32993,
4549
     32997, 33001, 33005, 33009, 33013, 33016, 33017, 33021, 33025, 33029,
4550
     33032, 33033, 33037, 33041, 33045, 33048, 33049, 33052, 33053, 33057,
4551
     33061, 33065, 33069, 33073, 33077, 33081, 33085, 33089, 33092, 33093,
4552
     33097, 33101, 33105, 33109, 33113, 33117, 33121, 33125, 33129, 33133,
4553
     33137, 33141, 33145, 33149, 33153, 33157, 33160, 33160, 33160, 33160,
4554
     33160, 33161, 33165, 33169, 33172, 33173, 33177, 33181, 33185, 33189,
4555
     33192, 33193, 33197, 33201, 33205, 33209, 33213, 33217, 33221, 33225,
4556
     33229, 33233, 33237, 33241, 33245, 33249, 33253, 33257, 33260, 33260,
4557
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4558
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4559
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4560
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4561
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4562
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4563
     33260, 33260, 33260, 33260, 33260, 33260, 33260},
4564
    {33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4565
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4566
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4567
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4568
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4569
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4570
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4571
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4572
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4573
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4574
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4575
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4576
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4577
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4578
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 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, 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, 33261},
4590
    {33261, 33269, 33277, 33285, 33293, 33301, 33309, 33317, 33325, 33333,
4591
     33341, 33348, 33348, 33348, 33348, 33348, 33349, 33361, 33373, 33385,
4592
     33397, 33409, 33421, 33433, 33445, 33457, 33469, 33481, 33493, 33505,
4593
     33517, 33529, 33541, 33553, 33565, 33577, 33589, 33601, 33613, 33625,
4594
     33637, 33649, 33661, 33673, 33677, 33681, 33689, 33696, 33697, 33701,
4595
     33705, 33709, 33713, 33717, 33721, 33725, 33729, 33733, 33737, 33741,
4596
     33745, 33749, 33753, 33757, 33761, 33765, 33769, 33773, 33777, 33781,
4597
     33785, 33789, 33793, 33797, 33801, 33809, 33817, 33825, 33833, 33845,
4598
     33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4599
     33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4600
     33852, 33852, 33852, 33852, 33852, 33852, 33853, 33861, 33869, 33876,
4601
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4602
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4603
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4604
     33876, 33876, 33876, 33876, 33877, 33884, 33884, 33884, 33884, 33884,
4605
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4606
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4607
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4608
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4609
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4610
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4611
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4612
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4613
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4614
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4615
     33884, 33884, 33884, 33884, 33884, 33884, 33885},
4616
    {33885, 33893, 33901, 33904, 33904, 33904, 33904, 33904, 33904, 33904,
4617
     33904, 33904, 33904, 33904, 33904, 33904, 33905, 33909, 33913, 33917,
4618
     33925, 33929, 33933, 33937, 33941, 33945, 33949, 33953, 33957, 33961,
4619
     33965, 33969, 33973, 33977, 33981, 33985, 33989, 33993, 33997, 34001,
4620
     34005, 34009, 34013, 34017, 34021, 34025, 34029, 34033, 34037, 34041,
4621
     34045, 34049, 34053, 34057, 34061, 34065, 34069, 34073, 34077, 34081,
4622
     34084, 34084, 34084, 34084, 34085, 34097, 34109, 34121, 34133, 34145,
4623
     34157, 34169, 34181, 34192, 34192, 34192, 34192, 34192, 34192, 34192,
4624
     34193, 34197, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4625
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4626
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4627
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4628
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4629
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4630
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4631
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4632
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4633
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4634
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4635
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4636
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4637
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4638
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4639
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4640
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4641
     34200, 34200, 34200, 34200, 34200, 34200, 34200},
4642
    {34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4643
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4644
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4645
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4646
     34200, 34200, 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, 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
     34201, 34205, 34209, 34213, 34217, 34221, 34225, 34229, 34233, 34237,
4667
     34240, 34240, 34240, 34240, 34240, 34240, 34240},
4668
    {34240, 34244, 34248, 34252, 34256, 34260, 34264, 34268, 34272, 34276,
4669
     34280, 34284, 34288, 34292, 34296, 34300, 34304, 34308, 34312, 34316,
4670
     34320, 34324, 34328, 34332, 34336, 34340, 34344, 34348, 34352, 34356,
4671
     34360, 34364, 34368, 34372, 34376, 34380, 34384, 34388, 34392, 34396,
4672
     34400, 34404, 34408, 34412, 34416, 34420, 34424, 34428, 34432, 34436,
4673
     34440, 34444, 34448, 34452, 34456, 34460, 34464, 34468, 34472, 34476,
4674
     34480, 34484, 34488, 34492, 34496, 34500, 34504, 34508, 34512, 34516,
4675
     34520, 34524, 34528, 34532, 34536, 34540, 34544, 34548, 34552, 34556,
4676
     34560, 34564, 34568, 34572, 34576, 34580, 34584, 34588, 34592, 34596,
4677
     34600, 34604, 34608, 34612, 34616, 34620, 34624, 34628, 34632, 34636,
4678
     34640, 34644, 34648, 34652, 34656, 34660, 34664, 34668, 34672, 34676,
4679
     34680, 34684, 34688, 34692, 34696, 34700, 34704, 34708, 34712, 34716,
4680
     34720, 34724, 34728, 34732, 34736, 34740, 34744, 34748, 34752, 34756,
4681
     34760, 34764, 34768, 34772, 34776, 34780, 34784, 34788, 34792, 34796,
4682
     34800, 34804, 34808, 34812, 34816, 34820, 34824, 34828, 34832, 34836,
4683
     34840, 34844, 34848, 34852, 34856, 34860, 34864, 34868, 34872, 34876,
4684
     34880, 34884, 34888, 34892, 34896, 34900, 34904, 34908, 34912, 34916,
4685
     34920, 34924, 34928, 34932, 34936, 34940, 34944, 34948, 34952, 34956,
4686
     34960, 34964, 34968, 34972, 34976, 34980, 34984, 34988, 34992, 34996,
4687
     35000, 35004, 35008, 35012, 35016, 35020, 35024, 35028, 35032, 35036,
4688
     35040, 35044, 35048, 35052, 35056, 35060, 35064, 35068, 35072, 35076,
4689
     35080, 35084, 35088, 35092, 35096, 35100, 35104, 35108, 35112, 35116,
4690
     35120, 35124, 35128, 35132, 35136, 35140, 35144, 35148, 35152, 35156,
4691
     35160, 35164, 35168, 35172, 35176, 35180, 35184, 35188, 35192, 35196,
4692
     35200, 35204, 35208, 35212, 35216, 35220, 35224, 35228, 35232, 35236,
4693
     35240, 35244, 35248, 35252, 35256, 35260, 35264},
4694
    {35264, 35268, 35272, 35276, 35280, 35284, 35288, 35292, 35296, 35300,
4695
     35304, 35308, 35312, 35316, 35320, 35324, 35328, 35332, 35336, 35340,
4696
     35344, 35348, 35352, 35356, 35360, 35364, 35368, 35372, 35376, 35380,
4697
     35384, 35388, 35392, 35396, 35400, 35404, 35408, 35412, 35416, 35420,
4698
     35424, 35428, 35432, 35436, 35440, 35444, 35448, 35452, 35456, 35460,
4699
     35464, 35468, 35472, 35476, 35480, 35484, 35488, 35492, 35496, 35500,
4700
     35504, 35508, 35512, 35516, 35520, 35524, 35528, 35532, 35536, 35540,
4701
     35544, 35548, 35552, 35556, 35560, 35564, 35568, 35572, 35576, 35580,
4702
     35584, 35588, 35592, 35596, 35600, 35604, 35608, 35612, 35616, 35620,
4703
     35624, 35628, 35632, 35636, 35640, 35644, 35648, 35652, 35656, 35660,
4704
     35664, 35668, 35672, 35676, 35680, 35684, 35688, 35692, 35696, 35700,
4705
     35704, 35708, 35712, 35716, 35720, 35724, 35728, 35732, 35736, 35740,
4706
     35744, 35748, 35752, 35756, 35760, 35764, 35768, 35772, 35776, 35780,
4707
     35784, 35788, 35792, 35796, 35800, 35804, 35808, 35812, 35816, 35820,
4708
     35824, 35828, 35832, 35836, 35840, 35844, 35848, 35852, 35856, 35860,
4709
     35864, 35868, 35872, 35876, 35880, 35884, 35888, 35892, 35896, 35900,
4710
     35904, 35908, 35912, 35916, 35920, 35924, 35928, 35932, 35936, 35940,
4711
     35944, 35948, 35952, 35956, 35960, 35964, 35968, 35972, 35976, 35980,
4712
     35984, 35988, 35992, 35996, 36000, 36004, 36008, 36012, 36016, 36020,
4713
     36024, 36028, 36032, 36036, 36040, 36044, 36048, 36052, 36056, 36060,
4714
     36064, 36068, 36072, 36076, 36080, 36084, 36088, 36092, 36096, 36100,
4715
     36104, 36108, 36112, 36116, 36120, 36124, 36128, 36132, 36136, 36140,
4716
     36144, 36148, 36152, 36156, 36160, 36164, 36168, 36172, 36176, 36180,
4717
     36184, 36188, 36192, 36196, 36200, 36204, 36208, 36212, 36216, 36220,
4718
     36224, 36228, 36232, 36236, 36240, 36244, 36248, 36252, 36256, 36260,
4719
     36264, 36268, 36272, 36276, 36280, 36284, 36288},
4720
    {36288, 36292, 36296, 36300, 36304, 36308, 36312, 36316, 36320, 36324,
4721
     36328, 36332, 36336, 36340, 36344, 36348, 36352, 36356, 36360, 36364,
4722
     36368, 36372, 36376, 36380, 36384, 36388, 36392, 36396, 36400, 36404,
4723
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4724
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4725
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4726
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4727
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4728
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4729
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4730
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4731
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4732
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4733
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4734
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4735
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4736
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4737
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4738
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4739
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4740
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4741
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4742
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4743
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4744
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4745
     36408, 36408, 36408, 36408, 36408, 36408, 36408}};
4746
const char32_t decomposition_data[9102] = {
4747
    0,      32,     32,     776,    97,     32,     772,    50,     51,
4748
    32,     769,    956,    32,     807,    49,     111,    49,     8260,
4749
    52,     49,     8260,   50,     51,     8260,   52,     65,     768,
4750
    65,     769,    65,     770,    65,     771,    65,     776,    65,
4751
    778,    67,     807,    69,     768,    69,     769,    69,     770,
4752
    69,     776,    73,     768,    73,     769,    73,     770,    73,
4753
    776,    78,     771,    79,     768,    79,     769,    79,     770,
4754
    79,     771,    79,     776,    85,     768,    85,     769,    85,
4755
    770,    85,     776,    89,     769,    97,     768,    97,     769,
4756
    97,     770,    97,     771,    97,     776,    97,     778,    99,
4757
    807,    101,    768,    101,    769,    101,    770,    101,    776,
4758
    105,    768,    105,    769,    105,    770,    105,    776,    110,
4759
    771,    111,    768,    111,    769,    111,    770,    111,    771,
4760
    111,    776,    117,    768,    117,    769,    117,    770,    117,
4761
    776,    121,    769,    121,    776,    65,     772,    97,     772,
4762
    65,     774,    97,     774,    65,     808,    97,     808,    67,
4763
    769,    99,     769,    67,     770,    99,     770,    67,     775,
4764
    99,     775,    67,     780,    99,     780,    68,     780,    100,
4765
    780,    69,     772,    101,    772,    69,     774,    101,    774,
4766
    69,     775,    101,    775,    69,     808,    101,    808,    69,
4767
    780,    101,    780,    71,     770,    103,    770,    71,     774,
4768
    103,    774,    71,     775,    103,    775,    71,     807,    103,
4769
    807,    72,     770,    104,    770,    73,     771,    105,    771,
4770
    73,     772,    105,    772,    73,     774,    105,    774,    73,
4771
    808,    105,    808,    73,     775,    73,     74,     105,    106,
4772
    74,     770,    106,    770,    75,     807,    107,    807,    76,
4773
    769,    108,    769,    76,     807,    108,    807,    76,     780,
4774
    108,    780,    76,     183,    108,    183,    78,     769,    110,
4775
    769,    78,     807,    110,    807,    78,     780,    110,    780,
4776
    700,    110,    79,     772,    111,    772,    79,     774,    111,
4777
    774,    79,     779,    111,    779,    82,     769,    114,    769,
4778
    82,     807,    114,    807,    82,     780,    114,    780,    83,
4779
    769,    115,    769,    83,     770,    115,    770,    83,     807,
4780
    115,    807,    83,     780,    115,    780,    84,     807,    116,
4781
    807,    84,     780,    116,    780,    85,     771,    117,    771,
4782
    85,     772,    117,    772,    85,     774,    117,    774,    85,
4783
    778,    117,    778,    85,     779,    117,    779,    85,     808,
4784
    117,    808,    87,     770,    119,    770,    89,     770,    121,
4785
    770,    89,     776,    90,     769,    122,    769,    90,     775,
4786
    122,    775,    90,     780,    122,    780,    115,    79,     795,
4787
    111,    795,    85,     795,    117,    795,    68,     90,     780,
4788
    68,     122,    780,    100,    122,    780,    76,     74,     76,
4789
    106,    108,    106,    78,     74,     78,     106,    110,    106,
4790
    65,     780,    97,     780,    73,     780,    105,    780,    79,
4791
    780,    111,    780,    85,     780,    117,    780,    85,     776,
4792
    772,    117,    776,    772,    85,     776,    769,    117,    776,
4793
    769,    85,     776,    780,    117,    776,    780,    85,     776,
4794
    768,    117,    776,    768,    65,     776,    772,    97,     776,
4795
    772,    65,     775,    772,    97,     775,    772,    198,    772,
4796
    230,    772,    71,     780,    103,    780,    75,     780,    107,
4797
    780,    79,     808,    111,    808,    79,     808,    772,    111,
4798
    808,    772,    439,    780,    658,    780,    106,    780,    68,
4799
    90,     68,     122,    100,    122,    71,     769,    103,    769,
4800
    78,     768,    110,    768,    65,     778,    769,    97,     778,
4801
    769,    198,    769,    230,    769,    216,    769,    248,    769,
4802
    65,     783,    97,     783,    65,     785,    97,     785,    69,
4803
    783,    101,    783,    69,     785,    101,    785,    73,     783,
4804
    105,    783,    73,     785,    105,    785,    79,     783,    111,
4805
    783,    79,     785,    111,    785,    82,     783,    114,    783,
4806
    82,     785,    114,    785,    85,     783,    117,    783,    85,
4807
    785,    117,    785,    83,     806,    115,    806,    84,     806,
4808
    116,    806,    72,     780,    104,    780,    65,     775,    97,
4809
    775,    69,     807,    101,    807,    79,     776,    772,    111,
4810
    776,    772,    79,     771,    772,    111,    771,    772,    79,
4811
    775,    111,    775,    79,     775,    772,    111,    775,    772,
4812
    89,     772,    121,    772,    104,    614,    106,    114,    633,
4813
    635,    641,    119,    121,    32,     774,    32,     775,    32,
4814
    778,    32,     808,    32,     771,    32,     779,    611,    108,
4815
    115,    120,    661,    768,    769,    787,    776,    769,    697,
4816
    32,     837,    59,     32,     769,    168,    769,    913,    769,
4817
    183,    917,    769,    919,    769,    921,    769,    927,    769,
4818
    933,    769,    937,    769,    953,    776,    769,    921,    776,
4819
    933,    776,    945,    769,    949,    769,    951,    769,    953,
4820
    769,    965,    776,    769,    953,    776,    965,    776,    959,
4821
    769,    965,    769,    969,    769,    946,    952,    933,    978,
4822
    769,    978,    776,    966,    960,    954,    961,    962,    920,
4823
    949,    931,    1045,   768,    1045,   776,    1043,   769,    1030,
4824
    776,    1050,   769,    1048,   768,    1059,   774,    1048,   774,
4825
    1080,   774,    1077,   768,    1077,   776,    1075,   769,    1110,
4826
    776,    1082,   769,    1080,   768,    1091,   774,    1140,   783,
4827
    1141,   783,    1046,   774,    1078,   774,    1040,   774,    1072,
4828
    774,    1040,   776,    1072,   776,    1045,   774,    1077,   774,
4829
    1240,   776,    1241,   776,    1046,   776,    1078,   776,    1047,
4830
    776,    1079,   776,    1048,   772,    1080,   772,    1048,   776,
4831
    1080,   776,    1054,   776,    1086,   776,    1256,   776,    1257,
4832
    776,    1069,   776,    1101,   776,    1059,   772,    1091,   772,
4833
    1059,   776,    1091,   776,    1059,   779,    1091,   779,    1063,
4834
    776,    1095,   776,    1067,   776,    1099,   776,    1381,   1410,
4835
    1575,   1619,   1575,   1620,   1608,   1620,   1575,   1621,   1610,
4836
    1620,   1575,   1652,   1608,   1652,   1735,   1652,   1610,   1652,
4837
    1749,   1620,   1729,   1620,   1746,   1620,   2344,   2364,   2352,
4838
    2364,   2355,   2364,   2325,   2364,   2326,   2364,   2327,   2364,
4839
    2332,   2364,   2337,   2364,   2338,   2364,   2347,   2364,   2351,
4840
    2364,   2503,   2494,   2503,   2519,   2465,   2492,   2466,   2492,
4841
    2479,   2492,   2610,   2620,   2616,   2620,   2582,   2620,   2583,
4842
    2620,   2588,   2620,   2603,   2620,   2887,   2902,   2887,   2878,
4843
    2887,   2903,   2849,   2876,   2850,   2876,   2962,   3031,   3014,
4844
    3006,   3015,   3006,   3014,   3031,   3142,   3158,   3263,   3285,
4845
    3270,   3285,   3270,   3286,   3270,   3266,   3270,   3266,   3285,
4846
    3398,   3390,   3399,   3390,   3398,   3415,   3545,   3530,   3545,
4847
    3535,   3545,   3535,   3530,   3545,   3551,   3661,   3634,   3789,
4848
    3762,   3755,   3737,   3755,   3745,   3851,   3906,   4023,   3916,
4849
    4023,   3921,   4023,   3926,   4023,   3931,   4023,   3904,   4021,
4850
    3953,   3954,   3953,   3956,   4018,   3968,   4018,   3953,   3968,
4851
    4019,   3968,   4019,   3953,   3968,   3953,   3968,   3986,   4023,
4852
    3996,   4023,   4001,   4023,   4006,   4023,   4011,   4023,   3984,
4853
    4021,   4133,   4142,   4316,   6917,   6965,   6919,   6965,   6921,
4854
    6965,   6923,   6965,   6925,   6965,   6929,   6965,   6970,   6965,
4855
    6972,   6965,   6974,   6965,   6975,   6965,   6978,   6965,   65,
4856
    198,    66,     68,     69,     398,    71,     72,     73,     74,
4857
    75,     76,     77,     78,     79,     546,    80,     82,     84,
4858
    85,     87,     97,     592,    593,    7426,   98,     100,    101,
4859
    601,    603,    604,    103,    107,    109,    331,    111,    596,
4860
    7446,   7447,   112,    116,    117,    7453,   623,    118,    7461,
4861
    946,    947,    948,    966,    967,    105,    114,    117,    118,
4862
    946,    947,    961,    966,    967,    1085,   594,    99,     597,
4863
    240,    604,    102,    607,    609,    613,    616,    617,    618,
4864
    7547,   669,    621,    7557,   671,    625,    624,    626,    627,
4865
    628,    629,    632,    642,    643,    427,    649,    650,    7452,
4866
    651,    652,    122,    656,    657,    658,    952,    65,     805,
4867
    97,     805,    66,     775,    98,     775,    66,     803,    98,
4868
    803,    66,     817,    98,     817,    67,     807,    769,    99,
4869
    807,    769,    68,     775,    100,    775,    68,     803,    100,
4870
    803,    68,     817,    100,    817,    68,     807,    100,    807,
4871
    68,     813,    100,    813,    69,     772,    768,    101,    772,
4872
    768,    69,     772,    769,    101,    772,    769,    69,     813,
4873
    101,    813,    69,     816,    101,    816,    69,     807,    774,
4874
    101,    807,    774,    70,     775,    102,    775,    71,     772,
4875
    103,    772,    72,     775,    104,    775,    72,     803,    104,
4876
    803,    72,     776,    104,    776,    72,     807,    104,    807,
4877
    72,     814,    104,    814,    73,     816,    105,    816,    73,
4878
    776,    769,    105,    776,    769,    75,     769,    107,    769,
4879
    75,     803,    107,    803,    75,     817,    107,    817,    76,
4880
    803,    108,    803,    76,     803,    772,    108,    803,    772,
4881
    76,     817,    108,    817,    76,     813,    108,    813,    77,
4882
    769,    109,    769,    77,     775,    109,    775,    77,     803,
4883
    109,    803,    78,     775,    110,    775,    78,     803,    110,
4884
    803,    78,     817,    110,    817,    78,     813,    110,    813,
4885
    79,     771,    769,    111,    771,    769,    79,     771,    776,
4886
    111,    771,    776,    79,     772,    768,    111,    772,    768,
4887
    79,     772,    769,    111,    772,    769,    80,     769,    112,
4888
    769,    80,     775,    112,    775,    82,     775,    114,    775,
4889
    82,     803,    114,    803,    82,     803,    772,    114,    803,
4890
    772,    82,     817,    114,    817,    83,     775,    115,    775,
4891
    83,     803,    115,    803,    83,     769,    775,    115,    769,
4892
    775,    83,     780,    775,    115,    780,    775,    83,     803,
4893
    775,    115,    803,    775,    84,     775,    116,    775,    84,
4894
    803,    116,    803,    84,     817,    116,    817,    84,     813,
4895
    116,    813,    85,     804,    117,    804,    85,     816,    117,
4896
    816,    85,     813,    117,    813,    85,     771,    769,    117,
4897
    771,    769,    85,     772,    776,    117,    772,    776,    86,
4898
    771,    118,    771,    86,     803,    118,    803,    87,     768,
4899
    119,    768,    87,     769,    119,    769,    87,     776,    119,
4900
    776,    87,     775,    119,    775,    87,     803,    119,    803,
4901
    88,     775,    120,    775,    88,     776,    120,    776,    89,
4902
    775,    121,    775,    90,     770,    122,    770,    90,     803,
4903
    122,    803,    90,     817,    122,    817,    104,    817,    116,
4904
    776,    119,    778,    121,    778,    97,     702,    383,    775,
4905
    65,     803,    97,     803,    65,     777,    97,     777,    65,
4906
    770,    769,    97,     770,    769,    65,     770,    768,    97,
4907
    770,    768,    65,     770,    777,    97,     770,    777,    65,
4908
    770,    771,    97,     770,    771,    65,     803,    770,    97,
4909
    803,    770,    65,     774,    769,    97,     774,    769,    65,
4910
    774,    768,    97,     774,    768,    65,     774,    777,    97,
4911
    774,    777,    65,     774,    771,    97,     774,    771,    65,
4912
    803,    774,    97,     803,    774,    69,     803,    101,    803,
4913
    69,     777,    101,    777,    69,     771,    101,    771,    69,
4914
    770,    769,    101,    770,    769,    69,     770,    768,    101,
4915
    770,    768,    69,     770,    777,    101,    770,    777,    69,
4916
    770,    771,    101,    770,    771,    69,     803,    770,    101,
4917
    803,    770,    73,     777,    105,    777,    73,     803,    105,
4918
    803,    79,     803,    111,    803,    79,     777,    111,    777,
4919
    79,     770,    769,    111,    770,    769,    79,     770,    768,
4920
    111,    770,    768,    79,     770,    777,    111,    770,    777,
4921
    79,     770,    771,    111,    770,    771,    79,     803,    770,
4922
    111,    803,    770,    79,     795,    769,    111,    795,    769,
4923
    79,     795,    768,    111,    795,    768,    79,     795,    777,
4924
    111,    795,    777,    79,     795,    771,    111,    795,    771,
4925
    79,     795,    803,    111,    795,    803,    85,     803,    117,
4926
    803,    85,     777,    117,    777,    85,     795,    769,    117,
4927
    795,    769,    85,     795,    768,    117,    795,    768,    85,
4928
    795,    777,    117,    795,    777,    85,     795,    771,    117,
4929
    795,    771,    85,     795,    803,    117,    795,    803,    89,
4930
    768,    121,    768,    89,     803,    121,    803,    89,     777,
4931
    121,    777,    89,     771,    121,    771,    945,    787,    945,
4932
    788,    945,    787,    768,    945,    788,    768,    945,    787,
4933
    769,    945,    788,    769,    945,    787,    834,    945,    788,
4934
    834,    913,    787,    913,    788,    913,    787,    768,    913,
4935
    788,    768,    913,    787,    769,    913,    788,    769,    913,
4936
    787,    834,    913,    788,    834,    949,    787,    949,    788,
4937
    949,    787,    768,    949,    788,    768,    949,    787,    769,
4938
    949,    788,    769,    917,    787,    917,    788,    917,    787,
4939
    768,    917,    788,    768,    917,    787,    769,    917,    788,
4940
    769,    951,    787,    951,    788,    951,    787,    768,    951,
4941
    788,    768,    951,    787,    769,    951,    788,    769,    951,
4942
    787,    834,    951,    788,    834,    919,    787,    919,    788,
4943
    919,    787,    768,    919,    788,    768,    919,    787,    769,
4944
    919,    788,    769,    919,    787,    834,    919,    788,    834,
4945
    953,    787,    953,    788,    953,    787,    768,    953,    788,
4946
    768,    953,    787,    769,    953,    788,    769,    953,    787,
4947
    834,    953,    788,    834,    921,    787,    921,    788,    921,
4948
    787,    768,    921,    788,    768,    921,    787,    769,    921,
4949
    788,    769,    921,    787,    834,    921,    788,    834,    959,
4950
    787,    959,    788,    959,    787,    768,    959,    788,    768,
4951
    959,    787,    769,    959,    788,    769,    927,    787,    927,
4952
    788,    927,    787,    768,    927,    788,    768,    927,    787,
4953
    769,    927,    788,    769,    965,    787,    965,    788,    965,
4954
    787,    768,    965,    788,    768,    965,    787,    769,    965,
4955
    788,    769,    965,    787,    834,    965,    788,    834,    933,
4956
    788,    933,    788,    768,    933,    788,    769,    933,    788,
4957
    834,    969,    787,    969,    788,    969,    787,    768,    969,
4958
    788,    768,    969,    787,    769,    969,    788,    769,    969,
4959
    787,    834,    969,    788,    834,    937,    787,    937,    788,
4960
    937,    787,    768,    937,    788,    768,    937,    787,    769,
4961
    937,    788,    769,    937,    787,    834,    937,    788,    834,
4962
    945,    768,    945,    769,    949,    768,    949,    769,    951,
4963
    768,    951,    769,    953,    768,    953,    769,    959,    768,
4964
    959,    769,    965,    768,    965,    769,    969,    768,    969,
4965
    769,    945,    787,    837,    945,    788,    837,    945,    787,
4966
    768,    837,    945,    788,    768,    837,    945,    787,    769,
4967
    837,    945,    788,    769,    837,    945,    787,    834,    837,
4968
    945,    788,    834,    837,    913,    787,    837,    913,    788,
4969
    837,    913,    787,    768,    837,    913,    788,    768,    837,
4970
    913,    787,    769,    837,    913,    788,    769,    837,    913,
4971
    787,    834,    837,    913,    788,    834,    837,    951,    787,
4972
    837,    951,    788,    837,    951,    787,    768,    837,    951,
4973
    788,    768,    837,    951,    787,    769,    837,    951,    788,
4974
    769,    837,    951,    787,    834,    837,    951,    788,    834,
4975
    837,    919,    787,    837,    919,    788,    837,    919,    787,
4976
    768,    837,    919,    788,    768,    837,    919,    787,    769,
4977
    837,    919,    788,    769,    837,    919,    787,    834,    837,
4978
    919,    788,    834,    837,    969,    787,    837,    969,    788,
4979
    837,    969,    787,    768,    837,    969,    788,    768,    837,
4980
    969,    787,    769,    837,    969,    788,    769,    837,    969,
4981
    787,    834,    837,    969,    788,    834,    837,    937,    787,
4982
    837,    937,    788,    837,    937,    787,    768,    837,    937,
4983
    788,    768,    837,    937,    787,    769,    837,    937,    788,
4984
    769,    837,    937,    787,    834,    837,    937,    788,    834,
4985
    837,    945,    774,    945,    772,    945,    768,    837,    945,
4986
    837,    945,    769,    837,    945,    834,    945,    834,    837,
4987
    913,    774,    913,    772,    913,    768,    913,    769,    913,
4988
    837,    32,     787,    953,    32,     787,    32,     834,    168,
4989
    834,    951,    768,    837,    951,    837,    951,    769,    837,
4990
    951,    834,    951,    834,    837,    917,    768,    917,    769,
4991
    919,    768,    919,    769,    919,    837,    8127,   768,    8127,
4992
    769,    8127,   834,    953,    774,    953,    772,    953,    776,
4993
    768,    953,    776,    769,    953,    834,    953,    776,    834,
4994
    921,    774,    921,    772,    921,    768,    921,    769,    8190,
4995
    768,    8190,   769,    8190,   834,    965,    774,    965,    772,
4996
    965,    776,    768,    965,    776,    769,    961,    787,    961,
4997
    788,    965,    834,    965,    776,    834,    933,    774,    933,
4998
    772,    933,    768,    933,    769,    929,    788,    168,    768,
4999
    168,    769,    96,     969,    768,    837,    969,    837,    969,
5000
    769,    837,    969,    834,    969,    834,    837,    927,    768,
5001
    927,    769,    937,    768,    937,    769,    937,    837,    180,
5002
    32,     788,    8194,   8195,   32,     32,     32,     32,     32,
5003
    32,     32,     32,     32,     8208,   32,     819,    46,     46,
5004
    46,     46,     46,     46,     32,     8242,   8242,   8242,   8242,
5005
    8242,   8245,   8245,   8245,   8245,   8245,   33,     33,     32,
5006
    773,    63,     63,     63,     33,     33,     63,     8242,   8242,
5007
    8242,   8242,   32,     48,     105,    52,     53,     54,     55,
5008
    56,     57,     43,     8722,   61,     40,     41,     110,    48,
5009
    49,     50,     51,     52,     53,     54,     55,     56,     57,
5010
    43,     8722,   61,     40,     41,     97,     101,    111,    120,
5011
    601,    104,    107,    108,    109,    110,    112,    115,    116,
5012
    82,     115,    97,     47,     99,     97,     47,     115,    67,
5013
    176,    67,     99,     47,     111,    99,     47,     117,    400,
5014
    176,    70,     103,    72,     72,     72,     104,    295,    73,
5015
    73,     76,     108,    78,     78,     111,    80,     81,     82,
5016
    82,     82,     83,     77,     84,     69,     76,     84,     77,
5017
    90,     937,    90,     75,     65,     778,    66,     67,     101,
5018
    69,     70,     77,     111,    1488,   1489,   1490,   1491,   105,
5019
    70,     65,     88,     960,    947,    915,    928,    8721,   68,
5020
    100,    101,    105,    106,    49,     8260,   55,     49,     8260,
5021
    57,     49,     8260,   49,     48,     49,     8260,   51,     50,
5022
    8260,   51,     49,     8260,   53,     50,     8260,   53,     51,
5023
    8260,   53,     52,     8260,   53,     49,     8260,   54,     53,
5024
    8260,   54,     49,     8260,   56,     51,     8260,   56,     53,
5025
    8260,   56,     55,     8260,   56,     49,     8260,   73,     73,
5026
    73,     73,     73,     73,     73,     86,     86,     86,     73,
5027
    86,     73,     73,     86,     73,     73,     73,     73,     88,
5028
    88,     88,     73,     88,     73,     73,     76,     67,     68,
5029
    77,     105,    105,    105,    105,    105,    105,    105,    118,
5030
    118,    118,    105,    118,    105,    105,    118,    105,    105,
5031
    105,    105,    120,    120,    120,    105,    120,    105,    105,
5032
    108,    99,     100,    109,    48,     8260,   51,     8592,   824,
5033
    8594,   824,    8596,   824,    8656,   824,    8660,   824,    8658,
5034
    824,    8707,   824,    8712,   824,    8715,   824,    8739,   824,
5035
    8741,   824,    8747,   8747,   8747,   8747,   8747,   8750,   8750,
5036
    8750,   8750,   8750,   8764,   824,    8771,   824,    8773,   824,
5037
    8776,   824,    61,     824,    8801,   824,    8781,   824,    60,
5038
    824,    62,     824,    8804,   824,    8805,   824,    8818,   824,
5039
    8819,   824,    8822,   824,    8823,   824,    8826,   824,    8827,
5040
    824,    8834,   824,    8835,   824,    8838,   824,    8839,   824,
5041
    8866,   824,    8872,   824,    8873,   824,    8875,   824,    8828,
5042
    824,    8829,   824,    8849,   824,    8850,   824,    8882,   824,
5043
    8883,   824,    8884,   824,    8885,   824,    12296,  12297,  49,
5044
    50,     51,     52,     53,     54,     55,     56,     57,     49,
5045
    48,     49,     49,     49,     50,     49,     51,     49,     52,
5046
    49,     53,     49,     54,     49,     55,     49,     56,     49,
5047
    57,     50,     48,     40,     49,     41,     40,     50,     41,
5048
    40,     51,     41,     40,     52,     41,     40,     53,     41,
5049
    40,     54,     41,     40,     55,     41,     40,     56,     41,
5050
    40,     57,     41,     40,     49,     48,     41,     40,     49,
5051
    49,     41,     40,     49,     50,     41,     40,     49,     51,
5052
    41,     40,     49,     52,     41,     40,     49,     53,     41,
5053
    40,     49,     54,     41,     40,     49,     55,     41,     40,
5054
    49,     56,     41,     40,     49,     57,     41,     40,     50,
5055
    48,     41,     49,     46,     50,     46,     51,     46,     52,
5056
    46,     53,     46,     54,     46,     55,     46,     56,     46,
5057
    57,     46,     49,     48,     46,     49,     49,     46,     49,
5058
    50,     46,     49,     51,     46,     49,     52,     46,     49,
5059
    53,     46,     49,     54,     46,     49,     55,     46,     49,
5060
    56,     46,     49,     57,     46,     50,     48,     46,     40,
5061
    97,     41,     40,     98,     41,     40,     99,     41,     40,
5062
    100,    41,     40,     101,    41,     40,     102,    41,     40,
5063
    103,    41,     40,     104,    41,     40,     105,    41,     40,
5064
    106,    41,     40,     107,    41,     40,     108,    41,     40,
5065
    109,    41,     40,     110,    41,     40,     111,    41,     40,
5066
    112,    41,     40,     113,    41,     40,     114,    41,     40,
5067
    115,    41,     40,     116,    41,     40,     117,    41,     40,
5068
    118,    41,     40,     119,    41,     40,     120,    41,     40,
5069
    121,    41,     40,     122,    41,     65,     66,     67,     68,
5070
    69,     70,     71,     72,     73,     74,     75,     76,     77,
5071
    78,     79,     80,     81,     82,     83,     84,     85,     86,
5072
    87,     88,     89,     90,     97,     98,     99,     100,    101,
5073
    102,    103,    104,    105,    106,    107,    108,    109,    110,
5074
    111,    112,    113,    114,    115,    116,    117,    118,    119,
5075
    120,    121,    122,    48,     8747,   8747,   8747,   8747,   58,
5076
    58,     61,     61,     61,     61,     61,     61,     10973,  824,
5077
    106,    86,     11617,  27597,  40863,  19968,  20008,  20022,  20031,
5078
    20057,  20101,  20108,  20128,  20154,  20799,  20837,  20843,  20866,
5079
    20886,  20907,  20960,  20981,  20992,  21147,  21241,  21269,  21274,
5080
    21304,  21313,  21340,  21353,  21378,  21430,  21448,  21475,  22231,
5081
    22303,  22763,  22786,  22794,  22805,  22823,  22899,  23376,  23424,
5082
    23544,  23567,  23586,  23608,  23662,  23665,  24027,  24037,  24049,
5083
    24062,  24178,  24186,  24191,  24308,  24318,  24331,  24339,  24400,
5084
    24417,  24435,  24515,  25096,  25142,  25163,  25903,  25908,  25991,
5085
    26007,  26020,  26041,  26080,  26085,  26352,  26376,  26408,  27424,
5086
    27490,  27513,  27571,  27595,  27604,  27611,  27663,  27668,  27700,
5087
    28779,  29226,  29238,  29243,  29247,  29255,  29273,  29275,  29356,
5088
    29572,  29577,  29916,  29926,  29976,  29983,  29992,  30000,  30091,
5089
    30098,  30326,  30333,  30382,  30399,  30446,  30683,  30690,  30707,
5090
    31034,  31160,  31166,  31348,  31435,  31481,  31859,  31992,  32566,
5091
    32593,  32650,  32701,  32769,  32780,  32786,  32819,  32895,  32905,
5092
    33251,  33258,  33267,  33276,  33292,  33307,  33311,  33390,  33394,
5093
    33400,  34381,  34411,  34880,  34892,  34915,  35198,  35211,  35282,
5094
    35328,  35895,  35910,  35925,  35960,  35997,  36196,  36208,  36275,
5095
    36523,  36554,  36763,  36784,  36789,  37009,  37193,  37318,  37324,
5096
    37329,  38263,  38272,  38428,  38582,  38585,  38632,  38737,  38750,
5097
    38754,  38761,  38859,  38893,  38899,  38913,  39080,  39131,  39135,
5098
    39318,  39321,  39340,  39592,  39640,  39647,  39717,  39727,  39730,
5099
    39740,  39770,  40165,  40565,  40575,  40613,  40635,  40643,  40653,
5100
    40657,  40697,  40701,  40718,  40723,  40736,  40763,  40778,  40786,
5101
    40845,  40860,  40864,  32,     12306,  21313,  21316,  21317,  12363,
5102
    12441,  12365,  12441,  12367,  12441,  12369,  12441,  12371,  12441,
5103
    12373,  12441,  12375,  12441,  12377,  12441,  12379,  12441,  12381,
5104
    12441,  12383,  12441,  12385,  12441,  12388,  12441,  12390,  12441,
5105
    12392,  12441,  12399,  12441,  12399,  12442,  12402,  12441,  12402,
5106
    12442,  12405,  12441,  12405,  12442,  12408,  12441,  12408,  12442,
5107
    12411,  12441,  12411,  12442,  12358,  12441,  32,     12441,  32,
5108
    12442,  12445,  12441,  12424,  12426,  12459,  12441,  12461,  12441,
5109
    12463,  12441,  12465,  12441,  12467,  12441,  12469,  12441,  12471,
5110
    12441,  12473,  12441,  12475,  12441,  12477,  12441,  12479,  12441,
5111
    12481,  12441,  12484,  12441,  12486,  12441,  12488,  12441,  12495,
5112
    12441,  12495,  12442,  12498,  12441,  12498,  12442,  12501,  12441,
5113
    12501,  12442,  12504,  12441,  12504,  12442,  12507,  12441,  12507,
5114
    12442,  12454,  12441,  12527,  12441,  12528,  12441,  12529,  12441,
5115
    12530,  12441,  12541,  12441,  12467,  12488,  4352,   4353,   4522,
5116
    4354,   4524,   4525,   4355,   4356,   4357,   4528,   4529,   4530,
5117
    4531,   4532,   4533,   4378,   4358,   4359,   4360,   4385,   4361,
5118
    4362,   4363,   4364,   4365,   4366,   4367,   4368,   4369,   4370,
5119
    4449,   4450,   4451,   4452,   4453,   4454,   4455,   4456,   4457,
5120
    4458,   4459,   4460,   4461,   4462,   4463,   4464,   4465,   4466,
5121
    4467,   4468,   4469,   4448,   4372,   4373,   4551,   4552,   4556,
5122
    4558,   4563,   4567,   4569,   4380,   4573,   4575,   4381,   4382,
5123
    4384,   4386,   4387,   4391,   4393,   4395,   4396,   4397,   4398,
5124
    4399,   4402,   4406,   4416,   4423,   4428,   4593,   4594,   4439,
5125
    4440,   4441,   4484,   4485,   4488,   4497,   4498,   4500,   4510,
5126
    4513,   19968,  20108,  19977,  22235,  19978,  20013,  19979,  30002,
5127
    20057,  19993,  19969,  22825,  22320,  20154,  40,     4352,   41,
5128
    40,     4354,   41,     40,     4355,   41,     40,     4357,   41,
5129
    40,     4358,   41,     40,     4359,   41,     40,     4361,   41,
5130
    40,     4363,   41,     40,     4364,   41,     40,     4366,   41,
5131
    40,     4367,   41,     40,     4368,   41,     40,     4369,   41,
5132
    40,     4370,   41,     40,     4352,   4449,   41,     40,     4354,
5133
    4449,   41,     40,     4355,   4449,   41,     40,     4357,   4449,
5134
    41,     40,     4358,   4449,   41,     40,     4359,   4449,   41,
5135
    40,     4361,   4449,   41,     40,     4363,   4449,   41,     40,
5136
    4364,   4449,   41,     40,     4366,   4449,   41,     40,     4367,
5137
    4449,   41,     40,     4368,   4449,   41,     40,     4369,   4449,
5138
    41,     40,     4370,   4449,   41,     40,     4364,   4462,   41,
5139
    40,     4363,   4457,   4364,   4453,   4523,   41,     40,     4363,
5140
    4457,   4370,   4462,   41,     40,     19968,  41,     40,     20108,
5141
    41,     40,     19977,  41,     40,     22235,  41,     40,     20116,
5142
    41,     40,     20845,  41,     40,     19971,  41,     40,     20843,
5143
    41,     40,     20061,  41,     40,     21313,  41,     40,     26376,
5144
    41,     40,     28779,  41,     40,     27700,  41,     40,     26408,
5145
    41,     40,     37329,  41,     40,     22303,  41,     40,     26085,
5146
    41,     40,     26666,  41,     40,     26377,  41,     40,     31038,
5147
    41,     40,     21517,  41,     40,     29305,  41,     40,     36001,
5148
    41,     40,     31069,  41,     40,     21172,  41,     40,     20195,
5149
    41,     40,     21628,  41,     40,     23398,  41,     40,     30435,
5150
    41,     40,     20225,  41,     40,     36039,  41,     40,     21332,
5151
    41,     40,     31085,  41,     40,     20241,  41,     40,     33258,
5152
    41,     40,     33267,  41,     21839,  24188,  25991,  31631,  80,
5153
    84,     69,     50,     49,     50,     50,     50,     51,     50,
5154
    52,     50,     53,     50,     54,     50,     55,     50,     56,
5155
    50,     57,     51,     48,     51,     49,     51,     50,     51,
5156
    51,     51,     52,     51,     53,     4352,   4354,   4355,   4357,
5157
    4358,   4359,   4361,   4363,   4364,   4366,   4367,   4368,   4369,
5158
    4370,   4352,   4449,   4354,   4449,   4355,   4449,   4357,   4449,
5159
    4358,   4449,   4359,   4449,   4361,   4449,   4363,   4449,   4364,
5160
    4449,   4366,   4449,   4367,   4449,   4368,   4449,   4369,   4449,
5161
    4370,   4449,   4366,   4449,   4535,   4352,   4457,   4364,   4462,
5162
    4363,   4468,   4363,   4462,   19968,  20108,  19977,  22235,  20116,
5163
    20845,  19971,  20843,  20061,  21313,  26376,  28779,  27700,  26408,
5164
    37329,  22303,  26085,  26666,  26377,  31038,  21517,  29305,  36001,
5165
    31069,  21172,  31192,  30007,  22899,  36969,  20778,  21360,  27880,
5166
    38917,  20241,  20889,  27491,  19978,  20013,  19979,  24038,  21491,
5167
    21307,  23447,  23398,  30435,  20225,  36039,  21332,  22812,  51,
5168
    54,     51,     55,     51,     56,     51,     57,     52,     48,
5169
    52,     49,     52,     50,     52,     51,     52,     52,     52,
5170
    53,     52,     54,     52,     55,     52,     56,     52,     57,
5171
    53,     48,     49,     26376,  50,     26376,  51,     26376,  52,
5172
    26376,  53,     26376,  54,     26376,  55,     26376,  56,     26376,
5173
    57,     26376,  49,     48,     26376,  49,     49,     26376,  49,
5174
    50,     26376,  72,     103,    101,    114,    103,    101,    86,
5175
    76,     84,     68,     12450,  12452,  12454,  12456,  12458,  12459,
5176
    12461,  12463,  12465,  12467,  12469,  12471,  12473,  12475,  12477,
5177
    12479,  12481,  12484,  12486,  12488,  12490,  12491,  12492,  12493,
5178
    12494,  12495,  12498,  12501,  12504,  12507,  12510,  12511,  12512,
5179
    12513,  12514,  12516,  12518,  12520,  12521,  12522,  12523,  12524,
5180
    12525,  12527,  12528,  12529,  12530,  20196,  21644,  12450,  12495,
5181
    12442,  12540,  12488,  12450,  12523,  12501,  12449,  12450,  12531,
5182
    12504,  12442,  12450,  12450,  12540,  12523,  12452,  12491,  12531,
5183
    12463,  12441,  12452,  12531,  12481,  12454,  12457,  12531,  12456,
5184
    12473,  12463,  12540,  12488,  12441,  12456,  12540,  12459,  12540,
5185
    12458,  12531,  12473,  12458,  12540,  12512,  12459,  12452,  12522,
5186
    12459,  12521,  12483,  12488,  12459,  12525,  12522,  12540,  12459,
5187
    12441,  12525,  12531,  12459,  12441,  12531,  12510,  12461,  12441,
5188
    12459,  12441,  12461,  12441,  12491,  12540,  12461,  12517,  12522,
5189
    12540,  12461,  12441,  12523,  12479,  12441,  12540,  12461,  12525,
5190
    12461,  12525,  12463,  12441,  12521,  12512,  12461,  12525,  12513,
5191
    12540,  12488,  12523,  12461,  12525,  12527,  12483,  12488,  12463,
5192
    12441,  12521,  12512,  12463,  12441,  12521,  12512,  12488,  12531,
5193
    12463,  12523,  12475,  12441,  12452,  12525,  12463,  12525,  12540,
5194
    12493,  12465,  12540,  12473,  12467,  12523,  12490,  12467,  12540,
5195
    12507,  12442,  12469,  12452,  12463,  12523,  12469,  12531,  12481,
5196
    12540,  12512,  12471,  12522,  12531,  12463,  12441,  12475,  12531,
5197
    12481,  12475,  12531,  12488,  12479,  12441,  12540,  12473,  12486,
5198
    12441,  12471,  12488,  12441,  12523,  12488,  12531,  12490,  12494,
5199
    12494,  12483,  12488,  12495,  12452,  12484,  12495,  12442,  12540,
5200
    12475,  12531,  12488,  12495,  12442,  12540,  12484,  12495,  12441,
5201
    12540,  12524,  12523,  12498,  12442,  12450,  12473,  12488,  12523,
5202
    12498,  12442,  12463,  12523,  12498,  12442,  12467,  12498,  12441,
5203
    12523,  12501,  12449,  12521,  12483,  12488,  12441,  12501,  12451,
5204
    12540,  12488,  12501,  12441,  12483,  12471,  12455,  12523,  12501,
5205
    12521,  12531,  12504,  12463,  12479,  12540,  12523,  12504,  12442,
5206
    12477,  12504,  12442,  12491,  12498,  12504,  12523,  12484,  12504,
5207
    12442,  12531,  12473,  12504,  12442,  12540,  12471,  12441,  12504,
5208
    12441,  12540,  12479,  12507,  12442,  12452,  12531,  12488,  12507,
5209
    12441,  12523,  12488,  12507,  12531,  12507,  12442,  12531,  12488,
5210
    12441,  12507,  12540,  12523,  12507,  12540,  12531,  12510,  12452,
5211
    12463,  12525,  12510,  12452,  12523,  12510,  12483,  12495,  12510,
5212
    12523,  12463,  12510,  12531,  12471,  12519,  12531,  12511,  12463,
5213
    12525,  12531,  12511,  12522,  12511,  12522,  12495,  12441,  12540,
5214
    12523,  12513,  12459,  12441,  12513,  12459,  12441,  12488,  12531,
5215
    12513,  12540,  12488,  12523,  12516,  12540,  12488,  12441,  12516,
5216
    12540,  12523,  12518,  12450,  12531,  12522,  12483,  12488,  12523,
5217
    12522,  12521,  12523,  12498,  12442,  12540,  12523,  12540,  12501,
5218
    12441,  12523,  12524,  12512,  12524,  12531,  12488,  12465,  12441,
5219
    12531,  12527,  12483,  12488,  48,     28857,  49,     28857,  50,
5220
    28857,  51,     28857,  52,     28857,  53,     28857,  54,     28857,
5221
    55,     28857,  56,     28857,  57,     28857,  49,     48,     28857,
5222
    49,     49,     28857,  49,     50,     28857,  49,     51,     28857,
5223
    49,     52,     28857,  49,     53,     28857,  49,     54,     28857,
5224
    49,     55,     28857,  49,     56,     28857,  49,     57,     28857,
5225
    50,     48,     28857,  50,     49,     28857,  50,     50,     28857,
5226
    50,     51,     28857,  50,     52,     28857,  104,    80,     97,
5227
    100,    97,     65,     85,     98,     97,     114,    111,    86,
5228
    112,    99,     100,    109,    100,    109,    50,     100,    109,
5229
    51,     73,     85,     24179,  25104,  26157,  21644,  22823,  27491,
5230
    26126,  27835,  26666,  24335,  20250,  31038,  112,    65,     110,
5231
    65,     956,    65,     109,    65,     107,    65,     75,     66,
5232
    77,     66,     71,     66,     99,     97,     108,    107,    99,
5233
    97,     108,    112,    70,     110,    70,     956,    70,     956,
5234
    103,    109,    103,    107,    103,    72,     122,    107,    72,
5235
    122,    77,     72,     122,    71,     72,     122,    84,     72,
5236
    122,    956,    108,    109,    108,    100,    108,    107,    108,
5237
    102,    109,    110,    109,    956,    109,    109,    109,    99,
5238
    109,    107,    109,    109,    109,    50,     99,     109,    50,
5239
    109,    50,     107,    109,    50,     109,    109,    51,     99,
5240
    109,    51,     109,    51,     107,    109,    51,     109,    8725,
5241
    115,    109,    8725,   115,    50,     80,     97,     107,    80,
5242
    97,     77,     80,     97,     71,     80,     97,     114,    97,
5243
    100,    114,    97,     100,    8725,   115,    114,    97,     100,
5244
    8725,   115,    50,     112,    115,    110,    115,    956,    115,
5245
    109,    115,    112,    86,     110,    86,     956,    86,     109,
5246
    86,     107,    86,     77,     86,     112,    87,     110,    87,
5247
    956,    87,     109,    87,     107,    87,     77,     87,     107,
5248
    937,    77,     937,    97,     46,     109,    46,     66,     113,
5249
    99,     99,     99,     100,    67,     8725,   107,    103,    67,
5250
    111,    46,     100,    66,     71,     121,    104,    97,     72,
5251
    80,     105,    110,    75,     75,     75,     77,     107,    116,
5252
    108,    109,    108,    110,    108,    111,    103,    108,    120,
5253
    109,    98,     109,    105,    108,    109,    111,    108,    80,
5254
    72,     112,    46,     109,    46,     80,     80,     77,     80,
5255
    82,     115,    114,    83,     118,    87,     98,     86,     8725,
5256
    109,    65,     8725,   109,    49,     26085,  50,     26085,  51,
5257
    26085,  52,     26085,  53,     26085,  54,     26085,  55,     26085,
5258
    56,     26085,  57,     26085,  49,     48,     26085,  49,     49,
5259
    26085,  49,     50,     26085,  49,     51,     26085,  49,     52,
5260
    26085,  49,     53,     26085,  49,     54,     26085,  49,     55,
5261
    26085,  49,     56,     26085,  49,     57,     26085,  50,     48,
5262
    26085,  50,     49,     26085,  50,     50,     26085,  50,     51,
5263
    26085,  50,     52,     26085,  50,     53,     26085,  50,     54,
5264
    26085,  50,     55,     26085,  50,     56,     26085,  50,     57,
5265
    26085,  51,     48,     26085,  51,     49,     26085,  103,    97,
5266
    108,    1098,   1100,   42863,  67,     70,     81,     294,    339,
5267
    42791,  43831,  619,    43858,  653,    35912,  26356,  36554,  36040,
5268
    28369,  20018,  21477,  40860,  40860,  22865,  37329,  21895,  22856,
5269
    25078,  30313,  32645,  34367,  34746,  35064,  37007,  27138,  27931,
5270
    28889,  29662,  33853,  37226,  39409,  20098,  21365,  27396,  29211,
5271
    34349,  40478,  23888,  28651,  34253,  35172,  25289,  33240,  34847,
5272
    24266,  26391,  28010,  29436,  37070,  20358,  20919,  21214,  25796,
5273
    27347,  29200,  30439,  32769,  34310,  34396,  36335,  38706,  39791,
5274
    40442,  30860,  31103,  32160,  33737,  37636,  40575,  35542,  22751,
5275
    24324,  31840,  32894,  29282,  30922,  36034,  38647,  22744,  23650,
5276
    27155,  28122,  28431,  32047,  32311,  38475,  21202,  32907,  20956,
5277
    20940,  31260,  32190,  33777,  38517,  35712,  25295,  27138,  35582,
5278
    20025,  23527,  24594,  29575,  30064,  21271,  30971,  20415,  24489,
5279
    19981,  27852,  25976,  32034,  21443,  22622,  30465,  33865,  35498,
5280
    27578,  36784,  27784,  25342,  33509,  25504,  30053,  20142,  20841,
5281
    20937,  26753,  31975,  33391,  35538,  37327,  21237,  21570,  22899,
5282
    24300,  26053,  28670,  31018,  38317,  39530,  40599,  40654,  21147,
5283
    26310,  27511,  36706,  24180,  24976,  25088,  25754,  28451,  29001,
5284
    29833,  31178,  32244,  32879,  36646,  34030,  36899,  37706,  21015,
5285
    21155,  21693,  28872,  35010,  35498,  24265,  24565,  25467,  27566,
5286
    31806,  29557,  20196,  22265,  23527,  23994,  24604,  29618,  29801,
5287
    32666,  32838,  37428,  38646,  38728,  38936,  20363,  31150,  37300,
5288
    38584,  24801,  20102,  20698,  23534,  23615,  26009,  27138,  29134,
5289
    30274,  34044,  36988,  40845,  26248,  38446,  21129,  26491,  26611,
5290
    27969,  28316,  29705,  30041,  30827,  32016,  39006,  20845,  25134,
5291
    38520,  20523,  23833,  28138,  36650,  24459,  24900,  26647,  29575,
5292
    38534,  21033,  21519,  23653,  26131,  26446,  26792,  27877,  29702,
5293
    30178,  32633,  35023,  35041,  37324,  38626,  21311,  28346,  21533,
5294
    29136,  29848,  34298,  38563,  40023,  40607,  26519,  28107,  33256,
5295
    31435,  31520,  31890,  29376,  28825,  35672,  20160,  33590,  21050,
5296
    20999,  24230,  25299,  31958,  23429,  27934,  26292,  36667,  34892,
5297
    38477,  35211,  24275,  20800,  21952,  22618,  26228,  20958,  29482,
5298
    30410,  31036,  31070,  31077,  31119,  38742,  31934,  32701,  34322,
5299
    35576,  36920,  37117,  39151,  39164,  39208,  40372,  37086,  38583,
5300
    20398,  20711,  20813,  21193,  21220,  21329,  21917,  22022,  22120,
5301
    22592,  22696,  23652,  23662,  24724,  24936,  24974,  25074,  25935,
5302
    26082,  26257,  26757,  28023,  28186,  28450,  29038,  29227,  29730,
5303
    30865,  31038,  31049,  31048,  31056,  31062,  31069,  31117,  31118,
5304
    31296,  31361,  31680,  32244,  32265,  32321,  32626,  32773,  33261,
5305
    33401,  33401,  33879,  35088,  35222,  35585,  35641,  36051,  36104,
5306
    36790,  36920,  38627,  38911,  38971,  24693,  148206, 33304,  20006,
5307
    20917,  20840,  20352,  20805,  20864,  21191,  21242,  21917,  21845,
5308
    21913,  21986,  22618,  22707,  22852,  22868,  23138,  23336,  24274,
5309
    24281,  24425,  24493,  24792,  24910,  24840,  24974,  24928,  25074,
5310
    25140,  25540,  25628,  25682,  25942,  26228,  26391,  26395,  26454,
5311
    27513,  27578,  27969,  28379,  28363,  28450,  28702,  29038,  30631,
5312
    29237,  29359,  29482,  29809,  29958,  30011,  30237,  30239,  30410,
5313
    30427,  30452,  30538,  30528,  30924,  31409,  31680,  31867,  32091,
5314
    32244,  32574,  32773,  33618,  33775,  34681,  35137,  35206,  35222,
5315
    35519,  35576,  35531,  35585,  35582,  35565,  35641,  35722,  36104,
5316
    36664,  36978,  37273,  37494,  38524,  38627,  38742,  38875,  38911,
5317
    38923,  38971,  39698,  40860,  141386, 141380, 144341, 15261,  16408,
5318
    16441,  152137, 154832, 163539, 40771,  40846,  102,    102,    102,
5319
    105,    102,    108,    102,    102,    105,    102,    102,    108,
5320
    115,    116,    115,    116,    1396,   1398,   1396,   1381,   1396,
5321
    1387,   1406,   1398,   1396,   1389,   1497,   1460,   1522,   1463,
5322
    1506,   1488,   1491,   1492,   1499,   1500,   1501,   1512,   1514,
5323
    43,     1513,   1473,   1513,   1474,   1513,   1468,   1473,   1513,
5324
    1468,   1474,   1488,   1463,   1488,   1464,   1488,   1468,   1489,
5325
    1468,   1490,   1468,   1491,   1468,   1492,   1468,   1493,   1468,
5326
    1494,   1468,   1496,   1468,   1497,   1468,   1498,   1468,   1499,
5327
    1468,   1500,   1468,   1502,   1468,   1504,   1468,   1505,   1468,
5328
    1507,   1468,   1508,   1468,   1510,   1468,   1511,   1468,   1512,
5329
    1468,   1513,   1468,   1514,   1468,   1493,   1465,   1489,   1471,
5330
    1499,   1471,   1508,   1471,   1488,   1500,   1649,   1649,   1659,
5331
    1659,   1659,   1659,   1662,   1662,   1662,   1662,   1664,   1664,
5332
    1664,   1664,   1658,   1658,   1658,   1658,   1663,   1663,   1663,
5333
    1663,   1657,   1657,   1657,   1657,   1700,   1700,   1700,   1700,
5334
    1702,   1702,   1702,   1702,   1668,   1668,   1668,   1668,   1667,
5335
    1667,   1667,   1667,   1670,   1670,   1670,   1670,   1671,   1671,
5336
    1671,   1671,   1677,   1677,   1676,   1676,   1678,   1678,   1672,
5337
    1672,   1688,   1688,   1681,   1681,   1705,   1705,   1705,   1705,
5338
    1711,   1711,   1711,   1711,   1715,   1715,   1715,   1715,   1713,
5339
    1713,   1713,   1713,   1722,   1722,   1723,   1723,   1723,   1723,
5340
    1749,   1620,   1749,   1620,   1729,   1729,   1729,   1729,   1726,
5341
    1726,   1726,   1726,   1746,   1746,   1746,   1620,   1746,   1620,
5342
    1709,   1709,   1709,   1709,   1735,   1735,   1734,   1734,   1736,
5343
    1736,   1735,   1652,   1739,   1739,   1733,   1733,   1737,   1737,
5344
    1744,   1744,   1744,   1744,   1609,   1609,   1610,   1620,   1575,
5345
    1610,   1620,   1575,   1610,   1620,   1749,   1610,   1620,   1749,
5346
    1610,   1620,   1608,   1610,   1620,   1608,   1610,   1620,   1735,
5347
    1610,   1620,   1735,   1610,   1620,   1734,   1610,   1620,   1734,
5348
    1610,   1620,   1736,   1610,   1620,   1736,   1610,   1620,   1744,
5349
    1610,   1620,   1744,   1610,   1620,   1744,   1610,   1620,   1609,
5350
    1610,   1620,   1609,   1610,   1620,   1609,   1740,   1740,   1740,
5351
    1740,   1610,   1620,   1580,   1610,   1620,   1581,   1610,   1620,
5352
    1605,   1610,   1620,   1609,   1610,   1620,   1610,   1576,   1580,
5353
    1576,   1581,   1576,   1582,   1576,   1605,   1576,   1609,   1576,
5354
    1610,   1578,   1580,   1578,   1581,   1578,   1582,   1578,   1605,
5355
    1578,   1609,   1578,   1610,   1579,   1580,   1579,   1605,   1579,
5356
    1609,   1579,   1610,   1580,   1581,   1580,   1605,   1581,   1580,
5357
    1581,   1605,   1582,   1580,   1582,   1581,   1582,   1605,   1587,
5358
    1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,   1581,
5359
    1589,   1605,   1590,   1580,   1590,   1581,   1590,   1582,   1590,
5360
    1605,   1591,   1581,   1591,   1605,   1592,   1605,   1593,   1580,
5361
    1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,   1601,
5362
    1581,   1601,   1582,   1601,   1605,   1601,   1609,   1601,   1610,
5363
    1602,   1581,   1602,   1605,   1602,   1609,   1602,   1610,   1603,
5364
    1575,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5365
    1603,   1605,   1603,   1609,   1603,   1610,   1604,   1580,   1604,
5366
    1581,   1604,   1582,   1604,   1605,   1604,   1609,   1604,   1610,
5367
    1605,   1580,   1605,   1581,   1605,   1582,   1605,   1605,   1605,
5368
    1609,   1605,   1610,   1606,   1580,   1606,   1581,   1606,   1582,
5369
    1606,   1605,   1606,   1609,   1606,   1610,   1607,   1580,   1607,
5370
    1605,   1607,   1609,   1607,   1610,   1610,   1580,   1610,   1581,
5371
    1610,   1582,   1610,   1605,   1610,   1609,   1610,   1610,   1584,
5372
    1648,   1585,   1648,   1609,   1648,   32,     1612,   1617,   32,
5373
    1613,   1617,   32,     1614,   1617,   32,     1615,   1617,   32,
5374
    1616,   1617,   32,     1617,   1648,   1610,   1620,   1585,   1610,
5375
    1620,   1586,   1610,   1620,   1605,   1610,   1620,   1606,   1610,
5376
    1620,   1609,   1610,   1620,   1610,   1576,   1585,   1576,   1586,
5377
    1576,   1605,   1576,   1606,   1576,   1609,   1576,   1610,   1578,
5378
    1585,   1578,   1586,   1578,   1605,   1578,   1606,   1578,   1609,
5379
    1578,   1610,   1579,   1585,   1579,   1586,   1579,   1605,   1579,
5380
    1606,   1579,   1609,   1579,   1610,   1601,   1609,   1601,   1610,
5381
    1602,   1609,   1602,   1610,   1603,   1575,   1603,   1604,   1603,
5382
    1605,   1603,   1609,   1603,   1610,   1604,   1605,   1604,   1609,
5383
    1604,   1610,   1605,   1575,   1605,   1605,   1606,   1585,   1606,
5384
    1586,   1606,   1605,   1606,   1606,   1606,   1609,   1606,   1610,
5385
    1609,   1648,   1610,   1585,   1610,   1586,   1610,   1605,   1610,
5386
    1606,   1610,   1609,   1610,   1610,   1610,   1620,   1580,   1610,
5387
    1620,   1581,   1610,   1620,   1582,   1610,   1620,   1605,   1610,
5388
    1620,   1607,   1576,   1580,   1576,   1581,   1576,   1582,   1576,
5389
    1605,   1576,   1607,   1578,   1580,   1578,   1581,   1578,   1582,
5390
    1578,   1605,   1578,   1607,   1579,   1605,   1580,   1581,   1580,
5391
    1605,   1581,   1580,   1581,   1605,   1582,   1580,   1582,   1605,
5392
    1587,   1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,
5393
    1581,   1589,   1582,   1589,   1605,   1590,   1580,   1590,   1581,
5394
    1590,   1582,   1590,   1605,   1591,   1581,   1592,   1605,   1593,
5395
    1580,   1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,
5396
    1601,   1581,   1601,   1582,   1601,   1605,   1602,   1581,   1602,
5397
    1605,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5398
    1603,   1605,   1604,   1580,   1604,   1581,   1604,   1582,   1604,
5399
    1605,   1604,   1607,   1605,   1580,   1605,   1581,   1605,   1582,
5400
    1605,   1605,   1606,   1580,   1606,   1581,   1606,   1582,   1606,
5401
    1605,   1606,   1607,   1607,   1580,   1607,   1605,   1607,   1648,
5402
    1610,   1580,   1610,   1581,   1610,   1582,   1610,   1605,   1610,
5403
    1607,   1610,   1620,   1605,   1610,   1620,   1607,   1576,   1605,
5404
    1576,   1607,   1578,   1605,   1578,   1607,   1579,   1605,   1579,
5405
    1607,   1587,   1605,   1587,   1607,   1588,   1605,   1588,   1607,
5406
    1603,   1604,   1603,   1605,   1604,   1605,   1606,   1605,   1606,
5407
    1607,   1610,   1605,   1610,   1607,   1600,   1614,   1617,   1600,
5408
    1615,   1617,   1600,   1616,   1617,   1591,   1609,   1591,   1610,
5409
    1593,   1609,   1593,   1610,   1594,   1609,   1594,   1610,   1587,
5410
    1609,   1587,   1610,   1588,   1609,   1588,   1610,   1581,   1609,
5411
    1581,   1610,   1580,   1609,   1580,   1610,   1582,   1609,   1582,
5412
    1610,   1589,   1609,   1589,   1610,   1590,   1609,   1590,   1610,
5413
    1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1588,
5414
    1585,   1587,   1585,   1589,   1585,   1590,   1585,   1591,   1609,
5415
    1591,   1610,   1593,   1609,   1593,   1610,   1594,   1609,   1594,
5416
    1610,   1587,   1609,   1587,   1610,   1588,   1609,   1588,   1610,
5417
    1581,   1609,   1581,   1610,   1580,   1609,   1580,   1610,   1582,
5418
    1609,   1582,   1610,   1589,   1609,   1589,   1610,   1590,   1609,
5419
    1590,   1610,   1588,   1580,   1588,   1581,   1588,   1582,   1588,
5420
    1605,   1588,   1585,   1587,   1585,   1589,   1585,   1590,   1585,
5421
    1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1587,
5422
    1607,   1588,   1607,   1591,   1605,   1587,   1580,   1587,   1581,
5423
    1587,   1582,   1588,   1580,   1588,   1581,   1588,   1582,   1591,
5424
    1605,   1592,   1605,   1575,   1611,   1575,   1611,   1578,   1580,
5425
    1605,   1578,   1581,   1580,   1578,   1581,   1580,   1578,   1581,
5426
    1605,   1578,   1582,   1605,   1578,   1605,   1580,   1578,   1605,
5427
    1581,   1578,   1605,   1582,   1580,   1605,   1581,   1580,   1605,
5428
    1581,   1581,   1605,   1610,   1581,   1605,   1609,   1587,   1581,
5429
    1580,   1587,   1580,   1581,   1587,   1580,   1609,   1587,   1605,
5430
    1581,   1587,   1605,   1581,   1587,   1605,   1580,   1587,   1605,
5431
    1605,   1587,   1605,   1605,   1589,   1581,   1581,   1589,   1581,
5432
    1581,   1589,   1605,   1605,   1588,   1581,   1605,   1588,   1581,
5433
    1605,   1588,   1580,   1610,   1588,   1605,   1582,   1588,   1605,
5434
    1582,   1588,   1605,   1605,   1588,   1605,   1605,   1590,   1581,
5435
    1609,   1590,   1582,   1605,   1590,   1582,   1605,   1591,   1605,
5436
    1581,   1591,   1605,   1581,   1591,   1605,   1605,   1591,   1605,
5437
    1610,   1593,   1580,   1605,   1593,   1605,   1605,   1593,   1605,
5438
    1605,   1593,   1605,   1609,   1594,   1605,   1605,   1594,   1605,
5439
    1610,   1594,   1605,   1609,   1601,   1582,   1605,   1601,   1582,
5440
    1605,   1602,   1605,   1581,   1602,   1605,   1605,   1604,   1581,
5441
    1605,   1604,   1581,   1610,   1604,   1581,   1609,   1604,   1580,
5442
    1580,   1604,   1580,   1580,   1604,   1582,   1605,   1604,   1582,
5443
    1605,   1604,   1605,   1581,   1604,   1605,   1581,   1605,   1581,
5444
    1580,   1605,   1581,   1605,   1605,   1581,   1610,   1605,   1580,
5445
    1581,   1605,   1580,   1605,   1605,   1582,   1580,   1605,   1582,
5446
    1605,   1605,   1580,   1582,   1607,   1605,   1580,   1607,   1605,
5447
    1605,   1606,   1581,   1605,   1606,   1581,   1609,   1606,   1580,
5448
    1605,   1606,   1580,   1605,   1606,   1580,   1609,   1606,   1605,
5449
    1610,   1606,   1605,   1609,   1610,   1605,   1605,   1610,   1605,
5450
    1605,   1576,   1582,   1610,   1578,   1580,   1610,   1578,   1580,
5451
    1609,   1578,   1582,   1610,   1578,   1582,   1609,   1578,   1605,
5452
    1610,   1578,   1605,   1609,   1580,   1605,   1610,   1580,   1581,
5453
    1609,   1580,   1605,   1609,   1587,   1582,   1609,   1589,   1581,
5454
    1610,   1588,   1581,   1610,   1590,   1581,   1610,   1604,   1580,
5455
    1610,   1604,   1605,   1610,   1610,   1581,   1610,   1610,   1580,
5456
    1610,   1610,   1605,   1610,   1605,   1605,   1610,   1602,   1605,
5457
    1610,   1606,   1581,   1610,   1602,   1605,   1581,   1604,   1581,
5458
    1605,   1593,   1605,   1610,   1603,   1605,   1610,   1606,   1580,
5459
    1581,   1605,   1582,   1610,   1604,   1580,   1605,   1603,   1605,
5460
    1605,   1604,   1580,   1605,   1606,   1580,   1581,   1580,   1581,
5461
    1610,   1581,   1580,   1610,   1605,   1580,   1610,   1601,   1605,
5462
    1610,   1576,   1581,   1610,   1603,   1605,   1605,   1593,   1580,
5463
    1605,   1589,   1605,   1605,   1587,   1582,   1610,   1606,   1580,
5464
    1610,   1589,   1604,   1746,   1602,   1604,   1746,   1575,   1604,
5465
    1604,   1607,   1575,   1603,   1576,   1585,   1605,   1581,   1605,
5466
    1583,   1589,   1604,   1593,   1605,   1585,   1587,   1608,   1604,
5467
    1593,   1604,   1610,   1607,   1608,   1587,   1604,   1605,   1589,
5468
    1604,   1609,   1589,   1604,   1609,   32,     1575,   1604,   1604,
5469
    1607,   32,     1593,   1604,   1610,   1607,   32,     1608,   1587,
5470
    1604,   1605,   1580,   1604,   32,     1580,   1604,   1575,   1604,
5471
    1607,   1585,   1740,   1575,   1604,   44,     12289,  12290,  58,
5472
    59,     33,     63,     12310,  12311,  46,     46,     46,     46,
5473
    46,     8212,   8211,   95,     95,     40,     41,     123,    125,
5474
    12308,  12309,  12304,  12305,  12298,  12299,  12296,  12297,  12300,
5475
    12301,  12302,  12303,  91,     93,     32,     773,    32,     773,
5476
    32,     773,    32,     773,    95,     95,     95,     44,     12289,
5477
    46,     59,     58,     63,     33,     8212,   40,     41,     123,
5478
    125,    12308,  12309,  35,     38,     42,     43,     45,     60,
5479
    62,     61,     92,     36,     37,     64,     32,     1611,   1600,
5480
    1611,   32,     1612,   32,     1613,   32,     1614,   1600,   1614,
5481
    32,     1615,   1600,   1615,   32,     1616,   1600,   1616,   32,
5482
    1617,   1600,   1617,   32,     1618,   1600,   1618,   1569,   1575,
5483
    1619,   1575,   1619,   1575,   1620,   1575,   1620,   1608,   1620,
5484
    1608,   1620,   1575,   1621,   1575,   1621,   1610,   1620,   1610,
5485
    1620,   1610,   1620,   1610,   1620,   1575,   1575,   1576,   1576,
5486
    1576,   1576,   1577,   1577,   1578,   1578,   1578,   1578,   1579,
5487
    1579,   1579,   1579,   1580,   1580,   1580,   1580,   1581,   1581,
5488
    1581,   1581,   1582,   1582,   1582,   1582,   1583,   1583,   1584,
5489
    1584,   1585,   1585,   1586,   1586,   1587,   1587,   1587,   1587,
5490
    1588,   1588,   1588,   1588,   1589,   1589,   1589,   1589,   1590,
5491
    1590,   1590,   1590,   1591,   1591,   1591,   1591,   1592,   1592,
5492
    1592,   1592,   1593,   1593,   1593,   1593,   1594,   1594,   1594,
5493
    1594,   1601,   1601,   1601,   1601,   1602,   1602,   1602,   1602,
5494
    1603,   1603,   1603,   1603,   1604,   1604,   1604,   1604,   1605,
5495
    1605,   1605,   1605,   1606,   1606,   1606,   1606,   1607,   1607,
5496
    1607,   1607,   1608,   1608,   1609,   1609,   1610,   1610,   1610,
5497
    1610,   1604,   1575,   1619,   1604,   1575,   1619,   1604,   1575,
5498
    1620,   1604,   1575,   1620,   1604,   1575,   1621,   1604,   1575,
5499
    1621,   1604,   1575,   1604,   1575,   33,     34,     35,     36,
5500
    37,     38,     39,     40,     41,     42,     43,     44,     45,
5501
    46,     47,     48,     49,     50,     51,     52,     53,     54,
5502
    55,     56,     57,     58,     59,     60,     61,     62,     63,
5503
    64,     65,     66,     67,     68,     69,     70,     71,     72,
5504
    73,     74,     75,     76,     77,     78,     79,     80,     81,
5505
    82,     83,     84,     85,     86,     87,     88,     89,     90,
5506
    91,     92,     93,     94,     95,     96,     97,     98,     99,
5507
    100,    101,    102,    103,    104,    105,    106,    107,    108,
5508
    109,    110,    111,    112,    113,    114,    115,    116,    117,
5509
    118,    119,    120,    121,    122,    123,    124,    125,    126,
5510
    10629,  10630,  12290,  12300,  12301,  12289,  12539,  12530,  12449,
5511
    12451,  12453,  12455,  12457,  12515,  12517,  12519,  12483,  12540,
5512
    12450,  12452,  12454,  12456,  12458,  12459,  12461,  12463,  12465,
5513
    12467,  12469,  12471,  12473,  12475,  12477,  12479,  12481,  12484,
5514
    12486,  12488,  12490,  12491,  12492,  12493,  12494,  12495,  12498,
5515
    12501,  12504,  12507,  12510,  12511,  12512,  12513,  12514,  12516,
5516
    12518,  12520,  12521,  12522,  12523,  12524,  12525,  12527,  12531,
5517
    12441,  12442,  4448,   4352,   4353,   4522,   4354,   4524,   4525,
5518
    4355,   4356,   4357,   4528,   4529,   4530,   4531,   4532,   4533,
5519
    4378,   4358,   4359,   4360,   4385,   4361,   4362,   4363,   4364,
5520
    4365,   4366,   4367,   4368,   4369,   4370,   4449,   4450,   4451,
5521
    4452,   4453,   4454,   4455,   4456,   4457,   4458,   4459,   4460,
5522
    4461,   4462,   4463,   4464,   4465,   4466,   4467,   4468,   4469,
5523
    162,    163,    172,    32,     772,    166,    165,    8361,   9474,
5524
    8592,   8593,   8594,   8595,   9632,   9675,   720,    721,    230,
5525
    665,    595,    675,    43878,  677,    676,    598,    599,    7569,
5526
    600,    606,    681,    612,    610,    608,    667,    295,    668,
5527
    615,    644,    682,    683,    620,    122628, 42894,  622,    122629,
5528
    654,    122630, 248,    630,    631,    113,    634,    122632, 637,
5529
    638,    640,    680,    678,    43879,  679,    648,    11377,  655,
5530
    673,    674,    664,    448,    449,    450,    122634, 122654, 69785,
5531
    69818,  69787,  69818,  69797,  69818,  69937,  69927,  69938,  69927,
5532
    70471,  70462,  70471,  70487,  70841,  70842,  70841,  70832,  70841,
5533
    70845,  71096,  71087,  71097,  71087,  71989,  71984,  119127, 119141,
5534
    119128, 119141, 119128, 119141, 119150, 119128, 119141, 119151, 119128,
5535
    119141, 119152, 119128, 119141, 119153, 119128, 119141, 119154, 119225,
5536
    119141, 119226, 119141, 119225, 119141, 119150, 119226, 119141, 119150,
5537
    119225, 119141, 119151, 119226, 119141, 119151, 65,     66,     67,
5538
    68,     69,     70,     71,     72,     73,     74,     75,     76,
5539
    77,     78,     79,     80,     81,     82,     83,     84,     85,
5540
    86,     87,     88,     89,     90,     97,     98,     99,     100,
5541
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5542
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5543
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5544
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5545
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5546
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5547
    103,    105,    106,    107,    108,    109,    110,    111,    112,
5548
    113,    114,    115,    116,    117,    118,    119,    120,    121,
5549
    122,    65,     66,     67,     68,     69,     70,     71,     72,
5550
    73,     74,     75,     76,     77,     78,     79,     80,     81,
5551
    82,     83,     84,     85,     86,     87,     88,     89,     90,
5552
    97,     98,     99,     100,    101,    102,    103,    104,    105,
5553
    106,    107,    108,    109,    110,    111,    112,    113,    114,
5554
    115,    116,    117,    118,    119,    120,    121,    122,    65,
5555
    67,     68,     71,     74,     75,     78,     79,     80,     81,
5556
    83,     84,     85,     86,     87,     88,     89,     90,     97,
5557
    98,     99,     100,    102,    104,    105,    106,    107,    108,
5558
    109,    110,    112,    113,    114,    115,    116,    117,    118,
5559
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5560
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5561
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5562
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5563
    103,    104,    105,    106,    107,    108,    109,    110,    111,
5564
    112,    113,    114,    115,    116,    117,    118,    119,    120,
5565
    121,    122,    65,     66,     68,     69,     70,     71,     74,
5566
    75,     76,     77,     78,     79,     80,     81,     83,     84,
5567
    85,     86,     87,     88,     89,     97,     98,     99,     100,
5568
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5569
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5570
    119,    120,    121,    122,    65,     66,     68,     69,     70,
5571
    71,     73,     74,     75,     76,     77,     79,     83,     84,
5572
    85,     86,     87,     88,     89,     97,     98,     99,     100,
5573
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5574
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5575
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5576
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5577
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5578
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5579
    103,    104,    105,    106,    107,    108,    109,    110,    111,
5580
    112,    113,    114,    115,    116,    117,    118,    119,    120,
5581
    121,    122,    65,     66,     67,     68,     69,     70,     71,
5582
    72,     73,     74,     75,     76,     77,     78,     79,     80,
5583
    81,     82,     83,     84,     85,     86,     87,     88,     89,
5584
    90,     97,     98,     99,     100,    101,    102,    103,    104,
5585
    105,    106,    107,    108,    109,    110,    111,    112,    113,
5586
    114,    115,    116,    117,    118,    119,    120,    121,    122,
5587
    65,     66,     67,     68,     69,     70,     71,     72,     73,
5588
    74,     75,     76,     77,     78,     79,     80,     81,     82,
5589
    83,     84,     85,     86,     87,     88,     89,     90,     97,
5590
    98,     99,     100,    101,    102,    103,    104,    105,    106,
5591
    107,    108,    109,    110,    111,    112,    113,    114,    115,
5592
    116,    117,    118,    119,    120,    121,    122,    65,     66,
5593
    67,     68,     69,     70,     71,     72,     73,     74,     75,
5594
    76,     77,     78,     79,     80,     81,     82,     83,     84,
5595
    85,     86,     87,     88,     89,     90,     97,     98,     99,
5596
    100,    101,    102,    103,    104,    105,    106,    107,    108,
5597
    109,    110,    111,    112,    113,    114,    115,    116,    117,
5598
    118,    119,    120,    121,    122,    65,     66,     67,     68,
5599
    69,     70,     71,     72,     73,     74,     75,     76,     77,
5600
    78,     79,     80,     81,     82,     83,     84,     85,     86,
5601
    87,     88,     89,     90,     97,     98,     99,     100,    101,
5602
    102,    103,    104,    105,    106,    107,    108,    109,    110,
5603
    111,    112,    113,    114,    115,    116,    117,    118,    119,
5604
    120,    121,    122,    65,     66,     67,     68,     69,     70,
5605
    71,     72,     73,     74,     75,     76,     77,     78,     79,
5606
    80,     81,     82,     83,     84,     85,     86,     87,     88,
5607
    89,     90,     97,     98,     99,     100,    101,    102,    103,
5608
    104,    105,    106,    107,    108,    109,    110,    111,    112,
5609
    113,    114,    115,    116,    117,    118,    119,    120,    121,
5610
    122,    305,    567,    913,    914,    915,    916,    917,    918,
5611
    919,    920,    921,    922,    923,    924,    925,    926,    927,
5612
    928,    929,    920,    931,    932,    933,    934,    935,    936,
5613
    937,    8711,   945,    946,    947,    948,    949,    950,    951,
5614
    952,    953,    954,    955,    956,    957,    958,    959,    960,
5615
    961,    962,    963,    964,    965,    966,    967,    968,    969,
5616
    8706,   949,    952,    954,    966,    961,    960,    913,    914,
5617
    915,    916,    917,    918,    919,    920,    921,    922,    923,
5618
    924,    925,    926,    927,    928,    929,    920,    931,    932,
5619
    933,    934,    935,    936,    937,    8711,   945,    946,    947,
5620
    948,    949,    950,    951,    952,    953,    954,    955,    956,
5621
    957,    958,    959,    960,    961,    962,    963,    964,    965,
5622
    966,    967,    968,    969,    8706,   949,    952,    954,    966,
5623
    961,    960,    913,    914,    915,    916,    917,    918,    919,
5624
    920,    921,    922,    923,    924,    925,    926,    927,    928,
5625
    929,    920,    931,    932,    933,    934,    935,    936,    937,
5626
    8711,   945,    946,    947,    948,    949,    950,    951,    952,
5627
    953,    954,    955,    956,    957,    958,    959,    960,    961,
5628
    962,    963,    964,    965,    966,    967,    968,    969,    8706,
5629
    949,    952,    954,    966,    961,    960,    913,    914,    915,
5630
    916,    917,    918,    919,    920,    921,    922,    923,    924,
5631
    925,    926,    927,    928,    929,    920,    931,    932,    933,
5632
    934,    935,    936,    937,    8711,   945,    946,    947,    948,
5633
    949,    950,    951,    952,    953,    954,    955,    956,    957,
5634
    958,    959,    960,    961,    962,    963,    964,    965,    966,
5635
    967,    968,    969,    8706,   949,    952,    954,    966,    961,
5636
    960,    913,    914,    915,    916,    917,    918,    919,    920,
5637
    921,    922,    923,    924,    925,    926,    927,    928,    929,
5638
    920,    931,    932,    933,    934,    935,    936,    937,    8711,
5639
    945,    946,    947,    948,    949,    950,    951,    952,    953,
5640
    954,    955,    956,    957,    958,    959,    960,    961,    962,
5641
    963,    964,    965,    966,    967,    968,    969,    8706,   949,
5642
    952,    954,    966,    961,    960,    988,    989,    48,     49,
5643
    50,     51,     52,     53,     54,     55,     56,     57,     48,
5644
    49,     50,     51,     52,     53,     54,     55,     56,     57,
5645
    48,     49,     50,     51,     52,     53,     54,     55,     56,
5646
    57,     48,     49,     50,     51,     52,     53,     54,     55,
5647
    56,     57,     48,     49,     50,     51,     52,     53,     54,
5648
    55,     56,     57,     1072,   1073,   1074,   1075,   1076,   1077,
5649
    1078,   1079,   1080,   1082,   1083,   1084,   1086,   1087,   1088,
5650
    1089,   1090,   1091,   1092,   1093,   1094,   1095,   1096,   1099,
5651
    1101,   1102,   42633,  1241,   1110,   1112,   1257,   1199,   1231,
5652
    1072,   1073,   1074,   1075,   1076,   1077,   1078,   1079,   1080,
5653
    1082,   1083,   1086,   1087,   1089,   1091,   1092,   1093,   1094,
5654
    1095,   1096,   1098,   1099,   1169,   1110,   1109,   1119,   1195,
5655
    42577,  1201,   1575,   1576,   1580,   1583,   1608,   1586,   1581,
5656
    1591,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5657
    1589,   1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,
5658
    1592,   1594,   1646,   1722,   1697,   1647,   1576,   1580,   1607,
5659
    1581,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5660
    1589,   1602,   1588,   1578,   1579,   1582,   1590,   1594,   1580,
5661
    1581,   1610,   1604,   1606,   1587,   1593,   1589,   1602,   1588,
5662
    1582,   1590,   1594,   1722,   1647,   1576,   1580,   1607,   1581,
5663
    1591,   1610,   1603,   1605,   1606,   1587,   1593,   1601,   1589,
5664
    1602,   1588,   1578,   1579,   1582,   1590,   1592,   1594,   1646,
5665
    1697,   1575,   1576,   1580,   1583,   1607,   1608,   1586,   1581,
5666
    1591,   1610,   1604,   1605,   1606,   1587,   1593,   1601,   1589,
5667
    1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,   1592,
5668
    1594,   1576,   1580,   1583,   1608,   1586,   1581,   1591,   1610,
5669
    1604,   1605,   1606,   1587,   1593,   1601,   1589,   1602,   1585,
5670
    1588,   1578,   1579,   1582,   1584,   1590,   1592,   1594,   48,
5671
    46,     48,     44,     49,     44,     50,     44,     51,     44,
5672
    52,     44,     53,     44,     54,     44,     55,     44,     56,
5673
    44,     57,     44,     40,     65,     41,     40,     66,     41,
5674
    40,     67,     41,     40,     68,     41,     40,     69,     41,
5675
    40,     70,     41,     40,     71,     41,     40,     72,     41,
5676
    40,     73,     41,     40,     74,     41,     40,     75,     41,
5677
    40,     76,     41,     40,     77,     41,     40,     78,     41,
5678
    40,     79,     41,     40,     80,     41,     40,     81,     41,
5679
    40,     82,     41,     40,     83,     41,     40,     84,     41,
5680
    40,     85,     41,     40,     86,     41,     40,     87,     41,
5681
    40,     88,     41,     40,     89,     41,     40,     90,     41,
5682
    12308,  83,     12309,  67,     82,     67,     68,     87,     90,
5683
    65,     66,     67,     68,     69,     70,     71,     72,     73,
5684
    74,     75,     76,     77,     78,     79,     80,     81,     82,
5685
    83,     84,     85,     86,     87,     88,     89,     90,     72,
5686
    86,     77,     86,     83,     68,     83,     83,     80,     80,
5687
    86,     87,     67,     77,     67,     77,     68,     77,     82,
5688
    68,     74,     12411,  12363,  12467,  12467,  12469,  25163,  23383,
5689
    21452,  12486,  12441,  20108,  22810,  35299,  22825,  20132,  26144,
5690
    28961,  26009,  21069,  24460,  20877,  26032,  21021,  32066,  29983,
5691
    36009,  22768,  21561,  28436,  25237,  25429,  19968,  19977,  36938,
5692
    24038,  20013,  21491,  25351,  36208,  25171,  31105,  31354,  21512,
5693
    28288,  26377,  26376,  30003,  21106,  21942,  37197,  12308,  26412,
5694
    12309,  12308,  19977,  12309,  12308,  20108,  12309,  12308,  23433,
5695
    12309,  12308,  28857,  12309,  12308,  25171,  12309,  12308,  30423,
5696
    12309,  12308,  21213,  12309,  12308,  25943,  12309,  24471,  21487,
5697
    48,     49,     50,     51,     52,     53,     54,     55,     56,
5698
    57,     20029,  20024,  20033,  131362, 20320,  20398,  20411,  20482,
5699
    20602,  20633,  20711,  20687,  13470,  132666, 20813,  20820,  20836,
5700
    20855,  132380, 13497,  20839,  20877,  132427, 20887,  20900,  20172,
5701
    20908,  20917,  168415, 20981,  20995,  13535,  21051,  21062,  21106,
5702
    21111,  13589,  21191,  21193,  21220,  21242,  21253,  21254,  21271,
5703
    21321,  21329,  21338,  21363,  21373,  21375,  21375,  21375,  133676,
5704
    28784,  21450,  21471,  133987, 21483,  21489,  21510,  21662,  21560,
5705
    21576,  21608,  21666,  21750,  21776,  21843,  21859,  21892,  21892,
5706
    21913,  21931,  21939,  21954,  22294,  22022,  22295,  22097,  22132,
5707
    20999,  22766,  22478,  22516,  22541,  22411,  22578,  22577,  22700,
5708
    136420, 22770,  22775,  22790,  22810,  22818,  22882,  136872, 136938,
5709
    23020,  23067,  23079,  23000,  23142,  14062,  14076,  23304,  23358,
5710
    23358,  137672, 23491,  23512,  23527,  23539,  138008, 23551,  23558,
5711
    24403,  23586,  14209,  23648,  23662,  23744,  23693,  138724, 23875,
5712
    138726, 23918,  23915,  23932,  24033,  24034,  14383,  24061,  24104,
5713
    24125,  24169,  14434,  139651, 14460,  24240,  24243,  24246,  24266,
5714
    172946, 24318,  140081, 140081, 33281,  24354,  24354,  14535,  144056,
5715
    156122, 24418,  24427,  14563,  24474,  24525,  24535,  24569,  24705,
5716
    14650,  14620,  24724,  141012, 24775,  24904,  24908,  24910,  24908,
5717
    24954,  24974,  25010,  24996,  25007,  25054,  25074,  25078,  25104,
5718
    25115,  25181,  25265,  25300,  25424,  142092, 25405,  25340,  25448,
5719
    25475,  25572,  142321, 25634,  25541,  25513,  14894,  25705,  25726,
5720
    25757,  25719,  14956,  25935,  25964,  143370, 26083,  26360,  26185,
5721
    15129,  26257,  15112,  15076,  20882,  20885,  26368,  26268,  32941,
5722
    17369,  26391,  26395,  26401,  26462,  26451,  144323, 15177,  26618,
5723
    26501,  26706,  26757,  144493, 26766,  26655,  26900,  15261,  26946,
5724
    27043,  27114,  27304,  145059, 27355,  15384,  27425,  145575, 27476,
5725
    15438,  27506,  27551,  27578,  27579,  146061, 138507, 146170, 27726,
5726
    146620, 27839,  27853,  27751,  27926,  27966,  28023,  27969,  28009,
5727
    28024,  28037,  146718, 27956,  28207,  28270,  15667,  28363,  28359,
5728
    147153, 28153,  28526,  147294, 147342, 28614,  28729,  28702,  28699,
5729
    15766,  28746,  28797,  28791,  28845,  132389, 28997,  148067, 29084,
5730
    148395, 29224,  29237,  29264,  149000, 29312,  29333,  149301, 149524,
5731
    29562,  29579,  16044,  29605,  16056,  16056,  29767,  29788,  29809,
5732
    29829,  29898,  16155,  29988,  150582, 30014,  150674, 30064,  139679,
5733
    30224,  151457, 151480, 151620, 16380,  16392,  30452,  151795, 151794,
5734
    151833, 151859, 30494,  30495,  30495,  30538,  16441,  30603,  16454,
5735
    16534,  152605, 30798,  30860,  30924,  16611,  153126, 31062,  153242,
5736
    153285, 31119,  31211,  16687,  31296,  31306,  31311,  153980, 154279,
5737
    154279, 31470,  16898,  154539, 31686,  31689,  16935,  154752, 31954,
5738
    17056,  31976,  31971,  32000,  155526, 32099,  17153,  32199,  32258,
5739
    32325,  17204,  156200, 156231, 17241,  156377, 32634,  156478, 32661,
5740
    32762,  32773,  156890, 156963, 32864,  157096, 32880,  144223, 17365,
5741
    32946,  33027,  17419,  33086,  23221,  157607, 157621, 144275, 144284,
5742
    33281,  33284,  36766,  17515,  33425,  33419,  33437,  21171,  33457,
5743
    33459,  33469,  33510,  158524, 33509,  33565,  33635,  33709,  33571,
5744
    33725,  33767,  33879,  33619,  33738,  33740,  33756,  158774, 159083,
5745
    158933, 17707,  34033,  34035,  34070,  160714, 34148,  159532, 17757,
5746
    17761,  159665, 159954, 17771,  34384,  34396,  34407,  34409,  34473,
5747
    34440,  34574,  34530,  34681,  34600,  34667,  34694,  17879,  34785,
5748
    34817,  17913,  34912,  34915,  161383, 35031,  35038,  17973,  35066,
5749
    13499,  161966, 162150, 18110,  18119,  35488,  35565,  35722,  35925,
5750
    162984, 36011,  36033,  36123,  36215,  163631, 133124, 36299,  36284,
5751
    36336,  133342, 36564,  36664,  165330, 165357, 37012,  37105,  37137,
5752
    165678, 37147,  37432,  37591,  37592,  37500,  37881,  37909,  166906,
5753
    38283,  18837,  38327,  167287, 18918,  38595,  23986,  38691,  168261,
5754
    168474, 19054,  19062,  38880,  168970, 19122,  169110, 38923,  38923,
5755
    38953,  169398, 39138,  19251,  39209,  39335,  39362,  39422,  19406,
5756
    170800, 39698,  40000,  40189,  19662,  19693,  40295,  172238, 19704,
5757
    172293, 172558, 172689, 40635,  19798,  40697,  40702,  40709,  40719,
5758
    40726,  40763,  173568};
5759
5760
const uint8_t canonical_combining_class_index[4352] = {
5761
    0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 0,  0,
5762
    15, 0,  0,  0,  16, 17, 18, 19, 20, 21, 22, 0,  0,  23, 0,  0,  0,  0,  0,
5763
    0,  0,  0,  0,  0,  0,  24, 25, 0,  0,  26, 0,  0,  0,  0,  0,  0,  0,  0,
5764
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5765
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5766
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5767
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5768
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5769
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  27, 0,  28, 29, 30,
5770
    31, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5771
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5772
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5773
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5774
    0,  0,  0,  0,  32, 0,  0,  33, 0,  0,  34, 35, 36, 0,  0,  0,  0,  0,  0,
5775
    37, 0,  0,  38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,  52,
5776
    53, 0,  54, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5777
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5778
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5779
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5780
    0,  55, 56, 0,  0,  0,  57, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5781
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5782
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5783
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5784
    0,  0,  0,  0,  0,  0,  0,  58, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5785
    0,  0,  0,  0,  0,  0,  0,  0,  0,  59, 60, 0,  0,  0,  0,  0,  0,  0,  0,
5786
    0,  0,  0,  0,  0,  61, 56, 62, 0,  63, 0,  0,  0,  64, 65, 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,  0,  0,  0,  0,  0,
5792
    0,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5797
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5798
    0,  0,  0,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5803
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5804
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5805
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5806
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5807
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5808
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5809
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5810
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5811
    0,  0,  0,  0,  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};
5991
const uint8_t canonical_combining_class_block[67][256] = {
5992
    {0, 0, 0, 0, 0, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0, 0, 0, 0, 0,
6002
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6003
    {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6004
     230, 230, 230, 230, 230, 230, 232, 220, 220, 220, 220, 232, 216, 220, 220,
6005
     220, 220, 220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220,
6006
     220, 220, 220, 220, 220, 220, 220, 1,   1,   1,   1,   1,   220, 220, 220,
6007
     220, 230, 230, 230, 230, 230, 230, 230, 230, 240, 230, 220, 220, 220, 230,
6008
     230, 230, 220, 220, 0,   230, 230, 230, 220, 220, 220, 220, 230, 232, 220,
6009
     220, 230, 233, 234, 234, 233, 234, 234, 233, 230, 230, 230, 230, 230, 230,
6010
     230, 230, 230, 230, 230, 230, 230, 0,   0,   0,   0,   0,   0,   0,   0,
6011
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6012
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6013
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6014
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6015
     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,
6017
     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,
6019
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6020
     0},
6021
    {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,
6023
     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, 0, 0, 0, 0, 0, 0,
6025
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6026
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230,
6027
     230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6028
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6029
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6030
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6031
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6032
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
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,   0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 230, 230, 230, 230,
6043
     220, 230, 230, 230, 222, 220, 230, 230, 230, 230, 230, 230, 220, 220, 220,
6044
     220, 220, 220, 230, 230, 220, 230, 230, 222, 228, 230, 10,  11,  12,  13,
6045
     14,  15,  16,  17,  18,  19,  19,  20,  21,  22,  0,   23,  0,   24,  25,
6046
     0,   230, 220, 0,   18,  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,
6048
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6049
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6050
     0},
6051
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6052
     0,   230, 230, 230, 230, 230, 230, 230, 230, 30,  31,  32,  0,   0,   0,
6053
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6054
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6055
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6056
     27,  28,  29,  30,  31,  32,  33,  34,  230, 230, 220, 220, 230, 230, 230,
6057
     230, 230, 220, 230, 230, 220, 0,   0,   0,   0,   0,   0,   0,   0,   0,
6058
     0,   0,   0,   0,   0,   0,   0,   35,  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,   0,   0,   0,   0,   0,
6065
     0,   0,   0,   0,   230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230,
6066
     230, 230, 220, 230, 0,   0,   230, 230, 0,   220, 230, 230, 220, 0,   0,
6067
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6068
     0},
6069
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6070
     0,   0,   36,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6071
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6072
     0,   0,   0,   230, 220, 230, 230, 220, 230, 230, 220, 220, 220, 230, 220,
6073
     220, 230, 220, 230, 230, 230, 220, 230, 220, 230, 220, 230, 220, 230, 230,
6074
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6075
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6076
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6077
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6078
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6079
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6080
     0,   0,   0,   0,   0,   0,   0,   0,   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,   230, 230, 230, 230, 230,
6085
     230, 230, 220, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 0,
6086
     0},
6087
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6088
     0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 0,   230, 230, 230,
6089
     230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 0,   230, 230, 230, 230,
6090
     230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6091
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6092
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   220,
6093
     220, 220, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6094
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6095
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6096
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6097
     0,   0,   230, 220, 220, 220, 230, 230, 230, 230, 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,   230, 230, 230, 230, 230, 220, 220, 220,
6101
     220, 220, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6102
     230, 0,   220, 230, 230, 220, 230, 230, 220, 230, 230, 230, 220, 220, 220,
6103
     27,  28,  29,  230, 230, 230, 220, 230, 230, 220, 220, 230, 230, 230, 230,
6104
     230},
6105
    {0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6107
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   7,   0,   0,   0, 0, 0,
6108
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0, 0, 230, 220, 230, 230, 0, 0, 0,
6109
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6110
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6111
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6112
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6113
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6114
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6115
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6116
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0},
6117
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6119
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6120
     0, 0, 0, 0, 0, 9, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6122
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6123
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6124
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
6125
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6126
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6127
     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, 0, 0,
6129
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6130
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6131
     0, 0, 0, 0, 0, 9, 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, 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, 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, 0, 0,
6135
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6136
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 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, 0, 0,
6138
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 84, 91, 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, 9, 9, 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, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6159
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6160
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6161
    {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,
6163
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6164
     0,   0,   103, 103, 9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6165
     107, 107, 107, 107, 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,
6167
     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,
6169
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6170
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6171
     0,   0,   0,   0,   118, 118, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6172
     0,   0,   122, 122, 122, 122, 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,
6174
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6175
     0,   0,   0,   0},
6176
    {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,   220, 220, 0,   0,   0, 0,
6178
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6179
     0,   0, 0,   0,   0,   0,   0, 0, 220, 0,   220, 0,   216, 0, 0,
6180
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6181
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6182
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6183
     0,   0, 0,   0,   0,   0,   0, 0, 129, 130, 0,   132, 0,   0, 0,
6184
     0,   0, 130, 130, 130, 130, 0, 0, 130, 0,   230, 230, 9,   0, 230,
6185
     230, 0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6186
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6187
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6188
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6189
     0,   0, 0,   220, 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,
6191
     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,
6193
     0},
6194
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6195
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6196
     0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6197
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6198
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6199
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0,
6200
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6201
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6202
     0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6204
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6205
    {0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6206
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6207
     0, 0, 0, 0, 0, 0,   0,   0,   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, 0, 0, 0, 0, 0, 0, 0,
6209
     0, 0, 0, 0, 0, 230, 230, 230, 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, 0, 0, 0, 0, 0, 0, 0,
6211
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6212
     0, 0, 0, 0, 0, 0,   0,   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, 0, 0, 0, 0, 0, 0, 0,
6214
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6215
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6216
     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, 9, 9, 0, 0,
6218
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6219
     0, 0, 0, 0, 9, 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, 0, 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, 9, 0, 0, 0, 0, 0,
6226
     0, 0, 0, 0, 0, 230, 0, 0, 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},
6228
    {0, 0,   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, 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, 0, 0,
6231
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6232
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6233
     0, 0,   0, 0, 0, 0, 0, 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, 0, 0,
6235
     0, 228, 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, 0, 0,
6237
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6238
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6239
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6240
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6241
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 230, 220, 0, 0, 0, 0, 0, 0,
6242
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6243
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6244
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6245
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6246
     0, 0, 0, 0, 0, 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, 0, 0, 0, 0,
6248
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6249
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6250
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6251
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6252
     0,   0,   0,   0,   0,   0,   0,   0,   230, 220, 0,   0,   0,   0,   0,
6253
     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,
6255
     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,
6257
     0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6258
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230,
6259
     230, 230, 230, 230, 230, 0,   0,   220, 0,   0,   0,   0,   0,   0,   0,
6260
     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,
6262
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230,
6263
     230, 220, 220, 220, 220, 220, 220, 230, 230, 220, 0,   220, 220, 230, 230,
6264
     220, 220, 230, 230, 230, 230, 230, 220, 230, 230, 230, 230, 0,   0,   0,
6265
     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,
6267
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6268
     0},
6269
    {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,
6271
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   7,   0,   0,   0,   0,
6272
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0,   0,   0,   0,   0,   0,
6273
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6274
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 230, 230, 230, 230, 230,
6275
     230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6276
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6277
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   9,
6278
     9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6279
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6280
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6281
     0,   0,   7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   9,   9,   0,   0,   0,
6282
     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,   0,   0,   0,   0,
6285
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6286
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   7,   0,   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,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6291
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6292
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6293
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6294
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6295
     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,   0,   230, 230,
6297
     230, 0, 1, 220, 220, 220, 220, 220, 230, 230, 220, 220, 220, 220, 230,
6298
     0,   1, 1, 1,   1,   1,   1,   1,   0,   0,   0,   0,   220, 0,   0,
6299
     0,   0, 0, 0,   230, 0,   0,   0,   230, 230, 0,   0,   0,   0,   0,
6300
     0},
6301
    {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,
6303
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6304
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6305
     0,   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,   0,   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,   230, 230, 220,
6314
     230, 230, 230, 230, 230, 230, 230, 220, 230, 230, 234, 214, 220, 202, 230,
6315
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6316
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6317
     230, 230, 230, 230, 230, 230, 232, 228, 228, 220, 218, 230, 233, 220, 230,
6318
     220},
6319
    {0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6320
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6321
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6322
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6323
     0,   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,   0,
6325
     0,   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,   0,
6327
     0,   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,   0,
6329
     0,   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,   0,
6331
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6332
     230, 230, 1, 1, 230, 230, 230, 230, 1,   1,   1, 230, 230, 0,   0,   0,
6333
     0,   230, 0, 0, 0,   1,   1,   230, 220, 230, 1, 1,   220, 220, 220, 220,
6334
     230, 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, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6336
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6337
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6338
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6339
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6340
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6341
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6342
     0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0,   0,   0,
6344
     0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 230, 230, 230,
6346
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6347
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6348
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6349
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6350
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6351
     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,
6353
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6354
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6355
     0,   0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,
6356
     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,
6358
     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,
6360
     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,   230,
6362
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6363
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6364
     230},
6365
    {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,
6367
     0, 0, 218, 228, 232, 222, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6368
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6369
     0, 0, 0,   0,   0,   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, 0, 0, 0, 0, 0,
6371
     0, 0, 0,   0,   0,   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, 8, 8, 0, 0, 0, 0, 0,
6373
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6374
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6375
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6376
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6377
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0},
6378
    {0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6379
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6380
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6381
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6382
     0,   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,   0,   0,
6384
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6385
     0,   0,   0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,
6386
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6387
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230,
6388
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6389
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6390
     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,
6392
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6393
     230, 230, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0},
6394
    {0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6395
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6396
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   9,
6397
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6398
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6399
     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,
6401
     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,
6403
     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,
6405
     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,
6407
     0,   9,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6408
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6409
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6410
     230, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6411
     0},
6412
    {0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6413
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220,
6414
     220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6415
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
6416
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6417
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6418
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6419
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6420
     0,   0,   0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6421
     0,   0,   0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0,
6423
     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, 0, 0, 0, 0,
6425
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6426
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6427
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6428
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6429
     0,   0,   0, 0,   0, 0,   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,   0, 0, 0, 0, 0,
6431
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6432
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6433
     0,   0,   0, 0,   0, 230, 0, 230, 230, 220, 0, 0, 230, 230, 0, 0, 0, 0, 0,
6434
     230, 230, 0, 230, 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,
6436
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 9,
6437
     0,   0,   0, 0,   0, 0,   0, 0,   0},
6438
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 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, 0, 0,
6442
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6443
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0,
6445
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 9, 0, 0,
6448
     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, 0, 0, 0, 0, 0,
6450
     0, 0, 0, 0, 0, 0, 26, 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, 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, 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, 0, 0, 0, 0, 0,
6454
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6455
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6456
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6457
     0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0,
6459
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0},
6460
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6461
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6462
     0,   0,   230, 230, 230, 230, 230, 230, 230, 220, 220, 220, 220, 220, 220,
6463
     220, 230, 230, 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,
6465
     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,
6467
     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,
6469
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6470
     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,
6472
     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,
6474
     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,
6476
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6477
     0},
6478
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6479
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6480
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6481
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6482
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6483
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6484
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6485
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6486
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6487
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6488
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0},
6489
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6490
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6491
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6492
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6493
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6494
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6495
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6496
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6497
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6498
     0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6499
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0},
6500
    {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,
6502
     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,
6504
     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, 230, 230, 230, 230, 230, 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,
6507
     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,
6509
     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,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6511
     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, 220, 0, 230, 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,
6514
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   230, 1, 220, 0,
6515
     0, 0, 0, 9, 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,
6517
     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,
6519
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6520
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6521
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6522
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6523
     0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 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},
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, 230, 230, 230, 230, 0, 0, 0, 0,
6527
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
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, 0,   0,   0,   0,   0, 0, 0, 0,
6534
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6535
     0, 0, 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},
6537
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6538
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6539
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6540
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6541
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6542
     0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0,
6544
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 230, 230, 0, 0, 0,
6545
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6546
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6547
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6548
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220},
6549
    {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,
6551
     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, 220, 220,
6553
     230, 230, 230, 220, 230, 220, 220, 220, 220, 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,
6555
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6556
     0,   0,   0,   0,   230, 220, 230, 220, 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,
6558
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6559
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6560
     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,
6562
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6563
     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, 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, 0, 0,
6566
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,
6567
     0, 0, 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, 9, 0, 0, 0, 0, 0, 0, 0,
6569
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6570
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6571
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0,
6572
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6573
     0, 0, 0, 0, 0, 0, 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},
6575
    {230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6576
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6577
     0,   0,   0,   0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6578
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6579
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6580
     0,   0,   0,   0, 0, 7, 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, 0, 0, 0, 0,
6582
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6583
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6584
     0,   0,   0,   0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6585
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6586
     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, 0, 0,
6589
     0, 0, 0, 0, 0, 9, 7, 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, 0, 0, 0, 0, 0, 0, 0, 0,
6591
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0,
6594
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 7, 9, 0, 0, 0, 0, 0,
6597
     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,
6599
     0,   0,   0,   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,
6601
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   7,   7,   0, 0, 0,
6602
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   9, 0, 0,
6603
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6604
     0,   0,   0,   0,   0,   0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0,
6605
     230, 230, 230, 230, 230, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6606
     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,
6608
     0,   0,   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,
6610
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6611
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6612
     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},
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, 9, 0, 0, 0, 7,   0,
6617
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0,
6618
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6619
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6620
     0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0,   0,
6622
     0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6623
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6624
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6625
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6626
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6627
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6628
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6629
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6630
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6631
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6632
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
6633
     7, 0, 0, 0, 0, 0, 0, 0, 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, 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, 9, 0, 0, 0, 0, 0, 0, 0, 0,
6639
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0,
6644
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 9, 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, 0,
6655
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6656
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6657
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
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, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6661
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6662
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6663
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6664
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6665
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6666
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6667
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6668
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
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, 0, 0, 0, 0, 0,
6671
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 7, 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, 9, 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, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
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, 9, 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, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
6694
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6701
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6702
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6703
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6704
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0,
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, 9, 0, 0, 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, 0, 0, 9, 9, 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, 0, 0, 0, 0, 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, 0, 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
     1, 1, 1, 1, 1, 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,
6736
     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, 230, 230, 230, 230, 230, 230, 230, 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,
6739
     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,
6741
     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,
6743
     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,
6745
     0, 0, 0, 0, 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,
6747
     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
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6757
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6758
     6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6759
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6760
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6761
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6762
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6763
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6764
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6765
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6766
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6767
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6768
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6769
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6770
    {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,
6772
     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,
6774
     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,
6776
     0,   0,   0,   0, 0, 216, 216, 1,   1,   1,   0,   0,   0,   226, 216, 216,
6777
     216, 216, 216, 0, 0, 0,   0,   0,   0,   0,   0,   220, 220, 220, 220, 220,
6778
     220, 220, 220, 0, 0, 230, 230, 230, 230, 230, 220, 220, 0,   0,   0,   0,
6779
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6780
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   230, 230, 230, 230, 0,   0,
6781
     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,
6783
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6784
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6785
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0},
6786
    {0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6787
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6788
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6789
     230, 230, 230, 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,
6791
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6792
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6793
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6794
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6795
     0,   0,   0,   0, 0, 0, 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, 0, 0, 0, 0, 0, 0,
6797
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6798
    {230, 230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 230, 230, 230, 230,
6799
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230, 230,
6800
     230, 230, 230, 230, 0,   230, 230, 0,   230, 230, 230, 230, 230, 0,   0,
6801
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6802
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6803
     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,
6805
     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,
6807
     0,   0,   0,   0,   0,   0,   0,   0,   230, 0,   0,   0,   0,   0,   0,
6808
     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,
6810
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6811
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6812
     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,
6814
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6815
     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, 0, 0, 0,   0,   0,   0,   0,   0,
6820
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6821
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6822
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6823
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   230, 0,
6824
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6825
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6826
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0,   0,
6827
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6828
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6829
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6830
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6831
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6832
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6833
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6834
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6835
     0, 0, 0, 0, 0, 0, 0, 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, 0, 0,   0,   0,   0,   0, 0,
6837
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6838
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 232, 220, 230, 0, 0,
6839
     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,
6841
     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,
6843
     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,
6845
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6846
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   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,
6848
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6849
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6850
     0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 220, 220, 220, 220, 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,
6852
     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,
6854
     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,
6856
     0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 7, 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,
6858
     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,
6860
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6861
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6862
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
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}};
6866
6867
const uint8_t composition_index[4352] = {
6868
    0, 1, 2, 3, 4,  5,  6, 5, 5,  7,  5, 8,  9,  10, 5, 5, 11, 5,  5, 5, 5, 5,
6869
    5, 5, 5, 5, 5,  12, 5, 5, 13, 14, 5, 15, 16, 5,  5, 5, 5,  5,  5, 5, 5, 5,
6870
    5, 5, 5, 5, 17, 5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6871
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6872
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6873
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6874
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6875
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6876
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6877
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6878
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6879
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6880
    5, 5, 5, 5, 5,  5,  5, 5, 18, 19, 5, 20, 21, 22, 5, 5, 5,  23, 5, 5, 5, 5,
6881
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6882
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6883
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6884
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6885
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6886
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6887
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6888
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6889
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6890
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6891
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6892
    5, 5, 5, 5, 5,  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, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  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};
7066
const uint16_t composition_block[67][257] = {
7067
    {1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7068
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7069
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7070
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7071
     1,   3,   5,   7,   7,   7,   39,  45,  55,  67,  101, 103, 117, 131, 161,
7072
     163, 173, 185, 191, 209, 241, 245, 245, 261, 275, 289, 327, 331, 343, 347,
7073
     365, 377, 377, 377, 377, 377, 377, 377, 409, 415, 425, 437, 471, 473, 487,
7074
     503, 531, 535, 545, 557, 563, 581, 613, 617, 617, 633, 647, 663, 701, 705,
7075
     719, 723, 743, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7076
     755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7077
     755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7078
     755, 755, 755, 755, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7079
     761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7080
     769, 769, 771, 773, 777, 779, 779, 779, 787, 787, 787, 787, 787, 789, 789,
7081
     789, 789, 789, 797, 803, 805, 805, 807, 807, 807, 807, 815, 815, 815, 815,
7082
     815, 815, 823, 823, 825, 827, 831, 833, 833, 833, 841, 841, 841, 841, 841,
7083
     843, 843, 843, 843, 843, 851, 857, 859, 859, 861, 861, 861, 861, 869, 869,
7084
     869, 869},
7085
    {869, 869, 869, 877, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885,
7086
     885, 885, 885, 885, 889, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7087
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7088
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7089
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7090
     893, 893, 897, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901,
7091
     901, 903, 905, 905, 905, 905, 905, 907, 909, 909, 909, 909, 909, 909, 909,
7092
     911, 913, 915, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917,
7093
     917, 917, 917, 917, 917, 917, 917, 917, 919, 919, 919, 919, 919, 919, 919,
7094
     919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919,
7095
     919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 929, 939, 939, 939,
7096
     939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 949, 959, 959, 959,
7097
     959, 959, 959, 959, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7098
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7099
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7100
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 963, 965, 965, 965, 965,
7101
     965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7102
     965, 965},
7103
    {965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7104
     965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7105
     965, 965, 965, 965, 965, 965, 965, 965, 965, 967, 969, 971, 973, 973, 973,
7106
     973, 973, 975, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7107
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7108
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7109
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7110
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7111
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7112
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 979, 979, 979,
7113
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7114
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7115
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7116
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7117
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7118
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7119
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7120
     979, 979},
7121
    {979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7122
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7123
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7124
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7125
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7126
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7127
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7128
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7129
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7130
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7131
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7132
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7133
     979,  979,  993,  993,  993,  993,  1001, 1001, 1011, 1011, 1025, 1025,
7134
     1025, 1025, 1025, 1025, 1033, 1033, 1035, 1035, 1035, 1035, 1047, 1047,
7135
     1047, 1047, 1057, 1057, 1057, 1059, 1059, 1061, 1061, 1061, 1077, 1077,
7136
     1077, 1077, 1085, 1085, 1097, 1097, 1113, 1113, 1113, 1113, 1113, 1113,
7137
     1121, 1121, 1125, 1125, 1125, 1125, 1141, 1141, 1141, 1141, 1153, 1159,
7138
     1165, 1165, 1165, 1167, 1167, 1167, 1167, 1171, 1171, 1171, 1171, 1171,
7139
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7140
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7141
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7142
     1171, 1171, 1171, 1171, 1171},
7143
    {1171, 1171, 1171, 1171, 1171, 1171, 1171, 1173, 1173, 1173, 1173, 1173,
7144
     1173, 1173, 1173, 1173, 1173, 1177, 1177, 1177, 1179, 1179, 1185, 1189,
7145
     1191, 1199, 1199, 1201, 1201, 1201, 1201, 1203, 1203, 1203, 1203, 1203,
7146
     1211, 1211, 1211, 1211, 1213, 1213, 1213, 1213, 1215, 1215, 1217, 1217,
7147
     1217, 1221, 1221, 1221, 1223, 1223, 1229, 1233, 1235, 1243, 1243, 1245,
7148
     1245, 1245, 1245, 1247, 1247, 1247, 1247, 1247, 1255, 1255, 1255, 1255,
7149
     1257, 1257, 1257, 1257, 1259, 1259, 1261, 1261, 1261, 1261, 1261, 1261,
7150
     1261, 1261, 1261, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7151
     1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7152
     1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1265, 1267, 1267,
7153
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7154
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7155
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7156
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7157
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7158
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7159
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7160
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7161
     1267, 1269, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271,
7162
     1271, 1271, 1271, 1271, 1271, 1273, 1275, 1275, 1275, 1275, 1275, 1275,
7163
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7164
     1275, 1275, 1275, 1275, 1275},
7165
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7166
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7167
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7168
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7169
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7170
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7171
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7172
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7173
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7174
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7175
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
7176
    {1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7177
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7178
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7179
     1275, 1275, 1275, 1275, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7180
     1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7181
     1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7182
     1281, 1283, 1283, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7183
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7184
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7185
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7186
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7187
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7188
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7189
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7190
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7191
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7192
     1285, 1285, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
7193
     1287, 1287, 1287, 1287, 1287, 1287, 1287, 1289, 1289, 1289, 1291, 1291,
7194
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7195
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7196
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7197
     1291, 1291, 1291, 1291, 1291},
7198
    {1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7199
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7200
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7201
     1291, 1291, 1291, 1291, 1291, 1293, 1293, 1293, 1293, 1293, 1293, 1293,
7202
     1293, 1295, 1295, 1295, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7203
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7204
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7205
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7206
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7207
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7208
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7209
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7210
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7211
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7212
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7213
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7214
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1301, 1301, 1301, 1301,
7215
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7216
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7217
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7218
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7219
     1301, 1301, 1301, 1301, 1301},
7220
    {1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7221
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7222
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7223
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7224
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7225
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7226
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7227
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7228
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7229
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7230
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7231
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7232
     1307, 1307, 1307, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7233
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7234
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7235
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7236
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1313, 1315, 1315, 1315, 1315,
7237
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7238
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7239
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7240
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7241
     1315, 1315, 1315, 1315, 1315},
7242
    {1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7243
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7244
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7245
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7246
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7247
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1317,
7248
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7249
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7250
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7251
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7252
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7253
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7254
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7255
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7256
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7257
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7258
     1319, 1319, 1319, 1319, 1319, 1319, 1319, 1325, 1325, 1325, 1325, 1327,
7259
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7260
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7261
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7262
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7263
     1327, 1327, 1327, 1327, 1327},
7264
    {1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7265
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7266
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7267
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7268
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7269
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1331,
7270
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7271
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7272
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7273
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7274
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7275
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7276
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7277
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7278
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7279
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7280
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7281
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7282
     1333, 1333, 1339, 1339, 1339, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7283
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7284
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7285
     1341, 1341, 1341, 1341, 1341},
7286
    {1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7287
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7288
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7289
     1341, 1341, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7290
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7291
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7292
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7293
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7294
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7295
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7296
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7297
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7298
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7299
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7300
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7301
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7302
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7303
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7304
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7305
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7306
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7307
     1343, 1343, 1343, 1343, 1343},
7308
    {1343, 1343, 1343, 1343, 1343, 1343, 1345, 1345, 1347, 1347, 1349, 1349,
7309
     1351, 1351, 1353, 1353, 1353, 1353, 1355, 1355, 1355, 1355, 1355, 1355,
7310
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7311
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7312
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1357,
7313
     1357, 1359, 1359, 1361, 1363, 1363, 1363, 1365, 1365, 1365, 1365, 1365,
7314
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7315
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7316
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7317
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7318
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7319
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7320
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7321
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7322
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7323
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7324
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7325
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7326
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7327
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7328
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7329
     1365, 1365, 1365, 1365, 1365},
7330
    {1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7331
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7332
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7333
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7334
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1367, 1369, 1369, 1369, 1369,
7335
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7336
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7337
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1371, 1373, 1373, 1373, 1373,
7338
     1373, 1373, 1373, 1375, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7339
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7340
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7341
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7342
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7343
     1377, 1377, 1377, 1377, 1377, 1381, 1385, 1385, 1385, 1385, 1385, 1385,
7344
     1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385,
7345
     1385, 1385, 1385, 1385, 1385, 1387, 1389, 1389, 1389, 1389, 1389, 1389,
7346
     1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389,
7347
     1389, 1391, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7348
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7349
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7350
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7351
     1393, 1393, 1393, 1393, 1393},
7352
    {1393, 1401, 1409, 1411, 1413, 1415, 1417, 1419, 1421, 1429, 1437, 1439,
7353
     1441, 1443, 1445, 1447, 1449, 1453, 1457, 1457, 1457, 1457, 1457, 1457,
7354
     1457, 1461, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1473, 1481, 1483,
7355
     1485, 1487, 1489, 1491, 1493, 1501, 1509, 1511, 1513, 1515, 1517, 1519,
7356
     1521, 1527, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1539, 1545, 1545,
7357
     1545, 1545, 1545, 1545, 1545, 1549, 1553, 1553, 1553, 1553, 1553, 1553,
7358
     1553, 1557, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1567, 1573, 1573,
7359
     1573, 1573, 1573, 1573, 1573, 1573, 1579, 1579, 1579, 1579, 1579, 1579,
7360
     1579, 1587, 1595, 1597, 1599, 1601, 1603, 1605, 1607, 1615, 1623, 1625,
7361
     1627, 1629, 1631, 1633, 1635, 1637, 1637, 1637, 1637, 1639, 1639, 1639,
7362
     1639, 1639, 1639, 1639, 1639, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7363
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7364
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7365
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7366
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7367
     1641, 1641, 1641, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643,
7368
     1649, 1649, 1649, 1649, 1649, 1649, 1649, 1651, 1651, 1651, 1651, 1651,
7369
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7370
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7371
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7372
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1653, 1653, 1653, 1653, 1653,
7373
     1653, 1653, 1653, 1659, 1659},
7374
    {1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7375
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7376
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7377
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7378
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7379
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7380
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7381
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7382
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7383
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7384
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7385
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7386
     1659, 1661, 1661, 1663, 1663, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7387
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7388
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7389
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7390
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7391
     1665, 1665, 1665, 1665, 1665, 1667, 1667, 1669, 1669, 1671, 1671, 1671,
7392
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7393
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7394
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7395
     1671, 1671, 1671, 1671, 1671},
7396
    {1671, 1671, 1671, 1671, 1673, 1673, 1673, 1673, 1673, 1675, 1675, 1675,
7397
     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7398
     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7399
     1679, 1679, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7400
     1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7401
     1681, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1685, 1685, 1687, 1687,
7402
     1687, 1689, 1689, 1689, 1689, 1689, 1691, 1691, 1691, 1691, 1691, 1691,
7403
     1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691,
7404
     1691, 1691, 1693, 1693, 1693, 1695, 1697, 1697, 1697, 1697, 1697, 1697,
7405
     1697, 1697, 1697, 1697, 1697, 1697, 1697, 1699, 1701, 1701, 1701, 1703,
7406
     1705, 1705, 1705, 1707, 1709, 1711, 1713, 1713, 1713, 1713, 1713, 1715,
7407
     1717, 1717, 1717, 1719, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
7408
     1721, 1721, 1723, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725,
7409
     1725, 1725, 1725, 1725, 1725, 1725, 1725, 1727, 1727, 1727, 1727, 1727,
7410
     1727, 1729, 1731, 1731, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1735,
7411
     1737, 1739, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7412
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7413
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7414
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7415
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7416
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7417
     1741, 1741, 1741, 1741, 1741},
7418
    {1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7419
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7420
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7421
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7422
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7423
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1743,
7424
     1743, 1743, 1743, 1743, 1745, 1745, 1747, 1747, 1749, 1749, 1751, 1751,
7425
     1753, 1753, 1755, 1755, 1757, 1757, 1759, 1759, 1761, 1761, 1763, 1763,
7426
     1765, 1765, 1767, 1767, 1767, 1769, 1769, 1771, 1771, 1773, 1773, 1773,
7427
     1773, 1773, 1773, 1773, 1777, 1777, 1777, 1781, 1781, 1781, 1785, 1785,
7428
     1785, 1789, 1789, 1789, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7429
     1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7430
     1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7431
     1793, 1793, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1797,
7432
     1797, 1797, 1797, 1797, 1799, 1799, 1801, 1801, 1803, 1803, 1805, 1805,
7433
     1807, 1807, 1809, 1809, 1811, 1811, 1813, 1813, 1815, 1815, 1817, 1817,
7434
     1819, 1819, 1821, 1821, 1821, 1823, 1823, 1825, 1825, 1827, 1827, 1827,
7435
     1827, 1827, 1827, 1827, 1831, 1831, 1831, 1835, 1835, 1835, 1839, 1839,
7436
     1839, 1843, 1843, 1843, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7437
     1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7438
     1849, 1851, 1853, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855,
7439
     1855, 1855, 1857, 1857, 1857},
7440
    {1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7441
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7442
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7443
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7444
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7445
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7446
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7447
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7448
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7449
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7450
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7451
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7452
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1859, 1859,
7453
     1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1863, 1863,
7454
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7455
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7456
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7457
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7458
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7459
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7460
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7461
     1863, 1863, 1863, 1863, 1863},
7462
    {1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7463
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7464
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7465
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7466
     1863, 1863, 1865, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7467
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7468
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7469
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7470
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7471
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7472
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7473
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7474
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7475
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7476
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7477
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7478
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7479
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7480
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7481
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7482
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7483
     1867, 1867, 1867, 1867, 1867},
7484
    {1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7485
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7486
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7487
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7488
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7489
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7490
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7491
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7492
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7493
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7494
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7495
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7496
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7497
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7498
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7499
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7500
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7501
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7502
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7503
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7504
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7505
     1871, 1871, 1871, 1871, 1871},
7506
    {1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7507
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7508
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7509
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7510
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7511
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
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, 1877, 1877, 1877, 1877, 1877, 1877,
7522
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7523
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7524
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7525
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7526
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7527
     1877, 1877, 1877, 1877, 1877},
7528
    {1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7529
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7530
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7531
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7532
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7533
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7534
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7535
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7536
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7537
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7538
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7539
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7540
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7541
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7542
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7543
     1877, 1877, 1877, 1877, 1877, 1879, 1881, 1881, 1881, 1881, 1881, 1881,
7544
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7545
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7546
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7547
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7548
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7549
     1881, 1881, 1881, 1881, 1881},
7550
    {1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7551
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7552
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7553
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7554
     1881, 1881, 1881, 1881, 1881, 1881, 1883, 1883, 1883, 1883, 1883, 1883,
7555
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7556
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7557
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7558
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7559
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7560
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7561
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7562
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7563
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7564
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7565
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7566
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7567
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7568
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7569
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7570
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7571
     1883, 1883, 1883, 1883, 1883}};
7572
const char32_t composition_data[1883] = {
7573
    0,     824,   8814,  824,   8800,  824,   8815,  768,   192,   769,   193,
7574
    770,   194,   771,   195,   772,   256,   774,   258,   775,   550,   776,
7575
    196,   777,   7842,  778,   197,   780,   461,   783,   512,   785,   514,
7576
    803,   7840,  805,   7680,  808,   260,   775,   7682,  803,   7684,  817,
7577
    7686,  769,   262,   770,   264,   775,   266,   780,   268,   807,   199,
7578
    775,   7690,  780,   270,   803,   7692,  807,   7696,  813,   7698,  817,
7579
    7694,  768,   200,   769,   201,   770,   202,   771,   7868,  772,   274,
7580
    774,   276,   775,   278,   776,   203,   777,   7866,  780,   282,   783,
7581
    516,   785,   518,   803,   7864,  807,   552,   808,   280,   813,   7704,
7582
    816,   7706,  775,   7710,  769,   500,   770,   284,   772,   7712,  774,
7583
    286,   775,   288,   780,   486,   807,   290,   770,   292,   775,   7714,
7584
    776,   7718,  780,   542,   803,   7716,  807,   7720,  814,   7722,  768,
7585
    204,   769,   205,   770,   206,   771,   296,   772,   298,   774,   300,
7586
    775,   304,   776,   207,   777,   7880,  780,   463,   783,   520,   785,
7587
    522,   803,   7882,  808,   302,   816,   7724,  770,   308,   769,   7728,
7588
    780,   488,   803,   7730,  807,   310,   817,   7732,  769,   313,   780,
7589
    317,   803,   7734,  807,   315,   813,   7740,  817,   7738,  769,   7742,
7590
    775,   7744,  803,   7746,  768,   504,   769,   323,   771,   209,   775,
7591
    7748,  780,   327,   803,   7750,  807,   325,   813,   7754,  817,   7752,
7592
    768,   210,   769,   211,   770,   212,   771,   213,   772,   332,   774,
7593
    334,   775,   558,   776,   214,   777,   7886,  779,   336,   780,   465,
7594
    783,   524,   785,   526,   795,   416,   803,   7884,  808,   490,   769,
7595
    7764,  775,   7766,  769,   340,   775,   7768,  780,   344,   783,   528,
7596
    785,   530,   803,   7770,  807,   342,   817,   7774,  769,   346,   770,
7597
    348,   775,   7776,  780,   352,   803,   7778,  806,   536,   807,   350,
7598
    775,   7786,  780,   356,   803,   7788,  806,   538,   807,   354,   813,
7599
    7792,  817,   7790,  768,   217,   769,   218,   770,   219,   771,   360,
7600
    772,   362,   774,   364,   776,   220,   777,   7910,  778,   366,   779,
7601
    368,   780,   467,   783,   532,   785,   534,   795,   431,   803,   7908,
7602
    804,   7794,  808,   370,   813,   7798,  816,   7796,  771,   7804,  803,
7603
    7806,  768,   7808,  769,   7810,  770,   372,   775,   7814,  776,   7812,
7604
    803,   7816,  775,   7818,  776,   7820,  768,   7922,  769,   221,   770,
7605
    374,   771,   7928,  772,   562,   775,   7822,  776,   376,   777,   7926,
7606
    803,   7924,  769,   377,   770,   7824,  775,   379,   780,   381,   803,
7607
    7826,  817,   7828,  768,   224,   769,   225,   770,   226,   771,   227,
7608
    772,   257,   774,   259,   775,   551,   776,   228,   777,   7843,  778,
7609
    229,   780,   462,   783,   513,   785,   515,   803,   7841,  805,   7681,
7610
    808,   261,   775,   7683,  803,   7685,  817,   7687,  769,   263,   770,
7611
    265,   775,   267,   780,   269,   807,   231,   775,   7691,  780,   271,
7612
    803,   7693,  807,   7697,  813,   7699,  817,   7695,  768,   232,   769,
7613
    233,   770,   234,   771,   7869,  772,   275,   774,   277,   775,   279,
7614
    776,   235,   777,   7867,  780,   283,   783,   517,   785,   519,   803,
7615
    7865,  807,   553,   808,   281,   813,   7705,  816,   7707,  775,   7711,
7616
    769,   501,   770,   285,   772,   7713,  774,   287,   775,   289,   780,
7617
    487,   807,   291,   770,   293,   775,   7715,  776,   7719,  780,   543,
7618
    803,   7717,  807,   7721,  814,   7723,  817,   7830,  768,   236,   769,
7619
    237,   770,   238,   771,   297,   772,   299,   774,   301,   776,   239,
7620
    777,   7881,  780,   464,   783,   521,   785,   523,   803,   7883,  808,
7621
    303,   816,   7725,  770,   309,   780,   496,   769,   7729,  780,   489,
7622
    803,   7731,  807,   311,   817,   7733,  769,   314,   780,   318,   803,
7623
    7735,  807,   316,   813,   7741,  817,   7739,  769,   7743,  775,   7745,
7624
    803,   7747,  768,   505,   769,   324,   771,   241,   775,   7749,  780,
7625
    328,   803,   7751,  807,   326,   813,   7755,  817,   7753,  768,   242,
7626
    769,   243,   770,   244,   771,   245,   772,   333,   774,   335,   775,
7627
    559,   776,   246,   777,   7887,  779,   337,   780,   466,   783,   525,
7628
    785,   527,   795,   417,   803,   7885,  808,   491,   769,   7765,  775,
7629
    7767,  769,   341,   775,   7769,  780,   345,   783,   529,   785,   531,
7630
    803,   7771,  807,   343,   817,   7775,  769,   347,   770,   349,   775,
7631
    7777,  780,   353,   803,   7779,  806,   537,   807,   351,   775,   7787,
7632
    776,   7831,  780,   357,   803,   7789,  806,   539,   807,   355,   813,
7633
    7793,  817,   7791,  768,   249,   769,   250,   770,   251,   771,   361,
7634
    772,   363,   774,   365,   776,   252,   777,   7911,  778,   367,   779,
7635
    369,   780,   468,   783,   533,   785,   535,   795,   432,   803,   7909,
7636
    804,   7795,  808,   371,   813,   7799,  816,   7797,  771,   7805,  803,
7637
    7807,  768,   7809,  769,   7811,  770,   373,   775,   7815,  776,   7813,
7638
    778,   7832,  803,   7817,  775,   7819,  776,   7821,  768,   7923,  769,
7639
    253,   770,   375,   771,   7929,  772,   563,   775,   7823,  776,   255,
7640
    777,   7927,  778,   7833,  803,   7925,  769,   378,   770,   7825,  775,
7641
    380,   780,   382,   803,   7827,  817,   7829,  768,   8173,  769,   901,
7642
    834,   8129,  768,   7846,  769,   7844,  771,   7850,  777,   7848,  772,
7643
    478,   769,   506,   769,   508,   772,   482,   769,   7688,  768,   7872,
7644
    769,   7870,  771,   7876,  777,   7874,  769,   7726,  768,   7890,  769,
7645
    7888,  771,   7894,  777,   7892,  769,   7756,  772,   556,   776,   7758,
7646
    772,   554,   769,   510,   768,   475,   769,   471,   772,   469,   780,
7647
    473,   768,   7847,  769,   7845,  771,   7851,  777,   7849,  772,   479,
7648
    769,   507,   769,   509,   772,   483,   769,   7689,  768,   7873,  769,
7649
    7871,  771,   7877,  777,   7875,  769,   7727,  768,   7891,  769,   7889,
7650
    771,   7895,  777,   7893,  769,   7757,  772,   557,   776,   7759,  772,
7651
    555,   769,   511,   768,   476,   769,   472,   772,   470,   780,   474,
7652
    768,   7856,  769,   7854,  771,   7860,  777,   7858,  768,   7857,  769,
7653
    7855,  771,   7861,  777,   7859,  768,   7700,  769,   7702,  768,   7701,
7654
    769,   7703,  768,   7760,  769,   7762,  768,   7761,  769,   7763,  775,
7655
    7780,  775,   7781,  775,   7782,  775,   7783,  769,   7800,  769,   7801,
7656
    776,   7802,  776,   7803,  775,   7835,  768,   7900,  769,   7898,  771,
7657
    7904,  777,   7902,  803,   7906,  768,   7901,  769,   7899,  771,   7905,
7658
    777,   7903,  803,   7907,  768,   7914,  769,   7912,  771,   7918,  777,
7659
    7916,  803,   7920,  768,   7915,  769,   7913,  771,   7919,  777,   7917,
7660
    803,   7921,  780,   494,   772,   492,   772,   493,   772,   480,   772,
7661
    481,   774,   7708,  774,   7709,  772,   560,   772,   561,   780,   495,
7662
    768,   8122,  769,   902,   772,   8121,  774,   8120,  787,   7944,  788,
7663
    7945,  837,   8124,  768,   8136,  769,   904,   787,   7960,  788,   7961,
7664
    768,   8138,  769,   905,   787,   7976,  788,   7977,  837,   8140,  768,
7665
    8154,  769,   906,   772,   8153,  774,   8152,  776,   938,   787,   7992,
7666
    788,   7993,  768,   8184,  769,   908,   787,   8008,  788,   8009,  788,
7667
    8172,  768,   8170,  769,   910,   772,   8169,  774,   8168,  776,   939,
7668
    788,   8025,  768,   8186,  769,   911,   787,   8040,  788,   8041,  837,
7669
    8188,  837,   8116,  837,   8132,  768,   8048,  769,   940,   772,   8113,
7670
    774,   8112,  787,   7936,  788,   7937,  834,   8118,  837,   8115,  768,
7671
    8050,  769,   941,   787,   7952,  788,   7953,  768,   8052,  769,   942,
7672
    787,   7968,  788,   7969,  834,   8134,  837,   8131,  768,   8054,  769,
7673
    943,   772,   8145,  774,   8144,  776,   970,   787,   7984,  788,   7985,
7674
    834,   8150,  768,   8056,  769,   972,   787,   8000,  788,   8001,  787,
7675
    8164,  788,   8165,  768,   8058,  769,   973,   772,   8161,  774,   8160,
7676
    776,   971,   787,   8016,  788,   8017,  834,   8166,  768,   8060,  769,
7677
    974,   787,   8032,  788,   8033,  834,   8182,  837,   8179,  768,   8146,
7678
    769,   912,   834,   8151,  768,   8162,  769,   944,   834,   8167,  837,
7679
    8180,  769,   979,   776,   980,   776,   1031,  774,   1232,  776,   1234,
7680
    769,   1027,  768,   1024,  774,   1238,  776,   1025,  774,   1217,  776,
7681
    1244,  776,   1246,  768,   1037,  772,   1250,  774,   1049,  776,   1252,
7682
    769,   1036,  776,   1254,  772,   1262,  774,   1038,  776,   1264,  779,
7683
    1266,  776,   1268,  776,   1272,  776,   1260,  774,   1233,  776,   1235,
7684
    769,   1107,  768,   1104,  774,   1239,  776,   1105,  774,   1218,  776,
7685
    1245,  776,   1247,  768,   1117,  772,   1251,  774,   1081,  776,   1253,
7686
    769,   1116,  776,   1255,  772,   1263,  774,   1118,  776,   1265,  779,
7687
    1267,  776,   1269,  776,   1273,  776,   1261,  776,   1111,  783,   1142,
7688
    783,   1143,  776,   1242,  776,   1243,  776,   1258,  776,   1259,  1619,
7689
    1570,  1620,  1571,  1621,  1573,  1620,  1572,  1620,  1574,  1620,  1730,
7690
    1620,  1747,  1620,  1728,  2364,  2345,  2364,  2353,  2364,  2356,  2494,
7691
    2507,  2519,  2508,  2878,  2891,  2902,  2888,  2903,  2892,  3031,  2964,
7692
    3006,  3018,  3031,  3020,  3006,  3019,  3158,  3144,  3285,  3264,  3266,
7693
    3274,  3285,  3271,  3286,  3272,  3285,  3275,  3390,  3402,  3415,  3404,
7694
    3390,  3403,  3530,  3546,  3535,  3548,  3551,  3550,  3530,  3549,  4142,
7695
    4134,  6965,  6918,  6965,  6920,  6965,  6922,  6965,  6924,  6965,  6926,
7696
    6965,  6930,  6965,  6971,  6965,  6973,  6965,  6976,  6965,  6977,  6965,
7697
    6979,  772,   7736,  772,   7737,  772,   7772,  772,   7773,  775,   7784,
7698
    775,   7785,  770,   7852,  774,   7862,  770,   7853,  774,   7863,  770,
7699
    7878,  770,   7879,  770,   7896,  770,   7897,  768,   7938,  769,   7940,
7700
    834,   7942,  837,   8064,  768,   7939,  769,   7941,  834,   7943,  837,
7701
    8065,  837,   8066,  837,   8067,  837,   8068,  837,   8069,  837,   8070,
7702
    837,   8071,  768,   7946,  769,   7948,  834,   7950,  837,   8072,  768,
7703
    7947,  769,   7949,  834,   7951,  837,   8073,  837,   8074,  837,   8075,
7704
    837,   8076,  837,   8077,  837,   8078,  837,   8079,  768,   7954,  769,
7705
    7956,  768,   7955,  769,   7957,  768,   7962,  769,   7964,  768,   7963,
7706
    769,   7965,  768,   7970,  769,   7972,  834,   7974,  837,   8080,  768,
7707
    7971,  769,   7973,  834,   7975,  837,   8081,  837,   8082,  837,   8083,
7708
    837,   8084,  837,   8085,  837,   8086,  837,   8087,  768,   7978,  769,
7709
    7980,  834,   7982,  837,   8088,  768,   7979,  769,   7981,  834,   7983,
7710
    837,   8089,  837,   8090,  837,   8091,  837,   8092,  837,   8093,  837,
7711
    8094,  837,   8095,  768,   7986,  769,   7988,  834,   7990,  768,   7987,
7712
    769,   7989,  834,   7991,  768,   7994,  769,   7996,  834,   7998,  768,
7713
    7995,  769,   7997,  834,   7999,  768,   8002,  769,   8004,  768,   8003,
7714
    769,   8005,  768,   8010,  769,   8012,  768,   8011,  769,   8013,  768,
7715
    8018,  769,   8020,  834,   8022,  768,   8019,  769,   8021,  834,   8023,
7716
    768,   8027,  769,   8029,  834,   8031,  768,   8034,  769,   8036,  834,
7717
    8038,  837,   8096,  768,   8035,  769,   8037,  834,   8039,  837,   8097,
7718
    837,   8098,  837,   8099,  837,   8100,  837,   8101,  837,   8102,  837,
7719
    8103,  768,   8042,  769,   8044,  834,   8046,  837,   8104,  768,   8043,
7720
    769,   8045,  834,   8047,  837,   8105,  837,   8106,  837,   8107,  837,
7721
    8108,  837,   8109,  837,   8110,  837,   8111,  837,   8114,  837,   8130,
7722
    837,   8178,  837,   8119,  768,   8141,  769,   8142,  834,   8143,  837,
7723
    8135,  837,   8183,  768,   8157,  769,   8158,  834,   8159,  824,   8602,
7724
    824,   8603,  824,   8622,  824,   8653,  824,   8655,  824,   8654,  824,
7725
    8708,  824,   8713,  824,   8716,  824,   8740,  824,   8742,  824,   8769,
7726
    824,   8772,  824,   8775,  824,   8777,  824,   8813,  824,   8802,  824,
7727
    8816,  824,   8817,  824,   8820,  824,   8821,  824,   8824,  824,   8825,
7728
    824,   8832,  824,   8833,  824,   8928,  824,   8929,  824,   8836,  824,
7729
    8837,  824,   8840,  824,   8841,  824,   8930,  824,   8931,  824,   8876,
7730
    824,   8877,  824,   8878,  824,   8879,  824,   8938,  824,   8939,  824,
7731
    8940,  824,   8941,  12441, 12436, 12441, 12364, 12441, 12366, 12441, 12368,
7732
    12441, 12370, 12441, 12372, 12441, 12374, 12441, 12376, 12441, 12378, 12441,
7733
    12380, 12441, 12382, 12441, 12384, 12441, 12386, 12441, 12389, 12441, 12391,
7734
    12441, 12393, 12441, 12400, 12442, 12401, 12441, 12403, 12442, 12404, 12441,
7735
    12406, 12442, 12407, 12441, 12409, 12442, 12410, 12441, 12412, 12442, 12413,
7736
    12441, 12446, 12441, 12532, 12441, 12460, 12441, 12462, 12441, 12464, 12441,
7737
    12466, 12441, 12468, 12441, 12470, 12441, 12472, 12441, 12474, 12441, 12476,
7738
    12441, 12478, 12441, 12480, 12441, 12482, 12441, 12485, 12441, 12487, 12441,
7739
    12489, 12441, 12496, 12442, 12497, 12441, 12499, 12442, 12500, 12441, 12502,
7740
    12442, 12503, 12441, 12505, 12442, 12506, 12441, 12508, 12442, 12509, 12441,
7741
    12535, 12441, 12536, 12441, 12537, 12441, 12538, 12441, 12542, 69818, 69786,
7742
    69818, 69788, 69818, 69803, 69927, 69934, 69927, 69935, 70462, 70475, 70487,
7743
    70476, 70832, 70844, 70842, 70843, 70845, 70846, 71087, 71098, 71087, 71099,
7744
    71984, 71992};
7745
7746
}  // namespace ada::idna
7747
#endif  // ADA_IDNA_NORMALIZATION_TABLES_H
7748
/* end file src/normalization_tables.cpp */
7749
7750
namespace ada::idna {
7751
7752
// See
7753
// https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/impl_norm.h#L467
7754
constexpr char32_t hangul_sbase = 0xAC00;
7755
constexpr char32_t hangul_tbase = 0x11A7;
7756
constexpr char32_t hangul_vbase = 0x1161;
7757
constexpr char32_t hangul_lbase = 0x1100;
7758
constexpr char32_t hangul_lcount = 19;
7759
constexpr char32_t hangul_vcount = 21;
7760
constexpr char32_t hangul_tcount = 28;
7761
constexpr char32_t hangul_ncount = hangul_vcount * hangul_tcount;
7762
constexpr char32_t hangul_scount =
7763
    hangul_lcount * hangul_vcount * hangul_tcount;
7764
7765
std::pair<bool, size_t> compute_decomposition_length(
7766
16.2k
    const std::u32string_view input) noexcept {
7767
16.2k
  bool decomposition_needed{false};
7768
16.2k
  size_t additional_elements{0};
7769
322k
  for (char32_t current_character : input) {
7770
322k
    size_t decomposition_length{0};
7771
7772
322k
    if (current_character >= hangul_sbase &&
7773
322k
        current_character < hangul_sbase + hangul_scount) {
7774
7.27k
      decomposition_length = 2;
7775
7.27k
      if ((current_character - hangul_sbase) % hangul_tcount) {
7776
3.99k
        decomposition_length = 3;
7777
3.99k
      }
7778
314k
    } else if (current_character < 0x110000) {
7779
314k
      const uint8_t di = decomposition_index[current_character >> 8];
7780
314k
      const uint16_t* const decomposition =
7781
314k
          decomposition_block[di] + (current_character % 256);
7782
314k
      decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
7783
314k
      if ((decomposition_length > 0) && (decomposition[0] & 1)) {
7784
0
        decomposition_length = 0;
7785
0
      }
7786
314k
    }
7787
322k
    if (decomposition_length != 0) {
7788
12.6k
      decomposition_needed = true;
7789
12.6k
      additional_elements += decomposition_length - 1;
7790
12.6k
    }
7791
322k
  }
7792
16.2k
  return {decomposition_needed, additional_elements};
7793
16.2k
}
7794
7795
3.70k
void decompose(std::u32string& input, size_t additional_elements) {
7796
3.70k
  input.resize(input.size() + additional_elements);
7797
3.70k
  for (size_t descending_idx = input.size(),
7798
3.70k
              input_count = descending_idx - additional_elements;
7799
81.3k
       input_count--;) {
7800
77.6k
    if (input[input_count] >= hangul_sbase &&
7801
77.6k
        input[input_count] < hangul_sbase + hangul_scount) {
7802
      // Hangul decomposition.
7803
7.27k
      char32_t s_index = input[input_count] - hangul_sbase;
7804
7.27k
      if (s_index % hangul_tcount != 0) {
7805
3.99k
        input[--descending_idx] = hangul_tbase + s_index % hangul_tcount;
7806
3.99k
      }
7807
7.27k
      input[--descending_idx] =
7808
7.27k
          hangul_vbase + (s_index % hangul_ncount) / hangul_tcount;
7809
7.27k
      input[--descending_idx] = hangul_lbase + s_index / hangul_ncount;
7810
70.3k
    } else if (input[input_count] < 0x110000) {
7811
      // Check decomposition_data.
7812
70.3k
      const uint16_t* decomposition =
7813
70.3k
          decomposition_block[decomposition_index[input[input_count] >> 8]] +
7814
70.3k
          (input[input_count] % 256);
7815
70.3k
      uint16_t decomposition_length =
7816
70.3k
          (decomposition[1] >> 2) - (decomposition[0] >> 2);
7817
70.3k
      if (decomposition_length > 0 && (decomposition[0] & 1)) {
7818
0
        decomposition_length = 0;
7819
0
      }
7820
70.3k
      if (decomposition_length > 0) {
7821
        // Non-recursive decomposition.
7822
17.8k
        while (decomposition_length-- > 0) {
7823
12.4k
          input[--descending_idx] = decomposition_data[(decomposition[0] >> 2) +
7824
12.4k
                                                       decomposition_length];
7825
12.4k
        }
7826
64.9k
      } else {
7827
        // No decomposition.
7828
64.9k
        input[--descending_idx] = input[input_count];
7829
64.9k
      }
7830
70.3k
    } else {
7831
      // Non-Unicode character.
7832
0
      input[--descending_idx] = input[input_count];
7833
0
    }
7834
77.6k
  }
7835
3.70k
}
7836
7837
643k
uint8_t get_ccc(char32_t c) noexcept {
7838
643k
  return c < 0x110000 ? canonical_combining_class_block
7839
643k
                            [canonical_combining_class_index[c >> 8]][c % 256]
7840
643k
                      : 0;
7841
643k
}
7842
7843
16.2k
void sort_marks(std::u32string& input) {
7844
340k
  for (size_t idx = 1; idx < input.size(); idx++) {
7845
324k
    uint8_t ccc = get_ccc(input[idx]);
7846
324k
    if (ccc == 0) {
7847
312k
      continue;
7848
312k
    }  // Skip non-combining characters.
7849
11.6k
    auto current_character = input[idx];
7850
11.6k
    size_t back_idx = idx;
7851
13.2k
    while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) {
7852
1.52k
      input[back_idx] = input[back_idx - 1];
7853
1.52k
      back_idx--;
7854
1.52k
    }
7855
11.6k
    input[back_idx] = current_character;
7856
11.6k
  }
7857
16.2k
}
7858
7859
16.2k
void decompose_nfc(std::u32string& input) {
7860
  /**
7861
   * Decompose the domain_name string to Unicode Normalization Form C.
7862
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepDecompose
7863
   */
7864
16.2k
  auto [decomposition_needed, additional_elements] =
7865
16.2k
      compute_decomposition_length(input);
7866
16.2k
  if (decomposition_needed) {
7867
3.70k
    decompose(input, additional_elements);
7868
3.70k
  }
7869
16.2k
  sort_marks(input);
7870
16.2k
}
7871
7872
16.2k
void compose(std::u32string& input) {
7873
  /**
7874
   * Compose the domain_name string to Unicode Normalization Form C.
7875
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepCompose
7876
   */
7877
16.2k
  size_t input_count{0};
7878
16.2k
  size_t composition_count{0};
7879
333k
  for (; input_count < input.size(); input_count++, composition_count++) {
7880
317k
    input[composition_count] = input[input_count];
7881
317k
    if (input[input_count] >= hangul_lbase &&
7882
317k
        input[input_count] < hangul_lbase + hangul_lcount) {
7883
8.63k
      if (input_count + 1 < input.size() &&
7884
8.63k
          input[input_count + 1] >= hangul_vbase &&
7885
8.63k
          input[input_count + 1] < hangul_vbase + hangul_vcount) {
7886
7.27k
        input[composition_count] =
7887
7.27k
            hangul_sbase +
7888
7.27k
            ((input[input_count] - hangul_lbase) * hangul_vcount +
7889
7.27k
             input[input_count + 1] - hangul_vbase) *
7890
7.27k
                hangul_tcount;
7891
7.27k
        input_count++;
7892
7.27k
        if (input_count + 1 < input.size() &&
7893
7.27k
            input[input_count + 1] > hangul_tbase &&
7894
7.27k
            input[input_count + 1] < hangul_tbase + hangul_tcount) {
7895
3.99k
          input[composition_count] += input[++input_count] - hangul_tbase;
7896
3.99k
        }
7897
7.27k
      }
7898
308k
    } else if (input[input_count] >= hangul_sbase &&
7899
308k
               input[input_count] < hangul_sbase + hangul_scount) {
7900
0
      if ((input[input_count] - hangul_sbase) % hangul_tcount &&
7901
0
          input_count + 1 < input.size() &&
7902
0
          input[input_count + 1] > hangul_tbase &&
7903
0
          input[input_count + 1] < hangul_tbase + hangul_tcount) {
7904
0
        input[composition_count] += input[++input_count] - hangul_tbase;
7905
0
      }
7906
308k
    } else if (input[input_count] < 0x110000) {
7907
308k
      const uint16_t* composition =
7908
308k
          &composition_block[composition_index[input[input_count] >> 8]]
7909
308k
                            [input[input_count] % 256];
7910
308k
      size_t initial_composition_count = composition_count;
7911
320k
      for (int32_t previous_ccc = -1; input_count + 1 < input.size();
7912
308k
           input_count++) {
7913
306k
        uint8_t ccc = get_ccc(input[input_count + 1]);
7914
7915
306k
        if (composition[1] != composition[0] && previous_ccc < ccc) {
7916
          // Try finding a composition.
7917
66.3k
          uint16_t left = composition[0];
7918
66.3k
          uint16_t right = composition[1];
7919
172k
          while (left + 2 < right) {
7920
            // mean without overflow
7921
105k
            uint16_t middle = left + (((right - left) >> 1) & ~1);
7922
105k
            if (composition_data[middle] <= input[input_count + 1]) {
7923
13.5k
              left = middle;
7924
13.5k
            }
7925
105k
            if (composition_data[middle] >= input[input_count + 1]) {
7926
96.5k
              right = middle;
7927
96.5k
            }
7928
105k
          }
7929
66.3k
          if (composition_data[left] == input[input_count + 1]) {
7930
7.07k
            input[initial_composition_count] = composition_data[left + 1];
7931
7.07k
            composition =
7932
7.07k
                &composition_block
7933
7.07k
                    [composition_index[composition_data[left + 1] >> 8]]
7934
7.07k
                    [composition_data[left + 1] % 256];
7935
7.07k
            continue;
7936
7.07k
          }
7937
66.3k
        }
7938
7939
298k
        if (ccc == 0) {
7940
294k
          break;
7941
294k
        }  // Not a combining character.
7942
4.63k
        previous_ccc = ccc;
7943
4.63k
        input[++composition_count] = input[input_count + 1];
7944
4.63k
      }
7945
308k
    }
7946
317k
  }
7947
7948
16.2k
  if (composition_count < input_count) {
7949
3.73k
    input.resize(composition_count);
7950
3.73k
  }
7951
16.2k
}
7952
7953
16.2k
void normalize(std::u32string& input) {
7954
  /**
7955
   * Normalize the domain_name string to Unicode Normalization Form C.
7956
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepNormalize
7957
   */
7958
16.2k
  decompose_nfc(input);
7959
16.2k
  compose(input);
7960
16.2k
}
7961
7962
}  // namespace ada::idna
7963
/* end file src/normalization.cpp */
7964
/* begin file src/punycode.cpp */
7965
7966
#include <cstdint>
7967
7968
namespace ada::idna {
7969
7970
constexpr int32_t base = 36;
7971
constexpr int32_t tmin = 1;
7972
constexpr int32_t tmax = 26;
7973
constexpr int32_t skew = 38;
7974
constexpr int32_t damp = 700;
7975
constexpr int32_t initial_bias = 72;
7976
constexpr uint32_t initial_n = 128;
7977
7978
98.0k
static constexpr int32_t char_to_digit_value(char value) {
7979
98.0k
  if (value >= 'a' && value <= 'z') return value - 'a';
7980
27.2k
  if (value >= '0' && value <= '9') return value - '0' + 26;
7981
608
  return -1;
7982
27.2k
}
7983
7984
378k
static constexpr char digit_to_char(int32_t digit) {
7985
378k
  return digit < 26 ? char(digit + 97) : char(digit + 22);
7986
378k
}
7987
7988
187k
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
7989
187k
  if (firsttime) {
7990
35.1k
    d = d / damp;
7991
152k
  } else {
7992
152k
    d = d / 2;
7993
152k
  }
7994
187k
  d += d / n;
7995
187k
  int32_t k = 0;
7996
274k
  while (d > ((base - tmin) * tmax) / 2) {
7997
86.2k
    d /= base - tmin;
7998
86.2k
    k += base;
7999
86.2k
  }
8000
187k
  return k + (((base - tmin + 1) * d) / (d + skew));
8001
187k
}
8002
8003
11.5k
bool punycode_to_utf32(std::string_view input, std::u32string &out) {
8004
11.5k
  int32_t written_out{0};
8005
11.5k
  out.reserve(out.size() + input.size());
8006
11.5k
  uint32_t n = initial_n;
8007
11.5k
  int32_t i = 0;
8008
11.5k
  int32_t bias = initial_bias;
8009
  // grab ascii content
8010
11.5k
  size_t end_of_ascii = input.find_last_of('-');
8011
11.5k
  if (end_of_ascii != std::string_view::npos) {
8012
15.0k
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8013
15.0k
      if (c >= 0x80) {
8014
0
        return false;
8015
0
      }
8016
15.0k
      out.push_back(c);
8017
15.0k
      written_out++;
8018
15.0k
    }
8019
3.54k
    input.remove_prefix(end_of_ascii + 1);
8020
3.54k
  }
8021
52.1k
  while (!input.empty()) {
8022
40.8k
    int32_t oldi = i;
8023
40.8k
    int32_t w = 1;
8024
89.4k
    for (int32_t k = base;; k += base) {
8025
89.4k
      if (input.empty()) {
8026
111
        return false;
8027
111
      }
8028
89.3k
      uint8_t code_point = input.front();
8029
89.3k
      input.remove_prefix(1);
8030
89.3k
      int32_t digit = char_to_digit_value(code_point);
8031
89.3k
      if (digit < 0) {
8032
103
        return false;
8033
103
      }
8034
89.2k
      if (digit > (0x7fffffff - i) / w) {
8035
20
        return false;
8036
20
      }
8037
89.2k
      i = i + digit * w;
8038
89.2k
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8039
89.2k
      if (digit < t) {
8040
40.6k
        break;
8041
40.6k
      }
8042
48.5k
      if (w > 0x7fffffff / (base - t)) {
8043
0
        return false;
8044
0
      }
8045
48.5k
      w = w * (base - t);
8046
48.5k
    }
8047
40.6k
    bias = adapt(i - oldi, written_out + 1, oldi == 0);
8048
40.6k
    if (i / (written_out + 1) > int32_t(0x7fffffff - n)) {
8049
46
      return false;
8050
46
    }
8051
40.6k
    n = n + i / (written_out + 1);
8052
40.6k
    i = i % (written_out + 1);
8053
40.6k
    if (n < 0x80) {
8054
0
      return false;
8055
0
    }
8056
40.6k
    out.insert(out.begin() + i, n);
8057
40.6k
    written_out++;
8058
40.6k
    ++i;
8059
40.6k
  }
8060
8061
11.2k
  return true;
8062
11.5k
}
8063
8064
2.08k
bool verify_punycode(std::string_view input) {
8065
2.08k
  size_t written_out{0};
8066
2.08k
  uint32_t n = initial_n;
8067
2.08k
  int32_t i = 0;
8068
2.08k
  int32_t bias = initial_bias;
8069
  // grab ascii content
8070
2.08k
  size_t end_of_ascii = input.find_last_of('-');
8071
2.08k
  if (end_of_ascii != std::string_view::npos) {
8072
2.22k
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8073
2.22k
      if (c >= 0x80) {
8074
0
        return false;
8075
0
      }
8076
2.22k
      written_out++;
8077
2.22k
    }
8078
516
    input.remove_prefix(end_of_ascii + 1);
8079
516
  }
8080
5.28k
  while (!input.empty()) {
8081
3.92k
    int32_t oldi = i;
8082
3.92k
    int32_t w = 1;
8083
8.84k
    for (int32_t k = base;; k += base) {
8084
8.84k
      if (input.empty()) {
8085
121
        return false;
8086
121
      }
8087
8.72k
      uint8_t code_point = input.front();
8088
8.72k
      input.remove_prefix(1);
8089
8.72k
      int32_t digit = char_to_digit_value(code_point);
8090
8.72k
      if (digit < 0) {
8091
505
        return false;
8092
505
      }
8093
8.22k
      if (digit > (0x7fffffff - i) / w) {
8094
40
        return false;
8095
40
      }
8096
8.18k
      i = i + digit * w;
8097
8.18k
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8098
8.18k
      if (digit < t) {
8099
3.26k
        break;
8100
3.26k
      }
8101
4.92k
      if (w > 0x7fffffff / (base - t)) {
8102
0
        return false;
8103
0
      }
8104
4.92k
      w = w * (base - t);
8105
4.92k
    }
8106
3.26k
    bias = adapt(i - oldi, int32_t(written_out + 1), oldi == 0);
8107
3.26k
    if (i / (written_out + 1) > 0x7fffffff - n) {
8108
62
      return false;
8109
62
    }
8110
3.19k
    n = n + i / int32_t(written_out + 1);
8111
3.19k
    i = i % int32_t(written_out + 1);
8112
3.19k
    if (n < 0x80) {
8113
0
      return false;
8114
0
    }
8115
3.19k
    written_out++;
8116
3.19k
    ++i;
8117
3.19k
  }
8118
8119
1.36k
  return true;
8120
2.08k
}
8121
8122
26.1k
bool utf32_to_punycode(std::u32string_view input, std::string &out) {
8123
26.1k
  out.reserve(input.size() + out.size());
8124
26.1k
  uint32_t n = initial_n;
8125
26.1k
  int32_t d = 0;
8126
26.1k
  int32_t bias = initial_bias;
8127
26.1k
  size_t h = 0;
8128
  // first push the ascii content
8129
168k
  for (uint32_t c : input) {
8130
168k
    if (c < 0x80) {
8131
24.6k
      ++h;
8132
24.6k
      out.push_back(char(c));
8133
24.6k
    }
8134
168k
    if (c > 0x10ffff || (c >= 0xd880 && c < 0xe000)) {
8135
0
      return false;
8136
0
    }
8137
168k
  }
8138
26.1k
  size_t b = h;
8139
26.1k
  if (b > 0) {
8140
5.67k
    out.push_back('-');
8141
5.67k
  }
8142
125k
  while (h < input.size()) {
8143
98.9k
    uint32_t m = 0x10FFFF;
8144
1.72M
    for (auto code_point : input) {
8145
1.72M
      if (code_point >= n && code_point < m) m = code_point;
8146
1.72M
    }
8147
8148
98.9k
    if ((m - n) > (0x7fffffff - d) / (h + 1)) {
8149
0
      return false;
8150
0
    }
8151
98.9k
    d = d + int32_t((m - n) * (h + 1));
8152
98.9k
    n = m;
8153
1.72M
    for (auto c : input) {
8154
1.72M
      if (c < n) {
8155
971k
        if (d == 0x7fffffff) {
8156
0
          return false;
8157
0
        }
8158
971k
        ++d;
8159
971k
      }
8160
1.72M
      if (c == n) {
8161
144k
        int32_t q = d;
8162
378k
        for (int32_t k = base;; k += base) {
8163
378k
          int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8164
8165
378k
          if (q < t) {
8166
144k
            break;
8167
144k
          }
8168
234k
          out.push_back(digit_to_char(t + ((q - t) % (base - t))));
8169
234k
          q = (q - t) / (base - t);
8170
234k
        }
8171
144k
        out.push_back(digit_to_char(q));
8172
144k
        bias = adapt(d, int32_t(h + 1), h == b);
8173
144k
        d = 0;
8174
144k
        ++h;
8175
144k
      }
8176
1.72M
    }
8177
98.9k
    ++d;
8178
98.9k
    ++n;
8179
98.9k
  }
8180
26.1k
  return true;
8181
26.1k
}
8182
8183
}  // namespace ada::idna
8184
/* end file src/punycode.cpp */
8185
/* begin file src/validity.cpp */
8186
#include <algorithm>
8187
#include <string_view>
8188
8189
namespace ada::idna {
8190
8191
enum direction : uint8_t {
8192
  NONE,
8193
  BN,
8194
  CS,
8195
  ES,
8196
  ON,
8197
  EN,
8198
  L,
8199
  R,
8200
  NSM,
8201
  AL,
8202
  AN,
8203
  ET,
8204
  WS,
8205
  RLO,
8206
  LRO,
8207
  PDF,
8208
  RLE,
8209
  RLI,
8210
  FSI,
8211
  PDI,
8212
  LRI,
8213
  B,
8214
  S,
8215
  LRE
8216
};
8217
8218
struct directions {
8219
  uint32_t start_code;
8220
  uint32_t final_code;
8221
  direction direct;
8222
};
8223
8224
static directions dir_table[] = {
8225
    {0x0, 0x8, direction::BN},          {0x9, 0x9, direction::S},
8226
    {0xa, 0xa, direction::B},           {0xb, 0xb, direction::S},
8227
    {0xc, 0xc, direction::WS},          {0xd, 0xd, direction::B},
8228
    {0xe, 0x1b, direction::BN},         {0x1c, 0x1e, direction::B},
8229
    {0x1f, 0x1f, direction::S},         {0x20, 0x20, direction::WS},
8230
    {0x21, 0x22, direction::ON},        {0x23, 0x25, direction::ET},
8231
    {0x26, 0x2a, direction::ON},        {0x2b, 0x2b, direction::ES},
8232
    {0x2c, 0x2c, direction::CS},        {0x2d, 0x2d, direction::ES},
8233
    {0x2e, 0x2f, direction::CS},        {0x30, 0x39, direction::EN},
8234
    {0x3a, 0x3a, direction::CS},        {0x3b, 0x40, direction::ON},
8235
    {0x41, 0x5a, direction::L},         {0x5b, 0x60, direction::ON},
8236
    {0x61, 0x7a, direction::L},         {0x7b, 0x7e, direction::ON},
8237
    {0x7f, 0x84, direction::BN},        {0x85, 0x85, direction::B},
8238
    {0x86, 0x9f, direction::BN},        {0xa0, 0xa0, direction::CS},
8239
    {0xa1, 0xa1, direction::ON},        {0xa2, 0xa5, direction::ET},
8240
    {0xa6, 0xa9, direction::ON},        {0xaa, 0xaa, direction::L},
8241
    {0xab, 0xac, direction::ON},        {0xad, 0xad, direction::BN},
8242
    {0xae, 0xaf, direction::ON},        {0xb0, 0xb1, direction::ET},
8243
    {0xb2, 0xb3, direction::EN},        {0xb4, 0xb4, direction::ON},
8244
    {0xb5, 0xb5, direction::L},         {0xb6, 0xb8, direction::ON},
8245
    {0xb9, 0xb9, direction::EN},        {0xba, 0xba, direction::L},
8246
    {0xbb, 0xbf, direction::ON},        {0xc0, 0xd6, direction::L},
8247
    {0xd7, 0xd7, direction::ON},        {0xd8, 0xf6, direction::L},
8248
    {0xf7, 0xf7, direction::ON},        {0xf8, 0x2b8, direction::L},
8249
    {0x2b9, 0x2ba, direction::ON},      {0x2bb, 0x2c1, direction::L},
8250
    {0x2c2, 0x2cf, direction::ON},      {0x2d0, 0x2d1, direction::L},
8251
    {0x2d2, 0x2df, direction::ON},      {0x2e0, 0x2e4, direction::L},
8252
    {0x2e5, 0x2ed, direction::ON},      {0x2ee, 0x2ee, direction::L},
8253
    {0x2ef, 0x2ff, direction::ON},      {0x300, 0x36f, direction::NSM},
8254
    {0x370, 0x373, direction::L},       {0x374, 0x375, direction::ON},
8255
    {0x376, 0x377, direction::L},       {0x37a, 0x37d, direction::L},
8256
    {0x37e, 0x37e, direction::ON},      {0x37f, 0x37f, direction::L},
8257
    {0x384, 0x385, direction::ON},      {0x386, 0x386, direction::L},
8258
    {0x387, 0x387, direction::ON},      {0x388, 0x38a, direction::L},
8259
    {0x38c, 0x38c, direction::L},       {0x38e, 0x3a1, direction::L},
8260
    {0x3a3, 0x3f5, direction::L},       {0x3f6, 0x3f6, direction::ON},
8261
    {0x3f7, 0x482, direction::L},       {0x483, 0x489, direction::NSM},
8262
    {0x48a, 0x52f, direction::L},       {0x531, 0x556, direction::L},
8263
    {0x559, 0x589, direction::L},       {0x58a, 0x58a, direction::ON},
8264
    {0x58d, 0x58e, direction::ON},      {0x58f, 0x58f, direction::ET},
8265
    {0x591, 0x5bd, direction::NSM},     {0x5be, 0x5be, direction::R},
8266
    {0x5bf, 0x5bf, direction::NSM},     {0x5c0, 0x5c0, direction::R},
8267
    {0x5c1, 0x5c2, direction::NSM},     {0x5c3, 0x5c3, direction::R},
8268
    {0x5c4, 0x5c5, direction::NSM},     {0x5c6, 0x5c6, direction::R},
8269
    {0x5c7, 0x5c7, direction::NSM},     {0x5d0, 0x5ea, direction::R},
8270
    {0x5ef, 0x5f4, direction::R},       {0x600, 0x605, direction::AN},
8271
    {0x606, 0x607, direction::ON},      {0x608, 0x608, direction::AL},
8272
    {0x609, 0x60a, direction::ET},      {0x60b, 0x60b, direction::AL},
8273
    {0x60c, 0x60c, direction::CS},      {0x60d, 0x60d, direction::AL},
8274
    {0x60e, 0x60f, direction::ON},      {0x610, 0x61a, direction::NSM},
8275
    {0x61b, 0x61c, direction::AL},      {0x61e, 0x64a, direction::AL},
8276
    {0x64b, 0x65f, direction::NSM},     {0x660, 0x669, direction::AN},
8277
    {0x66a, 0x66a, direction::ET},      {0x66b, 0x66c, direction::AN},
8278
    {0x66d, 0x66f, direction::AL},      {0x670, 0x670, direction::NSM},
8279
    {0x671, 0x6d5, direction::AL},      {0x6d6, 0x6dc, direction::NSM},
8280
    {0x6dd, 0x6dd, direction::AN},      {0x6de, 0x6de, direction::ON},
8281
    {0x6df, 0x6e4, direction::NSM},     {0x6e5, 0x6e6, direction::AL},
8282
    {0x6e7, 0x6e8, direction::NSM},     {0x6e9, 0x6e9, direction::ON},
8283
    {0x6ea, 0x6ed, direction::NSM},     {0x6ee, 0x6ef, direction::AL},
8284
    {0x6f0, 0x6f9, direction::EN},      {0x6fa, 0x70d, direction::AL},
8285
    {0x70f, 0x710, direction::AL},      {0x711, 0x711, direction::NSM},
8286
    {0x712, 0x72f, direction::AL},      {0x730, 0x74a, direction::NSM},
8287
    {0x74d, 0x7a5, direction::AL},      {0x7a6, 0x7b0, direction::NSM},
8288
    {0x7b1, 0x7b1, direction::AL},      {0x7c0, 0x7ea, direction::R},
8289
    {0x7eb, 0x7f3, direction::NSM},     {0x7f4, 0x7f5, direction::R},
8290
    {0x7f6, 0x7f9, direction::ON},      {0x7fa, 0x7fa, direction::R},
8291
    {0x7fd, 0x7fd, direction::NSM},     {0x7fe, 0x815, direction::R},
8292
    {0x816, 0x819, direction::NSM},     {0x81a, 0x81a, direction::R},
8293
    {0x81b, 0x823, direction::NSM},     {0x824, 0x824, direction::R},
8294
    {0x825, 0x827, direction::NSM},     {0x828, 0x828, direction::R},
8295
    {0x829, 0x82d, direction::NSM},     {0x830, 0x83e, direction::R},
8296
    {0x840, 0x858, direction::R},       {0x859, 0x85b, direction::NSM},
8297
    {0x85e, 0x85e, direction::R},       {0x860, 0x86a, direction::AL},
8298
    {0x8a0, 0x8b4, direction::AL},      {0x8b6, 0x8c7, direction::AL},
8299
    {0x8d3, 0x8e1, direction::NSM},     {0x8e2, 0x8e2, direction::AN},
8300
    {0x8e3, 0x902, direction::NSM},     {0x903, 0x939, direction::L},
8301
    {0x93a, 0x93a, direction::NSM},     {0x93b, 0x93b, direction::L},
8302
    {0x93c, 0x93c, direction::NSM},     {0x93d, 0x940, direction::L},
8303
    {0x941, 0x948, direction::NSM},     {0x949, 0x94c, direction::L},
8304
    {0x94d, 0x94d, direction::NSM},     {0x94e, 0x950, direction::L},
8305
    {0x951, 0x957, direction::NSM},     {0x958, 0x961, direction::L},
8306
    {0x962, 0x963, direction::NSM},     {0x964, 0x980, direction::L},
8307
    {0x981, 0x981, direction::NSM},     {0x982, 0x983, direction::L},
8308
    {0x985, 0x98c, direction::L},       {0x98f, 0x990, direction::L},
8309
    {0x993, 0x9a8, direction::L},       {0x9aa, 0x9b0, direction::L},
8310
    {0x9b2, 0x9b2, direction::L},       {0x9b6, 0x9b9, direction::L},
8311
    {0x9bc, 0x9bc, direction::NSM},     {0x9bd, 0x9c0, direction::L},
8312
    {0x9c1, 0x9c4, direction::NSM},     {0x9c7, 0x9c8, direction::L},
8313
    {0x9cb, 0x9cc, direction::L},       {0x9cd, 0x9cd, direction::NSM},
8314
    {0x9ce, 0x9ce, direction::L},       {0x9d7, 0x9d7, direction::L},
8315
    {0x9dc, 0x9dd, direction::L},       {0x9df, 0x9e1, direction::L},
8316
    {0x9e2, 0x9e3, direction::NSM},     {0x9e6, 0x9f1, direction::L},
8317
    {0x9f2, 0x9f3, direction::ET},      {0x9f4, 0x9fa, direction::L},
8318
    {0x9fb, 0x9fb, direction::ET},      {0x9fc, 0x9fd, direction::L},
8319
    {0x9fe, 0x9fe, direction::NSM},     {0xa01, 0xa02, direction::NSM},
8320
    {0xa03, 0xa03, direction::L},       {0xa05, 0xa0a, direction::L},
8321
    {0xa0f, 0xa10, direction::L},       {0xa13, 0xa28, direction::L},
8322
    {0xa2a, 0xa30, direction::L},       {0xa32, 0xa33, direction::L},
8323
    {0xa35, 0xa36, direction::L},       {0xa38, 0xa39, direction::L},
8324
    {0xa3c, 0xa3c, direction::NSM},     {0xa3e, 0xa40, direction::L},
8325
    {0xa41, 0xa42, direction::NSM},     {0xa47, 0xa48, direction::NSM},
8326
    {0xa4b, 0xa4d, direction::NSM},     {0xa51, 0xa51, direction::NSM},
8327
    {0xa59, 0xa5c, direction::L},       {0xa5e, 0xa5e, direction::L},
8328
    {0xa66, 0xa6f, direction::L},       {0xa70, 0xa71, direction::NSM},
8329
    {0xa72, 0xa74, direction::L},       {0xa75, 0xa75, direction::NSM},
8330
    {0xa76, 0xa76, direction::L},       {0xa81, 0xa82, direction::NSM},
8331
    {0xa83, 0xa83, direction::L},       {0xa85, 0xa8d, direction::L},
8332
    {0xa8f, 0xa91, direction::L},       {0xa93, 0xaa8, direction::L},
8333
    {0xaaa, 0xab0, direction::L},       {0xab2, 0xab3, direction::L},
8334
    {0xab5, 0xab9, direction::L},       {0xabc, 0xabc, direction::NSM},
8335
    {0xabd, 0xac0, direction::L},       {0xac1, 0xac5, direction::NSM},
8336
    {0xac7, 0xac8, direction::NSM},     {0xac9, 0xac9, direction::L},
8337
    {0xacb, 0xacc, direction::L},       {0xacd, 0xacd, direction::NSM},
8338
    {0xad0, 0xad0, direction::L},       {0xae0, 0xae1, direction::L},
8339
    {0xae2, 0xae3, direction::NSM},     {0xae6, 0xaf0, direction::L},
8340
    {0xaf1, 0xaf1, direction::ET},      {0xaf9, 0xaf9, direction::L},
8341
    {0xafa, 0xaff, direction::NSM},     {0xb01, 0xb01, direction::NSM},
8342
    {0xb02, 0xb03, direction::L},       {0xb05, 0xb0c, direction::L},
8343
    {0xb0f, 0xb10, direction::L},       {0xb13, 0xb28, direction::L},
8344
    {0xb2a, 0xb30, direction::L},       {0xb32, 0xb33, direction::L},
8345
    {0xb35, 0xb39, direction::L},       {0xb3c, 0xb3c, direction::NSM},
8346
    {0xb3d, 0xb3e, direction::L},       {0xb3f, 0xb3f, direction::NSM},
8347
    {0xb40, 0xb40, direction::L},       {0xb41, 0xb44, direction::NSM},
8348
    {0xb47, 0xb48, direction::L},       {0xb4b, 0xb4c, direction::L},
8349
    {0xb4d, 0xb4d, direction::NSM},     {0xb55, 0xb56, direction::NSM},
8350
    {0xb57, 0xb57, direction::L},       {0xb5c, 0xb5d, direction::L},
8351
    {0xb5f, 0xb61, direction::L},       {0xb62, 0xb63, direction::NSM},
8352
    {0xb66, 0xb77, direction::L},       {0xb82, 0xb82, direction::NSM},
8353
    {0xb83, 0xb83, direction::L},       {0xb85, 0xb8a, direction::L},
8354
    {0xb8e, 0xb90, direction::L},       {0xb92, 0xb95, direction::L},
8355
    {0xb99, 0xb9a, direction::L},       {0xb9c, 0xb9c, direction::L},
8356
    {0xb9e, 0xb9f, direction::L},       {0xba3, 0xba4, direction::L},
8357
    {0xba8, 0xbaa, direction::L},       {0xbae, 0xbb9, direction::L},
8358
    {0xbbe, 0xbbf, direction::L},       {0xbc0, 0xbc0, direction::NSM},
8359
    {0xbc1, 0xbc2, direction::L},       {0xbc6, 0xbc8, direction::L},
8360
    {0xbca, 0xbcc, direction::L},       {0xbcd, 0xbcd, direction::NSM},
8361
    {0xbd0, 0xbd0, direction::L},       {0xbd7, 0xbd7, direction::L},
8362
    {0xbe6, 0xbf2, direction::L},       {0xbf3, 0xbf8, direction::ON},
8363
    {0xbf9, 0xbf9, direction::ET},      {0xbfa, 0xbfa, direction::ON},
8364
    {0xc00, 0xc00, direction::NSM},     {0xc01, 0xc03, direction::L},
8365
    {0xc04, 0xc04, direction::NSM},     {0xc05, 0xc0c, direction::L},
8366
    {0xc0e, 0xc10, direction::L},       {0xc12, 0xc28, direction::L},
8367
    {0xc2a, 0xc39, direction::L},       {0xc3d, 0xc3d, direction::L},
8368
    {0xc3e, 0xc40, direction::NSM},     {0xc41, 0xc44, direction::L},
8369
    {0xc46, 0xc48, direction::NSM},     {0xc4a, 0xc4d, direction::NSM},
8370
    {0xc55, 0xc56, direction::NSM},     {0xc58, 0xc5a, direction::L},
8371
    {0xc60, 0xc61, direction::L},       {0xc62, 0xc63, direction::NSM},
8372
    {0xc66, 0xc6f, direction::L},       {0xc77, 0xc77, direction::L},
8373
    {0xc78, 0xc7e, direction::ON},      {0xc7f, 0xc80, direction::L},
8374
    {0xc81, 0xc81, direction::NSM},     {0xc82, 0xc8c, direction::L},
8375
    {0xc8e, 0xc90, direction::L},       {0xc92, 0xca8, direction::L},
8376
    {0xcaa, 0xcb3, direction::L},       {0xcb5, 0xcb9, direction::L},
8377
    {0xcbc, 0xcbc, direction::NSM},     {0xcbd, 0xcc4, direction::L},
8378
    {0xcc6, 0xcc8, direction::L},       {0xcca, 0xccb, direction::L},
8379
    {0xccc, 0xccd, direction::NSM},     {0xcd5, 0xcd6, direction::L},
8380
    {0xcde, 0xcde, direction::L},       {0xce0, 0xce1, direction::L},
8381
    {0xce2, 0xce3, direction::NSM},     {0xce6, 0xcef, direction::L},
8382
    {0xcf1, 0xcf2, direction::L},       {0xd00, 0xd01, direction::NSM},
8383
    {0xd02, 0xd0c, direction::L},       {0xd0e, 0xd10, direction::L},
8384
    {0xd12, 0xd3a, direction::L},       {0xd3b, 0xd3c, direction::NSM},
8385
    {0xd3d, 0xd40, direction::L},       {0xd41, 0xd44, direction::NSM},
8386
    {0xd46, 0xd48, direction::L},       {0xd4a, 0xd4c, direction::L},
8387
    {0xd4d, 0xd4d, direction::NSM},     {0xd4e, 0xd4f, direction::L},
8388
    {0xd54, 0xd61, direction::L},       {0xd62, 0xd63, direction::NSM},
8389
    {0xd66, 0xd7f, direction::L},       {0xd81, 0xd81, direction::NSM},
8390
    {0xd82, 0xd83, direction::L},       {0xd85, 0xd96, direction::L},
8391
    {0xd9a, 0xdb1, direction::L},       {0xdb3, 0xdbb, direction::L},
8392
    {0xdbd, 0xdbd, direction::L},       {0xdc0, 0xdc6, direction::L},
8393
    {0xdca, 0xdca, direction::NSM},     {0xdcf, 0xdd1, direction::L},
8394
    {0xdd2, 0xdd4, direction::NSM},     {0xdd6, 0xdd6, direction::NSM},
8395
    {0xdd8, 0xddf, direction::L},       {0xde6, 0xdef, direction::L},
8396
    {0xdf2, 0xdf4, direction::L},       {0xe01, 0xe30, direction::L},
8397
    {0xe31, 0xe31, direction::NSM},     {0xe32, 0xe33, direction::L},
8398
    {0xe34, 0xe3a, direction::NSM},     {0xe3f, 0xe3f, direction::ET},
8399
    {0xe40, 0xe46, direction::L},       {0xe47, 0xe4e, direction::NSM},
8400
    {0xe4f, 0xe5b, direction::L},       {0xe81, 0xe82, direction::L},
8401
    {0xe84, 0xe84, direction::L},       {0xe86, 0xe8a, direction::L},
8402
    {0xe8c, 0xea3, direction::L},       {0xea5, 0xea5, direction::L},
8403
    {0xea7, 0xeb0, direction::L},       {0xeb1, 0xeb1, direction::NSM},
8404
    {0xeb2, 0xeb3, direction::L},       {0xeb4, 0xebc, direction::NSM},
8405
    {0xebd, 0xebd, direction::L},       {0xec0, 0xec4, direction::L},
8406
    {0xec6, 0xec6, direction::L},       {0xec8, 0xecd, direction::NSM},
8407
    {0xed0, 0xed9, direction::L},       {0xedc, 0xedf, direction::L},
8408
    {0xf00, 0xf17, direction::L},       {0xf18, 0xf19, direction::NSM},
8409
    {0xf1a, 0xf34, direction::L},       {0xf35, 0xf35, direction::NSM},
8410
    {0xf36, 0xf36, direction::L},       {0xf37, 0xf37, direction::NSM},
8411
    {0xf38, 0xf38, direction::L},       {0xf39, 0xf39, direction::NSM},
8412
    {0xf3a, 0xf3d, direction::ON},      {0xf3e, 0xf47, direction::L},
8413
    {0xf49, 0xf6c, direction::L},       {0xf71, 0xf7e, direction::NSM},
8414
    {0xf7f, 0xf7f, direction::L},       {0xf80, 0xf84, direction::NSM},
8415
    {0xf85, 0xf85, direction::L},       {0xf86, 0xf87, direction::NSM},
8416
    {0xf88, 0xf8c, direction::L},       {0xf8d, 0xf97, direction::NSM},
8417
    {0xf99, 0xfbc, direction::NSM},     {0xfbe, 0xfc5, direction::L},
8418
    {0xfc6, 0xfc6, direction::NSM},     {0xfc7, 0xfcc, direction::L},
8419
    {0xfce, 0xfda, direction::L},       {0x1000, 0x102c, direction::L},
8420
    {0x102d, 0x1030, direction::NSM},   {0x1031, 0x1031, direction::L},
8421
    {0x1032, 0x1037, direction::NSM},   {0x1038, 0x1038, direction::L},
8422
    {0x1039, 0x103a, direction::NSM},   {0x103b, 0x103c, direction::L},
8423
    {0x103d, 0x103e, direction::NSM},   {0x103f, 0x1057, direction::L},
8424
    {0x1058, 0x1059, direction::NSM},   {0x105a, 0x105d, direction::L},
8425
    {0x105e, 0x1060, direction::NSM},   {0x1061, 0x1070, direction::L},
8426
    {0x1071, 0x1074, direction::NSM},   {0x1075, 0x1081, direction::L},
8427
    {0x1082, 0x1082, direction::NSM},   {0x1083, 0x1084, direction::L},
8428
    {0x1085, 0x1086, direction::NSM},   {0x1087, 0x108c, direction::L},
8429
    {0x108d, 0x108d, direction::NSM},   {0x108e, 0x109c, direction::L},
8430
    {0x109d, 0x109d, direction::NSM},   {0x109e, 0x10c5, direction::L},
8431
    {0x10c7, 0x10c7, direction::L},     {0x10cd, 0x10cd, direction::L},
8432
    {0x10d0, 0x1248, direction::L},     {0x124a, 0x124d, direction::L},
8433
    {0x1250, 0x1256, direction::L},     {0x1258, 0x1258, direction::L},
8434
    {0x125a, 0x125d, direction::L},     {0x1260, 0x1288, direction::L},
8435
    {0x128a, 0x128d, direction::L},     {0x1290, 0x12b0, direction::L},
8436
    {0x12b2, 0x12b5, direction::L},     {0x12b8, 0x12be, direction::L},
8437
    {0x12c0, 0x12c0, direction::L},     {0x12c2, 0x12c5, direction::L},
8438
    {0x12c8, 0x12d6, direction::L},     {0x12d8, 0x1310, direction::L},
8439
    {0x1312, 0x1315, direction::L},     {0x1318, 0x135a, direction::L},
8440
    {0x135d, 0x135f, direction::NSM},   {0x1360, 0x137c, direction::L},
8441
    {0x1380, 0x138f, direction::L},     {0x1390, 0x1399, direction::ON},
8442
    {0x13a0, 0x13f5, direction::L},     {0x13f8, 0x13fd, direction::L},
8443
    {0x1400, 0x1400, direction::ON},    {0x1401, 0x167f, direction::L},
8444
    {0x1680, 0x1680, direction::WS},    {0x1681, 0x169a, direction::L},
8445
    {0x169b, 0x169c, direction::ON},    {0x16a0, 0x16f8, direction::L},
8446
    {0x1700, 0x170c, direction::L},     {0x170e, 0x1711, direction::L},
8447
    {0x1712, 0x1714, direction::NSM},   {0x1720, 0x1731, direction::L},
8448
    {0x1732, 0x1734, direction::NSM},   {0x1735, 0x1736, direction::L},
8449
    {0x1740, 0x1751, direction::L},     {0x1752, 0x1753, direction::NSM},
8450
    {0x1760, 0x176c, direction::L},     {0x176e, 0x1770, direction::L},
8451
    {0x1772, 0x1773, direction::NSM},   {0x1780, 0x17b3, direction::L},
8452
    {0x17b4, 0x17b5, direction::NSM},   {0x17b6, 0x17b6, direction::L},
8453
    {0x17b7, 0x17bd, direction::NSM},   {0x17be, 0x17c5, direction::L},
8454
    {0x17c6, 0x17c6, direction::NSM},   {0x17c7, 0x17c8, direction::L},
8455
    {0x17c9, 0x17d3, direction::NSM},   {0x17d4, 0x17da, direction::L},
8456
    {0x17db, 0x17db, direction::ET},    {0x17dc, 0x17dc, direction::L},
8457
    {0x17dd, 0x17dd, direction::NSM},   {0x17e0, 0x17e9, direction::L},
8458
    {0x17f0, 0x17f9, direction::ON},    {0x1800, 0x180a, direction::ON},
8459
    {0x180b, 0x180d, direction::NSM},   {0x180e, 0x180e, direction::BN},
8460
    {0x1810, 0x1819, direction::L},     {0x1820, 0x1878, direction::L},
8461
    {0x1880, 0x1884, direction::L},     {0x1885, 0x1886, direction::NSM},
8462
    {0x1887, 0x18a8, direction::L},     {0x18a9, 0x18a9, direction::NSM},
8463
    {0x18aa, 0x18aa, direction::L},     {0x18b0, 0x18f5, direction::L},
8464
    {0x1900, 0x191e, direction::L},     {0x1920, 0x1922, direction::NSM},
8465
    {0x1923, 0x1926, direction::L},     {0x1927, 0x1928, direction::NSM},
8466
    {0x1929, 0x192b, direction::L},     {0x1930, 0x1931, direction::L},
8467
    {0x1932, 0x1932, direction::NSM},   {0x1933, 0x1938, direction::L},
8468
    {0x1939, 0x193b, direction::NSM},   {0x1940, 0x1940, direction::ON},
8469
    {0x1944, 0x1945, direction::ON},    {0x1946, 0x196d, direction::L},
8470
    {0x1970, 0x1974, direction::L},     {0x1980, 0x19ab, direction::L},
8471
    {0x19b0, 0x19c9, direction::L},     {0x19d0, 0x19da, direction::L},
8472
    {0x19de, 0x19ff, direction::ON},    {0x1a00, 0x1a16, direction::L},
8473
    {0x1a17, 0x1a18, direction::NSM},   {0x1a19, 0x1a1a, direction::L},
8474
    {0x1a1b, 0x1a1b, direction::NSM},   {0x1a1e, 0x1a55, direction::L},
8475
    {0x1a56, 0x1a56, direction::NSM},   {0x1a57, 0x1a57, direction::L},
8476
    {0x1a58, 0x1a5e, direction::NSM},   {0x1a60, 0x1a60, direction::NSM},
8477
    {0x1a61, 0x1a61, direction::L},     {0x1a62, 0x1a62, direction::NSM},
8478
    {0x1a63, 0x1a64, direction::L},     {0x1a65, 0x1a6c, direction::NSM},
8479
    {0x1a6d, 0x1a72, direction::L},     {0x1a73, 0x1a7c, direction::NSM},
8480
    {0x1a7f, 0x1a7f, direction::NSM},   {0x1a80, 0x1a89, direction::L},
8481
    {0x1a90, 0x1a99, direction::L},     {0x1aa0, 0x1aad, direction::L},
8482
    {0x1ab0, 0x1ac0, direction::NSM},   {0x1b00, 0x1b03, direction::NSM},
8483
    {0x1b04, 0x1b33, direction::L},     {0x1b34, 0x1b34, direction::NSM},
8484
    {0x1b35, 0x1b35, direction::L},     {0x1b36, 0x1b3a, direction::NSM},
8485
    {0x1b3b, 0x1b3b, direction::L},     {0x1b3c, 0x1b3c, direction::NSM},
8486
    {0x1b3d, 0x1b41, direction::L},     {0x1b42, 0x1b42, direction::NSM},
8487
    {0x1b43, 0x1b4b, direction::L},     {0x1b50, 0x1b6a, direction::L},
8488
    {0x1b6b, 0x1b73, direction::NSM},   {0x1b74, 0x1b7c, direction::L},
8489
    {0x1b80, 0x1b81, direction::NSM},   {0x1b82, 0x1ba1, direction::L},
8490
    {0x1ba2, 0x1ba5, direction::NSM},   {0x1ba6, 0x1ba7, direction::L},
8491
    {0x1ba8, 0x1ba9, direction::NSM},   {0x1baa, 0x1baa, direction::L},
8492
    {0x1bab, 0x1bad, direction::NSM},   {0x1bae, 0x1be5, direction::L},
8493
    {0x1be6, 0x1be6, direction::NSM},   {0x1be7, 0x1be7, direction::L},
8494
    {0x1be8, 0x1be9, direction::NSM},   {0x1bea, 0x1bec, direction::L},
8495
    {0x1bed, 0x1bed, direction::NSM},   {0x1bee, 0x1bee, direction::L},
8496
    {0x1bef, 0x1bf1, direction::NSM},   {0x1bf2, 0x1bf3, direction::L},
8497
    {0x1bfc, 0x1c2b, direction::L},     {0x1c2c, 0x1c33, direction::NSM},
8498
    {0x1c34, 0x1c35, direction::L},     {0x1c36, 0x1c37, direction::NSM},
8499
    {0x1c3b, 0x1c49, direction::L},     {0x1c4d, 0x1c88, direction::L},
8500
    {0x1c90, 0x1cba, direction::L},     {0x1cbd, 0x1cc7, direction::L},
8501
    {0x1cd0, 0x1cd2, direction::NSM},   {0x1cd3, 0x1cd3, direction::L},
8502
    {0x1cd4, 0x1ce0, direction::NSM},   {0x1ce1, 0x1ce1, direction::L},
8503
    {0x1ce2, 0x1ce8, direction::NSM},   {0x1ce9, 0x1cec, direction::L},
8504
    {0x1ced, 0x1ced, direction::NSM},   {0x1cee, 0x1cf3, direction::L},
8505
    {0x1cf4, 0x1cf4, direction::NSM},   {0x1cf5, 0x1cf7, direction::L},
8506
    {0x1cf8, 0x1cf9, direction::NSM},   {0x1cfa, 0x1cfa, direction::L},
8507
    {0x1d00, 0x1dbf, direction::L},     {0x1dc0, 0x1df9, direction::NSM},
8508
    {0x1dfb, 0x1dff, direction::NSM},   {0x1e00, 0x1f15, direction::L},
8509
    {0x1f18, 0x1f1d, direction::L},     {0x1f20, 0x1f45, direction::L},
8510
    {0x1f48, 0x1f4d, direction::L},     {0x1f50, 0x1f57, direction::L},
8511
    {0x1f59, 0x1f59, direction::L},     {0x1f5b, 0x1f5b, direction::L},
8512
    {0x1f5d, 0x1f5d, direction::L},     {0x1f5f, 0x1f7d, direction::L},
8513
    {0x1f80, 0x1fb4, direction::L},     {0x1fb6, 0x1fbc, direction::L},
8514
    {0x1fbd, 0x1fbd, direction::ON},    {0x1fbe, 0x1fbe, direction::L},
8515
    {0x1fbf, 0x1fc1, direction::ON},    {0x1fc2, 0x1fc4, direction::L},
8516
    {0x1fc6, 0x1fcc, direction::L},     {0x1fcd, 0x1fcf, direction::ON},
8517
    {0x1fd0, 0x1fd3, direction::L},     {0x1fd6, 0x1fdb, direction::L},
8518
    {0x1fdd, 0x1fdf, direction::ON},    {0x1fe0, 0x1fec, direction::L},
8519
    {0x1fed, 0x1fef, direction::ON},    {0x1ff2, 0x1ff4, direction::L},
8520
    {0x1ff6, 0x1ffc, direction::L},     {0x1ffd, 0x1ffe, direction::ON},
8521
    {0x2000, 0x200a, direction::WS},    {0x200b, 0x200d, direction::BN},
8522
    {0x200e, 0x200e, direction::L},     {0x200f, 0x200f, direction::R},
8523
    {0x2010, 0x2027, direction::ON},    {0x2028, 0x2028, direction::WS},
8524
    {0x2029, 0x2029, direction::B},     {0x202a, 0x202a, direction::LRE},
8525
    {0x202b, 0x202b, direction::RLE},   {0x202c, 0x202c, direction::PDF},
8526
    {0x202d, 0x202d, direction::LRO},   {0x202e, 0x202e, direction::RLO},
8527
    {0x202f, 0x202f, direction::CS},    {0x2030, 0x2034, direction::ET},
8528
    {0x2035, 0x2043, direction::ON},    {0x2044, 0x2044, direction::CS},
8529
    {0x2045, 0x205e, direction::ON},    {0x205f, 0x205f, direction::WS},
8530
    {0x2060, 0x2064, direction::BN},    {0x2066, 0x2066, direction::LRI},
8531
    {0x2067, 0x2067, direction::RLI},   {0x2068, 0x2068, direction::FSI},
8532
    {0x2069, 0x2069, direction::PDI},   {0x206a, 0x206f, direction::BN},
8533
    {0x2070, 0x2070, direction::EN},    {0x2071, 0x2071, direction::L},
8534
    {0x2074, 0x2079, direction::EN},    {0x207a, 0x207b, direction::ES},
8535
    {0x207c, 0x207e, direction::ON},    {0x207f, 0x207f, direction::L},
8536
    {0x2080, 0x2089, direction::EN},    {0x208a, 0x208b, direction::ES},
8537
    {0x208c, 0x208e, direction::ON},    {0x2090, 0x209c, direction::L},
8538
    {0x20a0, 0x20bf, direction::ET},    {0x20d0, 0x20f0, direction::NSM},
8539
    {0x2100, 0x2101, direction::ON},    {0x2102, 0x2102, direction::L},
8540
    {0x2103, 0x2106, direction::ON},    {0x2107, 0x2107, direction::L},
8541
    {0x2108, 0x2109, direction::ON},    {0x210a, 0x2113, direction::L},
8542
    {0x2114, 0x2114, direction::ON},    {0x2115, 0x2115, direction::L},
8543
    {0x2116, 0x2118, direction::ON},    {0x2119, 0x211d, direction::L},
8544
    {0x211e, 0x2123, direction::ON},    {0x2124, 0x2124, direction::L},
8545
    {0x2125, 0x2125, direction::ON},    {0x2126, 0x2126, direction::L},
8546
    {0x2127, 0x2127, direction::ON},    {0x2128, 0x2128, direction::L},
8547
    {0x2129, 0x2129, direction::ON},    {0x212a, 0x212d, direction::L},
8548
    {0x212e, 0x212e, direction::ET},    {0x212f, 0x2139, direction::L},
8549
    {0x213a, 0x213b, direction::ON},    {0x213c, 0x213f, direction::L},
8550
    {0x2140, 0x2144, direction::ON},    {0x2145, 0x2149, direction::L},
8551
    {0x214a, 0x214d, direction::ON},    {0x214e, 0x214f, direction::L},
8552
    {0x2150, 0x215f, direction::ON},    {0x2160, 0x2188, direction::L},
8553
    {0x2189, 0x218b, direction::ON},    {0x2190, 0x2211, direction::ON},
8554
    {0x2212, 0x2212, direction::ES},    {0x2213, 0x2213, direction::ET},
8555
    {0x2214, 0x2335, direction::ON},    {0x2336, 0x237a, direction::L},
8556
    {0x237b, 0x2394, direction::ON},    {0x2395, 0x2395, direction::L},
8557
    {0x2396, 0x2426, direction::ON},    {0x2440, 0x244a, direction::ON},
8558
    {0x2460, 0x2487, direction::ON},    {0x2488, 0x249b, direction::EN},
8559
    {0x249c, 0x24e9, direction::L},     {0x24ea, 0x26ab, direction::ON},
8560
    {0x26ac, 0x26ac, direction::L},     {0x26ad, 0x27ff, direction::ON},
8561
    {0x2800, 0x28ff, direction::L},     {0x2900, 0x2b73, direction::ON},
8562
    {0x2b76, 0x2b95, direction::ON},    {0x2b97, 0x2bff, direction::ON},
8563
    {0x2c00, 0x2c2e, direction::L},     {0x2c30, 0x2c5e, direction::L},
8564
    {0x2c60, 0x2ce4, direction::L},     {0x2ce5, 0x2cea, direction::ON},
8565
    {0x2ceb, 0x2cee, direction::L},     {0x2cef, 0x2cf1, direction::NSM},
8566
    {0x2cf2, 0x2cf3, direction::L},     {0x2cf9, 0x2cff, direction::ON},
8567
    {0x2d00, 0x2d25, direction::L},     {0x2d27, 0x2d27, direction::L},
8568
    {0x2d2d, 0x2d2d, direction::L},     {0x2d30, 0x2d67, direction::L},
8569
    {0x2d6f, 0x2d70, direction::L},     {0x2d7f, 0x2d7f, direction::NSM},
8570
    {0x2d80, 0x2d96, direction::L},     {0x2da0, 0x2da6, direction::L},
8571
    {0x2da8, 0x2dae, direction::L},     {0x2db0, 0x2db6, direction::L},
8572
    {0x2db8, 0x2dbe, direction::L},     {0x2dc0, 0x2dc6, direction::L},
8573
    {0x2dc8, 0x2dce, direction::L},     {0x2dd0, 0x2dd6, direction::L},
8574
    {0x2dd8, 0x2dde, direction::L},     {0x2de0, 0x2dff, direction::NSM},
8575
    {0x2e00, 0x2e52, direction::ON},    {0x2e80, 0x2e99, direction::ON},
8576
    {0x2e9b, 0x2ef3, direction::ON},    {0x2f00, 0x2fd5, direction::ON},
8577
    {0x2ff0, 0x2ffb, direction::ON},    {0x3000, 0x3000, direction::WS},
8578
    {0x3001, 0x3004, direction::ON},    {0x3005, 0x3007, direction::L},
8579
    {0x3008, 0x3020, direction::ON},    {0x3021, 0x3029, direction::L},
8580
    {0x302a, 0x302d, direction::NSM},   {0x302e, 0x302f, direction::L},
8581
    {0x3030, 0x3030, direction::ON},    {0x3031, 0x3035, direction::L},
8582
    {0x3036, 0x3037, direction::ON},    {0x3038, 0x303c, direction::L},
8583
    {0x303d, 0x303f, direction::ON},    {0x3041, 0x3096, direction::L},
8584
    {0x3099, 0x309a, direction::NSM},   {0x309b, 0x309c, direction::ON},
8585
    {0x309d, 0x309f, direction::L},     {0x30a0, 0x30a0, direction::ON},
8586
    {0x30a1, 0x30fa, direction::L},     {0x30fb, 0x30fb, direction::ON},
8587
    {0x30fc, 0x30ff, direction::L},     {0x3105, 0x312f, direction::L},
8588
    {0x3131, 0x318e, direction::L},     {0x3190, 0x31bf, direction::L},
8589
    {0x31c0, 0x31e3, direction::ON},    {0x31f0, 0x321c, direction::L},
8590
    {0x321d, 0x321e, direction::ON},    {0x3220, 0x324f, direction::L},
8591
    {0x3250, 0x325f, direction::ON},    {0x3260, 0x327b, direction::L},
8592
    {0x327c, 0x327e, direction::ON},    {0x327f, 0x32b0, direction::L},
8593
    {0x32b1, 0x32bf, direction::ON},    {0x32c0, 0x32cb, direction::L},
8594
    {0x32cc, 0x32cf, direction::ON},    {0x32d0, 0x3376, direction::L},
8595
    {0x3377, 0x337a, direction::ON},    {0x337b, 0x33dd, direction::L},
8596
    {0x33de, 0x33df, direction::ON},    {0x33e0, 0x33fe, direction::L},
8597
    {0x33ff, 0x33ff, direction::ON},    {0x3400, 0x4dbf, direction::L},
8598
    {0x4dc0, 0x4dff, direction::ON},    {0x4e00, 0x9ffc, direction::L},
8599
    {0xa000, 0xa48c, direction::L},     {0xa490, 0xa4c6, direction::ON},
8600
    {0xa4d0, 0xa60c, direction::L},     {0xa60d, 0xa60f, direction::ON},
8601
    {0xa610, 0xa62b, direction::L},     {0xa640, 0xa66e, direction::L},
8602
    {0xa66f, 0xa672, direction::NSM},   {0xa673, 0xa673, direction::ON},
8603
    {0xa674, 0xa67d, direction::NSM},   {0xa67e, 0xa67f, direction::ON},
8604
    {0xa680, 0xa69d, direction::L},     {0xa69e, 0xa69f, direction::NSM},
8605
    {0xa6a0, 0xa6ef, direction::L},     {0xa6f0, 0xa6f1, direction::NSM},
8606
    {0xa6f2, 0xa6f7, direction::L},     {0xa700, 0xa721, direction::ON},
8607
    {0xa722, 0xa787, direction::L},     {0xa788, 0xa788, direction::ON},
8608
    {0xa789, 0xa7bf, direction::L},     {0xa7c2, 0xa7ca, direction::L},
8609
    {0xa7f5, 0xa801, direction::L},     {0xa802, 0xa802, direction::NSM},
8610
    {0xa803, 0xa805, direction::L},     {0xa806, 0xa806, direction::NSM},
8611
    {0xa807, 0xa80a, direction::L},     {0xa80b, 0xa80b, direction::NSM},
8612
    {0xa80c, 0xa824, direction::L},     {0xa825, 0xa826, direction::NSM},
8613
    {0xa827, 0xa827, direction::L},     {0xa828, 0xa82b, direction::ON},
8614
    {0xa82c, 0xa82c, direction::NSM},   {0xa830, 0xa837, direction::L},
8615
    {0xa838, 0xa839, direction::ET},    {0xa840, 0xa873, direction::L},
8616
    {0xa874, 0xa877, direction::ON},    {0xa880, 0xa8c3, direction::L},
8617
    {0xa8c4, 0xa8c5, direction::NSM},   {0xa8ce, 0xa8d9, direction::L},
8618
    {0xa8e0, 0xa8f1, direction::NSM},   {0xa8f2, 0xa8fe, direction::L},
8619
    {0xa8ff, 0xa8ff, direction::NSM},   {0xa900, 0xa925, direction::L},
8620
    {0xa926, 0xa92d, direction::NSM},   {0xa92e, 0xa946, direction::L},
8621
    {0xa947, 0xa951, direction::NSM},   {0xa952, 0xa953, direction::L},
8622
    {0xa95f, 0xa97c, direction::L},     {0xa980, 0xa982, direction::NSM},
8623
    {0xa983, 0xa9b2, direction::L},     {0xa9b3, 0xa9b3, direction::NSM},
8624
    {0xa9b4, 0xa9b5, direction::L},     {0xa9b6, 0xa9b9, direction::NSM},
8625
    {0xa9ba, 0xa9bb, direction::L},     {0xa9bc, 0xa9bd, direction::NSM},
8626
    {0xa9be, 0xa9cd, direction::L},     {0xa9cf, 0xa9d9, direction::L},
8627
    {0xa9de, 0xa9e4, direction::L},     {0xa9e5, 0xa9e5, direction::NSM},
8628
    {0xa9e6, 0xa9fe, direction::L},     {0xaa00, 0xaa28, direction::L},
8629
    {0xaa29, 0xaa2e, direction::NSM},   {0xaa2f, 0xaa30, direction::L},
8630
    {0xaa31, 0xaa32, direction::NSM},   {0xaa33, 0xaa34, direction::L},
8631
    {0xaa35, 0xaa36, direction::NSM},   {0xaa40, 0xaa42, direction::L},
8632
    {0xaa43, 0xaa43, direction::NSM},   {0xaa44, 0xaa4b, direction::L},
8633
    {0xaa4c, 0xaa4c, direction::NSM},   {0xaa4d, 0xaa4d, direction::L},
8634
    {0xaa50, 0xaa59, direction::L},     {0xaa5c, 0xaa7b, direction::L},
8635
    {0xaa7c, 0xaa7c, direction::NSM},   {0xaa7d, 0xaaaf, direction::L},
8636
    {0xaab0, 0xaab0, direction::NSM},   {0xaab1, 0xaab1, direction::L},
8637
    {0xaab2, 0xaab4, direction::NSM},   {0xaab5, 0xaab6, direction::L},
8638
    {0xaab7, 0xaab8, direction::NSM},   {0xaab9, 0xaabd, direction::L},
8639
    {0xaabe, 0xaabf, direction::NSM},   {0xaac0, 0xaac0, direction::L},
8640
    {0xaac1, 0xaac1, direction::NSM},   {0xaac2, 0xaac2, direction::L},
8641
    {0xaadb, 0xaaeb, direction::L},     {0xaaec, 0xaaed, direction::NSM},
8642
    {0xaaee, 0xaaf5, direction::L},     {0xaaf6, 0xaaf6, direction::NSM},
8643
    {0xab01, 0xab06, direction::L},     {0xab09, 0xab0e, direction::L},
8644
    {0xab11, 0xab16, direction::L},     {0xab20, 0xab26, direction::L},
8645
    {0xab28, 0xab2e, direction::L},     {0xab30, 0xab69, direction::L},
8646
    {0xab6a, 0xab6b, direction::ON},    {0xab70, 0xabe4, direction::L},
8647
    {0xabe5, 0xabe5, direction::NSM},   {0xabe6, 0xabe7, direction::L},
8648
    {0xabe8, 0xabe8, direction::NSM},   {0xabe9, 0xabec, direction::L},
8649
    {0xabed, 0xabed, direction::NSM},   {0xabf0, 0xabf9, direction::L},
8650
    {0xac00, 0xd7a3, direction::L},     {0xd7b0, 0xd7c6, direction::L},
8651
    {0xd7cb, 0xd7fb, direction::L},     {0xd800, 0xfa6d, direction::L},
8652
    {0xfa70, 0xfad9, direction::L},     {0xfb00, 0xfb06, direction::L},
8653
    {0xfb13, 0xfb17, direction::L},     {0xfb1d, 0xfb1d, direction::R},
8654
    {0xfb1e, 0xfb1e, direction::NSM},   {0xfb1f, 0xfb28, direction::R},
8655
    {0xfb29, 0xfb29, direction::ES},    {0xfb2a, 0xfb36, direction::R},
8656
    {0xfb38, 0xfb3c, direction::R},     {0xfb3e, 0xfb3e, direction::R},
8657
    {0xfb40, 0xfb41, direction::R},     {0xfb43, 0xfb44, direction::R},
8658
    {0xfb46, 0xfb4f, direction::R},     {0xfb50, 0xfbc1, direction::AL},
8659
    {0xfbd3, 0xfd3d, direction::AL},    {0xfd3e, 0xfd3f, direction::ON},
8660
    {0xfd50, 0xfd8f, direction::AL},    {0xfd92, 0xfdc7, direction::AL},
8661
    {0xfdf0, 0xfdfc, direction::AL},    {0xfdfd, 0xfdfd, direction::ON},
8662
    {0xfe00, 0xfe0f, direction::NSM},   {0xfe10, 0xfe19, direction::ON},
8663
    {0xfe20, 0xfe2f, direction::NSM},   {0xfe30, 0xfe4f, direction::ON},
8664
    {0xfe50, 0xfe50, direction::CS},    {0xfe51, 0xfe51, direction::ON},
8665
    {0xfe52, 0xfe52, direction::CS},    {0xfe54, 0xfe54, direction::ON},
8666
    {0xfe55, 0xfe55, direction::CS},    {0xfe56, 0xfe5e, direction::ON},
8667
    {0xfe5f, 0xfe5f, direction::ET},    {0xfe60, 0xfe61, direction::ON},
8668
    {0xfe62, 0xfe63, direction::ES},    {0xfe64, 0xfe66, direction::ON},
8669
    {0xfe68, 0xfe68, direction::ON},    {0xfe69, 0xfe6a, direction::ET},
8670
    {0xfe6b, 0xfe6b, direction::ON},    {0xfe70, 0xfe74, direction::AL},
8671
    {0xfe76, 0xfefc, direction::AL},    {0xfeff, 0xfeff, direction::BN},
8672
    {0xff01, 0xff02, direction::ON},    {0xff03, 0xff05, direction::ET},
8673
    {0xff06, 0xff0a, direction::ON},    {0xff0b, 0xff0b, direction::ES},
8674
    {0xff0c, 0xff0c, direction::CS},    {0xff0d, 0xff0d, direction::ES},
8675
    {0xff0e, 0xff0f, direction::CS},    {0xff10, 0xff19, direction::EN},
8676
    {0xff1a, 0xff1a, direction::CS},    {0xff1b, 0xff20, direction::ON},
8677
    {0xff21, 0xff3a, direction::L},     {0xff3b, 0xff40, direction::ON},
8678
    {0xff41, 0xff5a, direction::L},     {0xff5b, 0xff65, direction::ON},
8679
    {0xff66, 0xffbe, direction::L},     {0xffc2, 0xffc7, direction::L},
8680
    {0xffca, 0xffcf, direction::L},     {0xffd2, 0xffd7, direction::L},
8681
    {0xffda, 0xffdc, direction::L},     {0xffe0, 0xffe1, direction::ET},
8682
    {0xffe2, 0xffe4, direction::ON},    {0xffe5, 0xffe6, direction::ET},
8683
    {0xffe8, 0xffee, direction::ON},    {0xfff9, 0xfffd, direction::ON},
8684
    {0x10000, 0x1000b, direction::L},   {0x1000d, 0x10026, direction::L},
8685
    {0x10028, 0x1003a, direction::L},   {0x1003c, 0x1003d, direction::L},
8686
    {0x1003f, 0x1004d, direction::L},   {0x10050, 0x1005d, direction::L},
8687
    {0x10080, 0x100fa, direction::L},   {0x10100, 0x10100, direction::L},
8688
    {0x10101, 0x10101, direction::ON},  {0x10102, 0x10102, direction::L},
8689
    {0x10107, 0x10133, direction::L},   {0x10137, 0x1013f, direction::L},
8690
    {0x10140, 0x1018c, direction::ON},  {0x1018d, 0x1018e, direction::L},
8691
    {0x10190, 0x1019c, direction::ON},  {0x101a0, 0x101a0, direction::ON},
8692
    {0x101d0, 0x101fc, direction::L},   {0x101fd, 0x101fd, direction::NSM},
8693
    {0x10280, 0x1029c, direction::L},   {0x102a0, 0x102d0, direction::L},
8694
    {0x102e0, 0x102e0, direction::NSM}, {0x102e1, 0x102fb, direction::EN},
8695
    {0x10300, 0x10323, direction::L},   {0x1032d, 0x1034a, direction::L},
8696
    {0x10350, 0x10375, direction::L},   {0x10376, 0x1037a, direction::NSM},
8697
    {0x10380, 0x1039d, direction::L},   {0x1039f, 0x103c3, direction::L},
8698
    {0x103c8, 0x103d5, direction::L},   {0x10400, 0x1049d, direction::L},
8699
    {0x104a0, 0x104a9, direction::L},   {0x104b0, 0x104d3, direction::L},
8700
    {0x104d8, 0x104fb, direction::L},   {0x10500, 0x10527, direction::L},
8701
    {0x10530, 0x10563, direction::L},   {0x1056f, 0x1056f, direction::L},
8702
    {0x10600, 0x10736, direction::L},   {0x10740, 0x10755, direction::L},
8703
    {0x10760, 0x10767, direction::L},   {0x10800, 0x10805, direction::R},
8704
    {0x10808, 0x10808, direction::R},   {0x1080a, 0x10835, direction::R},
8705
    {0x10837, 0x10838, direction::R},   {0x1083c, 0x1083c, direction::R},
8706
    {0x1083f, 0x10855, direction::R},   {0x10857, 0x1089e, direction::R},
8707
    {0x108a7, 0x108af, direction::R},   {0x108e0, 0x108f2, direction::R},
8708
    {0x108f4, 0x108f5, direction::R},   {0x108fb, 0x1091b, direction::R},
8709
    {0x1091f, 0x1091f, direction::ON},  {0x10920, 0x10939, direction::R},
8710
    {0x1093f, 0x1093f, direction::R},   {0x10980, 0x109b7, direction::R},
8711
    {0x109bc, 0x109cf, direction::R},   {0x109d2, 0x10a00, direction::R},
8712
    {0x10a01, 0x10a03, direction::NSM}, {0x10a05, 0x10a06, direction::NSM},
8713
    {0x10a0c, 0x10a0f, direction::NSM}, {0x10a10, 0x10a13, direction::R},
8714
    {0x10a15, 0x10a17, direction::R},   {0x10a19, 0x10a35, direction::R},
8715
    {0x10a38, 0x10a3a, direction::NSM}, {0x10a3f, 0x10a3f, direction::NSM},
8716
    {0x10a40, 0x10a48, direction::R},   {0x10a50, 0x10a58, direction::R},
8717
    {0x10a60, 0x10a9f, direction::R},   {0x10ac0, 0x10ae4, direction::R},
8718
    {0x10ae5, 0x10ae6, direction::NSM}, {0x10aeb, 0x10af6, direction::R},
8719
    {0x10b00, 0x10b35, direction::R},   {0x10b39, 0x10b3f, direction::ON},
8720
    {0x10b40, 0x10b55, direction::R},   {0x10b58, 0x10b72, direction::R},
8721
    {0x10b78, 0x10b91, direction::R},   {0x10b99, 0x10b9c, direction::R},
8722
    {0x10ba9, 0x10baf, direction::R},   {0x10c00, 0x10c48, direction::R},
8723
    {0x10c80, 0x10cb2, direction::R},   {0x10cc0, 0x10cf2, direction::R},
8724
    {0x10cfa, 0x10cff, direction::R},   {0x10d00, 0x10d23, direction::AL},
8725
    {0x10d24, 0x10d27, direction::NSM}, {0x10d30, 0x10d39, direction::AN},
8726
    {0x10e60, 0x10e7e, direction::AN},  {0x10e80, 0x10ea9, direction::R},
8727
    {0x10eab, 0x10eac, direction::NSM}, {0x10ead, 0x10ead, direction::R},
8728
    {0x10eb0, 0x10eb1, direction::R},   {0x10f00, 0x10f27, direction::R},
8729
    {0x10f30, 0x10f45, direction::AL},  {0x10f46, 0x10f50, direction::NSM},
8730
    {0x10f51, 0x10f59, direction::AL},  {0x10fb0, 0x10fcb, direction::R},
8731
    {0x10fe0, 0x10ff6, direction::R},   {0x11000, 0x11000, direction::L},
8732
    {0x11001, 0x11001, direction::NSM}, {0x11002, 0x11037, direction::L},
8733
    {0x11038, 0x11046, direction::NSM}, {0x11047, 0x1104d, direction::L},
8734
    {0x11052, 0x11065, direction::ON},  {0x11066, 0x1106f, direction::L},
8735
    {0x1107f, 0x11081, direction::NSM}, {0x11082, 0x110b2, direction::L},
8736
    {0x110b3, 0x110b6, direction::NSM}, {0x110b7, 0x110b8, direction::L},
8737
    {0x110b9, 0x110ba, direction::NSM}, {0x110bb, 0x110c1, direction::L},
8738
    {0x110cd, 0x110cd, direction::L},   {0x110d0, 0x110e8, direction::L},
8739
    {0x110f0, 0x110f9, direction::L},   {0x11100, 0x11102, direction::NSM},
8740
    {0x11103, 0x11126, direction::L},   {0x11127, 0x1112b, direction::NSM},
8741
    {0x1112c, 0x1112c, direction::L},   {0x1112d, 0x11134, direction::NSM},
8742
    {0x11136, 0x11147, direction::L},   {0x11150, 0x11172, direction::L},
8743
    {0x11173, 0x11173, direction::NSM}, {0x11174, 0x11176, direction::L},
8744
    {0x11180, 0x11181, direction::NSM}, {0x11182, 0x111b5, direction::L},
8745
    {0x111b6, 0x111be, direction::NSM}, {0x111bf, 0x111c8, direction::L},
8746
    {0x111c9, 0x111cc, direction::NSM}, {0x111cd, 0x111ce, direction::L},
8747
    {0x111cf, 0x111cf, direction::NSM}, {0x111d0, 0x111df, direction::L},
8748
    {0x111e1, 0x111f4, direction::L},   {0x11200, 0x11211, direction::L},
8749
    {0x11213, 0x1122e, direction::L},   {0x1122f, 0x11231, direction::NSM},
8750
    {0x11232, 0x11233, direction::L},   {0x11234, 0x11234, direction::NSM},
8751
    {0x11235, 0x11235, direction::L},   {0x11236, 0x11237, direction::NSM},
8752
    {0x11238, 0x1123d, direction::L},   {0x1123e, 0x1123e, direction::NSM},
8753
    {0x11280, 0x11286, direction::L},   {0x11288, 0x11288, direction::L},
8754
    {0x1128a, 0x1128d, direction::L},   {0x1128f, 0x1129d, direction::L},
8755
    {0x1129f, 0x112a9, direction::L},   {0x112b0, 0x112de, direction::L},
8756
    {0x112df, 0x112df, direction::NSM}, {0x112e0, 0x112e2, direction::L},
8757
    {0x112e3, 0x112ea, direction::NSM}, {0x112f0, 0x112f9, direction::L},
8758
    {0x11300, 0x11301, direction::NSM}, {0x11302, 0x11303, direction::L},
8759
    {0x11305, 0x1130c, direction::L},   {0x1130f, 0x11310, direction::L},
8760
    {0x11313, 0x11328, direction::L},   {0x1132a, 0x11330, direction::L},
8761
    {0x11332, 0x11333, direction::L},   {0x11335, 0x11339, direction::L},
8762
    {0x1133b, 0x1133c, direction::NSM}, {0x1133d, 0x1133f, direction::L},
8763
    {0x11340, 0x11340, direction::NSM}, {0x11341, 0x11344, direction::L},
8764
    {0x11347, 0x11348, direction::L},   {0x1134b, 0x1134d, direction::L},
8765
    {0x11350, 0x11350, direction::L},   {0x11357, 0x11357, direction::L},
8766
    {0x1135d, 0x11363, direction::L},   {0x11366, 0x1136c, direction::NSM},
8767
    {0x11370, 0x11374, direction::NSM}, {0x11400, 0x11437, direction::L},
8768
    {0x11438, 0x1143f, direction::NSM}, {0x11440, 0x11441, direction::L},
8769
    {0x11442, 0x11444, direction::NSM}, {0x11445, 0x11445, direction::L},
8770
    {0x11446, 0x11446, direction::NSM}, {0x11447, 0x1145b, direction::L},
8771
    {0x1145d, 0x1145d, direction::L},   {0x1145e, 0x1145e, direction::NSM},
8772
    {0x1145f, 0x11461, direction::L},   {0x11480, 0x114b2, direction::L},
8773
    {0x114b3, 0x114b8, direction::NSM}, {0x114b9, 0x114b9, direction::L},
8774
    {0x114ba, 0x114ba, direction::NSM}, {0x114bb, 0x114be, direction::L},
8775
    {0x114bf, 0x114c0, direction::NSM}, {0x114c1, 0x114c1, direction::L},
8776
    {0x114c2, 0x114c3, direction::NSM}, {0x114c4, 0x114c7, direction::L},
8777
    {0x114d0, 0x114d9, direction::L},   {0x11580, 0x115b1, direction::L},
8778
    {0x115b2, 0x115b5, direction::NSM}, {0x115b8, 0x115bb, direction::L},
8779
    {0x115bc, 0x115bd, direction::NSM}, {0x115be, 0x115be, direction::L},
8780
    {0x115bf, 0x115c0, direction::NSM}, {0x115c1, 0x115db, direction::L},
8781
    {0x115dc, 0x115dd, direction::NSM}, {0x11600, 0x11632, direction::L},
8782
    {0x11633, 0x1163a, direction::NSM}, {0x1163b, 0x1163c, direction::L},
8783
    {0x1163d, 0x1163d, direction::NSM}, {0x1163e, 0x1163e, direction::L},
8784
    {0x1163f, 0x11640, direction::NSM}, {0x11641, 0x11644, direction::L},
8785
    {0x11650, 0x11659, direction::L},   {0x11660, 0x1166c, direction::ON},
8786
    {0x11680, 0x116aa, direction::L},   {0x116ab, 0x116ab, direction::NSM},
8787
    {0x116ac, 0x116ac, direction::L},   {0x116ad, 0x116ad, direction::NSM},
8788
    {0x116ae, 0x116af, direction::L},   {0x116b0, 0x116b5, direction::NSM},
8789
    {0x116b6, 0x116b6, direction::L},   {0x116b7, 0x116b7, direction::NSM},
8790
    {0x116b8, 0x116b8, direction::L},   {0x116c0, 0x116c9, direction::L},
8791
    {0x11700, 0x1171a, direction::L},   {0x1171d, 0x1171f, direction::NSM},
8792
    {0x11720, 0x11721, direction::L},   {0x11722, 0x11725, direction::NSM},
8793
    {0x11726, 0x11726, direction::L},   {0x11727, 0x1172b, direction::NSM},
8794
    {0x11730, 0x1173f, direction::L},   {0x11800, 0x1182e, direction::L},
8795
    {0x1182f, 0x11837, direction::NSM}, {0x11838, 0x11838, direction::L},
8796
    {0x11839, 0x1183a, direction::NSM}, {0x1183b, 0x1183b, direction::L},
8797
    {0x118a0, 0x118f2, direction::L},   {0x118ff, 0x11906, direction::L},
8798
    {0x11909, 0x11909, direction::L},   {0x1190c, 0x11913, direction::L},
8799
    {0x11915, 0x11916, direction::L},   {0x11918, 0x11935, direction::L},
8800
    {0x11937, 0x11938, direction::L},   {0x1193b, 0x1193c, direction::NSM},
8801
    {0x1193d, 0x1193d, direction::L},   {0x1193e, 0x1193e, direction::NSM},
8802
    {0x1193f, 0x11942, direction::L},   {0x11943, 0x11943, direction::NSM},
8803
    {0x11944, 0x11946, direction::L},   {0x11950, 0x11959, direction::L},
8804
    {0x119a0, 0x119a7, direction::L},   {0x119aa, 0x119d3, direction::L},
8805
    {0x119d4, 0x119d7, direction::NSM}, {0x119da, 0x119db, direction::NSM},
8806
    {0x119dc, 0x119df, direction::L},   {0x119e0, 0x119e0, direction::NSM},
8807
    {0x119e1, 0x119e4, direction::L},   {0x11a00, 0x11a00, direction::L},
8808
    {0x11a01, 0x11a06, direction::NSM}, {0x11a07, 0x11a08, direction::L},
8809
    {0x11a09, 0x11a0a, direction::NSM}, {0x11a0b, 0x11a32, direction::L},
8810
    {0x11a33, 0x11a38, direction::NSM}, {0x11a39, 0x11a3a, direction::L},
8811
    {0x11a3b, 0x11a3e, direction::NSM}, {0x11a3f, 0x11a46, direction::L},
8812
    {0x11a47, 0x11a47, direction::NSM}, {0x11a50, 0x11a50, direction::L},
8813
    {0x11a51, 0x11a56, direction::NSM}, {0x11a57, 0x11a58, direction::L},
8814
    {0x11a59, 0x11a5b, direction::NSM}, {0x11a5c, 0x11a89, direction::L},
8815
    {0x11a8a, 0x11a96, direction::NSM}, {0x11a97, 0x11a97, direction::L},
8816
    {0x11a98, 0x11a99, direction::NSM}, {0x11a9a, 0x11aa2, direction::L},
8817
    {0x11ac0, 0x11af8, direction::L},   {0x11c00, 0x11c08, direction::L},
8818
    {0x11c0a, 0x11c2f, direction::L},   {0x11c30, 0x11c36, direction::NSM},
8819
    {0x11c38, 0x11c3d, direction::NSM}, {0x11c3e, 0x11c45, direction::L},
8820
    {0x11c50, 0x11c6c, direction::L},   {0x11c70, 0x11c8f, direction::L},
8821
    {0x11c92, 0x11ca7, direction::NSM}, {0x11ca9, 0x11ca9, direction::L},
8822
    {0x11caa, 0x11cb0, direction::NSM}, {0x11cb1, 0x11cb1, direction::L},
8823
    {0x11cb2, 0x11cb3, direction::NSM}, {0x11cb4, 0x11cb4, direction::L},
8824
    {0x11cb5, 0x11cb6, direction::NSM}, {0x11d00, 0x11d06, direction::L},
8825
    {0x11d08, 0x11d09, direction::L},   {0x11d0b, 0x11d30, direction::L},
8826
    {0x11d31, 0x11d36, direction::NSM}, {0x11d3a, 0x11d3a, direction::NSM},
8827
    {0x11d3c, 0x11d3d, direction::NSM}, {0x11d3f, 0x11d45, direction::NSM},
8828
    {0x11d46, 0x11d46, direction::L},   {0x11d47, 0x11d47, direction::NSM},
8829
    {0x11d50, 0x11d59, direction::L},   {0x11d60, 0x11d65, direction::L},
8830
    {0x11d67, 0x11d68, direction::L},   {0x11d6a, 0x11d8e, direction::L},
8831
    {0x11d90, 0x11d91, direction::NSM}, {0x11d93, 0x11d94, direction::L},
8832
    {0x11d95, 0x11d95, direction::NSM}, {0x11d96, 0x11d96, direction::L},
8833
    {0x11d97, 0x11d97, direction::NSM}, {0x11d98, 0x11d98, direction::L},
8834
    {0x11da0, 0x11da9, direction::L},   {0x11ee0, 0x11ef2, direction::L},
8835
    {0x11ef3, 0x11ef4, direction::NSM}, {0x11ef5, 0x11ef8, direction::L},
8836
    {0x11fb0, 0x11fb0, direction::L},   {0x11fc0, 0x11fd4, direction::L},
8837
    {0x11fd5, 0x11fdc, direction::ON},  {0x11fdd, 0x11fe0, direction::ET},
8838
    {0x11fe1, 0x11ff1, direction::ON},  {0x11fff, 0x12399, direction::L},
8839
    {0x12400, 0x1246e, direction::L},   {0x12470, 0x12474, direction::L},
8840
    {0x12480, 0x12543, direction::L},   {0x13000, 0x1342e, direction::L},
8841
    {0x13430, 0x13438, direction::L},   {0x14400, 0x14646, direction::L},
8842
    {0x16800, 0x16a38, direction::L},   {0x16a40, 0x16a5e, direction::L},
8843
    {0x16a60, 0x16a69, direction::L},   {0x16a6e, 0x16a6f, direction::L},
8844
    {0x16ad0, 0x16aed, direction::L},   {0x16af0, 0x16af4, direction::NSM},
8845
    {0x16af5, 0x16af5, direction::L},   {0x16b00, 0x16b2f, direction::L},
8846
    {0x16b30, 0x16b36, direction::NSM}, {0x16b37, 0x16b45, direction::L},
8847
    {0x16b50, 0x16b59, direction::L},   {0x16b5b, 0x16b61, direction::L},
8848
    {0x16b63, 0x16b77, direction::L},   {0x16b7d, 0x16b8f, direction::L},
8849
    {0x16e40, 0x16e9a, direction::L},   {0x16f00, 0x16f4a, direction::L},
8850
    {0x16f4f, 0x16f4f, direction::NSM}, {0x16f50, 0x16f87, direction::L},
8851
    {0x16f8f, 0x16f92, direction::NSM}, {0x16f93, 0x16f9f, direction::L},
8852
    {0x16fe0, 0x16fe1, direction::L},   {0x16fe2, 0x16fe2, direction::ON},
8853
    {0x16fe3, 0x16fe3, direction::L},   {0x16fe4, 0x16fe4, direction::NSM},
8854
    {0x16ff0, 0x16ff1, direction::L},   {0x17000, 0x187f7, direction::L},
8855
    {0x18800, 0x18cd5, direction::L},   {0x18d00, 0x18d08, direction::L},
8856
    {0x1b000, 0x1b11e, direction::L},   {0x1b150, 0x1b152, direction::L},
8857
    {0x1b164, 0x1b167, direction::L},   {0x1b170, 0x1b2fb, direction::L},
8858
    {0x1bc00, 0x1bc6a, direction::L},   {0x1bc70, 0x1bc7c, direction::L},
8859
    {0x1bc80, 0x1bc88, direction::L},   {0x1bc90, 0x1bc99, direction::L},
8860
    {0x1bc9c, 0x1bc9c, direction::L},   {0x1bc9d, 0x1bc9e, direction::NSM},
8861
    {0x1bc9f, 0x1bc9f, direction::L},   {0x1bca0, 0x1bca3, direction::BN},
8862
    {0x1d000, 0x1d0f5, direction::L},   {0x1d100, 0x1d126, direction::L},
8863
    {0x1d129, 0x1d166, direction::L},   {0x1d167, 0x1d169, direction::NSM},
8864
    {0x1d16a, 0x1d172, direction::L},   {0x1d173, 0x1d17a, direction::BN},
8865
    {0x1d17b, 0x1d182, direction::NSM}, {0x1d183, 0x1d184, direction::L},
8866
    {0x1d185, 0x1d18b, direction::NSM}, {0x1d18c, 0x1d1a9, direction::L},
8867
    {0x1d1aa, 0x1d1ad, direction::NSM}, {0x1d1ae, 0x1d1e8, direction::L},
8868
    {0x1d200, 0x1d241, direction::ON},  {0x1d242, 0x1d244, direction::NSM},
8869
    {0x1d245, 0x1d245, direction::ON},  {0x1d2e0, 0x1d2f3, direction::L},
8870
    {0x1d300, 0x1d356, direction::ON},  {0x1d360, 0x1d378, direction::L},
8871
    {0x1d400, 0x1d454, direction::L},   {0x1d456, 0x1d49c, direction::L},
8872
    {0x1d49e, 0x1d49f, direction::L},   {0x1d4a2, 0x1d4a2, direction::L},
8873
    {0x1d4a5, 0x1d4a6, direction::L},   {0x1d4a9, 0x1d4ac, direction::L},
8874
    {0x1d4ae, 0x1d4b9, direction::L},   {0x1d4bb, 0x1d4bb, direction::L},
8875
    {0x1d4bd, 0x1d4c3, direction::L},   {0x1d4c5, 0x1d505, direction::L},
8876
    {0x1d507, 0x1d50a, direction::L},   {0x1d50d, 0x1d514, direction::L},
8877
    {0x1d516, 0x1d51c, direction::L},   {0x1d51e, 0x1d539, direction::L},
8878
    {0x1d53b, 0x1d53e, direction::L},   {0x1d540, 0x1d544, direction::L},
8879
    {0x1d546, 0x1d546, direction::L},   {0x1d54a, 0x1d550, direction::L},
8880
    {0x1d552, 0x1d6a5, direction::L},   {0x1d6a8, 0x1d6da, direction::L},
8881
    {0x1d6db, 0x1d6db, direction::ON},  {0x1d6dc, 0x1d714, direction::L},
8882
    {0x1d715, 0x1d715, direction::ON},  {0x1d716, 0x1d74e, direction::L},
8883
    {0x1d74f, 0x1d74f, direction::ON},  {0x1d750, 0x1d788, direction::L},
8884
    {0x1d789, 0x1d789, direction::ON},  {0x1d78a, 0x1d7c2, direction::L},
8885
    {0x1d7c3, 0x1d7c3, direction::ON},  {0x1d7c4, 0x1d7cb, direction::L},
8886
    {0x1d7ce, 0x1d7ff, direction::EN},  {0x1d800, 0x1d9ff, direction::L},
8887
    {0x1da00, 0x1da36, direction::NSM}, {0x1da37, 0x1da3a, direction::L},
8888
    {0x1da3b, 0x1da6c, direction::NSM}, {0x1da6d, 0x1da74, direction::L},
8889
    {0x1da75, 0x1da75, direction::NSM}, {0x1da76, 0x1da83, direction::L},
8890
    {0x1da84, 0x1da84, direction::NSM}, {0x1da85, 0x1da8b, direction::L},
8891
    {0x1da9b, 0x1da9f, direction::NSM}, {0x1daa1, 0x1daaf, direction::NSM},
8892
    {0x1e000, 0x1e006, direction::NSM}, {0x1e008, 0x1e018, direction::NSM},
8893
    {0x1e01b, 0x1e021, direction::NSM}, {0x1e023, 0x1e024, direction::NSM},
8894
    {0x1e026, 0x1e02a, direction::NSM}, {0x1e100, 0x1e12c, direction::L},
8895
    {0x1e130, 0x1e136, direction::NSM}, {0x1e137, 0x1e13d, direction::L},
8896
    {0x1e140, 0x1e149, direction::L},   {0x1e14e, 0x1e14f, direction::L},
8897
    {0x1e2c0, 0x1e2eb, direction::L},   {0x1e2ec, 0x1e2ef, direction::NSM},
8898
    {0x1e2f0, 0x1e2f9, direction::L},   {0x1e2ff, 0x1e2ff, direction::ET},
8899
    {0x1e800, 0x1e8c4, direction::R},   {0x1e8c7, 0x1e8cf, direction::R},
8900
    {0x1e8d0, 0x1e8d6, direction::NSM}, {0x1e900, 0x1e943, direction::R},
8901
    {0x1e944, 0x1e94a, direction::NSM}, {0x1e94b, 0x1e94b, direction::R},
8902
    {0x1e950, 0x1e959, direction::R},   {0x1e95e, 0x1e95f, direction::R},
8903
    {0x1ec71, 0x1ecb4, direction::AL},  {0x1ed01, 0x1ed3d, direction::AL},
8904
    {0x1ee00, 0x1ee03, direction::AL},  {0x1ee05, 0x1ee1f, direction::AL},
8905
    {0x1ee21, 0x1ee22, direction::AL},  {0x1ee24, 0x1ee24, direction::AL},
8906
    {0x1ee27, 0x1ee27, direction::AL},  {0x1ee29, 0x1ee32, direction::AL},
8907
    {0x1ee34, 0x1ee37, direction::AL},  {0x1ee39, 0x1ee39, direction::AL},
8908
    {0x1ee3b, 0x1ee3b, direction::AL},  {0x1ee42, 0x1ee42, direction::AL},
8909
    {0x1ee47, 0x1ee47, direction::AL},  {0x1ee49, 0x1ee49, direction::AL},
8910
    {0x1ee4b, 0x1ee4b, direction::AL},  {0x1ee4d, 0x1ee4f, direction::AL},
8911
    {0x1ee51, 0x1ee52, direction::AL},  {0x1ee54, 0x1ee54, direction::AL},
8912
    {0x1ee57, 0x1ee57, direction::AL},  {0x1ee59, 0x1ee59, direction::AL},
8913
    {0x1ee5b, 0x1ee5b, direction::AL},  {0x1ee5d, 0x1ee5d, direction::AL},
8914
    {0x1ee5f, 0x1ee5f, direction::AL},  {0x1ee61, 0x1ee62, direction::AL},
8915
    {0x1ee64, 0x1ee64, direction::AL},  {0x1ee67, 0x1ee6a, direction::AL},
8916
    {0x1ee6c, 0x1ee72, direction::AL},  {0x1ee74, 0x1ee77, direction::AL},
8917
    {0x1ee79, 0x1ee7c, direction::AL},  {0x1ee7e, 0x1ee7e, direction::AL},
8918
    {0x1ee80, 0x1ee89, direction::AL},  {0x1ee8b, 0x1ee9b, direction::AL},
8919
    {0x1eea1, 0x1eea3, direction::AL},  {0x1eea5, 0x1eea9, direction::AL},
8920
    {0x1eeab, 0x1eebb, direction::AL},  {0x1eef0, 0x1eef1, direction::ON},
8921
    {0x1f000, 0x1f02b, direction::ON},  {0x1f030, 0x1f093, direction::ON},
8922
    {0x1f0a0, 0x1f0ae, direction::ON},  {0x1f0b1, 0x1f0bf, direction::ON},
8923
    {0x1f0c1, 0x1f0cf, direction::ON},  {0x1f0d1, 0x1f0f5, direction::ON},
8924
    {0x1f100, 0x1f10a, direction::EN},  {0x1f10b, 0x1f10f, direction::ON},
8925
    {0x1f110, 0x1f12e, direction::L},   {0x1f12f, 0x1f12f, direction::ON},
8926
    {0x1f130, 0x1f169, direction::L},   {0x1f16a, 0x1f16f, direction::ON},
8927
    {0x1f170, 0x1f1ac, direction::L},   {0x1f1ad, 0x1f1ad, direction::ON},
8928
    {0x1f1e6, 0x1f202, direction::L},   {0x1f210, 0x1f23b, direction::L},
8929
    {0x1f240, 0x1f248, direction::L},   {0x1f250, 0x1f251, direction::L},
8930
    {0x1f260, 0x1f265, direction::ON},  {0x1f300, 0x1f6d7, direction::ON},
8931
    {0x1f6e0, 0x1f6ec, direction::ON},  {0x1f6f0, 0x1f6fc, direction::ON},
8932
    {0x1f700, 0x1f773, direction::ON},  {0x1f780, 0x1f7d8, direction::ON},
8933
    {0x1f7e0, 0x1f7eb, direction::ON},  {0x1f800, 0x1f80b, direction::ON},
8934
    {0x1f810, 0x1f847, direction::ON},  {0x1f850, 0x1f859, direction::ON},
8935
    {0x1f860, 0x1f887, direction::ON},  {0x1f890, 0x1f8ad, direction::ON},
8936
    {0x1f8b0, 0x1f8b1, direction::ON},  {0x1f900, 0x1f978, direction::ON},
8937
    {0x1f97a, 0x1f9cb, direction::ON},  {0x1f9cd, 0x1fa53, direction::ON},
8938
    {0x1fa60, 0x1fa6d, direction::ON},  {0x1fa70, 0x1fa74, direction::ON},
8939
    {0x1fa78, 0x1fa7a, direction::ON},  {0x1fa80, 0x1fa86, direction::ON},
8940
    {0x1fa90, 0x1faa8, direction::ON},  {0x1fab0, 0x1fab6, direction::ON},
8941
    {0x1fac0, 0x1fac2, direction::ON},  {0x1fad0, 0x1fad6, direction::ON},
8942
    {0x1fb00, 0x1fb92, direction::ON},  {0x1fb94, 0x1fbca, direction::ON},
8943
    {0x1fbf0, 0x1fbf9, direction::EN},  {0x20000, 0x2a6dd, direction::L},
8944
    {0x2a700, 0x2b734, direction::L},   {0x2b740, 0x2b81d, direction::L},
8945
    {0x2b820, 0x2cea1, direction::L},   {0x2ceb0, 0x2ebe0, direction::L},
8946
    {0x2f800, 0x2fa1d, direction::L},   {0x30000, 0x3134a, direction::L},
8947
    {0xe0001, 0xe0001, direction::BN},  {0xe0020, 0xe007f, direction::BN},
8948
    {0xe0100, 0xe01ef, direction::NSM}, {0xf0000, 0xffffd, direction::L},
8949
    {0x100000, 0x10fffd, direction::L}};
8950
8951
// CheckJoiners and CheckBidi are true for URL specification.
8952
8953
242k
inline static direction find_direction(uint32_t code_point) noexcept {
8954
242k
  auto it = std::lower_bound(
8955
242k
      std::begin(dir_table), std::end(dir_table), code_point,
8956
2.47M
      [](const directions& d, uint32_t c) { return d.final_code < c; });
8957
8958
  // next check is almost surely in vain, but we use it for safety.
8959
242k
  if (it == std::end(dir_table)) {
8960
0
    return direction::NONE;
8961
0
  }
8962
  // We have that d.final_code >= c.
8963
242k
  if (code_point >= it->start_code) {
8964
241k
    return it->direct;
8965
241k
  }
8966
919
  return direction::NONE;
8967
242k
}
8968
8969
inline static size_t find_last_not_of_nsm(
8970
34.0k
    const std::u32string_view label) noexcept {
8971
35.0k
  for (int i = label.size() - 1; i >= 0; i--)
8972
35.0k
    if (find_direction(label[i]) != direction::NSM) return i;
8973
8974
0
  return std::u32string_view::npos;
8975
34.0k
}
8976
8977
// An RTL label is a label that contains at least one character of type R, AL,
8978
// or AN. https://www.rfc-editor.org/rfc/rfc5893#section-2
8979
34.0k
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
8980
34.0k
  const size_t mask =
8981
34.0k
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
8982
8983
34.0k
  size_t directions = 0;
8984
230k
  for (size_t i = 0; i < label.size(); i++) {
8985
196k
    directions |= 1u << find_direction(label[i]);
8986
196k
  }
8987
34.0k
  return (directions & mask) != 0;
8988
34.0k
}
8989
8990
36.2k
bool is_label_valid(const std::u32string_view label) {
8991
36.2k
  if (label.empty()) {
8992
0
    return true;
8993
0
  }
8994
8995
  ///////////////
8996
  // We have a normalization step which ensures that we are in NFC.
8997
  // If we receive punycode, we normalize and check that the normalized
8998
  // version matches the original.
8999
  // --------------------------------------
9000
  // The label must be in Unicode Normalization Form NFC.
9001
9002
  // Current URL standard indicatest that CheckHyphens is set to false.
9003
  // ---------------------------------------
9004
  // If CheckHyphens, the label must not contain a U+002D HYPHEN-MINUS character
9005
  // in both the third and fourth positions. If CheckHyphens, the label must
9006
  // neither begin nor end with a U+002D HYPHEN-MINUS character.
9007
9008
  // This is not necessary because we segment the
9009
  // labels by '.'.
9010
  // ---------------------------------------
9011
  // The label must not contain a U+002E ( . ) FULL STOP.
9012
  // if (label.find('.') != std::string_view::npos) return false;
9013
9014
  // The label must not begin with a combining mark, that is:
9015
  // General_Category=Mark.
9016
36.2k
  constexpr static uint32_t combining[] = {
9017
36.2k
      0x300,   0x301,   0x302,   0x303,   0x304,   0x305,   0x306,   0x307,
9018
36.2k
      0x308,   0x309,   0x30a,   0x30b,   0x30c,   0x30d,   0x30e,   0x30f,
9019
36.2k
      0x310,   0x311,   0x312,   0x313,   0x314,   0x315,   0x316,   0x317,
9020
36.2k
      0x318,   0x319,   0x31a,   0x31b,   0x31c,   0x31d,   0x31e,   0x31f,
9021
36.2k
      0x320,   0x321,   0x322,   0x323,   0x324,   0x325,   0x326,   0x327,
9022
36.2k
      0x328,   0x329,   0x32a,   0x32b,   0x32c,   0x32d,   0x32e,   0x32f,
9023
36.2k
      0x330,   0x331,   0x332,   0x333,   0x334,   0x335,   0x336,   0x337,
9024
36.2k
      0x338,   0x339,   0x33a,   0x33b,   0x33c,   0x33d,   0x33e,   0x33f,
9025
36.2k
      0x340,   0x341,   0x342,   0x343,   0x344,   0x345,   0x346,   0x347,
9026
36.2k
      0x348,   0x349,   0x34a,   0x34b,   0x34c,   0x34d,   0x34e,   0x34f,
9027
36.2k
      0x350,   0x351,   0x352,   0x353,   0x354,   0x355,   0x356,   0x357,
9028
36.2k
      0x358,   0x359,   0x35a,   0x35b,   0x35c,   0x35d,   0x35e,   0x35f,
9029
36.2k
      0x360,   0x361,   0x362,   0x363,   0x364,   0x365,   0x366,   0x367,
9030
36.2k
      0x368,   0x369,   0x36a,   0x36b,   0x36c,   0x36d,   0x36e,   0x36f,
9031
36.2k
      0x483,   0x484,   0x485,   0x486,   0x487,   0x488,   0x489,   0x591,
9032
36.2k
      0x592,   0x593,   0x594,   0x595,   0x596,   0x597,   0x598,   0x599,
9033
36.2k
      0x59a,   0x59b,   0x59c,   0x59d,   0x59e,   0x59f,   0x5a0,   0x5a1,
9034
36.2k
      0x5a2,   0x5a3,   0x5a4,   0x5a5,   0x5a6,   0x5a7,   0x5a8,   0x5a9,
9035
36.2k
      0x5aa,   0x5ab,   0x5ac,   0x5ad,   0x5ae,   0x5af,   0x5b0,   0x5b1,
9036
36.2k
      0x5b2,   0x5b3,   0x5b4,   0x5b5,   0x5b6,   0x5b7,   0x5b8,   0x5b9,
9037
36.2k
      0x5ba,   0x5bb,   0x5bc,   0x5bd,   0x5bf,   0x5c1,   0x5c2,   0x5c4,
9038
36.2k
      0x5c5,   0x5c7,   0x610,   0x611,   0x612,   0x613,   0x614,   0x615,
9039
36.2k
      0x616,   0x617,   0x618,   0x619,   0x61a,   0x64b,   0x64c,   0x64d,
9040
36.2k
      0x64e,   0x64f,   0x650,   0x651,   0x652,   0x653,   0x654,   0x655,
9041
36.2k
      0x656,   0x657,   0x658,   0x659,   0x65a,   0x65b,   0x65c,   0x65d,
9042
36.2k
      0x65e,   0x65f,   0x670,   0x6d6,   0x6d7,   0x6d8,   0x6d9,   0x6da,
9043
36.2k
      0x6db,   0x6dc,   0x6df,   0x6e0,   0x6e1,   0x6e2,   0x6e3,   0x6e4,
9044
36.2k
      0x6e7,   0x6e8,   0x6ea,   0x6eb,   0x6ec,   0x6ed,   0x711,   0x730,
9045
36.2k
      0x731,   0x732,   0x733,   0x734,   0x735,   0x736,   0x737,   0x738,
9046
36.2k
      0x739,   0x73a,   0x73b,   0x73c,   0x73d,   0x73e,   0x73f,   0x740,
9047
36.2k
      0x741,   0x742,   0x743,   0x744,   0x745,   0x746,   0x747,   0x748,
9048
36.2k
      0x749,   0x74a,   0x7a6,   0x7a7,   0x7a8,   0x7a9,   0x7aa,   0x7ab,
9049
36.2k
      0x7ac,   0x7ad,   0x7ae,   0x7af,   0x7b0,   0x7eb,   0x7ec,   0x7ed,
9050
36.2k
      0x7ee,   0x7ef,   0x7f0,   0x7f1,   0x7f2,   0x7f3,   0x7fd,   0x816,
9051
36.2k
      0x817,   0x818,   0x819,   0x81b,   0x81c,   0x81d,   0x81e,   0x81f,
9052
36.2k
      0x820,   0x821,   0x822,   0x823,   0x825,   0x826,   0x827,   0x829,
9053
36.2k
      0x82a,   0x82b,   0x82c,   0x82d,   0x859,   0x85a,   0x85b,   0x8d3,
9054
36.2k
      0x8d4,   0x8d5,   0x8d6,   0x8d7,   0x8d8,   0x8d9,   0x8da,   0x8db,
9055
36.2k
      0x8dc,   0x8dd,   0x8de,   0x8df,   0x8e0,   0x8e1,   0x8e3,   0x8e4,
9056
36.2k
      0x8e5,   0x8e6,   0x8e7,   0x8e8,   0x8e9,   0x8ea,   0x8eb,   0x8ec,
9057
36.2k
      0x8ed,   0x8ee,   0x8ef,   0x8f0,   0x8f1,   0x8f2,   0x8f3,   0x8f4,
9058
36.2k
      0x8f5,   0x8f6,   0x8f7,   0x8f8,   0x8f9,   0x8fa,   0x8fb,   0x8fc,
9059
36.2k
      0x8fd,   0x8fe,   0x8ff,   0x900,   0x901,   0x902,   0x903,   0x93a,
9060
36.2k
      0x93b,   0x93c,   0x93e,   0x93f,   0x940,   0x941,   0x942,   0x943,
9061
36.2k
      0x944,   0x945,   0x946,   0x947,   0x948,   0x949,   0x94a,   0x94b,
9062
36.2k
      0x94c,   0x94d,   0x94e,   0x94f,   0x951,   0x952,   0x953,   0x954,
9063
36.2k
      0x955,   0x956,   0x957,   0x962,   0x963,   0x981,   0x982,   0x983,
9064
36.2k
      0x9bc,   0x9be,   0x9bf,   0x9c0,   0x9c1,   0x9c2,   0x9c3,   0x9c4,
9065
36.2k
      0x9c7,   0x9c8,   0x9cb,   0x9cc,   0x9cd,   0x9d7,   0x9e2,   0x9e3,
9066
36.2k
      0x9fe,   0xa01,   0xa02,   0xa03,   0xa3c,   0xa3e,   0xa3f,   0xa40,
9067
36.2k
      0xa41,   0xa42,   0xa47,   0xa48,   0xa4b,   0xa4c,   0xa4d,   0xa51,
9068
36.2k
      0xa70,   0xa71,   0xa75,   0xa81,   0xa82,   0xa83,   0xabc,   0xabe,
9069
36.2k
      0xabf,   0xac0,   0xac1,   0xac2,   0xac3,   0xac4,   0xac5,   0xac7,
9070
36.2k
      0xac8,   0xac9,   0xacb,   0xacc,   0xacd,   0xae2,   0xae3,   0xafa,
9071
36.2k
      0xafb,   0xafc,   0xafd,   0xafe,   0xaff,   0xb01,   0xb02,   0xb03,
9072
36.2k
      0xb3c,   0xb3e,   0xb3f,   0xb40,   0xb41,   0xb42,   0xb43,   0xb44,
9073
36.2k
      0xb47,   0xb48,   0xb4b,   0xb4c,   0xb4d,   0xb55,   0xb56,   0xb57,
9074
36.2k
      0xb62,   0xb63,   0xb82,   0xbbe,   0xbbf,   0xbc0,   0xbc1,   0xbc2,
9075
36.2k
      0xbc6,   0xbc7,   0xbc8,   0xbca,   0xbcb,   0xbcc,   0xbcd,   0xbd7,
9076
36.2k
      0xc00,   0xc01,   0xc02,   0xc03,   0xc04,   0xc3e,   0xc3f,   0xc40,
9077
36.2k
      0xc41,   0xc42,   0xc43,   0xc44,   0xc46,   0xc47,   0xc48,   0xc4a,
9078
36.2k
      0xc4b,   0xc4c,   0xc4d,   0xc55,   0xc56,   0xc62,   0xc63,   0xc81,
9079
36.2k
      0xc82,   0xc83,   0xcbc,   0xcbe,   0xcbf,   0xcc0,   0xcc1,   0xcc2,
9080
36.2k
      0xcc3,   0xcc4,   0xcc6,   0xcc7,   0xcc8,   0xcca,   0xccb,   0xccc,
9081
36.2k
      0xccd,   0xcd5,   0xcd6,   0xce2,   0xce3,   0xd00,   0xd01,   0xd02,
9082
36.2k
      0xd03,   0xd3b,   0xd3c,   0xd3e,   0xd3f,   0xd40,   0xd41,   0xd42,
9083
36.2k
      0xd43,   0xd44,   0xd46,   0xd47,   0xd48,   0xd4a,   0xd4b,   0xd4c,
9084
36.2k
      0xd4d,   0xd57,   0xd62,   0xd63,   0xd81,   0xd82,   0xd83,   0xdca,
9085
36.2k
      0xdcf,   0xdd0,   0xdd1,   0xdd2,   0xdd3,   0xdd4,   0xdd6,   0xdd8,
9086
36.2k
      0xdd9,   0xdda,   0xddb,   0xddc,   0xddd,   0xdde,   0xddf,   0xdf2,
9087
36.2k
      0xdf3,   0xe31,   0xe34,   0xe35,   0xe36,   0xe37,   0xe38,   0xe39,
9088
36.2k
      0xe3a,   0xe47,   0xe48,   0xe49,   0xe4a,   0xe4b,   0xe4c,   0xe4d,
9089
36.2k
      0xe4e,   0xeb1,   0xeb4,   0xeb5,   0xeb6,   0xeb7,   0xeb8,   0xeb9,
9090
36.2k
      0xeba,   0xebb,   0xebc,   0xec8,   0xec9,   0xeca,   0xecb,   0xecc,
9091
36.2k
      0xecd,   0xf18,   0xf19,   0xf35,   0xf37,   0xf39,   0xf3e,   0xf3f,
9092
36.2k
      0xf71,   0xf72,   0xf73,   0xf74,   0xf75,   0xf76,   0xf77,   0xf78,
9093
36.2k
      0xf79,   0xf7a,   0xf7b,   0xf7c,   0xf7d,   0xf7e,   0xf7f,   0xf80,
9094
36.2k
      0xf81,   0xf82,   0xf83,   0xf84,   0xf86,   0xf87,   0xf8d,   0xf8e,
9095
36.2k
      0xf8f,   0xf90,   0xf91,   0xf92,   0xf93,   0xf94,   0xf95,   0xf96,
9096
36.2k
      0xf97,   0xf99,   0xf9a,   0xf9b,   0xf9c,   0xf9d,   0xf9e,   0xf9f,
9097
36.2k
      0xfa0,   0xfa1,   0xfa2,   0xfa3,   0xfa4,   0xfa5,   0xfa6,   0xfa7,
9098
36.2k
      0xfa8,   0xfa9,   0xfaa,   0xfab,   0xfac,   0xfad,   0xfae,   0xfaf,
9099
36.2k
      0xfb0,   0xfb1,   0xfb2,   0xfb3,   0xfb4,   0xfb5,   0xfb6,   0xfb7,
9100
36.2k
      0xfb8,   0xfb9,   0xfba,   0xfbb,   0xfbc,   0xfc6,   0x102b,  0x102c,
9101
36.2k
      0x102d,  0x102e,  0x102f,  0x1030,  0x1031,  0x1032,  0x1033,  0x1034,
9102
36.2k
      0x1035,  0x1036,  0x1037,  0x1038,  0x1039,  0x103a,  0x103b,  0x103c,
9103
36.2k
      0x103d,  0x103e,  0x1056,  0x1057,  0x1058,  0x1059,  0x105e,  0x105f,
9104
36.2k
      0x1060,  0x1062,  0x1063,  0x1064,  0x1067,  0x1068,  0x1069,  0x106a,
9105
36.2k
      0x106b,  0x106c,  0x106d,  0x1071,  0x1072,  0x1073,  0x1074,  0x1082,
9106
36.2k
      0x1083,  0x1084,  0x1085,  0x1086,  0x1087,  0x1088,  0x1089,  0x108a,
9107
36.2k
      0x108b,  0x108c,  0x108d,  0x108f,  0x109a,  0x109b,  0x109c,  0x109d,
9108
36.2k
      0x135d,  0x135e,  0x135f,  0x1712,  0x1713,  0x1714,  0x1732,  0x1733,
9109
36.2k
      0x1734,  0x1752,  0x1753,  0x1772,  0x1773,  0x17b4,  0x17b5,  0x17b6,
9110
36.2k
      0x17b7,  0x17b8,  0x17b9,  0x17ba,  0x17bb,  0x17bc,  0x17bd,  0x17be,
9111
36.2k
      0x17bf,  0x17c0,  0x17c1,  0x17c2,  0x17c3,  0x17c4,  0x17c5,  0x17c6,
9112
36.2k
      0x17c7,  0x17c8,  0x17c9,  0x17ca,  0x17cb,  0x17cc,  0x17cd,  0x17ce,
9113
36.2k
      0x17cf,  0x17d0,  0x17d1,  0x17d2,  0x17d3,  0x17dd,  0x180b,  0x180c,
9114
36.2k
      0x180d,  0x1885,  0x1886,  0x18a9,  0x1920,  0x1921,  0x1922,  0x1923,
9115
36.2k
      0x1924,  0x1925,  0x1926,  0x1927,  0x1928,  0x1929,  0x192a,  0x192b,
9116
36.2k
      0x1930,  0x1931,  0x1932,  0x1933,  0x1934,  0x1935,  0x1936,  0x1937,
9117
36.2k
      0x1938,  0x1939,  0x193a,  0x193b,  0x1a17,  0x1a18,  0x1a19,  0x1a1a,
9118
36.2k
      0x1a1b,  0x1a55,  0x1a56,  0x1a57,  0x1a58,  0x1a59,  0x1a5a,  0x1a5b,
9119
36.2k
      0x1a5c,  0x1a5d,  0x1a5e,  0x1a60,  0x1a61,  0x1a62,  0x1a63,  0x1a64,
9120
36.2k
      0x1a65,  0x1a66,  0x1a67,  0x1a68,  0x1a69,  0x1a6a,  0x1a6b,  0x1a6c,
9121
36.2k
      0x1a6d,  0x1a6e,  0x1a6f,  0x1a70,  0x1a71,  0x1a72,  0x1a73,  0x1a74,
9122
36.2k
      0x1a75,  0x1a76,  0x1a77,  0x1a78,  0x1a79,  0x1a7a,  0x1a7b,  0x1a7c,
9123
36.2k
      0x1a7f,  0x1ab0,  0x1ab1,  0x1ab2,  0x1ab3,  0x1ab4,  0x1ab5,  0x1ab6,
9124
36.2k
      0x1ab7,  0x1ab8,  0x1ab9,  0x1aba,  0x1abb,  0x1abc,  0x1abd,  0x1abe,
9125
36.2k
      0x1abf,  0x1ac0,  0x1b00,  0x1b01,  0x1b02,  0x1b03,  0x1b04,  0x1b34,
9126
36.2k
      0x1b35,  0x1b36,  0x1b37,  0x1b38,  0x1b39,  0x1b3a,  0x1b3b,  0x1b3c,
9127
36.2k
      0x1b3d,  0x1b3e,  0x1b3f,  0x1b40,  0x1b41,  0x1b42,  0x1b43,  0x1b44,
9128
36.2k
      0x1b6b,  0x1b6c,  0x1b6d,  0x1b6e,  0x1b6f,  0x1b70,  0x1b71,  0x1b72,
9129
36.2k
      0x1b73,  0x1b80,  0x1b81,  0x1b82,  0x1ba1,  0x1ba2,  0x1ba3,  0x1ba4,
9130
36.2k
      0x1ba5,  0x1ba6,  0x1ba7,  0x1ba8,  0x1ba9,  0x1baa,  0x1bab,  0x1bac,
9131
36.2k
      0x1bad,  0x1be6,  0x1be7,  0x1be8,  0x1be9,  0x1bea,  0x1beb,  0x1bec,
9132
36.2k
      0x1bed,  0x1bee,  0x1bef,  0x1bf0,  0x1bf1,  0x1bf2,  0x1bf3,  0x1c24,
9133
36.2k
      0x1c25,  0x1c26,  0x1c27,  0x1c28,  0x1c29,  0x1c2a,  0x1c2b,  0x1c2c,
9134
36.2k
      0x1c2d,  0x1c2e,  0x1c2f,  0x1c30,  0x1c31,  0x1c32,  0x1c33,  0x1c34,
9135
36.2k
      0x1c35,  0x1c36,  0x1c37,  0x1cd0,  0x1cd1,  0x1cd2,  0x1cd4,  0x1cd5,
9136
36.2k
      0x1cd6,  0x1cd7,  0x1cd8,  0x1cd9,  0x1cda,  0x1cdb,  0x1cdc,  0x1cdd,
9137
36.2k
      0x1cde,  0x1cdf,  0x1ce0,  0x1ce1,  0x1ce2,  0x1ce3,  0x1ce4,  0x1ce5,
9138
36.2k
      0x1ce6,  0x1ce7,  0x1ce8,  0x1ced,  0x1cf4,  0x1cf7,  0x1cf8,  0x1cf9,
9139
36.2k
      0x1dc0,  0x1dc1,  0x1dc2,  0x1dc3,  0x1dc4,  0x1dc5,  0x1dc6,  0x1dc7,
9140
36.2k
      0x1dc8,  0x1dc9,  0x1dca,  0x1dcb,  0x1dcc,  0x1dcd,  0x1dce,  0x1dcf,
9141
36.2k
      0x1dd0,  0x1dd1,  0x1dd2,  0x1dd3,  0x1dd4,  0x1dd5,  0x1dd6,  0x1dd7,
9142
36.2k
      0x1dd8,  0x1dd9,  0x1dda,  0x1ddb,  0x1ddc,  0x1ddd,  0x1dde,  0x1ddf,
9143
36.2k
      0x1de0,  0x1de1,  0x1de2,  0x1de3,  0x1de4,  0x1de5,  0x1de6,  0x1de7,
9144
36.2k
      0x1de8,  0x1de9,  0x1dea,  0x1deb,  0x1dec,  0x1ded,  0x1dee,  0x1def,
9145
36.2k
      0x1df0,  0x1df1,  0x1df2,  0x1df3,  0x1df4,  0x1df5,  0x1df6,  0x1df7,
9146
36.2k
      0x1df8,  0x1df9,  0x1dfb,  0x1dfc,  0x1dfd,  0x1dfe,  0x1dff,  0x20d0,
9147
36.2k
      0x20d1,  0x20d2,  0x20d3,  0x20d4,  0x20d5,  0x20d6,  0x20d7,  0x20d8,
9148
36.2k
      0x20d9,  0x20da,  0x20db,  0x20dc,  0x20dd,  0x20de,  0x20df,  0x20e0,
9149
36.2k
      0x20e1,  0x20e2,  0x20e3,  0x20e4,  0x20e5,  0x20e6,  0x20e7,  0x20e8,
9150
36.2k
      0x20e9,  0x20ea,  0x20eb,  0x20ec,  0x20ed,  0x20ee,  0x20ef,  0x20f0,
9151
36.2k
      0x2cef,  0x2cf0,  0x2cf1,  0x2d7f,  0x2de0,  0x2de1,  0x2de2,  0x2de3,
9152
36.2k
      0x2de4,  0x2de5,  0x2de6,  0x2de7,  0x2de8,  0x2de9,  0x2dea,  0x2deb,
9153
36.2k
      0x2dec,  0x2ded,  0x2dee,  0x2def,  0x2df0,  0x2df1,  0x2df2,  0x2df3,
9154
36.2k
      0x2df4,  0x2df5,  0x2df6,  0x2df7,  0x2df8,  0x2df9,  0x2dfa,  0x2dfb,
9155
36.2k
      0x2dfc,  0x2dfd,  0x2dfe,  0x2dff,  0x302a,  0x302b,  0x302c,  0x302d,
9156
36.2k
      0x302e,  0x302f,  0x3099,  0x309a,  0xa66f,  0xa670,  0xa671,  0xa672,
9157
36.2k
      0xa674,  0xa675,  0xa676,  0xa677,  0xa678,  0xa679,  0xa67a,  0xa67b,
9158
36.2k
      0xa67c,  0xa67d,  0xa69e,  0xa69f,  0xa6f0,  0xa6f1,  0xa802,  0xa806,
9159
36.2k
      0xa80b,  0xa823,  0xa824,  0xa825,  0xa826,  0xa827,  0xa82c,  0xa880,
9160
36.2k
      0xa881,  0xa8b4,  0xa8b5,  0xa8b6,  0xa8b7,  0xa8b8,  0xa8b9,  0xa8ba,
9161
36.2k
      0xa8bb,  0xa8bc,  0xa8bd,  0xa8be,  0xa8bf,  0xa8c0,  0xa8c1,  0xa8c2,
9162
36.2k
      0xa8c3,  0xa8c4,  0xa8c5,  0xa8e0,  0xa8e1,  0xa8e2,  0xa8e3,  0xa8e4,
9163
36.2k
      0xa8e5,  0xa8e6,  0xa8e7,  0xa8e8,  0xa8e9,  0xa8ea,  0xa8eb,  0xa8ec,
9164
36.2k
      0xa8ed,  0xa8ee,  0xa8ef,  0xa8f0,  0xa8f1,  0xa8ff,  0xa926,  0xa927,
9165
36.2k
      0xa928,  0xa929,  0xa92a,  0xa92b,  0xa92c,  0xa92d,  0xa947,  0xa948,
9166
36.2k
      0xa949,  0xa94a,  0xa94b,  0xa94c,  0xa94d,  0xa94e,  0xa94f,  0xa950,
9167
36.2k
      0xa951,  0xa952,  0xa953,  0xa980,  0xa981,  0xa982,  0xa983,  0xa9b3,
9168
36.2k
      0xa9b4,  0xa9b5,  0xa9b6,  0xa9b7,  0xa9b8,  0xa9b9,  0xa9ba,  0xa9bb,
9169
36.2k
      0xa9bc,  0xa9bd,  0xa9be,  0xa9bf,  0xa9c0,  0xa9e5,  0xaa29,  0xaa2a,
9170
36.2k
      0xaa2b,  0xaa2c,  0xaa2d,  0xaa2e,  0xaa2f,  0xaa30,  0xaa31,  0xaa32,
9171
36.2k
      0xaa33,  0xaa34,  0xaa35,  0xaa36,  0xaa43,  0xaa4c,  0xaa4d,  0xaa7b,
9172
36.2k
      0xaa7c,  0xaa7d,  0xaab0,  0xaab2,  0xaab3,  0xaab4,  0xaab7,  0xaab8,
9173
36.2k
      0xaabe,  0xaabf,  0xaac1,  0xaaeb,  0xaaec,  0xaaed,  0xaaee,  0xaaef,
9174
36.2k
      0xaaf5,  0xaaf6,  0xabe3,  0xabe4,  0xabe5,  0xabe6,  0xabe7,  0xabe8,
9175
36.2k
      0xabe9,  0xabea,  0xabec,  0xabed,  0xfb1e,  0xfe00,  0xfe01,  0xfe02,
9176
36.2k
      0xfe03,  0xfe04,  0xfe05,  0xfe06,  0xfe07,  0xfe08,  0xfe09,  0xfe0a,
9177
36.2k
      0xfe0b,  0xfe0c,  0xfe0d,  0xfe0e,  0xfe0f,  0xfe20,  0xfe21,  0xfe22,
9178
36.2k
      0xfe23,  0xfe24,  0xfe25,  0xfe26,  0xfe27,  0xfe28,  0xfe29,  0xfe2a,
9179
36.2k
      0xfe2b,  0xfe2c,  0xfe2d,  0xfe2e,  0xfe2f,  0x101fd, 0x102e0, 0x10376,
9180
36.2k
      0x10377, 0x10378, 0x10379, 0x1037a, 0x10a01, 0x10a02, 0x10a03, 0x10a05,
9181
36.2k
      0x10a06, 0x10a0c, 0x10a0d, 0x10a0e, 0x10a0f, 0x10a38, 0x10a39, 0x10a3a,
9182
36.2k
      0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d25, 0x10d26, 0x10d27, 0x10eab,
9183
36.2k
      0x10eac, 0x10f46, 0x10f47, 0x10f48, 0x10f49, 0x10f4a, 0x10f4b, 0x10f4c,
9184
36.2k
      0x10f4d, 0x10f4e, 0x10f4f, 0x10f50, 0x11000, 0x11001, 0x11002, 0x11038,
9185
36.2k
      0x11039, 0x1103a, 0x1103b, 0x1103c, 0x1103d, 0x1103e, 0x1103f, 0x11040,
9186
36.2k
      0x11041, 0x11042, 0x11043, 0x11044, 0x11045, 0x11046, 0x1107f, 0x11080,
9187
36.2k
      0x11081, 0x11082, 0x110b0, 0x110b1, 0x110b2, 0x110b3, 0x110b4, 0x110b5,
9188
36.2k
      0x110b6, 0x110b7, 0x110b8, 0x110b9, 0x110ba, 0x11100, 0x11101, 0x11102,
9189
36.2k
      0x11127, 0x11128, 0x11129, 0x1112a, 0x1112b, 0x1112c, 0x1112d, 0x1112e,
9190
36.2k
      0x1112f, 0x11130, 0x11131, 0x11132, 0x11133, 0x11134, 0x11145, 0x11146,
9191
36.2k
      0x11173, 0x11180, 0x11181, 0x11182, 0x111b3, 0x111b4, 0x111b5, 0x111b6,
9192
36.2k
      0x111b7, 0x111b8, 0x111b9, 0x111ba, 0x111bb, 0x111bc, 0x111bd, 0x111be,
9193
36.2k
      0x111bf, 0x111c0, 0x111c9, 0x111ca, 0x111cb, 0x111cc, 0x111ce, 0x111cf,
9194
36.2k
      0x1122c, 0x1122d, 0x1122e, 0x1122f, 0x11230, 0x11231, 0x11232, 0x11233,
9195
36.2k
      0x11234, 0x11235, 0x11236, 0x11237, 0x1123e, 0x112df, 0x112e0, 0x112e1,
9196
36.2k
      0x112e2, 0x112e3, 0x112e4, 0x112e5, 0x112e6, 0x112e7, 0x112e8, 0x112e9,
9197
36.2k
      0x112ea, 0x11300, 0x11301, 0x11302, 0x11303, 0x1133b, 0x1133c, 0x1133e,
9198
36.2k
      0x1133f, 0x11340, 0x11341, 0x11342, 0x11343, 0x11344, 0x11347, 0x11348,
9199
36.2k
      0x1134b, 0x1134c, 0x1134d, 0x11357, 0x11362, 0x11363, 0x11366, 0x11367,
9200
36.2k
      0x11368, 0x11369, 0x1136a, 0x1136b, 0x1136c, 0x11370, 0x11371, 0x11372,
9201
36.2k
      0x11373, 0x11374, 0x11435, 0x11436, 0x11437, 0x11438, 0x11439, 0x1143a,
9202
36.2k
      0x1143b, 0x1143c, 0x1143d, 0x1143e, 0x1143f, 0x11440, 0x11441, 0x11442,
9203
36.2k
      0x11443, 0x11444, 0x11445, 0x11446, 0x1145e, 0x114b0, 0x114b1, 0x114b2,
9204
36.2k
      0x114b3, 0x114b4, 0x114b5, 0x114b6, 0x114b7, 0x114b8, 0x114b9, 0x114ba,
9205
36.2k
      0x114bb, 0x114bc, 0x114bd, 0x114be, 0x114bf, 0x114c0, 0x114c1, 0x114c2,
9206
36.2k
      0x114c3, 0x115af, 0x115b0, 0x115b1, 0x115b2, 0x115b3, 0x115b4, 0x115b5,
9207
36.2k
      0x115b8, 0x115b9, 0x115ba, 0x115bb, 0x115bc, 0x115bd, 0x115be, 0x115bf,
9208
36.2k
      0x115c0, 0x115dc, 0x115dd, 0x11630, 0x11631, 0x11632, 0x11633, 0x11634,
9209
36.2k
      0x11635, 0x11636, 0x11637, 0x11638, 0x11639, 0x1163a, 0x1163b, 0x1163c,
9210
36.2k
      0x1163d, 0x1163e, 0x1163f, 0x11640, 0x116ab, 0x116ac, 0x116ad, 0x116ae,
9211
36.2k
      0x116af, 0x116b0, 0x116b1, 0x116b2, 0x116b3, 0x116b4, 0x116b5, 0x116b6,
9212
36.2k
      0x116b7, 0x1171d, 0x1171e, 0x1171f, 0x11720, 0x11721, 0x11722, 0x11723,
9213
36.2k
      0x11724, 0x11725, 0x11726, 0x11727, 0x11728, 0x11729, 0x1172a, 0x1172b,
9214
36.2k
      0x1182c, 0x1182d, 0x1182e, 0x1182f, 0x11830, 0x11831, 0x11832, 0x11833,
9215
36.2k
      0x11834, 0x11835, 0x11836, 0x11837, 0x11838, 0x11839, 0x1183a, 0x11930,
9216
36.2k
      0x11931, 0x11932, 0x11933, 0x11934, 0x11935, 0x11937, 0x11938, 0x1193b,
9217
36.2k
      0x1193c, 0x1193d, 0x1193e, 0x11940, 0x11942, 0x11943, 0x119d1, 0x119d2,
9218
36.2k
      0x119d3, 0x119d4, 0x119d5, 0x119d6, 0x119d7, 0x119da, 0x119db, 0x119dc,
9219
36.2k
      0x119dd, 0x119de, 0x119df, 0x119e0, 0x119e4, 0x11a01, 0x11a02, 0x11a03,
9220
36.2k
      0x11a04, 0x11a05, 0x11a06, 0x11a07, 0x11a08, 0x11a09, 0x11a0a, 0x11a33,
9221
36.2k
      0x11a34, 0x11a35, 0x11a36, 0x11a37, 0x11a38, 0x11a39, 0x11a3b, 0x11a3c,
9222
36.2k
      0x11a3d, 0x11a3e, 0x11a47, 0x11a51, 0x11a52, 0x11a53, 0x11a54, 0x11a55,
9223
36.2k
      0x11a56, 0x11a57, 0x11a58, 0x11a59, 0x11a5a, 0x11a5b, 0x11a8a, 0x11a8b,
9224
36.2k
      0x11a8c, 0x11a8d, 0x11a8e, 0x11a8f, 0x11a90, 0x11a91, 0x11a92, 0x11a93,
9225
36.2k
      0x11a94, 0x11a95, 0x11a96, 0x11a97, 0x11a98, 0x11a99, 0x11c2f, 0x11c30,
9226
36.2k
      0x11c31, 0x11c32, 0x11c33, 0x11c34, 0x11c35, 0x11c36, 0x11c38, 0x11c39,
9227
36.2k
      0x11c3a, 0x11c3b, 0x11c3c, 0x11c3d, 0x11c3e, 0x11c3f, 0x11c92, 0x11c93,
9228
36.2k
      0x11c94, 0x11c95, 0x11c96, 0x11c97, 0x11c98, 0x11c99, 0x11c9a, 0x11c9b,
9229
36.2k
      0x11c9c, 0x11c9d, 0x11c9e, 0x11c9f, 0x11ca0, 0x11ca1, 0x11ca2, 0x11ca3,
9230
36.2k
      0x11ca4, 0x11ca5, 0x11ca6, 0x11ca7, 0x11ca9, 0x11caa, 0x11cab, 0x11cac,
9231
36.2k
      0x11cad, 0x11cae, 0x11caf, 0x11cb0, 0x11cb1, 0x11cb2, 0x11cb3, 0x11cb4,
9232
36.2k
      0x11cb5, 0x11cb6, 0x11d31, 0x11d32, 0x11d33, 0x11d34, 0x11d35, 0x11d36,
9233
36.2k
      0x11d3a, 0x11d3c, 0x11d3d, 0x11d3f, 0x11d40, 0x11d41, 0x11d42, 0x11d43,
9234
36.2k
      0x11d44, 0x11d45, 0x11d47, 0x11d8a, 0x11d8b, 0x11d8c, 0x11d8d, 0x11d8e,
9235
36.2k
      0x11d90, 0x11d91, 0x11d93, 0x11d94, 0x11d95, 0x11d96, 0x11d97, 0x11ef3,
9236
36.2k
      0x11ef4, 0x11ef5, 0x11ef6, 0x16af0, 0x16af1, 0x16af2, 0x16af3, 0x16af4,
9237
36.2k
      0x16b30, 0x16b31, 0x16b32, 0x16b33, 0x16b34, 0x16b35, 0x16b36, 0x16f4f,
9238
36.2k
      0x16f51, 0x16f52, 0x16f53, 0x16f54, 0x16f55, 0x16f56, 0x16f57, 0x16f58,
9239
36.2k
      0x16f59, 0x16f5a, 0x16f5b, 0x16f5c, 0x16f5d, 0x16f5e, 0x16f5f, 0x16f60,
9240
36.2k
      0x16f61, 0x16f62, 0x16f63, 0x16f64, 0x16f65, 0x16f66, 0x16f67, 0x16f68,
9241
36.2k
      0x16f69, 0x16f6a, 0x16f6b, 0x16f6c, 0x16f6d, 0x16f6e, 0x16f6f, 0x16f70,
9242
36.2k
      0x16f71, 0x16f72, 0x16f73, 0x16f74, 0x16f75, 0x16f76, 0x16f77, 0x16f78,
9243
36.2k
      0x16f79, 0x16f7a, 0x16f7b, 0x16f7c, 0x16f7d, 0x16f7e, 0x16f7f, 0x16f80,
9244
36.2k
      0x16f81, 0x16f82, 0x16f83, 0x16f84, 0x16f85, 0x16f86, 0x16f87, 0x16f8f,
9245
36.2k
      0x16f90, 0x16f91, 0x16f92, 0x16fe4, 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e,
9246
36.2k
      0x1d165, 0x1d166, 0x1d167, 0x1d168, 0x1d169, 0x1d16d, 0x1d16e, 0x1d16f,
9247
36.2k
      0x1d170, 0x1d171, 0x1d172, 0x1d17b, 0x1d17c, 0x1d17d, 0x1d17e, 0x1d17f,
9248
36.2k
      0x1d180, 0x1d181, 0x1d182, 0x1d185, 0x1d186, 0x1d187, 0x1d188, 0x1d189,
9249
36.2k
      0x1d18a, 0x1d18b, 0x1d1aa, 0x1d1ab, 0x1d1ac, 0x1d1ad, 0x1d242, 0x1d243,
9250
36.2k
      0x1d244, 0x1da00, 0x1da01, 0x1da02, 0x1da03, 0x1da04, 0x1da05, 0x1da06,
9251
36.2k
      0x1da07, 0x1da08, 0x1da09, 0x1da0a, 0x1da0b, 0x1da0c, 0x1da0d, 0x1da0e,
9252
36.2k
      0x1da0f, 0x1da10, 0x1da11, 0x1da12, 0x1da13, 0x1da14, 0x1da15, 0x1da16,
9253
36.2k
      0x1da17, 0x1da18, 0x1da19, 0x1da1a, 0x1da1b, 0x1da1c, 0x1da1d, 0x1da1e,
9254
36.2k
      0x1da1f, 0x1da20, 0x1da21, 0x1da22, 0x1da23, 0x1da24, 0x1da25, 0x1da26,
9255
36.2k
      0x1da27, 0x1da28, 0x1da29, 0x1da2a, 0x1da2b, 0x1da2c, 0x1da2d, 0x1da2e,
9256
36.2k
      0x1da2f, 0x1da30, 0x1da31, 0x1da32, 0x1da33, 0x1da34, 0x1da35, 0x1da36,
9257
36.2k
      0x1da3b, 0x1da3c, 0x1da3d, 0x1da3e, 0x1da3f, 0x1da40, 0x1da41, 0x1da42,
9258
36.2k
      0x1da43, 0x1da44, 0x1da45, 0x1da46, 0x1da47, 0x1da48, 0x1da49, 0x1da4a,
9259
36.2k
      0x1da4b, 0x1da4c, 0x1da4d, 0x1da4e, 0x1da4f, 0x1da50, 0x1da51, 0x1da52,
9260
36.2k
      0x1da53, 0x1da54, 0x1da55, 0x1da56, 0x1da57, 0x1da58, 0x1da59, 0x1da5a,
9261
36.2k
      0x1da5b, 0x1da5c, 0x1da5d, 0x1da5e, 0x1da5f, 0x1da60, 0x1da61, 0x1da62,
9262
36.2k
      0x1da63, 0x1da64, 0x1da65, 0x1da66, 0x1da67, 0x1da68, 0x1da69, 0x1da6a,
9263
36.2k
      0x1da6b, 0x1da6c, 0x1da75, 0x1da84, 0x1da9b, 0x1da9c, 0x1da9d, 0x1da9e,
9264
36.2k
      0x1da9f, 0x1daa1, 0x1daa2, 0x1daa3, 0x1daa4, 0x1daa5, 0x1daa6, 0x1daa7,
9265
36.2k
      0x1daa8, 0x1daa9, 0x1daaa, 0x1daab, 0x1daac, 0x1daad, 0x1daae, 0x1daaf,
9266
36.2k
      0x1e000, 0x1e001, 0x1e002, 0x1e003, 0x1e004, 0x1e005, 0x1e006, 0x1e008,
9267
36.2k
      0x1e009, 0x1e00a, 0x1e00b, 0x1e00c, 0x1e00d, 0x1e00e, 0x1e00f, 0x1e010,
9268
36.2k
      0x1e011, 0x1e012, 0x1e013, 0x1e014, 0x1e015, 0x1e016, 0x1e017, 0x1e018,
9269
36.2k
      0x1e01b, 0x1e01c, 0x1e01d, 0x1e01e, 0x1e01f, 0x1e020, 0x1e021, 0x1e023,
9270
36.2k
      0x1e024, 0x1e026, 0x1e027, 0x1e028, 0x1e029, 0x1e02a, 0x1e130, 0x1e131,
9271
36.2k
      0x1e132, 0x1e133, 0x1e134, 0x1e135, 0x1e136, 0x1e2ec, 0x1e2ed, 0x1e2ee,
9272
36.2k
      0x1e2ef, 0x1e8d0, 0x1e8d1, 0x1e8d2, 0x1e8d3, 0x1e8d4, 0x1e8d5, 0x1e8d6,
9273
36.2k
      0x1e944, 0x1e945, 0x1e946, 0x1e947, 0x1e948, 0x1e949, 0x1e94a, 0xe0100,
9274
36.2k
      0xe0101, 0xe0102, 0xe0103, 0xe0104, 0xe0105, 0xe0106, 0xe0107, 0xe0108,
9275
36.2k
      0xe0109, 0xe010a, 0xe010b, 0xe010c, 0xe010d, 0xe010e, 0xe010f, 0xe0110,
9276
36.2k
      0xe0111, 0xe0112, 0xe0113, 0xe0114, 0xe0115, 0xe0116, 0xe0117, 0xe0118,
9277
36.2k
      0xe0119, 0xe011a, 0xe011b, 0xe011c, 0xe011d, 0xe011e, 0xe011f, 0xe0120,
9278
36.2k
      0xe0121, 0xe0122, 0xe0123, 0xe0124, 0xe0125, 0xe0126, 0xe0127, 0xe0128,
9279
36.2k
      0xe0129, 0xe012a, 0xe012b, 0xe012c, 0xe012d, 0xe012e, 0xe012f, 0xe0130,
9280
36.2k
      0xe0131, 0xe0132, 0xe0133, 0xe0134, 0xe0135, 0xe0136, 0xe0137, 0xe0138,
9281
36.2k
      0xe0139, 0xe013a, 0xe013b, 0xe013c, 0xe013d, 0xe013e, 0xe013f, 0xe0140,
9282
36.2k
      0xe0141, 0xe0142, 0xe0143, 0xe0144, 0xe0145, 0xe0146, 0xe0147, 0xe0148,
9283
36.2k
      0xe0149, 0xe014a, 0xe014b, 0xe014c, 0xe014d, 0xe014e, 0xe014f, 0xe0150,
9284
36.2k
      0xe0151, 0xe0152, 0xe0153, 0xe0154, 0xe0155, 0xe0156, 0xe0157, 0xe0158,
9285
36.2k
      0xe0159, 0xe015a, 0xe015b, 0xe015c, 0xe015d, 0xe015e, 0xe015f, 0xe0160,
9286
36.2k
      0xe0161, 0xe0162, 0xe0163, 0xe0164, 0xe0165, 0xe0166, 0xe0167, 0xe0168,
9287
36.2k
      0xe0169, 0xe016a, 0xe016b, 0xe016c, 0xe016d, 0xe016e, 0xe016f, 0xe0170,
9288
36.2k
      0xe0171, 0xe0172, 0xe0173, 0xe0174, 0xe0175, 0xe0176, 0xe0177, 0xe0178,
9289
36.2k
      0xe0179, 0xe017a, 0xe017b, 0xe017c, 0xe017d, 0xe017e, 0xe017f, 0xe0180,
9290
36.2k
      0xe0181, 0xe0182, 0xe0183, 0xe0184, 0xe0185, 0xe0186, 0xe0187, 0xe0188,
9291
36.2k
      0xe0189, 0xe018a, 0xe018b, 0xe018c, 0xe018d, 0xe018e, 0xe018f, 0xe0190,
9292
36.2k
      0xe0191, 0xe0192, 0xe0193, 0xe0194, 0xe0195, 0xe0196, 0xe0197, 0xe0198,
9293
36.2k
      0xe0199, 0xe019a, 0xe019b, 0xe019c, 0xe019d, 0xe019e, 0xe019f, 0xe01a0,
9294
36.2k
      0xe01a1, 0xe01a2, 0xe01a3, 0xe01a4, 0xe01a5, 0xe01a6, 0xe01a7, 0xe01a8,
9295
36.2k
      0xe01a9, 0xe01aa, 0xe01ab, 0xe01ac, 0xe01ad, 0xe01ae, 0xe01af, 0xe01b0,
9296
36.2k
      0xe01b1, 0xe01b2, 0xe01b3, 0xe01b4, 0xe01b5, 0xe01b6, 0xe01b7, 0xe01b8,
9297
36.2k
      0xe01b9, 0xe01ba, 0xe01bb, 0xe01bc, 0xe01bd, 0xe01be, 0xe01bf, 0xe01c0,
9298
36.2k
      0xe01c1, 0xe01c2, 0xe01c3, 0xe01c4, 0xe01c5, 0xe01c6, 0xe01c7, 0xe01c8,
9299
36.2k
      0xe01c9, 0xe01ca, 0xe01cb, 0xe01cc, 0xe01cd, 0xe01ce, 0xe01cf, 0xe01d0,
9300
36.2k
      0xe01d1, 0xe01d2, 0xe01d3, 0xe01d4, 0xe01d5, 0xe01d6, 0xe01d7, 0xe01d8,
9301
36.2k
      0xe01d9, 0xe01da, 0xe01db, 0xe01dc, 0xe01dd, 0xe01de, 0xe01df, 0xe01e0,
9302
36.2k
      0xe01e1, 0xe01e2, 0xe01e3, 0xe01e4, 0xe01e5, 0xe01e6, 0xe01e7, 0xe01e8,
9303
36.2k
      0xe01e9, 0xe01ea, 0xe01eb, 0xe01ec, 0xe01ed, 0xe01ee, 0xe01ef};
9304
36.2k
  if (std::binary_search(std::begin(combining), std::end(combining),
9305
36.2k
                         label.front())) {
9306
103
    return false;
9307
103
  }
9308
  // We verify this next step as part of the mapping:
9309
  // ---------------------------------------------
9310
  // Each code point in the label must only have certain status values
9311
  // according to Section 5, IDNA Mapping Table:
9312
  // - For Transitional Processing, each value must be valid.
9313
  // - For Nontransitional Processing, each value must be either valid or
9314
  // deviation.
9315
9316
  // If CheckJoiners, the label must satisfy the ContextJ rules from Appendix
9317
  // A, in The Unicode Code Points and Internationalized Domain Names for
9318
  // Applications (IDNA) [IDNA2008].
9319
36.1k
  constexpr static uint32_t virama[] = {
9320
36.1k
      0x094D,  0x09CD,  0x0A4D,  0x0ACD,  0x0B4D,  0x0BCD,  0x0C4D,  0x0CCD,
9321
36.1k
      0x0D3B,  0x0D3C,  0x0D4D,  0x0DCA,  0x0E3A,  0x0EBA,  0x0F84,  0x1039,
9322
36.1k
      0x103A,  0x1714,  0x1734,  0x17D2,  0x1A60,  0x1B44,  0x1BAA,  0x1BAB,
9323
36.1k
      0x1BF2,  0x1BF3,  0x2D7F,  0xA806,  0xA82C,  0xA8C4,  0xA953,  0xA9C0,
9324
36.1k
      0xAAF6,  0xABED,  0x10A3F, 0x11046, 0x1107F, 0x110B9, 0x11133, 0x11134,
9325
36.1k
      0x111C0, 0x11235, 0x112EA, 0x1134D, 0x11442, 0x114C2, 0x115BF, 0x1163F,
9326
36.1k
      0x116B6, 0x1172B, 0x11839, 0x1193D, 0x1193E, 0x119E0, 0x11A34, 0x11A47,
9327
36.1k
      0x11A99, 0x11C3F, 0x11D44, 0x11D45, 0x11D97};
9328
36.1k
  constexpr static uint32_t R[] = {
9329
36.1k
      0x622, 0x623, 0x624, 0x625, 0x627, 0x629, 0x62f, 0x630, 0x631,
9330
36.1k
      0x632, 0x648, 0x671, 0x672, 0x673, 0x675, 0x676, 0x677, 0x688,
9331
36.1k
      0x689, 0x68a, 0x68b, 0x68c, 0x68d, 0x68e, 0x68f, 0x690, 0x691,
9332
36.1k
      0x692, 0x693, 0x694, 0x695, 0x696, 0x697, 0x698, 0x699, 0x6c0,
9333
36.1k
      0x6c3, 0x6c4, 0x6c5, 0x6c6, 0x6c7, 0x6c8, 0x6c9, 0x6ca, 0x6cb,
9334
36.1k
      0x6cd, 0x6cf, 0x6d2, 0x6d3, 0x6d5, 0x6ee, 0x6ef, 0x710, 0x715,
9335
36.1k
      0x716, 0x717, 0x718, 0x719, 0x71e, 0x728, 0x72a, 0x72c, 0x72f,
9336
36.1k
      0x74d, 0x759, 0x75a, 0x75b, 0x854, 0x8aa, 0x8ab, 0x8ac};
9337
36.1k
  constexpr static uint32_t L[] = {0xa872};
9338
36.1k
  constexpr static uint32_t D[] = {
9339
36.1k
      0x620,  0x626,  0x628,  0x62a,  0x62b,  0x62c,  0x62d,  0x62e,  0x633,
9340
36.1k
      0x634,  0x635,  0x636,  0x637,  0x638,  0x639,  0x63a,  0x63b,  0x63c,
9341
36.1k
      0x63d,  0x63e,  0x63f,  0x641,  0x642,  0x643,  0x644,  0x645,  0x646,
9342
36.1k
      0x647,  0x649,  0x64a,  0x66e,  0x66f,  0x678,  0x679,  0x67a,  0x67b,
9343
36.1k
      0x67c,  0x67d,  0x67e,  0x67f,  0x680,  0x681,  0x682,  0x683,  0x684,
9344
36.1k
      0x685,  0x686,  0x687,  0x69a,  0x69b,  0x69c,  0x69d,  0x69e,  0x69f,
9345
36.1k
      0x6a0,  0x6a1,  0x6a2,  0x6a3,  0x6a4,  0x6a5,  0x6a6,  0x6a7,  0x6a8,
9346
36.1k
      0x6a9,  0x6aa,  0x6ab,  0x6ac,  0x6ad,  0x6ae,  0x6af,  0x6b0,  0x6b1,
9347
36.1k
      0x6b2,  0x6b3,  0x6b4,  0x6b5,  0x6b6,  0x6b7,  0x6b8,  0x6b9,  0x6ba,
9348
36.1k
      0x6bb,  0x6bc,  0x6bd,  0x6be,  0x6bf,  0x6c1,  0x6c2,  0x6cc,  0x6ce,
9349
36.1k
      0x6d0,  0x6d1,  0x6fa,  0x6fb,  0x6fc,  0x6ff,  0x712,  0x713,  0x714,
9350
36.1k
      0x71a,  0x71b,  0x71c,  0x71d,  0x71f,  0x720,  0x721,  0x722,  0x723,
9351
36.1k
      0x724,  0x725,  0x726,  0x727,  0x729,  0x72b,  0x72d,  0x72e,  0x74e,
9352
36.1k
      0x74f,  0x750,  0x751,  0x752,  0x753,  0x754,  0x755,  0x756,  0x757,
9353
36.1k
      0x758,  0x75c,  0x75d,  0x75e,  0x75f,  0x760,  0x761,  0x762,  0x763,
9354
36.1k
      0x764,  0x765,  0x766,  0x850,  0x851,  0x852,  0x853,  0x855,  0x8a0,
9355
36.1k
      0x8a2,  0x8a3,  0x8a4,  0x8a5,  0x8a6,  0x8a7,  0x8a8,  0x8a9,  0x1807,
9356
36.1k
      0x1820, 0x1821, 0x1822, 0x1823, 0x1824, 0x1825, 0x1826, 0x1827, 0x1828,
9357
36.1k
      0x1829, 0x182a, 0x182b, 0x182c, 0x182d, 0x182e, 0x182f, 0x1830, 0x1831,
9358
36.1k
      0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837, 0x1838, 0x1839, 0x183a,
9359
36.1k
      0x183b, 0x183c, 0x183d, 0x183e, 0x183f, 0x1840, 0x1841, 0x1842, 0x1843,
9360
36.1k
      0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x184a, 0x184b, 0x184c,
9361
36.1k
      0x184d, 0x184e, 0x184f, 0x1850, 0x1851, 0x1852, 0x1853, 0x1854, 0x1855,
9362
36.1k
      0x1856, 0x1857, 0x1858, 0x1859, 0x185a, 0x185b, 0x185c, 0x185d, 0x185e,
9363
36.1k
      0x185f, 0x1860, 0x1861, 0x1862, 0x1863, 0x1864, 0x1865, 0x1866, 0x1867,
9364
36.1k
      0x1868, 0x1869, 0x186a, 0x186b, 0x186c, 0x186d, 0x186e, 0x186f, 0x1870,
9365
36.1k
      0x1871, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, 0x1877, 0x1887, 0x1888,
9366
36.1k
      0x1889, 0x188a, 0x188b, 0x188c, 0x188d, 0x188e, 0x188f, 0x1890, 0x1891,
9367
36.1k
      0x1892, 0x1893, 0x1894, 0x1895, 0x1896, 0x1897, 0x1898, 0x1899, 0x189a,
9368
36.1k
      0x189b, 0x189c, 0x189d, 0x189e, 0x189f, 0x18a0, 0x18a1, 0x18a2, 0x18a3,
9369
36.1k
      0x18a4, 0x18a5, 0x18a6, 0x18a7, 0x18a8, 0x18aa, 0xa840, 0xa841, 0xa842,
9370
36.1k
      0xa843, 0xa844, 0xa845, 0xa846, 0xa847, 0xa848, 0xa849, 0xa84a, 0xa84b,
9371
36.1k
      0xa84c, 0xa84d, 0xa84e, 0xa84f, 0xa850, 0xa851, 0xa852, 0xa853, 0xa854,
9372
36.1k
      0xa855, 0xa856, 0xa857, 0xa858, 0xa859, 0xa85a, 0xa85b, 0xa85c, 0xa85d,
9373
36.1k
      0xa85e, 0xa85f, 0xa860, 0xa861, 0xa862, 0xa863, 0xa864, 0xa865, 0xa866,
9374
36.1k
      0xa867, 0xa868, 0xa869, 0xa86a, 0xa86b, 0xa86c, 0xa86d, 0xa86e, 0xa86f,
9375
36.1k
      0xa870, 0xa871};
9376
9377
254k
  for (size_t i = 0; i < label.size(); i++) {
9378
220k
    uint32_t c = label[i];
9379
220k
    if (c == 0x200c) {
9380
1.40k
      if (i > 0) {
9381
1.38k
        if (std::binary_search(std::begin(virama), std::end(virama),
9382
1.38k
                               label[i - 1])) {
9383
201
          return true;
9384
201
        }
9385
1.38k
      }
9386
1.20k
      if ((i == 0) || (i + 1 >= label.size())) {
9387
120
        return false;
9388
120
      }
9389
      // we go backward looking for L or D
9390
2.05k
      auto is_l_or_d = [](uint32_t code) {
9391
2.05k
        return std::binary_search(std::begin(L), std::end(L), code) ||
9392
2.05k
               std::binary_search(std::begin(D), std::end(D), code);
9393
2.05k
      };
9394
2.03k
      auto is_r_or_d = [](uint32_t code) {
9395
2.03k
        return std::binary_search(std::begin(R), std::end(R), code) ||
9396
2.03k
               std::binary_search(std::begin(D), std::end(D), code);
9397
2.03k
      };
9398
1.08k
      std::u32string_view before = label.substr(0, i);
9399
1.08k
      std::u32string_view after = label.substr(i + 1);
9400
1.08k
      return (std::find_if(before.begin(), before.end(), is_l_or_d) !=
9401
1.08k
              before.end()) &&
9402
1.08k
             (std::find_if(after.begin(), after.end(), is_r_or_d) !=
9403
962
              after.end());
9404
218k
    } else if (c == 0x200d) {
9405
681
      if (i > 0) {
9406
667
        if (std::binary_search(std::begin(virama), std::end(virama),
9407
667
                               label[i - 1])) {
9408
570
          return true;
9409
570
        }
9410
667
      }
9411
111
      return false;
9412
681
    }
9413
220k
  }
9414
9415
  // If CheckBidi, and if the domain name is a  Bidi domain name, then the label
9416
  // must satisfy all six of the numbered conditions in [IDNA2008] RFC 5893,
9417
  // Section 2.
9418
9419
  // The following rule, consisting of six conditions, applies to labels
9420
  // in Bidi domain names.  The requirements that this rule satisfies are
9421
  // described in Section 3.  All of the conditions must be satisfied for
9422
  // the rule to be satisfied.
9423
  //
9424
  //  1.  The first character must be a character with Bidi property L, R,
9425
  //     or AL.  If it has the R or AL property, it is an RTL label; if it
9426
  //     has the L property, it is an LTR label.
9427
  //
9428
  //  2.  In an RTL label, only characters with the Bidi properties R, AL,
9429
  //      AN, EN, ES, CS, ET, ON, BN, or NSM are allowed.
9430
  //
9431
  //   3.  In an RTL label, the end of the label must be a character with
9432
  //       Bidi property R, AL, EN, or AN, followed by zero or more
9433
  //       characters with Bidi property NSM.
9434
  //
9435
  //   4.  In an RTL label, if an EN is present, no AN may be present, and
9436
  //       vice versa.
9437
  //
9438
  //  5.  In an LTR label, only characters with the Bidi properties L, EN,
9439
  //       ES, CS, ET, ON, BN, or NSM are allowed.
9440
  //
9441
  //   6.  In an LTR label, the end of the label must be a character with
9442
  //       Bidi property L or EN, followed by zero or more characters with
9443
  //       Bidi property NSM.
9444
9445
34.0k
  size_t last_non_nsm_char = find_last_not_of_nsm(label);
9446
34.0k
  if (last_non_nsm_char == std::u32string_view::npos) {
9447
0
    return false;
9448
0
  }
9449
9450
  // A "Bidi domain name" is a domain name that contains at least one RTL label.
9451
  // The following rule, consisting of six conditions, applies to labels in Bidi
9452
  // domain names.
9453
34.0k
  if (is_rtl_label(label)) {
9454
    // The first character must be a character with Bidi property L, R,
9455
    // or AL. If it has the R or AL property, it is an RTL label; if it
9456
    // has the L property, it is an LTR label.
9457
9458
2.66k
    if (find_direction(label[0]) == direction::L) {
9459
      // Eval as LTR
9460
9461
      // In an LTR label, only characters with the Bidi properties L, EN,
9462
      // ES, CS, ET, ON, BN, or NSM are allowed.
9463
3.36k
      for (size_t i = 0; i < last_non_nsm_char; i++) {
9464
2.91k
        const direction d = find_direction(label[i]);
9465
2.91k
        if (!(d == direction::L || d == direction::EN || d == direction::ES ||
9466
2.91k
              d == direction::CS || d == direction::ET || d == direction::ON ||
9467
2.91k
              d == direction::BN || d == direction::NSM)) {
9468
107
          return false;
9469
107
        }
9470
9471
2.80k
        if ((i == last_non_nsm_char) &&
9472
2.80k
            !(d == direction::L || d == direction::EN)) {
9473
0
          return false;
9474
0
        }
9475
2.80k
      }
9476
9477
454
      return true;
9478
9479
2.10k
    } else {
9480
      // Eval as RTL
9481
9482
2.10k
      bool has_an = false;
9483
2.10k
      bool has_en = false;
9484
6.91k
      for (size_t i = 0; i <= last_non_nsm_char; i++) {
9485
5.01k
        const direction d = find_direction(label[i]);
9486
9487
        // In an RTL label, if an EN is present, no AN may be present, and vice
9488
        // versa.
9489
5.01k
        if ((d == direction::EN && ((has_en = true) && has_an)) ||
9490
5.01k
            (d == direction::AN && ((has_an = true) && has_en))) {
9491
29
          return false;
9492
29
        }
9493
9494
4.99k
        if (!(d == direction::R || d == direction::AL || d == direction::AN ||
9495
4.99k
              d == direction::EN || d == direction::ES || d == direction::CS ||
9496
4.99k
              d == direction::ET || d == direction::ON || d == direction::BN ||
9497
4.99k
              d == direction::NSM)) {
9498
133
          return false;
9499
133
        }
9500
9501
4.85k
        if (i == last_non_nsm_char &&
9502
4.85k
            !(d == direction::R || d == direction::AL || d == direction::AN ||
9503
1.94k
              d == direction::EN)) {
9504
53
          return false;
9505
53
        }
9506
4.85k
      }
9507
9508
1.89k
      return true;
9509
2.10k
    }
9510
2.66k
  }
9511
9512
31.3k
  return true;
9513
34.0k
}
9514
9515
}  // namespace ada::idna
9516
/* end file src/validity.cpp */
9517
/* begin file src/to_ascii.cpp */
9518
9519
#include <algorithm>
9520
#include <cstdint>
9521
9522
9523
namespace ada::idna {
9524
9525
32.0k
bool begins_with(std::u32string_view view, std::u32string_view prefix) {
9526
32.0k
  if (view.size() < prefix.size()) {
9527
6.93k
    return false;
9528
6.93k
  }
9529
  // constexpr as of C++20
9530
25.0k
  return std::equal(prefix.begin(), prefix.end(), view.begin());
9531
32.0k
}
9532
9533
56.2k
bool begins_with(std::string_view view, std::string_view prefix) {
9534
56.2k
  if (view.size() < prefix.size()) {
9535
27.1k
    return false;
9536
27.1k
  }
9537
  // constexpr as of C++20
9538
29.1k
  return std::equal(prefix.begin(), prefix.end(), view.begin());
9539
56.2k
}
9540
9541
29.8k
bool constexpr is_ascii(std::u32string_view view) {
9542
62.0k
  for (uint32_t c : view) {
9543
62.0k
    if (c >= 0x80) {
9544
27.0k
      return false;
9545
27.0k
    }
9546
62.0k
  }
9547
2.80k
  return true;
9548
29.8k
}
9549
9550
26.5k
bool constexpr is_ascii(std::string_view view) {
9551
321k
  for (uint8_t c : view) {
9552
321k
    if (c >= 0x80) {
9553
10.2k
      return false;
9554
10.2k
    }
9555
321k
  }
9556
16.3k
  return true;
9557
26.5k
}
9558
9559
constexpr static uint8_t is_forbidden_domain_code_point_table[] = {
9560
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9561
    1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
9562
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
9563
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
9564
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9565
    0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9566
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9567
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9568
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9569
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9570
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
9571
9572
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
9573
9574
0
inline bool is_forbidden_domain_code_point(const char c) noexcept {
9575
0
  return is_forbidden_domain_code_point_table[uint8_t(c)];
9576
0
}
9577
9578
0
bool contains_forbidden_domain_code_point(std::string_view view) {
9579
0
  return (
9580
0
      std::any_of(view.begin(), view.end(), is_forbidden_domain_code_point));
9581
0
}
9582
9583
// We return "" on error.
9584
14.2k
static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9585
14.2k
  static const std::string error = "";
9586
  // copy and map
9587
  // we could be more efficient by avoiding the copy when unnecessary.
9588
14.2k
  std::string mapped_string = std::string(ut8_string);
9589
14.2k
  ascii_map(mapped_string.data(), mapped_string.size());
9590
14.2k
  std::string out;
9591
14.2k
  size_t label_start = 0;
9592
9593
43.0k
  while (label_start != mapped_string.size()) {
9594
29.6k
    size_t loc_dot = mapped_string.find('.', label_start);
9595
29.6k
    bool is_last_label = (loc_dot == std::string_view::npos);
9596
29.6k
    size_t label_size = is_last_label ? mapped_string.size() - label_start
9597
29.6k
                                      : loc_dot - label_start;
9598
29.6k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9599
29.6k
    std::string_view label_view(mapped_string.data() + label_start, label_size);
9600
29.6k
    label_start += label_size_with_dot;
9601
29.6k
    if (label_size == 0) {
9602
      // empty label? Nothing to do.
9603
25.1k
    } else if (begins_with(label_view, "xn--")) {
9604
      // The xn-- part is the expensive game.
9605
8.09k
      out.append(label_view);
9606
8.09k
      std::string_view puny_segment_ascii(
9607
8.09k
          out.data() + out.size() - label_view.size() + 4,
9608
8.09k
          label_view.size() - 4);
9609
8.09k
      std::u32string tmp_buffer;
9610
8.09k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9611
8.09k
      if (!is_ok) {
9612
217
        return error;
9613
217
      }
9614
7.88k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9615
7.88k
      if (tmp_buffer != post_map) {
9616
403
        return error;
9617
403
      }
9618
7.47k
      std::u32string pre_normal = post_map;
9619
7.47k
      normalize(post_map);
9620
7.47k
      if (post_map != pre_normal) {
9621
45
        return error;
9622
45
      }
9623
7.43k
      if (post_map.empty()) {
9624
146
        return error;
9625
146
      }
9626
7.28k
      if (!is_label_valid(post_map)) {
9627
27
        return error;
9628
27
      }
9629
17.0k
    } else {
9630
17.0k
      out.append(label_view);
9631
17.0k
    }
9632
28.8k
    if (!is_last_label) {
9633
17.4k
      out.push_back('.');
9634
17.4k
    }
9635
28.8k
  }
9636
13.3k
  return out;
9637
14.2k
}
9638
9639
// We return "" on error.
9640
24.1k
std::string to_ascii(std::string_view ut8_string) {
9641
24.1k
  if (is_ascii(ut8_string)) {
9642
14.2k
    return from_ascii_to_ascii(ut8_string);
9643
14.2k
  }
9644
9.89k
  static const std::string error = "";
9645
  // We convert to UTF-32
9646
9.89k
  size_t utf32_length =
9647
9.89k
      ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9648
9.89k
  std::u32string utf32(utf32_length, '\0');
9649
9.89k
  size_t actual_utf32_length = ada::idna::utf8_to_utf32(
9650
9.89k
      ut8_string.data(), ut8_string.size(), utf32.data());
9651
9.89k
  if (actual_utf32_length == 0) {
9652
3.09k
    return error;
9653
3.09k
  }
9654
  // mapping
9655
6.79k
  utf32 = ada::idna::map(utf32);
9656
6.79k
  normalize(utf32);
9657
6.79k
  std::string out;
9658
6.79k
  size_t label_start = 0;
9659
9660
39.4k
  while (label_start != utf32.size()) {
9661
33.8k
    size_t loc_dot = utf32.find('.', label_start);
9662
33.8k
    bool is_last_label = (loc_dot == std::string_view::npos);
9663
33.8k
    size_t label_size =
9664
33.8k
        is_last_label ? utf32.size() - label_start : loc_dot - label_start;
9665
33.8k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9666
33.8k
    std::u32string_view label_view(utf32.data() + label_start, label_size);
9667
33.8k
    label_start += label_size_with_dot;
9668
33.8k
    if (label_size == 0) {
9669
      // empty label? Nothing to do.
9670
32.0k
    } else if (begins_with(label_view, U"xn--")) {
9671
      // we do not need to check, e.g., Xn-- because mapping goes to lower case
9672
23.9k
      for (char32_t c : label_view) {
9673
23.9k
        if (c >= 0x80) {
9674
21
          return error;
9675
21
        }
9676
23.9k
        out += (unsigned char)(c);
9677
23.9k
      }
9678
2.08k
      std::string_view puny_segment_ascii(
9679
2.08k
          out.data() + out.size() - label_view.size() + 4,
9680
2.08k
          label_view.size() - 4);
9681
2.08k
      std::u32string tmp_buffer;
9682
2.08k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9683
2.08k
      if (!is_ok) {
9684
63
        return error;
9685
63
      }
9686
2.02k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9687
2.02k
      if (tmp_buffer != post_map) {
9688
75
        return error;
9689
75
      }
9690
1.94k
      std::u32string pre_normal = post_map;
9691
1.94k
      normalize(post_map);
9692
1.94k
      if (post_map != pre_normal) {
9693
41
        return error;
9694
41
      }
9695
1.90k
      if (post_map.empty()) {
9696
74
        return error;
9697
74
      }
9698
1.83k
      if (!is_label_valid(post_map)) {
9699
14
        return error;
9700
14
      }
9701
29.8k
    } else {
9702
      // The fast path here is an ascii label.
9703
29.8k
      if (is_ascii(label_view)) {
9704
        // no validation needed.
9705
25.2k
        for (char32_t c : label_view) {
9706
25.2k
          out += (unsigned char)(c);
9707
25.2k
        }
9708
27.0k
      } else {
9709
        // slow path.
9710
        // first check validity.
9711
27.0k
        if (!is_label_valid(label_view)) {
9712
902
          return error;
9713
902
        }
9714
        // It is valid! So now we must encode it as punycode...
9715
26.1k
        out.append("xn--");
9716
26.1k
        bool is_ok = ada::idna::utf32_to_punycode(label_view, out);
9717
26.1k
        if (!is_ok) {
9718
0
          return error;
9719
0
        }
9720
26.1k
      }
9721
29.8k
    }
9722
32.6k
    if (!is_last_label) {
9723
27.4k
      out.push_back('.');
9724
27.4k
    }
9725
32.6k
  }
9726
5.60k
  return out;
9727
6.79k
}
9728
}  // namespace ada::idna
9729
/* end file src/to_ascii.cpp */
9730
/* begin file src/to_unicode.cpp */
9731
9732
#include <algorithm>
9733
#include <string>
9734
9735
9736
namespace ada::idna {
9737
13.9k
std::string to_unicode(std::string_view input) {
9738
13.9k
  std::string output;
9739
13.9k
  output.reserve(input.size());
9740
9741
13.9k
  size_t label_start = 0;
9742
45.1k
  while (label_start < input.size()) {
9743
31.1k
    size_t loc_dot = input.find('.', label_start);
9744
31.1k
    bool is_last_label = (loc_dot == std::string_view::npos);
9745
31.1k
    size_t label_size =
9746
31.1k
        is_last_label ? input.size() - label_start : loc_dot - label_start;
9747
31.1k
    auto label_view = std::string_view(input.data() + label_start, label_size);
9748
9749
31.1k
    if (ada::idna::begins_with(label_view, "xn--") &&
9750
31.1k
        ada::idna::is_ascii(label_view)) {
9751
2.08k
      label_view.remove_prefix(4);
9752
2.08k
      if (ada::idna::verify_punycode(label_view)) {
9753
1.36k
        std::u32string tmp_buffer;
9754
1.36k
        if (ada::idna::punycode_to_utf32(label_view, tmp_buffer)) {
9755
1.36k
          auto utf8_size = ada::idna::utf8_length_from_utf32(tmp_buffer.data(),
9756
1.36k
                                                             tmp_buffer.size());
9757
1.36k
          std::string final_utf8(utf8_size, '\0');
9758
1.36k
          ada::idna::utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9759
1.36k
                                   final_utf8.data());
9760
1.36k
          output.append(final_utf8);
9761
1.36k
        } else {
9762
          // ToUnicode never fails.  If any step fails, then the original input
9763
          // sequence is returned immediately in that step.
9764
0
          output.append(
9765
0
              std::string_view(input.data() + label_start, label_size));
9766
0
        }
9767
1.36k
      } else {
9768
728
        output.append(std::string_view(input.data() + label_start, label_size));
9769
728
      }
9770
29.0k
    } else {
9771
29.0k
      output.append(label_view);
9772
29.0k
    }
9773
9774
31.1k
    if (!is_last_label) {
9775
19.1k
      output.push_back('.');
9776
19.1k
    }
9777
9778
31.1k
    label_start += label_size + 1;
9779
31.1k
  }
9780
9781
13.9k
  return output;
9782
13.9k
}
9783
}  // namespace ada::idna
9784
/* end file src/to_unicode.cpp */
9785
/* end file src/idna.cpp */
9786
/* end file src/ada_idna.cpp */
9787
ADA_POP_DISABLE_WARNINGS
9788
9789
#include <algorithm>
9790
#if ADA_NEON
9791
#include <arm_neon.h>
9792
#elif ADA_SSE2
9793
#include <emmintrin.h>
9794
#endif
9795
9796
namespace ada::unicode {
9797
9798
88.5k
constexpr uint64_t broadcast(uint8_t v) noexcept {
9799
88.5k
  return 0x101010101010101ull * v;
9800
88.5k
}
9801
9802
29.5k
constexpr bool to_lower_ascii(char* input, size_t length) noexcept {
9803
29.5k
  uint64_t broadcast_80 = broadcast(0x80);
9804
29.5k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
9805
29.5k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
9806
29.5k
  uint64_t non_ascii = 0;
9807
29.5k
  size_t i = 0;
9808
9809
45.7k
  for (; i + 7 < length; i += 8) {
9810
16.2k
    uint64_t word{};
9811
16.2k
    memcpy(&word, input + i, sizeof(word));
9812
16.2k
    non_ascii |= (word & broadcast_80);
9813
16.2k
    word ^=
9814
16.2k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
9815
16.2k
    memcpy(input + i, &word, sizeof(word));
9816
16.2k
  }
9817
29.5k
  if (i < length) {
9818
28.9k
    uint64_t word{};
9819
28.9k
    memcpy(&word, input + i, length - i);
9820
28.9k
    non_ascii |= (word & broadcast_80);
9821
28.9k
    word ^=
9822
28.9k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
9823
28.9k
    memcpy(input + i, &word, length - i);
9824
28.9k
  }
9825
29.5k
  return non_ascii == 0;
9826
29.5k
}
9827
#if ADA_NEON
9828
ada_really_inline bool has_tabs_or_newline(
9829
    std::string_view user_input) noexcept {
9830
  // first check for short strings in which case we do it naively.
9831
  if (user_input.size() < 16) {  // slow path
9832
    for (size_t i = 0; i < user_input.size(); i++) {
9833
      if (user_input[i] == '\r' || user_input[i] == '\n' ||
9834
          user_input[i] == '\t') {
9835
        return true;
9836
      }
9837
    }
9838
    return false;
9839
  }
9840
  // fast path for long strings (expected to be common)
9841
  size_t i = 0;
9842
  const uint8x16_t mask1 = vmovq_n_u8('\r');
9843
  const uint8x16_t mask2 = vmovq_n_u8('\n');
9844
  const uint8x16_t mask3 = vmovq_n_u8('\t');
9845
  uint8x16_t running{0};
9846
  for (; i + 15 < user_input.size(); i += 16) {
9847
    uint8x16_t word = vld1q_u8((const uint8_t*)user_input.data() + i);
9848
    running = vorrq_u8(vorrq_u8(running, vorrq_u8(vceqq_u8(word, mask1),
9849
                                                  vceqq_u8(word, mask2))),
9850
                       vceqq_u8(word, mask3));
9851
  }
9852
  if (i < user_input.size()) {
9853
    uint8x16_t word =
9854
        vld1q_u8((const uint8_t*)user_input.data() + user_input.length() - 16);
9855
    running = vorrq_u8(vorrq_u8(running, vorrq_u8(vceqq_u8(word, mask1),
9856
                                                  vceqq_u8(word, mask2))),
9857
                       vceqq_u8(word, mask3));
9858
  }
9859
  return vmaxvq_u8(running) != 0;
9860
}
9861
#elif ADA_SSE2
9862
ada_really_inline bool has_tabs_or_newline(
9863
87.3k
    std::string_view user_input) noexcept {
9864
  // first check for short strings in which case we do it naively.
9865
87.3k
  if (user_input.size() < 16) {  // slow path
9866
336k
    for (size_t i = 0; i < user_input.size(); i++) {
9867
263k
      if (user_input[i] == '\r' || user_input[i] == '\n' ||
9868
263k
          user_input[i] == '\t') {
9869
633
        return true;
9870
633
      }
9871
263k
    }
9872
72.4k
    return false;
9873
73.0k
  }
9874
  // fast path for long strings (expected to be common)
9875
14.2k
  size_t i = 0;
9876
14.2k
  const __m128i mask1 = _mm_set1_epi8('\r');
9877
14.2k
  const __m128i mask2 = _mm_set1_epi8('\n');
9878
14.2k
  const __m128i mask3 = _mm_set1_epi8('\t');
9879
14.2k
  __m128i running{0};
9880
73.2k
  for (; i + 15 < user_input.size(); i += 16) {
9881
58.9k
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
9882
58.9k
    running = _mm_or_si128(
9883
58.9k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
9884
58.9k
                                           _mm_cmpeq_epi8(word, mask2))),
9885
58.9k
        _mm_cmpeq_epi8(word, mask3));
9886
58.9k
  }
9887
14.2k
  if (i < user_input.size()) {
9888
11.9k
    __m128i word = _mm_loadu_si128(
9889
11.9k
        (const __m128i*)(user_input.data() + user_input.length() - 16));
9890
11.9k
    running = _mm_or_si128(
9891
11.9k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
9892
11.9k
                                           _mm_cmpeq_epi8(word, mask2))),
9893
11.9k
        _mm_cmpeq_epi8(word, mask3));
9894
11.9k
  }
9895
14.2k
  return _mm_movemask_epi8(running) != 0;
9896
87.3k
}
9897
#else
9898
ada_really_inline bool has_tabs_or_newline(
9899
    std::string_view user_input) noexcept {
9900
  auto has_zero_byte = [](uint64_t v) {
9901
    return ((v - 0x0101010101010101) & ~(v)&0x8080808080808080);
9902
  };
9903
  size_t i = 0;
9904
  uint64_t mask1 = broadcast('\r');
9905
  uint64_t mask2 = broadcast('\n');
9906
  uint64_t mask3 = broadcast('\t');
9907
  uint64_t running{0};
9908
  for (; i + 7 < user_input.size(); i += 8) {
9909
    uint64_t word{};
9910
    memcpy(&word, user_input.data() + i, sizeof(word));
9911
    uint64_t xor1 = word ^ mask1;
9912
    uint64_t xor2 = word ^ mask2;
9913
    uint64_t xor3 = word ^ mask3;
9914
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
9915
  }
9916
  if (i < user_input.size()) {
9917
    uint64_t word{};
9918
    memcpy(&word, user_input.data() + i, user_input.size() - i);
9919
    uint64_t xor1 = word ^ mask1;
9920
    uint64_t xor2 = word ^ mask2;
9921
    uint64_t xor3 = word ^ mask3;
9922
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
9923
  }
9924
  return running;
9925
}
9926
#endif
9927
9928
// A forbidden host code point is U+0000 NULL, U+0009 TAB, U+000A LF, U+000D CR,
9929
// U+0020 SPACE, U+0023 (#), U+002F (/), U+003A (:), U+003C (<), U+003E (>),
9930
// U+003F (?), U+0040 (@), U+005B ([), U+005C (\), U+005D (]), U+005E (^), or
9931
// U+007C (|).
9932
constexpr static std::array<uint8_t, 256> is_forbidden_host_code_point_table =
9933
    []() constexpr {
9934
      std::array<uint8_t, 256> result{};
9935
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
9936
                        '>', '?', '@', '[', '\\', ']', '^', '|'}) {
9937
        result[c] = true;
9938
      }
9939
      return result;
9940
    }();
9941
9942
ada_really_inline constexpr bool is_forbidden_host_code_point(
9943
38.1k
    const char c) noexcept {
9944
38.1k
  return is_forbidden_host_code_point_table[uint8_t(c)];
9945
38.1k
}
9946
9947
constexpr static std::array<uint8_t, 256> is_forbidden_domain_code_point_table =
9948
    []() constexpr {
9949
      std::array<uint8_t, 256> result{};
9950
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
9951
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
9952
        result[c] = true;
9953
      }
9954
      for (uint8_t c = 0; c <= 32; c++) {
9955
        result[c] = true;
9956
      }
9957
      for (size_t c = 127; c < 255; c++) {
9958
        result[c] = true;
9959
      }
9960
      return result;
9961
    }();
9962
9963
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
9964
9965
ada_really_inline constexpr bool is_forbidden_domain_code_point(
9966
535k
    const char c) noexcept {
9967
535k
  return is_forbidden_domain_code_point_table[uint8_t(c)];
9968
535k
}
9969
9970
ada_really_inline constexpr bool contains_forbidden_domain_code_point(
9971
15.7k
    const char* input, size_t length) noexcept {
9972
15.7k
  size_t i = 0;
9973
15.7k
  uint8_t accumulator{};
9974
186k
  for (; i + 4 <= length; i += 4) {
9975
170k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
9976
170k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 1])];
9977
170k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 2])];
9978
170k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 3])];
9979
170k
  }
9980
38.8k
  for (; i < length; i++) {
9981
23.0k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
9982
23.0k
  }
9983
15.7k
  return accumulator;
9984
15.7k
}
9985
9986
constexpr static std::array<uint8_t, 256>
9987
    is_forbidden_domain_code_point_table_or_upper = []() constexpr {
9988
      std::array<uint8_t, 256> result{};
9989
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
9990
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
9991
        result[c] = 1;
9992
      }
9993
      for (uint8_t c = 'A'; c <= 'Z'; c++) {
9994
        result[c] = 2;
9995
      }
9996
      for (uint8_t c = 0; c <= 32; c++) {
9997
        result[c] = 1;
9998
      }
9999
      for (size_t c = 127; c < 255; c++) {
10000
        result[c] = 1;
10001
      }
10002
      return result;
10003
    }();
10004
10005
ada_really_inline constexpr uint8_t
10006
contains_forbidden_domain_code_point_or_upper(const char* input,
10007
14.9k
                                              size_t length) noexcept {
10008
14.9k
  size_t i = 0;
10009
14.9k
  uint8_t accumulator{};
10010
86.9k
  for (; i + 4 <= length; i += 4) {
10011
71.9k
    accumulator |=
10012
71.9k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10013
71.9k
    accumulator |=
10014
71.9k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 1])];
10015
71.9k
    accumulator |=
10016
71.9k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 2])];
10017
71.9k
    accumulator |=
10018
71.9k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 3])];
10019
71.9k
  }
10020
35.5k
  for (; i < length; i++) {
10021
20.6k
    accumulator |=
10022
20.6k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10023
20.6k
  }
10024
14.9k
  return accumulator;
10025
14.9k
}
10026
10027
// std::isalnum(c) || c == '+' || c == '-' || c == '.') is true for
10028
constexpr static std::array<bool, 256> is_alnum_plus_table = []() constexpr {
10029
  std::array<bool, 256> result{};
10030
  for (size_t c = 0; c < 256; c++) {
10031
    if (c >= '0' && c <= '9') {
10032
      result[c] = true;
10033
    } else if (c >= 'a' && c <= 'z') {
10034
      result[c] = true;
10035
    } else if (c >= 'A' && c <= 'Z') {
10036
      result[c] = true;
10037
    } else if (c == '+' || c == '-' || c == '.') {
10038
      result[c] = true;
10039
    }
10040
  }
10041
  return result;
10042
}();
10043
10044
125k
ada_really_inline constexpr bool is_alnum_plus(const char c) noexcept {
10045
125k
  return is_alnum_plus_table[uint8_t(c)];
10046
  // A table is almost surely much faster than the
10047
  // following under most compilers: return
10048
  // return (std::isalnum(c) || c == '+' || c == '-' || c == '.');
10049
125k
}
10050
10051
38.3k
ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept {
10052
38.3k
  return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
10053
38.3k
         (c >= 'a' && c <= 'f');
10054
38.3k
}
10055
10056
98.2k
ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept {
10057
98.2k
  return (unsigned char)c <= ' ';
10058
98.2k
}
10059
10060
ada_really_inline constexpr bool is_ascii_tab_or_newline(
10061
794k
    const char c) noexcept {
10062
794k
  return c == '\t' || c == '\n' || c == '\r';
10063
794k
}
10064
10065
constexpr std::string_view table_is_double_dot_path_segment[] = {
10066
    "..", "%2e.", ".%2e", "%2e%2e"};
10067
10068
ada_really_inline ada_constexpr bool is_double_dot_path_segment(
10069
75.2k
    std::string_view input) noexcept {
10070
  // This will catch most cases:
10071
  // The length must be 2,4 or 6.
10072
  // We divide by two and require
10073
  // that the result be between 1 and 3 inclusively.
10074
75.2k
  uint64_t half_length = uint64_t(input.size()) / 2;
10075
75.2k
  if (half_length - 1 > 2) {
10076
41.4k
    return false;
10077
41.4k
  }
10078
  // We have a string of length 2, 4 or 6.
10079
  // We now check the first character:
10080
33.7k
  if ((input[0] != '.') && (input[0] != '%')) {
10081
7.51k
    return false;
10082
7.51k
  }
10083
  // We are unlikely the get beyond this point.
10084
26.2k
  int hash_value = (input.size() + (unsigned)(input[0])) & 3;
10085
26.2k
  const std::string_view target = table_is_double_dot_path_segment[hash_value];
10086
26.2k
  if (target.size() != input.size()) {
10087
8.46k
    return false;
10088
8.46k
  }
10089
  // We almost never get here.
10090
  // Optimizing the rest is relatively unimportant.
10091
17.7k
  auto prefix_equal_unsafe = [](std::string_view a, std::string_view b) {
10092
17.7k
    uint16_t A, B;
10093
17.7k
    memcpy(&A, a.data(), sizeof(A));
10094
17.7k
    memcpy(&B, b.data(), sizeof(B));
10095
17.7k
    return A == B;
10096
17.7k
  };
10097
17.7k
  if (!prefix_equal_unsafe(input, target)) {
10098
1.62k
    return false;
10099
1.62k
  }
10100
22.1k
  for (size_t i = 2; i < input.size(); i++) {
10101
9.08k
    char c = input[i];
10102
9.08k
    if ((uint8_t((c | 0x20) - 0x61) <= 25 ? (c | 0x20) : c) != target[i]) {
10103
3.07k
      return false;
10104
3.07k
    }
10105
9.08k
  }
10106
13.0k
  return true;
10107
  // The above code might be a bit better than the code below. Compilers
10108
  // are not stupid and may use the fact that these strings have length 2,4 and
10109
  // 6 and other tricks.
10110
  // return input == ".." ||
10111
  //  input == ".%2e" || input == ".%2E" ||
10112
  //  input == "%2e." || input == "%2E." ||
10113
  //  input == "%2e%2e" || input == "%2E%2E" || input == "%2E%2e" || input ==
10114
  //  "%2e%2E";
10115
16.1k
}
10116
10117
ada_really_inline constexpr bool is_single_dot_path_segment(
10118
123k
    std::string_view input) noexcept {
10119
123k
  return input == "." || input == "%2e" || input == "%2E";
10120
123k
}
10121
10122
32.1k
ada_really_inline constexpr bool is_lowercase_hex(const char c) noexcept {
10123
32.1k
  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
10124
32.1k
}
10125
10126
constexpr static char hex_to_binary_table[] = {
10127
    0,  1,  2,  3,  4, 5, 6, 7, 8, 9, 0, 0,  0,  0,  0,  0,  0, 10, 11,
10128
    12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0,  0,
10129
    0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
10130
34.3k
unsigned constexpr convert_hex_to_binary(const char c) noexcept {
10131
34.3k
  return hex_to_binary_table[c - '0'];
10132
34.3k
}
10133
10134
6.93k
std::string percent_decode(const std::string_view input, size_t first_percent) {
10135
  // next line is for safety only, we expect users to avoid calling
10136
  // percent_decode when first_percent is outside the range.
10137
6.93k
  if (first_percent == std::string_view::npos) {
10138
5.59k
    return std::string(input);
10139
5.59k
  }
10140
1.34k
  std::string dest;
10141
1.34k
  dest.reserve(input.length());
10142
1.34k
  dest.append(input.substr(0, first_percent));
10143
1.34k
  const char* pointer = input.data() + first_percent;
10144
1.34k
  const char* end = input.data() + input.size();
10145
  // Optimization opportunity: if the following code gets
10146
  // called often, it can be optimized quite a bit.
10147
24.9k
  while (pointer < end) {
10148
23.6k
    const char ch = pointer[0];
10149
23.6k
    size_t remaining = end - pointer - 1;
10150
23.6k
    if (ch != '%' || remaining < 2 ||
10151
23.6k
        (  // ch == '%' && // It is unnecessary to check that ch == '%'.
10152
15.9k
            (!is_ascii_hex_digit(pointer[1]) ||
10153
15.9k
             !is_ascii_hex_digit(pointer[2])))) {
10154
8.94k
      dest += ch;
10155
8.94k
      pointer++;
10156
8.94k
      continue;
10157
14.6k
    } else {
10158
14.6k
      unsigned a = convert_hex_to_binary(pointer[1]);
10159
14.6k
      unsigned b = convert_hex_to_binary(pointer[2]);
10160
14.6k
      char c = static_cast<char>(a * 16 + b);
10161
14.6k
      dest += c;
10162
14.6k
      pointer += 3;
10163
14.6k
    }
10164
23.6k
  }
10165
1.34k
  return dest;
10166
6.93k
}
10167
10168
std::string percent_encode(const std::string_view input,
10169
57.2k
                           const uint8_t character_set[]) {
10170
57.2k
  auto pointer =
10171
268k
      std::find_if(input.begin(), input.end(), [character_set](const char c) {
10172
268k
        return character_sets::bit_at(character_set, c);
10173
268k
      });
10174
  // Optimization: Don't iterate if percent encode is not required
10175
57.2k
  if (pointer == input.end()) {
10176
42.3k
    return std::string(input);
10177
42.3k
  }
10178
10179
14.9k
  std::string result;
10180
14.9k
  result.reserve(input.length());  // in the worst case, percent encoding might
10181
                                   // produce 3 characters.
10182
14.9k
  result.append(input.substr(0, std::distance(input.begin(), pointer)));
10183
10184
423k
  for (; pointer != input.end(); pointer++) {
10185
408k
    if (character_sets::bit_at(character_set, *pointer)) {
10186
293k
      result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10187
293k
    } else {
10188
115k
      result += *pointer;
10189
115k
    }
10190
408k
  }
10191
10192
14.9k
  return result;
10193
57.2k
}
10194
10195
template <bool append>
10196
bool percent_encode(const std::string_view input, const uint8_t character_set[],
10197
43.8k
                    std::string& out) {
10198
43.8k
  ada_log("percent_encode ", input, " to output string while ",
10199
43.8k
          append ? "appending" : "overwriting");
10200
43.8k
  auto pointer =
10201
97.2k
      std::find_if(input.begin(), input.end(), [character_set](const char c) {
10202
97.2k
        return character_sets::bit_at(character_set, c);
10203
97.2k
      });
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
10201
68.4k
      std::find_if(input.begin(), input.end(), [character_set](const char c) {
10202
68.4k
        return character_sets::bit_at(character_set, c);
10203
68.4k
      });
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
10201
28.8k
      std::find_if(input.begin(), input.end(), [character_set](const char c) {
10202
28.8k
        return character_sets::bit_at(character_set, c);
10203
28.8k
      });
10204
43.8k
  ada_log("percent_encode done checking, moved to ",
10205
43.8k
          std::distance(input.begin(), pointer));
10206
10207
  // Optimization: Don't iterate if percent encode is not required
10208
43.8k
  if (pointer == input.end()) {
10209
25.2k
    ada_log("percent_encode encoding not needed.");
10210
25.2k
    return false;
10211
25.2k
  }
10212
18.6k
  if (!append) {
10213
17.2k
    out.clear();
10214
17.2k
  }
10215
18.6k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10216
18.6k
          " bytes");
10217
18.6k
  out.append(input.data(), std::distance(input.begin(), pointer));
10218
18.6k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10219
18.6k
          " bytes");
10220
267k
  for (; pointer != input.end(); pointer++) {
10221
248k
    if (character_sets::bit_at(character_set, *pointer)) {
10222
199k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10223
199k
    } else {
10224
49.0k
      out += *pointer;
10225
49.0k
    }
10226
248k
  }
10227
18.6k
  return true;
10228
43.8k
}
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
10197
39.4k
                    std::string& out) {
10198
39.4k
  ada_log("percent_encode ", input, " to output string while ",
10199
39.4k
          append ? "appending" : "overwriting");
10200
39.4k
  auto pointer =
10201
39.4k
      std::find_if(input.begin(), input.end(), [character_set](const char c) {
10202
39.4k
        return character_sets::bit_at(character_set, c);
10203
39.4k
      });
10204
39.4k
  ada_log("percent_encode done checking, moved to ",
10205
39.4k
          std::distance(input.begin(), pointer));
10206
10207
  // Optimization: Don't iterate if percent encode is not required
10208
39.4k
  if (pointer == input.end()) {
10209
22.2k
    ada_log("percent_encode encoding not needed.");
10210
22.2k
    return false;
10211
22.2k
  }
10212
17.2k
  if (!append) {
10213
17.2k
    out.clear();
10214
17.2k
  }
10215
17.2k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10216
17.2k
          " bytes");
10217
17.2k
  out.append(input.data(), std::distance(input.begin(), pointer));
10218
17.2k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10219
17.2k
          " bytes");
10220
210k
  for (; pointer != input.end(); pointer++) {
10221
193k
    if (character_sets::bit_at(character_set, *pointer)) {
10222
157k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10223
157k
    } else {
10224
35.7k
      out += *pointer;
10225
35.7k
    }
10226
193k
  }
10227
17.2k
  return true;
10228
39.4k
}
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
10197
4.37k
                    std::string& out) {
10198
4.37k
  ada_log("percent_encode ", input, " to output string while ",
10199
4.37k
          append ? "appending" : "overwriting");
10200
4.37k
  auto pointer =
10201
4.37k
      std::find_if(input.begin(), input.end(), [character_set](const char c) {
10202
4.37k
        return character_sets::bit_at(character_set, c);
10203
4.37k
      });
10204
4.37k
  ada_log("percent_encode done checking, moved to ",
10205
4.37k
          std::distance(input.begin(), pointer));
10206
10207
  // Optimization: Don't iterate if percent encode is not required
10208
4.37k
  if (pointer == input.end()) {
10209
2.97k
    ada_log("percent_encode encoding not needed.");
10210
2.97k
    return false;
10211
2.97k
  }
10212
1.40k
  if (!append) {
10213
0
    out.clear();
10214
0
  }
10215
1.40k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10216
1.40k
          " bytes");
10217
1.40k
  out.append(input.data(), std::distance(input.begin(), pointer));
10218
1.40k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10219
1.40k
          " bytes");
10220
56.1k
  for (; pointer != input.end(); pointer++) {
10221
54.7k
    if (character_sets::bit_at(character_set, *pointer)) {
10222
41.4k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10223
41.4k
    } else {
10224
13.2k
      out += *pointer;
10225
13.2k
    }
10226
54.7k
  }
10227
1.40k
  return true;
10228
4.37k
}
10229
10230
bool to_ascii(std::optional<std::string>& out, const std::string_view plain,
10231
10.1k
              size_t first_percent) {
10232
10.1k
  std::string percent_decoded_buffer;
10233
10.1k
  std::string_view input = plain;
10234
10.1k
  if (first_percent != std::string_view::npos) {
10235
921
    percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
10236
921
    input = percent_decoded_buffer;
10237
921
  }
10238
  // input is a non-empty UTF-8 string, must be percent decoded
10239
10.1k
  std::string idna_ascii = ada::idna::to_ascii(input);
10240
10.1k
  if (idna_ascii.empty() || contains_forbidden_domain_code_point(
10241
7.90k
                                idna_ascii.data(), idna_ascii.size())) {
10242
3.22k
    return false;
10243
3.22k
  }
10244
6.92k
  out = std::move(idna_ascii);
10245
6.92k
  return true;
10246
10.1k
}
10247
10248
std::string percent_encode(const std::string_view input,
10249
1.63k
                           const uint8_t character_set[], size_t index) {
10250
1.63k
  std::string out;
10251
1.63k
  out.append(input.data(), index);
10252
1.63k
  auto pointer = input.begin() + index;
10253
59.9k
  for (; pointer != input.end(); pointer++) {
10254
58.2k
    if (character_sets::bit_at(character_set, *pointer)) {
10255
49.9k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10256
49.9k
    } else {
10257
8.29k
      out += *pointer;
10258
8.29k
    }
10259
58.2k
  }
10260
1.63k
  return out;
10261
1.63k
}
10262
10263
0
std::string to_unicode(std::string_view input) {
10264
0
  return ada::idna::to_unicode(input);
10265
0
}
10266
10267
}  // namespace ada::unicode
10268
/* end file src/unicode.cpp */
10269
/* begin file src/serializers.cpp */
10270
10271
#include <array>
10272
#include <string>
10273
10274
namespace ada::serializers {
10275
10276
void find_longest_sequence_of_ipv6_pieces(
10277
    const std::array<uint16_t, 8>& address, size_t& compress,
10278
622
    size_t& compress_length) noexcept {
10279
2.45k
  for (size_t i = 0; i < 8; i++) {
10280
2.05k
    if (address[i] == 0) {
10281
735
      size_t next = i + 1;
10282
3.37k
      while (next != 8 && address[next] == 0) ++next;
10283
735
      const size_t count = next - i;
10284
735
      if (compress_length < count) {
10285
571
        compress_length = count;
10286
571
        compress = i;
10287
571
        if (next == 8) break;
10288
348
        i = next;
10289
348
      }
10290
735
    }
10291
2.05k
  }
10292
622
}
10293
10294
622
std::string ipv6(const std::array<uint16_t, 8>& address) noexcept {
10295
622
  size_t compress_length = 0;  // The length of a long sequence of zeros.
10296
622
  size_t compress = 0;         // The start of a long sequence of zeros.
10297
622
  find_longest_sequence_of_ipv6_pieces(address, compress, compress_length);
10298
10299
622
  if (compress_length <= 1) {
10300
    // Optimization opportunity: Find a faster way then snprintf for imploding
10301
    // and return here.
10302
121
    compress = compress_length = 8;
10303
121
  }
10304
10305
622
  std::string output(4 * 8 + 7 + 2, '\0');
10306
622
  size_t piece_index = 0;
10307
622
  char* point = output.data();
10308
622
  char* point_end = output.data() + output.size();
10309
622
  *point++ = '[';
10310
2.12k
  while (true) {
10311
2.12k
    if (piece_index == compress) {
10312
501
      *point++ = ':';
10313
      // If we skip a value initially, we need to write '::', otherwise
10314
      // a single ':' will do since it follows a previous ':'.
10315
501
      if (piece_index == 0) {
10316
290
        *point++ = ':';
10317
290
      }
10318
501
      piece_index += compress_length;
10319
501
      if (piece_index == 8) {
10320
217
        break;
10321
217
      }
10322
501
    }
10323
1.91k
    point = std::to_chars(point, point_end, address[piece_index], 16).ptr;
10324
1.91k
    piece_index++;
10325
1.91k
    if (piece_index == 8) {
10326
405
      break;
10327
405
    }
10328
1.50k
    *point++ = ':';
10329
1.50k
  }
10330
622
  *point++ = ']';
10331
622
  output.resize(point - output.data());
10332
622
  return output;
10333
622
}
10334
10335
4.04k
std::string ipv4(const uint64_t address) noexcept {
10336
4.04k
  std::string output(15, '\0');
10337
4.04k
  char* point = output.data();
10338
4.04k
  char* point_end = output.data() + output.size();
10339
4.04k
  point = std::to_chars(point, point_end, uint8_t(address >> 24)).ptr;
10340
16.1k
  for (int i = 2; i >= 0; i--) {
10341
12.1k
    *point++ = '.';
10342
12.1k
    point = std::to_chars(point, point_end, uint8_t(address >> (i * 8))).ptr;
10343
12.1k
  }
10344
4.04k
  output.resize(point - output.data());
10345
4.04k
  return output;
10346
4.04k
}
10347
10348
}  // namespace ada::serializers
10349
/* end file src/serializers.cpp */
10350
/* begin file src/implementation.cpp */
10351
#include <string_view>
10352
10353
10354
namespace ada {
10355
10356
template <class result_type>
10357
ada_warn_unused tl::expected<result_type, ada::errors> parse(
10358
59.3k
    std::string_view input, const result_type* base_url) {
10359
59.3k
  result_type u = ada::parser::parse_url<result_type>(input, base_url);
10360
59.3k
  if (!u.is_valid) {
10361
30.3k
    return tl::unexpected(errors::generic_error);
10362
30.3k
  }
10363
29.0k
  return u;
10364
59.3k
}
tl::expected<ada::url, ada::errors> ada::parse<ada::url>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url const*)
Line
Count
Source
10358
14.3k
    std::string_view input, const result_type* base_url) {
10359
14.3k
  result_type u = ada::parser::parse_url<result_type>(input, base_url);
10360
14.3k
  if (!u.is_valid) {
10361
6.26k
    return tl::unexpected(errors::generic_error);
10362
6.26k
  }
10363
8.11k
  return u;
10364
14.3k
}
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
10358
45.0k
    std::string_view input, const result_type* base_url) {
10359
45.0k
  result_type u = ada::parser::parse_url<result_type>(input, base_url);
10360
45.0k
  if (!u.is_valid) {
10361
24.0k
    return tl::unexpected(errors::generic_error);
10362
24.0k
  }
10363
20.9k
  return u;
10364
45.0k
}
10365
10366
template ada::result<url> parse<url>(std::string_view input,
10367
                                     const url* base_url = nullptr);
10368
template ada::result<url_aggregator> parse<url_aggregator>(
10369
    std::string_view input, const url_aggregator* base_url = nullptr);
10370
10371
13.9k
std::string href_from_file(std::string_view input) {
10372
  // This is going to be much faster than constructing a URL.
10373
13.9k
  std::string tmp_buffer;
10374
13.9k
  std::string_view internal_input;
10375
13.9k
  if (unicode::has_tabs_or_newline(input)) {
10376
195
    tmp_buffer = input;
10377
195
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
10378
195
    internal_input = tmp_buffer;
10379
13.7k
  } else {
10380
13.7k
    internal_input = input;
10381
13.7k
  }
10382
13.9k
  std::string path;
10383
13.9k
  if (internal_input.empty()) {
10384
1.14k
    path = "/";
10385
12.8k
  } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
10386
716
    helpers::parse_prepared_path(internal_input.substr(1),
10387
716
                                 ada::scheme::type::FILE, path);
10388
12.1k
  } else {
10389
12.1k
    helpers::parse_prepared_path(internal_input, ada::scheme::type::FILE, path);
10390
12.1k
  }
10391
13.9k
  return "file://" + path;
10392
13.9k
}
10393
10394
27.9k
bool can_parse(std::string_view input, const std::string_view* base_input) {
10395
27.9k
  ada::result<ada::url_aggregator> base;
10396
27.9k
  ada::url_aggregator* base_pointer = nullptr;
10397
27.9k
  if (base_input != nullptr) {
10398
13.9k
    base = ada::parse<url_aggregator>(*base_input);
10399
13.9k
    if (!base) {
10400
11.3k
      return false;
10401
11.3k
    }
10402
2.64k
    base_pointer = &base.value();
10403
2.64k
  }
10404
16.6k
  return ada::parse<url_aggregator>(input, base_pointer).has_value();
10405
27.9k
}
10406
10407
0
ada_warn_unused std::string to_string(ada::encoding_type type) {
10408
0
  switch (type) {
10409
0
    case ada::encoding_type::UTF8:
10410
0
      return "UTF-8";
10411
0
    case ada::encoding_type::UTF_16LE:
10412
0
      return "UTF-16LE";
10413
0
    case ada::encoding_type::UTF_16BE:
10414
0
      return "UTF-16BE";
10415
0
    default:
10416
0
      unreachable();
10417
0
  }
10418
0
}
10419
10420
}  // namespace ada
10421
/* end file src/implementation.cpp */
10422
/* begin file src/helpers.cpp */
10423
10424
#include <algorithm>
10425
#include <charconv>
10426
#include <cstring>
10427
#include <sstream>
10428
10429
namespace ada::helpers {
10430
10431
template <typename out_iter>
10432
0
void encode_json(std::string_view view, out_iter out) {
10433
  // trivial implementation. could be faster.
10434
0
  const char* hexvalues =
10435
0
      "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
10436
0
  for (uint8_t c : view) {
10437
0
    if (c == '\\') {
10438
0
      *out++ = '\\';
10439
0
      *out++ = '\\';
10440
0
    } else if (c == '"') {
10441
0
      *out++ = '\\';
10442
0
      *out++ = '"';
10443
0
    } else if (c <= 0x1f) {
10444
0
      *out++ = '\\';
10445
0
      *out++ = 'u';
10446
0
      *out++ = '0';
10447
0
      *out++ = '0';
10448
0
      *out++ = hexvalues[2 * c];
10449
0
      *out++ = hexvalues[2 * c + 1];
10450
0
    } else {
10451
0
      *out++ = c;
10452
0
    }
10453
0
  }
10454
0
}
10455
10456
0
ada_unused std::string get_state(ada::state s) {
10457
0
  switch (s) {
10458
0
    case ada::state::AUTHORITY:
10459
0
      return "Authority";
10460
0
    case ada::state::SCHEME_START:
10461
0
      return "Scheme Start";
10462
0
    case ada::state::SCHEME:
10463
0
      return "Scheme";
10464
0
    case ada::state::HOST:
10465
0
      return "Host";
10466
0
    case ada::state::NO_SCHEME:
10467
0
      return "No Scheme";
10468
0
    case ada::state::FRAGMENT:
10469
0
      return "Fragment";
10470
0
    case ada::state::RELATIVE_SCHEME:
10471
0
      return "Relative Scheme";
10472
0
    case ada::state::RELATIVE_SLASH:
10473
0
      return "Relative Slash";
10474
0
    case ada::state::FILE:
10475
0
      return "File";
10476
0
    case ada::state::FILE_HOST:
10477
0
      return "File Host";
10478
0
    case ada::state::FILE_SLASH:
10479
0
      return "File Slash";
10480
0
    case ada::state::PATH_OR_AUTHORITY:
10481
0
      return "Path or Authority";
10482
0
    case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES:
10483
0
      return "Special Authority Ignore Slashes";
10484
0
    case ada::state::SPECIAL_AUTHORITY_SLASHES:
10485
0
      return "Special Authority Slashes";
10486
0
    case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY:
10487
0
      return "Special Relative or Authority";
10488
0
    case ada::state::QUERY:
10489
0
      return "Query";
10490
0
    case ada::state::PATH:
10491
0
      return "Path";
10492
0
    case ada::state::PATH_START:
10493
0
      return "Path Start";
10494
0
    case ada::state::OPAQUE_PATH:
10495
0
      return "Opaque Path";
10496
0
    case ada::state::PORT:
10497
0
      return "Port";
10498
0
    default:
10499
0
      return "unknown state";
10500
0
  }
10501
0
}
10502
10503
ada_really_inline std::optional<std::string_view> prune_hash(
10504
59.3k
    std::string_view& input) noexcept {
10505
  // compiles down to 20--30 instructions including a class to memchr (C
10506
  // function). this function should be quite fast.
10507
59.3k
  size_t location_of_first = input.find('#');
10508
59.3k
  if (location_of_first == std::string_view::npos) {
10509
58.0k
    return std::nullopt;
10510
58.0k
  }
10511
1.30k
  std::string_view hash = input;
10512
1.30k
  hash.remove_prefix(location_of_first + 1);
10513
1.30k
  input.remove_suffix(input.size() - location_of_first);
10514
1.30k
  return hash;
10515
59.3k
}
10516
10517
ada_really_inline bool shorten_path(std::string& path,
10518
13.0k
                                    ada::scheme::type type) noexcept {
10519
13.0k
  size_t first_delimiter = path.find_first_of('/', 1);
10520
10521
  // Let path be url's path.
10522
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
10523
  // Windows drive letter, then return.
10524
13.0k
  if (type == ada::scheme::type::FILE &&
10525
13.0k
      first_delimiter == std::string_view::npos && !path.empty()) {
10526
6.66k
    if (checkers::is_normalized_windows_drive_letter(
10527
6.66k
            helpers::substring(path, 1))) {
10528
1.68k
      return false;
10529
1.68k
    }
10530
6.66k
  }
10531
10532
  // Remove path's last item, if any.
10533
11.3k
  size_t last_delimiter = path.rfind('/');
10534
11.3k
  if (last_delimiter != std::string::npos) {
10535
7.19k
    path.erase(last_delimiter);
10536
7.19k
    return true;
10537
7.19k
  }
10538
10539
4.17k
  return false;
10540
11.3k
}
10541
10542
ada_really_inline bool shorten_path(std::string_view& path,
10543
279
                                    ada::scheme::type type) noexcept {
10544
279
  size_t first_delimiter = path.find_first_of('/', 1);
10545
10546
  // Let path be url's path.
10547
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
10548
  // Windows drive letter, then return.
10549
279
  if (type == ada::scheme::type::FILE &&
10550
279
      first_delimiter == std::string_view::npos && !path.empty()) {
10551
65
    if (checkers::is_normalized_windows_drive_letter(
10552
65
            helpers::substring(path, 1))) {
10553
2
      return false;
10554
2
    }
10555
65
  }
10556
10557
  // Remove path's last item, if any.
10558
277
  if (!path.empty()) {
10559
260
    size_t slash_loc = path.rfind('/');
10560
260
    if (slash_loc != std::string_view::npos) {
10561
244
      path.remove_suffix(path.size() - slash_loc);
10562
244
      return true;
10563
244
    }
10564
260
  }
10565
10566
33
  return false;
10567
277
}
10568
10569
ada_really_inline void remove_ascii_tab_or_newline(
10570
63.9k
    std::string& input) noexcept {
10571
  // if this ever becomes a performance issue, we could use an approach similar
10572
  // to has_tabs_or_newline
10573
63.9k
  input.erase(std::remove_if(input.begin(), input.end(),
10574
794k
                             [](char c) {
10575
794k
                               return ada::unicode::is_ascii_tab_or_newline(c);
10576
794k
                             }),
10577
63.9k
              input.end());
10578
63.9k
}
10579
10580
ada_really_inline std::string_view substring(std::string_view input,
10581
80.6k
                                             size_t pos) noexcept {
10582
80.6k
  ADA_ASSERT_TRUE(pos <= input.size());
10583
  // The following is safer but unneeded if we have the above line:
10584
  // return pos > input.size() ? std::string_view() : input.substr(pos);
10585
80.6k
  return input.substr(pos);
10586
80.6k
}
10587
10588
13
ada_really_inline void resize(std::string_view& input, size_t pos) noexcept {
10589
13
  ADA_ASSERT_TRUE(pos <= input.size());
10590
13
  input.remove_suffix(input.size() - pos);
10591
13
}
10592
10593
// computes the number of trailing zeroes
10594
// this is a private inline function only defined in this source file.
10595
8.24k
ada_really_inline int trailing_zeroes(uint32_t input_num) noexcept {
10596
#ifdef ADA_REGULAR_VISUAL_STUDIO
10597
  unsigned long ret;
10598
  // Search the mask data from least significant bit (LSB)
10599
  // to the most significant bit (MSB) for a set bit (1).
10600
  _BitScanForward(&ret, input_num);
10601
  return (int)ret;
10602
#else   // ADA_REGULAR_VISUAL_STUDIO
10603
8.24k
  return __builtin_ctzl(input_num);
10604
8.24k
#endif  // ADA_REGULAR_VISUAL_STUDIO
10605
8.24k
}
10606
10607
// starting at index location, this finds the next location of a character
10608
// :, /, \\, ? or [. If none is found, view.size() is returned.
10609
// For use within get_host_delimiter_location.
10610
#if ADA_NEON
10611
// The ada_make_uint8x16_t macro is necessary because Visual Studio does not
10612
// support direct initialization of uint8x16_t. See
10613
// https://developercommunity.visualstudio.com/t/error-C2078:-too-many-initializers-whe/402911?q=backend+neon
10614
#ifndef ada_make_uint8x16_t
10615
#define ada_make_uint8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
10616
                            x13, x14, x15, x16)                                \
10617
  ([=]() {                                                                     \
10618
    static uint8_t array[16] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8,          \
10619
                                x9, x10, x11, x12, x13, x14, x15, x16};        \
10620
    return vld1q_u8(array);                                                    \
10621
  }())
10622
#endif
10623
10624
ada_really_inline size_t find_next_host_delimiter_special(
10625
    std::string_view view, size_t location) noexcept {
10626
  // first check for short strings in which case we do it naively.
10627
  if (view.size() - location < 16) {  // slow path
10628
    for (size_t i = location; i < view.size(); i++) {
10629
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
10630
          view[i] == '?' || view[i] == '[') {
10631
        return i;
10632
      }
10633
    }
10634
    return size_t(view.size());
10635
  }
10636
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
10637
    uint8x16_t bit_mask =
10638
        ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
10639
                            0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
10640
    uint8x16_t minput = vandq_u8(input, bit_mask);
10641
    uint8x16_t tmp = vpaddq_u8(minput, minput);
10642
    tmp = vpaddq_u8(tmp, tmp);
10643
    tmp = vpaddq_u8(tmp, tmp);
10644
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
10645
  };
10646
10647
  // fast path for long strings (expected to be common)
10648
  size_t i = location;
10649
  uint8x16_t low_mask =
10650
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
10651
                          0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
10652
  uint8x16_t high_mask =
10653
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
10654
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
10655
  uint8x16_t fmask = vmovq_n_u8(0xf);
10656
  uint8x16_t zero{0};
10657
  for (; i + 15 < view.size(); i += 16) {
10658
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
10659
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
10660
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
10661
    uint8x16_t classify = vandq_u8(lowpart, highpart);
10662
    if (vmaxvq_u8(classify) != 0) {
10663
      uint8x16_t is_zero = vceqq_u8(classify, zero);
10664
      uint16_t is_non_zero = ~to_bitmask(is_zero);
10665
      return i + trailing_zeroes(is_non_zero);
10666
    }
10667
  }
10668
10669
  if (i < view.size()) {
10670
    uint8x16_t word =
10671
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
10672
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
10673
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
10674
    uint8x16_t classify = vandq_u8(lowpart, highpart);
10675
    if (vmaxvq_u8(classify) != 0) {
10676
      uint8x16_t is_zero = vceqq_u8(classify, zero);
10677
      uint16_t is_non_zero = ~to_bitmask(is_zero);
10678
      return view.length() - 16 + trailing_zeroes(is_non_zero);
10679
    }
10680
  }
10681
  return size_t(view.size());
10682
}
10683
#elif ADA_SSE2
10684
ada_really_inline size_t find_next_host_delimiter_special(
10685
38.8k
    std::string_view view, size_t location) noexcept {
10686
  // first check for short strings in which case we do it naively.
10687
38.8k
  if (view.size() - location < 16) {  // slow path
10688
83.9k
    for (size_t i = location; i < view.size(); i++) {
10689
58.9k
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
10690
58.9k
          view[i] == '?' || view[i] == '[') {
10691
6.21k
        return i;
10692
6.21k
      }
10693
58.9k
    }
10694
25.0k
    return size_t(view.size());
10695
31.2k
  }
10696
  // fast path for long strings (expected to be common)
10697
7.60k
  size_t i = location;
10698
7.60k
  const __m128i mask1 = _mm_set1_epi8(':');
10699
7.60k
  const __m128i mask2 = _mm_set1_epi8('/');
10700
7.60k
  const __m128i mask3 = _mm_set1_epi8('\\');
10701
7.60k
  const __m128i mask4 = _mm_set1_epi8('?');
10702
7.60k
  const __m128i mask5 = _mm_set1_epi8('[');
10703
10704
22.8k
  for (; i + 15 < view.size(); i += 16) {
10705
19.6k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
10706
19.6k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
10707
19.6k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
10708
19.6k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
10709
19.6k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
10710
19.6k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
10711
19.6k
    __m128i m = _mm_or_si128(
10712
19.6k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
10713
19.6k
    int mask = _mm_movemask_epi8(m);
10714
19.6k
    if (mask != 0) {
10715
4.46k
      return i + trailing_zeroes(mask);
10716
4.46k
    }
10717
19.6k
  }
10718
3.13k
  if (i < view.size()) {
10719
2.77k
    __m128i word =
10720
2.77k
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
10721
2.77k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
10722
2.77k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
10723
2.77k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
10724
2.77k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
10725
2.77k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
10726
2.77k
    __m128i m = _mm_or_si128(
10727
2.77k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
10728
2.77k
    int mask = _mm_movemask_epi8(m);
10729
2.77k
    if (mask != 0) {
10730
451
      return view.length() - 16 + trailing_zeroes(mask);
10731
451
    }
10732
2.77k
  }
10733
2.68k
  return size_t(view.length());
10734
3.13k
}
10735
#else
10736
// : / [ \\ ?
10737
static constexpr std::array<uint8_t, 256> special_host_delimiters =
10738
    []() constexpr {
10739
      std::array<uint8_t, 256> result{};
10740
      for (int i : {':', '/', '[', '\\', '?'}) {
10741
        result[i] = 1;
10742
      }
10743
      return result;
10744
    }();
10745
// credit: @the-moisrex recommended a table-based approach
10746
ada_really_inline size_t find_next_host_delimiter_special(
10747
    std::string_view view, size_t location) noexcept {
10748
  auto const str = view.substr(location);
10749
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
10750
    if (special_host_delimiters[(uint8_t)*pos]) {
10751
      return pos - str.begin() + location;
10752
    }
10753
  }
10754
  return size_t(view.size());
10755
}
10756
#endif
10757
10758
// starting at index location, this finds the next location of a character
10759
// :, /, ? or [. If none is found, view.size() is returned.
10760
// For use within get_host_delimiter_location.
10761
#if ADA_NEON
10762
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
10763
                                                  size_t location) noexcept {
10764
  // first check for short strings in which case we do it naively.
10765
  if (view.size() - location < 16) {  // slow path
10766
    for (size_t i = location; i < view.size(); i++) {
10767
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
10768
          view[i] == '[') {
10769
        return i;
10770
      }
10771
    }
10772
    return size_t(view.size());
10773
  }
10774
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
10775
    uint8x16_t bit_mask =
10776
        ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
10777
                            0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
10778
    uint8x16_t minput = vandq_u8(input, bit_mask);
10779
    uint8x16_t tmp = vpaddq_u8(minput, minput);
10780
    tmp = vpaddq_u8(tmp, tmp);
10781
    tmp = vpaddq_u8(tmp, tmp);
10782
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
10783
  };
10784
10785
  // fast path for long strings (expected to be common)
10786
  size_t i = location;
10787
  uint8x16_t low_mask =
10788
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
10789
                          0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
10790
  uint8x16_t high_mask =
10791
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
10792
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
10793
  uint8x16_t fmask = vmovq_n_u8(0xf);
10794
  uint8x16_t zero{0};
10795
  for (; i + 15 < view.size(); i += 16) {
10796
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
10797
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
10798
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
10799
    uint8x16_t classify = vandq_u8(lowpart, highpart);
10800
    if (vmaxvq_u8(classify) != 0) {
10801
      uint8x16_t is_zero = vceqq_u8(classify, zero);
10802
      uint16_t is_non_zero = ~to_bitmask(is_zero);
10803
      return i + trailing_zeroes(is_non_zero);
10804
    }
10805
  }
10806
10807
  if (i < view.size()) {
10808
    uint8x16_t word =
10809
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
10810
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
10811
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
10812
    uint8x16_t classify = vandq_u8(lowpart, highpart);
10813
    if (vmaxvq_u8(classify) != 0) {
10814
      uint8x16_t is_zero = vceqq_u8(classify, zero);
10815
      uint16_t is_non_zero = ~to_bitmask(is_zero);
10816
      return view.length() - 16 + trailing_zeroes(is_non_zero);
10817
    }
10818
  }
10819
  return size_t(view.size());
10820
}
10821
#elif ADA_SSE2
10822
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
10823
12.1k
                                                  size_t location) noexcept {
10824
  // first check for short strings in which case we do it naively.
10825
12.1k
  if (view.size() - location < 16) {  // slow path
10826
13.9k
    for (size_t i = location; i < view.size(); i++) {
10827
7.80k
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
10828
7.80k
          view[i] == '[') {
10829
2.27k
        return i;
10830
2.27k
      }
10831
7.80k
    }
10832
6.18k
    return size_t(view.size());
10833
8.45k
  }
10834
  // fast path for long strings (expected to be common)
10835
3.67k
  size_t i = location;
10836
3.67k
  const __m128i mask1 = _mm_set1_epi8(':');
10837
3.67k
  const __m128i mask2 = _mm_set1_epi8('/');
10838
3.67k
  const __m128i mask4 = _mm_set1_epi8('?');
10839
3.67k
  const __m128i mask5 = _mm_set1_epi8('[');
10840
10841
6.65k
  for (; i + 15 < view.size(); i += 16) {
10842
6.15k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
10843
6.15k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
10844
6.15k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
10845
6.15k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
10846
6.15k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
10847
6.15k
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
10848
6.15k
    int mask = _mm_movemask_epi8(m);
10849
6.15k
    if (mask != 0) {
10850
3.17k
      return i + trailing_zeroes(mask);
10851
3.17k
    }
10852
6.15k
  }
10853
499
  if (i < view.size()) {
10854
378
    __m128i word =
10855
378
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
10856
378
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
10857
378
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
10858
378
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
10859
378
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
10860
378
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
10861
378
    int mask = _mm_movemask_epi8(m);
10862
378
    if (mask != 0) {
10863
153
      return view.length() - 16 + trailing_zeroes(mask);
10864
153
    }
10865
378
  }
10866
346
  return size_t(view.length());
10867
499
}
10868
#else
10869
// : / [ ?
10870
static constexpr std::array<uint8_t, 256> host_delimiters = []() constexpr {
10871
  std::array<uint8_t, 256> result{};
10872
  for (int i : {':', '/', '?', '['}) {
10873
    result[i] = 1;
10874
  }
10875
  return result;
10876
}();
10877
// credit: @the-moisrex recommended a table-based approach
10878
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
10879
                                                  size_t location) noexcept {
10880
  auto const str = view.substr(location);
10881
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
10882
    if (host_delimiters[(uint8_t)*pos]) {
10883
      return pos - str.begin() + location;
10884
    }
10885
  }
10886
  return size_t(view.size());
10887
}
10888
#endif
10889
10890
ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
10891
41.8k
    const bool is_special, std::string_view& view) noexcept {
10892
  /**
10893
   * The spec at https://url.spec.whatwg.org/#hostname-state expects us to
10894
   * compute a variable called insideBrackets but this variable is only used
10895
   * once, to check whether a ':' character was found outside brackets. Exact
10896
   * text: "Otherwise, if c is U+003A (:) and insideBrackets is false, then:".
10897
   * It is conceptually simpler and arguably more efficient to just return a
10898
   * Boolean indicating whether ':' was found outside brackets.
10899
   */
10900
41.8k
  const size_t view_size = view.size();
10901
41.8k
  size_t location = 0;
10902
41.8k
  bool found_colon = false;
10903
  /**
10904
   * Performance analysis:
10905
   *
10906
   * We are basically seeking the end of the hostname which can be indicated
10907
   * by the end of the view, or by one of the characters ':', '/', '?', '\\'
10908
   * (where '\\' is only applicable for special URLs). However, these must
10909
   * appear outside a bracket range. E.g., if you have [something?]fd: then the
10910
   * '?' does not count.
10911
   *
10912
   * So we can skip ahead to the next delimiter, as long as we include '[' in
10913
   * the set of delimiters, and that we handle it first.
10914
   *
10915
   * So the trick is to have a fast function that locates the next delimiter.
10916
   * Unless we find '[', then it only needs to be called once! Ideally, such a
10917
   * function would be provided by the C++ standard library, but it seems that
10918
   * find_first_of is not very fast, so we are forced to roll our own.
10919
   *
10920
   * We do not break into two loops for speed, but for clarity.
10921
   */
10922
41.8k
  if (is_special) {
10923
    // We move to the next delimiter.
10924
33.4k
    location = find_next_host_delimiter_special(view, location);
10925
    // Unless we find '[' then we are going only going to have to call
10926
    // find_next_host_delimiter_special once.
10927
38.8k
    for (; location < view_size;
10928
33.4k
         location = find_next_host_delimiter_special(view, location)) {
10929
11.1k
      if (view[location] == '[') {
10930
5.73k
        location = view.find(']', location);
10931
5.73k
        if (location == std::string_view::npos) {
10932
          // performance: view.find might get translated to a memchr, which
10933
          // has no notion of std::string_view::npos, so the code does not
10934
          // reflect the assembly.
10935
320
          location = view_size;
10936
320
          break;
10937
320
        }
10938
5.73k
      } else {
10939
5.40k
        found_colon = view[location] == ':';
10940
5.40k
        break;
10941
5.40k
      }
10942
11.1k
    }
10943
33.4k
  } else {
10944
    // We move to the next delimiter.
10945
8.38k
    location = find_next_host_delimiter(view, location);
10946
    // Unless we find '[' then we are going only going to have to call
10947
    // find_next_host_delimiter_special once.
10948
12.1k
    for (; location < view_size;
10949
8.38k
         location = find_next_host_delimiter(view, location)) {
10950
5.60k
      if (view[location] == '[') {
10951
3.99k
        location = view.find(']', location);
10952
3.99k
        if (location == std::string_view::npos) {
10953
          // performance: view.find might get translated to a memchr, which
10954
          // has no notion of std::string_view::npos, so the code does not
10955
          // reflect the assembly.
10956
244
          location = view_size;
10957
244
          break;
10958
244
        }
10959
3.99k
      } else {
10960
1.60k
        found_colon = view[location] == ':';
10961
1.60k
        break;
10962
1.60k
      }
10963
5.60k
    }
10964
8.38k
  }
10965
  // performance: remove_suffix may translate into a single instruction.
10966
41.8k
  view.remove_suffix(view_size - location);
10967
41.8k
  return {location, found_colon};
10968
41.8k
}
10969
10970
59.3k
ada_really_inline void trim_c0_whitespace(std::string_view& input) noexcept {
10971
63.9k
  while (!input.empty() &&
10972
63.9k
         ada::unicode::is_c0_control_or_space(input.front())) {
10973
4.55k
    input.remove_prefix(1);
10974
4.55k
  }
10975
61.7k
  while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
10976
2.41k
    input.remove_suffix(1);
10977
2.41k
  }
10978
59.3k
}
10979
10980
ada_really_inline void parse_prepared_path(std::string_view input,
10981
                                           ada::scheme::type type,
10982
18.5k
                                           std::string& path) {
10983
18.5k
  ada_log("parse_prepared_path ", input);
10984
18.5k
  uint8_t accumulator = checkers::path_signature(input);
10985
  // Let us first detect a trivial case.
10986
  // If it is special, we check that we have no dot, no %,  no \ and no
10987
  // character needing percent encoding. Otherwise, we check that we have no %,
10988
  // no dot, and no character needing percent encoding.
10989
18.5k
  constexpr uint8_t need_encoding = 1;
10990
18.5k
  constexpr uint8_t backslash_char = 2;
10991
18.5k
  constexpr uint8_t dot_char = 4;
10992
18.5k
  constexpr uint8_t percent_char = 8;
10993
18.5k
  bool special = type != ada::scheme::NOT_SPECIAL;
10994
18.5k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
10995
18.5k
                                      checkers::is_windows_drive_letter(input));
10996
18.5k
  bool trivial_path =
10997
18.5k
      (special ? (accumulator == 0)
10998
18.5k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
10999
2.31k
                  0)) &&
11000
18.5k
      (!may_need_slow_file_handling);
11001
18.5k
  if (accumulator == dot_char && !may_need_slow_file_handling) {
11002
    // '4' means that we have at least one dot, but nothing that requires
11003
    // percent encoding or decoding. The only part that is not trivial is
11004
    // that we may have single dots and double dots path segments.
11005
    // If we have such segments, then we either have a path that begins
11006
    // with '.' (easy to check), or we have the sequence './'.
11007
    // Note: input cannot be empty, it must at least contain one character ('.')
11008
    // Note: we know that '\' is not present.
11009
2.35k
    if (input[0] != '.') {
11010
1.80k
      size_t slashdot = input.find("/.");
11011
1.80k
      if (slashdot == std::string_view::npos) {  // common case
11012
1.06k
        trivial_path = true;
11013
1.06k
      } else {  // uncommon
11014
        // only three cases matter: /./, /.. or a final /
11015
735
        trivial_path =
11016
735
            !(slashdot + 2 == input.size() || input[slashdot + 2] == '.' ||
11017
735
              input[slashdot + 2] == '/');
11018
735
      }
11019
1.80k
    }
11020
2.35k
  }
11021
18.5k
  if (trivial_path) {
11022
7.98k
    ada_log("parse_path trivial");
11023
7.98k
    path += '/';
11024
7.98k
    path += input;
11025
7.98k
    return;
11026
7.98k
  }
11027
  // We are going to need to look a bit at the path, but let us see if we can
11028
  // ignore percent encoding *and* backslashes *and* percent characters.
11029
  // Except for the trivial case, this is likely to capture 99% of paths out
11030
  // there.
11031
10.5k
  bool fast_path =
11032
10.5k
      (special &&
11033
10.5k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
11034
10.5k
      (type != ada::scheme::type::FILE);
11035
10.5k
  if (fast_path) {
11036
479
    ada_log("parse_prepared_path fast");
11037
    // Here we don't need to worry about \ or percent encoding.
11038
    // We also do not have a file protocol. We might have dots, however,
11039
    // but dots must as appear as '.', and they cannot be encoded because
11040
    // the symbol '%' is not present.
11041
479
    size_t previous_location = 0;  // We start at 0.
11042
4.45k
    do {
11043
4.45k
      size_t new_location = input.find('/', previous_location);
11044
      // std::string_view path_view = input;
11045
      //  We process the last segment separately:
11046
4.45k
      if (new_location == std::string_view::npos) {
11047
479
        std::string_view path_view = input.substr(previous_location);
11048
479
        if (path_view == "..") {  // The path ends with ..
11049
          // e.g., if you receive ".." with an empty path, you go to "/".
11050
30
          if (path.empty()) {
11051
11
            path = '/';
11052
11
            return;
11053
11
          }
11054
          // Fast case where we have nothing to do:
11055
19
          if (path.back() == '/') {
11056
9
            return;
11057
9
          }
11058
          // If you have the path "/joe/myfriend",
11059
          // then you delete 'myfriend'.
11060
10
          path.resize(path.rfind('/') + 1);
11061
10
          return;
11062
19
        }
11063
449
        path += '/';
11064
449
        if (path_view != ".") {
11065
302
          path.append(path_view);
11066
302
        }
11067
449
        return;
11068
3.97k
      } else {
11069
        // This is a non-final segment.
11070
3.97k
        std::string_view path_view =
11071
3.97k
            input.substr(previous_location, new_location - previous_location);
11072
3.97k
        previous_location = new_location + 1;
11073
3.97k
        if (path_view == "..") {
11074
556
          size_t last_delimiter = path.rfind('/');
11075
556
          if (last_delimiter != std::string::npos) {
11076
296
            path.erase(last_delimiter);
11077
296
          }
11078
3.42k
        } else if (path_view != ".") {
11079
2.93k
          path += '/';
11080
2.93k
          path.append(path_view);
11081
2.93k
        }
11082
3.97k
      }
11083
4.45k
    } while (true);
11084
10.0k
  } else {
11085
10.0k
    ada_log("parse_path slow");
11086
    // we have reached the general case
11087
10.0k
    bool needs_percent_encoding = (accumulator & 1);
11088
10.0k
    std::string path_buffer_tmp;
11089
53.5k
    do {
11090
53.5k
      size_t location = (special && (accumulator & 2))
11091
53.5k
                            ? input.find_first_of("/\\")
11092
53.5k
                            : input.find('/');
11093
53.5k
      std::string_view path_view = input;
11094
53.5k
      if (location != std::string_view::npos) {
11095
43.4k
        path_view.remove_suffix(path_view.size() - location);
11096
43.4k
        input.remove_prefix(location + 1);
11097
43.4k
      }
11098
      // path_buffer is either path_view or it might point at a percent encoded
11099
      // temporary file.
11100
53.5k
      std::string_view path_buffer =
11101
53.5k
          (needs_percent_encoding &&
11102
53.5k
           ada::unicode::percent_encode<false>(
11103
27.0k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
11104
53.5k
              ? path_buffer_tmp
11105
53.5k
              : path_view;
11106
53.5k
      if (unicode::is_double_dot_path_segment(path_buffer)) {
11107
8.19k
        if ((helpers::shorten_path(path, type) || special) &&
11108
8.19k
            location == std::string_view::npos) {
11109
604
          path += '/';
11110
604
        }
11111
45.3k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
11112
45.3k
                 (location == std::string_view::npos)) {
11113
303
        path += '/';
11114
303
      }
11115
      // Otherwise, if path_buffer is not a single-dot path segment, then:
11116
45.0k
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
11117
        // If url's scheme is "file", url's path is empty, and path_buffer is a
11118
        // Windows drive letter, then replace the second code point in
11119
        // path_buffer with U+003A (:).
11120
40.8k
        if (type == ada::scheme::type::FILE && path.empty() &&
11121
40.8k
            checkers::is_windows_drive_letter(path_buffer)) {
11122
2.23k
          path += '/';
11123
2.23k
          path += path_buffer[0];
11124
2.23k
          path += ':';
11125
2.23k
          path_buffer.remove_prefix(2);
11126
2.23k
          path.append(path_buffer);
11127
38.6k
        } else {
11128
          // Append path_buffer to url's path.
11129
38.6k
          path += '/';
11130
38.6k
          path.append(path_buffer);
11131
38.6k
        }
11132
40.8k
      }
11133
53.5k
      if (location == std::string_view::npos) {
11134
10.0k
        return;
11135
10.0k
      }
11136
53.5k
    } while (true);
11137
10.0k
  }
11138
10.5k
}
11139
11140
0
bool overlaps(std::string_view input1, const std::string& input2) noexcept {
11141
0
  ada_log("helpers::overlaps check if string_view '", input1, "' [",
11142
0
          input1.size(), " bytes] is part of string '", input2, "' [",
11143
0
          input2.size(), " bytes]");
11144
0
  return !input1.empty() && !input2.empty() && input1.data() >= input2.data() &&
11145
0
         input1.data() < input2.data() + input2.size();
11146
0
}
11147
11148
template <class url_type>
11149
ada_really_inline void strip_trailing_spaces_from_opaque_path(
11150
23.0k
    url_type& url) noexcept {
11151
23.0k
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
11152
23.0k
  if (!url.has_opaque_path) return;
11153
3.46k
  if (url.has_hash()) return;
11154
3.31k
  if (url.has_search()) return;
11155
11156
3.31k
  auto path = std::string(url.get_pathname());
11157
5.07k
  while (!path.empty() && path.back() == ' ') {
11158
1.76k
    path.resize(path.size() - 1);
11159
1.76k
  }
11160
3.31k
  url.update_base_pathname(path);
11161
3.31k
}
void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url>(ada::url&)
Line
Count
Source
11150
10.2k
    url_type& url) noexcept {
11151
10.2k
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
11152
10.2k
  if (!url.has_opaque_path) return;
11153
1.74k
  if (url.has_hash()) return;
11154
1.66k
  if (url.has_search()) return;
11155
11156
1.66k
  auto path = std::string(url.get_pathname());
11157
2.55k
  while (!path.empty() && path.back() == ' ') {
11158
882
    path.resize(path.size() - 1);
11159
882
  }
11160
1.66k
  url.update_base_pathname(path);
11161
1.66k
}
void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url_aggregator>(ada::url_aggregator&)
Line
Count
Source
11150
12.8k
    url_type& url) noexcept {
11151
12.8k
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
11152
12.8k
  if (!url.has_opaque_path) return;
11153
1.71k
  if (url.has_hash()) return;
11154
1.64k
  if (url.has_search()) return;
11155
11156
1.64k
  auto path = std::string(url.get_pathname());
11157
2.52k
  while (!path.empty() && path.back() == ' ') {
11158
882
    path.resize(path.size() - 1);
11159
882
  }
11160
1.64k
  url.update_base_pathname(path);
11161
1.64k
}
11162
11163
// @ / \\ ?
11164
static constexpr std::array<uint8_t, 256> authority_delimiter_special =
11165
    []() constexpr {
11166
      std::array<uint8_t, 256> result{};
11167
      for (int i : {'@', '/', '\\', '?'}) {
11168
        result[i] = 1;
11169
      }
11170
      return result;
11171
    }();
11172
// credit: @the-moisrex recommended a table-based approach
11173
ada_really_inline size_t
11174
8.69k
find_authority_delimiter_special(std::string_view view) noexcept {
11175
  // performance note: we might be able to gain further performance
11176
  // with SIMD instrinsics.
11177
48.9k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
11178
48.0k
    if (authority_delimiter_special[(uint8_t)*pos]) {
11179
7.73k
      return pos - view.begin();
11180
7.73k
    }
11181
48.0k
  }
11182
958
  return size_t(view.size());
11183
8.69k
}
11184
11185
// @ / ?
11186
static constexpr std::array<uint8_t, 256> authority_delimiter = []() constexpr {
11187
  std::array<uint8_t, 256> result{};
11188
  for (int i : {'@', '/', '?'}) {
11189
    result[i] = 1;
11190
  }
11191
  return result;
11192
}();
11193
// credit: @the-moisrex recommended a table-based approach
11194
ada_really_inline size_t
11195
1.61k
find_authority_delimiter(std::string_view view) noexcept {
11196
  // performance note: we might be able to gain further performance
11197
  // with SIMD instrinsics.
11198
5.83k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
11199
5.66k
    if (authority_delimiter[(uint8_t)*pos]) {
11200
1.45k
      return pos - view.begin();
11201
1.45k
    }
11202
5.66k
  }
11203
165
  return size_t(view.size());
11204
1.61k
}
11205
11206
}  // namespace ada::helpers
11207
11208
namespace ada {
11209
0
ada_warn_unused std::string to_string(ada::state state) {
11210
0
  return ada::helpers::get_state(state);
11211
0
}
11212
#undef ada_make_uint8x16_t
11213
}  // namespace ada
11214
/* end file src/helpers.cpp */
11215
/* begin file src/url.cpp */
11216
11217
#include <numeric>
11218
#include <algorithm>
11219
#include <string>
11220
11221
namespace ada {
11222
11223
1.06k
bool url::parse_opaque_host(std::string_view input) {
11224
1.06k
  ada_log("parse_opaque_host ", input, "[", input.size(), " bytes]");
11225
1.06k
  if (std::any_of(input.begin(), input.end(),
11226
1.06k
                  ada::unicode::is_forbidden_host_code_point)) {
11227
166
    return is_valid = false;
11228
166
  }
11229
11230
  // Return the result of running UTF-8 percent-encode on input using the C0
11231
  // control percent-encode set.
11232
900
  host = ada::unicode::percent_encode(
11233
900
      input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
11234
900
  return true;
11235
1.06k
}
11236
11237
2.08k
bool url::parse_ipv4(std::string_view input) {
11238
2.08k
  ada_log("parse_ipv4 ", input, "[", input.size(), " bytes]");
11239
2.08k
  if (input.back() == '.') {
11240
20
    input.remove_suffix(1);
11241
20
  }
11242
2.08k
  size_t digit_count{0};
11243
2.08k
  int pure_decimal_count = 0;  // entries that are decimal
11244
2.08k
  std::string_view original_input =
11245
2.08k
      input;  // we might use this if pure_decimal_count == 4.
11246
2.08k
  uint64_t ipv4{0};
11247
  // we could unroll for better performance?
11248
2.62k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
11249
2.60k
    uint32_t
11250
2.60k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
11251
2.60k
    bool is_hex = checkers::has_hex_prefix(input);
11252
2.60k
    if (is_hex && ((input.length() == 2) ||
11253
776
                   ((input.length() > 2) && (input[2] == '.')))) {
11254
      // special case
11255
64
      segment_result = 0;
11256
64
      input.remove_prefix(2);
11257
2.53k
    } else {
11258
2.53k
      std::from_chars_result r;
11259
2.53k
      if (is_hex) {
11260
712
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
11261
712
                            segment_result, 16);
11262
1.82k
      } else if ((input.length() >= 2) && input[0] == '0' &&
11263
1.82k
                 checkers::is_digit(input[1])) {
11264
349
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
11265
349
                            segment_result, 8);
11266
1.47k
      } else {
11267
1.47k
        pure_decimal_count++;
11268
1.47k
        r = std::from_chars(input.data(), input.data() + input.size(),
11269
1.47k
                            segment_result, 10);
11270
1.47k
      }
11271
2.53k
      if (r.ec != std::errc()) {
11272
473
        return is_valid = false;
11273
473
      }
11274
2.06k
      input.remove_prefix(r.ptr - input.data());
11275
2.06k
    }
11276
2.13k
    if (input.empty()) {
11277
      // We have the last value.
11278
      // At this stage, ipv4 contains digit_count*8 bits.
11279
      // So we have 32-digit_count*8 bits left.
11280
1.45k
      if (segment_result > (uint64_t(1) << (32 - digit_count * 8))) {
11281
12
        return is_valid = false;
11282
12
      }
11283
1.44k
      ipv4 <<= (32 - digit_count * 8);
11284
1.44k
      ipv4 |= segment_result;
11285
1.44k
      goto final;
11286
1.45k
    } else {
11287
      // There is more, so that the value must no be larger than 255
11288
      // and we must have a '.'.
11289
673
      if ((segment_result > 255) || (input[0] != '.')) {
11290
125
        return is_valid = false;
11291
125
      }
11292
548
      ipv4 <<= 8;
11293
548
      ipv4 |= segment_result;
11294
548
      input.remove_prefix(1);  // remove '.'
11295
548
    }
11296
2.13k
  }
11297
26
  if ((digit_count != 4) || (!input.empty())) {
11298
26
    return is_valid = false;
11299
26
  }
11300
1.44k
final:
11301
  // We could also check r.ptr to see where the parsing ended.
11302
1.44k
  if (pure_decimal_count == 4) {
11303
53
    host = original_input;  // The original input was already all decimal and we
11304
                            // validated it.
11305
1.39k
  } else {
11306
1.39k
    host = ada::serializers::ipv4(ipv4);  // We have to reserialize the address.
11307
1.39k
  }
11308
1.44k
  host_type = IPV4;
11309
1.44k
  return true;
11310
26
}
11311
11312
548
bool url::parse_ipv6(std::string_view input) {
11313
548
  ada_log("parse_ipv6 ", input, "[", input.size(), " bytes]");
11314
11315
548
  if (input.empty()) {
11316
27
    return is_valid = false;
11317
27
  }
11318
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
11319
521
  std::array<uint16_t, 8> address{};
11320
11321
  // Let pieceIndex be 0.
11322
521
  int piece_index = 0;
11323
11324
  // Let compress be null.
11325
521
  std::optional<int> compress{};
11326
11327
  // Let pointer be a pointer for input.
11328
521
  std::string_view::iterator pointer = input.begin();
11329
11330
  // If c is U+003A (:), then:
11331
521
  if (input[0] == ':') {
11332
    // If remaining does not start with U+003A (:), validation error, return
11333
    // failure.
11334
122
    if (input.size() == 1 || input[1] != ':') {
11335
18
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
11336
18
      return is_valid = false;
11337
18
    }
11338
11339
    // Increase pointer by 2.
11340
104
    pointer += 2;
11341
11342
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
11343
104
    compress = ++piece_index;
11344
104
  }
11345
11346
  // While c is not the EOF code point:
11347
1.46k
  while (pointer != input.end()) {
11348
    // If pieceIndex is 8, validation error, return failure.
11349
1.21k
    if (piece_index == 8) {
11350
7
      ada_log("parse_ipv6 piece_index == 8");
11351
7
      return is_valid = false;
11352
7
    }
11353
11354
    // If c is U+003A (:), then:
11355
1.20k
    if (*pointer == ':') {
11356
      // If compress is non-null, validation error, return failure.
11357
96
      if (compress.has_value()) {
11358
6
        ada_log("parse_ipv6 compress is non-null");
11359
6
        return is_valid = false;
11360
6
      }
11361
11362
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
11363
      // then continue.
11364
90
      pointer++;
11365
90
      compress = ++piece_index;
11366
90
      continue;
11367
96
    }
11368
11369
    // Let value and length be 0.
11370
1.11k
    uint16_t value = 0, length = 0;
11371
11372
    // While length is less than 4 and c is an ASCII hex digit,
11373
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
11374
    // increase pointer and length by 1.
11375
2.85k
    while (length < 4 && pointer != input.end() &&
11376
2.85k
           unicode::is_ascii_hex_digit(*pointer)) {
11377
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
11378
1.74k
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
11379
1.74k
      pointer++;
11380
1.74k
      length++;
11381
1.74k
    }
11382
11383
    // If c is U+002E (.), then:
11384
1.11k
    if (pointer != input.end() && *pointer == '.') {
11385
      // If length is 0, validation error, return failure.
11386
112
      if (length == 0) {
11387
8
        ada_log("parse_ipv6 length is 0");
11388
8
        return is_valid = false;
11389
8
      }
11390
11391
      // Decrease pointer by length.
11392
104
      pointer -= length;
11393
11394
      // If pieceIndex is greater than 6, validation error, return failure.
11395
104
      if (piece_index > 6) {
11396
4
        ada_log("parse_ipv6 piece_index > 6");
11397
4
        return is_valid = false;
11398
4
      }
11399
11400
      // Let numbersSeen be 0.
11401
100
      int numbers_seen = 0;
11402
11403
      // While c is not the EOF code point:
11404
308
      while (pointer != input.end()) {
11405
        // Let ipv4Piece be null.
11406
268
        std::optional<uint16_t> ipv4_piece{};
11407
11408
        // If numbersSeen is greater than 0, then:
11409
268
        if (numbers_seen > 0) {
11410
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
11411
          // pointer by 1.
11412
168
          if (*pointer == '.' && numbers_seen < 4) {
11413
154
            pointer++;
11414
154
          }
11415
          // Otherwise, validation error, return failure.
11416
14
          else {
11417
14
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
11418
14
            return is_valid = false;
11419
14
          }
11420
168
        }
11421
11422
        // If c is not an ASCII digit, validation error, return failure.
11423
254
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
11424
25
          ada_log(
11425
25
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
11426
25
              "failure");
11427
25
          return is_valid = false;
11428
25
        }
11429
11430
        // While c is an ASCII digit:
11431
577
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
11432
          // Let number be c interpreted as decimal number.
11433
369
          int number = *pointer - '0';
11434
11435
          // If ipv4Piece is null, then set ipv4Piece to number.
11436
369
          if (!ipv4_piece.has_value()) {
11437
229
            ipv4_piece = number;
11438
229
          }
11439
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
11440
140
          else if (ipv4_piece == 0) {
11441
4
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
11442
4
            return is_valid = false;
11443
4
          }
11444
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
11445
136
          else {
11446
136
            ipv4_piece = *ipv4_piece * 10 + number;
11447
136
          }
11448
11449
          // If ipv4Piece is greater than 255, validation error, return failure.
11450
365
          if (ipv4_piece > 255) {
11451
17
            ada_log("parse_ipv6 ipv4_piece > 255");
11452
17
            return is_valid = false;
11453
17
          }
11454
11455
          // Increase pointer by 1.
11456
348
          pointer++;
11457
348
        }
11458
11459
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
11460
        // ipv4Piece.
11461
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
11462
208
        address[piece_index] =
11463
208
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
11464
11465
        // Increase numbersSeen by 1.
11466
208
        numbers_seen++;
11467
11468
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
11469
208
        if (numbers_seen == 2 || numbers_seen == 4) {
11470
87
          piece_index++;
11471
87
        }
11472
208
      }
11473
11474
      // If numbersSeen is not 4, validation error, return failure.
11475
40
      if (numbers_seen != 4) {
11476
16
        return is_valid = false;
11477
16
      }
11478
11479
      // Break.
11480
24
      break;
11481
40
    }
11482
    // Otherwise, if c is U+003A (:):
11483
1.00k
    else if ((pointer != input.end()) && (*pointer == ':')) {
11484
      // Increase pointer by 1.
11485
699
      pointer++;
11486
11487
      // If c is the EOF code point, validation error, return failure.
11488
699
      if (pointer == input.end()) {
11489
7
        ada_log(
11490
7
            "parse_ipv6 If c is the EOF code point, validation error, return "
11491
7
            "failure");
11492
7
        return is_valid = false;
11493
7
      }
11494
699
    }
11495
    // Otherwise, if c is not the EOF code point, validation error, return
11496
    // failure.
11497
301
    else if (pointer != input.end()) {
11498
117
      ada_log(
11499
117
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
11500
117
          "error, return failure");
11501
117
      return is_valid = false;
11502
117
    }
11503
11504
    // Set address[pieceIndex] to value.
11505
876
    address[piece_index] = value;
11506
11507
    // Increase pieceIndex by 1.
11508
876
    piece_index++;
11509
876
  }
11510
11511
  // If compress is non-null, then:
11512
278
  if (compress.has_value()) {
11513
    // Let swaps be pieceIndex - compress.
11514
178
    int swaps = piece_index - *compress;
11515
11516
    // Set pieceIndex to 7.
11517
178
    piece_index = 7;
11518
11519
    // While pieceIndex is not 0 and swaps is greater than 0,
11520
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
11521
    // decrease both pieceIndex and swaps by 1.
11522
479
    while (piece_index != 0 && swaps > 0) {
11523
301
      std::swap(address[piece_index], address[*compress + swaps - 1]);
11524
301
      piece_index--;
11525
301
      swaps--;
11526
301
    }
11527
178
  }
11528
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
11529
  // return failure.
11530
100
  else if (piece_index != 8) {
11531
77
    ada_log(
11532
77
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
11533
77
        "error, return failure");
11534
77
    return is_valid = false;
11535
77
  }
11536
201
  host = ada::serializers::ipv6(address);
11537
201
  ada_log("parse_ipv6 ", *host);
11538
201
  host_type = IPV6;
11539
201
  return true;
11540
278
}
11541
11542
template <bool has_state_override>
11543
10.2k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
11544
10.2k
  auto parsed_type = ada::scheme::get_scheme_type(input);
11545
10.2k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
11546
  /**
11547
   * In the common case, we will immediately recognize a special scheme (e.g.,
11548
   *http, https), in which case, we can go really fast.
11549
   **/
11550
10.2k
  if (is_input_special) {  // fast path!!!
11551
3.84k
    if (has_state_override) {
11552
      // If url's scheme is not a special scheme and buffer is a special scheme,
11553
      // then return.
11554
39
      if (is_special() != is_input_special) {
11555
2
        return true;
11556
2
      }
11557
11558
      // If url includes credentials or has a non-null port, and buffer is
11559
      // "file", then return.
11560
37
      if ((has_credentials() || port.has_value()) &&
11561
37
          parsed_type == ada::scheme::type::FILE) {
11562
1
        return true;
11563
1
      }
11564
11565
      // If url's scheme is "file" and its host is an empty host, then return.
11566
      // An empty host is the empty string.
11567
36
      if (type == ada::scheme::type::FILE && host.has_value() &&
11568
36
          host.value().empty()) {
11569
2
        return true;
11570
2
      }
11571
36
    }
11572
11573
3.84k
    type = parsed_type;
11574
11575
3.84k
    if (has_state_override) {
11576
      // This is uncommon.
11577
34
      uint16_t urls_scheme_port = get_special_port();
11578
11579
34
      if (urls_scheme_port) {
11580
        // If url's port is url's scheme's default port, then set url's port to
11581
        // null.
11582
25
        if (port.has_value() && *port == urls_scheme_port) {
11583
1
          port = std::nullopt;
11584
1
        }
11585
25
      }
11586
34
    }
11587
6.41k
  } else {  // slow path
11588
6.41k
    std::string _buffer = std::string(input);
11589
    // Next function is only valid if the input is ASCII and returns false
11590
    // otherwise, but it seems that we always have ascii content so we do not
11591
    // need to check the return value.
11592
    // bool is_ascii =
11593
6.41k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
11594
11595
6.41k
    if (has_state_override) {
11596
      // If url's scheme is a special scheme and buffer is not a special scheme,
11597
      // then return. If url's scheme is not a special scheme and buffer is a
11598
      // special scheme, then return.
11599
245
      if (is_special() != ada::scheme::is_special(_buffer)) {
11600
116
        return true;
11601
116
      }
11602
11603
      // If url includes credentials or has a non-null port, and buffer is
11604
      // "file", then return.
11605
129
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
11606
1
        return true;
11607
1
      }
11608
11609
      // If url's scheme is "file" and its host is an empty host, then return.
11610
      // An empty host is the empty string.
11611
128
      if (type == ada::scheme::type::FILE && host.has_value() &&
11612
128
          host.value().empty()) {
11613
1
        return true;
11614
1
      }
11615
128
    }
11616
11617
6.29k
    set_scheme(std::move(_buffer));
11618
11619
6.29k
    if (has_state_override) {
11620
      // This is uncommon.
11621
127
      uint16_t urls_scheme_port = get_special_port();
11622
11623
127
      if (urls_scheme_port) {
11624
        // If url's port is url's scheme's default port, then set url's port to
11625
        // null.
11626
10
        if (port.has_value() && *port == urls_scheme_port) {
11627
1
          port = std::nullopt;
11628
1
        }
11629
10
      }
11630
127
    }
11631
6.29k
  }
11632
11633
10.1k
  return true;
11634
10.2k
}
bool ada::url::parse_scheme<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
11543
284
ada_really_inline bool url::parse_scheme(const std::string_view input) {
11544
284
  auto parsed_type = ada::scheme::get_scheme_type(input);
11545
284
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
11546
  /**
11547
   * In the common case, we will immediately recognize a special scheme (e.g.,
11548
   *http, https), in which case, we can go really fast.
11549
   **/
11550
284
  if (is_input_special) {  // fast path!!!
11551
39
    if (has_state_override) {
11552
      // If url's scheme is not a special scheme and buffer is a special scheme,
11553
      // then return.
11554
39
      if (is_special() != is_input_special) {
11555
2
        return true;
11556
2
      }
11557
11558
      // If url includes credentials or has a non-null port, and buffer is
11559
      // "file", then return.
11560
37
      if ((has_credentials() || port.has_value()) &&
11561
37
          parsed_type == ada::scheme::type::FILE) {
11562
1
        return true;
11563
1
      }
11564
11565
      // If url's scheme is "file" and its host is an empty host, then return.
11566
      // An empty host is the empty string.
11567
36
      if (type == ada::scheme::type::FILE && host.has_value() &&
11568
36
          host.value().empty()) {
11569
2
        return true;
11570
2
      }
11571
36
    }
11572
11573
34
    type = parsed_type;
11574
11575
34
    if (has_state_override) {
11576
      // This is uncommon.
11577
34
      uint16_t urls_scheme_port = get_special_port();
11578
11579
34
      if (urls_scheme_port) {
11580
        // If url's port is url's scheme's default port, then set url's port to
11581
        // null.
11582
25
        if (port.has_value() && *port == urls_scheme_port) {
11583
1
          port = std::nullopt;
11584
1
        }
11585
25
      }
11586
34
    }
11587
245
  } else {  // slow path
11588
245
    std::string _buffer = std::string(input);
11589
    // Next function is only valid if the input is ASCII and returns false
11590
    // otherwise, but it seems that we always have ascii content so we do not
11591
    // need to check the return value.
11592
    // bool is_ascii =
11593
245
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
11594
11595
245
    if (has_state_override) {
11596
      // If url's scheme is a special scheme and buffer is not a special scheme,
11597
      // then return. If url's scheme is not a special scheme and buffer is a
11598
      // special scheme, then return.
11599
245
      if (is_special() != ada::scheme::is_special(_buffer)) {
11600
116
        return true;
11601
116
      }
11602
11603
      // If url includes credentials or has a non-null port, and buffer is
11604
      // "file", then return.
11605
129
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
11606
1
        return true;
11607
1
      }
11608
11609
      // If url's scheme is "file" and its host is an empty host, then return.
11610
      // An empty host is the empty string.
11611
128
      if (type == ada::scheme::type::FILE && host.has_value() &&
11612
128
          host.value().empty()) {
11613
1
        return true;
11614
1
      }
11615
128
    }
11616
11617
127
    set_scheme(std::move(_buffer));
11618
11619
127
    if (has_state_override) {
11620
      // This is uncommon.
11621
127
      uint16_t urls_scheme_port = get_special_port();
11622
11623
127
      if (urls_scheme_port) {
11624
        // If url's port is url's scheme's default port, then set url's port to
11625
        // null.
11626
10
        if (port.has_value() && *port == urls_scheme_port) {
11627
1
          port = std::nullopt;
11628
1
        }
11629
10
      }
11630
127
    }
11631
127
  }
11632
11633
161
  return true;
11634
284
}
bool ada::url::parse_scheme<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
11543
9.97k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
11544
9.97k
  auto parsed_type = ada::scheme::get_scheme_type(input);
11545
9.97k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
11546
  /**
11547
   * In the common case, we will immediately recognize a special scheme (e.g.,
11548
   *http, https), in which case, we can go really fast.
11549
   **/
11550
9.97k
  if (is_input_special) {  // fast path!!!
11551
3.80k
    if (has_state_override) {
11552
      // If url's scheme is not a special scheme and buffer is a special scheme,
11553
      // then return.
11554
0
      if (is_special() != is_input_special) {
11555
0
        return true;
11556
0
      }
11557
11558
      // If url includes credentials or has a non-null port, and buffer is
11559
      // "file", then return.
11560
0
      if ((has_credentials() || port.has_value()) &&
11561
0
          parsed_type == ada::scheme::type::FILE) {
11562
0
        return true;
11563
0
      }
11564
11565
      // If url's scheme is "file" and its host is an empty host, then return.
11566
      // An empty host is the empty string.
11567
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
11568
0
          host.value().empty()) {
11569
0
        return true;
11570
0
      }
11571
0
    }
11572
11573
3.80k
    type = parsed_type;
11574
11575
3.80k
    if (has_state_override) {
11576
      // This is uncommon.
11577
0
      uint16_t urls_scheme_port = get_special_port();
11578
11579
0
      if (urls_scheme_port) {
11580
        // If url's port is url's scheme's default port, then set url's port to
11581
        // null.
11582
0
        if (port.has_value() && *port == urls_scheme_port) {
11583
0
          port = std::nullopt;
11584
0
        }
11585
0
      }
11586
0
    }
11587
6.17k
  } else {  // slow path
11588
6.17k
    std::string _buffer = std::string(input);
11589
    // Next function is only valid if the input is ASCII and returns false
11590
    // otherwise, but it seems that we always have ascii content so we do not
11591
    // need to check the return value.
11592
    // bool is_ascii =
11593
6.17k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
11594
11595
6.17k
    if (has_state_override) {
11596
      // If url's scheme is a special scheme and buffer is not a special scheme,
11597
      // then return. If url's scheme is not a special scheme and buffer is a
11598
      // special scheme, then return.
11599
0
      if (is_special() != ada::scheme::is_special(_buffer)) {
11600
0
        return true;
11601
0
      }
11602
11603
      // If url includes credentials or has a non-null port, and buffer is
11604
      // "file", then return.
11605
0
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
11606
0
        return true;
11607
0
      }
11608
11609
      // If url's scheme is "file" and its host is an empty host, then return.
11610
      // An empty host is the empty string.
11611
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
11612
0
          host.value().empty()) {
11613
0
        return true;
11614
0
      }
11615
0
    }
11616
11617
6.17k
    set_scheme(std::move(_buffer));
11618
11619
6.17k
    if (has_state_override) {
11620
      // This is uncommon.
11621
0
      uint16_t urls_scheme_port = get_special_port();
11622
11623
0
      if (urls_scheme_port) {
11624
        // If url's port is url's scheme's default port, then set url's port to
11625
        // null.
11626
0
        if (port.has_value() && *port == urls_scheme_port) {
11627
0
          port = std::nullopt;
11628
0
        }
11629
0
      }
11630
0
    }
11631
6.17k
  }
11632
11633
9.97k
  return true;
11634
9.97k
}
11635
11636
9.92k
ada_really_inline bool url::parse_host(std::string_view input) {
11637
9.92k
  ada_log("parse_host ", input, "[", input.size(), " bytes]");
11638
9.92k
  if (input.empty()) {
11639
29
    return is_valid = false;
11640
29
  }  // technically unnecessary.
11641
  // If input starts with U+005B ([), then:
11642
9.89k
  if (input[0] == '[') {
11643
    // If input does not end with U+005D (]), validation error, return failure.
11644
976
    if (input.back() != ']') {
11645
428
      return is_valid = false;
11646
428
    }
11647
548
    ada_log("parse_host ipv6");
11648
11649
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
11650
    // trailing U+005D (]) removed.
11651
548
    input.remove_prefix(1);
11652
548
    input.remove_suffix(1);
11653
548
    return parse_ipv6(input);
11654
976
  }
11655
11656
  // If isNotSpecial is true, then return the result of opaque-host parsing
11657
  // input.
11658
8.92k
  if (!is_special()) {
11659
1.06k
    return parse_opaque_host(input);
11660
1.06k
  }
11661
  // Let domain be the result of running UTF-8 decode without BOM on the
11662
  // percent-decoding of input. Let asciiDomain be the result of running domain
11663
  // to ASCII with domain and false. The most common case is an ASCII input, in
11664
  // which case we do not need to call the expensive 'to_ascii' if a few
11665
  // conditions are met: no '%' and no 'xn-' subsequence.
11666
7.85k
  std::string buffer = std::string(input);
11667
  // This next function checks that the result is ascii, but we are going to
11668
  // to check anyhow with is_forbidden.
11669
  // bool is_ascii =
11670
7.85k
  unicode::to_lower_ascii(buffer.data(), buffer.size());
11671
7.85k
  bool is_forbidden = unicode::contains_forbidden_domain_code_point(
11672
7.85k
      buffer.data(), buffer.size());
11673
7.85k
  if (is_forbidden == 0 && buffer.find("xn-") == std::string_view::npos) {
11674
    // fast path
11675
4.93k
    host = std::move(buffer);
11676
4.93k
    if (checkers::is_ipv4(host.value())) {
11677
1.76k
      ada_log("parse_host fast path ipv4");
11678
1.76k
      return parse_ipv4(host.value());
11679
1.76k
    }
11680
3.17k
    ada_log("parse_host fast path ", *host);
11681
3.17k
    return true;
11682
4.93k
  }
11683
2.91k
  ada_log("parse_host calling to_ascii");
11684
2.91k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
11685
2.91k
  if (!is_valid) {
11686
1.37k
    ada_log("parse_host to_ascii returns false");
11687
1.37k
    return is_valid = false;
11688
1.37k
  }
11689
11690
1.54k
  if (std::any_of(host.value().begin(), host.value().end(),
11691
1.54k
                  ada::unicode::is_forbidden_domain_code_point)) {
11692
0
    host = std::nullopt;
11693
0
    return is_valid = false;
11694
0
  }
11695
11696
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
11697
  // asciiDomain.
11698
1.54k
  if (checkers::is_ipv4(host.value())) {
11699
316
    ada_log("parse_host got ipv4", *host);
11700
316
    return parse_ipv4(host.value());
11701
316
  }
11702
11703
1.22k
  return true;
11704
1.54k
}
11705
11706
6.99k
ada_really_inline void url::parse_path(std::string_view input) {
11707
6.99k
  ada_log("parse_path ", input);
11708
6.99k
  std::string tmp_buffer;
11709
6.99k
  std::string_view internal_input;
11710
6.99k
  if (unicode::has_tabs_or_newline(input)) {
11711
83
    tmp_buffer = input;
11712
    // Optimization opportunity: Instead of copying and then pruning, we could
11713
    // just directly build the string from user_input.
11714
83
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
11715
83
    internal_input = tmp_buffer;
11716
6.91k
  } else {
11717
6.91k
    internal_input = input;
11718
6.91k
  }
11719
11720
  // If url is special, then:
11721
6.99k
  if (is_special()) {
11722
5.27k
    if (internal_input.empty()) {
11723
3.32k
      path = "/";
11724
3.32k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
11725
518
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
11726
518
      return;
11727
1.42k
    } else {
11728
1.42k
      helpers::parse_prepared_path(internal_input, type, path);
11729
1.42k
      return;
11730
1.42k
    }
11731
5.27k
  } else if (!internal_input.empty()) {
11732
792
    if (internal_input[0] == '/') {
11733
266
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
11734
266
      return;
11735
526
    } else {
11736
526
      helpers::parse_prepared_path(internal_input, type, path);
11737
526
      return;
11738
526
    }
11739
937
  } else {
11740
937
    if (!host.has_value()) {
11741
0
      path = "/";
11742
0
    }
11743
937
  }
11744
6.99k
}
11745
11746
0
[[nodiscard]] std::string url::to_string() const {
11747
0
  if (!is_valid) {
11748
0
    return "null";
11749
0
  }
11750
0
  std::string answer;
11751
0
  auto back = std::back_insert_iterator(answer);
11752
0
  answer.append("{\n");
11753
0
  answer.append("\t\"protocol\":\"");
11754
0
  helpers::encode_json(get_protocol(), back);
11755
0
  answer.append("\",\n");
11756
0
  if (has_credentials()) {
11757
0
    answer.append("\t\"username\":\"");
11758
0
    helpers::encode_json(username, back);
11759
0
    answer.append("\",\n");
11760
0
    answer.append("\t\"password\":\"");
11761
0
    helpers::encode_json(password, back);
11762
0
    answer.append("\",\n");
11763
0
  }
11764
0
  if (host.has_value()) {
11765
0
    answer.append("\t\"host\":\"");
11766
0
    helpers::encode_json(host.value(), back);
11767
0
    answer.append("\",\n");
11768
0
  }
11769
0
  if (port.has_value()) {
11770
0
    answer.append("\t\"port\":\"");
11771
0
    answer.append(std::to_string(port.value()));
11772
0
    answer.append("\",\n");
11773
0
  }
11774
0
  answer.append("\t\"path\":\"");
11775
0
  helpers::encode_json(path, back);
11776
0
  answer.append("\",\n");
11777
0
  answer.append("\t\"opaque path\":");
11778
0
  answer.append((has_opaque_path ? "true" : "false"));
11779
0
  if (has_search()) {
11780
0
    answer.append(",\n");
11781
0
    answer.append("\t\"query\":\"");
11782
0
    helpers::encode_json(query.value(), back);
11783
0
    answer.append("\"");
11784
0
  }
11785
0
  if (hash.has_value()) {
11786
0
    answer.append(",\n");
11787
0
    answer.append("\t\"hash\":\"");
11788
0
    helpers::encode_json(hash.value(), back);
11789
0
    answer.append("\"");
11790
0
  }
11791
0
  answer.append("\n}");
11792
0
  return answer;
11793
0
}
11794
11795
0
[[nodiscard]] bool url::has_valid_domain() const noexcept {
11796
0
  if (!host.has_value()) {
11797
0
    return false;
11798
0
  }
11799
0
  return checkers::verify_dns_length(host.value());
11800
0
}
11801
11802
}  // namespace ada
11803
/* end file src/url.cpp */
11804
/* begin file src/url-getters.cpp */
11805
/**
11806
 * @file url-getters.cpp
11807
 * Includes all the getters of `ada::url`
11808
 */
11809
11810
#include <algorithm>
11811
#include <string>
11812
11813
namespace ada {
11814
8.01k
[[nodiscard]] std::string url::get_origin() const noexcept {
11815
8.01k
  if (is_special()) {
11816
    // Return a new opaque origin.
11817
5.27k
    if (type == scheme::FILE) {
11818
1.39k
      return "null";
11819
1.39k
    }
11820
3.87k
    return ada::helpers::concat(get_protocol(), "//", get_host());
11821
5.27k
  }
11822
11823
2.74k
  if (non_special_scheme == "blob") {
11824
413
    if (!path.empty()) {
11825
404
      auto result = ada::parse<ada::url>(path);
11826
404
      if (result &&
11827
404
          (result->type == scheme::HTTP || result->type == scheme::HTTPS)) {
11828
        // If pathURL's scheme is not "http" and not "https", then return a
11829
        // new opaque origin.
11830
13
        return ada::helpers::concat(result->get_protocol(), "//",
11831
13
                                    result->get_host());
11832
13
      }
11833
404
    }
11834
413
  }
11835
11836
  // Return a new opaque origin.
11837
2.73k
  return "null";
11838
2.74k
}
11839
11840
11.9k
[[nodiscard]] std::string url::get_protocol() const noexcept {
11841
11.9k
  if (is_special()) {
11842
9.15k
    return helpers::concat(ada::scheme::details::is_special_list[type], ":");
11843
9.15k
  }
11844
  // We only move the 'scheme' if it is non-special.
11845
2.74k
  return helpers::concat(non_special_scheme, ":");
11846
11.9k
}
11847
11848
11.9k
[[nodiscard]] std::string url::get_host() const noexcept {
11849
  // If url's host is null, then return the empty string.
11850
  // If url's port is null, return url's host, serialized.
11851
  // Return url's host, serialized, followed by U+003A (:) and url's port,
11852
  // serialized.
11853
11.9k
  if (!host.has_value()) {
11854
1.18k
    return "";
11855
1.18k
  }
11856
10.7k
  if (port.has_value()) {
11857
392
    return host.value() + ":" + get_port();
11858
392
  }
11859
10.3k
  return host.value();
11860
10.7k
}
11861
11862
8.01k
[[nodiscard]] std::string url::get_hostname() const noexcept {
11863
8.01k
  return host.value_or("");
11864
8.01k
}
11865
11866
9.68k
[[nodiscard]] std::string_view url::get_pathname() const noexcept {
11867
9.68k
  return path;
11868
9.68k
}
11869
11870
8.01k
[[nodiscard]] std::string url::get_search() const noexcept {
11871
  // If this's URL's query is either null or the empty string, then return the
11872
  // empty string. Return U+003F (?), followed by this's URL's query.
11873
8.01k
  return (!query.has_value() || (query.value().empty())) ? ""
11874
8.01k
                                                         : "?" + query.value();
11875
8.01k
}
11876
11877
8.01k
[[nodiscard]] const std::string& url::get_username() const noexcept {
11878
8.01k
  return username;
11879
8.01k
}
11880
11881
8.01k
[[nodiscard]] const std::string& url::get_password() const noexcept {
11882
8.01k
  return password;
11883
8.01k
}
11884
11885
8.40k
[[nodiscard]] std::string url::get_port() const noexcept {
11886
8.40k
  return port.has_value() ? std::to_string(port.value()) : "";
11887
8.40k
}
11888
11889
8.01k
[[nodiscard]] std::string url::get_hash() const noexcept {
11890
  // If this's URL's fragment is either null or the empty string, then return
11891
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
11892
8.01k
  return (!hash.has_value() || (hash.value().empty())) ? ""
11893
8.01k
                                                       : "#" + hash.value();
11894
8.01k
}
11895
11896
}  // namespace ada
11897
/* end file src/url-getters.cpp */
11898
/* begin file src/url-setters.cpp */
11899
/**
11900
 * @file url-setters.cpp
11901
 * Includes all the setters of `ada::url`
11902
 */
11903
11904
#include <optional>
11905
#include <string>
11906
11907
namespace ada {
11908
11909
template <bool override_hostname>
11910
16.0k
bool url::set_host_or_hostname(const std::string_view input) {
11911
16.0k
  if (has_opaque_path) {
11912
2.03k
    return false;
11913
2.03k
  }
11914
11915
13.9k
  std::optional<std::string> previous_host = host;
11916
13.9k
  std::optional<uint16_t> previous_port = port;
11917
11918
13.9k
  size_t host_end_pos = input.find('#');
11919
13.9k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
11920
13.9k
                                      ? host_end_pos
11921
13.9k
                                      : input.size());
11922
13.9k
  helpers::remove_ascii_tab_or_newline(_host);
11923
13.9k
  std::string_view new_host(_host);
11924
11925
  // If url's scheme is "file", then set state to file host state, instead of
11926
  // host state.
11927
13.9k
  if (type != ada::scheme::type::FILE) {
11928
11.2k
    std::string_view host_view(_host.data(), _host.length());
11929
11.2k
    auto [location, found_colon] =
11930
11.2k
        helpers::get_host_delimiter_location(is_special(), host_view);
11931
11932
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
11933
    // Note: the 'found_colon' value is true if and only if a colon was
11934
    // encountered while not inside brackets.
11935
11.2k
    if (found_colon) {
11936
184
      if (override_hostname) {
11937
92
        return false;
11938
92
      }
11939
92
      std::string_view buffer = new_host.substr(location + 1);
11940
92
      if (!buffer.empty()) {
11941
82
        set_port(buffer);
11942
82
      }
11943
92
    }
11944
    // If url is special and host_view is the empty string, validation error,
11945
    // return failure. Otherwise, if state override is given, host_view is the
11946
    // empty string, and either url includes credentials or url's port is
11947
    // non-null, return.
11948
11.0k
    else if (host_view.empty() &&
11949
11.0k
             (is_special() || has_credentials() || port.has_value())) {
11950
5.78k
      return false;
11951
5.78k
    }
11952
11953
    // Let host be the result of host parsing host_view with url is not special.
11954
5.33k
    if (host_view.empty() && !is_special()) {
11955
2.32k
      host = "";
11956
2.32k
      return true;
11957
2.32k
    }
11958
11959
3.00k
    bool succeeded = parse_host(host_view);
11960
3.00k
    if (!succeeded) {
11961
1.14k
      host = previous_host;
11962
1.14k
      update_base_port(previous_port);
11963
1.14k
    }
11964
3.00k
    return succeeded;
11965
5.33k
  }
11966
11967
2.79k
  size_t location = new_host.find_first_of("/\\?");
11968
2.79k
  if (location != std::string_view::npos) {
11969
576
    new_host.remove_suffix(new_host.length() - location);
11970
576
  }
11971
11972
2.79k
  if (new_host.empty()) {
11973
    // Set url's host to the empty string.
11974
2.02k
    host = "";
11975
2.02k
  } else {
11976
    // Let host be the result of host parsing buffer with url is not special.
11977
768
    if (!parse_host(new_host)) {
11978
316
      host = previous_host;
11979
316
      update_base_port(previous_port);
11980
316
      return false;
11981
316
    }
11982
11983
    // If host is "localhost", then set host to the empty string.
11984
452
    if (host.has_value() && host.value() == "localhost") {
11985
2
      host = "";
11986
2
    }
11987
452
  }
11988
2.47k
  return true;
11989
2.79k
}
bool ada::url::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
11910
8.01k
bool url::set_host_or_hostname(const std::string_view input) {
11911
8.01k
  if (has_opaque_path) {
11912
1.01k
    return false;
11913
1.01k
  }
11914
11915
6.99k
  std::optional<std::string> previous_host = host;
11916
6.99k
  std::optional<uint16_t> previous_port = port;
11917
11918
6.99k
  size_t host_end_pos = input.find('#');
11919
6.99k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
11920
6.99k
                                      ? host_end_pos
11921
6.99k
                                      : input.size());
11922
6.99k
  helpers::remove_ascii_tab_or_newline(_host);
11923
6.99k
  std::string_view new_host(_host);
11924
11925
  // If url's scheme is "file", then set state to file host state, instead of
11926
  // host state.
11927
6.99k
  if (type != ada::scheme::type::FILE) {
11928
5.60k
    std::string_view host_view(_host.data(), _host.length());
11929
5.60k
    auto [location, found_colon] =
11930
5.60k
        helpers::get_host_delimiter_location(is_special(), host_view);
11931
11932
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
11933
    // Note: the 'found_colon' value is true if and only if a colon was
11934
    // encountered while not inside brackets.
11935
5.60k
    if (found_colon) {
11936
92
      if (override_hostname) {
11937
0
        return false;
11938
0
      }
11939
92
      std::string_view buffer = new_host.substr(location + 1);
11940
92
      if (!buffer.empty()) {
11941
82
        set_port(buffer);
11942
82
      }
11943
92
    }
11944
    // If url is special and host_view is the empty string, validation error,
11945
    // return failure. Otherwise, if state override is given, host_view is the
11946
    // empty string, and either url includes credentials or url's port is
11947
    // non-null, return.
11948
5.51k
    else if (host_view.empty() &&
11949
5.51k
             (is_special() || has_credentials() || port.has_value())) {
11950
2.89k
      return false;
11951
2.89k
    }
11952
11953
    // Let host be the result of host parsing host_view with url is not special.
11954
2.71k
    if (host_view.empty() && !is_special()) {
11955
1.16k
      host = "";
11956
1.16k
      return true;
11957
1.16k
    }
11958
11959
1.54k
    bool succeeded = parse_host(host_view);
11960
1.54k
    if (!succeeded) {
11961
595
      host = previous_host;
11962
595
      update_base_port(previous_port);
11963
595
    }
11964
1.54k
    return succeeded;
11965
2.71k
  }
11966
11967
1.39k
  size_t location = new_host.find_first_of("/\\?");
11968
1.39k
  if (location != std::string_view::npos) {
11969
288
    new_host.remove_suffix(new_host.length() - location);
11970
288
  }
11971
11972
1.39k
  if (new_host.empty()) {
11973
    // Set url's host to the empty string.
11974
1.01k
    host = "";
11975
1.01k
  } else {
11976
    // Let host be the result of host parsing buffer with url is not special.
11977
384
    if (!parse_host(new_host)) {
11978
158
      host = previous_host;
11979
158
      update_base_port(previous_port);
11980
158
      return false;
11981
158
    }
11982
11983
    // If host is "localhost", then set host to the empty string.
11984
226
    if (host.has_value() && host.value() == "localhost") {
11985
1
      host = "";
11986
1
    }
11987
226
  }
11988
1.23k
  return true;
11989
1.39k
}
bool ada::url::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
11910
8.01k
bool url::set_host_or_hostname(const std::string_view input) {
11911
8.01k
  if (has_opaque_path) {
11912
1.01k
    return false;
11913
1.01k
  }
11914
11915
6.99k
  std::optional<std::string> previous_host = host;
11916
6.99k
  std::optional<uint16_t> previous_port = port;
11917
11918
6.99k
  size_t host_end_pos = input.find('#');
11919
6.99k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
11920
6.99k
                                      ? host_end_pos
11921
6.99k
                                      : input.size());
11922
6.99k
  helpers::remove_ascii_tab_or_newline(_host);
11923
6.99k
  std::string_view new_host(_host);
11924
11925
  // If url's scheme is "file", then set state to file host state, instead of
11926
  // host state.
11927
6.99k
  if (type != ada::scheme::type::FILE) {
11928
5.60k
    std::string_view host_view(_host.data(), _host.length());
11929
5.60k
    auto [location, found_colon] =
11930
5.60k
        helpers::get_host_delimiter_location(is_special(), host_view);
11931
11932
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
11933
    // Note: the 'found_colon' value is true if and only if a colon was
11934
    // encountered while not inside brackets.
11935
5.60k
    if (found_colon) {
11936
92
      if (override_hostname) {
11937
92
        return false;
11938
92
      }
11939
0
      std::string_view buffer = new_host.substr(location + 1);
11940
0
      if (!buffer.empty()) {
11941
0
        set_port(buffer);
11942
0
      }
11943
0
    }
11944
    // If url is special and host_view is the empty string, validation error,
11945
    // return failure. Otherwise, if state override is given, host_view is the
11946
    // empty string, and either url includes credentials or url's port is
11947
    // non-null, return.
11948
5.51k
    else if (host_view.empty() &&
11949
5.51k
             (is_special() || has_credentials() || port.has_value())) {
11950
2.89k
      return false;
11951
2.89k
    }
11952
11953
    // Let host be the result of host parsing host_view with url is not special.
11954
2.61k
    if (host_view.empty() && !is_special()) {
11955
1.15k
      host = "";
11956
1.15k
      return true;
11957
1.15k
    }
11958
11959
1.46k
    bool succeeded = parse_host(host_view);
11960
1.46k
    if (!succeeded) {
11961
550
      host = previous_host;
11962
550
      update_base_port(previous_port);
11963
550
    }
11964
1.46k
    return succeeded;
11965
2.61k
  }
11966
11967
1.39k
  size_t location = new_host.find_first_of("/\\?");
11968
1.39k
  if (location != std::string_view::npos) {
11969
288
    new_host.remove_suffix(new_host.length() - location);
11970
288
  }
11971
11972
1.39k
  if (new_host.empty()) {
11973
    // Set url's host to the empty string.
11974
1.01k
    host = "";
11975
1.01k
  } else {
11976
    // Let host be the result of host parsing buffer with url is not special.
11977
384
    if (!parse_host(new_host)) {
11978
158
      host = previous_host;
11979
158
      update_base_port(previous_port);
11980
158
      return false;
11981
158
    }
11982
11983
    // If host is "localhost", then set host to the empty string.
11984
226
    if (host.has_value() && host.value() == "localhost") {
11985
1
      host = "";
11986
1
    }
11987
226
  }
11988
1.23k
  return true;
11989
1.39k
}
11990
11991
8.01k
bool url::set_host(const std::string_view input) {
11992
8.01k
  return set_host_or_hostname<false>(input);
11993
8.01k
}
11994
11995
8.01k
bool url::set_hostname(const std::string_view input) {
11996
8.01k
  return set_host_or_hostname<true>(input);
11997
8.01k
}
11998
11999
8.01k
bool url::set_username(const std::string_view input) {
12000
8.01k
  if (cannot_have_credentials_or_port()) {
12001
3.90k
    return false;
12002
3.90k
  }
12003
4.10k
  username = ada::unicode::percent_encode(
12004
4.10k
      input, character_sets::USERINFO_PERCENT_ENCODE);
12005
4.10k
  return true;
12006
8.01k
}
12007
12008
8.01k
bool url::set_password(const std::string_view input) {
12009
8.01k
  if (cannot_have_credentials_or_port()) {
12010
3.90k
    return false;
12011
3.90k
  }
12012
4.10k
  password = ada::unicode::percent_encode(
12013
4.10k
      input, character_sets::USERINFO_PERCENT_ENCODE);
12014
4.10k
  return true;
12015
8.01k
}
12016
12017
8.09k
bool url::set_port(const std::string_view input) {
12018
8.09k
  if (cannot_have_credentials_or_port()) {
12019
3.77k
    return false;
12020
3.77k
  }
12021
4.32k
  std::string trimmed(input);
12022
4.32k
  helpers::remove_ascii_tab_or_newline(trimmed);
12023
4.32k
  if (trimmed.empty()) {
12024
2.51k
    port = std::nullopt;
12025
2.51k
    return true;
12026
2.51k
  }
12027
  // Input should not start with control characters.
12028
1.80k
  if (ada::unicode::is_c0_control_or_space(trimmed.front())) {
12029
53
    return false;
12030
53
  }
12031
  // Input should contain at least one ascii digit.
12032
1.75k
  if (input.find_first_of("0123456789") == std::string_view::npos) {
12033
1.04k
    return false;
12034
1.04k
  }
12035
12036
  // Revert changes if parse_port fails.
12037
708
  std::optional<uint16_t> previous_port = port;
12038
708
  parse_port(trimmed);
12039
708
  if (is_valid) {
12040
510
    return true;
12041
510
  }
12042
198
  port = previous_port;
12043
198
  is_valid = true;
12044
198
  return false;
12045
708
}
12046
12047
8.01k
void url::set_hash(const std::string_view input) {
12048
8.01k
  if (input.empty()) {
12049
5.11k
    hash = std::nullopt;
12050
5.11k
    helpers::strip_trailing_spaces_from_opaque_path(*this);
12051
5.11k
    return;
12052
5.11k
  }
12053
12054
2.90k
  std::string new_value;
12055
2.90k
  new_value = input[0] == '#' ? input.substr(1) : input;
12056
2.90k
  helpers::remove_ascii_tab_or_newline(new_value);
12057
2.90k
  hash = unicode::percent_encode(new_value,
12058
2.90k
                                 ada::character_sets::FRAGMENT_PERCENT_ENCODE);
12059
2.90k
  return;
12060
8.01k
}
12061
12062
8.01k
void url::set_search(const std::string_view input) {
12063
8.01k
  if (input.empty()) {
12064
5.11k
    query = std::nullopt;
12065
5.11k
    helpers::strip_trailing_spaces_from_opaque_path(*this);
12066
5.11k
    return;
12067
5.11k
  }
12068
12069
2.90k
  std::string new_value;
12070
2.90k
  new_value = input[0] == '?' ? input.substr(1) : input;
12071
2.90k
  helpers::remove_ascii_tab_or_newline(new_value);
12072
12073
2.90k
  auto query_percent_encode_set =
12074
2.90k
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12075
2.90k
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
12076
12077
2.90k
  query = ada::unicode::percent_encode(std::string_view(new_value),
12078
2.90k
                                       query_percent_encode_set);
12079
2.90k
}
12080
12081
8.01k
bool url::set_pathname(const std::string_view input) {
12082
8.01k
  if (has_opaque_path) {
12083
1.01k
    return false;
12084
1.01k
  }
12085
6.99k
  path = "";
12086
6.99k
  parse_path(input);
12087
6.99k
  return true;
12088
8.01k
}
12089
12090
8.01k
bool url::set_protocol(const std::string_view input) {
12091
8.01k
  std::string view(input);
12092
8.01k
  helpers::remove_ascii_tab_or_newline(view);
12093
8.01k
  if (view.empty()) {
12094
5.15k
    return true;
12095
5.15k
  }
12096
12097
  // Schemes should start with alpha values.
12098
2.86k
  if (!checkers::is_alpha(view[0])) {
12099
2.40k
    return false;
12100
2.40k
  }
12101
12102
457
  view.append(":");
12103
12104
457
  std::string::iterator pointer =
12105
457
      std::find_if_not(view.begin(), view.end(), unicode::is_alnum_plus);
12106
12107
457
  if (pointer != view.end() && *pointer == ':') {
12108
284
    return parse_scheme<true>(
12109
284
        std::string_view(view.data(), pointer - view.begin()));
12110
284
  }
12111
173
  return false;
12112
457
}
12113
12114
0
bool url::set_href(const std::string_view input) {
12115
0
  ada::result<ada::url> out = ada::parse<ada::url>(input);
12116
12117
0
  if (out) {
12118
0
    username = out->username;
12119
0
    password = out->password;
12120
0
    host = out->host;
12121
0
    port = out->port;
12122
0
    path = out->path;
12123
0
    query = out->query;
12124
0
    hash = out->hash;
12125
0
    type = out->type;
12126
0
    non_special_scheme = out->non_special_scheme;
12127
0
    has_opaque_path = out->has_opaque_path;
12128
0
  }
12129
12130
0
  return out.has_value();
12131
0
}
12132
12133
}  // namespace ada
12134
/* end file src/url-setters.cpp */
12135
/* begin file src/parser.cpp */
12136
12137
#include <numeric>
12138
#include <limits>
12139
12140
namespace ada::parser {
12141
12142
template <class result_type>
12143
result_type parse_url(std::string_view user_input,
12144
59.3k
                      const result_type* base_url) {
12145
  // We can specialize the implementation per type.
12146
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
12147
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
12148
  // something else } is free (at runtime). This means that ada::url_aggregator
12149
  // and ada::url **do not have to support the exact same API**.
12150
59.3k
  constexpr bool result_type_is_ada_url =
12151
59.3k
      std::is_same<ada::url, result_type>::value;
12152
59.3k
  constexpr bool result_type_is_ada_url_aggregator =
12153
59.3k
      std::is_same<ada::url_aggregator, result_type>::value;
12154
59.3k
  static_assert(result_type_is_ada_url ||
12155
59.3k
                result_type_is_ada_url_aggregator);  // We don't support
12156
                                                     // anything else for now.
12157
12158
59.3k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
12159
59.3k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
12160
59.3k
          ")");
12161
12162
59.3k
  ada::state state = ada::state::SCHEME_START;
12163
59.3k
  result_type url{};
12164
12165
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
12166
  // surely the result of a bug or are otherwise a security concern.
12167
59.3k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) {
12168
2
    url.is_valid = false;
12169
2
  }
12170
  // Going forward, user_input.size() is in [0,
12171
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
12172
  // base, or the optional_url was invalid, we must return.
12173
59.3k
  if (base_url != nullptr) {
12174
2.64k
    url.is_valid &= base_url->is_valid;
12175
2.64k
  }
12176
59.3k
  if (!url.is_valid) {
12177
2
    return url;
12178
2
  }
12179
59.3k
  if constexpr (result_type_is_ada_url_aggregator) {
12180
    // Most of the time, we just need user_input.size().
12181
    // In some instances, we may need a bit more.
12182
    ///////////////////////////
12183
    // This is *very* important. This line should *not* be removed
12184
    // hastily. There are principled reasons why reserve is important
12185
    // for performance. If you have a benchmark with small inputs,
12186
    // it may not matter, but in other instances, it could.
12187
    ////
12188
    // This rounds up to the next power of two.
12189
    // We know that user_input.size() is in [0,
12190
    // std::numeric_limits<uint32_t>::max).
12191
44.9k
    uint32_t reserve_capacity =
12192
44.9k
        (0xFFFFFFFF >>
12193
44.9k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
12194
44.9k
        1;
12195
44.9k
    url.reserve(reserve_capacity);
12196
    //
12197
    //
12198
    //
12199
44.9k
  }
12200
59.3k
  std::string tmp_buffer;
12201
59.3k
  std::string_view internal_input;
12202
59.3k
  if (unicode::has_tabs_or_newline(user_input)) {
12203
667
    tmp_buffer = user_input;
12204
    // Optimization opportunity: Instead of copying and then pruning, we could
12205
    // just directly build the string from user_input.
12206
667
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12207
667
    internal_input = tmp_buffer;
12208
58.7k
  } else {
12209
58.7k
    internal_input = user_input;
12210
58.7k
  }
12211
12212
  // Leading and trailing control characters are uncommon and easy to deal with
12213
  // (no performance concern).
12214
59.3k
  std::string_view url_data = internal_input;
12215
59.3k
  helpers::trim_c0_whitespace(url_data);
12216
12217
  // Optimization opportunity. Most websites do not have fragment.
12218
59.3k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
12219
  // We add it last so that an implementation like ada::url_aggregator
12220
  // can append it last to its internal buffer, thus improving performance.
12221
12222
  // Here url_data no longer has its fragment.
12223
  // We are going to access the data from url_data (it is immutable).
12224
  // At any given time, we are pointing at byte 'input_position' in url_data.
12225
  // The input_position variable should range from 0 to input_size.
12226
  // It is illegal to access url_data at input_size.
12227
59.3k
  size_t input_position = 0;
12228
59.3k
  const size_t input_size = url_data.size();
12229
  // Keep running the following state machine by switching on state.
12230
  // If after a run pointer points to the EOF code point, go to the next step.
12231
  // Otherwise, increase pointer by 1 and continue with the state machine.
12232
  // We never decrement input_position.
12233
240k
  while (input_position <= input_size) {
12234
226k
    ada_log("In parsing at ", input_position, " out of ", input_size,
12235
226k
            " in state ", ada::to_string(state));
12236
226k
    switch (state) {
12237
59.3k
      case ada::state::SCHEME_START: {
12238
59.3k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
12239
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
12240
        // state to scheme state.
12241
59.3k
        if ((input_position != input_size) &&
12242
59.3k
            checkers::is_alpha(url_data[input_position])) {
12243
36.9k
          state = ada::state::SCHEME;
12244
36.9k
          input_position++;
12245
36.9k
        } else {
12246
          // Otherwise, if state override is not given, set state to no scheme
12247
          // state and decrease pointer by 1.
12248
22.4k
          state = ada::state::NO_SCHEME;
12249
22.4k
        }
12250
59.3k
        break;
12251
0
      }
12252
36.9k
      case ada::state::SCHEME: {
12253
36.9k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
12254
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
12255
        // append c, lowercased, to buffer.
12256
119k
        while ((input_position != input_size) &&
12257
119k
               (ada::unicode::is_alnum_plus(url_data[input_position]))) {
12258
82.1k
          input_position++;
12259
82.1k
        }
12260
        // Otherwise, if c is U+003A (:), then:
12261
36.9k
        if ((input_position != input_size) &&
12262
36.9k
            (url_data[input_position] == ':')) {
12263
33.7k
          ada_log("SCHEME the scheme should be ",
12264
33.7k
                  url_data.substr(0, input_position));
12265
33.7k
          if constexpr (result_type_is_ada_url) {
12266
23.7k
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
12267
0
              return url;
12268
0
            }
12269
23.7k
          } else {
12270
            // we pass the colon along instead of painfully adding it back.
12271
23.7k
            if (!url.parse_scheme_with_colon(
12272
23.7k
                    url_data.substr(0, input_position + 1))) {
12273
0
              return url;
12274
0
            }
12275
23.7k
          }
12276
33.7k
          ada_log("SCHEME the scheme is ", url.get_protocol());
12277
12278
          // If url's scheme is "file", then:
12279
33.7k
          if (url.type == ada::scheme::type::FILE) {
12280
            // Set state to file state.
12281
5.42k
            state = ada::state::FILE;
12282
5.42k
          }
12283
          // Otherwise, if url is special, base is non-null, and base's scheme
12284
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
12285
          // != nullptr is false.
12286
28.3k
          else if (url.is_special() && base_url != nullptr &&
12287
28.3k
                   base_url->type == url.type) {
12288
            // Set state to special relative or authority state.
12289
93
            state = ada::state::SPECIAL_RELATIVE_OR_AUTHORITY;
12290
93
          }
12291
          // Otherwise, if url is special, set state to special authority
12292
          // slashes state.
12293
28.2k
          else if (url.is_special()) {
12294
17.8k
            state = ada::state::SPECIAL_AUTHORITY_SLASHES;
12295
17.8k
          }
12296
          // Otherwise, if remaining starts with an U+002F (/), set state to
12297
          // path or authority state and increase pointer by 1.
12298
10.3k
          else if (input_position + 1 < input_size &&
12299
10.3k
                   url_data[input_position + 1] == '/') {
12300
6.07k
            state = ada::state::PATH_OR_AUTHORITY;
12301
6.07k
            input_position++;
12302
6.07k
          }
12303
          // Otherwise, set url's path to the empty string and set state to
12304
          // opaque path state.
12305
4.29k
          else {
12306
4.29k
            state = ada::state::OPAQUE_PATH;
12307
4.29k
          }
12308
33.7k
        }
12309
        // Otherwise, if state override is not given, set buffer to the empty
12310
        // string, state to no scheme state, and start over (from the first code
12311
        // point in input).
12312
3.21k
        else {
12313
3.21k
          state = ada::state::NO_SCHEME;
12314
3.21k
          input_position = 0;
12315
3.21k
          break;
12316
3.21k
        }
12317
33.7k
        input_position++;
12318
33.7k
        break;
12319
36.9k
      }
12320
25.6k
      case ada::state::NO_SCHEME: {
12321
25.6k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
12322
        // If base is null, or base has an opaque path and c is not U+0023 (#),
12323
        // validation error, return failure.
12324
25.6k
        if (base_url == nullptr ||
12325
25.6k
            (base_url->has_opaque_path && !fragment.has_value())) {
12326
24.4k
          ada_log("NO_SCHEME validation error");
12327
24.4k
          url.is_valid = false;
12328
24.4k
          return url;
12329
24.4k
        }
12330
        // Otherwise, if base has an opaque path and c is U+0023 (#),
12331
        // set url's scheme to base's scheme, url's path to base's path, url's
12332
        // query to base's query, and set state to fragment state.
12333
1.17k
        else if (base_url->has_opaque_path && fragment.has_value() &&
12334
1.17k
                 input_position == input_size) {
12335
29
          ada_log("NO_SCHEME opaque base with fragment");
12336
29
          url.copy_scheme(*base_url);
12337
29
          url.has_opaque_path = base_url->has_opaque_path;
12338
12339
29
          if constexpr (result_type_is_ada_url) {
12340
29
            url.path = base_url->path;
12341
29
            url.query = base_url->query;
12342
29
          } else {
12343
29
            url.update_base_pathname(base_url->get_pathname());
12344
29
            url.update_base_search(base_url->get_search());
12345
29
          }
12346
29
          url.update_unencoded_base_hash(*fragment);
12347
29
          return url;
12348
29
        }
12349
        // Otherwise, if base's scheme is not "file", set state to relative
12350
        // state and decrease pointer by 1.
12351
1.14k
        else if (base_url->type != ada::scheme::type::FILE) {
12352
663
          ada_log("NO_SCHEME non-file relative path");
12353
663
          state = ada::state::RELATIVE_SCHEME;
12354
663
        }
12355
        // Otherwise, set state to file state and decrease pointer by 1.
12356
485
        else {
12357
485
          ada_log("NO_SCHEME file base type");
12358
485
          state = ada::state::FILE;
12359
485
        }
12360
1.14k
        break;
12361
25.6k
      }
12362
19.2k
      case ada::state::AUTHORITY: {
12363
19.2k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
12364
        // most URLs have no @. Having no @ tells us that we don't have to worry
12365
        // about AUTHORITY. Of course, we could have @ and still not have to
12366
        // worry about AUTHORITY.
12367
        // TODO: Instead of just collecting a bool, collect the location of the
12368
        // '@' and do something useful with it.
12369
        // TODO: We could do various processing early on, using a single pass
12370
        // over the string to collect information about it, e.g., telling us
12371
        // whether there is a @ and if so, where (or how many).
12372
19.2k
        const bool contains_ampersand =
12373
19.2k
            (url_data.find('@', input_position) != std::string_view::npos);
12374
12375
19.2k
        if (!contains_ampersand) {
12376
18.0k
          state = ada::state::HOST;
12377
18.0k
          break;
12378
18.0k
        }
12379
1.26k
        bool at_sign_seen{false};
12380
1.26k
        bool password_token_seen{false};
12381
        /**
12382
         * We expect something of the sort...
12383
         * https://user:pass@example.com:1234/foo/bar?baz#quux
12384
         * --------^
12385
         */
12386
10.3k
        do {
12387
10.3k
          std::string_view view = helpers::substring(url_data, input_position);
12388
          // The delimiters are @, /, ? \\.
12389
10.3k
          size_t location =
12390
10.3k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
12391
10.3k
                               : helpers::find_authority_delimiter(view);
12392
10.3k
          std::string_view authority_view(view.data(), location);
12393
10.3k
          size_t end_of_authority = input_position + authority_view.size();
12394
          // If c is U+0040 (@), then:
12395
10.3k
          if ((end_of_authority != input_size) &&
12396
10.3k
              (url_data[end_of_authority] == '@')) {
12397
            // If atSignSeen is true, then prepend "%40" to buffer.
12398
9.04k
            if (at_sign_seen) {
12399
7.82k
              if (password_token_seen) {
12400
2.32k
                if constexpr (result_type_is_ada_url) {
12401
1.63k
                  url.password += "%40";
12402
1.63k
                } else {
12403
1.63k
                  url.append_base_password("%40");
12404
1.63k
                }
12405
5.49k
              } else {
12406
5.49k
                if constexpr (result_type_is_ada_url) {
12407
3.85k
                  url.username += "%40";
12408
3.85k
                } else {
12409
3.85k
                  url.append_base_username("%40");
12410
3.85k
                }
12411
5.49k
              }
12412
7.82k
            }
12413
12414
9.04k
            at_sign_seen = true;
12415
12416
9.04k
            if (!password_token_seen) {
12417
6.72k
              size_t password_token_location = authority_view.find(':');
12418
6.72k
              password_token_seen =
12419
6.72k
                  password_token_location != std::string_view::npos;
12420
12421
6.72k
              if (!password_token_seen) {
12422
6.24k
                if constexpr (result_type_is_ada_url) {
12423
4.37k
                  url.username += unicode::percent_encode(
12424
4.37k
                      authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12425
4.37k
                } else {
12426
4.37k
                  url.append_base_username(unicode::percent_encode(
12427
4.37k
                      authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12428
4.37k
                }
12429
6.24k
              } else {
12430
477
                if constexpr (result_type_is_ada_url) {
12431
336
                  url.username += unicode::percent_encode(
12432
336
                      authority_view.substr(0, password_token_location),
12433
336
                      character_sets::USERINFO_PERCENT_ENCODE);
12434
336
                  url.password += unicode::percent_encode(
12435
336
                      authority_view.substr(password_token_location + 1),
12436
336
                      character_sets::USERINFO_PERCENT_ENCODE);
12437
336
                } else {
12438
336
                  url.append_base_username(unicode::percent_encode(
12439
336
                      authority_view.substr(0, password_token_location),
12440
336
                      character_sets::USERINFO_PERCENT_ENCODE));
12441
336
                  url.append_base_password(unicode::percent_encode(
12442
336
                      authority_view.substr(password_token_location + 1),
12443
336
                      character_sets::USERINFO_PERCENT_ENCODE));
12444
336
                }
12445
477
              }
12446
6.72k
            } else {
12447
2.32k
              if constexpr (result_type_is_ada_url) {
12448
1.63k
                url.password += unicode::percent_encode(
12449
1.63k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12450
1.63k
              } else {
12451
1.63k
                url.append_base_password(unicode::percent_encode(
12452
1.63k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12453
1.63k
              }
12454
2.32k
            }
12455
9.04k
          }
12456
          // Otherwise, if one of the following is true:
12457
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12458
          // - url is special and c is U+005C (\)
12459
1.26k
          else if (end_of_authority == input_size ||
12460
1.26k
                   url_data[end_of_authority] == '/' ||
12461
1.26k
                   url_data[end_of_authority] == '?' ||
12462
1.26k
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
12463
            // If atSignSeen is true and authority_view is the empty string,
12464
            // validation error, return failure.
12465
1.26k
            if (at_sign_seen && authority_view.empty()) {
12466
682
              url.is_valid = false;
12467
682
              return url;
12468
682
            }
12469
583
            state = ada::state::HOST;
12470
583
            break;
12471
1.26k
          }
12472
9.04k
          if (end_of_authority == input_size) {
12473
0
            if (fragment.has_value()) {
12474
0
              url.update_unencoded_base_hash(*fragment);
12475
0
            }
12476
0
            return url;
12477
0
          }
12478
9.04k
          input_position = end_of_authority + 1;
12479
9.04k
        } while (true);
12480
12481
583
        break;
12482
1.26k
      }
12483
583
      case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY: {
12484
93
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
12485
93
                helpers::substring(url_data, input_position));
12486
12487
        // If c is U+002F (/) and remaining starts with U+002F (/),
12488
        // then set state to special authority ignore slashes state and increase
12489
        // pointer by 1.
12490
93
        std::string_view view = helpers::substring(url_data, input_position);
12491
93
        if (ada::checkers::begins_with(view, "//")) {
12492
2
          state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12493
2
          input_position += 2;
12494
91
        } else {
12495
          // Otherwise, validation error, set state to relative state and
12496
          // decrease pointer by 1.
12497
91
          state = ada::state::RELATIVE_SCHEME;
12498
91
        }
12499
12500
93
        break;
12501
1.26k
      }
12502
6.07k
      case ada::state::PATH_OR_AUTHORITY: {
12503
6.07k
        ada_log("PATH_OR_AUTHORITY ",
12504
6.07k
                helpers::substring(url_data, input_position));
12505
12506
        // If c is U+002F (/), then set state to authority state.
12507
6.07k
        if ((input_position != input_size) &&
12508
6.07k
            (url_data[input_position] == '/')) {
12509
1.41k
          state = ada::state::AUTHORITY;
12510
1.41k
          input_position++;
12511
4.65k
        } else {
12512
          // Otherwise, set state to path state, and decrease pointer by 1.
12513
4.65k
          state = ada::state::PATH;
12514
4.65k
        }
12515
12516
6.07k
        break;
12517
1.26k
      }
12518
754
      case ada::state::RELATIVE_SCHEME: {
12519
754
        ada_log("RELATIVE_SCHEME ",
12520
754
                helpers::substring(url_data, input_position));
12521
12522
        // Set url's scheme to base's scheme.
12523
754
        url.copy_scheme(*base_url);
12524
12525
        // If c is U+002F (/), then set state to relative slash state.
12526
754
        if ((input_position != input_size) &&
12527
754
            (url_data[input_position] == '/')) {
12528
39
          ada_log(
12529
39
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
12530
39
              "slash state");
12531
39
          state = ada::state::RELATIVE_SLASH;
12532
715
        } else if (url.is_special() && (input_position != input_size) &&
12533
715
                   (url_data[input_position] == '\\')) {
12534
          // Otherwise, if url is special and c is U+005C (\), validation error,
12535
          // set state to relative slash state.
12536
1
          ada_log(
12537
1
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
12538
1
              "error, set state to relative slash state");
12539
1
          state = ada::state::RELATIVE_SLASH;
12540
714
        } else {
12541
714
          ada_log("RELATIVE_SCHEME otherwise");
12542
          // Set url's username to base's username, url's password to base's
12543
          // password, url's host to base's host, url's port to base's port,
12544
          // url's path to a clone of base's path, and url's query to base's
12545
          // query.
12546
714
          if constexpr (result_type_is_ada_url) {
12547
714
            url.username = base_url->username;
12548
714
            url.password = base_url->password;
12549
714
            url.host = base_url->host;
12550
714
            url.port = base_url->port;
12551
            // cloning the base path includes cloning the has_opaque_path flag
12552
0
            url.has_opaque_path = base_url->has_opaque_path;
12553
0
            url.path = base_url->path;
12554
0
            url.query = base_url->query;
12555
714
          } else {
12556
714
            url.update_base_authority(base_url->get_href(),
12557
714
                                      base_url->get_components());
12558
            // TODO: Get rid of set_hostname and replace it with
12559
            // update_base_hostname
12560
714
            url.set_hostname(base_url->get_hostname());
12561
714
            url.update_base_port(base_url->retrieve_base_port());
12562
            // cloning the base path includes cloning the has_opaque_path flag
12563
714
            url.has_opaque_path = base_url->has_opaque_path;
12564
714
            url.update_base_pathname(base_url->get_pathname());
12565
714
            url.update_base_search(base_url->get_search());
12566
714
          }
12567
12568
714
          url.has_opaque_path = base_url->has_opaque_path;
12569
12570
          // If c is U+003F (?), then set url's query to the empty string, and
12571
          // state to query state.
12572
714
          if ((input_position != input_size) &&
12573
714
              (url_data[input_position] == '?')) {
12574
6
            state = ada::state::QUERY;
12575
6
          }
12576
          // Otherwise, if c is not the EOF code point:
12577
708
          else if (input_position != input_size) {
12578
            // Set url's query to null.
12579
199
            url.clear_search();
12580
199
            if constexpr (result_type_is_ada_url) {
12581
              // Shorten url's path.
12582
0
              helpers::shorten_path(url.path, url.type);
12583
199
            } else {
12584
199
              std::string_view path = url.get_pathname();
12585
199
              if (helpers::shorten_path(path, url.type)) {
12586
166
                url.update_base_pathname(std::string(path));
12587
166
              }
12588
199
            }
12589
            // Set state to path state and decrease pointer by 1.
12590
199
            state = ada::state::PATH;
12591
199
            break;
12592
199
          }
12593
714
        }
12594
555
        input_position++;
12595
555
        break;
12596
754
      }
12597
40
      case ada::state::RELATIVE_SLASH: {
12598
40
        ada_log("RELATIVE_SLASH ",
12599
40
                helpers::substring(url_data, input_position));
12600
12601
        // If url is special and c is U+002F (/) or U+005C (\), then:
12602
40
        if (url.is_special() && (input_position != input_size) &&
12603
40
            (url_data[input_position] == '/' ||
12604
11
             url_data[input_position] == '\\')) {
12605
          // Set state to special authority ignore slashes state.
12606
3
          state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12607
3
        }
12608
        // Otherwise, if c is U+002F (/), then set state to authority state.
12609
37
        else if ((input_position != input_size) &&
12610
37
                 (url_data[input_position] == '/')) {
12611
5
          state = ada::state::AUTHORITY;
12612
5
        }
12613
        // Otherwise, set
12614
        // - url's username to base's username,
12615
        // - url's password to base's password,
12616
        // - url's host to base's host,
12617
        // - url's port to base's port,
12618
        // - state to path state, and then, decrease pointer by 1.
12619
32
        else {
12620
32
          if constexpr (result_type_is_ada_url) {
12621
32
            url.username = base_url->username;
12622
32
            url.password = base_url->password;
12623
32
            url.host = base_url->host;
12624
32
            url.port = base_url->port;
12625
32
          } else {
12626
32
            url.update_base_authority(base_url->get_href(),
12627
32
                                      base_url->get_components());
12628
            // TODO: Get rid of set_hostname and replace it with
12629
            // update_base_hostname
12630
32
            url.set_hostname(base_url->get_hostname());
12631
32
            url.update_base_port(base_url->retrieve_base_port());
12632
32
          }
12633
32
          state = ada::state::PATH;
12634
32
          break;
12635
32
        }
12636
12637
8
        input_position++;
12638
8
        break;
12639
40
      }
12640
17.8k
      case ada::state::SPECIAL_AUTHORITY_SLASHES: {
12641
17.8k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
12642
17.8k
                helpers::substring(url_data, input_position));
12643
12644
        // If c is U+002F (/) and remaining starts with U+002F (/),
12645
        // then set state to special authority ignore slashes state and increase
12646
        // pointer by 1.
12647
17.8k
        std::string_view view = helpers::substring(url_data, input_position);
12648
17.8k
        if (ada::checkers::begins_with(view, "//")) {
12649
44
          input_position += 2;
12650
44
        }
12651
12652
17.8k
        [[fallthrough]];
12653
17.8k
      }
12654
17.8k
      case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
12655
17.8k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
12656
17.8k
                helpers::substring(url_data, input_position));
12657
12658
        // If c is neither U+002F (/) nor U+005C (\), then set state to
12659
        // authority state and decrease pointer by 1.
12660
19.7k
        while ((input_position != input_size) &&
12661
19.7k
               ((url_data[input_position] == '/') ||
12662
19.5k
                (url_data[input_position] == '\\'))) {
12663
1.82k
          input_position++;
12664
1.82k
        }
12665
17.8k
        state = ada::state::AUTHORITY;
12666
12667
17.8k
        break;
12668
17.8k
      }
12669
942
      case ada::state::QUERY: {
12670
942
        ada_log("QUERY ", helpers::substring(url_data, input_position));
12671
        // Let queryPercentEncodeSet be the special-query percent-encode set if
12672
        // url is special; otherwise the query percent-encode set.
12673
942
        const uint8_t* query_percent_encode_set =
12674
942
            url.is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12675
942
                             : ada::character_sets::QUERY_PERCENT_ENCODE;
12676
12677
        // Percent-encode after encoding, with encoding, buffer, and
12678
        // queryPercentEncodeSet, and append the result to url's query.
12679
942
        url.update_base_search(helpers::substring(url_data, input_position),
12680
942
                               query_percent_encode_set);
12681
942
        ada_log("QUERY update_base_search completed ");
12682
942
        if (fragment.has_value()) {
12683
123
          url.update_unencoded_base_hash(*fragment);
12684
123
        }
12685
942
        return url;
12686
17.8k
      }
12687
18.6k
      case ada::state::HOST: {
12688
18.6k
        ada_log("HOST ", helpers::substring(url_data, input_position));
12689
12690
18.6k
        std::string_view host_view =
12691
18.6k
            helpers::substring(url_data, input_position);
12692
18.6k
        auto [location, found_colon] =
12693
18.6k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
12694
18.6k
        input_position = (location != std::string_view::npos)
12695
18.6k
                             ? input_position + location
12696
18.6k
                             : input_size;
12697
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12698
        // Note: the 'found_colon' value is true if and only if a colon was
12699
        // encountered while not inside brackets.
12700
18.6k
        if (found_colon) {
12701
          // If buffer is the empty string, validation error, return failure.
12702
          // Let host be the result of host parsing buffer with url is not
12703
          // special.
12704
2.63k
          ada_log("HOST parsing ", host_view);
12705
2.63k
          if (!url.parse_host(host_view)) {
12706
483
            return url;
12707
483
          }
12708
2.14k
          ada_log("HOST parsing results in ", url.get_hostname());
12709
          // Set url's host to host, buffer to the empty string, and state to
12710
          // port state.
12711
2.14k
          state = ada::state::PORT;
12712
2.14k
          input_position++;
12713
2.14k
        }
12714
        // Otherwise, if one of the following is true:
12715
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12716
        // - url is special and c is U+005C (\)
12717
        // The get_host_delimiter_location function either brings us to
12718
        // the colon outside of the bracket, or to one of those characters.
12719
15.9k
        else {
12720
          // If url is special and host_view is the empty string, validation
12721
          // error, return failure.
12722
15.9k
          if (url.is_special() && host_view.empty()) {
12723
137
            url.is_valid = false;
12724
137
            return url;
12725
137
          }
12726
15.8k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
12727
          // Let host be the result of host parsing host_view with url is not
12728
          // special.
12729
15.8k
          if (host_view.empty()) {
12730
66
            url.update_base_hostname("");
12731
15.7k
          } else if (!url.parse_host(host_view)) {
12732
3.90k
            return url;
12733
3.90k
          }
12734
11.9k
          ada_log("HOST parsing results in ", url.get_hostname(),
12735
11.9k
                  " href=", url.get_href());
12736
12737
          // Set url's host to host, and state to path start state.
12738
11.9k
          state = ada::state::PATH_START;
12739
11.9k
        }
12740
12741
14.0k
        break;
12742
18.6k
      }
12743
14.0k
      case ada::state::OPAQUE_PATH: {
12744
4.29k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
12745
4.29k
        std::string_view view = helpers::substring(url_data, input_position);
12746
        // If c is U+003F (?), then set url's query to the empty string and
12747
        // state to query state.
12748
4.29k
        size_t location = view.find('?');
12749
4.29k
        if (location != std::string_view::npos) {
12750
248
          view.remove_suffix(view.size() - location);
12751
248
          state = ada::state::QUERY;
12752
248
          input_position += location + 1;
12753
4.05k
        } else {
12754
4.05k
          input_position = input_size + 1;
12755
4.05k
        }
12756
4.29k
        url.has_opaque_path = true;
12757
        // This is a really unlikely scenario in real world. We should not seek
12758
        // to optimize it.
12759
4.29k
        url.update_base_pathname(unicode::percent_encode(
12760
4.29k
            view, character_sets::C0_CONTROL_PERCENT_ENCODE));
12761
4.29k
        break;
12762
18.6k
      }
12763
2.14k
      case ada::state::PORT: {
12764
2.14k
        ada_log("PORT ", helpers::substring(url_data, input_position));
12765
2.14k
        std::string_view port_view =
12766
2.14k
            helpers::substring(url_data, input_position);
12767
2.14k
        size_t consumed_bytes = url.parse_port(port_view, true);
12768
2.14k
        input_position += consumed_bytes;
12769
2.14k
        if (!url.is_valid) {
12770
267
          return url;
12771
267
        }
12772
1.88k
        state = state::PATH_START;
12773
1.88k
        [[fallthrough]];
12774
1.88k
      }
12775
15.4k
      case ada::state::PATH_START: {
12776
15.4k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
12777
12778
        // If url is special, then:
12779
15.4k
        if (url.is_special()) {
12780
          // Set state to path state.
12781
14.5k
          state = ada::state::PATH;
12782
12783
          // Optimization: Avoiding going into PATH state improves the
12784
          // performance of urls ending with /.
12785
14.5k
          if (input_position == input_size) {
12786
13.2k
            url.update_base_pathname("/");
12787
13.2k
            if (fragment.has_value()) {
12788
198
              url.update_unencoded_base_hash(*fragment);
12789
198
            }
12790
13.2k
            return url;
12791
13.2k
          }
12792
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
12793
          // by 1. We know that (input_position == input_size) is impossible
12794
          // here, because of the previous if-check.
12795
1.33k
          if ((url_data[input_position] != '/') &&
12796
1.33k
              (url_data[input_position] != '\\')) {
12797
296
            break;
12798
296
          }
12799
1.33k
        }
12800
        // Otherwise, if state override is not given and c is U+003F (?),
12801
        // set url's query to the empty string and state to query state.
12802
898
        else if ((input_position != input_size) &&
12803
898
                 (url_data[input_position] == '?')) {
12804
110
          state = ada::state::QUERY;
12805
110
        }
12806
        // Otherwise, if c is not the EOF code point:
12807
788
        else if (input_position != input_size) {
12808
          // Set state to path state.
12809
61
          state = ada::state::PATH;
12810
12811
          // If c is not U+002F (/), then decrease pointer by 1.
12812
61
          if (url_data[input_position] != '/') {
12813
0
            break;
12814
0
          }
12815
61
        }
12816
12817
1.93k
        input_position++;
12818
1.93k
        break;
12819
15.4k
      }
12820
9.89k
      case ada::state::PATH: {
12821
9.89k
        std::string_view view = helpers::substring(url_data, input_position);
12822
9.89k
        ada_log("PATH ", helpers::substring(url_data, input_position));
12823
12824
        // Most time, we do not need percent encoding.
12825
        // Furthermore, we can immediately locate the '?'.
12826
9.89k
        size_t locofquestionmark = view.find('?');
12827
9.89k
        if (locofquestionmark != std::string_view::npos) {
12828
576
          state = ada::state::QUERY;
12829
576
          view.remove_suffix(view.size() - locofquestionmark);
12830
576
          input_position += locofquestionmark + 1;
12831
9.31k
        } else {
12832
9.31k
          input_position = input_size + 1;
12833
9.31k
        }
12834
9.89k
        if constexpr (result_type_is_ada_url) {
12835
6.96k
          helpers::parse_prepared_path(view, url.type, url.path);
12836
6.96k
        } else {
12837
6.96k
          url.consume_prepared_path(view);
12838
6.96k
          ADA_ASSERT_TRUE(url.validate());
12839
6.96k
        }
12840
9.89k
        break;
12841
15.4k
      }
12842
2.50k
      case ada::state::FILE_SLASH: {
12843
2.50k
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
12844
12845
        // If c is U+002F (/) or U+005C (\), then:
12846
2.50k
        if ((input_position != input_size) &&
12847
2.50k
            (url_data[input_position] == '/' ||
12848
2.16k
             url_data[input_position] == '\\')) {
12849
2.06k
          ada_log("FILE_SLASH c is U+002F or U+005C");
12850
          // Set state to file host state.
12851
2.06k
          state = ada::state::FILE_HOST;
12852
2.06k
          input_position++;
12853
2.06k
        } else {
12854
435
          ada_log("FILE_SLASH otherwise");
12855
          // If base is non-null and base's scheme is "file", then:
12856
          // Note: it is unsafe to do base_url->scheme unless you know that
12857
          // base_url_has_value() is true.
12858
435
          if (base_url != nullptr &&
12859
435
              base_url->type == ada::scheme::type::FILE) {
12860
            // Set url's host to base's host.
12861
230
            if constexpr (result_type_is_ada_url) {
12862
230
              url.host = base_url->host;
12863
230
            } else {
12864
              // TODO: Optimization opportunity.
12865
230
              url.set_host(base_url->get_host());
12866
230
            }
12867
            // If the code point substring from pointer to the end of input does
12868
            // not start with a Windows drive letter and base's path[0] is a
12869
            // normalized Windows drive letter, then append base's path[0] to
12870
            // url's path.
12871
230
            if (!base_url->get_pathname().empty()) {
12872
230
              if (!checkers::is_windows_drive_letter(
12873
230
                      helpers::substring(url_data, input_position))) {
12874
224
                std::string_view first_base_url_path =
12875
224
                    base_url->get_pathname().substr(1);
12876
224
                size_t loc = first_base_url_path.find('/');
12877
224
                if (loc != std::string_view::npos) {
12878
13
                  helpers::resize(first_base_url_path, loc);
12879
13
                }
12880
224
                if (checkers::is_normalized_windows_drive_letter(
12881
224
                        first_base_url_path)) {
12882
3
                  if constexpr (result_type_is_ada_url) {
12883
3
                    url.path += '/';
12884
3
                    url.path += first_base_url_path;
12885
3
                  } else {
12886
3
                    url.append_base_pathname(
12887
3
                        helpers::concat("/", first_base_url_path));
12888
3
                  }
12889
3
                }
12890
224
              }
12891
230
            }
12892
230
          }
12893
12894
          // Set state to path state, and decrease pointer by 1.
12895
435
          state = ada::state::PATH;
12896
435
        }
12897
12898
2.50k
        break;
12899
15.4k
      }
12900
2.06k
      case ada::state::FILE_HOST: {
12901
2.06k
        std::string_view view = helpers::substring(url_data, input_position);
12902
2.06k
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
12903
12904
2.06k
        size_t location = view.find_first_of("/\\?");
12905
2.06k
        std::string_view file_host_buffer(
12906
2.06k
            view.data(),
12907
2.06k
            (location != std::string_view::npos) ? location : view.size());
12908
12909
2.06k
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
12910
26
          state = ada::state::PATH;
12911
2.04k
        } else if (file_host_buffer.empty()) {
12912
          // Set url's host to the empty string.
12913
55
          if constexpr (result_type_is_ada_url) {
12914
42
            url.host = "";
12915
42
          } else {
12916
42
            url.update_base_hostname("");
12917
42
          }
12918
          // Set state to path start state.
12919
55
          state = ada::state::PATH_START;
12920
1.98k
        } else {
12921
1.98k
          size_t consumed_bytes = file_host_buffer.size();
12922
1.98k
          input_position += consumed_bytes;
12923
          // Let host be the result of host parsing buffer with url is not
12924
          // special.
12925
1.98k
          if (!url.parse_host(file_host_buffer)) {
12926
401
            return url;
12927
401
          }
12928
12929
1.58k
          if constexpr (result_type_is_ada_url) {
12930
            // If host is "localhost", then set host to the empty string.
12931
1.23k
            if (url.host.has_value() && url.host.value() == "localhost") {
12932
3
              url.host = "";
12933
3
            }
12934
1.23k
          } else {
12935
1.23k
            if (url.get_hostname() == "localhost") {
12936
11
              url.update_base_hostname("");
12937
11
            }
12938
1.23k
          }
12939
12940
          // Set buffer to the empty string and state to path start state.
12941
1.58k
          state = ada::state::PATH_START;
12942
1.58k
        }
12943
12944
1.66k
        break;
12945
2.06k
      }
12946
5.91k
      case ada::state::FILE: {
12947
5.91k
        ada_log("FILE ", helpers::substring(url_data, input_position));
12948
5.91k
        std::string_view file_view =
12949
5.91k
            helpers::substring(url_data, input_position);
12950
12951
5.91k
        url.set_protocol_as_file();
12952
5.91k
        if constexpr (result_type_is_ada_url) {
12953
          // Set url's host to the empty string.
12954
1.51k
          url.host = "";
12955
4.40k
        } else {
12956
4.40k
          url.update_base_hostname("");
12957
4.40k
        }
12958
        // If c is U+002F (/) or U+005C (\), then:
12959
5.91k
        if (input_position != input_size &&
12960
5.91k
            (url_data[input_position] == '/' ||
12961
3.73k
             url_data[input_position] == '\\')) {
12962
2.50k
          ada_log("FILE c is U+002F or U+005C");
12963
          // Set state to file slash state.
12964
2.50k
          state = ada::state::FILE_SLASH;
12965
2.50k
        }
12966
        // Otherwise, if base is non-null and base's scheme is "file":
12967
3.40k
        else if (base_url != nullptr &&
12968
3.40k
                 base_url->type == ada::scheme::type::FILE) {
12969
          // Set url's host to base's host, url's path to a clone of base's
12970
          // path, and url's query to base's query.
12971
351
          ada_log("FILE base non-null");
12972
351
          if constexpr (result_type_is_ada_url) {
12973
351
            url.host = base_url->host;
12974
351
            url.path = base_url->path;
12975
351
            url.query = base_url->query;
12976
351
          } else {
12977
            // TODO: Get rid of set_hostname and replace it with
12978
            // update_base_hostname
12979
351
            url.set_hostname(base_url->get_hostname());
12980
351
            url.update_base_pathname(base_url->get_pathname());
12981
351
            url.update_base_search(base_url->get_search());
12982
351
          }
12983
351
          url.has_opaque_path = base_url->has_opaque_path;
12984
12985
          // If c is U+003F (?), then set url's query to the empty string and
12986
          // state to query state.
12987
351
          if (input_position != input_size && url_data[input_position] == '?') {
12988
2
            state = ada::state::QUERY;
12989
2
          }
12990
          // Otherwise, if c is not the EOF code point:
12991
349
          else if (input_position != input_size) {
12992
            // Set url's query to null.
12993
91
            url.clear_search();
12994
            // If the code point substring from pointer to the end of input does
12995
            // not start with a Windows drive letter, then shorten url's path.
12996
91
            if (!checkers::is_windows_drive_letter(file_view)) {
12997
80
              if constexpr (result_type_is_ada_url) {
12998
80
                helpers::shorten_path(url.path, url.type);
12999
80
              } else {
13000
80
                std::string_view path = url.get_pathname();
13001
80
                if (helpers::shorten_path(path, url.type)) {
13002
78
                  url.update_base_pathname(std::string(path));
13003
78
                }
13004
80
              }
13005
80
            }
13006
            // Otherwise:
13007
11
            else {
13008
              // Set url's path to an empty list.
13009
11
              url.clear_pathname();
13010
11
              url.has_opaque_path = true;
13011
11
            }
13012
13013
            // Set state to path state and decrease pointer by 1.
13014
91
            state = ada::state::PATH;
13015
91
            break;
13016
91
          }
13017
351
        }
13018
        // Otherwise, set state to path state, and decrease pointer by 1.
13019
3.05k
        else {
13020
3.05k
          ada_log("FILE go to path");
13021
3.05k
          state = ada::state::PATH;
13022
3.05k
          break;
13023
3.05k
        }
13024
13025
2.76k
        input_position++;
13026
2.76k
        break;
13027
5.91k
      }
13028
0
      default:
13029
0
        ada::unreachable();
13030
226k
    }
13031
226k
  }
13032
14.8k
  if (fragment.has_value()) {
13033
587
    url.update_unencoded_base_hash(*fragment);
13034
587
  }
13035
14.8k
  return url;
13036
59.3k
}
ada::url ada::parser::parse_url<ada::url>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url const*)
Line
Count
Source
12144
14.3k
                      const result_type* base_url) {
12145
  // We can specialize the implementation per type.
12146
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
12147
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
12148
  // something else } is free (at runtime). This means that ada::url_aggregator
12149
  // and ada::url **do not have to support the exact same API**.
12150
14.3k
  constexpr bool result_type_is_ada_url =
12151
14.3k
      std::is_same<ada::url, result_type>::value;
12152
14.3k
  constexpr bool result_type_is_ada_url_aggregator =
12153
14.3k
      std::is_same<ada::url_aggregator, result_type>::value;
12154
14.3k
  static_assert(result_type_is_ada_url ||
12155
14.3k
                result_type_is_ada_url_aggregator);  // We don't support
12156
                                                     // anything else for now.
12157
12158
14.3k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
12159
14.3k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
12160
14.3k
          ")");
12161
12162
14.3k
  ada::state state = ada::state::SCHEME_START;
12163
14.3k
  result_type url{};
12164
12165
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
12166
  // surely the result of a bug or are otherwise a security concern.
12167
14.3k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) {
12168
0
    url.is_valid = false;
12169
0
  }
12170
  // Going forward, user_input.size() is in [0,
12171
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
12172
  // base, or the optional_url was invalid, we must return.
12173
14.3k
  if (base_url != nullptr) {
12174
0
    url.is_valid &= base_url->is_valid;
12175
0
  }
12176
14.3k
  if (!url.is_valid) {
12177
0
    return url;
12178
0
  }
12179
14.3k
  if constexpr (result_type_is_ada_url_aggregator) {
12180
    // Most of the time, we just need user_input.size().
12181
    // In some instances, we may need a bit more.
12182
    ///////////////////////////
12183
    // This is *very* important. This line should *not* be removed
12184
    // hastily. There are principled reasons why reserve is important
12185
    // for performance. If you have a benchmark with small inputs,
12186
    // it may not matter, but in other instances, it could.
12187
    ////
12188
    // This rounds up to the next power of two.
12189
    // We know that user_input.size() is in [0,
12190
    // std::numeric_limits<uint32_t>::max).
12191
14.3k
    uint32_t reserve_capacity =
12192
14.3k
        (0xFFFFFFFF >>
12193
14.3k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
12194
14.3k
        1;
12195
14.3k
    url.reserve(reserve_capacity);
12196
    //
12197
    //
12198
    //
12199
14.3k
  }
12200
14.3k
  std::string tmp_buffer;
12201
14.3k
  std::string_view internal_input;
12202
14.3k
  if (unicode::has_tabs_or_newline(user_input)) {
12203
195
    tmp_buffer = user_input;
12204
    // Optimization opportunity: Instead of copying and then pruning, we could
12205
    // just directly build the string from user_input.
12206
195
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12207
195
    internal_input = tmp_buffer;
12208
14.1k
  } else {
12209
14.1k
    internal_input = user_input;
12210
14.1k
  }
12211
12212
  // Leading and trailing control characters are uncommon and easy to deal with
12213
  // (no performance concern).
12214
14.3k
  std::string_view url_data = internal_input;
12215
14.3k
  helpers::trim_c0_whitespace(url_data);
12216
12217
  // Optimization opportunity. Most websites do not have fragment.
12218
14.3k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
12219
  // We add it last so that an implementation like ada::url_aggregator
12220
  // can append it last to its internal buffer, thus improving performance.
12221
12222
  // Here url_data no longer has its fragment.
12223
  // We are going to access the data from url_data (it is immutable).
12224
  // At any given time, we are pointing at byte 'input_position' in url_data.
12225
  // The input_position variable should range from 0 to input_size.
12226
  // It is illegal to access url_data at input_size.
12227
14.3k
  size_t input_position = 0;
12228
14.3k
  const size_t input_size = url_data.size();
12229
  // Keep running the following state machine by switching on state.
12230
  // If after a run pointer points to the EOF code point, go to the next step.
12231
  // Otherwise, increase pointer by 1 and continue with the state machine.
12232
  // We never decrement input_position.
12233
64.3k
  while (input_position <= input_size) {
12234
60.3k
    ada_log("In parsing at ", input_position, " out of ", input_size,
12235
60.3k
            " in state ", ada::to_string(state));
12236
60.3k
    switch (state) {
12237
14.3k
      case ada::state::SCHEME_START: {
12238
14.3k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
12239
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
12240
        // state to scheme state.
12241
14.3k
        if ((input_position != input_size) &&
12242
14.3k
            checkers::is_alpha(url_data[input_position])) {
12243
11.0k
          state = ada::state::SCHEME;
12244
11.0k
          input_position++;
12245
11.0k
        } else {
12246
          // Otherwise, if state override is not given, set state to no scheme
12247
          // state and decrease pointer by 1.
12248
3.38k
          state = ada::state::NO_SCHEME;
12249
3.38k
        }
12250
14.3k
        break;
12251
0
      }
12252
11.0k
      case ada::state::SCHEME: {
12253
11.0k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
12254
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
12255
        // append c, lowercased, to buffer.
12256
36.4k
        while ((input_position != input_size) &&
12257
36.4k
               (ada::unicode::is_alnum_plus(url_data[input_position]))) {
12258
25.4k
          input_position++;
12259
25.4k
        }
12260
        // Otherwise, if c is U+003A (:), then:
12261
11.0k
        if ((input_position != input_size) &&
12262
11.0k
            (url_data[input_position] == ':')) {
12263
9.97k
          ada_log("SCHEME the scheme should be ",
12264
9.97k
                  url_data.substr(0, input_position));
12265
9.97k
          if constexpr (result_type_is_ada_url) {
12266
9.97k
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
12267
0
              return url;
12268
0
            }
12269
9.97k
          } else {
12270
            // we pass the colon along instead of painfully adding it back.
12271
9.97k
            if (!url.parse_scheme_with_colon(
12272
9.97k
                    url_data.substr(0, input_position + 1))) {
12273
9.97k
              return url;
12274
9.97k
            }
12275
9.97k
          }
12276
9.97k
          ada_log("SCHEME the scheme is ", url.get_protocol());
12277
12278
          // If url's scheme is "file", then:
12279
9.97k
          if (url.type == ada::scheme::type::FILE) {
12280
            // Set state to file state.
12281
1.51k
            state = ada::state::FILE;
12282
1.51k
          }
12283
          // Otherwise, if url is special, base is non-null, and base's scheme
12284
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
12285
          // != nullptr is false.
12286
8.46k
          else if (url.is_special() && base_url != nullptr &&
12287
8.46k
                   base_url->type == url.type) {
12288
            // Set state to special relative or authority state.
12289
0
            state = ada::state::SPECIAL_RELATIVE_OR_AUTHORITY;
12290
0
          }
12291
          // Otherwise, if url is special, set state to special authority
12292
          // slashes state.
12293
8.46k
          else if (url.is_special()) {
12294
5.47k
            state = ada::state::SPECIAL_AUTHORITY_SLASHES;
12295
5.47k
          }
12296
          // Otherwise, if remaining starts with an U+002F (/), set state to
12297
          // path or authority state and increase pointer by 1.
12298
2.98k
          else if (input_position + 1 < input_size &&
12299
2.98k
                   url_data[input_position + 1] == '/') {
12300
1.95k
            state = ada::state::PATH_OR_AUTHORITY;
12301
1.95k
            input_position++;
12302
1.95k
          }
12303
          // Otherwise, set url's path to the empty string and set state to
12304
          // opaque path state.
12305
1.03k
          else {
12306
1.03k
            state = ada::state::OPAQUE_PATH;
12307
1.03k
          }
12308
9.97k
        }
12309
        // Otherwise, if state override is not given, set buffer to the empty
12310
        // string, state to no scheme state, and start over (from the first code
12311
        // point in input).
12312
1.02k
        else {
12313
1.02k
          state = ada::state::NO_SCHEME;
12314
1.02k
          input_position = 0;
12315
1.02k
          break;
12316
1.02k
        }
12317
9.97k
        input_position++;
12318
9.97k
        break;
12319
11.0k
      }
12320
4.40k
      case ada::state::NO_SCHEME: {
12321
4.40k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
12322
        // If base is null, or base has an opaque path and c is not U+0023 (#),
12323
        // validation error, return failure.
12324
4.40k
        if (base_url == nullptr ||
12325
4.40k
            (base_url->has_opaque_path && !fragment.has_value())) {
12326
4.40k
          ada_log("NO_SCHEME validation error");
12327
4.40k
          url.is_valid = false;
12328
4.40k
          return url;
12329
4.40k
        }
12330
        // Otherwise, if base has an opaque path and c is U+0023 (#),
12331
        // set url's scheme to base's scheme, url's path to base's path, url's
12332
        // query to base's query, and set state to fragment state.
12333
0
        else if (base_url->has_opaque_path && fragment.has_value() &&
12334
0
                 input_position == input_size) {
12335
0
          ada_log("NO_SCHEME opaque base with fragment");
12336
0
          url.copy_scheme(*base_url);
12337
0
          url.has_opaque_path = base_url->has_opaque_path;
12338
12339
0
          if constexpr (result_type_is_ada_url) {
12340
0
            url.path = base_url->path;
12341
0
            url.query = base_url->query;
12342
0
          } else {
12343
0
            url.update_base_pathname(base_url->get_pathname());
12344
0
            url.update_base_search(base_url->get_search());
12345
0
          }
12346
0
          url.update_unencoded_base_hash(*fragment);
12347
0
          return url;
12348
0
        }
12349
        // Otherwise, if base's scheme is not "file", set state to relative
12350
        // state and decrease pointer by 1.
12351
0
        else if (base_url->type != ada::scheme::type::FILE) {
12352
0
          ada_log("NO_SCHEME non-file relative path");
12353
0
          state = ada::state::RELATIVE_SCHEME;
12354
0
        }
12355
        // Otherwise, set state to file state and decrease pointer by 1.
12356
0
        else {
12357
0
          ada_log("NO_SCHEME file base type");
12358
0
          state = ada::state::FILE;
12359
0
        }
12360
0
        break;
12361
4.40k
      }
12362
5.92k
      case ada::state::AUTHORITY: {
12363
5.92k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
12364
        // most URLs have no @. Having no @ tells us that we don't have to worry
12365
        // about AUTHORITY. Of course, we could have @ and still not have to
12366
        // worry about AUTHORITY.
12367
        // TODO: Instead of just collecting a bool, collect the location of the
12368
        // '@' and do something useful with it.
12369
        // TODO: We could do various processing early on, using a single pass
12370
        // over the string to collect information about it, e.g., telling us
12371
        // whether there is a @ and if so, where (or how many).
12372
5.92k
        const bool contains_ampersand =
12373
5.92k
            (url_data.find('@', input_position) != std::string_view::npos);
12374
12375
5.92k
        if (!contains_ampersand) {
12376
5.54k
          state = ada::state::HOST;
12377
5.54k
          break;
12378
5.54k
        }
12379
379
        bool at_sign_seen{false};
12380
379
        bool password_token_seen{false};
12381
        /**
12382
         * We expect something of the sort...
12383
         * https://user:pass@example.com:1234/foo/bar?baz#quux
12384
         * --------^
12385
         */
12386
3.07k
        do {
12387
3.07k
          std::string_view view = helpers::substring(url_data, input_position);
12388
          // The delimiters are @, /, ? \\.
12389
3.07k
          size_t location =
12390
3.07k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
12391
3.07k
                               : helpers::find_authority_delimiter(view);
12392
3.07k
          std::string_view authority_view(view.data(), location);
12393
3.07k
          size_t end_of_authority = input_position + authority_view.size();
12394
          // If c is U+0040 (@), then:
12395
3.07k
          if ((end_of_authority != input_size) &&
12396
3.07k
              (url_data[end_of_authority] == '@')) {
12397
            // If atSignSeen is true, then prepend "%40" to buffer.
12398
2.69k
            if (at_sign_seen) {
12399
2.33k
              if (password_token_seen) {
12400
684
                if constexpr (result_type_is_ada_url) {
12401
684
                  url.password += "%40";
12402
684
                } else {
12403
684
                  url.append_base_password("%40");
12404
684
                }
12405
1.64k
              } else {
12406
1.64k
                if constexpr (result_type_is_ada_url) {
12407
1.64k
                  url.username += "%40";
12408
1.64k
                } else {
12409
1.64k
                  url.append_base_username("%40");
12410
1.64k
                }
12411
1.64k
              }
12412
2.33k
            }
12413
12414
2.69k
            at_sign_seen = true;
12415
12416
2.69k
            if (!password_token_seen) {
12417
2.01k
              size_t password_token_location = authority_view.find(':');
12418
2.01k
              password_token_seen =
12419
2.01k
                  password_token_location != std::string_view::npos;
12420
12421
2.01k
              if (!password_token_seen) {
12422
1.87k
                if constexpr (result_type_is_ada_url) {
12423
1.87k
                  url.username += unicode::percent_encode(
12424
1.87k
                      authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12425
1.87k
                } else {
12426
1.87k
                  url.append_base_username(unicode::percent_encode(
12427
1.87k
                      authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12428
1.87k
                }
12429
1.87k
              } else {
12430
141
                if constexpr (result_type_is_ada_url) {
12431
141
                  url.username += unicode::percent_encode(
12432
141
                      authority_view.substr(0, password_token_location),
12433
141
                      character_sets::USERINFO_PERCENT_ENCODE);
12434
141
                  url.password += unicode::percent_encode(
12435
141
                      authority_view.substr(password_token_location + 1),
12436
141
                      character_sets::USERINFO_PERCENT_ENCODE);
12437
141
                } else {
12438
141
                  url.append_base_username(unicode::percent_encode(
12439
141
                      authority_view.substr(0, password_token_location),
12440
141
                      character_sets::USERINFO_PERCENT_ENCODE));
12441
141
                  url.append_base_password(unicode::percent_encode(
12442
141
                      authority_view.substr(password_token_location + 1),
12443
141
                      character_sets::USERINFO_PERCENT_ENCODE));
12444
141
                }
12445
141
              }
12446
2.01k
            } else {
12447
684
              if constexpr (result_type_is_ada_url) {
12448
684
                url.password += unicode::percent_encode(
12449
684
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12450
684
              } else {
12451
684
                url.append_base_password(unicode::percent_encode(
12452
684
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12453
684
              }
12454
684
            }
12455
2.69k
          }
12456
          // Otherwise, if one of the following is true:
12457
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12458
          // - url is special and c is U+005C (\)
12459
379
          else if (end_of_authority == input_size ||
12460
379
                   url_data[end_of_authority] == '/' ||
12461
379
                   url_data[end_of_authority] == '?' ||
12462
379
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
12463
            // If atSignSeen is true and authority_view is the empty string,
12464
            // validation error, return failure.
12465
379
            if (at_sign_seen && authority_view.empty()) {
12466
211
              url.is_valid = false;
12467
211
              return url;
12468
211
            }
12469
168
            state = ada::state::HOST;
12470
168
            break;
12471
379
          }
12472
2.69k
          if (end_of_authority == input_size) {
12473
0
            if (fragment.has_value()) {
12474
0
              url.update_unencoded_base_hash(*fragment);
12475
0
            }
12476
0
            return url;
12477
0
          }
12478
2.69k
          input_position = end_of_authority + 1;
12479
2.69k
        } while (true);
12480
12481
168
        break;
12482
379
      }
12483
168
      case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY: {
12484
0
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
12485
0
                helpers::substring(url_data, input_position));
12486
12487
        // If c is U+002F (/) and remaining starts with U+002F (/),
12488
        // then set state to special authority ignore slashes state and increase
12489
        // pointer by 1.
12490
0
        std::string_view view = helpers::substring(url_data, input_position);
12491
0
        if (ada::checkers::begins_with(view, "//")) {
12492
0
          state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12493
0
          input_position += 2;
12494
0
        } else {
12495
          // Otherwise, validation error, set state to relative state and
12496
          // decrease pointer by 1.
12497
0
          state = ada::state::RELATIVE_SCHEME;
12498
0
        }
12499
12500
0
        break;
12501
379
      }
12502
1.95k
      case ada::state::PATH_OR_AUTHORITY: {
12503
1.95k
        ada_log("PATH_OR_AUTHORITY ",
12504
1.95k
                helpers::substring(url_data, input_position));
12505
12506
        // If c is U+002F (/), then set state to authority state.
12507
1.95k
        if ((input_position != input_size) &&
12508
1.95k
            (url_data[input_position] == '/')) {
12509
449
          state = ada::state::AUTHORITY;
12510
449
          input_position++;
12511
1.50k
        } else {
12512
          // Otherwise, set state to path state, and decrease pointer by 1.
12513
1.50k
          state = ada::state::PATH;
12514
1.50k
        }
12515
12516
1.95k
        break;
12517
379
      }
12518
0
      case ada::state::RELATIVE_SCHEME: {
12519
0
        ada_log("RELATIVE_SCHEME ",
12520
0
                helpers::substring(url_data, input_position));
12521
12522
        // Set url's scheme to base's scheme.
12523
0
        url.copy_scheme(*base_url);
12524
12525
        // If c is U+002F (/), then set state to relative slash state.
12526
0
        if ((input_position != input_size) &&
12527
0
            (url_data[input_position] == '/')) {
12528
0
          ada_log(
12529
0
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
12530
0
              "slash state");
12531
0
          state = ada::state::RELATIVE_SLASH;
12532
0
        } else if (url.is_special() && (input_position != input_size) &&
12533
0
                   (url_data[input_position] == '\\')) {
12534
          // Otherwise, if url is special and c is U+005C (\), validation error,
12535
          // set state to relative slash state.
12536
0
          ada_log(
12537
0
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
12538
0
              "error, set state to relative slash state");
12539
0
          state = ada::state::RELATIVE_SLASH;
12540
0
        } else {
12541
0
          ada_log("RELATIVE_SCHEME otherwise");
12542
          // Set url's username to base's username, url's password to base's
12543
          // password, url's host to base's host, url's port to base's port,
12544
          // url's path to a clone of base's path, and url's query to base's
12545
          // query.
12546
0
          if constexpr (result_type_is_ada_url) {
12547
0
            url.username = base_url->username;
12548
0
            url.password = base_url->password;
12549
0
            url.host = base_url->host;
12550
0
            url.port = base_url->port;
12551
            // cloning the base path includes cloning the has_opaque_path flag
12552
0
            url.has_opaque_path = base_url->has_opaque_path;
12553
0
            url.path = base_url->path;
12554
0
            url.query = base_url->query;
12555
0
          } else {
12556
0
            url.update_base_authority(base_url->get_href(),
12557
0
                                      base_url->get_components());
12558
            // TODO: Get rid of set_hostname and replace it with
12559
            // update_base_hostname
12560
0
            url.set_hostname(base_url->get_hostname());
12561
0
            url.update_base_port(base_url->retrieve_base_port());
12562
            // cloning the base path includes cloning the has_opaque_path flag
12563
0
            url.has_opaque_path = base_url->has_opaque_path;
12564
0
            url.update_base_pathname(base_url->get_pathname());
12565
0
            url.update_base_search(base_url->get_search());
12566
0
          }
12567
12568
0
          url.has_opaque_path = base_url->has_opaque_path;
12569
12570
          // If c is U+003F (?), then set url's query to the empty string, and
12571
          // state to query state.
12572
0
          if ((input_position != input_size) &&
12573
0
              (url_data[input_position] == '?')) {
12574
0
            state = ada::state::QUERY;
12575
0
          }
12576
          // Otherwise, if c is not the EOF code point:
12577
0
          else if (input_position != input_size) {
12578
            // Set url's query to null.
12579
0
            url.clear_search();
12580
0
            if constexpr (result_type_is_ada_url) {
12581
              // Shorten url's path.
12582
0
              helpers::shorten_path(url.path, url.type);
12583
0
            } else {
12584
0
              std::string_view path = url.get_pathname();
12585
0
              if (helpers::shorten_path(path, url.type)) {
12586
0
                url.update_base_pathname(std::string(path));
12587
0
              }
12588
0
            }
12589
            // Set state to path state and decrease pointer by 1.
12590
0
            state = ada::state::PATH;
12591
0
            break;
12592
0
          }
12593
0
        }
12594
0
        input_position++;
12595
0
        break;
12596
0
      }
12597
0
      case ada::state::RELATIVE_SLASH: {
12598
0
        ada_log("RELATIVE_SLASH ",
12599
0
                helpers::substring(url_data, input_position));
12600
12601
        // If url is special and c is U+002F (/) or U+005C (\), then:
12602
0
        if (url.is_special() && (input_position != input_size) &&
12603
0
            (url_data[input_position] == '/' ||
12604
0
             url_data[input_position] == '\\')) {
12605
          // Set state to special authority ignore slashes state.
12606
0
          state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12607
0
        }
12608
        // Otherwise, if c is U+002F (/), then set state to authority state.
12609
0
        else if ((input_position != input_size) &&
12610
0
                 (url_data[input_position] == '/')) {
12611
0
          state = ada::state::AUTHORITY;
12612
0
        }
12613
        // Otherwise, set
12614
        // - url's username to base's username,
12615
        // - url's password to base's password,
12616
        // - url's host to base's host,
12617
        // - url's port to base's port,
12618
        // - state to path state, and then, decrease pointer by 1.
12619
0
        else {
12620
0
          if constexpr (result_type_is_ada_url) {
12621
0
            url.username = base_url->username;
12622
0
            url.password = base_url->password;
12623
0
            url.host = base_url->host;
12624
0
            url.port = base_url->port;
12625
0
          } else {
12626
0
            url.update_base_authority(base_url->get_href(),
12627
0
                                      base_url->get_components());
12628
            // TODO: Get rid of set_hostname and replace it with
12629
            // update_base_hostname
12630
0
            url.set_hostname(base_url->get_hostname());
12631
0
            url.update_base_port(base_url->retrieve_base_port());
12632
0
          }
12633
0
          state = ada::state::PATH;
12634
0
          break;
12635
0
        }
12636
12637
0
        input_position++;
12638
0
        break;
12639
0
      }
12640
5.47k
      case ada::state::SPECIAL_AUTHORITY_SLASHES: {
12641
5.47k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
12642
5.47k
                helpers::substring(url_data, input_position));
12643
12644
        // If c is U+002F (/) and remaining starts with U+002F (/),
12645
        // then set state to special authority ignore slashes state and increase
12646
        // pointer by 1.
12647
5.47k
        std::string_view view = helpers::substring(url_data, input_position);
12648
5.47k
        if (ada::checkers::begins_with(view, "//")) {
12649
13
          input_position += 2;
12650
13
        }
12651
12652
5.47k
        [[fallthrough]];
12653
5.47k
      }
12654
5.47k
      case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
12655
5.47k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
12656
5.47k
                helpers::substring(url_data, input_position));
12657
12658
        // If c is neither U+002F (/) nor U+005C (\), then set state to
12659
        // authority state and decrease pointer by 1.
12660
6.05k
        while ((input_position != input_size) &&
12661
6.05k
               ((url_data[input_position] == '/') ||
12662
6.02k
                (url_data[input_position] == '\\'))) {
12663
576
          input_position++;
12664
576
        }
12665
5.47k
        state = ada::state::AUTHORITY;
12666
12667
5.47k
        break;
12668
5.47k
      }
12669
263
      case ada::state::QUERY: {
12670
263
        ada_log("QUERY ", helpers::substring(url_data, input_position));
12671
        // Let queryPercentEncodeSet be the special-query percent-encode set if
12672
        // url is special; otherwise the query percent-encode set.
12673
263
        const uint8_t* query_percent_encode_set =
12674
263
            url.is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12675
263
                             : ada::character_sets::QUERY_PERCENT_ENCODE;
12676
12677
        // Percent-encode after encoding, with encoding, buffer, and
12678
        // queryPercentEncodeSet, and append the result to url's query.
12679
263
        url.update_base_search(helpers::substring(url_data, input_position),
12680
263
                               query_percent_encode_set);
12681
263
        ada_log("QUERY update_base_search completed ");
12682
263
        if (fragment.has_value()) {
12683
30
          url.update_unencoded_base_hash(*fragment);
12684
30
        }
12685
263
        return url;
12686
5.47k
      }
12687
5.71k
      case ada::state::HOST: {
12688
5.71k
        ada_log("HOST ", helpers::substring(url_data, input_position));
12689
12690
5.71k
        std::string_view host_view =
12691
5.71k
            helpers::substring(url_data, input_position);
12692
5.71k
        auto [location, found_colon] =
12693
5.71k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
12694
5.71k
        input_position = (location != std::string_view::npos)
12695
5.71k
                             ? input_position + location
12696
5.71k
                             : input_size;
12697
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12698
        // Note: the 'found_colon' value is true if and only if a colon was
12699
        // encountered while not inside brackets.
12700
5.71k
        if (found_colon) {
12701
          // If buffer is the empty string, validation error, return failure.
12702
          // Let host be the result of host parsing buffer with url is not
12703
          // special.
12704
807
          ada_log("HOST parsing ", host_view);
12705
807
          if (!url.parse_host(host_view)) {
12706
154
            return url;
12707
154
          }
12708
653
          ada_log("HOST parsing results in ", url.get_hostname());
12709
          // Set url's host to host, buffer to the empty string, and state to
12710
          // port state.
12711
653
          state = ada::state::PORT;
12712
653
          input_position++;
12713
653
        }
12714
        // Otherwise, if one of the following is true:
12715
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12716
        // - url is special and c is U+005C (\)
12717
        // The get_host_delimiter_location function either brings us to
12718
        // the colon outside of the bracket, or to one of those characters.
12719
4.90k
        else {
12720
          // If url is special and host_view is the empty string, validation
12721
          // error, return failure.
12722
4.90k
          if (url.is_special() && host_view.empty()) {
12723
38
            url.is_valid = false;
12724
38
            return url;
12725
38
          }
12726
4.87k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
12727
          // Let host be the result of host parsing host_view with url is not
12728
          // special.
12729
4.87k
          if (host_view.empty()) {
12730
16
            url.update_base_hostname("");
12731
4.85k
          } else if (!url.parse_host(host_view)) {
12732
1.23k
            return url;
12733
1.23k
          }
12734
3.63k
          ada_log("HOST parsing results in ", url.get_hostname(),
12735
3.63k
                  " href=", url.get_href());
12736
12737
          // Set url's host to host, and state to path start state.
12738
3.63k
          state = ada::state::PATH_START;
12739
3.63k
        }
12740
12741
4.29k
        break;
12742
5.71k
      }
12743
4.29k
      case ada::state::OPAQUE_PATH: {
12744
1.03k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
12745
1.03k
        std::string_view view = helpers::substring(url_data, input_position);
12746
        // If c is U+003F (?), then set url's query to the empty string and
12747
        // state to query state.
12748
1.03k
        size_t location = view.find('?');
12749
1.03k
        if (location != std::string_view::npos) {
12750
68
          view.remove_suffix(view.size() - location);
12751
68
          state = ada::state::QUERY;
12752
68
          input_position += location + 1;
12753
968
        } else {
12754
968
          input_position = input_size + 1;
12755
968
        }
12756
1.03k
        url.has_opaque_path = true;
12757
        // This is a really unlikely scenario in real world. We should not seek
12758
        // to optimize it.
12759
1.03k
        url.update_base_pathname(unicode::percent_encode(
12760
1.03k
            view, character_sets::C0_CONTROL_PERCENT_ENCODE));
12761
1.03k
        break;
12762
5.71k
      }
12763
653
      case ada::state::PORT: {
12764
653
        ada_log("PORT ", helpers::substring(url_data, input_position));
12765
653
        std::string_view port_view =
12766
653
            helpers::substring(url_data, input_position);
12767
653
        size_t consumed_bytes = url.parse_port(port_view, true);
12768
653
        input_position += consumed_bytes;
12769
653
        if (!url.is_valid) {
12770
92
          return url;
12771
92
        }
12772
561
        state = state::PATH_START;
12773
561
        [[fallthrough]];
12774
561
      }
12775
4.56k
      case ada::state::PATH_START: {
12776
4.56k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
12777
12778
        // If url is special, then:
12779
4.56k
        if (url.is_special()) {
12780
          // Set state to path state.
12781
4.29k
          state = ada::state::PATH;
12782
12783
          // Optimization: Avoiding going into PATH state improves the
12784
          // performance of urls ending with /.
12785
4.29k
          if (input_position == input_size) {
12786
3.90k
            url.update_base_pathname("/");
12787
3.90k
            if (fragment.has_value()) {
12788
61
              url.update_unencoded_base_hash(*fragment);
12789
61
            }
12790
3.90k
            return url;
12791
3.90k
          }
12792
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
12793
          // by 1. We know that (input_position == input_size) is impossible
12794
          // here, because of the previous if-check.
12795
391
          if ((url_data[input_position] != '/') &&
12796
391
              (url_data[input_position] != '\\')) {
12797
86
            break;
12798
86
          }
12799
391
        }
12800
        // Otherwise, if state override is not given and c is U+003F (?),
12801
        // set url's query to the empty string and state to query state.
12802
274
        else if ((input_position != input_size) &&
12803
274
                 (url_data[input_position] == '?')) {
12804
35
          state = ada::state::QUERY;
12805
35
        }
12806
        // Otherwise, if c is not the EOF code point:
12807
239
        else if (input_position != input_size) {
12808
          // Set state to path state.
12809
18
          state = ada::state::PATH;
12810
12811
          // If c is not U+002F (/), then decrease pointer by 1.
12812
18
          if (url_data[input_position] != '/') {
12813
0
            break;
12814
0
          }
12815
18
        }
12816
12817
579
        input_position++;
12818
579
        break;
12819
4.56k
      }
12820
2.92k
      case ada::state::PATH: {
12821
2.92k
        std::string_view view = helpers::substring(url_data, input_position);
12822
2.92k
        ada_log("PATH ", helpers::substring(url_data, input_position));
12823
12824
        // Most time, we do not need percent encoding.
12825
        // Furthermore, we can immediately locate the '?'.
12826
2.92k
        size_t locofquestionmark = view.find('?');
12827
2.92k
        if (locofquestionmark != std::string_view::npos) {
12828
160
          state = ada::state::QUERY;
12829
160
          view.remove_suffix(view.size() - locofquestionmark);
12830
160
          input_position += locofquestionmark + 1;
12831
2.76k
        } else {
12832
2.76k
          input_position = input_size + 1;
12833
2.76k
        }
12834
2.92k
        if constexpr (result_type_is_ada_url) {
12835
2.92k
          helpers::parse_prepared_path(view, url.type, url.path);
12836
2.92k
        } else {
12837
2.92k
          url.consume_prepared_path(view);
12838
2.92k
          ADA_ASSERT_TRUE(url.validate());
12839
2.92k
        }
12840
2.92k
        break;
12841
4.56k
      }
12842
573
      case ada::state::FILE_SLASH: {
12843
573
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
12844
12845
        // If c is U+002F (/) or U+005C (\), then:
12846
573
        if ((input_position != input_size) &&
12847
573
            (url_data[input_position] == '/' ||
12848
525
             url_data[input_position] == '\\')) {
12849
507
          ada_log("FILE_SLASH c is U+002F or U+005C");
12850
          // Set state to file host state.
12851
507
          state = ada::state::FILE_HOST;
12852
507
          input_position++;
12853
507
        } else {
12854
66
          ada_log("FILE_SLASH otherwise");
12855
          // If base is non-null and base's scheme is "file", then:
12856
          // Note: it is unsafe to do base_url->scheme unless you know that
12857
          // base_url_has_value() is true.
12858
66
          if (base_url != nullptr &&
12859
66
              base_url->type == ada::scheme::type::FILE) {
12860
            // Set url's host to base's host.
12861
0
            if constexpr (result_type_is_ada_url) {
12862
0
              url.host = base_url->host;
12863
0
            } else {
12864
              // TODO: Optimization opportunity.
12865
0
              url.set_host(base_url->get_host());
12866
0
            }
12867
            // If the code point substring from pointer to the end of input does
12868
            // not start with a Windows drive letter and base's path[0] is a
12869
            // normalized Windows drive letter, then append base's path[0] to
12870
            // url's path.
12871
0
            if (!base_url->get_pathname().empty()) {
12872
0
              if (!checkers::is_windows_drive_letter(
12873
0
                      helpers::substring(url_data, input_position))) {
12874
0
                std::string_view first_base_url_path =
12875
0
                    base_url->get_pathname().substr(1);
12876
0
                size_t loc = first_base_url_path.find('/');
12877
0
                if (loc != std::string_view::npos) {
12878
0
                  helpers::resize(first_base_url_path, loc);
12879
0
                }
12880
0
                if (checkers::is_normalized_windows_drive_letter(
12881
0
                        first_base_url_path)) {
12882
0
                  if constexpr (result_type_is_ada_url) {
12883
0
                    url.path += '/';
12884
0
                    url.path += first_base_url_path;
12885
0
                  } else {
12886
0
                    url.append_base_pathname(
12887
0
                        helpers::concat("/", first_base_url_path));
12888
0
                  }
12889
0
                }
12890
0
              }
12891
0
            }
12892
0
          }
12893
12894
          // Set state to path state, and decrease pointer by 1.
12895
66
          state = ada::state::PATH;
12896
66
        }
12897
12898
573
        break;
12899
4.56k
      }
12900
507
      case ada::state::FILE_HOST: {
12901
507
        std::string_view view = helpers::substring(url_data, input_position);
12902
507
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
12903
12904
507
        size_t location = view.find_first_of("/\\?");
12905
507
        std::string_view file_host_buffer(
12906
507
            view.data(),
12907
507
            (location != std::string_view::npos) ? location : view.size());
12908
12909
507
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
12910
6
          state = ada::state::PATH;
12911
501
        } else if (file_host_buffer.empty()) {
12912
          // Set url's host to the empty string.
12913
13
          if constexpr (result_type_is_ada_url) {
12914
13
            url.host = "";
12915
13
          } else {
12916
13
            url.update_base_hostname("");
12917
13
          }
12918
          // Set state to path start state.
12919
13
          state = ada::state::PATH_START;
12920
488
        } else {
12921
488
          size_t consumed_bytes = file_host_buffer.size();
12922
488
          input_position += consumed_bytes;
12923
          // Let host be the result of host parsing buffer with url is not
12924
          // special.
12925
488
          if (!url.parse_host(file_host_buffer)) {
12926
132
            return url;
12927
132
          }
12928
12929
356
          if constexpr (result_type_is_ada_url) {
12930
            // If host is "localhost", then set host to the empty string.
12931
356
            if (url.host.has_value() && url.host.value() == "localhost") {
12932
3
              url.host = "";
12933
3
            }
12934
356
          } else {
12935
356
            if (url.get_hostname() == "localhost") {
12936
356
              url.update_base_hostname("");
12937
356
            }
12938
356
          }
12939
12940
          // Set buffer to the empty string and state to path start state.
12941
356
          state = ada::state::PATH_START;
12942
356
        }
12943
12944
375
        break;
12945
507
      }
12946
1.51k
      case ada::state::FILE: {
12947
1.51k
        ada_log("FILE ", helpers::substring(url_data, input_position));
12948
1.51k
        std::string_view file_view =
12949
1.51k
            helpers::substring(url_data, input_position);
12950
12951
1.51k
        url.set_protocol_as_file();
12952
1.51k
        if constexpr (result_type_is_ada_url) {
12953
          // Set url's host to the empty string.
12954
1.51k
          url.host = "";
12955
1.51k
        } else {
12956
1.51k
          url.update_base_hostname("");
12957
1.51k
        }
12958
        // If c is U+002F (/) or U+005C (\), then:
12959
1.51k
        if (input_position != input_size &&
12960
1.51k
            (url_data[input_position] == '/' ||
12961
895
             url_data[input_position] == '\\')) {
12962
573
          ada_log("FILE c is U+002F or U+005C");
12963
          // Set state to file slash state.
12964
573
          state = ada::state::FILE_SLASH;
12965
573
        }
12966
        // Otherwise, if base is non-null and base's scheme is "file":
12967
940
        else if (base_url != nullptr &&
12968
940
                 base_url->type == ada::scheme::type::FILE) {
12969
          // Set url's host to base's host, url's path to a clone of base's
12970
          // path, and url's query to base's query.
12971
0
          ada_log("FILE base non-null");
12972
0
          if constexpr (result_type_is_ada_url) {
12973
0
            url.host = base_url->host;
12974
0
            url.path = base_url->path;
12975
0
            url.query = base_url->query;
12976
0
          } else {
12977
            // TODO: Get rid of set_hostname and replace it with
12978
            // update_base_hostname
12979
0
            url.set_hostname(base_url->get_hostname());
12980
0
            url.update_base_pathname(base_url->get_pathname());
12981
0
            url.update_base_search(base_url->get_search());
12982
0
          }
12983
0
          url.has_opaque_path = base_url->has_opaque_path;
12984
12985
          // If c is U+003F (?), then set url's query to the empty string and
12986
          // state to query state.
12987
0
          if (input_position != input_size && url_data[input_position] == '?') {
12988
0
            state = ada::state::QUERY;
12989
0
          }
12990
          // Otherwise, if c is not the EOF code point:
12991
0
          else if (input_position != input_size) {
12992
            // Set url's query to null.
12993
0
            url.clear_search();
12994
            // If the code point substring from pointer to the end of input does
12995
            // not start with a Windows drive letter, then shorten url's path.
12996
0
            if (!checkers::is_windows_drive_letter(file_view)) {
12997
0
              if constexpr (result_type_is_ada_url) {
12998
0
                helpers::shorten_path(url.path, url.type);
12999
0
              } else {
13000
0
                std::string_view path = url.get_pathname();
13001
0
                if (helpers::shorten_path(path, url.type)) {
13002
0
                  url.update_base_pathname(std::string(path));
13003
0
                }
13004
0
              }
13005
0
            }
13006
            // Otherwise:
13007
0
            else {
13008
              // Set url's path to an empty list.
13009
0
              url.clear_pathname();
13010
0
              url.has_opaque_path = true;
13011
0
            }
13012
13013
            // Set state to path state and decrease pointer by 1.
13014
0
            state = ada::state::PATH;
13015
0
            break;
13016
0
          }
13017
0
        }
13018
        // Otherwise, set state to path state, and decrease pointer by 1.
13019
940
        else {
13020
940
          ada_log("FILE go to path");
13021
940
          state = ada::state::PATH;
13022
940
          break;
13023
940
        }
13024
13025
573
        input_position++;
13026
573
        break;
13027
1.51k
      }
13028
0
      default:
13029
0
        ada::unreachable();
13030
60.3k
    }
13031
60.3k
  }
13032
3.95k
  if (fragment.has_value()) {
13033
167
    url.update_unencoded_base_hash(*fragment);
13034
167
  }
13035
3.95k
  return url;
13036
14.3k
}
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*)
Line
Count
Source
12144
45.0k
                      const result_type* base_url) {
12145
  // We can specialize the implementation per type.
12146
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
12147
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
12148
  // something else } is free (at runtime). This means that ada::url_aggregator
12149
  // and ada::url **do not have to support the exact same API**.
12150
45.0k
  constexpr bool result_type_is_ada_url =
12151
45.0k
      std::is_same<ada::url, result_type>::value;
12152
45.0k
  constexpr bool result_type_is_ada_url_aggregator =
12153
45.0k
      std::is_same<ada::url_aggregator, result_type>::value;
12154
45.0k
  static_assert(result_type_is_ada_url ||
12155
45.0k
                result_type_is_ada_url_aggregator);  // We don't support
12156
                                                     // anything else for now.
12157
12158
45.0k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
12159
45.0k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
12160
45.0k
          ")");
12161
12162
45.0k
  ada::state state = ada::state::SCHEME_START;
12163
45.0k
  result_type url{};
12164
12165
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
12166
  // surely the result of a bug or are otherwise a security concern.
12167
45.0k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) {
12168
2
    url.is_valid = false;
12169
2
  }
12170
  // Going forward, user_input.size() is in [0,
12171
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
12172
  // base, or the optional_url was invalid, we must return.
12173
45.0k
  if (base_url != nullptr) {
12174
2.64k
    url.is_valid &= base_url->is_valid;
12175
2.64k
  }
12176
45.0k
  if (!url.is_valid) {
12177
2
    return url;
12178
2
  }
12179
44.9k
  if constexpr (result_type_is_ada_url_aggregator) {
12180
    // Most of the time, we just need user_input.size().
12181
    // In some instances, we may need a bit more.
12182
    ///////////////////////////
12183
    // This is *very* important. This line should *not* be removed
12184
    // hastily. There are principled reasons why reserve is important
12185
    // for performance. If you have a benchmark with small inputs,
12186
    // it may not matter, but in other instances, it could.
12187
    ////
12188
    // This rounds up to the next power of two.
12189
    // We know that user_input.size() is in [0,
12190
    // std::numeric_limits<uint32_t>::max).
12191
44.9k
    uint32_t reserve_capacity =
12192
44.9k
        (0xFFFFFFFF >>
12193
44.9k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
12194
44.9k
        1;
12195
44.9k
    url.reserve(reserve_capacity);
12196
    //
12197
    //
12198
    //
12199
44.9k
  }
12200
44.9k
  std::string tmp_buffer;
12201
44.9k
  std::string_view internal_input;
12202
44.9k
  if (unicode::has_tabs_or_newline(user_input)) {
12203
472
    tmp_buffer = user_input;
12204
    // Optimization opportunity: Instead of copying and then pruning, we could
12205
    // just directly build the string from user_input.
12206
472
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12207
472
    internal_input = tmp_buffer;
12208
44.5k
  } else {
12209
44.5k
    internal_input = user_input;
12210
44.5k
  }
12211
12212
  // Leading and trailing control characters are uncommon and easy to deal with
12213
  // (no performance concern).
12214
44.9k
  std::string_view url_data = internal_input;
12215
44.9k
  helpers::trim_c0_whitespace(url_data);
12216
12217
  // Optimization opportunity. Most websites do not have fragment.
12218
44.9k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
12219
  // We add it last so that an implementation like ada::url_aggregator
12220
  // can append it last to its internal buffer, thus improving performance.
12221
12222
  // Here url_data no longer has its fragment.
12223
  // We are going to access the data from url_data (it is immutable).
12224
  // At any given time, we are pointing at byte 'input_position' in url_data.
12225
  // The input_position variable should range from 0 to input_size.
12226
  // It is illegal to access url_data at input_size.
12227
44.9k
  size_t input_position = 0;
12228
44.9k
  const size_t input_size = url_data.size();
12229
  // Keep running the following state machine by switching on state.
12230
  // If after a run pointer points to the EOF code point, go to the next step.
12231
  // Otherwise, increase pointer by 1 and continue with the state machine.
12232
  // We never decrement input_position.
12233
176k
  while (input_position <= input_size) {
12234
165k
    ada_log("In parsing at ", input_position, " out of ", input_size,
12235
165k
            " in state ", ada::to_string(state));
12236
165k
    switch (state) {
12237
44.9k
      case ada::state::SCHEME_START: {
12238
44.9k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
12239
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
12240
        // state to scheme state.
12241
44.9k
        if ((input_position != input_size) &&
12242
44.9k
            checkers::is_alpha(url_data[input_position])) {
12243
25.9k
          state = ada::state::SCHEME;
12244
25.9k
          input_position++;
12245
25.9k
        } else {
12246
          // Otherwise, if state override is not given, set state to no scheme
12247
          // state and decrease pointer by 1.
12248
19.0k
          state = ada::state::NO_SCHEME;
12249
19.0k
        }
12250
44.9k
        break;
12251
0
      }
12252
25.9k
      case ada::state::SCHEME: {
12253
25.9k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
12254
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
12255
        // append c, lowercased, to buffer.
12256
82.5k
        while ((input_position != input_size) &&
12257
82.5k
               (ada::unicode::is_alnum_plus(url_data[input_position]))) {
12258
56.6k
          input_position++;
12259
56.6k
        }
12260
        // Otherwise, if c is U+003A (:), then:
12261
25.9k
        if ((input_position != input_size) &&
12262
25.9k
            (url_data[input_position] == ':')) {
12263
23.7k
          ada_log("SCHEME the scheme should be ",
12264
23.7k
                  url_data.substr(0, input_position));
12265
23.7k
          if constexpr (result_type_is_ada_url) {
12266
23.7k
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
12267
23.7k
              return url;
12268
23.7k
            }
12269
23.7k
          } else {
12270
            // we pass the colon along instead of painfully adding it back.
12271
23.7k
            if (!url.parse_scheme_with_colon(
12272
23.7k
                    url_data.substr(0, input_position + 1))) {
12273
0
              return url;
12274
0
            }
12275
23.7k
          }
12276
23.7k
          ada_log("SCHEME the scheme is ", url.get_protocol());
12277
12278
          // If url's scheme is "file", then:
12279
23.7k
          if (url.type == ada::scheme::type::FILE) {
12280
            // Set state to file state.
12281
3.91k
            state = ada::state::FILE;
12282
3.91k
          }
12283
          // Otherwise, if url is special, base is non-null, and base's scheme
12284
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
12285
          // != nullptr is false.
12286
19.8k
          else if (url.is_special() && base_url != nullptr &&
12287
19.8k
                   base_url->type == url.type) {
12288
            // Set state to special relative or authority state.
12289
93
            state = ada::state::SPECIAL_RELATIVE_OR_AUTHORITY;
12290
93
          }
12291
          // Otherwise, if url is special, set state to special authority
12292
          // slashes state.
12293
19.7k
          else if (url.is_special()) {
12294
12.3k
            state = ada::state::SPECIAL_AUTHORITY_SLASHES;
12295
12.3k
          }
12296
          // Otherwise, if remaining starts with an U+002F (/), set state to
12297
          // path or authority state and increase pointer by 1.
12298
7.38k
          else if (input_position + 1 < input_size &&
12299
7.38k
                   url_data[input_position + 1] == '/') {
12300
4.12k
            state = ada::state::PATH_OR_AUTHORITY;
12301
4.12k
            input_position++;
12302
4.12k
          }
12303
          // Otherwise, set url's path to the empty string and set state to
12304
          // opaque path state.
12305
3.26k
          else {
12306
3.26k
            state = ada::state::OPAQUE_PATH;
12307
3.26k
          }
12308
23.7k
        }
12309
        // Otherwise, if state override is not given, set buffer to the empty
12310
        // string, state to no scheme state, and start over (from the first code
12311
        // point in input).
12312
2.18k
        else {
12313
2.18k
          state = ada::state::NO_SCHEME;
12314
2.18k
          input_position = 0;
12315
2.18k
          break;
12316
2.18k
        }
12317
23.7k
        input_position++;
12318
23.7k
        break;
12319
25.9k
      }
12320
21.2k
      case ada::state::NO_SCHEME: {
12321
21.2k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
12322
        // If base is null, or base has an opaque path and c is not U+0023 (#),
12323
        // validation error, return failure.
12324
21.2k
        if (base_url == nullptr ||
12325
21.2k
            (base_url->has_opaque_path && !fragment.has_value())) {
12326
20.0k
          ada_log("NO_SCHEME validation error");
12327
20.0k
          url.is_valid = false;
12328
20.0k
          return url;
12329
20.0k
        }
12330
        // Otherwise, if base has an opaque path and c is U+0023 (#),
12331
        // set url's scheme to base's scheme, url's path to base's path, url's
12332
        // query to base's query, and set state to fragment state.
12333
1.17k
        else if (base_url->has_opaque_path && fragment.has_value() &&
12334
1.17k
                 input_position == input_size) {
12335
29
          ada_log("NO_SCHEME opaque base with fragment");
12336
29
          url.copy_scheme(*base_url);
12337
29
          url.has_opaque_path = base_url->has_opaque_path;
12338
12339
29
          if constexpr (result_type_is_ada_url) {
12340
29
            url.path = base_url->path;
12341
29
            url.query = base_url->query;
12342
29
          } else {
12343
29
            url.update_base_pathname(base_url->get_pathname());
12344
29
            url.update_base_search(base_url->get_search());
12345
29
          }
12346
29
          url.update_unencoded_base_hash(*fragment);
12347
29
          return url;
12348
29
        }
12349
        // Otherwise, if base's scheme is not "file", set state to relative
12350
        // state and decrease pointer by 1.
12351
1.14k
        else if (base_url->type != ada::scheme::type::FILE) {
12352
663
          ada_log("NO_SCHEME non-file relative path");
12353
663
          state = ada::state::RELATIVE_SCHEME;
12354
663
        }
12355
        // Otherwise, set state to file state and decrease pointer by 1.
12356
485
        else {
12357
485
          ada_log("NO_SCHEME file base type");
12358
485
          state = ada::state::FILE;
12359
485
        }
12360
1.14k
        break;
12361
21.2k
      }
12362
13.3k
      case ada::state::AUTHORITY: {
12363
13.3k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
12364
        // most URLs have no @. Having no @ tells us that we don't have to worry
12365
        // about AUTHORITY. Of course, we could have @ and still not have to
12366
        // worry about AUTHORITY.
12367
        // TODO: Instead of just collecting a bool, collect the location of the
12368
        // '@' and do something useful with it.
12369
        // TODO: We could do various processing early on, using a single pass
12370
        // over the string to collect information about it, e.g., telling us
12371
        // whether there is a @ and if so, where (or how many).
12372
13.3k
        const bool contains_ampersand =
12373
13.3k
            (url_data.find('@', input_position) != std::string_view::npos);
12374
12375
13.3k
        if (!contains_ampersand) {
12376
12.4k
          state = ada::state::HOST;
12377
12.4k
          break;
12378
12.4k
        }
12379
886
        bool at_sign_seen{false};
12380
886
        bool password_token_seen{false};
12381
        /**
12382
         * We expect something of the sort...
12383
         * https://user:pass@example.com:1234/foo/bar?baz#quux
12384
         * --------^
12385
         */
12386
7.23k
        do {
12387
7.23k
          std::string_view view = helpers::substring(url_data, input_position);
12388
          // The delimiters are @, /, ? \\.
12389
7.23k
          size_t location =
12390
7.23k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
12391
7.23k
                               : helpers::find_authority_delimiter(view);
12392
7.23k
          std::string_view authority_view(view.data(), location);
12393
7.23k
          size_t end_of_authority = input_position + authority_view.size();
12394
          // If c is U+0040 (@), then:
12395
7.23k
          if ((end_of_authority != input_size) &&
12396
7.23k
              (url_data[end_of_authority] == '@')) {
12397
            // If atSignSeen is true, then prepend "%40" to buffer.
12398
6.34k
            if (at_sign_seen) {
12399
5.49k
              if (password_token_seen) {
12400
1.63k
                if constexpr (result_type_is_ada_url) {
12401
1.63k
                  url.password += "%40";
12402
1.63k
                } else {
12403
1.63k
                  url.append_base_password("%40");
12404
1.63k
                }
12405
3.85k
              } else {
12406
3.85k
                if constexpr (result_type_is_ada_url) {
12407
3.85k
                  url.username += "%40";
12408
3.85k
                } else {
12409
3.85k
                  url.append_base_username("%40");
12410
3.85k
                }
12411
3.85k
              }
12412
5.49k
            }
12413
12414
6.34k
            at_sign_seen = true;
12415
12416
6.34k
            if (!password_token_seen) {
12417
4.70k
              size_t password_token_location = authority_view.find(':');
12418
4.70k
              password_token_seen =
12419
4.70k
                  password_token_location != std::string_view::npos;
12420
12421
4.70k
              if (!password_token_seen) {
12422
4.37k
                if constexpr (result_type_is_ada_url) {
12423
4.37k
                  url.username += unicode::percent_encode(
12424
4.37k
                      authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12425
4.37k
                } else {
12426
4.37k
                  url.append_base_username(unicode::percent_encode(
12427
4.37k
                      authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12428
4.37k
                }
12429
4.37k
              } else {
12430
336
                if constexpr (result_type_is_ada_url) {
12431
336
                  url.username += unicode::percent_encode(
12432
336
                      authority_view.substr(0, password_token_location),
12433
336
                      character_sets::USERINFO_PERCENT_ENCODE);
12434
336
                  url.password += unicode::percent_encode(
12435
336
                      authority_view.substr(password_token_location + 1),
12436
336
                      character_sets::USERINFO_PERCENT_ENCODE);
12437
336
                } else {
12438
336
                  url.append_base_username(unicode::percent_encode(
12439
336
                      authority_view.substr(0, password_token_location),
12440
336
                      character_sets::USERINFO_PERCENT_ENCODE));
12441
336
                  url.append_base_password(unicode::percent_encode(
12442
336
                      authority_view.substr(password_token_location + 1),
12443
336
                      character_sets::USERINFO_PERCENT_ENCODE));
12444
336
                }
12445
336
              }
12446
4.70k
            } else {
12447
1.63k
              if constexpr (result_type_is_ada_url) {
12448
1.63k
                url.password += unicode::percent_encode(
12449
1.63k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12450
1.63k
              } else {
12451
1.63k
                url.append_base_password(unicode::percent_encode(
12452
1.63k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12453
1.63k
              }
12454
1.63k
            }
12455
6.34k
          }
12456
          // Otherwise, if one of the following is true:
12457
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12458
          // - url is special and c is U+005C (\)
12459
886
          else if (end_of_authority == input_size ||
12460
886
                   url_data[end_of_authority] == '/' ||
12461
886
                   url_data[end_of_authority] == '?' ||
12462
886
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
12463
            // If atSignSeen is true and authority_view is the empty string,
12464
            // validation error, return failure.
12465
886
            if (at_sign_seen && authority_view.empty()) {
12466
471
              url.is_valid = false;
12467
471
              return url;
12468
471
            }
12469
415
            state = ada::state::HOST;
12470
415
            break;
12471
886
          }
12472
6.34k
          if (end_of_authority == input_size) {
12473
0
            if (fragment.has_value()) {
12474
0
              url.update_unencoded_base_hash(*fragment);
12475
0
            }
12476
0
            return url;
12477
0
          }
12478
6.34k
          input_position = end_of_authority + 1;
12479
6.34k
        } while (true);
12480
12481
415
        break;
12482
886
      }
12483
415
      case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY: {
12484
93
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
12485
93
                helpers::substring(url_data, input_position));
12486
12487
        // If c is U+002F (/) and remaining starts with U+002F (/),
12488
        // then set state to special authority ignore slashes state and increase
12489
        // pointer by 1.
12490
93
        std::string_view view = helpers::substring(url_data, input_position);
12491
93
        if (ada::checkers::begins_with(view, "//")) {
12492
2
          state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12493
2
          input_position += 2;
12494
91
        } else {
12495
          // Otherwise, validation error, set state to relative state and
12496
          // decrease pointer by 1.
12497
91
          state = ada::state::RELATIVE_SCHEME;
12498
91
        }
12499
12500
93
        break;
12501
886
      }
12502
4.12k
      case ada::state::PATH_OR_AUTHORITY: {
12503
4.12k
        ada_log("PATH_OR_AUTHORITY ",
12504
4.12k
                helpers::substring(url_data, input_position));
12505
12506
        // If c is U+002F (/), then set state to authority state.
12507
4.12k
        if ((input_position != input_size) &&
12508
4.12k
            (url_data[input_position] == '/')) {
12509
965
          state = ada::state::AUTHORITY;
12510
965
          input_position++;
12511
3.15k
        } else {
12512
          // Otherwise, set state to path state, and decrease pointer by 1.
12513
3.15k
          state = ada::state::PATH;
12514
3.15k
        }
12515
12516
4.12k
        break;
12517
886
      }
12518
754
      case ada::state::RELATIVE_SCHEME: {
12519
754
        ada_log("RELATIVE_SCHEME ",
12520
754
                helpers::substring(url_data, input_position));
12521
12522
        // Set url's scheme to base's scheme.
12523
754
        url.copy_scheme(*base_url);
12524
12525
        // If c is U+002F (/), then set state to relative slash state.
12526
754
        if ((input_position != input_size) &&
12527
754
            (url_data[input_position] == '/')) {
12528
39
          ada_log(
12529
39
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
12530
39
              "slash state");
12531
39
          state = ada::state::RELATIVE_SLASH;
12532
715
        } else if (url.is_special() && (input_position != input_size) &&
12533
715
                   (url_data[input_position] == '\\')) {
12534
          // Otherwise, if url is special and c is U+005C (\), validation error,
12535
          // set state to relative slash state.
12536
1
          ada_log(
12537
1
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
12538
1
              "error, set state to relative slash state");
12539
1
          state = ada::state::RELATIVE_SLASH;
12540
714
        } else {
12541
714
          ada_log("RELATIVE_SCHEME otherwise");
12542
          // Set url's username to base's username, url's password to base's
12543
          // password, url's host to base's host, url's port to base's port,
12544
          // url's path to a clone of base's path, and url's query to base's
12545
          // query.
12546
714
          if constexpr (result_type_is_ada_url) {
12547
714
            url.username = base_url->username;
12548
714
            url.password = base_url->password;
12549
714
            url.host = base_url->host;
12550
714
            url.port = base_url->port;
12551
            // cloning the base path includes cloning the has_opaque_path flag
12552
714
            url.has_opaque_path = base_url->has_opaque_path;
12553
714
            url.path = base_url->path;
12554
714
            url.query = base_url->query;
12555
714
          } else {
12556
714
            url.update_base_authority(base_url->get_href(),
12557
714
                                      base_url->get_components());
12558
            // TODO: Get rid of set_hostname and replace it with
12559
            // update_base_hostname
12560
714
            url.set_hostname(base_url->get_hostname());
12561
714
            url.update_base_port(base_url->retrieve_base_port());
12562
            // cloning the base path includes cloning the has_opaque_path flag
12563
714
            url.has_opaque_path = base_url->has_opaque_path;
12564
714
            url.update_base_pathname(base_url->get_pathname());
12565
714
            url.update_base_search(base_url->get_search());
12566
714
          }
12567
12568
714
          url.has_opaque_path = base_url->has_opaque_path;
12569
12570
          // If c is U+003F (?), then set url's query to the empty string, and
12571
          // state to query state.
12572
714
          if ((input_position != input_size) &&
12573
714
              (url_data[input_position] == '?')) {
12574
6
            state = ada::state::QUERY;
12575
6
          }
12576
          // Otherwise, if c is not the EOF code point:
12577
708
          else if (input_position != input_size) {
12578
            // Set url's query to null.
12579
199
            url.clear_search();
12580
199
            if constexpr (result_type_is_ada_url) {
12581
              // Shorten url's path.
12582
199
              helpers::shorten_path(url.path, url.type);
12583
199
            } else {
12584
199
              std::string_view path = url.get_pathname();
12585
199
              if (helpers::shorten_path(path, url.type)) {
12586
166
                url.update_base_pathname(std::string(path));
12587
166
              }
12588
199
            }
12589
            // Set state to path state and decrease pointer by 1.
12590
199
            state = ada::state::PATH;
12591
199
            break;
12592
199
          }
12593
714
        }
12594
555
        input_position++;
12595
555
        break;
12596
754
      }
12597
40
      case ada::state::RELATIVE_SLASH: {
12598
40
        ada_log("RELATIVE_SLASH ",
12599
40
                helpers::substring(url_data, input_position));
12600
12601
        // If url is special and c is U+002F (/) or U+005C (\), then:
12602
40
        if (url.is_special() && (input_position != input_size) &&
12603
40
            (url_data[input_position] == '/' ||
12604
11
             url_data[input_position] == '\\')) {
12605
          // Set state to special authority ignore slashes state.
12606
3
          state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12607
3
        }
12608
        // Otherwise, if c is U+002F (/), then set state to authority state.
12609
37
        else if ((input_position != input_size) &&
12610
37
                 (url_data[input_position] == '/')) {
12611
5
          state = ada::state::AUTHORITY;
12612
5
        }
12613
        // Otherwise, set
12614
        // - url's username to base's username,
12615
        // - url's password to base's password,
12616
        // - url's host to base's host,
12617
        // - url's port to base's port,
12618
        // - state to path state, and then, decrease pointer by 1.
12619
32
        else {
12620
32
          if constexpr (result_type_is_ada_url) {
12621
32
            url.username = base_url->username;
12622
32
            url.password = base_url->password;
12623
32
            url.host = base_url->host;
12624
32
            url.port = base_url->port;
12625
32
          } else {
12626
32
            url.update_base_authority(base_url->get_href(),
12627
32
                                      base_url->get_components());
12628
            // TODO: Get rid of set_hostname and replace it with
12629
            // update_base_hostname
12630
32
            url.set_hostname(base_url->get_hostname());
12631
32
            url.update_base_port(base_url->retrieve_base_port());
12632
32
          }
12633
32
          state = ada::state::PATH;
12634
32
          break;
12635
32
        }
12636
12637
8
        input_position++;
12638
8
        break;
12639
40
      }
12640
12.3k
      case ada::state::SPECIAL_AUTHORITY_SLASHES: {
12641
12.3k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
12642
12.3k
                helpers::substring(url_data, input_position));
12643
12644
        // If c is U+002F (/) and remaining starts with U+002F (/),
12645
        // then set state to special authority ignore slashes state and increase
12646
        // pointer by 1.
12647
12.3k
        std::string_view view = helpers::substring(url_data, input_position);
12648
12.3k
        if (ada::checkers::begins_with(view, "//")) {
12649
31
          input_position += 2;
12650
31
        }
12651
12652
12.3k
        [[fallthrough]];
12653
12.3k
      }
12654
12.3k
      case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
12655
12.3k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
12656
12.3k
                helpers::substring(url_data, input_position));
12657
12658
        // If c is neither U+002F (/) nor U+005C (\), then set state to
12659
        // authority state and decrease pointer by 1.
12660
13.6k
        while ((input_position != input_size) &&
12661
13.6k
               ((url_data[input_position] == '/') ||
12662
13.5k
                (url_data[input_position] == '\\'))) {
12663
1.25k
          input_position++;
12664
1.25k
        }
12665
12.3k
        state = ada::state::AUTHORITY;
12666
12667
12.3k
        break;
12668
12.3k
      }
12669
679
      case ada::state::QUERY: {
12670
679
        ada_log("QUERY ", helpers::substring(url_data, input_position));
12671
        // Let queryPercentEncodeSet be the special-query percent-encode set if
12672
        // url is special; otherwise the query percent-encode set.
12673
679
        const uint8_t* query_percent_encode_set =
12674
679
            url.is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12675
679
                             : ada::character_sets::QUERY_PERCENT_ENCODE;
12676
12677
        // Percent-encode after encoding, with encoding, buffer, and
12678
        // queryPercentEncodeSet, and append the result to url's query.
12679
679
        url.update_base_search(helpers::substring(url_data, input_position),
12680
679
                               query_percent_encode_set);
12681
679
        ada_log("QUERY update_base_search completed ");
12682
679
        if (fragment.has_value()) {
12683
93
          url.update_unencoded_base_hash(*fragment);
12684
93
        }
12685
679
        return url;
12686
12.3k
      }
12687
12.8k
      case ada::state::HOST: {
12688
12.8k
        ada_log("HOST ", helpers::substring(url_data, input_position));
12689
12690
12.8k
        std::string_view host_view =
12691
12.8k
            helpers::substring(url_data, input_position);
12692
12.8k
        auto [location, found_colon] =
12693
12.8k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
12694
12.8k
        input_position = (location != std::string_view::npos)
12695
12.8k
                             ? input_position + location
12696
12.8k
                             : input_size;
12697
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12698
        // Note: the 'found_colon' value is true if and only if a colon was
12699
        // encountered while not inside brackets.
12700
12.8k
        if (found_colon) {
12701
          // If buffer is the empty string, validation error, return failure.
12702
          // Let host be the result of host parsing buffer with url is not
12703
          // special.
12704
1.82k
          ada_log("HOST parsing ", host_view);
12705
1.82k
          if (!url.parse_host(host_view)) {
12706
329
            return url;
12707
329
          }
12708
1.49k
          ada_log("HOST parsing results in ", url.get_hostname());
12709
          // Set url's host to host, buffer to the empty string, and state to
12710
          // port state.
12711
1.49k
          state = ada::state::PORT;
12712
1.49k
          input_position++;
12713
1.49k
        }
12714
        // Otherwise, if one of the following is true:
12715
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12716
        // - url is special and c is U+005C (\)
12717
        // The get_host_delimiter_location function either brings us to
12718
        // the colon outside of the bracket, or to one of those characters.
12719
11.0k
        else {
12720
          // If url is special and host_view is the empty string, validation
12721
          // error, return failure.
12722
11.0k
          if (url.is_special() && host_view.empty()) {
12723
99
            url.is_valid = false;
12724
99
            return url;
12725
99
          }
12726
10.9k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
12727
          // Let host be the result of host parsing host_view with url is not
12728
          // special.
12729
10.9k
          if (host_view.empty()) {
12730
50
            url.update_base_hostname("");
12731
10.9k
          } else if (!url.parse_host(host_view)) {
12732
2.67k
            return url;
12733
2.67k
          }
12734
8.30k
          ada_log("HOST parsing results in ", url.get_hostname(),
12735
8.30k
                  " href=", url.get_href());
12736
12737
          // Set url's host to host, and state to path start state.
12738
8.30k
          state = ada::state::PATH_START;
12739
8.30k
        }
12740
12741
9.79k
        break;
12742
12.8k
      }
12743
9.79k
      case ada::state::OPAQUE_PATH: {
12744
3.26k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
12745
3.26k
        std::string_view view = helpers::substring(url_data, input_position);
12746
        // If c is U+003F (?), then set url's query to the empty string and
12747
        // state to query state.
12748
3.26k
        size_t location = view.find('?');
12749
3.26k
        if (location != std::string_view::npos) {
12750
180
          view.remove_suffix(view.size() - location);
12751
180
          state = ada::state::QUERY;
12752
180
          input_position += location + 1;
12753
3.08k
        } else {
12754
3.08k
          input_position = input_size + 1;
12755
3.08k
        }
12756
3.26k
        url.has_opaque_path = true;
12757
        // This is a really unlikely scenario in real world. We should not seek
12758
        // to optimize it.
12759
3.26k
        url.update_base_pathname(unicode::percent_encode(
12760
3.26k
            view, character_sets::C0_CONTROL_PERCENT_ENCODE));
12761
3.26k
        break;
12762
12.8k
      }
12763
1.49k
      case ada::state::PORT: {
12764
1.49k
        ada_log("PORT ", helpers::substring(url_data, input_position));
12765
1.49k
        std::string_view port_view =
12766
1.49k
            helpers::substring(url_data, input_position);
12767
1.49k
        size_t consumed_bytes = url.parse_port(port_view, true);
12768
1.49k
        input_position += consumed_bytes;
12769
1.49k
        if (!url.is_valid) {
12770
175
          return url;
12771
175
        }
12772
1.32k
        state = state::PATH_START;
12773
1.32k
        [[fallthrough]];
12774
1.32k
      }
12775
10.8k
      case ada::state::PATH_START: {
12776
10.8k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
12777
12778
        // If url is special, then:
12779
10.8k
        if (url.is_special()) {
12780
          // Set state to path state.
12781
10.2k
          state = ada::state::PATH;
12782
12783
          // Optimization: Avoiding going into PATH state improves the
12784
          // performance of urls ending with /.
12785
10.2k
          if (input_position == input_size) {
12786
9.33k
            url.update_base_pathname("/");
12787
9.33k
            if (fragment.has_value()) {
12788
137
              url.update_unencoded_base_hash(*fragment);
12789
137
            }
12790
9.33k
            return url;
12791
9.33k
          }
12792
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
12793
          // by 1. We know that (input_position == input_size) is impossible
12794
          // here, because of the previous if-check.
12795
942
          if ((url_data[input_position] != '/') &&
12796
942
              (url_data[input_position] != '\\')) {
12797
210
            break;
12798
210
          }
12799
942
        }
12800
        // Otherwise, if state override is not given and c is U+003F (?),
12801
        // set url's query to the empty string and state to query state.
12802
624
        else if ((input_position != input_size) &&
12803
624
                 (url_data[input_position] == '?')) {
12804
75
          state = ada::state::QUERY;
12805
75
        }
12806
        // Otherwise, if c is not the EOF code point:
12807
549
        else if (input_position != input_size) {
12808
          // Set state to path state.
12809
43
          state = ada::state::PATH;
12810
12811
          // If c is not U+002F (/), then decrease pointer by 1.
12812
43
          if (url_data[input_position] != '/') {
12813
0
            break;
12814
0
          }
12815
43
        }
12816
12817
1.35k
        input_position++;
12818
1.35k
        break;
12819
10.8k
      }
12820
6.96k
      case ada::state::PATH: {
12821
6.96k
        std::string_view view = helpers::substring(url_data, input_position);
12822
6.96k
        ada_log("PATH ", helpers::substring(url_data, input_position));
12823
12824
        // Most time, we do not need percent encoding.
12825
        // Furthermore, we can immediately locate the '?'.
12826
6.96k
        size_t locofquestionmark = view.find('?');
12827
6.96k
        if (locofquestionmark != std::string_view::npos) {
12828
416
          state = ada::state::QUERY;
12829
416
          view.remove_suffix(view.size() - locofquestionmark);
12830
416
          input_position += locofquestionmark + 1;
12831
6.55k
        } else {
12832
6.55k
          input_position = input_size + 1;
12833
6.55k
        }
12834
6.96k
        if constexpr (result_type_is_ada_url) {
12835
6.96k
          helpers::parse_prepared_path(view, url.type, url.path);
12836
6.96k
        } else {
12837
6.96k
          url.consume_prepared_path(view);
12838
6.96k
          ADA_ASSERT_TRUE(url.validate());
12839
6.96k
        }
12840
6.96k
        break;
12841
10.8k
      }
12842
1.93k
      case ada::state::FILE_SLASH: {
12843
1.93k
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
12844
12845
        // If c is U+002F (/) or U+005C (\), then:
12846
1.93k
        if ((input_position != input_size) &&
12847
1.93k
            (url_data[input_position] == '/' ||
12848
1.63k
             url_data[input_position] == '\\')) {
12849
1.56k
          ada_log("FILE_SLASH c is U+002F or U+005C");
12850
          // Set state to file host state.
12851
1.56k
          state = ada::state::FILE_HOST;
12852
1.56k
          input_position++;
12853
1.56k
        } else {
12854
369
          ada_log("FILE_SLASH otherwise");
12855
          // If base is non-null and base's scheme is "file", then:
12856
          // Note: it is unsafe to do base_url->scheme unless you know that
12857
          // base_url_has_value() is true.
12858
369
          if (base_url != nullptr &&
12859
369
              base_url->type == ada::scheme::type::FILE) {
12860
            // Set url's host to base's host.
12861
230
            if constexpr (result_type_is_ada_url) {
12862
230
              url.host = base_url->host;
12863
230
            } else {
12864
              // TODO: Optimization opportunity.
12865
230
              url.set_host(base_url->get_host());
12866
230
            }
12867
            // If the code point substring from pointer to the end of input does
12868
            // not start with a Windows drive letter and base's path[0] is a
12869
            // normalized Windows drive letter, then append base's path[0] to
12870
            // url's path.
12871
230
            if (!base_url->get_pathname().empty()) {
12872
230
              if (!checkers::is_windows_drive_letter(
12873
230
                      helpers::substring(url_data, input_position))) {
12874
224
                std::string_view first_base_url_path =
12875
224
                    base_url->get_pathname().substr(1);
12876
224
                size_t loc = first_base_url_path.find('/');
12877
224
                if (loc != std::string_view::npos) {
12878
13
                  helpers::resize(first_base_url_path, loc);
12879
13
                }
12880
224
                if (checkers::is_normalized_windows_drive_letter(
12881
224
                        first_base_url_path)) {
12882
3
                  if constexpr (result_type_is_ada_url) {
12883
3
                    url.path += '/';
12884
3
                    url.path += first_base_url_path;
12885
3
                  } else {
12886
3
                    url.append_base_pathname(
12887
3
                        helpers::concat("/", first_base_url_path));
12888
3
                  }
12889
3
                }
12890
224
              }
12891
230
            }
12892
230
          }
12893
12894
          // Set state to path state, and decrease pointer by 1.
12895
369
          state = ada::state::PATH;
12896
369
        }
12897
12898
1.93k
        break;
12899
10.8k
      }
12900
1.56k
      case ada::state::FILE_HOST: {
12901
1.56k
        std::string_view view = helpers::substring(url_data, input_position);
12902
1.56k
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
12903
12904
1.56k
        size_t location = view.find_first_of("/\\?");
12905
1.56k
        std::string_view file_host_buffer(
12906
1.56k
            view.data(),
12907
1.56k
            (location != std::string_view::npos) ? location : view.size());
12908
12909
1.56k
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
12910
20
          state = ada::state::PATH;
12911
1.54k
        } else if (file_host_buffer.empty()) {
12912
          // Set url's host to the empty string.
12913
42
          if constexpr (result_type_is_ada_url) {
12914
42
            url.host = "";
12915
42
          } else {
12916
42
            url.update_base_hostname("");
12917
42
          }
12918
          // Set state to path start state.
12919
42
          state = ada::state::PATH_START;
12920
1.50k
        } else {
12921
1.50k
          size_t consumed_bytes = file_host_buffer.size();
12922
1.50k
          input_position += consumed_bytes;
12923
          // Let host be the result of host parsing buffer with url is not
12924
          // special.
12925
1.50k
          if (!url.parse_host(file_host_buffer)) {
12926
269
            return url;
12927
269
          }
12928
12929
1.23k
          if constexpr (result_type_is_ada_url) {
12930
            // If host is "localhost", then set host to the empty string.
12931
1.23k
            if (url.host.has_value() && url.host.value() == "localhost") {
12932
1.23k
              url.host = "";
12933
1.23k
            }
12934
1.23k
          } else {
12935
1.23k
            if (url.get_hostname() == "localhost") {
12936
11
              url.update_base_hostname("");
12937
11
            }
12938
1.23k
          }
12939
12940
          // Set buffer to the empty string and state to path start state.
12941
1.23k
          state = ada::state::PATH_START;
12942
1.23k
        }
12943
12944
1.29k
        break;
12945
1.56k
      }
12946
4.40k
      case ada::state::FILE: {
12947
4.40k
        ada_log("FILE ", helpers::substring(url_data, input_position));
12948
4.40k
        std::string_view file_view =
12949
4.40k
            helpers::substring(url_data, input_position);
12950
12951
4.40k
        url.set_protocol_as_file();
12952
4.40k
        if constexpr (result_type_is_ada_url) {
12953
          // Set url's host to the empty string.
12954
4.40k
          url.host = "";
12955
4.40k
        } else {
12956
4.40k
          url.update_base_hostname("");
12957
4.40k
        }
12958
        // If c is U+002F (/) or U+005C (\), then:
12959
4.40k
        if (input_position != input_size &&
12960
4.40k
            (url_data[input_position] == '/' ||
12961
2.84k
             url_data[input_position] == '\\')) {
12962
1.93k
          ada_log("FILE c is U+002F or U+005C");
12963
          // Set state to file slash state.
12964
1.93k
          state = ada::state::FILE_SLASH;
12965
1.93k
        }
12966
        // Otherwise, if base is non-null and base's scheme is "file":
12967
2.46k
        else if (base_url != nullptr &&
12968
2.46k
                 base_url->type == ada::scheme::type::FILE) {
12969
          // Set url's host to base's host, url's path to a clone of base's
12970
          // path, and url's query to base's query.
12971
351
          ada_log("FILE base non-null");
12972
351
          if constexpr (result_type_is_ada_url) {
12973
351
            url.host = base_url->host;
12974
351
            url.path = base_url->path;
12975
351
            url.query = base_url->query;
12976
351
          } else {
12977
            // TODO: Get rid of set_hostname and replace it with
12978
            // update_base_hostname
12979
351
            url.set_hostname(base_url->get_hostname());
12980
351
            url.update_base_pathname(base_url->get_pathname());
12981
351
            url.update_base_search(base_url->get_search());
12982
351
          }
12983
351
          url.has_opaque_path = base_url->has_opaque_path;
12984
12985
          // If c is U+003F (?), then set url's query to the empty string and
12986
          // state to query state.
12987
351
          if (input_position != input_size && url_data[input_position] == '?') {
12988
2
            state = ada::state::QUERY;
12989
2
          }
12990
          // Otherwise, if c is not the EOF code point:
12991
349
          else if (input_position != input_size) {
12992
            // Set url's query to null.
12993
91
            url.clear_search();
12994
            // If the code point substring from pointer to the end of input does
12995
            // not start with a Windows drive letter, then shorten url's path.
12996
91
            if (!checkers::is_windows_drive_letter(file_view)) {
12997
80
              if constexpr (result_type_is_ada_url) {
12998
80
                helpers::shorten_path(url.path, url.type);
12999
80
              } else {
13000
80
                std::string_view path = url.get_pathname();
13001
80
                if (helpers::shorten_path(path, url.type)) {
13002
78
                  url.update_base_pathname(std::string(path));
13003
78
                }
13004
80
              }
13005
80
            }
13006
            // Otherwise:
13007
11
            else {
13008
              // Set url's path to an empty list.
13009
11
              url.clear_pathname();
13010
11
              url.has_opaque_path = true;
13011
11
            }
13012
13013
            // Set state to path state and decrease pointer by 1.
13014
91
            state = ada::state::PATH;
13015
91
            break;
13016
91
          }
13017
351
        }
13018
        // Otherwise, set state to path state, and decrease pointer by 1.
13019
2.11k
        else {
13020
2.11k
          ada_log("FILE go to path");
13021
2.11k
          state = ada::state::PATH;
13022
2.11k
          break;
13023
2.11k
        }
13024
13025
2.19k
        input_position++;
13026
2.19k
        break;
13027
4.40k
      }
13028
0
      default:
13029
0
        ada::unreachable();
13030
165k
    }
13031
165k
  }
13032
10.9k
  if (fragment.has_value()) {
13033
420
    url.update_unencoded_base_hash(*fragment);
13034
420
  }
13035
10.9k
  return url;
13036
44.9k
}
13037
13038
template url parse_url<url>(std::string_view user_input,
13039
                            const url* base_url = nullptr);
13040
template url_aggregator parse_url<url_aggregator>(
13041
    std::string_view user_input, const url_aggregator* base_url = nullptr);
13042
13043
}  // namespace ada::parser
13044
/* end file src/parser.cpp */
13045
/* begin file src/url_components.cpp */
13046
13047
#include <numeric>
13048
#include <string>
13049
13050
namespace ada {
13051
13052
0
[[nodiscard]] bool url_components::check_offset_consistency() const noexcept {
13053
  /**
13054
   * https://user:pass@example.com:1234/foo/bar?baz#quux
13055
   *       |     |    |          | ^^^^|       |   |
13056
   *       |     |    |          | |   |       |   `----- hash_start
13057
   *       |     |    |          | |   |       `--------- search_start
13058
   *       |     |    |          | |   `----------------- pathname_start
13059
   *       |     |    |          | `--------------------- port
13060
   *       |     |    |          `----------------------- host_end
13061
   *       |     |    `---------------------------------- host_start
13062
   *       |     `--------------------------------------- username_end
13063
   *       `--------------------------------------------- protocol_end
13064
   */
13065
  // These conditions can be made more strict.
13066
0
  uint32_t index = 0;
13067
13068
0
  if (protocol_end == url_components::omitted) {
13069
0
    return false;
13070
0
  }
13071
0
  if (protocol_end < index) {
13072
0
    return false;
13073
0
  }
13074
0
  index = protocol_end;
13075
13076
0
  if (username_end == url_components::omitted) {
13077
0
    return false;
13078
0
  }
13079
0
  if (username_end < index) {
13080
0
    return false;
13081
0
  }
13082
0
  index = username_end;
13083
13084
0
  if (host_start == url_components::omitted) {
13085
0
    return false;
13086
0
  }
13087
0
  if (host_start < index) {
13088
0
    return false;
13089
0
  }
13090
0
  index = host_start;
13091
13092
0
  if (port != url_components::omitted) {
13093
0
    if (port > 0xffff) {
13094
0
      return false;
13095
0
    }
13096
0
    uint32_t port_length = helpers::fast_digit_count(port) + 1;
13097
0
    if (index + port_length < index) {
13098
0
      return false;
13099
0
    }
13100
0
    index += port_length;
13101
0
  }
13102
13103
0
  if (pathname_start == url_components::omitted) {
13104
0
    return false;
13105
0
  }
13106
0
  if (pathname_start < index) {
13107
0
    return false;
13108
0
  }
13109
0
  index = pathname_start;
13110
13111
0
  if (search_start != url_components::omitted) {
13112
0
    if (search_start < index) {
13113
0
      return false;
13114
0
    }
13115
0
    index = search_start;
13116
0
  }
13117
13118
0
  if (hash_start != url_components::omitted) {
13119
0
    if (hash_start < index) {
13120
0
      return false;
13121
0
    }
13122
0
    index = hash_start;
13123
0
  }
13124
13125
0
  return true;
13126
0
}
13127
13128
0
[[nodiscard]] std::string url_components::to_string() const {
13129
0
  std::string answer;
13130
0
  auto back = std::back_insert_iterator(answer);
13131
0
  answer.append("{\n");
13132
13133
0
  answer.append("\t\"protocol_end\":\"");
13134
0
  helpers::encode_json(std::to_string(protocol_end), back);
13135
0
  answer.append("\",\n");
13136
13137
0
  answer.append("\t\"username_end\":\"");
13138
0
  helpers::encode_json(std::to_string(username_end), back);
13139
0
  answer.append("\",\n");
13140
13141
0
  answer.append("\t\"host_start\":\"");
13142
0
  helpers::encode_json(std::to_string(host_start), back);
13143
0
  answer.append("\",\n");
13144
13145
0
  answer.append("\t\"host_end\":\"");
13146
0
  helpers::encode_json(std::to_string(host_end), back);
13147
0
  answer.append("\",\n");
13148
13149
0
  answer.append("\t\"port\":\"");
13150
0
  helpers::encode_json(std::to_string(port), back);
13151
0
  answer.append("\",\n");
13152
13153
0
  answer.append("\t\"pathname_start\":\"");
13154
0
  helpers::encode_json(std::to_string(pathname_start), back);
13155
0
  answer.append("\",\n");
13156
13157
0
  answer.append("\t\"search_start\":\"");
13158
0
  helpers::encode_json(std::to_string(search_start), back);
13159
0
  answer.append("\",\n");
13160
13161
0
  answer.append("\t\"hash_start\":\"");
13162
0
  helpers::encode_json(std::to_string(hash_start), back);
13163
0
  answer.append("\",\n");
13164
13165
0
  answer.append("\n}");
13166
0
  return answer;
13167
0
}
13168
13169
}  // namespace ada
13170
/* end file src/url_components.cpp */
13171
/* begin file src/url_aggregator.cpp */
13172
13173
#include <string>
13174
#include <string_view>
13175
13176
namespace ada {
13177
template <bool has_state_override>
13178
[[nodiscard]] ada_really_inline bool url_aggregator::parse_scheme_with_colon(
13179
24.1k
    const std::string_view input_with_colon) {
13180
24.1k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
13181
24.1k
  ADA_ASSERT_TRUE(validate());
13182
24.1k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
13183
24.1k
  std::string_view input{input_with_colon};
13184
24.1k
  input.remove_suffix(1);
13185
24.1k
  auto parsed_type = ada::scheme::get_scheme_type(input);
13186
24.1k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
13187
  /**
13188
   * In the common case, we will immediately recognize a special scheme (e.g.,
13189
   *http, https), in which case, we can go really fast.
13190
   **/
13191
24.1k
  if (is_input_special) {  // fast path!!!
13192
8.89k
    if (has_state_override) {
13193
      // If url's scheme is not a special scheme and buffer is a special scheme,
13194
      // then return.
13195
78
      if (is_special() != is_input_special) {
13196
3
        return true;
13197
3
      }
13198
13199
      // If url includes credentials or has a non-null port, and buffer is
13200
      // "file", then return.
13201
75
      if ((has_credentials() || components.port != url_components::omitted) &&
13202
75
          parsed_type == ada::scheme::type::FILE) {
13203
1
        return true;
13204
1
      }
13205
13206
      // If url's scheme is "file" and its host is an empty host, then return.
13207
      // An empty host is the empty string.
13208
74
      if (type == ada::scheme::type::FILE &&
13209
74
          components.host_start == components.host_end) {
13210
2
        return true;
13211
2
      }
13212
74
    }
13213
13214
8.89k
    type = parsed_type;
13215
8.89k
    set_scheme_from_view_with_colon(input_with_colon);
13216
13217
8.89k
    if (has_state_override) {
13218
      // This is uncommon.
13219
72
      uint16_t urls_scheme_port = get_special_port();
13220
13221
      // If url's port is url's scheme's default port, then set url's port to
13222
      // null.
13223
72
      if (components.port == urls_scheme_port) {
13224
3
        clear_port();
13225
3
      }
13226
72
    }
13227
15.2k
  } else {  // slow path
13228
15.2k
    std::string _buffer = std::string(input);
13229
    // Next function is only valid if the input is ASCII and returns false
13230
    // otherwise, but it seems that we always have ascii content so we do not
13231
    // need to check the return value.
13232
15.2k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
13233
13234
15.2k
    if (has_state_override) {
13235
      // If url's scheme is a special scheme and buffer is not a special scheme,
13236
      // then return. If url's scheme is not a special scheme and buffer is a
13237
      // special scheme, then return.
13238
270
      if (is_special() != ada::scheme::is_special(_buffer)) {
13239
122
        return true;
13240
122
      }
13241
13242
      // If url includes credentials or has a non-null port, and buffer is
13243
      // "file", then return.
13244
148
      if ((has_credentials() || components.port != url_components::omitted) &&
13245
148
          _buffer == "file") {
13246
1
        return true;
13247
1
      }
13248
13249
      // If url's scheme is "file" and its host is an empty host, then return.
13250
      // An empty host is the empty string.
13251
147
      if (type == ada::scheme::type::FILE &&
13252
147
          components.host_start == components.host_end) {
13253
1
        return true;
13254
1
      }
13255
147
    }
13256
13257
15.1k
    set_scheme(_buffer);
13258
13259
15.1k
    if (has_state_override) {
13260
      // This is uncommon.
13261
146
      uint16_t urls_scheme_port = get_special_port();
13262
13263
      // If url's port is url's scheme's default port, then set url's port to
13264
      // null.
13265
146
      if (components.port == urls_scheme_port) {
13266
23
        clear_port();
13267
23
      }
13268
146
    }
13269
15.1k
  }
13270
24.0k
  ADA_ASSERT_TRUE(validate());
13271
24.0k
  return true;
13272
24.1k
}
bool ada::url_aggregator::parse_scheme_with_colon<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
13179
23.7k
    const std::string_view input_with_colon) {
13180
23.7k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
13181
23.7k
  ADA_ASSERT_TRUE(validate());
13182
23.7k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
13183
23.7k
  std::string_view input{input_with_colon};
13184
23.7k
  input.remove_suffix(1);
13185
23.7k
  auto parsed_type = ada::scheme::get_scheme_type(input);
13186
23.7k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
13187
  /**
13188
   * In the common case, we will immediately recognize a special scheme (e.g.,
13189
   *http, https), in which case, we can go really fast.
13190
   **/
13191
23.7k
  if (is_input_special) {  // fast path!!!
13192
8.82k
    if (has_state_override) {
13193
      // If url's scheme is not a special scheme and buffer is a special scheme,
13194
      // then return.
13195
0
      if (is_special() != is_input_special) {
13196
0
        return true;
13197
0
      }
13198
13199
      // If url includes credentials or has a non-null port, and buffer is
13200
      // "file", then return.
13201
0
      if ((has_credentials() || components.port != url_components::omitted) &&
13202
0
          parsed_type == ada::scheme::type::FILE) {
13203
0
        return true;
13204
0
      }
13205
13206
      // If url's scheme is "file" and its host is an empty host, then return.
13207
      // An empty host is the empty string.
13208
0
      if (type == ada::scheme::type::FILE &&
13209
0
          components.host_start == components.host_end) {
13210
0
        return true;
13211
0
      }
13212
0
    }
13213
13214
8.82k
    type = parsed_type;
13215
8.82k
    set_scheme_from_view_with_colon(input_with_colon);
13216
13217
8.82k
    if (has_state_override) {
13218
      // This is uncommon.
13219
0
      uint16_t urls_scheme_port = get_special_port();
13220
13221
      // If url's port is url's scheme's default port, then set url's port to
13222
      // null.
13223
0
      if (components.port == urls_scheme_port) {
13224
0
        clear_port();
13225
0
      }
13226
0
    }
13227
14.9k
  } else {  // slow path
13228
14.9k
    std::string _buffer = std::string(input);
13229
    // Next function is only valid if the input is ASCII and returns false
13230
    // otherwise, but it seems that we always have ascii content so we do not
13231
    // need to check the return value.
13232
14.9k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
13233
13234
14.9k
    if (has_state_override) {
13235
      // If url's scheme is a special scheme and buffer is not a special scheme,
13236
      // then return. If url's scheme is not a special scheme and buffer is a
13237
      // special scheme, then return.
13238
0
      if (is_special() != ada::scheme::is_special(_buffer)) {
13239
0
        return true;
13240
0
      }
13241
13242
      // If url includes credentials or has a non-null port, and buffer is
13243
      // "file", then return.
13244
0
      if ((has_credentials() || components.port != url_components::omitted) &&
13245
0
          _buffer == "file") {
13246
0
        return true;
13247
0
      }
13248
13249
      // If url's scheme is "file" and its host is an empty host, then return.
13250
      // An empty host is the empty string.
13251
0
      if (type == ada::scheme::type::FILE &&
13252
0
          components.host_start == components.host_end) {
13253
0
        return true;
13254
0
      }
13255
0
    }
13256
13257
14.9k
    set_scheme(_buffer);
13258
13259
14.9k
    if (has_state_override) {
13260
      // This is uncommon.
13261
0
      uint16_t urls_scheme_port = get_special_port();
13262
13263
      // If url's port is url's scheme's default port, then set url's port to
13264
      // null.
13265
0
      if (components.port == urls_scheme_port) {
13266
0
        clear_port();
13267
0
      }
13268
0
    }
13269
14.9k
  }
13270
23.7k
  ADA_ASSERT_TRUE(validate());
13271
23.7k
  return true;
13272
23.7k
}
bool ada::url_aggregator::parse_scheme_with_colon<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
13179
348
    const std::string_view input_with_colon) {
13180
348
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
13181
348
  ADA_ASSERT_TRUE(validate());
13182
348
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
13183
348
  std::string_view input{input_with_colon};
13184
348
  input.remove_suffix(1);
13185
348
  auto parsed_type = ada::scheme::get_scheme_type(input);
13186
348
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
13187
  /**
13188
   * In the common case, we will immediately recognize a special scheme (e.g.,
13189
   *http, https), in which case, we can go really fast.
13190
   **/
13191
348
  if (is_input_special) {  // fast path!!!
13192
78
    if (has_state_override) {
13193
      // If url's scheme is not a special scheme and buffer is a special scheme,
13194
      // then return.
13195
78
      if (is_special() != is_input_special) {
13196
3
        return true;
13197
3
      }
13198
13199
      // If url includes credentials or has a non-null port, and buffer is
13200
      // "file", then return.
13201
75
      if ((has_credentials() || components.port != url_components::omitted) &&
13202
75
          parsed_type == ada::scheme::type::FILE) {
13203
1
        return true;
13204
1
      }
13205
13206
      // If url's scheme is "file" and its host is an empty host, then return.
13207
      // An empty host is the empty string.
13208
74
      if (type == ada::scheme::type::FILE &&
13209
74
          components.host_start == components.host_end) {
13210
2
        return true;
13211
2
      }
13212
74
    }
13213
13214
72
    type = parsed_type;
13215
72
    set_scheme_from_view_with_colon(input_with_colon);
13216
13217
72
    if (has_state_override) {
13218
      // This is uncommon.
13219
72
      uint16_t urls_scheme_port = get_special_port();
13220
13221
      // If url's port is url's scheme's default port, then set url's port to
13222
      // null.
13223
72
      if (components.port == urls_scheme_port) {
13224
3
        clear_port();
13225
3
      }
13226
72
    }
13227
270
  } else {  // slow path
13228
270
    std::string _buffer = std::string(input);
13229
    // Next function is only valid if the input is ASCII and returns false
13230
    // otherwise, but it seems that we always have ascii content so we do not
13231
    // need to check the return value.
13232
270
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
13233
13234
270
    if (has_state_override) {
13235
      // If url's scheme is a special scheme and buffer is not a special scheme,
13236
      // then return. If url's scheme is not a special scheme and buffer is a
13237
      // special scheme, then return.
13238
270
      if (is_special() != ada::scheme::is_special(_buffer)) {
13239
122
        return true;
13240
122
      }
13241
13242
      // If url includes credentials or has a non-null port, and buffer is
13243
      // "file", then return.
13244
148
      if ((has_credentials() || components.port != url_components::omitted) &&
13245
148
          _buffer == "file") {
13246
1
        return true;
13247
1
      }
13248
13249
      // If url's scheme is "file" and its host is an empty host, then return.
13250
      // An empty host is the empty string.
13251
147
      if (type == ada::scheme::type::FILE &&
13252
147
          components.host_start == components.host_end) {
13253
1
        return true;
13254
1
      }
13255
147
    }
13256
13257
146
    set_scheme(_buffer);
13258
13259
146
    if (has_state_override) {
13260
      // This is uncommon.
13261
146
      uint16_t urls_scheme_port = get_special_port();
13262
13263
      // If url's port is url's scheme's default port, then set url's port to
13264
      // null.
13265
146
      if (components.port == urls_scheme_port) {
13266
23
        clear_port();
13267
23
      }
13268
146
    }
13269
146
  }
13270
218
  ADA_ASSERT_TRUE(validate());
13271
218
  return true;
13272
348
}
13273
13274
783
inline void url_aggregator::copy_scheme(const url_aggregator& u) noexcept {
13275
783
  ada_log("url_aggregator::copy_scheme ", u.buffer);
13276
783
  ADA_ASSERT_TRUE(validate());
13277
  // next line could overflow but unsigned arithmetic has well-defined
13278
  // overflows.
13279
783
  uint32_t new_difference = u.components.protocol_end - components.protocol_end;
13280
783
  type = u.type;
13281
783
  buffer.erase(0, components.protocol_end);
13282
783
  buffer.insert(0, u.get_protocol());
13283
783
  components.protocol_end = u.components.protocol_end;
13284
13285
  // No need to update the components
13286
783
  if (new_difference == 0) {
13287
91
    return;
13288
91
  }
13289
13290
  // Update the rest of the components.
13291
692
  components.username_end += new_difference;
13292
692
  components.host_start += new_difference;
13293
692
  components.host_end += new_difference;
13294
692
  components.pathname_start += new_difference;
13295
692
  if (components.search_start != url_components::omitted) {
13296
0
    components.search_start += new_difference;
13297
0
  }
13298
692
  if (components.hash_start != url_components::omitted) {
13299
0
    components.hash_start += new_difference;
13300
0
  }
13301
692
  ADA_ASSERT_TRUE(validate());
13302
692
}
13303
13304
inline void url_aggregator::set_scheme_from_view_with_colon(
13305
8.89k
    std::string_view new_scheme_with_colon) noexcept {
13306
8.89k
  ada_log("url_aggregator::set_scheme_from_view_with_colon ",
13307
8.89k
          new_scheme_with_colon);
13308
8.89k
  ADA_ASSERT_TRUE(validate());
13309
8.89k
  ADA_ASSERT_TRUE(!new_scheme_with_colon.empty() &&
13310
8.89k
                  new_scheme_with_colon.back() == ':');
13311
  // next line could overflow but unsigned arithmetic has well-defined
13312
  // overflows.
13313
8.89k
  uint32_t new_difference =
13314
8.89k
      uint32_t(new_scheme_with_colon.size()) - components.protocol_end;
13315
13316
8.89k
  if (buffer.empty()) {
13317
8.82k
    buffer.append(new_scheme_with_colon);
13318
8.82k
  } else {
13319
72
    buffer.erase(0, components.protocol_end);
13320
72
    buffer.insert(0, new_scheme_with_colon);
13321
72
  }
13322
8.89k
  components.protocol_end += new_difference;
13323
13324
  // Update the rest of the components.
13325
8.89k
  components.username_end += new_difference;
13326
8.89k
  components.host_start += new_difference;
13327
8.89k
  components.host_end += new_difference;
13328
8.89k
  components.pathname_start += new_difference;
13329
8.89k
  if (components.search_start != url_components::omitted) {
13330
14
    components.search_start += new_difference;
13331
14
  }
13332
8.89k
  if (components.hash_start != url_components::omitted) {
13333
16
    components.hash_start += new_difference;
13334
16
  }
13335
8.89k
  ADA_ASSERT_TRUE(validate());
13336
8.89k
}
13337
13338
15.1k
inline void url_aggregator::set_scheme(std::string_view new_scheme) noexcept {
13339
15.1k
  ada_log("url_aggregator::set_scheme ", new_scheme);
13340
15.1k
  ADA_ASSERT_TRUE(validate());
13341
15.1k
  ADA_ASSERT_TRUE(new_scheme.empty() || new_scheme.back() != ':');
13342
  // next line could overflow but unsigned arithmetic has well-defined
13343
  // overflows.
13344
15.1k
  uint32_t new_difference =
13345
15.1k
      uint32_t(new_scheme.size()) - components.protocol_end + 1;
13346
13347
15.1k
  type = ada::scheme::get_scheme_type(new_scheme);
13348
15.1k
  if (buffer.empty()) {
13349
14.9k
    buffer.append(helpers::concat(new_scheme, ":"));
13350
14.9k
  } else {
13351
146
    buffer.erase(0, components.protocol_end);
13352
146
    buffer.insert(0, helpers::concat(new_scheme, ":"));
13353
146
  }
13354
15.1k
  components.protocol_end = uint32_t(new_scheme.size() + 1);
13355
13356
  // Update the rest of the components.
13357
15.1k
  components.username_end += new_difference;
13358
15.1k
  components.host_start += new_difference;
13359
15.1k
  components.host_end += new_difference;
13360
15.1k
  components.pathname_start += new_difference;
13361
15.1k
  if (components.search_start != url_components::omitted) {
13362
19
    components.search_start += new_difference;
13363
19
  }
13364
15.1k
  if (components.hash_start != url_components::omitted) {
13365
20
    components.hash_start += new_difference;
13366
20
  }
13367
15.1k
  ADA_ASSERT_TRUE(validate());
13368
15.1k
}
13369
13370
8.00k
bool url_aggregator::set_protocol(const std::string_view input) {
13371
8.00k
  ada_log("url_aggregator::set_protocol ", input);
13372
8.00k
  ADA_ASSERT_TRUE(validate());
13373
8.00k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13374
8.00k
  std::string view(input);
13375
8.00k
  helpers::remove_ascii_tab_or_newline(view);
13376
8.00k
  if (view.empty()) {
13377
6.49k
    return true;
13378
6.49k
  }
13379
13380
  // Schemes should start with alpha values.
13381
1.50k
  if (!checkers::is_alpha(view[0])) {
13382
1.08k
    return false;
13383
1.08k
  }
13384
13385
424
  view.append(":");
13386
13387
424
  std::string::iterator pointer =
13388
424
      std::find_if_not(view.begin(), view.end(), unicode::is_alnum_plus);
13389
13390
424
  if (pointer != view.end() && *pointer == ':') {
13391
348
    return parse_scheme_with_colon<true>(
13392
348
        std::string_view(view.data(), pointer - view.begin() + 1));
13393
348
  }
13394
76
  return false;
13395
424
}
13396
13397
8.00k
bool url_aggregator::set_username(const std::string_view input) {
13398
8.00k
  ada_log("url_aggregator::set_username '", input, "' ");
13399
8.00k
  ADA_ASSERT_TRUE(validate());
13400
8.00k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13401
8.00k
  if (cannot_have_credentials_or_port()) {
13402
3.88k
    return false;
13403
3.88k
  }
13404
4.11k
  size_t idx = ada::unicode::percent_encode_index(
13405
4.11k
      input, character_sets::USERINFO_PERCENT_ENCODE);
13406
4.11k
  if (idx == input.size()) {
13407
3.57k
    update_base_username(input);
13408
3.57k
  } else {
13409
    // We only create a temporary string if we have to!
13410
543
    update_base_username(ada::unicode::percent_encode(
13411
543
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
13412
543
  }
13413
4.11k
  ADA_ASSERT_TRUE(validate());
13414
4.11k
  return true;
13415
8.00k
}
13416
13417
8.00k
bool url_aggregator::set_password(const std::string_view input) {
13418
8.00k
  ada_log("url_aggregator::set_password '", input, "'");
13419
8.00k
  ADA_ASSERT_TRUE(validate());
13420
8.00k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13421
8.00k
  if (cannot_have_credentials_or_port()) {
13422
3.88k
    return false;
13423
3.88k
  }
13424
4.11k
  size_t idx = ada::unicode::percent_encode_index(
13425
4.11k
      input, character_sets::USERINFO_PERCENT_ENCODE);
13426
4.11k
  if (idx == input.size()) {
13427
3.57k
    update_base_password(input);
13428
3.57k
  } else {
13429
    // We only create a temporary string if we have to!
13430
543
    update_base_password(ada::unicode::percent_encode(
13431
543
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
13432
543
  }
13433
4.11k
  ADA_ASSERT_TRUE(validate());
13434
4.11k
  return true;
13435
8.00k
}
13436
13437
8.15k
bool url_aggregator::set_port(const std::string_view input) {
13438
8.15k
  ada_log("url_aggregator::set_port ", input);
13439
8.15k
  ADA_ASSERT_TRUE(validate());
13440
8.15k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13441
8.15k
  if (cannot_have_credentials_or_port()) {
13442
3.85k
    return false;
13443
3.85k
  }
13444
4.30k
  std::string trimmed(input);
13445
4.30k
  helpers::remove_ascii_tab_or_newline(trimmed);
13446
4.30k
  if (trimmed.empty()) {
13447
3.16k
    clear_port();
13448
3.16k
    return true;
13449
3.16k
  }
13450
  // Input should not start with control characters.
13451
1.14k
  if (ada::unicode::is_c0_control_or_space(trimmed.front())) {
13452
52
    return false;
13453
52
  }
13454
  // Input should contain at least one ascii digit.
13455
1.08k
  if (input.find_first_of("0123456789") == std::string_view::npos) {
13456
561
    return false;
13457
561
  }
13458
13459
  // Revert changes if parse_port fails.
13460
528
  uint32_t previous_port = components.port;
13461
528
  parse_port(trimmed);
13462
528
  if (is_valid) {
13463
363
    return true;
13464
363
  }
13465
165
  update_base_port(previous_port);
13466
165
  is_valid = true;
13467
165
  ADA_ASSERT_TRUE(validate());
13468
165
  return false;
13469
528
}
13470
13471
8.00k
bool url_aggregator::set_pathname(const std::string_view input) {
13472
8.00k
  ada_log("url_aggregator::set_pathname ", input);
13473
8.00k
  ADA_ASSERT_TRUE(validate());
13474
8.00k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13475
8.00k
  if (has_opaque_path) {
13476
1.01k
    return false;
13477
1.01k
  }
13478
6.98k
  clear_pathname();
13479
6.98k
  parse_path(input);
13480
6.98k
  if (checkers::begins_with(input, "//") && !has_authority() &&
13481
6.98k
      !has_dash_dot()) {
13482
4
    buffer.insert(components.pathname_start, "/.");
13483
4
    components.pathname_start += 2;
13484
4
  }
13485
6.98k
  ADA_ASSERT_TRUE(validate());
13486
6.98k
  return true;
13487
8.00k
}
13488
13489
6.98k
ada_really_inline void url_aggregator::parse_path(std::string_view input) {
13490
6.98k
  ada_log("url_aggregator::parse_path ", input);
13491
6.98k
  ADA_ASSERT_TRUE(validate());
13492
6.98k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13493
6.98k
  std::string tmp_buffer;
13494
6.98k
  std::string_view internal_input;
13495
6.98k
  if (unicode::has_tabs_or_newline(input)) {
13496
130
    tmp_buffer = input;
13497
    // Optimization opportunity: Instead of copying and then pruning, we could
13498
    // just directly build the string from user_input.
13499
130
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13500
130
    internal_input = tmp_buffer;
13501
6.85k
  } else {
13502
6.85k
    internal_input = input;
13503
6.85k
  }
13504
13505
  // If url is special, then:
13506
6.98k
  if (is_special()) {
13507
5.25k
    if (internal_input.empty()) {
13508
4.27k
      update_base_pathname("/");
13509
4.27k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
13510
16
      consume_prepared_path(internal_input.substr(1));
13511
967
    } else {
13512
967
      consume_prepared_path(internal_input);
13513
967
    }
13514
5.25k
  } else if (!internal_input.empty()) {
13515
389
    if (internal_input[0] == '/') {
13516
20
      consume_prepared_path(internal_input.substr(1));
13517
369
    } else {
13518
369
      consume_prepared_path(internal_input);
13519
369
    }
13520
1.34k
  } else {
13521
    // Non-special URLs with an empty host can have their paths erased
13522
    // Path-only URLs cannot have their paths erased
13523
1.34k
    if (components.host_start == components.host_end && !has_authority()) {
13524
1.17k
      update_base_pathname("/");
13525
1.17k
    }
13526
1.34k
  }
13527
6.98k
  ADA_ASSERT_TRUE(validate());
13528
6.98k
}
13529
13530
8.00k
void url_aggregator::set_search(const std::string_view input) {
13531
8.00k
  ada_log("url_aggregator::set_search ", input);
13532
8.00k
  ADA_ASSERT_TRUE(validate());
13533
8.00k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13534
8.00k
  if (input.empty()) {
13535
6.43k
    clear_search();
13536
6.43k
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13537
6.43k
    return;
13538
6.43k
  }
13539
13540
1.57k
  std::string new_value;
13541
1.57k
  new_value = input[0] == '?' ? input.substr(1) : input;
13542
1.57k
  helpers::remove_ascii_tab_or_newline(new_value);
13543
13544
1.57k
  auto query_percent_encode_set =
13545
1.57k
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13546
1.57k
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
13547
13548
1.57k
  update_base_search(new_value, query_percent_encode_set);
13549
1.57k
  ADA_ASSERT_TRUE(validate());
13550
1.57k
}
13551
13552
8.00k
void url_aggregator::set_hash(const std::string_view input) {
13553
8.00k
  ada_log("url_aggregator::set_hash ", input);
13554
8.00k
  ADA_ASSERT_TRUE(validate());
13555
8.00k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13556
8.00k
  if (input.empty()) {
13557
6.43k
    if (components.hash_start != url_components::omitted) {
13558
136
      buffer.resize(components.hash_start);
13559
136
      components.hash_start = url_components::omitted;
13560
136
    }
13561
6.43k
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13562
6.43k
    return;
13563
6.43k
  }
13564
13565
1.57k
  std::string new_value;
13566
1.57k
  new_value = input[0] == '#' ? input.substr(1) : input;
13567
1.57k
  helpers::remove_ascii_tab_or_newline(new_value);
13568
1.57k
  update_unencoded_base_hash(new_value);
13569
1.57k
  ADA_ASSERT_TRUE(validate());
13570
1.57k
}
13571
13572
0
bool url_aggregator::set_href(const std::string_view input) {
13573
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13574
0
  ada_log("url_aggregator::set_href ", input, "[", input.size(), " bytes]");
13575
0
  ada::result<url_aggregator> out = ada::parse<url_aggregator>(input);
13576
0
  ada_log("url_aggregator::set_href, success :", out.has_value());
13577
13578
0
  if (out) {
13579
0
    ada_log("url_aggregator::set_href, parsed ", out->to_string());
13580
    // TODO: Figure out why the following line puts test to never finish.
13581
0
    *this = *out;
13582
0
  }
13583
13584
0
  return out.has_value();
13585
0
}
13586
13587
17.7k
ada_really_inline bool url_aggregator::parse_host(std::string_view input) {
13588
17.7k
  ada_log("url_aggregator:parse_host ", input, "[", input.size(), " bytes]");
13589
17.7k
  ADA_ASSERT_TRUE(validate());
13590
17.7k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13591
17.7k
  if (input.empty()) {
13592
63
    return is_valid = false;
13593
63
  }  // technically unnecessary.
13594
  // If input starts with U+005B ([), then:
13595
17.6k
  if (input[0] == '[') {
13596
    // If input does not end with U+005D (]), validation error, return failure.
13597
1.54k
    if (input.back() != ']') {
13598
591
      return is_valid = false;
13599
591
    }
13600
958
    ada_log("parse_host ipv6");
13601
13602
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
13603
    // trailing U+005D (]) removed.
13604
958
    input.remove_prefix(1);
13605
958
    input.remove_suffix(1);
13606
958
    return parse_ipv6(input);
13607
1.54k
  }
13608
13609
  // If isNotSpecial is true, then return the result of opaque-host parsing
13610
  // input.
13611
16.1k
  if (!is_special()) {
13612
1.17k
    return parse_opaque_host(input);
13613
1.17k
  }
13614
  // Let domain be the result of running UTF-8 decode without BOM on the
13615
  // percent-decoding of input. Let asciiDomain be the result of running domain
13616
  // to ASCII with domain and false. The most common case is an ASCII input, in
13617
  // which case we do not need to call the expensive 'to_ascii' if a few
13618
  // conditions are met: no '%' and no 'xn-' subsequence.
13619
13620
  // Often, the input does not contain any forbidden code points, and no upper
13621
  // case ASCII letter, then we can just copy it to the buffer. We want to
13622
  // optimize for such a common case.
13623
14.9k
  uint8_t is_forbidden_or_upper =
13624
14.9k
      unicode::contains_forbidden_domain_code_point_or_upper(input.data(),
13625
14.9k
                                                             input.size());
13626
  // Minor optimization opportunity:
13627
  // contains_forbidden_domain_code_point_or_upper could be extend to check for
13628
  // the presence of characters that cannot appear in the ipv4 address and we
13629
  // could also check whether x and n and - are present, and so we could skip
13630
  // some of the checks below. However, the gains are likely to be small, and
13631
  // the code would be more complex.
13632
14.9k
  if (is_forbidden_or_upper == 0 &&
13633
14.9k
      input.find("xn-") == std::string_view::npos) {
13634
    // fast path
13635
7.70k
    update_base_hostname(input);
13636
7.70k
    if (checkers::is_ipv4(get_hostname())) {
13637
2.94k
      ada_log("parse_host fast path ipv4");
13638
2.94k
      return parse_ipv4(get_hostname());
13639
2.94k
    }
13640
4.75k
    ada_log("parse_host fast path ", get_hostname());
13641
4.75k
    return true;
13642
7.70k
  }
13643
  // We have encountered at least one forbidden code point or the input contains
13644
  // 'xn-' (case insensitive), so we need to call 'to_ascii' to perform the full
13645
  // conversion.
13646
13647
7.22k
  ada_log("parse_host calling to_ascii");
13648
7.22k
  std::optional<std::string> host = std::string(get_hostname());
13649
7.22k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
13650
7.22k
  if (!is_valid) {
13651
1.84k
    ada_log("parse_host to_ascii returns false");
13652
1.84k
    return is_valid = false;
13653
1.84k
  }
13654
13655
5.37k
  if (std::any_of(host.value().begin(), host.value().end(),
13656
5.37k
                  ada::unicode::is_forbidden_domain_code_point)) {
13657
0
    return is_valid = false;
13658
0
  }
13659
13660
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
13661
  // asciiDomain.
13662
5.37k
  if (checkers::is_ipv4(host.value())) {
13663
929
    ada_log("parse_host got ipv4", *host);
13664
929
    return parse_ipv4(host.value());
13665
929
  }
13666
13667
4.44k
  update_base_hostname(host.value());
13668
4.44k
  ADA_ASSERT_TRUE(validate());
13669
4.44k
  return true;
13670
5.37k
}
13671
13672
template <bool override_hostname>
13673
17.3k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
13674
17.3k
  ada_log("url_aggregator::set_host_or_hostname ", input);
13675
17.3k
  ADA_ASSERT_TRUE(validate());
13676
17.3k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13677
17.3k
  if (has_opaque_path) {
13678
2.03k
    return false;
13679
2.03k
  }
13680
13681
15.2k
  std::string previous_host = std::string(get_hostname());
13682
15.2k
  uint32_t previous_port = components.port;
13683
13684
15.2k
  size_t host_end_pos = input.find('#');
13685
15.2k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
13686
15.2k
                                      ? host_end_pos
13687
15.2k
                                      : input.size());
13688
15.2k
  helpers::remove_ascii_tab_or_newline(_host);
13689
15.2k
  std::string_view new_host(_host);
13690
13691
  // If url's scheme is "file", then set state to file host state, instead of
13692
  // host state.
13693
15.2k
  if (type != ada::scheme::type::FILE) {
13694
12.0k
    std::string_view host_view(_host.data(), _host.length());
13695
12.0k
    auto [location, found_colon] =
13696
12.0k
        helpers::get_host_delimiter_location(is_special(), host_view);
13697
13698
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13699
    // Note: the 'found_colon' value is true if and only if a colon was
13700
    // encountered while not inside brackets.
13701
12.0k
    if (found_colon) {
13702
356
      if (override_hostname) {
13703
178
        return false;
13704
178
      }
13705
178
      std::string_view sub_buffer = new_host.substr(location + 1);
13706
178
      if (!sub_buffer.empty()) {
13707
154
        set_port(sub_buffer);
13708
154
      }
13709
178
    }
13710
    // If url is special and host_view is the empty string, validation error,
13711
    // return failure. Otherwise, if state override is given, host_view is the
13712
    // empty string, and either url includes credentials or url's port is
13713
    // non-null, return.
13714
11.6k
    else if (host_view.empty() &&
13715
11.6k
             (is_special() || has_credentials() || has_port())) {
13716
6.38k
      return false;
13717
6.38k
    }
13718
13719
    // Let host be the result of host parsing host_view with url is not special.
13720
5.43k
    if (host_view.empty() && !is_special()) {
13721
2.81k
      if (has_hostname()) {
13722
263
        clear_hostname();  // easy!
13723
2.55k
      } else if (has_dash_dot()) {
13724
37
        add_authority_slashes_if_needed();
13725
37
        delete_dash_dot();
13726
37
      }
13727
2.81k
      return true;
13728
2.81k
    }
13729
13730
2.61k
    bool succeeded = parse_host(host_view);
13731
2.61k
    if (!succeeded) {
13732
758
      update_base_hostname(previous_host);
13733
758
      update_base_port(previous_port);
13734
1.85k
    } else if (has_dash_dot()) {
13735
      // Should remove dash_dot from pathname
13736
16
      delete_dash_dot();
13737
16
    }
13738
2.61k
    return succeeded;
13739
5.43k
  }
13740
13741
3.29k
  size_t location = new_host.find_first_of("/\\?");
13742
3.29k
  if (location != std::string_view::npos) {
13743
36
    new_host.remove_suffix(new_host.length() - location);
13744
36
  }
13745
13746
3.29k
  if (new_host.empty()) {
13747
    // Set url's host to the empty string.
13748
2.44k
    clear_hostname();
13749
2.44k
  } else {
13750
    // Let host be the result of host parsing buffer with url is not special.
13751
853
    if (!parse_host(new_host)) {
13752
124
      update_base_hostname(previous_host);
13753
124
      update_base_port(previous_port);
13754
124
      return false;
13755
124
    }
13756
13757
    // If host is "localhost", then set host to the empty string.
13758
729
    if (helpers::substring(buffer, components.host_start,
13759
729
                           components.host_end) == "localhost") {
13760
36
      clear_hostname();
13761
36
    }
13762
729
  }
13763
3.17k
  ADA_ASSERT_TRUE(validate());
13764
3.17k
  return true;
13765
3.29k
}
bool ada::url_aggregator::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
13673
8.23k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
13674
8.23k
  ada_log("url_aggregator::set_host_or_hostname ", input);
13675
8.23k
  ADA_ASSERT_TRUE(validate());
13676
8.23k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13677
8.23k
  if (has_opaque_path) {
13678
1.01k
    return false;
13679
1.01k
  }
13680
13681
7.21k
  std::string previous_host = std::string(get_hostname());
13682
7.21k
  uint32_t previous_port = components.port;
13683
13684
7.21k
  size_t host_end_pos = input.find('#');
13685
7.21k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
13686
7.21k
                                      ? host_end_pos
13687
7.21k
                                      : input.size());
13688
7.21k
  helpers::remove_ascii_tab_or_newline(_host);
13689
7.21k
  std::string_view new_host(_host);
13690
13691
  // If url's scheme is "file", then set state to file host state, instead of
13692
  // host state.
13693
7.21k
  if (type != ada::scheme::type::FILE) {
13694
5.62k
    std::string_view host_view(_host.data(), _host.length());
13695
5.62k
    auto [location, found_colon] =
13696
5.62k
        helpers::get_host_delimiter_location(is_special(), host_view);
13697
13698
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13699
    // Note: the 'found_colon' value is true if and only if a colon was
13700
    // encountered while not inside brackets.
13701
5.62k
    if (found_colon) {
13702
178
      if (override_hostname) {
13703
0
        return false;
13704
0
      }
13705
178
      std::string_view sub_buffer = new_host.substr(location + 1);
13706
178
      if (!sub_buffer.empty()) {
13707
154
        set_port(sub_buffer);
13708
154
      }
13709
178
    }
13710
    // If url is special and host_view is the empty string, validation error,
13711
    // return failure. Otherwise, if state override is given, host_view is the
13712
    // empty string, and either url includes credentials or url's port is
13713
    // non-null, return.
13714
5.44k
    else if (host_view.empty() &&
13715
5.44k
             (is_special() || has_credentials() || has_port())) {
13716
3.19k
      return false;
13717
3.19k
    }
13718
13719
    // Let host be the result of host parsing host_view with url is not special.
13720
2.43k
    if (host_view.empty() && !is_special()) {
13721
1.36k
      if (has_hostname()) {
13722
156
        clear_hostname();  // easy!
13723
1.20k
      } else if (has_dash_dot()) {
13724
1
        add_authority_slashes_if_needed();
13725
1
        delete_dash_dot();
13726
1
      }
13727
1.36k
      return true;
13728
1.36k
    }
13729
13730
1.07k
    bool succeeded = parse_host(host_view);
13731
1.07k
    if (!succeeded) {
13732
418
      update_base_hostname(previous_host);
13733
418
      update_base_port(previous_port);
13734
654
    } else if (has_dash_dot()) {
13735
      // Should remove dash_dot from pathname
13736
13
      delete_dash_dot();
13737
13
    }
13738
1.07k
    return succeeded;
13739
2.43k
  }
13740
13741
1.58k
  size_t location = new_host.find_first_of("/\\?");
13742
1.58k
  if (location != std::string_view::npos) {
13743
18
    new_host.remove_suffix(new_host.length() - location);
13744
18
  }
13745
13746
1.58k
  if (new_host.empty()) {
13747
    // Set url's host to the empty string.
13748
1.18k
    clear_hostname();
13749
1.18k
  } else {
13750
    // Let host be the result of host parsing buffer with url is not special.
13751
405
    if (!parse_host(new_host)) {
13752
62
      update_base_hostname(previous_host);
13753
62
      update_base_port(previous_port);
13754
62
      return false;
13755
62
    }
13756
13757
    // If host is "localhost", then set host to the empty string.
13758
343
    if (helpers::substring(buffer, components.host_start,
13759
343
                           components.host_end) == "localhost") {
13760
18
      clear_hostname();
13761
18
    }
13762
343
  }
13763
1.52k
  ADA_ASSERT_TRUE(validate());
13764
1.52k
  return true;
13765
1.58k
}
bool ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
13673
9.09k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
13674
9.09k
  ada_log("url_aggregator::set_host_or_hostname ", input);
13675
9.09k
  ADA_ASSERT_TRUE(validate());
13676
9.09k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13677
9.09k
  if (has_opaque_path) {
13678
1.01k
    return false;
13679
1.01k
  }
13680
13681
8.08k
  std::string previous_host = std::string(get_hostname());
13682
8.08k
  uint32_t previous_port = components.port;
13683
13684
8.08k
  size_t host_end_pos = input.find('#');
13685
8.08k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
13686
8.08k
                                      ? host_end_pos
13687
8.08k
                                      : input.size());
13688
8.08k
  helpers::remove_ascii_tab_or_newline(_host);
13689
8.08k
  std::string_view new_host(_host);
13690
13691
  // If url's scheme is "file", then set state to file host state, instead of
13692
  // host state.
13693
8.08k
  if (type != ada::scheme::type::FILE) {
13694
6.37k
    std::string_view host_view(_host.data(), _host.length());
13695
6.37k
    auto [location, found_colon] =
13696
6.37k
        helpers::get_host_delimiter_location(is_special(), host_view);
13697
13698
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13699
    // Note: the 'found_colon' value is true if and only if a colon was
13700
    // encountered while not inside brackets.
13701
6.37k
    if (found_colon) {
13702
178
      if (override_hostname) {
13703
178
        return false;
13704
178
      }
13705
0
      std::string_view sub_buffer = new_host.substr(location + 1);
13706
0
      if (!sub_buffer.empty()) {
13707
0
        set_port(sub_buffer);
13708
0
      }
13709
0
    }
13710
    // If url is special and host_view is the empty string, validation error,
13711
    // return failure. Otherwise, if state override is given, host_view is the
13712
    // empty string, and either url includes credentials or url's port is
13713
    // non-null, return.
13714
6.19k
    else if (host_view.empty() &&
13715
6.19k
             (is_special() || has_credentials() || has_port())) {
13716
3.19k
      return false;
13717
3.19k
    }
13718
13719
    // Let host be the result of host parsing host_view with url is not special.
13720
2.99k
    if (host_view.empty() && !is_special()) {
13721
1.45k
      if (has_hostname()) {
13722
107
        clear_hostname();  // easy!
13723
1.34k
      } else if (has_dash_dot()) {
13724
36
        add_authority_slashes_if_needed();
13725
36
        delete_dash_dot();
13726
36
      }
13727
1.45k
      return true;
13728
1.45k
    }
13729
13730
1.54k
    bool succeeded = parse_host(host_view);
13731
1.54k
    if (!succeeded) {
13732
340
      update_base_hostname(previous_host);
13733
340
      update_base_port(previous_port);
13734
1.20k
    } else if (has_dash_dot()) {
13735
      // Should remove dash_dot from pathname
13736
3
      delete_dash_dot();
13737
3
    }
13738
1.54k
    return succeeded;
13739
2.99k
  }
13740
13741
1.71k
  size_t location = new_host.find_first_of("/\\?");
13742
1.71k
  if (location != std::string_view::npos) {
13743
18
    new_host.remove_suffix(new_host.length() - location);
13744
18
  }
13745
13746
1.71k
  if (new_host.empty()) {
13747
    // Set url's host to the empty string.
13748
1.26k
    clear_hostname();
13749
1.26k
  } else {
13750
    // Let host be the result of host parsing buffer with url is not special.
13751
448
    if (!parse_host(new_host)) {
13752
62
      update_base_hostname(previous_host);
13753
62
      update_base_port(previous_port);
13754
62
      return false;
13755
62
    }
13756
13757
    // If host is "localhost", then set host to the empty string.
13758
386
    if (helpers::substring(buffer, components.host_start,
13759
386
                           components.host_end) == "localhost") {
13760
18
      clear_hostname();
13761
18
    }
13762
386
  }
13763
1.64k
  ADA_ASSERT_TRUE(validate());
13764
1.64k
  return true;
13765
1.71k
}
13766
13767
8.23k
bool url_aggregator::set_host(const std::string_view input) {
13768
8.23k
  ada_log("url_aggregator::set_host '", input, "'");
13769
8.23k
  ADA_ASSERT_TRUE(validate());
13770
8.23k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13771
8.23k
  return set_host_or_hostname<false>(input);
13772
8.23k
}
13773
13774
9.09k
bool url_aggregator::set_hostname(const std::string_view input) {
13775
9.09k
  ada_log("url_aggregator::set_hostname '", input, "'");
13776
9.09k
  ADA_ASSERT_TRUE(validate());
13777
9.09k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13778
9.09k
  return set_host_or_hostname<true>(input);
13779
9.09k
}
13780
13781
8.00k
[[nodiscard]] std::string url_aggregator::get_origin() const noexcept {
13782
8.00k
  ada_log("url_aggregator::get_origin");
13783
8.00k
  if (is_special()) {
13784
    // Return a new opaque origin.
13785
5.25k
    if (type == scheme::FILE) {
13786
1.35k
      return "null";
13787
1.35k
    }
13788
13789
3.89k
    return helpers::concat(get_protocol(), "//", get_host());
13790
5.25k
  }
13791
13792
2.74k
  if (get_protocol() == "blob:") {
13793
411
    std::string_view path = get_pathname();
13794
411
    if (!path.empty()) {
13795
408
      auto out = ada::parse<ada::url_aggregator>(path);
13796
408
      if (out && (out->type == scheme::HTTP || out->type == scheme::HTTPS)) {
13797
        // If pathURL's scheme is not "http" and not "https", then return a
13798
        // new opaque origin.
13799
13
        return helpers::concat(out->get_protocol(), "//", out->get_host());
13800
13
      }
13801
408
    }
13802
411
  }
13803
13804
  // Return a new opaque origin.
13805
2.73k
  return "null";
13806
2.74k
}
13807
13808
8.00k
[[nodiscard]] std::string_view url_aggregator::get_username() const noexcept {
13809
8.00k
  ada_log("url_aggregator::get_username");
13810
8.00k
  if (has_non_empty_username()) {
13811
882
    return helpers::substring(buffer, components.protocol_end + 2,
13812
882
                              components.username_end);
13813
882
  }
13814
7.11k
  return "";
13815
8.00k
}
13816
13817
8.00k
[[nodiscard]] std::string_view url_aggregator::get_password() const noexcept {
13818
8.00k
  ada_log("url_aggregator::get_password");
13819
8.00k
  if (has_non_empty_password()) {
13820
882
    return helpers::substring(buffer, components.username_end + 1,
13821
882
                              components.host_start);
13822
882
  }
13823
7.11k
  return "";
13824
8.00k
}
13825
13826
8.00k
[[nodiscard]] std::string_view url_aggregator::get_port() const noexcept {
13827
8.00k
  ada_log("url_aggregator::get_port");
13828
8.00k
  if (components.port == url_components::omitted) {
13829
7.74k
    return "";
13830
7.74k
  }
13831
256
  return helpers::substring(buffer, components.host_end + 1,
13832
256
                            components.pathname_start);
13833
8.00k
}
13834
13835
8.00k
[[nodiscard]] std::string_view url_aggregator::get_hash() const noexcept {
13836
8.00k
  ada_log("url_aggregator::get_hash");
13837
  // If this's URL's fragment is either null or the empty string, then return
13838
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
13839
8.00k
  if (components.hash_start == url_components::omitted) {
13840
6.43k
    return "";
13841
6.43k
  }
13842
1.57k
  if (buffer.size() - components.hash_start <= 1) {
13843
63
    return "";
13844
63
  }
13845
1.50k
  return helpers::substring(buffer, components.hash_start);
13846
1.57k
}
13847
13848
12.1k
[[nodiscard]] std::string_view url_aggregator::get_host() const noexcept {
13849
12.1k
  ada_log("url_aggregator::get_host");
13850
  // Technically, we should check if there is a hostname, but
13851
  // the code below works even if there isn't.
13852
  // if(!has_hostname()) { return ""; }
13853
12.1k
  size_t start = components.host_start;
13854
12.1k
  if (components.host_end > components.host_start &&
13855
12.1k
      buffer[components.host_start] == '@') {
13856
1.64k
    start++;
13857
1.64k
  }
13858
  // if we have an empty host, then the space between components.host_end and
13859
  // components.pathname_start may be occupied by /.
13860
12.1k
  if (start == components.host_end) {
13861
3.75k
    return std::string_view();
13862
3.75k
  }
13863
8.39k
  return helpers::substring(buffer, start, components.pathname_start);
13864
12.1k
}
13865
13866
43.5k
[[nodiscard]] std::string_view url_aggregator::get_hostname() const noexcept {
13867
43.5k
  ada_log("url_aggregator::get_hostname");
13868
  // Technically, we should check if there is a hostname, but
13869
  // the code below works even if there isn't.
13870
  // if(!has_hostname()) { return ""; }
13871
43.5k
  size_t start = components.host_start;
13872
  // So host_start is not where the host begins.
13873
43.5k
  if (components.host_end > components.host_start &&
13874
43.5k
      buffer[components.host_start] == '@') {
13875
4.39k
    start++;
13876
4.39k
  }
13877
43.5k
  return helpers::substring(buffer, start, components.host_end);
13878
43.5k
}
13879
13880
15.2k
[[nodiscard]] std::string_view url_aggregator::get_pathname() const noexcept {
13881
15.2k
  ada_log("url_aggregator::get_pathname pathname_start = ",
13882
15.2k
          components.pathname_start, " buffer.size() = ", buffer.size(),
13883
15.2k
          " components.search_start = ", components.search_start,
13884
15.2k
          " components.hash_start = ", components.hash_start);
13885
15.2k
  uint32_t ending_index = uint32_t(buffer.size());
13886
15.2k
  if (components.search_start != url_components::omitted) {
13887
1.77k
    ending_index = components.search_start;
13888
13.4k
  } else if (components.hash_start != url_components::omitted) {
13889
138
    ending_index = components.hash_start;
13890
138
  }
13891
15.2k
  return helpers::substring(buffer, components.pathname_start, ending_index);
13892
15.2k
}
13893
13894
9.09k
[[nodiscard]] std::string_view url_aggregator::get_search() const noexcept {
13895
9.09k
  ada_log("url_aggregator::get_search");
13896
  // If this's URL's query is either null or the empty string, then return the
13897
  // empty string. Return U+003F (?), followed by this's URL's query.
13898
9.09k
  if (components.search_start == url_components::omitted) {
13899
7.45k
    return "";
13900
7.45k
  }
13901
1.63k
  uint32_t ending_index = uint32_t(buffer.size());
13902
1.63k
  if (components.hash_start != url_components::omitted) {
13903
1.59k
    ending_index = components.hash_start;
13904
1.59k
  }
13905
1.63k
  if (ending_index - components.search_start <= 1) {
13906
108
    return "";
13907
108
  }
13908
1.53k
  return helpers::substring(buffer, components.search_start, ending_index);
13909
1.63k
}
13910
13911
15.4k
[[nodiscard]] std::string_view url_aggregator::get_protocol() const noexcept {
13912
15.4k
  ada_log("url_aggregator::get_protocol");
13913
15.4k
  return helpers::substring(buffer, 0, components.protocol_end);
13914
15.4k
}
13915
13916
0
[[nodiscard]] std::string ada::url_aggregator::to_string() const {
13917
0
  ada_log("url_aggregator::to_string buffer:", buffer, "[", buffer.size(),
13918
0
          " bytes]");
13919
0
  if (!is_valid) {
13920
0
    return "null";
13921
0
  }
13922
13923
0
  std::string answer;
13924
0
  auto back = std::back_insert_iterator(answer);
13925
0
  answer.append("{\n");
13926
13927
0
  answer.append("\t\"buffer\":\"");
13928
0
  helpers::encode_json(buffer, back);
13929
0
  answer.append("\",\n");
13930
13931
0
  answer.append("\t\"protocol\":\"");
13932
0
  helpers::encode_json(get_protocol(), back);
13933
0
  answer.append("\",\n");
13934
13935
0
  if (has_credentials()) {
13936
0
    answer.append("\t\"username\":\"");
13937
0
    helpers::encode_json(get_username(), back);
13938
0
    answer.append("\",\n");
13939
0
    answer.append("\t\"password\":\"");
13940
0
    helpers::encode_json(get_password(), back);
13941
0
    answer.append("\",\n");
13942
0
  }
13943
13944
0
  answer.append("\t\"host\":\"");
13945
0
  helpers::encode_json(get_host(), back);
13946
0
  answer.append("\",\n");
13947
13948
0
  answer.append("\t\"path\":\"");
13949
0
  helpers::encode_json(get_pathname(), back);
13950
0
  answer.append("\",\n");
13951
0
  answer.append("\t\"opaque path\":");
13952
0
  answer.append((has_opaque_path ? "true" : "false"));
13953
0
  answer.append(",\n");
13954
13955
0
  if (components.search_start != url_components::omitted) {
13956
0
    answer.append("\t\"query\":\"");
13957
0
    helpers::encode_json(get_search(), back);
13958
0
    answer.append("\",\n");
13959
0
  }
13960
0
  if (components.hash_start != url_components::omitted) {
13961
0
    answer.append("\t\"fragment\":\"");
13962
0
    helpers::encode_json(get_hash(), back);
13963
0
    answer.append("\",\n");
13964
0
  }
13965
13966
0
  auto convert_offset_to_string = [](uint32_t offset) -> std::string {
13967
0
    if (offset == url_components::omitted) {
13968
0
      return "null";
13969
0
    } else {
13970
0
      return std::to_string(offset);
13971
0
    }
13972
0
  };
13973
13974
0
  answer.append("\t\"protocol_end\":");
13975
0
  answer.append(convert_offset_to_string(components.protocol_end));
13976
0
  answer.append(",\n");
13977
13978
0
  answer.append("\t\"username_end\":");
13979
0
  answer.append(convert_offset_to_string(components.username_end));
13980
0
  answer.append(",\n");
13981
13982
0
  answer.append("\t\"host_start\":");
13983
0
  answer.append(convert_offset_to_string(components.host_start));
13984
0
  answer.append(",\n");
13985
13986
0
  answer.append("\t\"host_end\":");
13987
0
  answer.append(convert_offset_to_string(components.host_end));
13988
0
  answer.append(",\n");
13989
13990
0
  answer.append("\t\"port\":");
13991
0
  answer.append(convert_offset_to_string(components.port));
13992
0
  answer.append(",\n");
13993
13994
0
  answer.append("\t\"pathname_start\":");
13995
0
  answer.append(convert_offset_to_string(components.pathname_start));
13996
0
  answer.append(",\n");
13997
13998
0
  answer.append("\t\"search_start\":");
13999
0
  answer.append(convert_offset_to_string(components.search_start));
14000
0
  answer.append(",\n");
14001
14002
0
  answer.append("\t\"hash_start\":");
14003
0
  answer.append(convert_offset_to_string(components.hash_start));
14004
0
  answer.append("\n}");
14005
14006
0
  return answer;
14007
0
}
14008
14009
0
[[nodiscard]] bool url_aggregator::has_valid_domain() const noexcept {
14010
0
  if (components.host_start == components.host_end) {
14011
0
    return false;
14012
0
  }
14013
0
  return checkers::verify_dns_length(get_hostname());
14014
0
}
14015
14016
3.87k
bool url_aggregator::parse_ipv4(std::string_view input) {
14017
3.87k
  ada_log("parse_ipv4 ", input, "[", input.size(),
14018
3.87k
          " bytes], overlaps with buffer: ",
14019
3.87k
          helpers::overlaps(input, buffer) ? "yes" : "no");
14020
3.87k
  ADA_ASSERT_TRUE(validate());
14021
3.87k
  const bool trailing_dot = (input.back() == '.');
14022
3.87k
  if (trailing_dot) {
14023
44
    input.remove_suffix(1);
14024
44
  }
14025
3.87k
  size_t digit_count{0};
14026
3.87k
  int pure_decimal_count = 0;  // entries that are decimal
14027
3.87k
  uint64_t ipv4{0};
14028
  // we could unroll for better performance?
14029
5.14k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
14030
5.11k
    uint32_t
14031
5.11k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
14032
5.11k
    bool is_hex = checkers::has_hex_prefix(input);
14033
5.11k
    if (is_hex && ((input.length() == 2) ||
14034
1.31k
                   ((input.length() > 2) && (input[2] == '.')))) {
14035
      // special case
14036
134
      segment_result = 0;
14037
134
      input.remove_prefix(2);
14038
4.97k
    } else {
14039
4.97k
      std::from_chars_result r;
14040
4.97k
      if (is_hex) {
14041
1.18k
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
14042
1.18k
                            segment_result, 16);
14043
3.79k
      } else if ((input.length() >= 2) && input[0] == '0' &&
14044
3.79k
                 checkers::is_digit(input[1])) {
14045
496
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
14046
496
                            segment_result, 8);
14047
3.29k
      } else {
14048
3.29k
        pure_decimal_count++;
14049
3.29k
        r = std::from_chars(input.data(), input.data() + input.size(),
14050
3.29k
                            segment_result, 10);
14051
3.29k
      }
14052
4.97k
      if (r.ec != std::errc()) {
14053
742
        return is_valid = false;
14054
742
      }
14055
4.23k
      input.remove_prefix(r.ptr - input.data());
14056
4.23k
    }
14057
4.36k
    if (input.empty()) {
14058
      // We have the last value.
14059
      // At this stage, ipv4 contains digit_count*8 bits.
14060
      // So we have 32-digit_count*8 bits left.
14061
2.89k
      if (segment_result > (uint64_t(1) << (32 - digit_count * 8))) {
14062
15
        return is_valid = false;
14063
15
      }
14064
2.88k
      ipv4 <<= (32 - digit_count * 8);
14065
2.88k
      ipv4 |= segment_result;
14066
2.88k
      goto final;
14067
2.89k
    } else {
14068
      // There is more, so that the value must no be larger than 255
14069
      // and we must have a '.'.
14070
1.46k
      if ((segment_result > 255) || (input[0] != '.')) {
14071
198
        return is_valid = false;
14072
198
      }
14073
1.27k
      ipv4 <<= 8;
14074
1.27k
      ipv4 |= segment_result;
14075
1.27k
      input.remove_prefix(1);  // remove '.'
14076
1.27k
    }
14077
4.36k
  }
14078
36
  if ((digit_count != 4) || (!input.empty())) {
14079
36
    return is_valid = false;
14080
36
  }
14081
2.88k
final:
14082
2.88k
  ada_log("url_aggregator::parse_ipv4 completed ", get_href(),
14083
2.88k
          " host: ", get_host());
14084
14085
  // We could also check r.ptr to see where the parsing ended.
14086
2.88k
  if (pure_decimal_count == 4 && !trailing_dot) {
14087
    // The original input was already all decimal and we validated it. So we
14088
    // don't need to do anything.
14089
2.65k
  } else {
14090
    // Optimization opportunity: Get rid of unnecessary string return in ipv4
14091
    // serializer.
14092
    // TODO: This is likely a bug because it goes back update_base_hostname, not
14093
    // what we want to do.
14094
2.65k
    update_base_hostname(
14095
2.65k
        ada::serializers::ipv4(ipv4));  // We have to reserialize the address.
14096
2.65k
  }
14097
2.88k
  host_type = IPV4;
14098
2.88k
  ADA_ASSERT_TRUE(validate());
14099
2.88k
  return true;
14100
36
}
14101
14102
958
bool url_aggregator::parse_ipv6(std::string_view input) {
14103
  // TODO: Find a way to merge parse_ipv6 with url.cpp implementation.
14104
958
  ada_log("parse_ipv6 ", input, "[", input.size(), " bytes]");
14105
958
  ADA_ASSERT_TRUE(validate());
14106
958
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14107
958
  if (input.empty()) {
14108
59
    return is_valid = false;
14109
59
  }
14110
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
14111
899
  std::array<uint16_t, 8> address{};
14112
14113
  // Let pieceIndex be 0.
14114
899
  int piece_index = 0;
14115
14116
  // Let compress be null.
14117
899
  std::optional<int> compress{};
14118
14119
  // Let pointer be a pointer for input.
14120
899
  std::string_view::iterator pointer = input.begin();
14121
14122
  // If c is U+003A (:), then:
14123
899
  if (input[0] == ':') {
14124
    // If remaining does not start with U+003A (:), validation error, return
14125
    // failure.
14126
239
    if (input.size() == 1 || input[1] != ':') {
14127
29
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
14128
29
      return is_valid = false;
14129
29
    }
14130
14131
    // Increase pointer by 2.
14132
210
    pointer += 2;
14133
14134
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
14135
210
    compress = ++piece_index;
14136
210
  }
14137
14138
  // While c is not the EOF code point:
14139
2.64k
  while (pointer != input.end()) {
14140
    // If pieceIndex is 8, validation error, return failure.
14141
2.15k
    if (piece_index == 8) {
14142
8
      ada_log("parse_ipv6 piece_index == 8");
14143
8
      return is_valid = false;
14144
8
    }
14145
14146
    // If c is U+003A (:), then:
14147
2.15k
    if (*pointer == ':') {
14148
      // If compress is non-null, validation error, return failure.
14149
184
      if (compress.has_value()) {
14150
6
        ada_log("parse_ipv6 compress is non-null");
14151
6
        return is_valid = false;
14152
6
      }
14153
14154
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
14155
      // then continue.
14156
178
      pointer++;
14157
178
      compress = ++piece_index;
14158
178
      continue;
14159
184
    }
14160
14161
    // Let value and length be 0.
14162
1.96k
    uint16_t value = 0, length = 0;
14163
14164
    // While length is less than 4 and c is an ASCII hex digit,
14165
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
14166
    // increase pointer and length by 1.
14167
5.15k
    while (length < 4 && pointer != input.end() &&
14168
5.15k
           unicode::is_ascii_hex_digit(*pointer)) {
14169
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
14170
3.18k
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
14171
3.18k
      pointer++;
14172
3.18k
      length++;
14173
3.18k
    }
14174
14175
    // If c is U+002E (.), then:
14176
1.96k
    if (pointer != input.end() && *pointer == '.') {
14177
      // If length is 0, validation error, return failure.
14178
177
      if (length == 0) {
14179
8
        ada_log("parse_ipv6 length is 0");
14180
8
        return is_valid = false;
14181
8
      }
14182
14183
      // Decrease pointer by length.
14184
169
      pointer -= length;
14185
14186
      // If pieceIndex is greater than 6, validation error, return failure.
14187
169
      if (piece_index > 6) {
14188
6
        ada_log("parse_ipv6 piece_index > 6");
14189
6
        return is_valid = false;
14190
6
      }
14191
14192
      // Let numbersSeen be 0.
14193
163
      int numbers_seen = 0;
14194
14195
      // While c is not the EOF code point:
14196
504
      while (pointer != input.end()) {
14197
        // Let ipv4Piece be null.
14198
437
        std::optional<uint16_t> ipv4_piece{};
14199
14200
        // If numbersSeen is greater than 0, then:
14201
437
        if (numbers_seen > 0) {
14202
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
14203
          // pointer by 1.
14204
274
          if (*pointer == '.' && numbers_seen < 4) {
14205
250
            pointer++;
14206
250
          } else {
14207
            // Otherwise, validation error, return failure.
14208
24
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
14209
24
            return is_valid = false;
14210
24
          }
14211
274
        }
14212
14213
        // If c is not an ASCII digit, validation error, return failure.
14214
413
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
14215
45
          ada_log(
14216
45
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
14217
45
              "failure");
14218
45
          return is_valid = false;
14219
45
        }
14220
14221
        // While c is an ASCII digit:
14222
874
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
14223
          // Let number be c interpreted as decimal number.
14224
533
          int number = *pointer - '0';
14225
14226
          // If ipv4Piece is null, then set ipv4Piece to number.
14227
533
          if (!ipv4_piece.has_value()) {
14228
368
            ipv4_piece = number;
14229
368
          }
14230
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
14231
165
          else if (ipv4_piece == 0) {
14232
6
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
14233
6
            return is_valid = false;
14234
6
          }
14235
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
14236
159
          else {
14237
159
            ipv4_piece = *ipv4_piece * 10 + number;
14238
159
          }
14239
14240
          // If ipv4Piece is greater than 255, validation error, return failure.
14241
527
          if (ipv4_piece > 255) {
14242
21
            ada_log("parse_ipv6 ipv4_piece > 255");
14243
21
            return is_valid = false;
14244
21
          }
14245
14246
          // Increase pointer by 1.
14247
506
          pointer++;
14248
506
        }
14249
14250
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
14251
        // ipv4Piece.
14252
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
14253
341
        address[piece_index] =
14254
341
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
14255
14256
        // Increase numbersSeen by 1.
14257
341
        numbers_seen++;
14258
14259
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
14260
341
        if (numbers_seen == 2 || numbers_seen == 4) {
14261
148
          piece_index++;
14262
148
        }
14263
341
      }
14264
14265
      // If numbersSeen is not 4, validation error, return failure.
14266
67
      if (numbers_seen != 4) {
14267
20
        return is_valid = false;
14268
20
      }
14269
14270
      // Break.
14271
47
      break;
14272
67
    }
14273
    // Otherwise, if c is U+003A (:):
14274
1.79k
    else if ((pointer != input.end()) && (*pointer == ':')) {
14275
      // Increase pointer by 1.
14276
1.26k
      pointer++;
14277
14278
      // If c is the EOF code point, validation error, return failure.
14279
1.26k
      if (pointer == input.end()) {
14280
8
        ada_log(
14281
8
            "parse_ipv6 If c is the EOF code point, validation error, return "
14282
8
            "failure");
14283
8
        return is_valid = false;
14284
8
      }
14285
1.26k
    }
14286
    // Otherwise, if c is not the EOF code point, validation error, return
14287
    // failure.
14288
522
    else if (pointer != input.end()) {
14289
181
      ada_log(
14290
181
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
14291
181
          "error, return failure");
14292
181
      return is_valid = false;
14293
181
    }
14294
14295
    // Set address[pieceIndex] to value.
14296
1.60k
    address[piece_index] = value;
14297
14298
    // Increase pieceIndex by 1.
14299
1.60k
    piece_index++;
14300
1.60k
  }
14301
14302
  // If compress is non-null, then:
14303
537
  if (compress.has_value()) {
14304
    // Let swaps be pieceIndex - compress.
14305
370
    int swaps = piece_index - *compress;
14306
14307
    // Set pieceIndex to 7.
14308
370
    piece_index = 7;
14309
14310
    // While pieceIndex is not 0 and swaps is greater than 0,
14311
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
14312
    // decrease both pieceIndex and swaps by 1.
14313
960
    while (piece_index != 0 && swaps > 0) {
14314
590
      std::swap(address[piece_index], address[*compress + swaps - 1]);
14315
590
      piece_index--;
14316
590
      swaps--;
14317
590
    }
14318
370
  }
14319
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
14320
  // return failure.
14321
167
  else if (piece_index != 8) {
14322
116
    ada_log(
14323
116
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
14324
116
        "error, return failure");
14325
116
    return is_valid = false;
14326
116
  }
14327
  // TODO: Optimization opportunity: Get rid of unnecessary string creation.
14328
  // TODO: This is likely a bug because it goes back update_base_hostname, not
14329
  // what we want to do.
14330
421
  update_base_hostname(ada::serializers::ipv6(address));
14331
421
  ada_log("parse_ipv6 ", get_hostname());
14332
421
  ADA_ASSERT_TRUE(validate());
14333
421
  host_type = IPV6;
14334
421
  return true;
14335
537
}
14336
14337
1.17k
bool url_aggregator::parse_opaque_host(std::string_view input) {
14338
1.17k
  ada_log("parse_opaque_host ", input, "[", input.size(), " bytes]");
14339
1.17k
  ADA_ASSERT_TRUE(validate());
14340
1.17k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14341
1.17k
  if (std::any_of(input.begin(), input.end(),
14342
1.17k
                  ada::unicode::is_forbidden_host_code_point)) {
14343
123
    return is_valid = false;
14344
123
  }
14345
14346
  // Return the result of running UTF-8 percent-encode on input using the C0
14347
  // control percent-encode set.
14348
1.05k
  size_t idx = ada::unicode::percent_encode_index(
14349
1.05k
      input, character_sets::C0_CONTROL_PERCENT_ENCODE);
14350
1.05k
  if (idx == input.size()) {
14351
505
    update_base_hostname(input);
14352
550
  } else {
14353
    // We only create a temporary string if we need to.
14354
550
    update_base_hostname(ada::unicode::percent_encode(
14355
550
        input, character_sets::C0_CONTROL_PERCENT_ENCODE, idx));
14356
550
  }
14357
1.05k
  ADA_ASSERT_TRUE(validate());
14358
1.05k
  return true;
14359
1.17k
}
14360
14361
0
[[nodiscard]] std::string url_aggregator::to_diagram() const {
14362
0
  if (!is_valid) {
14363
0
    return "invalid";
14364
0
  }
14365
0
  std::string answer;
14366
0
  answer.append(buffer);
14367
0
  answer.append(" [");
14368
0
  answer.append(std::to_string(buffer.size()));
14369
0
  answer.append(" bytes]");
14370
0
  answer.append("\n");
14371
  // first line
14372
0
  std::string line1;
14373
0
  line1.resize(buffer.size(), ' ');
14374
0
  if (components.hash_start != url_components::omitted) {
14375
0
    line1[components.hash_start] = '|';
14376
0
  }
14377
0
  if (components.search_start != url_components::omitted) {
14378
0
    line1[components.search_start] = '|';
14379
0
  }
14380
0
  if (components.pathname_start != buffer.size()) {
14381
0
    line1[components.pathname_start] = '|';
14382
0
  }
14383
0
  if (components.host_end != buffer.size()) {
14384
0
    line1[components.host_end] = '|';
14385
0
  }
14386
0
  if (components.host_start != buffer.size()) {
14387
0
    line1[components.host_start] = '|';
14388
0
  }
14389
0
  if (components.username_end != buffer.size()) {
14390
0
    line1[components.username_end] = '|';
14391
0
  }
14392
0
  if (components.protocol_end != buffer.size()) {
14393
0
    line1[components.protocol_end] = '|';
14394
0
  }
14395
0
  answer.append(line1);
14396
0
  answer.append("\n");
14397
14398
0
  std::string line2 = line1;
14399
0
  if (components.hash_start != url_components::omitted) {
14400
0
    line2[components.hash_start] = '`';
14401
0
    line1[components.hash_start] = ' ';
14402
14403
0
    for (size_t i = components.hash_start + 1; i < line2.size(); i++) {
14404
0
      line2[i] = '-';
14405
0
    }
14406
0
    line2.append(" hash_start");
14407
0
    answer.append(line2);
14408
0
    answer.append("\n");
14409
0
  }
14410
14411
0
  std::string line3 = line1;
14412
0
  if (components.search_start != url_components::omitted) {
14413
0
    line3[components.search_start] = '`';
14414
0
    line1[components.search_start] = ' ';
14415
14416
0
    for (size_t i = components.search_start + 1; i < line3.size(); i++) {
14417
0
      line3[i] = '-';
14418
0
    }
14419
0
    line3.append(" search_start ");
14420
0
    line3.append(std::to_string(components.search_start));
14421
0
    answer.append(line3);
14422
0
    answer.append("\n");
14423
0
  }
14424
14425
0
  std::string line4 = line1;
14426
0
  if (components.pathname_start != buffer.size()) {
14427
0
    line4[components.pathname_start] = '`';
14428
0
    line1[components.pathname_start] = ' ';
14429
0
    for (size_t i = components.pathname_start + 1; i < line4.size(); i++) {
14430
0
      line4[i] = '-';
14431
0
    }
14432
0
    line4.append(" pathname_start ");
14433
0
    line4.append(std::to_string(components.pathname_start));
14434
0
    answer.append(line4);
14435
0
    answer.append("\n");
14436
0
  }
14437
14438
0
  std::string line5 = line1;
14439
0
  if (components.host_end != buffer.size()) {
14440
0
    line5[components.host_end] = '`';
14441
0
    line1[components.host_end] = ' ';
14442
14443
0
    for (size_t i = components.host_end + 1; i < line5.size(); i++) {
14444
0
      line5[i] = '-';
14445
0
    }
14446
0
    line5.append(" host_end ");
14447
0
    line5.append(std::to_string(components.host_end));
14448
0
    answer.append(line5);
14449
0
    answer.append("\n");
14450
0
  }
14451
14452
0
  std::string line6 = line1;
14453
0
  if (components.host_start != buffer.size()) {
14454
0
    line6[components.host_start] = '`';
14455
0
    line1[components.host_start] = ' ';
14456
14457
0
    for (size_t i = components.host_start + 1; i < line6.size(); i++) {
14458
0
      line6[i] = '-';
14459
0
    }
14460
0
    line6.append(" host_start ");
14461
0
    line6.append(std::to_string(components.host_start));
14462
0
    answer.append(line6);
14463
0
    answer.append("\n");
14464
0
  }
14465
14466
0
  std::string line7 = line1;
14467
0
  if (components.username_end != buffer.size()) {
14468
0
    line7[components.username_end] = '`';
14469
0
    line1[components.username_end] = ' ';
14470
14471
0
    for (size_t i = components.username_end + 1; i < line7.size(); i++) {
14472
0
      line7[i] = '-';
14473
0
    }
14474
0
    line7.append(" username_end ");
14475
0
    line7.append(std::to_string(components.username_end));
14476
0
    answer.append(line7);
14477
0
    answer.append("\n");
14478
0
  }
14479
14480
0
  std::string line8 = line1;
14481
0
  if (components.protocol_end != buffer.size()) {
14482
0
    line8[components.protocol_end] = '`';
14483
0
    line1[components.protocol_end] = ' ';
14484
14485
0
    for (size_t i = components.protocol_end + 1; i < line8.size(); i++) {
14486
0
      line8[i] = '-';
14487
0
    }
14488
0
    line8.append(" protocol_end ");
14489
0
    line8.append(std::to_string(components.protocol_end));
14490
0
    answer.append(line8);
14491
0
    answer.append("\n");
14492
0
  }
14493
14494
0
  if (components.hash_start == url_components::omitted) {
14495
0
    answer.append("note: hash omitted\n");
14496
0
  }
14497
0
  if (components.search_start == url_components::omitted) {
14498
0
    answer.append("note: search omitted\n");
14499
0
  }
14500
0
  if (components.protocol_end > buffer.size()) {
14501
0
    answer.append("warning: protocol_end overflows\n");
14502
0
  }
14503
0
  if (components.username_end > buffer.size()) {
14504
0
    answer.append("warning: username_end overflows\n");
14505
0
  }
14506
0
  if (components.host_start > buffer.size()) {
14507
0
    answer.append("warning: host_start overflows\n");
14508
0
  }
14509
0
  if (components.host_end > buffer.size()) {
14510
0
    answer.append("warning: host_end overflows\n");
14511
0
  }
14512
0
  if (components.pathname_start > buffer.size()) {
14513
0
    answer.append("warning: pathname_start overflows\n");
14514
0
  }
14515
0
  return answer;
14516
0
}
14517
14518
0
[[nodiscard]] bool url_aggregator::validate() const noexcept {
14519
0
  if (!is_valid) {
14520
0
    return true;
14521
0
  }
14522
0
  if (!components.check_offset_consistency()) {
14523
0
    ada_log("url_aggregator::validate inconsistent components \n",
14524
0
            to_diagram());
14525
0
    return false;
14526
0
  }
14527
  // We have a credible components struct, but let us investivate more
14528
  // carefully:
14529
  /**
14530
   * https://user:pass@example.com:1234/foo/bar?baz#quux
14531
   *       |     |    |          | ^^^^|       |   |
14532
   *       |     |    |          | |   |       |   `----- hash_start
14533
   *       |     |    |          | |   |       `--------- search_start
14534
   *       |     |    |          | |   `----------------- pathname_start
14535
   *       |     |    |          | `--------------------- port
14536
   *       |     |    |          `----------------------- host_end
14537
   *       |     |    `---------------------------------- host_start
14538
   *       |     `--------------------------------------- username_end
14539
   *       `--------------------------------------------- protocol_end
14540
   */
14541
0
  if (components.protocol_end == url_components::omitted) {
14542
0
    ada_log("url_aggregator::validate omitted protocol_end \n", to_diagram());
14543
0
    return false;
14544
0
  }
14545
0
  if (components.username_end == url_components::omitted) {
14546
0
    ada_log("url_aggregator::validate omitted username_end \n", to_diagram());
14547
0
    return false;
14548
0
  }
14549
0
  if (components.host_start == url_components::omitted) {
14550
0
    ada_log("url_aggregator::validate omitted host_start \n", to_diagram());
14551
0
    return false;
14552
0
  }
14553
0
  if (components.host_end == url_components::omitted) {
14554
0
    ada_log("url_aggregator::validate omitted host_end \n", to_diagram());
14555
0
    return false;
14556
0
  }
14557
0
  if (components.pathname_start == url_components::omitted) {
14558
0
    ada_log("url_aggregator::validate omitted pathname_start \n", to_diagram());
14559
0
    return false;
14560
0
  }
14561
14562
0
  if (components.protocol_end > buffer.size()) {
14563
0
    ada_log("url_aggregator::validate protocol_end overflow \n", to_diagram());
14564
0
    return false;
14565
0
  }
14566
0
  if (components.username_end > buffer.size()) {
14567
0
    ada_log("url_aggregator::validate username_end overflow \n", to_diagram());
14568
0
    return false;
14569
0
  }
14570
0
  if (components.host_start > buffer.size()) {
14571
0
    ada_log("url_aggregator::validate host_start overflow \n", to_diagram());
14572
0
    return false;
14573
0
  }
14574
0
  if (components.host_end > buffer.size()) {
14575
0
    ada_log("url_aggregator::validate host_end overflow \n", to_diagram());
14576
0
    return false;
14577
0
  }
14578
0
  if (components.pathname_start > buffer.size()) {
14579
0
    ada_log("url_aggregator::validate pathname_start overflow \n",
14580
0
            to_diagram());
14581
0
    return false;
14582
0
  }
14583
14584
0
  if (components.protocol_end > 0) {
14585
0
    if (buffer[components.protocol_end - 1] != ':') {
14586
0
      ada_log(
14587
0
          "url_aggregator::validate missing : at the end of the protocol \n",
14588
0
          to_diagram());
14589
0
      return false;
14590
0
    }
14591
0
  }
14592
14593
0
  if (components.username_end != buffer.size() &&
14594
0
      components.username_end > components.protocol_end + 2) {
14595
0
    if (buffer[components.username_end] != ':' &&
14596
0
        buffer[components.username_end] != '@') {
14597
0
      ada_log(
14598
0
          "url_aggregator::validate missing : or @ at the end of the username "
14599
0
          "\n",
14600
0
          to_diagram());
14601
0
      return false;
14602
0
    }
14603
0
  }
14604
14605
0
  if (components.host_start != buffer.size()) {
14606
0
    if (components.host_start > components.username_end) {
14607
0
      if (buffer[components.host_start] != '@') {
14608
0
        ada_log(
14609
0
            "url_aggregator::validate missing @ at the end of the password \n",
14610
0
            to_diagram());
14611
0
        return false;
14612
0
      }
14613
0
    } else if (components.host_start == components.username_end &&
14614
0
               components.host_end > components.host_start) {
14615
0
      if (components.host_start == components.protocol_end + 2) {
14616
0
        if (buffer[components.protocol_end] != '/' ||
14617
0
            buffer[components.protocol_end + 1] != '/') {
14618
0
          ada_log(
14619
0
              "url_aggregator::validate missing // between protocol and host "
14620
0
              "\n",
14621
0
              to_diagram());
14622
0
          return false;
14623
0
        }
14624
0
      } else {
14625
0
        if (components.host_start > components.protocol_end &&
14626
0
            buffer[components.host_start] != '@') {
14627
0
          ada_log(
14628
0
              "url_aggregator::validate missing @ at the end of the username "
14629
0
              "\n",
14630
0
              to_diagram());
14631
0
          return false;
14632
0
        }
14633
0
      }
14634
0
    } else {
14635
0
      if (components.host_end != components.host_start) {
14636
0
        ada_log("url_aggregator::validate expected omitted host \n",
14637
0
                to_diagram());
14638
0
        return false;
14639
0
      }
14640
0
    }
14641
0
  }
14642
0
  if (components.host_end != buffer.size() &&
14643
0
      components.pathname_start > components.host_end) {
14644
0
    if (components.pathname_start == components.host_end + 2 &&
14645
0
        buffer[components.host_end] == '/' &&
14646
0
        buffer[components.host_end + 1] == '.') {
14647
0
      if (components.pathname_start + 1 >= buffer.size() ||
14648
0
          buffer[components.pathname_start] != '/' ||
14649
0
          buffer[components.pathname_start + 1] != '/') {
14650
0
        ada_log(
14651
0
            "url_aggregator::validate expected the path to begin with // \n",
14652
0
            to_diagram());
14653
0
        return false;
14654
0
      }
14655
0
    } else if (buffer[components.host_end] != ':') {
14656
0
      ada_log("url_aggregator::validate missing : at the port \n",
14657
0
              to_diagram());
14658
0
      return false;
14659
0
    }
14660
0
  }
14661
0
  if (components.pathname_start != buffer.size() &&
14662
0
      components.pathname_start < components.search_start &&
14663
0
      components.pathname_start < components.hash_start && !has_opaque_path) {
14664
0
    if (buffer[components.pathname_start] != '/') {
14665
0
      ada_log("url_aggregator::validate missing / at the path \n",
14666
0
              to_diagram());
14667
0
      return false;
14668
0
    }
14669
0
  }
14670
0
  if (components.search_start != url_components::omitted) {
14671
0
    if (buffer[components.search_start] != '?') {
14672
0
      ada_log("url_aggregator::validate missing ? at the search \n",
14673
0
              to_diagram());
14674
0
      return false;
14675
0
    }
14676
0
  }
14677
0
  if (components.hash_start != url_components::omitted) {
14678
0
    if (buffer[components.hash_start] != '#') {
14679
0
      ada_log("url_aggregator::validate missing # at the hash \n",
14680
0
              to_diagram());
14681
0
      return false;
14682
0
    }
14683
0
  }
14684
14685
0
  return true;
14686
0
}
14687
14688
57
void url_aggregator::delete_dash_dot() {
14689
57
  ada_log("url_aggregator::delete_dash_dot");
14690
57
  ADA_ASSERT_TRUE(validate());
14691
57
  ADA_ASSERT_TRUE(has_dash_dot());
14692
57
  buffer.erase(components.host_end, 2);
14693
57
  components.pathname_start -= 2;
14694
57
  if (components.search_start != url_components::omitted) {
14695
18
    components.search_start -= 2;
14696
18
  }
14697
57
  if (components.hash_start != url_components::omitted) {
14698
27
    components.hash_start -= 2;
14699
27
  }
14700
57
  ADA_ASSERT_TRUE(validate());
14701
57
  ADA_ASSERT_TRUE(!has_dash_dot());
14702
57
}
14703
14704
8.34k
inline void url_aggregator::consume_prepared_path(std::string_view input) {
14705
8.34k
  ada_log("url_aggregator::consume_prepared_path ", input);
14706
  /***
14707
   * This is largely duplicated code from helpers::parse_prepared_path, which is
14708
   * unfortunate. This particular function is nearly identical, except that it
14709
   * is a method on url_aggregator. The idea is that the trivial path (which is
14710
   * very common) merely appends to the buffer. This is the same trivial path as
14711
   * with helpers::parse_prepared_path, except that we have the additional check
14712
   * for is_at_path(). Otherwise, we grab a copy of the current path and we
14713
   * modify it, and then insert it back into the buffer.
14714
   */
14715
8.34k
  uint8_t accumulator = checkers::path_signature(input);
14716
  // Let us first detect a trivial case.
14717
  // If it is special, we check that we have no dot, no %,  no \ and no
14718
  // character needing percent encoding. Otherwise, we check that we have no %,
14719
  // no dot, and no character needing percent encoding.
14720
8.34k
  constexpr uint8_t need_encoding = 1;
14721
8.34k
  constexpr uint8_t backslash_char = 2;
14722
8.34k
  constexpr uint8_t dot_char = 4;
14723
8.34k
  constexpr uint8_t percent_char = 8;
14724
8.34k
  bool special = type != ada::scheme::NOT_SPECIAL;
14725
8.34k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
14726
8.34k
                                      checkers::is_windows_drive_letter(input));
14727
8.34k
  bool trivial_path =
14728
8.34k
      (special ? (accumulator == 0)
14729
8.34k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
14730
3.66k
                  0)) &&
14731
8.34k
      (!may_need_slow_file_handling);
14732
8.34k
  if (accumulator == dot_char && !may_need_slow_file_handling) {
14733
    // '4' means that we have at least one dot, but nothing that requires
14734
    // percent encoding or decoding. The only part that is not trivial is
14735
    // that we may have single dots and double dots path segments.
14736
    // If we have such segments, then we either have a path that begins
14737
    // with '.' (easy to check), or we have the sequence './'.
14738
    // Note: input cannot be empty, it must at least contain one character ('.')
14739
    // Note: we know that '\' is not present.
14740
968
    if (input[0] != '.') {
14741
473
      size_t slashdot = input.find("/.");
14742
473
      if (slashdot == std::string_view::npos) {  // common case
14743
106
        trivial_path = true;
14744
367
      } else {  // uncommon
14745
        // only three cases matter: /./, /.. or a final /
14746
367
        trivial_path =
14747
367
            !(slashdot + 2 == input.size() || input[slashdot + 2] == '.' ||
14748
367
              input[slashdot + 2] == '/');
14749
367
      }
14750
473
    }
14751
968
  }
14752
8.34k
  if (trivial_path && is_at_path()) {
14753
4.95k
    ada_log("parse_path trivial");
14754
4.95k
    buffer += '/';
14755
4.95k
    buffer += input;
14756
4.95k
    return;
14757
4.95k
  }
14758
3.38k
  std::string path = std::string(get_pathname());
14759
  // We are going to need to look a bit at the path, but let us see if we can
14760
  // ignore percent encoding *and* backslashes *and* percent characters.
14761
  // Except for the trivial case, this is likely to capture 99% of paths out
14762
  // there.
14763
3.38k
  bool fast_path =
14764
3.38k
      (special &&
14765
3.38k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
14766
3.38k
      (type != ada::scheme::type::FILE);
14767
3.38k
  if (fast_path) {
14768
539
    ada_log("parse_prepared_path fast");
14769
    // Here we don't need to worry about \ or percent encoding.
14770
    // We also do not have a file protocol. We might have dots, however,
14771
    // but dots must as appear as '.', and they cannot be encoded because
14772
    // the symbol '%' is not present.
14773
539
    size_t previous_location = 0;  // We start at 0.
14774
3.96k
    do {
14775
3.96k
      size_t new_location = input.find('/', previous_location);
14776
      // std::string_view path_view = input;
14777
      //  We process the last segment separately:
14778
3.96k
      if (new_location == std::string_view::npos) {
14779
539
        std::string_view path_view = input.substr(previous_location);
14780
539
        if (path_view == "..") {  // The path ends with ..
14781
          // e.g., if you receive ".." with an empty path, you go to "/".
14782
68
          if (path.empty()) {
14783
24
            path = '/';
14784
24
            update_base_pathname(path);
14785
24
            return;
14786
24
          }
14787
          // Fast case where we have nothing to do:
14788
44
          if (path.back() == '/') {
14789
21
            update_base_pathname(path);
14790
21
            return;
14791
21
          }
14792
          // If you have the path "/joe/myfriend",
14793
          // then you delete 'myfriend'.
14794
23
          path.resize(path.rfind('/') + 1);
14795
23
          update_base_pathname(path);
14796
23
          return;
14797
44
        }
14798
471
        path += '/';
14799
471
        if (path_view != ".") {
14800
345
          path.append(path_view);
14801
345
        }
14802
471
        update_base_pathname(path);
14803
471
        return;
14804
3.42k
      } else {
14805
        // This is a non-final segment.
14806
3.42k
        std::string_view path_view =
14807
3.42k
            input.substr(previous_location, new_location - previous_location);
14808
3.42k
        previous_location = new_location + 1;
14809
3.42k
        if (path_view == "..") {
14810
668
          size_t last_delimiter = path.rfind('/');
14811
668
          if (last_delimiter != std::string::npos) {
14812
350
            path.erase(last_delimiter);
14813
350
          }
14814
2.76k
        } else if (path_view != ".") {
14815
2.37k
          path += '/';
14816
2.37k
          path.append(path_view);
14817
2.37k
        }
14818
3.42k
      }
14819
3.96k
    } while (true);
14820
2.84k
  } else {
14821
2.84k
    ada_log("parse_path slow");
14822
    // we have reached the general case
14823
2.84k
    bool needs_percent_encoding = (accumulator & 1);
14824
2.84k
    std::string path_buffer_tmp;
14825
21.7k
    do {
14826
21.7k
      size_t location = (special && (accumulator & 2))
14827
21.7k
                            ? input.find_first_of("/\\")
14828
21.7k
                            : input.find('/');
14829
21.7k
      std::string_view path_view = input;
14830
21.7k
      if (location != std::string_view::npos) {
14831
18.8k
        path_view.remove_suffix(path_view.size() - location);
14832
18.8k
        input.remove_prefix(location + 1);
14833
18.8k
      }
14834
      // path_buffer is either path_view or it might point at a percent encoded
14835
      // temporary string.
14836
21.7k
      std::string_view path_buffer =
14837
21.7k
          (needs_percent_encoding &&
14838
21.7k
           ada::unicode::percent_encode<false>(
14839
12.3k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
14840
21.7k
              ? path_buffer_tmp
14841
21.7k
              : path_view;
14842
21.7k
      if (unicode::is_double_dot_path_segment(path_buffer)) {
14843
4.85k
        if ((helpers::shorten_path(path, type) || special) &&
14844
4.85k
            location == std::string_view::npos) {
14845
268
          path += '/';
14846
268
        }
14847
16.8k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
14848
16.8k
                 (location == std::string_view::npos)) {
14849
117
        path += '/';
14850
117
      }
14851
      // Otherwise, if path_buffer is not a single-dot path segment, then:
14852
16.7k
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
14853
        // If url's scheme is "file", url's path is empty, and path_buffer is a
14854
        // Windows drive letter, then replace the second code point in
14855
        // path_buffer with U+003A (:).
14856
15.4k
        if (type == ada::scheme::type::FILE && path.empty() &&
14857
15.4k
            checkers::is_windows_drive_letter(path_buffer)) {
14858
128
          path += '/';
14859
128
          path += path_buffer[0];
14860
128
          path += ':';
14861
128
          path_buffer.remove_prefix(2);
14862
128
          path.append(path_buffer);
14863
15.2k
        } else {
14864
          // Append path_buffer to url's path.
14865
15.2k
          path += '/';
14866
15.2k
          path.append(path_buffer);
14867
15.2k
        }
14868
15.4k
      }
14869
21.7k
      if (location == std::string_view::npos) {
14870
2.84k
        update_base_pathname(path);
14871
2.84k
        return;
14872
2.84k
      }
14873
21.7k
    } while (true);
14874
2.84k
  }
14875
3.38k
}
14876
}  // namespace ada
14877
/* end file src/url_aggregator.cpp */
14878
/* begin file src/ada_c.cpp */
14879
14880
0
ada::result<ada::url_aggregator>& get_instance(void* result) noexcept {
14881
0
  return *(ada::result<ada::url_aggregator>*)result;
14882
0
}
14883
14884
extern "C" {
14885
typedef void* ada_url;
14886
typedef void* ada_url_search_params;
14887
typedef void* ada_strings;
14888
typedef void* ada_url_search_params_keys_iter;
14889
typedef void* ada_url_search_params_values_iter;
14890
typedef void* ada_url_search_params_entries_iter;
14891
14892
struct ada_string {
14893
  const char* data;
14894
  size_t length;
14895
};
14896
14897
struct ada_owned_string {
14898
  const char* data;
14899
  size_t length;
14900
};
14901
14902
struct ada_string_pair {
14903
  ada_string key;
14904
  ada_string value;
14905
};
14906
14907
0
ada_string ada_string_create(const char* data, size_t length) {
14908
0
  ada_string out{};
14909
0
  out.data = data;
14910
0
  out.length = length;
14911
0
  return out;
14912
0
}
14913
14914
struct ada_url_components {
14915
  /*
14916
   * By using 32-bit integers, we implicitly assume that the URL string
14917
   * cannot exceed 4 GB.
14918
   *
14919
   * https://user:pass@example.com:1234/foo/bar?baz#quux
14920
   *       |     |    |          | ^^^^|       |   |
14921
   *       |     |    |          | |   |       |   `----- hash_start
14922
   *       |     |    |          | |   |       `--------- search_start
14923
   *       |     |    |          | |   `----------------- pathname_start
14924
   *       |     |    |          | `--------------------- port
14925
   *       |     |    |          `----------------------- host_end
14926
   *       |     |    `---------------------------------- host_start
14927
   *       |     `--------------------------------------- username_end
14928
   *       `--------------------------------------------- protocol_end
14929
   */
14930
  uint32_t protocol_end;
14931
  /**
14932
   * Username end is not `omitted` by default (-1) to make username and password
14933
   * getters less costly to implement.
14934
   */
14935
  uint32_t username_end;
14936
  uint32_t host_start;
14937
  uint32_t host_end;
14938
  uint32_t port;
14939
  uint32_t pathname_start;
14940
  uint32_t search_start;
14941
  uint32_t hash_start;
14942
};
14943
14944
0
ada_url ada_parse(const char* input, size_t length) noexcept {
14945
0
  return new ada::result<ada::url_aggregator>(
14946
0
      ada::parse<ada::url_aggregator>(std::string_view(input, length)));
14947
0
}
14948
14949
ada_url ada_parse_with_base(const char* input, size_t input_length,
14950
0
                            const char* base, size_t base_length) noexcept {
14951
0
  auto base_out =
14952
0
      ada::parse<ada::url_aggregator>(std::string_view(base, base_length));
14953
14954
0
  if (!base_out) {
14955
0
    return new ada::result<ada::url_aggregator>(base_out);
14956
0
  }
14957
14958
0
  return new ada::result<ada::url_aggregator>(ada::parse<ada::url_aggregator>(
14959
0
      std::string_view(input, input_length), &base_out.value()));
14960
0
}
14961
14962
0
bool ada_can_parse(const char* input, size_t length) noexcept {
14963
0
  return ada::can_parse(std::string_view(input, length));
14964
0
}
14965
14966
bool ada_can_parse_with_base(const char* input, size_t input_length,
14967
0
                             const char* base, size_t base_length) noexcept {
14968
0
  auto base_view = std::string_view(base, base_length);
14969
0
  return ada::can_parse(std::string_view(input, input_length), &base_view);
14970
0
}
14971
14972
0
void ada_free(ada_url result) noexcept {
14973
0
  ada::result<ada::url_aggregator>* r =
14974
0
      (ada::result<ada::url_aggregator>*)result;
14975
0
  delete r;
14976
0
}
14977
14978
0
ada_url ada_copy(ada_url input) noexcept {
14979
0
  ada::result<ada::url_aggregator>& r = get_instance(input);
14980
0
  return new ada::result<ada::url_aggregator>(r);
14981
0
}
14982
14983
0
bool ada_is_valid(ada_url result) noexcept {
14984
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
14985
0
  return r.has_value();
14986
0
}
14987
14988
// caller must free the result with ada_free_owned_string
14989
0
ada_owned_string ada_get_origin(ada_url result) noexcept {
14990
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
14991
0
  ada_owned_string owned;
14992
0
  if (!r) {
14993
0
    owned.data = nullptr;
14994
0
    owned.length = 0;
14995
0
    return owned;
14996
0
  }
14997
0
  std::string out = r->get_origin();
14998
0
  owned.length = out.size();
14999
0
  owned.data = new char[owned.length];
15000
0
  memcpy((void*)owned.data, out.data(), owned.length);
15001
0
  return owned;
15002
0
}
15003
15004
0
void ada_free_owned_string(ada_owned_string owned) noexcept {
15005
0
  delete[] owned.data;
15006
0
  owned.data = nullptr;
15007
0
  owned.length = 0;
15008
0
}
15009
15010
0
ada_string ada_get_href(ada_url result) noexcept {
15011
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15012
0
  if (!r) {
15013
0
    return ada_string_create(NULL, 0);
15014
0
  }
15015
0
  std::string_view out = r->get_href();
15016
0
  return ada_string_create(out.data(), out.length());
15017
0
}
15018
15019
0
ada_string ada_get_username(ada_url result) noexcept {
15020
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15021
0
  if (!r) {
15022
0
    return ada_string_create(NULL, 0);
15023
0
  }
15024
0
  std::string_view out = r->get_username();
15025
0
  return ada_string_create(out.data(), out.length());
15026
0
}
15027
15028
0
ada_string ada_get_password(ada_url result) noexcept {
15029
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15030
0
  if (!r) {
15031
0
    return ada_string_create(NULL, 0);
15032
0
  }
15033
0
  std::string_view out = r->get_password();
15034
0
  return ada_string_create(out.data(), out.length());
15035
0
}
15036
15037
0
ada_string ada_get_port(ada_url result) noexcept {
15038
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15039
0
  if (!r) {
15040
0
    return ada_string_create(NULL, 0);
15041
0
  }
15042
0
  std::string_view out = r->get_port();
15043
0
  return ada_string_create(out.data(), out.length());
15044
0
}
15045
15046
0
ada_string ada_get_hash(ada_url result) noexcept {
15047
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15048
0
  if (!r) {
15049
0
    return ada_string_create(NULL, 0);
15050
0
  }
15051
0
  std::string_view out = r->get_hash();
15052
0
  return ada_string_create(out.data(), out.length());
15053
0
}
15054
15055
0
ada_string ada_get_host(ada_url result) noexcept {
15056
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15057
0
  if (!r) {
15058
0
    return ada_string_create(NULL, 0);
15059
0
  }
15060
0
  std::string_view out = r->get_host();
15061
0
  return ada_string_create(out.data(), out.length());
15062
0
}
15063
15064
0
ada_string ada_get_hostname(ada_url result) noexcept {
15065
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15066
0
  if (!r) {
15067
0
    return ada_string_create(NULL, 0);
15068
0
  }
15069
0
  std::string_view out = r->get_hostname();
15070
0
  return ada_string_create(out.data(), out.length());
15071
0
}
15072
15073
0
ada_string ada_get_pathname(ada_url result) noexcept {
15074
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15075
0
  if (!r) {
15076
0
    return ada_string_create(NULL, 0);
15077
0
  }
15078
0
  std::string_view out = r->get_pathname();
15079
0
  return ada_string_create(out.data(), out.length());
15080
0
}
15081
15082
0
ada_string ada_get_search(ada_url result) noexcept {
15083
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15084
0
  if (!r) {
15085
0
    return ada_string_create(NULL, 0);
15086
0
  }
15087
0
  std::string_view out = r->get_search();
15088
0
  return ada_string_create(out.data(), out.length());
15089
0
}
15090
15091
0
ada_string ada_get_protocol(ada_url result) noexcept {
15092
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15093
0
  if (!r) {
15094
0
    return ada_string_create(NULL, 0);
15095
0
  }
15096
0
  std::string_view out = r->get_protocol();
15097
0
  return ada_string_create(out.data(), out.length());
15098
0
}
15099
15100
0
uint8_t ada_get_host_type(ada_url result) noexcept {
15101
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15102
0
  if (!r) {
15103
0
    return 0;
15104
0
  }
15105
0
  return r->host_type;
15106
0
}
15107
15108
0
uint8_t ada_get_scheme_type(ada_url result) noexcept {
15109
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15110
0
  if (!r) {
15111
0
    return 0;
15112
0
  }
15113
0
  return r->type;
15114
0
}
15115
15116
0
bool ada_set_href(ada_url result, const char* input, size_t length) noexcept {
15117
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15118
0
  if (!r) {
15119
0
    return false;
15120
0
  }
15121
0
  return r->set_href(std::string_view(input, length));
15122
0
}
15123
15124
0
bool ada_set_host(ada_url result, const char* input, size_t length) noexcept {
15125
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15126
0
  if (!r) {
15127
0
    return false;
15128
0
  }
15129
0
  return r->set_host(std::string_view(input, length));
15130
0
}
15131
15132
bool ada_set_hostname(ada_url result, const char* input,
15133
0
                      size_t length) noexcept {
15134
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15135
0
  if (!r) {
15136
0
    return false;
15137
0
  }
15138
0
  return r->set_hostname(std::string_view(input, length));
15139
0
}
15140
15141
bool ada_set_protocol(ada_url result, const char* input,
15142
0
                      size_t length) noexcept {
15143
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15144
0
  if (!r) {
15145
0
    return false;
15146
0
  }
15147
0
  return r->set_protocol(std::string_view(input, length));
15148
0
}
15149
15150
bool ada_set_username(ada_url result, const char* input,
15151
0
                      size_t length) noexcept {
15152
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15153
0
  if (!r) {
15154
0
    return false;
15155
0
  }
15156
0
  return r->set_username(std::string_view(input, length));
15157
0
}
15158
15159
bool ada_set_password(ada_url result, const char* input,
15160
0
                      size_t length) noexcept {
15161
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15162
0
  if (!r) {
15163
0
    return false;
15164
0
  }
15165
0
  return r->set_password(std::string_view(input, length));
15166
0
}
15167
15168
0
bool ada_set_port(ada_url result, const char* input, size_t length) noexcept {
15169
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15170
0
  if (!r) {
15171
0
    return false;
15172
0
  }
15173
0
  return r->set_port(std::string_view(input, length));
15174
0
}
15175
15176
bool ada_set_pathname(ada_url result, const char* input,
15177
0
                      size_t length) noexcept {
15178
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15179
0
  if (!r) {
15180
0
    return false;
15181
0
  }
15182
0
  return r->set_pathname(std::string_view(input, length));
15183
0
}
15184
15185
/**
15186
 * Update the search/query of the URL.
15187
 *
15188
 * If a URL has `?` as the search value, passing empty string to this function
15189
 * does not remove the attribute. If you need to remove it, please use
15190
 * `ada_clear_search` method.
15191
 */
15192
0
void ada_set_search(ada_url result, const char* input, size_t length) noexcept {
15193
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15194
0
  if (r) {
15195
0
    r->set_search(std::string_view(input, length));
15196
0
  }
15197
0
}
15198
15199
/**
15200
 * Update the hash/fragment of the URL.
15201
 *
15202
 * If a URL has `#` as the hash value, passing empty string to this function
15203
 * does not remove the attribute. If you need to remove it, please use
15204
 * `ada_clear_hash` method.
15205
 */
15206
0
void ada_set_hash(ada_url result, const char* input, size_t length) noexcept {
15207
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15208
0
  if (r) {
15209
0
    r->set_hash(std::string_view(input, length));
15210
0
  }
15211
0
}
15212
15213
0
void ada_clear_port(ada_url result) noexcept {
15214
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15215
0
  if (r) {
15216
0
    r->clear_port();
15217
0
  }
15218
0
}
15219
15220
/**
15221
 * Removes the hash of the URL.
15222
 *
15223
 * Despite `ada_set_hash` method, this function allows the complete
15224
 * removal of the hash attribute, even if it has a value of `#`.
15225
 */
15226
0
void ada_clear_hash(ada_url result) noexcept {
15227
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15228
0
  if (r) {
15229
0
    r->clear_hash();
15230
0
  }
15231
0
}
15232
15233
/**
15234
 * Removes the search of the URL.
15235
 *
15236
 * Despite `ada_set_search` method, this function allows the complete
15237
 * removal of the search attribute, even if it has a value of `?`.
15238
 */
15239
0
void ada_clear_search(ada_url result) noexcept {
15240
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15241
0
  if (r) {
15242
0
    r->clear_search();
15243
0
  }
15244
0
}
15245
15246
0
bool ada_has_credentials(ada_url result) noexcept {
15247
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15248
0
  if (!r) {
15249
0
    return false;
15250
0
  }
15251
0
  return r->has_credentials();
15252
0
}
15253
15254
0
bool ada_has_empty_hostname(ada_url result) noexcept {
15255
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15256
0
  if (!r) {
15257
0
    return false;
15258
0
  }
15259
0
  return r->has_empty_hostname();
15260
0
}
15261
15262
0
bool ada_has_hostname(ada_url result) noexcept {
15263
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15264
0
  if (!r) {
15265
0
    return false;
15266
0
  }
15267
0
  return r->has_hostname();
15268
0
}
15269
15270
0
bool ada_has_non_empty_username(ada_url result) noexcept {
15271
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15272
0
  if (!r) {
15273
0
    return false;
15274
0
  }
15275
0
  return r->has_non_empty_username();
15276
0
}
15277
15278
0
bool ada_has_non_empty_password(ada_url result) noexcept {
15279
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15280
0
  if (!r) {
15281
0
    return false;
15282
0
  }
15283
0
  return r->has_non_empty_password();
15284
0
}
15285
15286
0
bool ada_has_port(ada_url result) noexcept {
15287
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15288
0
  if (!r) {
15289
0
    return false;
15290
0
  }
15291
0
  return r->has_port();
15292
0
}
15293
15294
0
bool ada_has_password(ada_url result) noexcept {
15295
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15296
0
  if (!r) {
15297
0
    return false;
15298
0
  }
15299
0
  return r->has_password();
15300
0
}
15301
15302
0
bool ada_has_hash(ada_url result) noexcept {
15303
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15304
0
  if (!r) {
15305
0
    return false;
15306
0
  }
15307
0
  return r->has_hash();
15308
0
}
15309
15310
0
bool ada_has_search(ada_url result) noexcept {
15311
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15312
0
  if (!r) {
15313
0
    return false;
15314
0
  }
15315
0
  return r->has_search();
15316
0
}
15317
15318
// returns a pointer to the internal url_aggregator::url_components
15319
0
const ada_url_components* ada_get_components(ada_url result) noexcept {
15320
0
  static_assert(sizeof(ada_url_components) == sizeof(ada::url_components));
15321
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15322
0
  if (!r) {
15323
0
    return nullptr;
15324
0
  }
15325
0
  return reinterpret_cast<const ada_url_components*>(&r->get_components());
15326
0
}
15327
15328
0
ada_owned_string ada_idna_to_unicode(const char* input, size_t length) {
15329
0
  std::string out = ada::idna::to_unicode(std::string_view(input, length));
15330
0
  ada_owned_string owned{};
15331
0
  owned.length = out.length();
15332
0
  owned.data = new char[owned.length];
15333
0
  memcpy((void*)owned.data, out.data(), owned.length);
15334
0
  return owned;
15335
0
}
15336
15337
0
ada_owned_string ada_idna_to_ascii(const char* input, size_t length) {
15338
0
  std::string out = ada::idna::to_ascii(std::string_view(input, length));
15339
0
  ada_owned_string owned{};
15340
0
  owned.length = out.size();
15341
0
  owned.data = new char[owned.length];
15342
0
  memcpy((void*)owned.data, out.data(), owned.length);
15343
0
  return owned;
15344
0
}
15345
15346
ada_url_search_params ada_parse_search_params(const char* input,
15347
0
                                              size_t length) {
15348
0
  return new ada::result<ada::url_search_params>(
15349
0
      ada::url_search_params(std::string_view(input, length)));
15350
0
}
15351
15352
0
void ada_free_search_params(ada_url_search_params result) {
15353
0
  ada::result<ada::url_search_params>* r =
15354
0
      (ada::result<ada::url_search_params>*)result;
15355
0
  delete r;
15356
0
}
15357
15358
0
ada_owned_string ada_search_params_to_string(ada_url_search_params result) {
15359
0
  ada::result<ada::url_search_params>& r =
15360
0
      *(ada::result<ada::url_search_params>*)result;
15361
0
  if (!r) return ada_owned_string{NULL, 0};
15362
0
  std::string out = r->to_string();
15363
0
  ada_owned_string owned{};
15364
0
  owned.length = out.size();
15365
0
  owned.data = new char[owned.length];
15366
0
  memcpy((void*)owned.data, out.data(), owned.length);
15367
0
  return owned;
15368
0
}
15369
15370
0
size_t ada_search_params_size(ada_url_search_params result) {
15371
0
  ada::result<ada::url_search_params>& r =
15372
0
      *(ada::result<ada::url_search_params>*)result;
15373
0
  if (!r) return 0;
15374
0
  return r->size();
15375
0
}
15376
15377
0
void ada_search_params_sort(ada_url_search_params result) {
15378
0
  ada::result<ada::url_search_params>& r =
15379
0
      *(ada::result<ada::url_search_params>*)result;
15380
0
  if (r) r->sort();
15381
0
}
15382
15383
void ada_search_params_append(ada_url_search_params result, const char* key,
15384
                              size_t key_length, const char* value,
15385
0
                              size_t value_length) {
15386
0
  ada::result<ada::url_search_params>& r =
15387
0
      *(ada::result<ada::url_search_params>*)result;
15388
0
  if (r) {
15389
0
    r->append(std::string_view(key, key_length),
15390
0
              std::string_view(value, value_length));
15391
0
  }
15392
0
}
15393
15394
void ada_search_params_set(ada_url_search_params result, const char* key,
15395
                           size_t key_length, const char* value,
15396
0
                           size_t value_length) {
15397
0
  ada::result<ada::url_search_params>& r =
15398
0
      *(ada::result<ada::url_search_params>*)result;
15399
0
  if (r) {
15400
0
    r->set(std::string_view(key, key_length),
15401
0
           std::string_view(value, value_length));
15402
0
  }
15403
0
}
15404
15405
void ada_search_params_remove(ada_url_search_params result, const char* key,
15406
0
                              size_t key_length) {
15407
0
  ada::result<ada::url_search_params>& r =
15408
0
      *(ada::result<ada::url_search_params>*)result;
15409
0
  if (r) {
15410
0
    r->remove(std::string_view(key, key_length));
15411
0
  }
15412
0
}
15413
15414
void ada_search_params_remove_value(ada_url_search_params result,
15415
                                    const char* key, size_t key_length,
15416
0
                                    const char* value, size_t value_length) {
15417
0
  ada::result<ada::url_search_params>& r =
15418
0
      *(ada::result<ada::url_search_params>*)result;
15419
0
  if (r) {
15420
0
    r->remove(std::string_view(key, key_length),
15421
0
              std::string_view(value, value_length));
15422
0
  }
15423
0
}
15424
15425
bool ada_search_params_has(ada_url_search_params result, const char* key,
15426
0
                           size_t key_length) {
15427
0
  ada::result<ada::url_search_params>& r =
15428
0
      *(ada::result<ada::url_search_params>*)result;
15429
0
  if (!r) return false;
15430
0
  return r->has(std::string_view(key, key_length));
15431
0
}
15432
15433
bool ada_search_params_has_value(ada_url_search_params result, const char* key,
15434
                                 size_t key_length, const char* value,
15435
0
                                 size_t value_length) {
15436
0
  ada::result<ada::url_search_params>& r =
15437
0
      *(ada::result<ada::url_search_params>*)result;
15438
0
  if (!r) return false;
15439
0
  return r->has(std::string_view(key, key_length),
15440
0
                std::string_view(value, value_length));
15441
0
}
15442
15443
ada_string ada_search_params_get(ada_url_search_params result, const char* key,
15444
0
                                 size_t key_length) {
15445
0
  ada::result<ada::url_search_params>& r =
15446
0
      *(ada::result<ada::url_search_params>*)result;
15447
0
  if (!r) return ada_string_create(NULL, 0);
15448
0
  auto found = r->get(std::string_view(key, key_length));
15449
0
  if (!found.has_value()) return ada_string_create(NULL, 0);
15450
0
  return ada_string_create(found->data(), found->length());
15451
0
}
15452
15453
ada_strings ada_search_params_get_all(ada_url_search_params result,
15454
0
                                      const char* key, size_t key_length) {
15455
0
  ada::result<ada::url_search_params>& r =
15456
0
      *(ada::result<ada::url_search_params>*)result;
15457
0
  if (!r) {
15458
0
    return new ada::result<std::vector<std::string>>(
15459
0
        std::vector<std::string>());
15460
0
  }
15461
0
  return new ada::result<std::vector<std::string>>(
15462
0
      r->get_all(std::string_view(key, key_length)));
15463
0
}
15464
15465
ada_url_search_params_keys_iter ada_search_params_get_keys(
15466
0
    ada_url_search_params result) {
15467
0
  ada::result<ada::url_search_params>& r =
15468
0
      *(ada::result<ada::url_search_params>*)result;
15469
0
  if (!r) {
15470
0
    return new ada::result<ada::url_search_params_keys_iter>(
15471
0
        ada::url_search_params_keys_iter());
15472
0
  }
15473
0
  return new ada::result<ada::url_search_params_keys_iter>(r->get_keys());
15474
0
}
15475
15476
ada_url_search_params_values_iter ada_search_params_get_values(
15477
0
    ada_url_search_params result) {
15478
0
  ada::result<ada::url_search_params>& r =
15479
0
      *(ada::result<ada::url_search_params>*)result;
15480
0
  if (!r) {
15481
0
    return new ada::result<ada::url_search_params_values_iter>(
15482
0
        ada::url_search_params_values_iter());
15483
0
  }
15484
0
  return new ada::result<ada::url_search_params_values_iter>(r->get_values());
15485
0
}
15486
15487
ada_url_search_params_entries_iter ada_search_params_get_entries(
15488
0
    ada_url_search_params result) {
15489
0
  ada::result<ada::url_search_params>& r =
15490
0
      *(ada::result<ada::url_search_params>*)result;
15491
0
  if (!r) {
15492
0
    return new ada::result<ada::url_search_params_entries_iter>(
15493
0
        ada::url_search_params_entries_iter());
15494
0
  }
15495
0
  return new ada::result<ada::url_search_params_entries_iter>(r->get_entries());
15496
0
}
15497
15498
0
void ada_free_strings(ada_strings result) {
15499
0
  ada::result<std::vector<std::string>>* r =
15500
0
      (ada::result<std::vector<std::string>>*)result;
15501
0
  delete r;
15502
0
}
15503
15504
0
size_t ada_strings_size(ada_strings result) {
15505
0
  ada::result<std::vector<std::string>>* r =
15506
0
      (ada::result<std::vector<std::string>>*)result;
15507
0
  if (!r) return 0;
15508
0
  return (*r)->size();
15509
0
}
15510
15511
0
ada_string ada_strings_get(ada_strings result, size_t index) {
15512
0
  ada::result<std::vector<std::string>>* r =
15513
0
      (ada::result<std::vector<std::string>>*)result;
15514
0
  if (!r) return ada_string_create(NULL, 0);
15515
0
  std::string_view view = (*r)->at(index);
15516
0
  return ada_string_create(view.data(), view.length());
15517
0
}
15518
15519
0
void ada_free_search_params_keys_iter(ada_url_search_params_keys_iter result) {
15520
0
  ada::result<ada::url_search_params_keys_iter>* r =
15521
0
      (ada::result<ada::url_search_params_keys_iter>*)result;
15522
0
  delete r;
15523
0
}
15524
15525
ada_string ada_search_params_keys_iter_next(
15526
0
    ada_url_search_params_keys_iter result) {
15527
0
  ada::result<ada::url_search_params_keys_iter>* r =
15528
0
      (ada::result<ada::url_search_params_keys_iter>*)result;
15529
0
  if (!r) return ada_string_create(NULL, 0);
15530
0
  auto next = (*r)->next();
15531
0
  if (!next.has_value()) return ada_string_create(NULL, 0);
15532
0
  return ada_string_create(next->data(), next->length());
15533
0
}
15534
15535
bool ada_search_params_keys_iter_has_next(
15536
0
    ada_url_search_params_keys_iter result) {
15537
0
  ada::result<ada::url_search_params_keys_iter>* r =
15538
0
      (ada::result<ada::url_search_params_keys_iter>*)result;
15539
0
  if (!r) return false;
15540
0
  return (*r)->has_next();
15541
0
}
15542
15543
void ada_free_search_params_values_iter(
15544
0
    ada_url_search_params_values_iter result) {
15545
0
  ada::result<ada::url_search_params_values_iter>* r =
15546
0
      (ada::result<ada::url_search_params_values_iter>*)result;
15547
0
  delete r;
15548
0
}
15549
15550
ada_string ada_search_params_values_iter_next(
15551
0
    ada_url_search_params_values_iter result) {
15552
0
  ada::result<ada::url_search_params_values_iter>* r =
15553
0
      (ada::result<ada::url_search_params_values_iter>*)result;
15554
0
  if (!r) return ada_string_create(NULL, 0);
15555
0
  auto next = (*r)->next();
15556
0
  if (!next.has_value()) return ada_string_create(NULL, 0);
15557
0
  return ada_string_create(next->data(), next->length());
15558
0
}
15559
15560
bool ada_search_params_values_iter_has_next(
15561
0
    ada_url_search_params_values_iter result) {
15562
0
  ada::result<ada::url_search_params_values_iter>* r =
15563
0
      (ada::result<ada::url_search_params_values_iter>*)result;
15564
0
  if (!r) return false;
15565
0
  return (*r)->has_next();
15566
0
}
15567
15568
void ada_free_search_params_entries_iter(
15569
0
    ada_url_search_params_entries_iter result) {
15570
0
  ada::result<ada::url_search_params_entries_iter>* r =
15571
0
      (ada::result<ada::url_search_params_entries_iter>*)result;
15572
0
  delete r;
15573
0
}
15574
15575
ada_string_pair ada_search_params_entries_iter_next(
15576
0
    ada_url_search_params_entries_iter result) {
15577
0
  ada::result<ada::url_search_params_entries_iter>* r =
15578
0
      (ada::result<ada::url_search_params_entries_iter>*)result;
15579
0
  if (!r) return {ada_string_create(NULL, 0), ada_string_create(NULL, 0)};
15580
0
  auto next = (*r)->next();
15581
0
  if (!next.has_value())
15582
0
    return {ada_string_create(NULL, 0), ada_string_create(NULL, 0)};
15583
0
  return ada_string_pair{
15584
0
      ada_string_create(next->first.data(), next->first.length()),
15585
0
      ada_string_create(next->second.data(), next->second.length())};
15586
0
}
15587
15588
bool ada_search_params_entries_iter_has_next(
15589
0
    ada_url_search_params_entries_iter result) {
15590
0
  ada::result<ada::url_search_params_entries_iter>* r =
15591
0
      (ada::result<ada::url_search_params_entries_iter>*)result;
15592
0
  if (!r) return false;
15593
0
  return (*r)->has_next();
15594
0
}
15595
15596
}  // extern "C"
15597
/* end file src/ada_c.cpp */
15598
/* end file src/ada.cpp */