Coverage Report

Created: 2023-11-19 06:20

/src/ada-url/build/singleheader/ada.cpp
Line
Count
Source (jump to first uncovered line)
1
/* auto-generated on 2023-11-15 22:48:04 -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.4k
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.4k
  char last_char = view.back();
17
  // If the address ends with a dot, we need to prune it (special case).
18
19.4k
  if (last_char == '.') {
19
2.05k
    view.remove_suffix(1);
20
2.05k
    if (view.empty()) {
21
1.46k
      return false;
22
1.46k
    }
23
586
    last_char = view.back();
24
586
  }
25
18.0k
  bool possible_ipv4 = (last_char >= '0' && last_char <= '9') ||
26
18.0k
                       (last_char >= 'a' && last_char <= 'f') ||
27
18.0k
                       last_char == 'x';
28
18.0k
  if (!possible_ipv4) {
29
6.84k
    return false;
30
6.84k
  }
31
  // From the last character, find the last dot.
32
11.1k
  size_t last_dot = view.rfind('.');
33
11.1k
  if (last_dot != std::string_view::npos) {
34
    // We have at least one dot.
35
2.76k
    view = view.substr(last_dot + 1);
36
2.76k
  }
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.1k
  if (std::all_of(view.begin(), view.end(), ada::checkers::is_digit)) {
41
4.25k
    return true;
42
4.25k
  }
43
  // It could be hex (0x), but not if there is a single character.
44
6.92k
  if (view.size() == 1) {
45
1.63k
    return false;
46
1.63k
  }
47
  // It must start with 0x.
48
5.29k
  if (!std::equal(view.begin(), view.begin() + 2, "0x")) {
49
3.11k
    return false;
50
3.11k
  }
51
  // We must allow "0x".
52
2.18k
  if (view.size() == 2) {
53
124
    return true;
54
124
  }
55
  // We have 0x followed by some characters, we need to check that they are
56
  // hexadecimals.
57
2.05k
  return std::all_of(view.begin() + 2, view.end(),
58
2.05k
                     ada::unicode::is_lowercase_hex);
59
2.18k
}
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.7k
  for (; i + 7 < input.size(); i += 8) {
94
48.9k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])] |
95
48.9k
                           path_signature_table[uint8_t(input[i + 1])] |
96
48.9k
                           path_signature_table[uint8_t(input[i + 2])] |
97
48.9k
                           path_signature_table[uint8_t(input[i + 3])] |
98
48.9k
                           path_signature_table[uint8_t(input[i + 4])] |
99
48.9k
                           path_signature_table[uint8_t(input[i + 5])] |
100
48.9k
                           path_signature_table[uint8_t(input[i + 6])] |
101
48.9k
                           path_signature_table[uint8_t(input[i + 7])]);
102
48.9k
  }
103
95.6k
  for (; i < input.size(); i++) {
104
68.8k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])]);
105
68.8k
  }
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.71k
size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) {
147
9.71k
  const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
148
9.71k
  size_t pos = 0;
149
9.71k
  char32_t* start{utf32_output};
150
125k
  while (pos < len) {
151
    // try to convert the next block of 16 ASCII bytes
152
118k
    if (pos + 16 <= len) {  // if it is safe to read 16 more
153
                            // bytes, check that they are ascii
154
76.5k
      uint64_t v1;
155
76.5k
      std::memcpy(&v1, data + pos, sizeof(uint64_t));
156
76.5k
      uint64_t v2;
157
76.5k
      std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
158
76.5k
      uint64_t v{v1 | v2};
159
76.5k
      if ((v & 0x8080808080808080) == 0) {
160
2.18k
        size_t final_pos = pos + 16;
161
37.0k
        while (pos < final_pos) {
162
34.9k
          *utf32_output++ = char32_t(buf[pos]);
163
34.9k
          pos++;
164
34.9k
        }
165
2.18k
        continue;
166
2.18k
      }
167
76.5k
    }
168
116k
    uint8_t leading_byte = data[pos];  // leading byte
169
116k
    if (leading_byte < 0b10000000) {
170
      // converting one ASCII byte !!!
171
68.3k
      *utf32_output++ = char32_t(leading_byte);
172
68.3k
      pos++;
173
68.3k
    } else if ((leading_byte & 0b11100000) == 0b11000000) {
174
      // We have a two-byte UTF-8
175
8.70k
      if (pos + 1 >= len) {
176
234
        return 0;
177
234
      }  // minimal bound checking
178
8.46k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
179
361
        return 0;
180
361
      }
181
      // range check
182
8.10k
      uint32_t code_point =
183
8.10k
          (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
184
8.10k
      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
39.6k
    } else if ((leading_byte & 0b11110000) == 0b11100000) {
190
      // We have a three-byte UTF-8
191
36.8k
      if (pos + 2 >= len) {
192
96
        return 0;
193
96
      }  // minimal bound checking
194
195
36.7k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
196
159
        return 0;
197
159
      }
198
36.6k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
199
42
        return 0;
200
42
      }
201
      // range check
202
36.5k
      uint32_t code_point = (leading_byte & 0b00001111) << 12 |
203
36.5k
                            (data[pos + 1] & 0b00111111) << 6 |
204
36.5k
                            (data[pos + 2] & 0b00111111);
205
36.5k
      if (code_point < 0x800 || 0xffff < code_point ||
206
36.5k
          (0xd7ff < code_point && code_point < 0xe000)) {
207
49
        return 0;
208
49
      }
209
36.5k
      *utf32_output++ = char32_t(code_point);
210
36.5k
      pos += 3;
211
36.5k
    } else if ((leading_byte & 0b11111000) == 0b11110000) {  // 0b11110000
212
      // we have a 4-byte UTF-8 word.
213
949
      if (pos + 3 >= len) {
214
69
        return 0;
215
69
      }  // minimal bound checking
216
880
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
217
96
        return 0;
218
96
      }
219
784
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
220
29
        return 0;
221
29
      }
222
755
      if ((data[pos + 3] & 0b11000000) != 0b10000000) {
223
26
        return 0;
224
26
      }
225
226
      // range check
227
729
      uint32_t code_point = (leading_byte & 0b00000111) << 18 |
228
729
                            (data[pos + 1] & 0b00111111) << 12 |
229
729
                            (data[pos + 2] & 0b00111111) << 6 |
230
729
                            (data[pos + 3] & 0b00111111);
231
729
      if (code_point <= 0xffff || 0x10ffff < code_point) {
232
48
        return 0;
233
48
      }
234
681
      *utf32_output++ = char32_t(code_point);
235
681
      pos += 4;
236
1.78k
    } else {
237
1.78k
      return 0;
238
1.78k
    }
239
116k
  }
240
6.68k
  return utf32_output - start;
241
9.71k
}
242
243
1.37k
size_t utf8_length_from_utf32(const char32_t* buf, size_t len) {
244
  // We are not BOM aware.
245
1.37k
  const uint32_t* p = reinterpret_cast<const uint32_t*>(buf);
246
1.37k
  size_t counter{0};
247
5.97k
  for (size_t i = 0; i != len; ++i) {
248
4.60k
    ++counter;                                      // ASCII
249
4.60k
    counter += static_cast<size_t>(p[i] > 0x7F);    // two-byte
250
4.60k
    counter += static_cast<size_t>(p[i] > 0x7FF);   // three-byte
251
4.60k
    counter += static_cast<size_t>(p[i] > 0xFFFF);  // four-bytes
252
4.60k
  }
253
1.37k
  return counter;
254
1.37k
}
255
256
9.71k
size_t utf32_length_from_utf8(const char* buf, size_t len) {
257
9.71k
  const int8_t* p = reinterpret_cast<const int8_t*>(buf);
258
318k
  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
318k
    return c > -65;
262
318k
  });
263
9.71k
}
264
265
1.37k
size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) {
266
1.37k
  const uint32_t* data = reinterpret_cast<const uint32_t*>(buf);
267
1.37k
  size_t pos = 0;
268
1.37k
  char* start{utf8_output};
269
5.06k
  while (pos < len) {
270
    // try to convert the next block of 2 ASCII characters
271
3.87k
    if (pos + 2 <= len) {  // if it is safe to read 8 more
272
                           // bytes, check that they are ascii
273
2.85k
      uint64_t v;
274
2.85k
      std::memcpy(&v, data + pos, sizeof(uint64_t));
275
2.85k
      if ((v & 0xFFFFFF80FFFFFF80) == 0) {
276
626
        *utf8_output++ = char(buf[pos]);
277
626
        *utf8_output++ = char(buf[pos + 1]);
278
626
        pos += 2;
279
626
        continue;
280
626
      }
281
2.85k
    }
282
3.25k
    uint32_t word = data[pos];
283
3.25k
    if ((word & 0xFFFFFF80) == 0) {
284
      // will generate one UTF-8 bytes
285
496
      *utf8_output++ = char(word);
286
496
      pos++;
287
2.75k
    } else if ((word & 0xFFFFF800) == 0) {
288
      // will generate two UTF-8 bytes
289
      // we have 0b110XXXXX 0b10XXXXXX
290
902
      *utf8_output++ = char((word >> 6) | 0b11000000);
291
902
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
292
902
      pos++;
293
1.85k
    } else if ((word & 0xFFFF0000) == 0) {
294
      // will generate three UTF-8 bytes
295
      // we have 0b1110XXXX 0b10XXXXXX 0b10XXXXXX
296
993
      if (word >= 0xD800 && word <= 0xDFFF) {
297
42
        return 0;
298
42
      }
299
951
      *utf8_output++ = char((word >> 12) | 0b11100000);
300
951
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
301
951
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
302
951
      pos++;
303
951
    } else {
304
      // will generate four UTF-8 bytes
305
      // we have 0b11110XXX 0b10XXXXXX 0b10XXXXXX
306
      // 0b10XXXXXX
307
860
      if (word > 0x10FFFF) {
308
141
        return 0;
309
141
      }
310
719
      *utf8_output++ = char((word >> 18) | 0b11110000);
311
719
      *utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
312
719
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
313
719
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
314
719
      pos++;
315
719
    }
316
3.25k
  }
317
1.18k
  return utf8_output - start;
318
1.37k
}
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
171k
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
171k
  uint32_t len = std::size(table);
2739
171k
  uint32_t low = 0;
2740
171k
  uint32_t high = len - 1;
2741
2.29M
  while (low <= high) {
2742
2.17M
    uint32_t middle_index = (low + high) >> 1;  // cannot overflow
2743
2.17M
    uint32_t middle_value = table[middle_index][0];
2744
2.17M
    if (middle_value < key) {
2745
652k
      low = middle_index + 1;
2746
1.51M
    } else if (middle_value > key) {
2747
1.46M
      high = middle_index - 1;
2748
1.46M
    } else {
2749
52.6k
      return middle_index;  // perfect match
2750
52.6k
    }
2751
2.17M
  }
2752
119k
  return low == 0 ? 0 : low - 1;
2753
171k
}
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.3k
void ascii_map(char* input, size_t length) {
2780
43.0k
  auto broadcast = [](uint8_t v) -> uint64_t {
2781
43.0k
    return 0x101010101010101ull * v;
2782
43.0k
  };
2783
14.3k
  uint64_t broadcast_80 = broadcast(0x80);
2784
14.3k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
2785
14.3k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2786
14.3k
  size_t i = 0;
2787
2788
40.0k
  for (; i + 7 < length; i += 8) {
2789
25.6k
    uint64_t word{};
2790
25.6k
    memcpy(&word, input + i, sizeof(word));
2791
25.6k
    word ^=
2792
25.6k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2793
25.6k
    memcpy(input + i, &word, sizeof(word));
2794
25.6k
  }
2795
14.3k
  if (i < length) {
2796
12.3k
    uint64_t word{};
2797
12.3k
    memcpy(&word, input + i, length - i);
2798
12.3k
    word ^=
2799
12.3k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2800
12.3k
    memcpy(input + i, &word, length - i);
2801
12.3k
  }
2802
14.3k
}
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
171k
  for (char32_t x : input) {
2823
171k
    size_t index = find_range_index(x);
2824
171k
    uint32_t descriptor = table[index][1];
2825
171k
    uint8_t code = uint8_t(descriptor);
2826
171k
    switch (code) {
2827
223
      case 0:
2828
223
        break;  // nothing to do, ignored
2829
125k
      case 1:
2830
125k
        answer.push_back(x);  // valid, we just copy it to output
2831
125k
        break;
2832
421
      case 2:
2833
421
        return error;  // disallowed
2834
      // case 3 :
2835
45.9k
      default:
2836
        // We have a mapping
2837
45.9k
        {
2838
45.9k
          size_t char_count = (descriptor >> 24);
2839
45.9k
          uint16_t char_index = uint16_t(descriptor >> 8);
2840
264k
          for (size_t idx = char_index; idx < char_index + char_count; idx++) {
2841
218k
            answer.push_back(mappings[idx]);
2842
218k
          }
2843
45.9k
        }
2844
171k
    }
2845
171k
  }
2846
16.1k
  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.1k
    const std::u32string_view input) noexcept {
7767
16.1k
  bool decomposition_needed{false};
7768
16.1k
  size_t additional_elements{0};
7769
314k
  for (char32_t current_character : input) {
7770
314k
    size_t decomposition_length{0};
7771
7772
314k
    if (current_character >= hangul_sbase &&
7773
314k
        current_character < hangul_sbase + hangul_scount) {
7774
6.32k
      decomposition_length = 2;
7775
6.32k
      if ((current_character - hangul_sbase) % hangul_tcount) {
7776
3.07k
        decomposition_length = 3;
7777
3.07k
      }
7778
308k
    } else if (current_character < 0x110000) {
7779
308k
      const uint8_t di = decomposition_index[current_character >> 8];
7780
308k
      const uint16_t* const decomposition =
7781
308k
          decomposition_block[di] + (current_character % 256);
7782
308k
      decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
7783
308k
      if ((decomposition_length > 0) && (decomposition[0] & 1)) {
7784
0
        decomposition_length = 0;
7785
0
      }
7786
308k
    }
7787
314k
    if (decomposition_length != 0) {
7788
11.7k
      decomposition_needed = true;
7789
11.7k
      additional_elements += decomposition_length - 1;
7790
11.7k
    }
7791
314k
  }
7792
16.1k
  return {decomposition_needed, additional_elements};
7793
16.1k
}
7794
7795
3.67k
void decompose(std::u32string& input, size_t additional_elements) {
7796
3.67k
  input.resize(input.size() + additional_elements);
7797
3.67k
  for (size_t descending_idx = input.size(),
7798
3.67k
              input_count = descending_idx - additional_elements;
7799
73.0k
       input_count--;) {
7800
69.4k
    if (input[input_count] >= hangul_sbase &&
7801
69.4k
        input[input_count] < hangul_sbase + hangul_scount) {
7802
      // Hangul decomposition.
7803
6.32k
      char32_t s_index = input[input_count] - hangul_sbase;
7804
6.32k
      if (s_index % hangul_tcount != 0) {
7805
3.07k
        input[--descending_idx] = hangul_tbase + s_index % hangul_tcount;
7806
3.07k
      }
7807
6.32k
      input[--descending_idx] =
7808
6.32k
          hangul_vbase + (s_index % hangul_ncount) / hangul_tcount;
7809
6.32k
      input[--descending_idx] = hangul_lbase + s_index / hangul_ncount;
7810
63.0k
    } else if (input[input_count] < 0x110000) {
7811
      // Check decomposition_data.
7812
63.0k
      const uint16_t* decomposition =
7813
63.0k
          decomposition_block[decomposition_index[input[input_count] >> 8]] +
7814
63.0k
          (input[input_count] % 256);
7815
63.0k
      uint16_t decomposition_length =
7816
63.0k
          (decomposition[1] >> 2) - (decomposition[0] >> 2);
7817
63.0k
      if (decomposition_length > 0 && (decomposition[0] & 1)) {
7818
0
        decomposition_length = 0;
7819
0
      }
7820
63.0k
      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
57.6k
      } else {
7827
        // No decomposition.
7828
57.6k
        input[--descending_idx] = input[input_count];
7829
57.6k
      }
7830
63.0k
    } else {
7831
      // Non-Unicode character.
7832
0
      input[--descending_idx] = input[input_count];
7833
0
    }
7834
69.4k
  }
7835
3.67k
}
7836
7837
627k
uint8_t get_ccc(char32_t c) noexcept {
7838
627k
  return c < 0x110000 ? canonical_combining_class_block
7839
627k
                            [canonical_combining_class_index[c >> 8]][c % 256]
7840
627k
                      : 0;
7841
627k
}
7842
7843
16.1k
void sort_marks(std::u32string& input) {
7844
331k
  for (size_t idx = 1; idx < input.size(); idx++) {
7845
315k
    uint8_t ccc = get_ccc(input[idx]);
7846
315k
    if (ccc == 0) {
7847
304k
      continue;
7848
304k
    }  // Skip non-combining characters.
7849
11.3k
    auto current_character = input[idx];
7850
11.3k
    size_t back_idx = idx;
7851
12.4k
    while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) {
7852
1.14k
      input[back_idx] = input[back_idx - 1];
7853
1.14k
      back_idx--;
7854
1.14k
    }
7855
11.3k
    input[back_idx] = current_character;
7856
11.3k
  }
7857
16.1k
}
7858
7859
16.1k
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.1k
  auto [decomposition_needed, additional_elements] =
7865
16.1k
      compute_decomposition_length(input);
7866
16.1k
  if (decomposition_needed) {
7867
3.67k
    decompose(input, additional_elements);
7868
3.67k
  }
7869
16.1k
  sort_marks(input);
7870
16.1k
}
7871
7872
16.1k
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.1k
  size_t input_count{0};
7878
16.1k
  size_t composition_count{0};
7879
326k
  for (; input_count < input.size(); input_count++, composition_count++) {
7880
310k
    input[composition_count] = input[input_count];
7881
310k
    if (input[input_count] >= hangul_lbase &&
7882
310k
        input[input_count] < hangul_lbase + hangul_lcount) {
7883
7.73k
      if (input_count + 1 < input.size() &&
7884
7.73k
          input[input_count + 1] >= hangul_vbase &&
7885
7.73k
          input[input_count + 1] < hangul_vbase + hangul_vcount) {
7886
6.32k
        input[composition_count] =
7887
6.32k
            hangul_sbase +
7888
6.32k
            ((input[input_count] - hangul_lbase) * hangul_vcount +
7889
6.32k
             input[input_count + 1] - hangul_vbase) *
7890
6.32k
                hangul_tcount;
7891
6.32k
        input_count++;
7892
6.32k
        if (input_count + 1 < input.size() &&
7893
6.32k
            input[input_count + 1] > hangul_tbase &&
7894
6.32k
            input[input_count + 1] < hangul_tbase + hangul_tcount) {
7895
3.07k
          input[composition_count] += input[++input_count] - hangul_tbase;
7896
3.07k
        }
7897
6.32k
      }
7898
302k
    } else if (input[input_count] >= hangul_sbase &&
7899
302k
               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
302k
    } else if (input[input_count] < 0x110000) {
7907
302k
      const uint16_t* composition =
7908
302k
          &composition_block[composition_index[input[input_count] >> 8]]
7909
302k
                            [input[input_count] % 256];
7910
302k
      size_t initial_composition_count = composition_count;
7911
314k
      for (int32_t previous_ccc = -1; input_count + 1 < input.size();
7912
302k
           input_count++) {
7913
299k
        uint8_t ccc = get_ccc(input[input_count + 1]);
7914
7915
299k
        if (composition[1] != composition[0] && previous_ccc < ccc) {
7916
          // Try finding a composition.
7917
63.2k
          uint16_t left = composition[0];
7918
63.2k
          uint16_t right = composition[1];
7919
162k
          while (left + 2 < right) {
7920
            // mean without overflow
7921
99.1k
            uint16_t middle = left + (((right - left) >> 1) & ~1);
7922
99.1k
            if (composition_data[middle] <= input[input_count + 1]) {
7923
13.8k
              left = middle;
7924
13.8k
            }
7925
99.1k
            if (composition_data[middle] >= input[input_count + 1]) {
7926
89.7k
              right = middle;
7927
89.7k
            }
7928
99.1k
          }
7929
63.2k
          if (composition_data[left] == input[input_count + 1]) {
7930
7.05k
            input[initial_composition_count] = composition_data[left + 1];
7931
7.05k
            composition =
7932
7.05k
                &composition_block
7933
7.05k
                    [composition_index[composition_data[left + 1] >> 8]]
7934
7.05k
                    [composition_data[left + 1] % 256];
7935
7.05k
            continue;
7936
7.05k
          }
7937
63.2k
        }
7938
7939
292k
        if (ccc == 0) {
7940
288k
          break;
7941
288k
        }  // Not a combining character.
7942
4.31k
        previous_ccc = ccc;
7943
4.31k
        input[++composition_count] = input[input_count + 1];
7944
4.31k
      }
7945
302k
    }
7946
310k
  }
7947
7948
16.1k
  if (composition_count < input_count) {
7949
3.70k
    input.resize(composition_count);
7950
3.70k
  }
7951
16.1k
}
7952
7953
16.1k
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.1k
  decompose_nfc(input);
7959
16.1k
  compose(input);
7960
16.1k
}
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
96.5k
static constexpr int32_t char_to_digit_value(char value) {
7979
96.5k
  if (value >= 'a' && value <= 'z') return value - 'a';
7980
27.0k
  if (value >= '0' && value <= '9') return value - '0' + 26;
7981
613
  return -1;
7982
27.0k
}
7983
7984
372k
static constexpr char digit_to_char(int32_t digit) {
7985
372k
  return digit < 26 ? char(digit + 97) : char(digit + 22);
7986
372k
}
7987
7988
184k
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
7989
184k
  if (firsttime) {
7990
34.6k
    d = d / damp;
7991
150k
  } else {
7992
150k
    d = d / 2;
7993
150k
  }
7994
184k
  d += d / n;
7995
184k
  int32_t k = 0;
7996
269k
  while (d > ((base - tmin) * tmax) / 2) {
7997
84.5k
    d /= base - tmin;
7998
84.5k
    k += base;
7999
84.5k
  }
8000
184k
  return k + (((base - tmin + 1) * d) / (d + skew));
8001
184k
}
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
14.0k
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8013
14.0k
      if (c >= 0x80) {
8014
0
        return false;
8015
0
      }
8016
14.0k
      out.push_back(c);
8017
14.0k
      written_out++;
8018
14.0k
    }
8019
3.61k
    input.remove_prefix(end_of_ascii + 1);
8020
3.61k
  }
8021
51.0k
  while (!input.empty()) {
8022
39.7k
    int32_t oldi = i;
8023
39.7k
    int32_t w = 1;
8024
87.5k
    for (int32_t k = base;; k += base) {
8025
87.5k
      if (input.empty()) {
8026
108
        return false;
8027
108
      }
8028
87.4k
      uint8_t code_point = input.front();
8029
87.4k
      input.remove_prefix(1);
8030
87.4k
      int32_t digit = char_to_digit_value(code_point);
8031
87.4k
      if (digit < 0) {
8032
98
        return false;
8033
98
      }
8034
87.3k
      if (digit > (0x7fffffff - i) / w) {
8035
20
        return false;
8036
20
      }
8037
87.3k
      i = i + digit * w;
8038
87.3k
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8039
87.3k
      if (digit < t) {
8040
39.5k
        break;
8041
39.5k
      }
8042
47.7k
      if (w > 0x7fffffff / (base - t)) {
8043
0
        return false;
8044
0
      }
8045
47.7k
      w = w * (base - t);
8046
47.7k
    }
8047
39.5k
    bias = adapt(i - oldi, written_out + 1, oldi == 0);
8048
39.5k
    if (i / (written_out + 1) > int32_t(0x7fffffff - n)) {
8049
45
      return false;
8050
45
    }
8051
39.5k
    n = n + i / (written_out + 1);
8052
39.5k
    i = i % (written_out + 1);
8053
39.5k
    if (n < 0x80) {
8054
0
      return false;
8055
0
    }
8056
39.5k
    out.insert(out.begin() + i, n);
8057
39.5k
    written_out++;
8058
39.5k
    ++i;
8059
39.5k
  }
8060
8061
11.2k
  return true;
8062
11.5k
}
8063
8064
2.11k
bool verify_punycode(std::string_view input) {
8065
2.11k
  size_t written_out{0};
8066
2.11k
  uint32_t n = initial_n;
8067
2.11k
  int32_t i = 0;
8068
2.11k
  int32_t bias = initial_bias;
8069
  // grab ascii content
8070
2.11k
  size_t end_of_ascii = input.find_last_of('-');
8071
2.11k
  if (end_of_ascii != std::string_view::npos) {
8072
1.85k
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8073
1.85k
      if (c >= 0x80) {
8074
0
        return false;
8075
0
      }
8076
1.85k
      written_out++;
8077
1.85k
    }
8078
538
    input.remove_prefix(end_of_ascii + 1);
8079
538
  }
8080
5.55k
  while (!input.empty()) {
8081
4.18k
    int32_t oldi = i;
8082
4.18k
    int32_t w = 1;
8083
9.16k
    for (int32_t k = base;; k += base) {
8084
9.16k
      if (input.empty()) {
8085
130
        return false;
8086
130
      }
8087
9.03k
      uint8_t code_point = input.front();
8088
9.03k
      input.remove_prefix(1);
8089
9.03k
      int32_t digit = char_to_digit_value(code_point);
8090
9.03k
      if (digit < 0) {
8091
515
        return false;
8092
515
      }
8093
8.51k
      if (digit > (0x7fffffff - i) / w) {
8094
40
        return false;
8095
40
      }
8096
8.47k
      i = i + digit * w;
8097
8.47k
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8098
8.47k
      if (digit < t) {
8099
3.49k
        break;
8100
3.49k
      }
8101
4.97k
      if (w > 0x7fffffff / (base - t)) {
8102
0
        return false;
8103
0
      }
8104
4.97k
      w = w * (base - t);
8105
4.97k
    }
8106
3.49k
    bias = adapt(i - oldi, int32_t(written_out + 1), oldi == 0);
8107
3.49k
    if (i / (written_out + 1) > 0x7fffffff - n) {
8108
63
      return false;
8109
63
    }
8110
3.43k
    n = n + i / int32_t(written_out + 1);
8111
3.43k
    i = i % int32_t(written_out + 1);
8112
3.43k
    if (n < 0x80) {
8113
0
      return false;
8114
0
    }
8115
3.43k
    written_out++;
8116
3.43k
    ++i;
8117
3.43k
  }
8118
8119
1.37k
  return true;
8120
2.11k
}
8121
8122
25.7k
bool utf32_to_punycode(std::u32string_view input, std::string &out) {
8123
25.7k
  out.reserve(input.size() + out.size());
8124
25.7k
  uint32_t n = initial_n;
8125
25.7k
  int32_t d = 0;
8126
25.7k
  int32_t bias = initial_bias;
8127
25.7k
  size_t h = 0;
8128
  // first push the ascii content
8129
167k
  for (uint32_t c : input) {
8130
167k
    if (c < 0x80) {
8131
25.2k
      ++h;
8132
25.2k
      out.push_back(char(c));
8133
25.2k
    }
8134
167k
    if (c > 0x10ffff || (c >= 0xd880 && c < 0xe000)) {
8135
0
      return false;
8136
0
    }
8137
167k
  }
8138
25.7k
  size_t b = h;
8139
25.7k
  if (b > 0) {
8140
5.55k
    out.push_back('-');
8141
5.55k
  }
8142
122k
  while (h < input.size()) {
8143
97.1k
    uint32_t m = 0x10FFFF;
8144
1.74M
    for (auto code_point : input) {
8145
1.74M
      if (code_point >= n && code_point < m) m = code_point;
8146
1.74M
    }
8147
8148
97.1k
    if ((m - n) > (0x7fffffff - d) / (h + 1)) {
8149
0
      return false;
8150
0
    }
8151
97.1k
    d = d + int32_t((m - n) * (h + 1));
8152
97.1k
    n = m;
8153
1.74M
    for (auto c : input) {
8154
1.74M
      if (c < n) {
8155
983k
        if (d == 0x7fffffff) {
8156
0
          return false;
8157
0
        }
8158
983k
        ++d;
8159
983k
      }
8160
1.74M
      if (c == n) {
8161
141k
        int32_t q = d;
8162
372k
        for (int32_t k = base;; k += base) {
8163
372k
          int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8164
8165
372k
          if (q < t) {
8166
141k
            break;
8167
141k
          }
8168
230k
          out.push_back(digit_to_char(t + ((q - t) % (base - t))));
8169
230k
          q = (q - t) / (base - t);
8170
230k
        }
8171
141k
        out.push_back(digit_to_char(q));
8172
141k
        bias = adapt(d, int32_t(h + 1), h == b);
8173
141k
        d = 0;
8174
141k
        ++h;
8175
141k
      }
8176
1.74M
    }
8177
97.1k
    ++d;
8178
97.1k
    ++n;
8179
97.1k
  }
8180
25.7k
  return true;
8181
25.7k
}
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
236k
inline static direction find_direction(uint32_t code_point) noexcept {
8954
236k
  auto it = std::lower_bound(
8955
236k
      std::begin(dir_table), std::end(dir_table), code_point,
8956
2.42M
      [](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
236k
  if (it == std::end(dir_table)) {
8960
0
    return direction::NONE;
8961
0
  }
8962
  // We have that d.final_code >= c.
8963
236k
  if (code_point >= it->start_code) {
8964
235k
    return it->direct;
8965
235k
  }
8966
922
  return direction::NONE;
8967
236k
}
8968
8969
inline static size_t find_last_not_of_nsm(
8970
33.5k
    const std::u32string_view label) noexcept {
8971
34.6k
  for (int i = label.size() - 1; i >= 0; i--)
8972
34.6k
    if (find_direction(label[i]) != direction::NSM) return i;
8973
8974
0
  return std::u32string_view::npos;
8975
33.5k
}
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
33.5k
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
8980
33.5k
  const size_t mask =
8981
33.5k
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
8982
8983
33.5k
  size_t directions = 0;
8984
225k
  for (size_t i = 0; i < label.size(); i++) {
8985
191k
    directions |= 1u << find_direction(label[i]);
8986
191k
  }
8987
33.5k
  return (directions & mask) != 0;
8988
33.5k
}
8989
8990
35.7k
bool is_label_valid(const std::u32string_view label) {
8991
35.7k
  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
35.7k
  constexpr static uint32_t combining[] = {
9017
35.7k
      0x300,   0x301,   0x302,   0x303,   0x304,   0x305,   0x306,   0x307,
9018
35.7k
      0x308,   0x309,   0x30a,   0x30b,   0x30c,   0x30d,   0x30e,   0x30f,
9019
35.7k
      0x310,   0x311,   0x312,   0x313,   0x314,   0x315,   0x316,   0x317,
9020
35.7k
      0x318,   0x319,   0x31a,   0x31b,   0x31c,   0x31d,   0x31e,   0x31f,
9021
35.7k
      0x320,   0x321,   0x322,   0x323,   0x324,   0x325,   0x326,   0x327,
9022
35.7k
      0x328,   0x329,   0x32a,   0x32b,   0x32c,   0x32d,   0x32e,   0x32f,
9023
35.7k
      0x330,   0x331,   0x332,   0x333,   0x334,   0x335,   0x336,   0x337,
9024
35.7k
      0x338,   0x339,   0x33a,   0x33b,   0x33c,   0x33d,   0x33e,   0x33f,
9025
35.7k
      0x340,   0x341,   0x342,   0x343,   0x344,   0x345,   0x346,   0x347,
9026
35.7k
      0x348,   0x349,   0x34a,   0x34b,   0x34c,   0x34d,   0x34e,   0x34f,
9027
35.7k
      0x350,   0x351,   0x352,   0x353,   0x354,   0x355,   0x356,   0x357,
9028
35.7k
      0x358,   0x359,   0x35a,   0x35b,   0x35c,   0x35d,   0x35e,   0x35f,
9029
35.7k
      0x360,   0x361,   0x362,   0x363,   0x364,   0x365,   0x366,   0x367,
9030
35.7k
      0x368,   0x369,   0x36a,   0x36b,   0x36c,   0x36d,   0x36e,   0x36f,
9031
35.7k
      0x483,   0x484,   0x485,   0x486,   0x487,   0x488,   0x489,   0x591,
9032
35.7k
      0x592,   0x593,   0x594,   0x595,   0x596,   0x597,   0x598,   0x599,
9033
35.7k
      0x59a,   0x59b,   0x59c,   0x59d,   0x59e,   0x59f,   0x5a0,   0x5a1,
9034
35.7k
      0x5a2,   0x5a3,   0x5a4,   0x5a5,   0x5a6,   0x5a7,   0x5a8,   0x5a9,
9035
35.7k
      0x5aa,   0x5ab,   0x5ac,   0x5ad,   0x5ae,   0x5af,   0x5b0,   0x5b1,
9036
35.7k
      0x5b2,   0x5b3,   0x5b4,   0x5b5,   0x5b6,   0x5b7,   0x5b8,   0x5b9,
9037
35.7k
      0x5ba,   0x5bb,   0x5bc,   0x5bd,   0x5bf,   0x5c1,   0x5c2,   0x5c4,
9038
35.7k
      0x5c5,   0x5c7,   0x610,   0x611,   0x612,   0x613,   0x614,   0x615,
9039
35.7k
      0x616,   0x617,   0x618,   0x619,   0x61a,   0x64b,   0x64c,   0x64d,
9040
35.7k
      0x64e,   0x64f,   0x650,   0x651,   0x652,   0x653,   0x654,   0x655,
9041
35.7k
      0x656,   0x657,   0x658,   0x659,   0x65a,   0x65b,   0x65c,   0x65d,
9042
35.7k
      0x65e,   0x65f,   0x670,   0x6d6,   0x6d7,   0x6d8,   0x6d9,   0x6da,
9043
35.7k
      0x6db,   0x6dc,   0x6df,   0x6e0,   0x6e1,   0x6e2,   0x6e3,   0x6e4,
9044
35.7k
      0x6e7,   0x6e8,   0x6ea,   0x6eb,   0x6ec,   0x6ed,   0x711,   0x730,
9045
35.7k
      0x731,   0x732,   0x733,   0x734,   0x735,   0x736,   0x737,   0x738,
9046
35.7k
      0x739,   0x73a,   0x73b,   0x73c,   0x73d,   0x73e,   0x73f,   0x740,
9047
35.7k
      0x741,   0x742,   0x743,   0x744,   0x745,   0x746,   0x747,   0x748,
9048
35.7k
      0x749,   0x74a,   0x7a6,   0x7a7,   0x7a8,   0x7a9,   0x7aa,   0x7ab,
9049
35.7k
      0x7ac,   0x7ad,   0x7ae,   0x7af,   0x7b0,   0x7eb,   0x7ec,   0x7ed,
9050
35.7k
      0x7ee,   0x7ef,   0x7f0,   0x7f1,   0x7f2,   0x7f3,   0x7fd,   0x816,
9051
35.7k
      0x817,   0x818,   0x819,   0x81b,   0x81c,   0x81d,   0x81e,   0x81f,
9052
35.7k
      0x820,   0x821,   0x822,   0x823,   0x825,   0x826,   0x827,   0x829,
9053
35.7k
      0x82a,   0x82b,   0x82c,   0x82d,   0x859,   0x85a,   0x85b,   0x8d3,
9054
35.7k
      0x8d4,   0x8d5,   0x8d6,   0x8d7,   0x8d8,   0x8d9,   0x8da,   0x8db,
9055
35.7k
      0x8dc,   0x8dd,   0x8de,   0x8df,   0x8e0,   0x8e1,   0x8e3,   0x8e4,
9056
35.7k
      0x8e5,   0x8e6,   0x8e7,   0x8e8,   0x8e9,   0x8ea,   0x8eb,   0x8ec,
9057
35.7k
      0x8ed,   0x8ee,   0x8ef,   0x8f0,   0x8f1,   0x8f2,   0x8f3,   0x8f4,
9058
35.7k
      0x8f5,   0x8f6,   0x8f7,   0x8f8,   0x8f9,   0x8fa,   0x8fb,   0x8fc,
9059
35.7k
      0x8fd,   0x8fe,   0x8ff,   0x900,   0x901,   0x902,   0x903,   0x93a,
9060
35.7k
      0x93b,   0x93c,   0x93e,   0x93f,   0x940,   0x941,   0x942,   0x943,
9061
35.7k
      0x944,   0x945,   0x946,   0x947,   0x948,   0x949,   0x94a,   0x94b,
9062
35.7k
      0x94c,   0x94d,   0x94e,   0x94f,   0x951,   0x952,   0x953,   0x954,
9063
35.7k
      0x955,   0x956,   0x957,   0x962,   0x963,   0x981,   0x982,   0x983,
9064
35.7k
      0x9bc,   0x9be,   0x9bf,   0x9c0,   0x9c1,   0x9c2,   0x9c3,   0x9c4,
9065
35.7k
      0x9c7,   0x9c8,   0x9cb,   0x9cc,   0x9cd,   0x9d7,   0x9e2,   0x9e3,
9066
35.7k
      0x9fe,   0xa01,   0xa02,   0xa03,   0xa3c,   0xa3e,   0xa3f,   0xa40,
9067
35.7k
      0xa41,   0xa42,   0xa47,   0xa48,   0xa4b,   0xa4c,   0xa4d,   0xa51,
9068
35.7k
      0xa70,   0xa71,   0xa75,   0xa81,   0xa82,   0xa83,   0xabc,   0xabe,
9069
35.7k
      0xabf,   0xac0,   0xac1,   0xac2,   0xac3,   0xac4,   0xac5,   0xac7,
9070
35.7k
      0xac8,   0xac9,   0xacb,   0xacc,   0xacd,   0xae2,   0xae3,   0xafa,
9071
35.7k
      0xafb,   0xafc,   0xafd,   0xafe,   0xaff,   0xb01,   0xb02,   0xb03,
9072
35.7k
      0xb3c,   0xb3e,   0xb3f,   0xb40,   0xb41,   0xb42,   0xb43,   0xb44,
9073
35.7k
      0xb47,   0xb48,   0xb4b,   0xb4c,   0xb4d,   0xb55,   0xb56,   0xb57,
9074
35.7k
      0xb62,   0xb63,   0xb82,   0xbbe,   0xbbf,   0xbc0,   0xbc1,   0xbc2,
9075
35.7k
      0xbc6,   0xbc7,   0xbc8,   0xbca,   0xbcb,   0xbcc,   0xbcd,   0xbd7,
9076
35.7k
      0xc00,   0xc01,   0xc02,   0xc03,   0xc04,   0xc3e,   0xc3f,   0xc40,
9077
35.7k
      0xc41,   0xc42,   0xc43,   0xc44,   0xc46,   0xc47,   0xc48,   0xc4a,
9078
35.7k
      0xc4b,   0xc4c,   0xc4d,   0xc55,   0xc56,   0xc62,   0xc63,   0xc81,
9079
35.7k
      0xc82,   0xc83,   0xcbc,   0xcbe,   0xcbf,   0xcc0,   0xcc1,   0xcc2,
9080
35.7k
      0xcc3,   0xcc4,   0xcc6,   0xcc7,   0xcc8,   0xcca,   0xccb,   0xccc,
9081
35.7k
      0xccd,   0xcd5,   0xcd6,   0xce2,   0xce3,   0xd00,   0xd01,   0xd02,
9082
35.7k
      0xd03,   0xd3b,   0xd3c,   0xd3e,   0xd3f,   0xd40,   0xd41,   0xd42,
9083
35.7k
      0xd43,   0xd44,   0xd46,   0xd47,   0xd48,   0xd4a,   0xd4b,   0xd4c,
9084
35.7k
      0xd4d,   0xd57,   0xd62,   0xd63,   0xd81,   0xd82,   0xd83,   0xdca,
9085
35.7k
      0xdcf,   0xdd0,   0xdd1,   0xdd2,   0xdd3,   0xdd4,   0xdd6,   0xdd8,
9086
35.7k
      0xdd9,   0xdda,   0xddb,   0xddc,   0xddd,   0xdde,   0xddf,   0xdf2,
9087
35.7k
      0xdf3,   0xe31,   0xe34,   0xe35,   0xe36,   0xe37,   0xe38,   0xe39,
9088
35.7k
      0xe3a,   0xe47,   0xe48,   0xe49,   0xe4a,   0xe4b,   0xe4c,   0xe4d,
9089
35.7k
      0xe4e,   0xeb1,   0xeb4,   0xeb5,   0xeb6,   0xeb7,   0xeb8,   0xeb9,
9090
35.7k
      0xeba,   0xebb,   0xebc,   0xec8,   0xec9,   0xeca,   0xecb,   0xecc,
9091
35.7k
      0xecd,   0xf18,   0xf19,   0xf35,   0xf37,   0xf39,   0xf3e,   0xf3f,
9092
35.7k
      0xf71,   0xf72,   0xf73,   0xf74,   0xf75,   0xf76,   0xf77,   0xf78,
9093
35.7k
      0xf79,   0xf7a,   0xf7b,   0xf7c,   0xf7d,   0xf7e,   0xf7f,   0xf80,
9094
35.7k
      0xf81,   0xf82,   0xf83,   0xf84,   0xf86,   0xf87,   0xf8d,   0xf8e,
9095
35.7k
      0xf8f,   0xf90,   0xf91,   0xf92,   0xf93,   0xf94,   0xf95,   0xf96,
9096
35.7k
      0xf97,   0xf99,   0xf9a,   0xf9b,   0xf9c,   0xf9d,   0xf9e,   0xf9f,
9097
35.7k
      0xfa0,   0xfa1,   0xfa2,   0xfa3,   0xfa4,   0xfa5,   0xfa6,   0xfa7,
9098
35.7k
      0xfa8,   0xfa9,   0xfaa,   0xfab,   0xfac,   0xfad,   0xfae,   0xfaf,
9099
35.7k
      0xfb0,   0xfb1,   0xfb2,   0xfb3,   0xfb4,   0xfb5,   0xfb6,   0xfb7,
9100
35.7k
      0xfb8,   0xfb9,   0xfba,   0xfbb,   0xfbc,   0xfc6,   0x102b,  0x102c,
9101
35.7k
      0x102d,  0x102e,  0x102f,  0x1030,  0x1031,  0x1032,  0x1033,  0x1034,
9102
35.7k
      0x1035,  0x1036,  0x1037,  0x1038,  0x1039,  0x103a,  0x103b,  0x103c,
9103
35.7k
      0x103d,  0x103e,  0x1056,  0x1057,  0x1058,  0x1059,  0x105e,  0x105f,
9104
35.7k
      0x1060,  0x1062,  0x1063,  0x1064,  0x1067,  0x1068,  0x1069,  0x106a,
9105
35.7k
      0x106b,  0x106c,  0x106d,  0x1071,  0x1072,  0x1073,  0x1074,  0x1082,
9106
35.7k
      0x1083,  0x1084,  0x1085,  0x1086,  0x1087,  0x1088,  0x1089,  0x108a,
9107
35.7k
      0x108b,  0x108c,  0x108d,  0x108f,  0x109a,  0x109b,  0x109c,  0x109d,
9108
35.7k
      0x135d,  0x135e,  0x135f,  0x1712,  0x1713,  0x1714,  0x1732,  0x1733,
9109
35.7k
      0x1734,  0x1752,  0x1753,  0x1772,  0x1773,  0x17b4,  0x17b5,  0x17b6,
9110
35.7k
      0x17b7,  0x17b8,  0x17b9,  0x17ba,  0x17bb,  0x17bc,  0x17bd,  0x17be,
9111
35.7k
      0x17bf,  0x17c0,  0x17c1,  0x17c2,  0x17c3,  0x17c4,  0x17c5,  0x17c6,
9112
35.7k
      0x17c7,  0x17c8,  0x17c9,  0x17ca,  0x17cb,  0x17cc,  0x17cd,  0x17ce,
9113
35.7k
      0x17cf,  0x17d0,  0x17d1,  0x17d2,  0x17d3,  0x17dd,  0x180b,  0x180c,
9114
35.7k
      0x180d,  0x1885,  0x1886,  0x18a9,  0x1920,  0x1921,  0x1922,  0x1923,
9115
35.7k
      0x1924,  0x1925,  0x1926,  0x1927,  0x1928,  0x1929,  0x192a,  0x192b,
9116
35.7k
      0x1930,  0x1931,  0x1932,  0x1933,  0x1934,  0x1935,  0x1936,  0x1937,
9117
35.7k
      0x1938,  0x1939,  0x193a,  0x193b,  0x1a17,  0x1a18,  0x1a19,  0x1a1a,
9118
35.7k
      0x1a1b,  0x1a55,  0x1a56,  0x1a57,  0x1a58,  0x1a59,  0x1a5a,  0x1a5b,
9119
35.7k
      0x1a5c,  0x1a5d,  0x1a5e,  0x1a60,  0x1a61,  0x1a62,  0x1a63,  0x1a64,
9120
35.7k
      0x1a65,  0x1a66,  0x1a67,  0x1a68,  0x1a69,  0x1a6a,  0x1a6b,  0x1a6c,
9121
35.7k
      0x1a6d,  0x1a6e,  0x1a6f,  0x1a70,  0x1a71,  0x1a72,  0x1a73,  0x1a74,
9122
35.7k
      0x1a75,  0x1a76,  0x1a77,  0x1a78,  0x1a79,  0x1a7a,  0x1a7b,  0x1a7c,
9123
35.7k
      0x1a7f,  0x1ab0,  0x1ab1,  0x1ab2,  0x1ab3,  0x1ab4,  0x1ab5,  0x1ab6,
9124
35.7k
      0x1ab7,  0x1ab8,  0x1ab9,  0x1aba,  0x1abb,  0x1abc,  0x1abd,  0x1abe,
9125
35.7k
      0x1abf,  0x1ac0,  0x1b00,  0x1b01,  0x1b02,  0x1b03,  0x1b04,  0x1b34,
9126
35.7k
      0x1b35,  0x1b36,  0x1b37,  0x1b38,  0x1b39,  0x1b3a,  0x1b3b,  0x1b3c,
9127
35.7k
      0x1b3d,  0x1b3e,  0x1b3f,  0x1b40,  0x1b41,  0x1b42,  0x1b43,  0x1b44,
9128
35.7k
      0x1b6b,  0x1b6c,  0x1b6d,  0x1b6e,  0x1b6f,  0x1b70,  0x1b71,  0x1b72,
9129
35.7k
      0x1b73,  0x1b80,  0x1b81,  0x1b82,  0x1ba1,  0x1ba2,  0x1ba3,  0x1ba4,
9130
35.7k
      0x1ba5,  0x1ba6,  0x1ba7,  0x1ba8,  0x1ba9,  0x1baa,  0x1bab,  0x1bac,
9131
35.7k
      0x1bad,  0x1be6,  0x1be7,  0x1be8,  0x1be9,  0x1bea,  0x1beb,  0x1bec,
9132
35.7k
      0x1bed,  0x1bee,  0x1bef,  0x1bf0,  0x1bf1,  0x1bf2,  0x1bf3,  0x1c24,
9133
35.7k
      0x1c25,  0x1c26,  0x1c27,  0x1c28,  0x1c29,  0x1c2a,  0x1c2b,  0x1c2c,
9134
35.7k
      0x1c2d,  0x1c2e,  0x1c2f,  0x1c30,  0x1c31,  0x1c32,  0x1c33,  0x1c34,
9135
35.7k
      0x1c35,  0x1c36,  0x1c37,  0x1cd0,  0x1cd1,  0x1cd2,  0x1cd4,  0x1cd5,
9136
35.7k
      0x1cd6,  0x1cd7,  0x1cd8,  0x1cd9,  0x1cda,  0x1cdb,  0x1cdc,  0x1cdd,
9137
35.7k
      0x1cde,  0x1cdf,  0x1ce0,  0x1ce1,  0x1ce2,  0x1ce3,  0x1ce4,  0x1ce5,
9138
35.7k
      0x1ce6,  0x1ce7,  0x1ce8,  0x1ced,  0x1cf4,  0x1cf7,  0x1cf8,  0x1cf9,
9139
35.7k
      0x1dc0,  0x1dc1,  0x1dc2,  0x1dc3,  0x1dc4,  0x1dc5,  0x1dc6,  0x1dc7,
9140
35.7k
      0x1dc8,  0x1dc9,  0x1dca,  0x1dcb,  0x1dcc,  0x1dcd,  0x1dce,  0x1dcf,
9141
35.7k
      0x1dd0,  0x1dd1,  0x1dd2,  0x1dd3,  0x1dd4,  0x1dd5,  0x1dd6,  0x1dd7,
9142
35.7k
      0x1dd8,  0x1dd9,  0x1dda,  0x1ddb,  0x1ddc,  0x1ddd,  0x1dde,  0x1ddf,
9143
35.7k
      0x1de0,  0x1de1,  0x1de2,  0x1de3,  0x1de4,  0x1de5,  0x1de6,  0x1de7,
9144
35.7k
      0x1de8,  0x1de9,  0x1dea,  0x1deb,  0x1dec,  0x1ded,  0x1dee,  0x1def,
9145
35.7k
      0x1df0,  0x1df1,  0x1df2,  0x1df3,  0x1df4,  0x1df5,  0x1df6,  0x1df7,
9146
35.7k
      0x1df8,  0x1df9,  0x1dfb,  0x1dfc,  0x1dfd,  0x1dfe,  0x1dff,  0x20d0,
9147
35.7k
      0x20d1,  0x20d2,  0x20d3,  0x20d4,  0x20d5,  0x20d6,  0x20d7,  0x20d8,
9148
35.7k
      0x20d9,  0x20da,  0x20db,  0x20dc,  0x20dd,  0x20de,  0x20df,  0x20e0,
9149
35.7k
      0x20e1,  0x20e2,  0x20e3,  0x20e4,  0x20e5,  0x20e6,  0x20e7,  0x20e8,
9150
35.7k
      0x20e9,  0x20ea,  0x20eb,  0x20ec,  0x20ed,  0x20ee,  0x20ef,  0x20f0,
9151
35.7k
      0x2cef,  0x2cf0,  0x2cf1,  0x2d7f,  0x2de0,  0x2de1,  0x2de2,  0x2de3,
9152
35.7k
      0x2de4,  0x2de5,  0x2de6,  0x2de7,  0x2de8,  0x2de9,  0x2dea,  0x2deb,
9153
35.7k
      0x2dec,  0x2ded,  0x2dee,  0x2def,  0x2df0,  0x2df1,  0x2df2,  0x2df3,
9154
35.7k
      0x2df4,  0x2df5,  0x2df6,  0x2df7,  0x2df8,  0x2df9,  0x2dfa,  0x2dfb,
9155
35.7k
      0x2dfc,  0x2dfd,  0x2dfe,  0x2dff,  0x302a,  0x302b,  0x302c,  0x302d,
9156
35.7k
      0x302e,  0x302f,  0x3099,  0x309a,  0xa66f,  0xa670,  0xa671,  0xa672,
9157
35.7k
      0xa674,  0xa675,  0xa676,  0xa677,  0xa678,  0xa679,  0xa67a,  0xa67b,
9158
35.7k
      0xa67c,  0xa67d,  0xa69e,  0xa69f,  0xa6f0,  0xa6f1,  0xa802,  0xa806,
9159
35.7k
      0xa80b,  0xa823,  0xa824,  0xa825,  0xa826,  0xa827,  0xa82c,  0xa880,
9160
35.7k
      0xa881,  0xa8b4,  0xa8b5,  0xa8b6,  0xa8b7,  0xa8b8,  0xa8b9,  0xa8ba,
9161
35.7k
      0xa8bb,  0xa8bc,  0xa8bd,  0xa8be,  0xa8bf,  0xa8c0,  0xa8c1,  0xa8c2,
9162
35.7k
      0xa8c3,  0xa8c4,  0xa8c5,  0xa8e0,  0xa8e1,  0xa8e2,  0xa8e3,  0xa8e4,
9163
35.7k
      0xa8e5,  0xa8e6,  0xa8e7,  0xa8e8,  0xa8e9,  0xa8ea,  0xa8eb,  0xa8ec,
9164
35.7k
      0xa8ed,  0xa8ee,  0xa8ef,  0xa8f0,  0xa8f1,  0xa8ff,  0xa926,  0xa927,
9165
35.7k
      0xa928,  0xa929,  0xa92a,  0xa92b,  0xa92c,  0xa92d,  0xa947,  0xa948,
9166
35.7k
      0xa949,  0xa94a,  0xa94b,  0xa94c,  0xa94d,  0xa94e,  0xa94f,  0xa950,
9167
35.7k
      0xa951,  0xa952,  0xa953,  0xa980,  0xa981,  0xa982,  0xa983,  0xa9b3,
9168
35.7k
      0xa9b4,  0xa9b5,  0xa9b6,  0xa9b7,  0xa9b8,  0xa9b9,  0xa9ba,  0xa9bb,
9169
35.7k
      0xa9bc,  0xa9bd,  0xa9be,  0xa9bf,  0xa9c0,  0xa9e5,  0xaa29,  0xaa2a,
9170
35.7k
      0xaa2b,  0xaa2c,  0xaa2d,  0xaa2e,  0xaa2f,  0xaa30,  0xaa31,  0xaa32,
9171
35.7k
      0xaa33,  0xaa34,  0xaa35,  0xaa36,  0xaa43,  0xaa4c,  0xaa4d,  0xaa7b,
9172
35.7k
      0xaa7c,  0xaa7d,  0xaab0,  0xaab2,  0xaab3,  0xaab4,  0xaab7,  0xaab8,
9173
35.7k
      0xaabe,  0xaabf,  0xaac1,  0xaaeb,  0xaaec,  0xaaed,  0xaaee,  0xaaef,
9174
35.7k
      0xaaf5,  0xaaf6,  0xabe3,  0xabe4,  0xabe5,  0xabe6,  0xabe7,  0xabe8,
9175
35.7k
      0xabe9,  0xabea,  0xabec,  0xabed,  0xfb1e,  0xfe00,  0xfe01,  0xfe02,
9176
35.7k
      0xfe03,  0xfe04,  0xfe05,  0xfe06,  0xfe07,  0xfe08,  0xfe09,  0xfe0a,
9177
35.7k
      0xfe0b,  0xfe0c,  0xfe0d,  0xfe0e,  0xfe0f,  0xfe20,  0xfe21,  0xfe22,
9178
35.7k
      0xfe23,  0xfe24,  0xfe25,  0xfe26,  0xfe27,  0xfe28,  0xfe29,  0xfe2a,
9179
35.7k
      0xfe2b,  0xfe2c,  0xfe2d,  0xfe2e,  0xfe2f,  0x101fd, 0x102e0, 0x10376,
9180
35.7k
      0x10377, 0x10378, 0x10379, 0x1037a, 0x10a01, 0x10a02, 0x10a03, 0x10a05,
9181
35.7k
      0x10a06, 0x10a0c, 0x10a0d, 0x10a0e, 0x10a0f, 0x10a38, 0x10a39, 0x10a3a,
9182
35.7k
      0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d25, 0x10d26, 0x10d27, 0x10eab,
9183
35.7k
      0x10eac, 0x10f46, 0x10f47, 0x10f48, 0x10f49, 0x10f4a, 0x10f4b, 0x10f4c,
9184
35.7k
      0x10f4d, 0x10f4e, 0x10f4f, 0x10f50, 0x11000, 0x11001, 0x11002, 0x11038,
9185
35.7k
      0x11039, 0x1103a, 0x1103b, 0x1103c, 0x1103d, 0x1103e, 0x1103f, 0x11040,
9186
35.7k
      0x11041, 0x11042, 0x11043, 0x11044, 0x11045, 0x11046, 0x1107f, 0x11080,
9187
35.7k
      0x11081, 0x11082, 0x110b0, 0x110b1, 0x110b2, 0x110b3, 0x110b4, 0x110b5,
9188
35.7k
      0x110b6, 0x110b7, 0x110b8, 0x110b9, 0x110ba, 0x11100, 0x11101, 0x11102,
9189
35.7k
      0x11127, 0x11128, 0x11129, 0x1112a, 0x1112b, 0x1112c, 0x1112d, 0x1112e,
9190
35.7k
      0x1112f, 0x11130, 0x11131, 0x11132, 0x11133, 0x11134, 0x11145, 0x11146,
9191
35.7k
      0x11173, 0x11180, 0x11181, 0x11182, 0x111b3, 0x111b4, 0x111b5, 0x111b6,
9192
35.7k
      0x111b7, 0x111b8, 0x111b9, 0x111ba, 0x111bb, 0x111bc, 0x111bd, 0x111be,
9193
35.7k
      0x111bf, 0x111c0, 0x111c9, 0x111ca, 0x111cb, 0x111cc, 0x111ce, 0x111cf,
9194
35.7k
      0x1122c, 0x1122d, 0x1122e, 0x1122f, 0x11230, 0x11231, 0x11232, 0x11233,
9195
35.7k
      0x11234, 0x11235, 0x11236, 0x11237, 0x1123e, 0x112df, 0x112e0, 0x112e1,
9196
35.7k
      0x112e2, 0x112e3, 0x112e4, 0x112e5, 0x112e6, 0x112e7, 0x112e8, 0x112e9,
9197
35.7k
      0x112ea, 0x11300, 0x11301, 0x11302, 0x11303, 0x1133b, 0x1133c, 0x1133e,
9198
35.7k
      0x1133f, 0x11340, 0x11341, 0x11342, 0x11343, 0x11344, 0x11347, 0x11348,
9199
35.7k
      0x1134b, 0x1134c, 0x1134d, 0x11357, 0x11362, 0x11363, 0x11366, 0x11367,
9200
35.7k
      0x11368, 0x11369, 0x1136a, 0x1136b, 0x1136c, 0x11370, 0x11371, 0x11372,
9201
35.7k
      0x11373, 0x11374, 0x11435, 0x11436, 0x11437, 0x11438, 0x11439, 0x1143a,
9202
35.7k
      0x1143b, 0x1143c, 0x1143d, 0x1143e, 0x1143f, 0x11440, 0x11441, 0x11442,
9203
35.7k
      0x11443, 0x11444, 0x11445, 0x11446, 0x1145e, 0x114b0, 0x114b1, 0x114b2,
9204
35.7k
      0x114b3, 0x114b4, 0x114b5, 0x114b6, 0x114b7, 0x114b8, 0x114b9, 0x114ba,
9205
35.7k
      0x114bb, 0x114bc, 0x114bd, 0x114be, 0x114bf, 0x114c0, 0x114c1, 0x114c2,
9206
35.7k
      0x114c3, 0x115af, 0x115b0, 0x115b1, 0x115b2, 0x115b3, 0x115b4, 0x115b5,
9207
35.7k
      0x115b8, 0x115b9, 0x115ba, 0x115bb, 0x115bc, 0x115bd, 0x115be, 0x115bf,
9208
35.7k
      0x115c0, 0x115dc, 0x115dd, 0x11630, 0x11631, 0x11632, 0x11633, 0x11634,
9209
35.7k
      0x11635, 0x11636, 0x11637, 0x11638, 0x11639, 0x1163a, 0x1163b, 0x1163c,
9210
35.7k
      0x1163d, 0x1163e, 0x1163f, 0x11640, 0x116ab, 0x116ac, 0x116ad, 0x116ae,
9211
35.7k
      0x116af, 0x116b0, 0x116b1, 0x116b2, 0x116b3, 0x116b4, 0x116b5, 0x116b6,
9212
35.7k
      0x116b7, 0x1171d, 0x1171e, 0x1171f, 0x11720, 0x11721, 0x11722, 0x11723,
9213
35.7k
      0x11724, 0x11725, 0x11726, 0x11727, 0x11728, 0x11729, 0x1172a, 0x1172b,
9214
35.7k
      0x1182c, 0x1182d, 0x1182e, 0x1182f, 0x11830, 0x11831, 0x11832, 0x11833,
9215
35.7k
      0x11834, 0x11835, 0x11836, 0x11837, 0x11838, 0x11839, 0x1183a, 0x11930,
9216
35.7k
      0x11931, 0x11932, 0x11933, 0x11934, 0x11935, 0x11937, 0x11938, 0x1193b,
9217
35.7k
      0x1193c, 0x1193d, 0x1193e, 0x11940, 0x11942, 0x11943, 0x119d1, 0x119d2,
9218
35.7k
      0x119d3, 0x119d4, 0x119d5, 0x119d6, 0x119d7, 0x119da, 0x119db, 0x119dc,
9219
35.7k
      0x119dd, 0x119de, 0x119df, 0x119e0, 0x119e4, 0x11a01, 0x11a02, 0x11a03,
9220
35.7k
      0x11a04, 0x11a05, 0x11a06, 0x11a07, 0x11a08, 0x11a09, 0x11a0a, 0x11a33,
9221
35.7k
      0x11a34, 0x11a35, 0x11a36, 0x11a37, 0x11a38, 0x11a39, 0x11a3b, 0x11a3c,
9222
35.7k
      0x11a3d, 0x11a3e, 0x11a47, 0x11a51, 0x11a52, 0x11a53, 0x11a54, 0x11a55,
9223
35.7k
      0x11a56, 0x11a57, 0x11a58, 0x11a59, 0x11a5a, 0x11a5b, 0x11a8a, 0x11a8b,
9224
35.7k
      0x11a8c, 0x11a8d, 0x11a8e, 0x11a8f, 0x11a90, 0x11a91, 0x11a92, 0x11a93,
9225
35.7k
      0x11a94, 0x11a95, 0x11a96, 0x11a97, 0x11a98, 0x11a99, 0x11c2f, 0x11c30,
9226
35.7k
      0x11c31, 0x11c32, 0x11c33, 0x11c34, 0x11c35, 0x11c36, 0x11c38, 0x11c39,
9227
35.7k
      0x11c3a, 0x11c3b, 0x11c3c, 0x11c3d, 0x11c3e, 0x11c3f, 0x11c92, 0x11c93,
9228
35.7k
      0x11c94, 0x11c95, 0x11c96, 0x11c97, 0x11c98, 0x11c99, 0x11c9a, 0x11c9b,
9229
35.7k
      0x11c9c, 0x11c9d, 0x11c9e, 0x11c9f, 0x11ca0, 0x11ca1, 0x11ca2, 0x11ca3,
9230
35.7k
      0x11ca4, 0x11ca5, 0x11ca6, 0x11ca7, 0x11ca9, 0x11caa, 0x11cab, 0x11cac,
9231
35.7k
      0x11cad, 0x11cae, 0x11caf, 0x11cb0, 0x11cb1, 0x11cb2, 0x11cb3, 0x11cb4,
9232
35.7k
      0x11cb5, 0x11cb6, 0x11d31, 0x11d32, 0x11d33, 0x11d34, 0x11d35, 0x11d36,
9233
35.7k
      0x11d3a, 0x11d3c, 0x11d3d, 0x11d3f, 0x11d40, 0x11d41, 0x11d42, 0x11d43,
9234
35.7k
      0x11d44, 0x11d45, 0x11d47, 0x11d8a, 0x11d8b, 0x11d8c, 0x11d8d, 0x11d8e,
9235
35.7k
      0x11d90, 0x11d91, 0x11d93, 0x11d94, 0x11d95, 0x11d96, 0x11d97, 0x11ef3,
9236
35.7k
      0x11ef4, 0x11ef5, 0x11ef6, 0x16af0, 0x16af1, 0x16af2, 0x16af3, 0x16af4,
9237
35.7k
      0x16b30, 0x16b31, 0x16b32, 0x16b33, 0x16b34, 0x16b35, 0x16b36, 0x16f4f,
9238
35.7k
      0x16f51, 0x16f52, 0x16f53, 0x16f54, 0x16f55, 0x16f56, 0x16f57, 0x16f58,
9239
35.7k
      0x16f59, 0x16f5a, 0x16f5b, 0x16f5c, 0x16f5d, 0x16f5e, 0x16f5f, 0x16f60,
9240
35.7k
      0x16f61, 0x16f62, 0x16f63, 0x16f64, 0x16f65, 0x16f66, 0x16f67, 0x16f68,
9241
35.7k
      0x16f69, 0x16f6a, 0x16f6b, 0x16f6c, 0x16f6d, 0x16f6e, 0x16f6f, 0x16f70,
9242
35.7k
      0x16f71, 0x16f72, 0x16f73, 0x16f74, 0x16f75, 0x16f76, 0x16f77, 0x16f78,
9243
35.7k
      0x16f79, 0x16f7a, 0x16f7b, 0x16f7c, 0x16f7d, 0x16f7e, 0x16f7f, 0x16f80,
9244
35.7k
      0x16f81, 0x16f82, 0x16f83, 0x16f84, 0x16f85, 0x16f86, 0x16f87, 0x16f8f,
9245
35.7k
      0x16f90, 0x16f91, 0x16f92, 0x16fe4, 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e,
9246
35.7k
      0x1d165, 0x1d166, 0x1d167, 0x1d168, 0x1d169, 0x1d16d, 0x1d16e, 0x1d16f,
9247
35.7k
      0x1d170, 0x1d171, 0x1d172, 0x1d17b, 0x1d17c, 0x1d17d, 0x1d17e, 0x1d17f,
9248
35.7k
      0x1d180, 0x1d181, 0x1d182, 0x1d185, 0x1d186, 0x1d187, 0x1d188, 0x1d189,
9249
35.7k
      0x1d18a, 0x1d18b, 0x1d1aa, 0x1d1ab, 0x1d1ac, 0x1d1ad, 0x1d242, 0x1d243,
9250
35.7k
      0x1d244, 0x1da00, 0x1da01, 0x1da02, 0x1da03, 0x1da04, 0x1da05, 0x1da06,
9251
35.7k
      0x1da07, 0x1da08, 0x1da09, 0x1da0a, 0x1da0b, 0x1da0c, 0x1da0d, 0x1da0e,
9252
35.7k
      0x1da0f, 0x1da10, 0x1da11, 0x1da12, 0x1da13, 0x1da14, 0x1da15, 0x1da16,
9253
35.7k
      0x1da17, 0x1da18, 0x1da19, 0x1da1a, 0x1da1b, 0x1da1c, 0x1da1d, 0x1da1e,
9254
35.7k
      0x1da1f, 0x1da20, 0x1da21, 0x1da22, 0x1da23, 0x1da24, 0x1da25, 0x1da26,
9255
35.7k
      0x1da27, 0x1da28, 0x1da29, 0x1da2a, 0x1da2b, 0x1da2c, 0x1da2d, 0x1da2e,
9256
35.7k
      0x1da2f, 0x1da30, 0x1da31, 0x1da32, 0x1da33, 0x1da34, 0x1da35, 0x1da36,
9257
35.7k
      0x1da3b, 0x1da3c, 0x1da3d, 0x1da3e, 0x1da3f, 0x1da40, 0x1da41, 0x1da42,
9258
35.7k
      0x1da43, 0x1da44, 0x1da45, 0x1da46, 0x1da47, 0x1da48, 0x1da49, 0x1da4a,
9259
35.7k
      0x1da4b, 0x1da4c, 0x1da4d, 0x1da4e, 0x1da4f, 0x1da50, 0x1da51, 0x1da52,
9260
35.7k
      0x1da53, 0x1da54, 0x1da55, 0x1da56, 0x1da57, 0x1da58, 0x1da59, 0x1da5a,
9261
35.7k
      0x1da5b, 0x1da5c, 0x1da5d, 0x1da5e, 0x1da5f, 0x1da60, 0x1da61, 0x1da62,
9262
35.7k
      0x1da63, 0x1da64, 0x1da65, 0x1da66, 0x1da67, 0x1da68, 0x1da69, 0x1da6a,
9263
35.7k
      0x1da6b, 0x1da6c, 0x1da75, 0x1da84, 0x1da9b, 0x1da9c, 0x1da9d, 0x1da9e,
9264
35.7k
      0x1da9f, 0x1daa1, 0x1daa2, 0x1daa3, 0x1daa4, 0x1daa5, 0x1daa6, 0x1daa7,
9265
35.7k
      0x1daa8, 0x1daa9, 0x1daaa, 0x1daab, 0x1daac, 0x1daad, 0x1daae, 0x1daaf,
9266
35.7k
      0x1e000, 0x1e001, 0x1e002, 0x1e003, 0x1e004, 0x1e005, 0x1e006, 0x1e008,
9267
35.7k
      0x1e009, 0x1e00a, 0x1e00b, 0x1e00c, 0x1e00d, 0x1e00e, 0x1e00f, 0x1e010,
9268
35.7k
      0x1e011, 0x1e012, 0x1e013, 0x1e014, 0x1e015, 0x1e016, 0x1e017, 0x1e018,
9269
35.7k
      0x1e01b, 0x1e01c, 0x1e01d, 0x1e01e, 0x1e01f, 0x1e020, 0x1e021, 0x1e023,
9270
35.7k
      0x1e024, 0x1e026, 0x1e027, 0x1e028, 0x1e029, 0x1e02a, 0x1e130, 0x1e131,
9271
35.7k
      0x1e132, 0x1e133, 0x1e134, 0x1e135, 0x1e136, 0x1e2ec, 0x1e2ed, 0x1e2ee,
9272
35.7k
      0x1e2ef, 0x1e8d0, 0x1e8d1, 0x1e8d2, 0x1e8d3, 0x1e8d4, 0x1e8d5, 0x1e8d6,
9273
35.7k
      0x1e944, 0x1e945, 0x1e946, 0x1e947, 0x1e948, 0x1e949, 0x1e94a, 0xe0100,
9274
35.7k
      0xe0101, 0xe0102, 0xe0103, 0xe0104, 0xe0105, 0xe0106, 0xe0107, 0xe0108,
9275
35.7k
      0xe0109, 0xe010a, 0xe010b, 0xe010c, 0xe010d, 0xe010e, 0xe010f, 0xe0110,
9276
35.7k
      0xe0111, 0xe0112, 0xe0113, 0xe0114, 0xe0115, 0xe0116, 0xe0117, 0xe0118,
9277
35.7k
      0xe0119, 0xe011a, 0xe011b, 0xe011c, 0xe011d, 0xe011e, 0xe011f, 0xe0120,
9278
35.7k
      0xe0121, 0xe0122, 0xe0123, 0xe0124, 0xe0125, 0xe0126, 0xe0127, 0xe0128,
9279
35.7k
      0xe0129, 0xe012a, 0xe012b, 0xe012c, 0xe012d, 0xe012e, 0xe012f, 0xe0130,
9280
35.7k
      0xe0131, 0xe0132, 0xe0133, 0xe0134, 0xe0135, 0xe0136, 0xe0137, 0xe0138,
9281
35.7k
      0xe0139, 0xe013a, 0xe013b, 0xe013c, 0xe013d, 0xe013e, 0xe013f, 0xe0140,
9282
35.7k
      0xe0141, 0xe0142, 0xe0143, 0xe0144, 0xe0145, 0xe0146, 0xe0147, 0xe0148,
9283
35.7k
      0xe0149, 0xe014a, 0xe014b, 0xe014c, 0xe014d, 0xe014e, 0xe014f, 0xe0150,
9284
35.7k
      0xe0151, 0xe0152, 0xe0153, 0xe0154, 0xe0155, 0xe0156, 0xe0157, 0xe0158,
9285
35.7k
      0xe0159, 0xe015a, 0xe015b, 0xe015c, 0xe015d, 0xe015e, 0xe015f, 0xe0160,
9286
35.7k
      0xe0161, 0xe0162, 0xe0163, 0xe0164, 0xe0165, 0xe0166, 0xe0167, 0xe0168,
9287
35.7k
      0xe0169, 0xe016a, 0xe016b, 0xe016c, 0xe016d, 0xe016e, 0xe016f, 0xe0170,
9288
35.7k
      0xe0171, 0xe0172, 0xe0173, 0xe0174, 0xe0175, 0xe0176, 0xe0177, 0xe0178,
9289
35.7k
      0xe0179, 0xe017a, 0xe017b, 0xe017c, 0xe017d, 0xe017e, 0xe017f, 0xe0180,
9290
35.7k
      0xe0181, 0xe0182, 0xe0183, 0xe0184, 0xe0185, 0xe0186, 0xe0187, 0xe0188,
9291
35.7k
      0xe0189, 0xe018a, 0xe018b, 0xe018c, 0xe018d, 0xe018e, 0xe018f, 0xe0190,
9292
35.7k
      0xe0191, 0xe0192, 0xe0193, 0xe0194, 0xe0195, 0xe0196, 0xe0197, 0xe0198,
9293
35.7k
      0xe0199, 0xe019a, 0xe019b, 0xe019c, 0xe019d, 0xe019e, 0xe019f, 0xe01a0,
9294
35.7k
      0xe01a1, 0xe01a2, 0xe01a3, 0xe01a4, 0xe01a5, 0xe01a6, 0xe01a7, 0xe01a8,
9295
35.7k
      0xe01a9, 0xe01aa, 0xe01ab, 0xe01ac, 0xe01ad, 0xe01ae, 0xe01af, 0xe01b0,
9296
35.7k
      0xe01b1, 0xe01b2, 0xe01b3, 0xe01b4, 0xe01b5, 0xe01b6, 0xe01b7, 0xe01b8,
9297
35.7k
      0xe01b9, 0xe01ba, 0xe01bb, 0xe01bc, 0xe01bd, 0xe01be, 0xe01bf, 0xe01c0,
9298
35.7k
      0xe01c1, 0xe01c2, 0xe01c3, 0xe01c4, 0xe01c5, 0xe01c6, 0xe01c7, 0xe01c8,
9299
35.7k
      0xe01c9, 0xe01ca, 0xe01cb, 0xe01cc, 0xe01cd, 0xe01ce, 0xe01cf, 0xe01d0,
9300
35.7k
      0xe01d1, 0xe01d2, 0xe01d3, 0xe01d4, 0xe01d5, 0xe01d6, 0xe01d7, 0xe01d8,
9301
35.7k
      0xe01d9, 0xe01da, 0xe01db, 0xe01dc, 0xe01dd, 0xe01de, 0xe01df, 0xe01e0,
9302
35.7k
      0xe01e1, 0xe01e2, 0xe01e3, 0xe01e4, 0xe01e5, 0xe01e6, 0xe01e7, 0xe01e8,
9303
35.7k
      0xe01e9, 0xe01ea, 0xe01eb, 0xe01ec, 0xe01ed, 0xe01ee, 0xe01ef};
9304
35.7k
  if (std::binary_search(std::begin(combining), std::end(combining),
9305
35.7k
                         label.front())) {
9306
100
    return false;
9307
100
  }
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
35.6k
  constexpr static uint32_t virama[] = {
9320
35.6k
      0x094D,  0x09CD,  0x0A4D,  0x0ACD,  0x0B4D,  0x0BCD,  0x0C4D,  0x0CCD,
9321
35.6k
      0x0D3B,  0x0D3C,  0x0D4D,  0x0DCA,  0x0E3A,  0x0EBA,  0x0F84,  0x1039,
9322
35.6k
      0x103A,  0x1714,  0x1734,  0x17D2,  0x1A60,  0x1B44,  0x1BAA,  0x1BAB,
9323
35.6k
      0x1BF2,  0x1BF3,  0x2D7F,  0xA806,  0xA82C,  0xA8C4,  0xA953,  0xA9C0,
9324
35.6k
      0xAAF6,  0xABED,  0x10A3F, 0x11046, 0x1107F, 0x110B9, 0x11133, 0x11134,
9325
35.6k
      0x111C0, 0x11235, 0x112EA, 0x1134D, 0x11442, 0x114C2, 0x115BF, 0x1163F,
9326
35.6k
      0x116B6, 0x1172B, 0x11839, 0x1193D, 0x1193E, 0x119E0, 0x11A34, 0x11A47,
9327
35.6k
      0x11A99, 0x11C3F, 0x11D44, 0x11D45, 0x11D97};
9328
35.6k
  constexpr static uint32_t R[] = {
9329
35.6k
      0x622, 0x623, 0x624, 0x625, 0x627, 0x629, 0x62f, 0x630, 0x631,
9330
35.6k
      0x632, 0x648, 0x671, 0x672, 0x673, 0x675, 0x676, 0x677, 0x688,
9331
35.6k
      0x689, 0x68a, 0x68b, 0x68c, 0x68d, 0x68e, 0x68f, 0x690, 0x691,
9332
35.6k
      0x692, 0x693, 0x694, 0x695, 0x696, 0x697, 0x698, 0x699, 0x6c0,
9333
35.6k
      0x6c3, 0x6c4, 0x6c5, 0x6c6, 0x6c7, 0x6c8, 0x6c9, 0x6ca, 0x6cb,
9334
35.6k
      0x6cd, 0x6cf, 0x6d2, 0x6d3, 0x6d5, 0x6ee, 0x6ef, 0x710, 0x715,
9335
35.6k
      0x716, 0x717, 0x718, 0x719, 0x71e, 0x728, 0x72a, 0x72c, 0x72f,
9336
35.6k
      0x74d, 0x759, 0x75a, 0x75b, 0x854, 0x8aa, 0x8ab, 0x8ac};
9337
35.6k
  constexpr static uint32_t L[] = {0xa872};
9338
35.6k
  constexpr static uint32_t D[] = {
9339
35.6k
      0x620,  0x626,  0x628,  0x62a,  0x62b,  0x62c,  0x62d,  0x62e,  0x633,
9340
35.6k
      0x634,  0x635,  0x636,  0x637,  0x638,  0x639,  0x63a,  0x63b,  0x63c,
9341
35.6k
      0x63d,  0x63e,  0x63f,  0x641,  0x642,  0x643,  0x644,  0x645,  0x646,
9342
35.6k
      0x647,  0x649,  0x64a,  0x66e,  0x66f,  0x678,  0x679,  0x67a,  0x67b,
9343
35.6k
      0x67c,  0x67d,  0x67e,  0x67f,  0x680,  0x681,  0x682,  0x683,  0x684,
9344
35.6k
      0x685,  0x686,  0x687,  0x69a,  0x69b,  0x69c,  0x69d,  0x69e,  0x69f,
9345
35.6k
      0x6a0,  0x6a1,  0x6a2,  0x6a3,  0x6a4,  0x6a5,  0x6a6,  0x6a7,  0x6a8,
9346
35.6k
      0x6a9,  0x6aa,  0x6ab,  0x6ac,  0x6ad,  0x6ae,  0x6af,  0x6b0,  0x6b1,
9347
35.6k
      0x6b2,  0x6b3,  0x6b4,  0x6b5,  0x6b6,  0x6b7,  0x6b8,  0x6b9,  0x6ba,
9348
35.6k
      0x6bb,  0x6bc,  0x6bd,  0x6be,  0x6bf,  0x6c1,  0x6c2,  0x6cc,  0x6ce,
9349
35.6k
      0x6d0,  0x6d1,  0x6fa,  0x6fb,  0x6fc,  0x6ff,  0x712,  0x713,  0x714,
9350
35.6k
      0x71a,  0x71b,  0x71c,  0x71d,  0x71f,  0x720,  0x721,  0x722,  0x723,
9351
35.6k
      0x724,  0x725,  0x726,  0x727,  0x729,  0x72b,  0x72d,  0x72e,  0x74e,
9352
35.6k
      0x74f,  0x750,  0x751,  0x752,  0x753,  0x754,  0x755,  0x756,  0x757,
9353
35.6k
      0x758,  0x75c,  0x75d,  0x75e,  0x75f,  0x760,  0x761,  0x762,  0x763,
9354
35.6k
      0x764,  0x765,  0x766,  0x850,  0x851,  0x852,  0x853,  0x855,  0x8a0,
9355
35.6k
      0x8a2,  0x8a3,  0x8a4,  0x8a5,  0x8a6,  0x8a7,  0x8a8,  0x8a9,  0x1807,
9356
35.6k
      0x1820, 0x1821, 0x1822, 0x1823, 0x1824, 0x1825, 0x1826, 0x1827, 0x1828,
9357
35.6k
      0x1829, 0x182a, 0x182b, 0x182c, 0x182d, 0x182e, 0x182f, 0x1830, 0x1831,
9358
35.6k
      0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837, 0x1838, 0x1839, 0x183a,
9359
35.6k
      0x183b, 0x183c, 0x183d, 0x183e, 0x183f, 0x1840, 0x1841, 0x1842, 0x1843,
9360
35.6k
      0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x184a, 0x184b, 0x184c,
9361
35.6k
      0x184d, 0x184e, 0x184f, 0x1850, 0x1851, 0x1852, 0x1853, 0x1854, 0x1855,
9362
35.6k
      0x1856, 0x1857, 0x1858, 0x1859, 0x185a, 0x185b, 0x185c, 0x185d, 0x185e,
9363
35.6k
      0x185f, 0x1860, 0x1861, 0x1862, 0x1863, 0x1864, 0x1865, 0x1866, 0x1867,
9364
35.6k
      0x1868, 0x1869, 0x186a, 0x186b, 0x186c, 0x186d, 0x186e, 0x186f, 0x1870,
9365
35.6k
      0x1871, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, 0x1877, 0x1887, 0x1888,
9366
35.6k
      0x1889, 0x188a, 0x188b, 0x188c, 0x188d, 0x188e, 0x188f, 0x1890, 0x1891,
9367
35.6k
      0x1892, 0x1893, 0x1894, 0x1895, 0x1896, 0x1897, 0x1898, 0x1899, 0x189a,
9368
35.6k
      0x189b, 0x189c, 0x189d, 0x189e, 0x189f, 0x18a0, 0x18a1, 0x18a2, 0x18a3,
9369
35.6k
      0x18a4, 0x18a5, 0x18a6, 0x18a7, 0x18a8, 0x18aa, 0xa840, 0xa841, 0xa842,
9370
35.6k
      0xa843, 0xa844, 0xa845, 0xa846, 0xa847, 0xa848, 0xa849, 0xa84a, 0xa84b,
9371
35.6k
      0xa84c, 0xa84d, 0xa84e, 0xa84f, 0xa850, 0xa851, 0xa852, 0xa853, 0xa854,
9372
35.6k
      0xa855, 0xa856, 0xa857, 0xa858, 0xa859, 0xa85a, 0xa85b, 0xa85c, 0xa85d,
9373
35.6k
      0xa85e, 0xa85f, 0xa860, 0xa861, 0xa862, 0xa863, 0xa864, 0xa865, 0xa866,
9374
35.6k
      0xa867, 0xa868, 0xa869, 0xa86a, 0xa86b, 0xa86c, 0xa86d, 0xa86e, 0xa86f,
9375
35.6k
      0xa870, 0xa871};
9376
9377
248k
  for (size_t i = 0; i < label.size(); i++) {
9378
214k
    uint32_t c = label[i];
9379
214k
    if (c == 0x200c) {
9380
1.41k
      if (i > 0) {
9381
1.39k
        if (std::binary_search(std::begin(virama), std::end(virama),
9382
1.39k
                               label[i - 1])) {
9383
209
          return true;
9384
209
        }
9385
1.39k
      }
9386
1.20k
      if ((i == 0) || (i + 1 >= label.size())) {
9387
121
        return false;
9388
121
      }
9389
      // we go backward looking for L or D
9390
1.98k
      auto is_l_or_d = [](uint32_t code) {
9391
1.98k
        return std::binary_search(std::begin(L), std::end(L), code) ||
9392
1.98k
               std::binary_search(std::begin(D), std::end(D), code);
9393
1.98k
      };
9394
1.86k
      auto is_r_or_d = [](uint32_t code) {
9395
1.86k
        return std::binary_search(std::begin(R), std::end(R), code) ||
9396
1.86k
               std::binary_search(std::begin(D), std::end(D), code);
9397
1.86k
      };
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
952
              after.end());
9404
213k
    } else if (c == 0x200d) {
9405
686
      if (i > 0) {
9406
671
        if (std::binary_search(std::begin(virama), std::end(virama),
9407
671
                               label[i - 1])) {
9408
568
          return true;
9409
568
        }
9410
671
      }
9411
118
      return false;
9412
686
    }
9413
214k
  }
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
33.5k
  size_t last_non_nsm_char = find_last_not_of_nsm(label);
9446
33.5k
  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
33.5k
  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.67k
    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.34k
      for (size_t i = 0; i < last_non_nsm_char; i++) {
9464
2.92k
        const direction d = find_direction(label[i]);
9465
2.92k
        if (!(d == direction::L || d == direction::EN || d == direction::ES ||
9466
2.92k
              d == direction::CS || d == direction::ET || d == direction::ON ||
9467
2.92k
              d == direction::BN || d == direction::NSM)) {
9468
126
          return false;
9469
126
        }
9470
9471
2.79k
        if ((i == last_non_nsm_char) &&
9472
2.79k
            !(d == direction::L || d == direction::EN)) {
9473
0
          return false;
9474
0
        }
9475
2.79k
      }
9476
9477
423
      return true;
9478
9479
2.12k
    } else {
9480
      // Eval as RTL
9481
9482
2.12k
      bool has_an = false;
9483
2.12k
      bool has_en = false;
9484
7.00k
      for (size_t i = 0; i <= last_non_nsm_char; i++) {
9485
5.10k
        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.10k
        if ((d == direction::EN && ((has_en = true) && has_an)) ||
9490
5.10k
            (d == direction::AN && ((has_an = true) && has_en))) {
9491
23
          return false;
9492
23
        }
9493
9494
5.07k
        if (!(d == direction::R || d == direction::AL || d == direction::AN ||
9495
5.07k
              d == direction::EN || d == direction::ES || d == direction::CS ||
9496
5.07k
              d == direction::ET || d == direction::ON || d == direction::BN ||
9497
5.07k
              d == direction::NSM)) {
9498
144
          return false;
9499
144
        }
9500
9501
4.93k
        if (i == last_non_nsm_char &&
9502
4.93k
            !(d == direction::R || d == direction::AL || d == direction::AN ||
9503
1.96k
              d == direction::EN)) {
9504
63
          return false;
9505
63
        }
9506
4.93k
      }
9507
9508
1.89k
      return true;
9509
2.12k
    }
9510
2.67k
  }
9511
9512
30.9k
  return true;
9513
33.5k
}
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
31.4k
bool begins_with(std::u32string_view view, std::u32string_view prefix) {
9526
31.4k
  if (view.size() < prefix.size()) {
9527
6.89k
    return false;
9528
6.89k
  }
9529
  // constexpr as of C++20
9530
24.5k
  return std::equal(prefix.begin(), prefix.end(), view.begin());
9531
31.4k
}
9532
9533
56.3k
bool begins_with(std::string_view view, std::string_view prefix) {
9534
56.3k
  if (view.size() < prefix.size()) {
9535
27.1k
    return false;
9536
27.1k
  }
9537
  // constexpr as of C++20
9538
29.2k
  return std::equal(prefix.begin(), prefix.end(), view.begin());
9539
56.3k
}
9540
9541
29.3k
bool constexpr is_ascii(std::u32string_view view) {
9542
60.5k
  for (uint32_t c : view) {
9543
60.5k
    if (c >= 0x80) {
9544
26.6k
      return false;
9545
26.6k
    }
9546
60.5k
  }
9547
2.74k
  return true;
9548
29.3k
}
9549
9550
26.4k
bool constexpr is_ascii(std::string_view view) {
9551
323k
  for (uint8_t c : view) {
9552
323k
    if (c >= 0x80) {
9553
10.0k
      return false;
9554
10.0k
    }
9555
323k
  }
9556
16.4k
  return true;
9557
26.4k
}
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.3k
static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9585
14.3k
  static const std::string error = "";
9586
  // copy and map
9587
  // we could be more efficient by avoiding the copy when unnecessary.
9588
14.3k
  std::string mapped_string = std::string(ut8_string);
9589
14.3k
  ascii_map(mapped_string.data(), mapped_string.size());
9590
14.3k
  std::string out;
9591
14.3k
  size_t label_start = 0;
9592
9593
43.6k
  while (label_start != mapped_string.size()) {
9594
30.1k
    size_t loc_dot = mapped_string.find('.', label_start);
9595
30.1k
    bool is_last_label = (loc_dot == std::string_view::npos);
9596
30.1k
    size_t label_size = is_last_label ? mapped_string.size() - label_start
9597
30.1k
                                      : loc_dot - label_start;
9598
30.1k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9599
30.1k
    std::string_view label_view(mapped_string.data() + label_start, label_size);
9600
30.1k
    label_start += label_size_with_dot;
9601
30.1k
    if (label_size == 0) {
9602
      // empty label? Nothing to do.
9603
25.5k
    } else if (begins_with(label_view, "xn--")) {
9604
      // The xn-- part is the expensive game.
9605
8.12k
      out.append(label_view);
9606
8.12k
      std::string_view puny_segment_ascii(
9607
8.12k
          out.data() + out.size() - label_view.size() + 4,
9608
8.12k
          label_view.size() - 4);
9609
8.12k
      std::u32string tmp_buffer;
9610
8.12k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9611
8.12k
      if (!is_ok) {
9612
219
        return error;
9613
219
      }
9614
7.90k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9615
7.90k
      if (tmp_buffer != post_map) {
9616
390
        return error;
9617
390
      }
9618
7.51k
      std::u32string pre_normal = post_map;
9619
7.51k
      normalize(post_map);
9620
7.51k
      if (post_map != pre_normal) {
9621
47
        return error;
9622
47
      }
9623
7.46k
      if (post_map.empty()) {
9624
147
        return error;
9625
147
      }
9626
7.32k
      if (!is_label_valid(post_map)) {
9627
24
        return error;
9628
24
      }
9629
17.4k
    } else {
9630
17.4k
      out.append(label_view);
9631
17.4k
    }
9632
29.2k
    if (!is_last_label) {
9633
17.7k
      out.push_back('.');
9634
17.7k
    }
9635
29.2k
  }
9636
13.5k
  return out;
9637
14.3k
}
9638
9639
// We return "" on error.
9640
24.0k
std::string to_ascii(std::string_view ut8_string) {
9641
24.0k
  if (is_ascii(ut8_string)) {
9642
14.3k
    return from_ascii_to_ascii(ut8_string);
9643
14.3k
  }
9644
9.71k
  static const std::string error = "";
9645
  // We convert to UTF-32
9646
9.71k
  size_t utf32_length =
9647
9.71k
      ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9648
9.71k
  std::u32string utf32(utf32_length, '\0');
9649
9.71k
  size_t actual_utf32_length = ada::idna::utf8_to_utf32(
9650
9.71k
      ut8_string.data(), ut8_string.size(), utf32.data());
9651
9.71k
  if (actual_utf32_length == 0) {
9652
3.02k
    return error;
9653
3.02k
  }
9654
  // mapping
9655
6.68k
  utf32 = ada::idna::map(utf32);
9656
6.68k
  normalize(utf32);
9657
6.68k
  std::string out;
9658
6.68k
  size_t label_start = 0;
9659
9660
38.8k
  while (label_start != utf32.size()) {
9661
33.3k
    size_t loc_dot = utf32.find('.', label_start);
9662
33.3k
    bool is_last_label = (loc_dot == std::string_view::npos);
9663
33.3k
    size_t label_size =
9664
33.3k
        is_last_label ? utf32.size() - label_start : loc_dot - label_start;
9665
33.3k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9666
33.3k
    std::u32string_view label_view(utf32.data() + label_start, label_size);
9667
33.3k
    label_start += label_size_with_dot;
9668
33.3k
    if (label_size == 0) {
9669
      // empty label? Nothing to do.
9670
31.4k
    } 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.4k
      for (char32_t c : label_view) {
9673
23.4k
        if (c >= 0x80) {
9674
22
          return error;
9675
22
        }
9676
23.4k
        out += (unsigned char)(c);
9677
23.4k
      }
9678
2.06k
      std::string_view puny_segment_ascii(
9679
2.06k
          out.data() + out.size() - label_view.size() + 4,
9680
2.06k
          label_view.size() - 4);
9681
2.06k
      std::u32string tmp_buffer;
9682
2.06k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9683
2.06k
      if (!is_ok) {
9684
52
        return error;
9685
52
      }
9686
2.01k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9687
2.01k
      if (tmp_buffer != post_map) {
9688
77
        return error;
9689
77
      }
9690
1.93k
      std::u32string pre_normal = post_map;
9691
1.93k
      normalize(post_map);
9692
1.93k
      if (post_map != pre_normal) {
9693
39
        return error;
9694
39
      }
9695
1.89k
      if (post_map.empty()) {
9696
83
        return error;
9697
83
      }
9698
1.81k
      if (!is_label_valid(post_map)) {
9699
14
        return error;
9700
14
      }
9701
29.3k
    } else {
9702
      // The fast path here is an ascii label.
9703
29.3k
      if (is_ascii(label_view)) {
9704
        // no validation needed.
9705
24.0k
        for (char32_t c : label_view) {
9706
24.0k
          out += (unsigned char)(c);
9707
24.0k
        }
9708
26.6k
      } else {
9709
        // slow path.
9710
        // first check validity.
9711
26.6k
        if (!is_label_valid(label_view)) {
9712
942
          return error;
9713
942
        }
9714
        // It is valid! So now we must encode it as punycode...
9715
25.7k
        out.append("xn--");
9716
25.7k
        bool is_ok = ada::idna::utf32_to_punycode(label_view, out);
9717
25.7k
        if (!is_ok) {
9718
0
          return error;
9719
0
        }
9720
25.7k
      }
9721
29.3k
    }
9722
32.1k
    if (!is_last_label) {
9723
27.0k
      out.push_back('.');
9724
27.0k
    }
9725
32.1k
  }
9726
5.45k
  return out;
9727
6.68k
}
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
44.7k
  while (label_start < input.size()) {
9743
30.8k
    size_t loc_dot = input.find('.', label_start);
9744
30.8k
    bool is_last_label = (loc_dot == std::string_view::npos);
9745
30.8k
    size_t label_size =
9746
30.8k
        is_last_label ? input.size() - label_start : loc_dot - label_start;
9747
30.8k
    auto label_view = std::string_view(input.data() + label_start, label_size);
9748
9749
30.8k
    if (ada::idna::begins_with(label_view, "xn--") &&
9750
30.8k
        ada::idna::is_ascii(label_view)) {
9751
2.11k
      label_view.remove_prefix(4);
9752
2.11k
      if (ada::idna::verify_punycode(label_view)) {
9753
1.37k
        std::u32string tmp_buffer;
9754
1.37k
        if (ada::idna::punycode_to_utf32(label_view, tmp_buffer)) {
9755
1.37k
          auto utf8_size = ada::idna::utf8_length_from_utf32(tmp_buffer.data(),
9756
1.37k
                                                             tmp_buffer.size());
9757
1.37k
          std::string final_utf8(utf8_size, '\0');
9758
1.37k
          ada::idna::utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9759
1.37k
                                   final_utf8.data());
9760
1.37k
          output.append(final_utf8);
9761
1.37k
        } 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.37k
      } else {
9768
748
        output.append(std::string_view(input.data() + label_start, label_size));
9769
748
      }
9770
28.7k
    } else {
9771
28.7k
      output.append(label_view);
9772
28.7k
    }
9773
9774
30.8k
    if (!is_last_label) {
9775
18.8k
      output.push_back('.');
9776
18.8k
    }
9777
9778
30.8k
    label_start += label_size + 1;
9779
30.8k
  }
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.4k
constexpr uint64_t broadcast(uint8_t v) noexcept {
9799
88.4k
  return 0x101010101010101ull * v;
9800
88.4k
}
9801
9802
29.4k
constexpr bool to_lower_ascii(char* input, size_t length) noexcept {
9803
29.4k
  uint64_t broadcast_80 = broadcast(0x80);
9804
29.4k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
9805
29.4k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
9806
29.4k
  uint64_t non_ascii = 0;
9807
29.4k
  size_t i = 0;
9808
9809
45.9k
  for (; i + 7 < length; i += 8) {
9810
16.5k
    uint64_t word{};
9811
16.5k
    memcpy(&word, input + i, sizeof(word));
9812
16.5k
    non_ascii |= (word & broadcast_80);
9813
16.5k
    word ^=
9814
16.5k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
9815
16.5k
    memcpy(input + i, &word, sizeof(word));
9816
16.5k
  }
9817
29.4k
  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.4k
  return non_ascii == 0;
9826
29.4k
}
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.0k
    std::string_view user_input) noexcept {
9864
  // first check for short strings in which case we do it naively.
9865
87.0k
  if (user_input.size() < 16) {  // slow path
9866
334k
    for (size_t i = 0; i < user_input.size(); i++) {
9867
261k
      if (user_input[i] == '\r' || user_input[i] == '\n' ||
9868
261k
          user_input[i] == '\t') {
9869
680
        return true;
9870
680
      }
9871
261k
    }
9872
72.0k
    return false;
9873
72.7k
  }
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.3k
  for (; i + 15 < user_input.size(); i += 16) {
9881
59.1k
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
9882
59.1k
    running = _mm_or_si128(
9883
59.1k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
9884
59.1k
                                           _mm_cmpeq_epi8(word, mask2))),
9885
59.1k
        _mm_cmpeq_epi8(word, mask3));
9886
59.1k
  }
9887
14.2k
  if (i < user_input.size()) {
9888
11.8k
    __m128i word = _mm_loadu_si128(
9889
11.8k
        (const __m128i*)(user_input.data() + user_input.length() - 16));
9890
11.8k
    running = _mm_or_si128(
9891
11.8k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
9892
11.8k
                                           _mm_cmpeq_epi8(word, mask2))),
9893
11.8k
        _mm_cmpeq_epi8(word, mask3));
9894
11.8k
  }
9895
14.2k
  return _mm_movemask_epi8(running) != 0;
9896
87.0k
}
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
36.9k
    const char c) noexcept {
9944
36.9k
  return is_forbidden_host_code_point_table[uint8_t(c)];
9945
36.9k
}
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
528k
    const char c) noexcept {
9967
528k
  return is_forbidden_domain_code_point_table[uint8_t(c)];
9968
528k
}
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
184k
  for (; i + 4 <= length; i += 4) {
9975
168k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
9976
168k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 1])];
9977
168k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 2])];
9978
168k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 3])];
9979
168k
  }
9980
38.7k
  for (; i < length; i++) {
9981
22.9k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
9982
22.9k
  }
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.8k
                                              size_t length) noexcept {
10008
14.8k
  size_t i = 0;
10009
14.8k
  uint8_t accumulator{};
10010
86.1k
  for (; i + 4 <= length; i += 4) {
10011
71.2k
    accumulator |=
10012
71.2k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10013
71.2k
    accumulator |=
10014
71.2k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 1])];
10015
71.2k
    accumulator |=
10016
71.2k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 2])];
10017
71.2k
    accumulator |=
10018
71.2k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 3])];
10019
71.2k
  }
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.8k
  return accumulator;
10025
14.8k
}
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
124k
ada_really_inline constexpr bool is_alnum_plus(const char c) noexcept {
10045
124k
  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
124k
}
10050
10051
40.5k
ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept {
10052
40.5k
  return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
10053
40.5k
         (c >= 'a' && c <= 'f');
10054
40.5k
}
10055
10056
98.0k
ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept {
10057
98.0k
  return (unsigned char)c <= ' ';
10058
98.0k
}
10059
10060
ada_really_inline constexpr bool is_ascii_tab_or_newline(
10061
808k
    const char c) noexcept {
10062
808k
  return c == '\t' || c == '\n' || c == '\r';
10063
808k
}
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.1k
    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.1k
  uint64_t half_length = uint64_t(input.size()) / 2;
10075
75.1k
  if (half_length - 1 > 2) {
10076
42.0k
    return false;
10077
42.0k
  }
10078
  // We have a string of length 2, 4 or 6.
10079
  // We now check the first character:
10080
33.1k
  if ((input[0] != '.') && (input[0] != '%')) {
10081
7.14k
    return false;
10082
7.14k
  }
10083
  // We are unlikely the get beyond this point.
10084
25.9k
  int hash_value = (input.size() + (unsigned)(input[0])) & 3;
10085
25.9k
  const std::string_view target = table_is_double_dot_path_segment[hash_value];
10086
25.9k
  if (target.size() != input.size()) {
10087
8.34k
    return false;
10088
8.34k
  }
10089
  // We almost never get here.
10090
  // Optimizing the rest is relatively unimportant.
10091
17.6k
  auto prefix_equal_unsafe = [](std::string_view a, std::string_view b) {
10092
17.6k
    uint16_t A, B;
10093
17.6k
    memcpy(&A, a.data(), sizeof(A));
10094
17.6k
    memcpy(&B, b.data(), sizeof(B));
10095
17.6k
    return A == B;
10096
17.6k
  };
10097
17.6k
  if (!prefix_equal_unsafe(input, target)) {
10098
1.58k
    return false;
10099
1.58k
  }
10100
21.7k
  for (size_t i = 2; i < input.size(); i++) {
10101
8.80k
    char c = input[i];
10102
8.80k
    if ((uint8_t((c | 0x20) - 0x61) <= 25 ? (c | 0x20) : c) != target[i]) {
10103
3.07k
      return false;
10104
3.07k
    }
10105
8.80k
  }
10106
12.9k
  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.0k
}
10116
10117
ada_really_inline constexpr bool is_single_dot_path_segment(
10118
124k
    std::string_view input) noexcept {
10119
124k
  return input == "." || input == "%2e" || input == "%2E";
10120
124k
}
10121
10122
31.0k
ada_really_inline constexpr bool is_lowercase_hex(const char c) noexcept {
10123
31.0k
  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
10124
31.0k
}
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
35.8k
unsigned constexpr convert_hex_to_binary(const char c) noexcept {
10131
35.8k
  return hex_to_binary_table[c - '0'];
10132
35.8k
}
10133
10134
6.41k
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.41k
  if (first_percent == std::string_view::npos) {
10138
5.05k
    return std::string(input);
10139
5.05k
  }
10140
1.36k
  std::string dest;
10141
1.36k
  dest.reserve(input.length());
10142
1.36k
  dest.append(input.substr(0, first_percent));
10143
1.36k
  const char* pointer = input.data() + first_percent;
10144
1.36k
  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
26.9k
  while (pointer < end) {
10148
25.5k
    const char ch = pointer[0];
10149
25.5k
    size_t remaining = end - pointer - 1;
10150
25.5k
    if (ch != '%' || remaining < 2 ||
10151
25.5k
        (  // ch == '%' && // It is unnecessary to check that ch == '%'.
10152
17.2k
            (!is_ascii_hex_digit(pointer[1]) ||
10153
17.2k
             !is_ascii_hex_digit(pointer[2])))) {
10154
10.1k
      dest += ch;
10155
10.1k
      pointer++;
10156
10.1k
      continue;
10157
15.4k
    } else {
10158
15.4k
      unsigned a = convert_hex_to_binary(pointer[1]);
10159
15.4k
      unsigned b = convert_hex_to_binary(pointer[2]);
10160
15.4k
      char c = static_cast<char>(a * 16 + b);
10161
15.4k
      dest += c;
10162
15.4k
      pointer += 3;
10163
15.4k
    }
10164
25.5k
  }
10165
1.36k
  return dest;
10166
6.41k
}
10167
10168
std::string percent_encode(const std::string_view input,
10169
57.5k
                           const uint8_t character_set[]) {
10170
57.5k
  auto pointer =
10171
271k
      std::find_if(input.begin(), input.end(), [character_set](const char c) {
10172
271k
        return character_sets::bit_at(character_set, c);
10173
271k
      });
10174
  // Optimization: Don't iterate if percent encode is not required
10175
57.5k
  if (pointer == input.end()) {
10176
42.6k
    return std::string(input);
10177
42.6k
  }
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
292k
      result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10187
292k
    } else {
10188
116k
      result += *pointer;
10189
116k
    }
10190
408k
  }
10191
10192
14.9k
  return result;
10193
57.5k
}
10194
10195
template <bool append>
10196
bool percent_encode(const std::string_view input, const uint8_t character_set[],
10197
42.7k
                    std::string& out) {
10198
42.7k
  ada_log("percent_encode ", input, " to output string while ",
10199
42.7k
          append ? "appending" : "overwriting");
10200
42.7k
  auto pointer =
10201
99.0k
      std::find_if(input.begin(), input.end(), [character_set](const char c) {
10202
99.0k
        return character_sets::bit_at(character_set, c);
10203
99.0k
      });
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
67.0k
      std::find_if(input.begin(), input.end(), [character_set](const char c) {
10202
67.0k
        return character_sets::bit_at(character_set, c);
10203
67.0k
      });
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
32.0k
      std::find_if(input.begin(), input.end(), [character_set](const char c) {
10202
32.0k
        return character_sets::bit_at(character_set, c);
10203
32.0k
      });
10204
42.7k
  ada_log("percent_encode done checking, moved to ",
10205
42.7k
          std::distance(input.begin(), pointer));
10206
10207
  // Optimization: Don't iterate if percent encode is not required
10208
42.7k
  if (pointer == input.end()) {
10209
24.3k
    ada_log("percent_encode encoding not needed.");
10210
24.3k
    return false;
10211
24.3k
  }
10212
18.3k
  if (!append) {
10213
17.0k
    out.clear();
10214
17.0k
  }
10215
18.3k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10216
18.3k
          " bytes");
10217
18.3k
  out.append(input.data(), std::distance(input.begin(), pointer));
10218
18.3k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10219
18.3k
          " bytes");
10220
263k
  for (; pointer != input.end(); pointer++) {
10221
245k
    if (character_sets::bit_at(character_set, *pointer)) {
10222
194k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10223
194k
    } else {
10224
51.1k
      out += *pointer;
10225
51.1k
    }
10226
245k
  }
10227
18.3k
  return true;
10228
42.7k
}
bool ada::unicode::percent_encode<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Line
Count
Source
10197
38.4k
                    std::string& out) {
10198
38.4k
  ada_log("percent_encode ", input, " to output string while ",
10199
38.4k
          append ? "appending" : "overwriting");
10200
38.4k
  auto pointer =
10201
38.4k
      std::find_if(input.begin(), input.end(), [character_set](const char c) {
10202
38.4k
        return character_sets::bit_at(character_set, c);
10203
38.4k
      });
10204
38.4k
  ada_log("percent_encode done checking, moved to ",
10205
38.4k
          std::distance(input.begin(), pointer));
10206
10207
  // Optimization: Don't iterate if percent encode is not required
10208
38.4k
  if (pointer == input.end()) {
10209
21.3k
    ada_log("percent_encode encoding not needed.");
10210
21.3k
    return false;
10211
21.3k
  }
10212
17.0k
  if (!append) {
10213
17.0k
    out.clear();
10214
17.0k
  }
10215
17.0k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10216
17.0k
          " bytes");
10217
17.0k
  out.append(input.data(), std::distance(input.begin(), pointer));
10218
17.0k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10219
17.0k
          " bytes");
10220
208k
  for (; pointer != input.end(); pointer++) {
10221
191k
    if (character_sets::bit_at(character_set, *pointer)) {
10222
155k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10223
155k
    } else {
10224
36.5k
      out += *pointer;
10225
36.5k
    }
10226
191k
  }
10227
17.0k
  return true;
10228
38.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.35k
                    std::string& out) {
10198
4.35k
  ada_log("percent_encode ", input, " to output string while ",
10199
4.35k
          append ? "appending" : "overwriting");
10200
4.35k
  auto pointer =
10201
4.35k
      std::find_if(input.begin(), input.end(), [character_set](const char c) {
10202
4.35k
        return character_sets::bit_at(character_set, c);
10203
4.35k
      });
10204
4.35k
  ada_log("percent_encode done checking, moved to ",
10205
4.35k
          std::distance(input.begin(), pointer));
10206
10207
  // Optimization: Don't iterate if percent encode is not required
10208
4.35k
  if (pointer == input.end()) {
10209
3.01k
    ada_log("percent_encode encoding not needed.");
10210
3.01k
    return false;
10211
3.01k
  }
10212
1.34k
  if (!append) {
10213
0
    out.clear();
10214
0
  }
10215
1.34k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10216
1.34k
          " bytes");
10217
1.34k
  out.append(input.data(), std::distance(input.begin(), pointer));
10218
1.34k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10219
1.34k
          " bytes");
10220
55.2k
  for (; pointer != input.end(); pointer++) {
10221
53.8k
    if (character_sets::bit_at(character_set, *pointer)) {
10222
39.3k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10223
39.3k
    } else {
10224
14.5k
      out += *pointer;
10225
14.5k
    }
10226
53.8k
  }
10227
1.34k
  return true;
10228
4.35k
}
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
928
    percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
10236
928
    input = percent_decoded_buffer;
10237
928
  }
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.91k
                                idna_ascii.data(), idna_ascii.size())) {
10242
3.18k
    return false;
10243
3.18k
  }
10244
6.93k
  out = std::move(idna_ascii);
10245
6.93k
  return true;
10246
10.1k
}
10247
10248
std::string percent_encode(const std::string_view input,
10249
1.53k
                           const uint8_t character_set[], size_t index) {
10250
1.53k
  std::string out;
10251
1.53k
  out.append(input.data(), index);
10252
1.53k
  auto pointer = input.begin() + index;
10253
57.1k
  for (; pointer != input.end(); pointer++) {
10254
55.6k
    if (character_sets::bit_at(character_set, *pointer)) {
10255
47.9k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10256
47.9k
    } else {
10257
7.66k
      out += *pointer;
10258
7.66k
    }
10259
55.6k
  }
10260
1.53k
  return out;
10261
1.53k
}
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
603
    size_t& compress_length) noexcept {
10279
2.40k
  for (size_t i = 0; i < 8; i++) {
10280
2.01k
    if (address[i] == 0) {
10281
762
      size_t next = i + 1;
10282
3.32k
      while (next != 8 && address[next] == 0) ++next;
10283
762
      const size_t count = next - i;
10284
762
      if (compress_length < count) {
10285
561
        compress_length = count;
10286
561
        compress = i;
10287
561
        if (next == 8) break;
10288
353
        i = next;
10289
353
      }
10290
762
    }
10291
2.01k
  }
10292
603
}
10293
10294
603
std::string ipv6(const std::array<uint16_t, 8>& address) noexcept {
10295
603
  size_t compress_length = 0;  // The length of a long sequence of zeros.
10296
603
  size_t compress = 0;         // The start of a long sequence of zeros.
10297
603
  find_longest_sequence_of_ipv6_pieces(address, compress, compress_length);
10298
10299
603
  if (compress_length <= 1) {
10300
    // Optimization opportunity: Find a faster way then snprintf for imploding
10301
    // and return here.
10302
113
    compress = compress_length = 8;
10303
113
  }
10304
10305
603
  std::string output(4 * 8 + 7 + 2, '\0');
10306
603
  size_t piece_index = 0;
10307
603
  char* point = output.data();
10308
603
  char* point_end = output.data() + output.size();
10309
603
  *point++ = '[';
10310
2.08k
  while (true) {
10311
2.08k
    if (piece_index == compress) {
10312
490
      *point++ = ':';
10313
      // If we skip a value initially, we need to write '::', otherwise
10314
      // a single ':' will do since it follows a previous ':'.
10315
490
      if (piece_index == 0) {
10316
293
        *point++ = ':';
10317
293
      }
10318
490
      piece_index += compress_length;
10319
490
      if (piece_index == 8) {
10320
204
        break;
10321
204
      }
10322
490
    }
10323
1.88k
    point = std::to_chars(point, point_end, address[piece_index], 16).ptr;
10324
1.88k
    piece_index++;
10325
1.88k
    if (piece_index == 8) {
10326
399
      break;
10327
399
    }
10328
1.48k
    *point++ = ':';
10329
1.48k
  }
10330
603
  *point++ = ']';
10331
603
  output.resize(point - output.data());
10332
603
  return output;
10333
603
}
10334
10335
3.92k
std::string ipv4(const uint64_t address) noexcept {
10336
3.92k
  std::string output(15, '\0');
10337
3.92k
  char* point = output.data();
10338
3.92k
  char* point_end = output.data() + output.size();
10339
3.92k
  point = std::to_chars(point, point_end, uint8_t(address >> 24)).ptr;
10340
15.6k
  for (int i = 2; i >= 0; i--) {
10341
11.7k
    *point++ = '.';
10342
11.7k
    point = std::to_chars(point, point_end, uint8_t(address >> (i * 8))).ptr;
10343
11.7k
  }
10344
3.92k
  output.resize(point - output.data());
10345
3.92k
  return output;
10346
3.92k
}
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.1k
    std::string_view input, const result_type* base_url) {
10359
59.1k
  result_type u = ada::parser::parse_url<result_type>(input, base_url);
10360
59.1k
  if (!u.is_valid) {
10361
30.1k
    return tl::unexpected(errors::generic_error);
10362
30.1k
  }
10363
28.9k
  return u;
10364
59.1k
}
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.23k
    return tl::unexpected(errors::generic_error);
10362
6.23k
  }
10363
8.10k
  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
44.8k
    std::string_view input, const result_type* base_url) {
10359
44.8k
  result_type u = ada::parser::parse_url<result_type>(input, base_url);
10360
44.8k
  if (!u.is_valid) {
10361
23.9k
    return tl::unexpected(errors::generic_error);
10362
23.9k
  }
10363
20.8k
  return u;
10364
44.8k
}
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
208
    tmp_buffer = input;
10377
208
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
10378
208
    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.13k
    path = "/";
10385
12.8k
  } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
10386
713
    helpers::parse_prepared_path(internal_input.substr(1),
10387
713
                                 ada::scheme::type::FILE, path);
10388
12.0k
  } else {
10389
12.0k
    helpers::parse_prepared_path(internal_input, ada::scheme::type::FILE, path);
10390
12.0k
  }
10391
13.9k
  return "file://" + path;
10392
13.9k
}
10393
10394
27.8k
bool can_parse(std::string_view input, const std::string_view* base_input) {
10395
27.8k
  ada::result<ada::url_aggregator> base;
10396
27.8k
  ada::url_aggregator* base_pointer = nullptr;
10397
27.8k
  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.61k
    base_pointer = &base.value();
10403
2.61k
  }
10404
16.5k
  return ada::parse<url_aggregator>(input, base_pointer).has_value();
10405
27.8k
}
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.1k
    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.1k
  size_t location_of_first = input.find('#');
10508
59.1k
  if (location_of_first == std::string_view::npos) {
10509
57.8k
    return std::nullopt;
10510
57.8k
  }
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.1k
}
10516
10517
ada_really_inline bool shorten_path(std::string& path,
10518
12.9k
                                    ada::scheme::type type) noexcept {
10519
12.9k
  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
12.9k
  if (type == ada::scheme::type::FILE &&
10525
12.9k
      first_delimiter == std::string_view::npos && !path.empty()) {
10526
6.40k
    if (checkers::is_normalized_windows_drive_letter(
10527
6.40k
            helpers::substring(path, 1))) {
10528
1.64k
      return false;
10529
1.64k
    }
10530
6.40k
  }
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
6.94k
    path.erase(last_delimiter);
10536
6.94k
    return true;
10537
6.94k
  }
10538
10539
4.36k
  return false;
10540
11.3k
}
10541
10542
ada_really_inline bool shorten_path(std::string_view& path,
10543
290
                                    ada::scheme::type type) noexcept {
10544
290
  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
290
  if (type == ada::scheme::type::FILE &&
10550
290
      first_delimiter == std::string_view::npos && !path.empty()) {
10551
64
    if (checkers::is_normalized_windows_drive_letter(
10552
64
            helpers::substring(path, 1))) {
10553
5
      return false;
10554
5
    }
10555
64
  }
10556
10557
  // Remove path's last item, if any.
10558
285
  if (!path.empty()) {
10559
267
    size_t slash_loc = path.rfind('/');
10560
267
    if (slash_loc != std::string_view::npos) {
10561
248
      path.remove_suffix(path.size() - slash_loc);
10562
248
      return true;
10563
248
    }
10564
267
  }
10565
10566
37
  return false;
10567
285
}
10568
10569
ada_really_inline void remove_ascii_tab_or_newline(
10570
63.8k
    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.8k
  input.erase(std::remove_if(input.begin(), input.end(),
10574
808k
                             [](char c) {
10575
808k
                               return ada::unicode::is_ascii_tab_or_newline(c);
10576
808k
                             }),
10577
63.8k
              input.end());
10578
63.8k
}
10579
10580
ada_really_inline std::string_view substring(std::string_view input,
10581
80.4k
                                             size_t pos) noexcept {
10582
80.4k
  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.4k
  return input.substr(pos);
10586
80.4k
}
10587
10588
12
ada_really_inline void resize(std::string_view& input, size_t pos) noexcept {
10589
12
  ADA_ASSERT_TRUE(pos <= input.size());
10590
12
  input.remove_suffix(input.size() - pos);
10591
12
}
10592
10593
// computes the number of trailing zeroes
10594
// this is a private inline function only defined in this source file.
10595
8.25k
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.25k
  return __builtin_ctzl(input_num);
10604
8.25k
#endif  // ADA_REGULAR_VISUAL_STUDIO
10605
8.25k
}
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
ada_really_inline size_t find_next_host_delimiter_special(
10612
    std::string_view view, size_t location) noexcept {
10613
  // first check for short strings in which case we do it naively.
10614
  if (view.size() - location < 16) {  // slow path
10615
    for (size_t i = location; i < view.size(); i++) {
10616
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
10617
          view[i] == '?' || view[i] == '[') {
10618
        return i;
10619
      }
10620
    }
10621
    return size_t(view.size());
10622
  }
10623
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
10624
    uint8x16_t bit_mask = {0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
10625
                           0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80};
10626
    uint8x16_t minput = vandq_u8(input, bit_mask);
10627
    uint8x16_t tmp = vpaddq_u8(minput, minput);
10628
    tmp = vpaddq_u8(tmp, tmp);
10629
    tmp = vpaddq_u8(tmp, tmp);
10630
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
10631
  };
10632
10633
  // fast path for long strings (expected to be common)
10634
  size_t i = location;
10635
  uint8x16_t low_mask = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
10636
                         0x00, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x03};
10637
  uint8x16_t high_mask = {0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00,
10638
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
10639
  uint8x16_t fmask = vmovq_n_u8(0xf);
10640
  uint8x16_t zero{0};
10641
  for (; i + 15 < view.size(); i += 16) {
10642
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
10643
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
10644
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
10645
    uint8x16_t classify = vandq_u8(lowpart, highpart);
10646
    if (vmaxvq_u8(classify) != 0) {
10647
      uint8x16_t is_zero = vceqq_u8(classify, zero);
10648
      uint16_t is_non_zero = ~to_bitmask(is_zero);
10649
      return i + trailing_zeroes(is_non_zero);
10650
    }
10651
  }
10652
10653
  if (i < view.size()) {
10654
    uint8x16_t word =
10655
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
10656
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
10657
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
10658
    uint8x16_t classify = vandq_u8(lowpart, highpart);
10659
    if (vmaxvq_u8(classify) != 0) {
10660
      uint8x16_t is_zero = vceqq_u8(classify, zero);
10661
      uint16_t is_non_zero = ~to_bitmask(is_zero);
10662
      return view.length() - 16 + trailing_zeroes(is_non_zero);
10663
    }
10664
  }
10665
  return size_t(view.size());
10666
}
10667
#elif ADA_SSE2
10668
ada_really_inline size_t find_next_host_delimiter_special(
10669
38.6k
    std::string_view view, size_t location) noexcept {
10670
  // first check for short strings in which case we do it naively.
10671
38.6k
  if (view.size() - location < 16) {  // slow path
10672
83.5k
    for (size_t i = location; i < view.size(); i++) {
10673
58.6k
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
10674
58.6k
          view[i] == '?' || view[i] == '[') {
10675
6.18k
        return i;
10676
6.18k
      }
10677
58.6k
    }
10678
24.9k
    return size_t(view.size());
10679
31.0k
  }
10680
  // fast path for long strings (expected to be common)
10681
7.52k
  size_t i = location;
10682
7.52k
  const __m128i mask1 = _mm_set1_epi8(':');
10683
7.52k
  const __m128i mask2 = _mm_set1_epi8('/');
10684
7.52k
  const __m128i mask3 = _mm_set1_epi8('\\');
10685
7.52k
  const __m128i mask4 = _mm_set1_epi8('?');
10686
7.52k
  const __m128i mask5 = _mm_set1_epi8('[');
10687
10688
22.6k
  for (; i + 15 < view.size(); i += 16) {
10689
19.5k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
10690
19.5k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
10691
19.5k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
10692
19.5k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
10693
19.5k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
10694
19.5k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
10695
19.5k
    __m128i m = _mm_or_si128(
10696
19.5k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
10697
19.5k
    int mask = _mm_movemask_epi8(m);
10698
19.5k
    if (mask != 0) {
10699
4.40k
      return i + trailing_zeroes(mask);
10700
4.40k
    }
10701
19.5k
  }
10702
3.12k
  if (i < view.size()) {
10703
2.78k
    __m128i word =
10704
2.78k
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
10705
2.78k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
10706
2.78k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
10707
2.78k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
10708
2.78k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
10709
2.78k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
10710
2.78k
    __m128i m = _mm_or_si128(
10711
2.78k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
10712
2.78k
    int mask = _mm_movemask_epi8(m);
10713
2.78k
    if (mask != 0) {
10714
460
      return view.length() - 16 + trailing_zeroes(mask);
10715
460
    }
10716
2.78k
  }
10717
2.66k
  return size_t(view.length());
10718
3.12k
}
10719
#else
10720
// : / [ \\ ?
10721
static constexpr std::array<uint8_t, 256> special_host_delimiters =
10722
    []() constexpr {
10723
      std::array<uint8_t, 256> result{};
10724
      for (int i : {':', '/', '[', '\\', '?'}) {
10725
        result[i] = 1;
10726
      }
10727
      return result;
10728
    }();
10729
// credit: @the-moisrex recommended a table-based approach
10730
ada_really_inline size_t find_next_host_delimiter_special(
10731
    std::string_view view, size_t location) noexcept {
10732
  auto const str = view.substr(location);
10733
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
10734
    if (special_host_delimiters[(uint8_t)*pos]) {
10735
      return pos - str.begin() + location;
10736
    }
10737
  }
10738
  return size_t(view.size());
10739
}
10740
#endif
10741
10742
// starting at index location, this finds the next location of a character
10743
// :, /, ? or [. If none is found, view.size() is returned.
10744
// For use within get_host_delimiter_location.
10745
#if ADA_NEON
10746
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
10747
                                                  size_t location) noexcept {
10748
  // first check for short strings in which case we do it naively.
10749
  if (view.size() - location < 16) {  // slow path
10750
    for (size_t i = location; i < view.size(); i++) {
10751
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
10752
          view[i] == '[') {
10753
        return i;
10754
      }
10755
    }
10756
    return size_t(view.size());
10757
  }
10758
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
10759
    uint8x16_t bit_mask = {0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
10760
                           0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80};
10761
    uint8x16_t minput = vandq_u8(input, bit_mask);
10762
    uint8x16_t tmp = vpaddq_u8(minput, minput);
10763
    tmp = vpaddq_u8(tmp, tmp);
10764
    tmp = vpaddq_u8(tmp, tmp);
10765
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
10766
  };
10767
10768
  // fast path for long strings (expected to be common)
10769
  size_t i = location;
10770
  uint8x16_t low_mask = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
10771
                         0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x03};
10772
  uint8x16_t high_mask = {0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00,
10773
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
10774
  uint8x16_t fmask = vmovq_n_u8(0xf);
10775
  uint8x16_t zero{0};
10776
  for (; i + 15 < view.size(); i += 16) {
10777
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
10778
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
10779
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
10780
    uint8x16_t classify = vandq_u8(lowpart, highpart);
10781
    if (vmaxvq_u8(classify) != 0) {
10782
      uint8x16_t is_zero = vceqq_u8(classify, zero);
10783
      uint16_t is_non_zero = ~to_bitmask(is_zero);
10784
      return i + trailing_zeroes(is_non_zero);
10785
    }
10786
  }
10787
10788
  if (i < view.size()) {
10789
    uint8x16_t word =
10790
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
10791
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
10792
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
10793
    uint8x16_t classify = vandq_u8(lowpart, highpart);
10794
    if (vmaxvq_u8(classify) != 0) {
10795
      uint8x16_t is_zero = vceqq_u8(classify, zero);
10796
      uint16_t is_non_zero = ~to_bitmask(is_zero);
10797
      return view.length() - 16 + trailing_zeroes(is_non_zero);
10798
    }
10799
  }
10800
  return size_t(view.size());
10801
}
10802
#elif ADA_SSE2
10803
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
10804
12.1k
                                                  size_t location) noexcept {
10805
  // first check for short strings in which case we do it naively.
10806
12.1k
  if (view.size() - location < 16) {  // slow path
10807
13.7k
    for (size_t i = location; i < view.size(); i++) {
10808
7.66k
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
10809
7.66k
          view[i] == '[') {
10810
2.24k
        return i;
10811
2.24k
      }
10812
7.66k
    }
10813
6.13k
    return size_t(view.size());
10814
8.37k
  }
10815
  // fast path for long strings (expected to be common)
10816
3.74k
  size_t i = location;
10817
3.74k
  const __m128i mask1 = _mm_set1_epi8(':');
10818
3.74k
  const __m128i mask2 = _mm_set1_epi8('/');
10819
3.74k
  const __m128i mask4 = _mm_set1_epi8('?');
10820
3.74k
  const __m128i mask5 = _mm_set1_epi8('[');
10821
10822
6.84k
  for (; i + 15 < view.size(); i += 16) {
10823
6.34k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
10824
6.34k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
10825
6.34k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
10826
6.34k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
10827
6.34k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
10828
6.34k
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
10829
6.34k
    int mask = _mm_movemask_epi8(m);
10830
6.34k
    if (mask != 0) {
10831
3.24k
      return i + trailing_zeroes(mask);
10832
3.24k
    }
10833
6.34k
  }
10834
499
  if (i < view.size()) {
10835
370
    __m128i word =
10836
370
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
10837
370
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
10838
370
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
10839
370
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
10840
370
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
10841
370
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
10842
370
    int mask = _mm_movemask_epi8(m);
10843
370
    if (mask != 0) {
10844
147
      return view.length() - 16 + trailing_zeroes(mask);
10845
147
    }
10846
370
  }
10847
352
  return size_t(view.length());
10848
499
}
10849
#else
10850
// : / [ ?
10851
static constexpr std::array<uint8_t, 256> host_delimiters = []() constexpr {
10852
  std::array<uint8_t, 256> result{};
10853
  for (int i : {':', '/', '?', '['}) {
10854
    result[i] = 1;
10855
  }
10856
  return result;
10857
}();
10858
// credit: @the-moisrex recommended a table-based approach
10859
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
10860
                                                  size_t location) noexcept {
10861
  auto const str = view.substr(location);
10862
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
10863
    if (host_delimiters[(uint8_t)*pos]) {
10864
      return pos - str.begin() + location;
10865
    }
10866
  }
10867
  return size_t(view.size());
10868
}
10869
#endif
10870
10871
ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
10872
41.5k
    const bool is_special, std::string_view& view) noexcept {
10873
  /**
10874
   * The spec at https://url.spec.whatwg.org/#hostname-state expects us to
10875
   * compute a variable called insideBrackets but this variable is only used
10876
   * once, to check whether a ':' character was found outside brackets. Exact
10877
   * text: "Otherwise, if c is U+003A (:) and insideBrackets is false, then:".
10878
   * It is conceptually simpler and arguably more efficient to just return a
10879
   * Boolean indicating whether ':' was found outside brackets.
10880
   */
10881
41.5k
  const size_t view_size = view.size();
10882
41.5k
  size_t location = 0;
10883
41.5k
  bool found_colon = false;
10884
  /**
10885
   * Performance analysis:
10886
   *
10887
   * We are basically seeking the end of the hostname which can be indicated
10888
   * by the end of the view, or by one of the characters ':', '/', '?', '\\'
10889
   * (where '\\' is only applicable for special URLs). However, these must
10890
   * appear outside a bracket range. E.g., if you have [something?]fd: then the
10891
   * '?' does not count.
10892
   *
10893
   * So we can skip ahead to the next delimiter, as long as we include '[' in
10894
   * the set of delimiters, and that we handle it first.
10895
   *
10896
   * So the trick is to have a fast function that locates the next delimiter.
10897
   * Unless we find '[', then it only needs to be called once! Ideally, such a
10898
   * function would be provided by the C++ standard library, but it seems that
10899
   * find_first_of is not very fast, so we are forced to roll our own.
10900
   *
10901
   * We do not break into two loops for speed, but for clarity.
10902
   */
10903
41.5k
  if (is_special) {
10904
    // We move to the next delimiter.
10905
33.2k
    location = find_next_host_delimiter_special(view, location);
10906
    // Unless we find '[' then we are going only going to have to call
10907
    // find_next_host_delimiter_special once.
10908
38.6k
    for (; location < view_size;
10909
33.2k
         location = find_next_host_delimiter_special(view, location)) {
10910
11.0k
      if (view[location] == '[') {
10911
5.68k
        location = view.find(']', location);
10912
5.68k
        if (location == std::string_view::npos) {
10913
          // performance: view.find might get translated to a memchr, which
10914
          // has no notion of std::string_view::npos, so the code does not
10915
          // reflect the assembly.
10916
312
          location = view_size;
10917
312
          break;
10918
312
        }
10919
5.68k
      } else {
10920
5.36k
        found_colon = view[location] == ':';
10921
5.36k
        break;
10922
5.36k
      }
10923
11.0k
    }
10924
33.2k
  } else {
10925
    // We move to the next delimiter.
10926
8.32k
    location = find_next_host_delimiter(view, location);
10927
    // Unless we find '[' then we are going only going to have to call
10928
    // find_next_host_delimiter_special once.
10929
12.1k
    for (; location < view_size;
10930
8.32k
         location = find_next_host_delimiter(view, location)) {
10931
5.63k
      if (view[location] == '[') {
10932
4.01k
        location = view.find(']', location);
10933
4.01k
        if (location == std::string_view::npos) {
10934
          // performance: view.find might get translated to a memchr, which
10935
          // has no notion of std::string_view::npos, so the code does not
10936
          // reflect the assembly.
10937
215
          location = view_size;
10938
215
          break;
10939
215
        }
10940
4.01k
      } else {
10941
1.62k
        found_colon = view[location] == ':';
10942
1.62k
        break;
10943
1.62k
      }
10944
5.63k
    }
10945
8.32k
  }
10946
  // performance: remove_suffix may translate into a single instruction.
10947
41.5k
  view.remove_suffix(view_size - location);
10948
41.5k
  return {location, found_colon};
10949
41.5k
}
10950
10951
59.1k
ada_really_inline void trim_c0_whitespace(std::string_view& input) noexcept {
10952
63.8k
  while (!input.empty() &&
10953
63.8k
         ada::unicode::is_c0_control_or_space(input.front())) {
10954
4.70k
    input.remove_prefix(1);
10955
4.70k
  }
10956
61.5k
  while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
10957
2.37k
    input.remove_suffix(1);
10958
2.37k
  }
10959
59.1k
}
10960
10961
ada_really_inline void parse_prepared_path(std::string_view input,
10962
                                           ada::scheme::type type,
10963
18.4k
                                           std::string& path) {
10964
18.4k
  ada_log("parse_prepared_path ", input);
10965
18.4k
  uint8_t accumulator = checkers::path_signature(input);
10966
  // Let us first detect a trivial case.
10967
  // If it is special, we check that we have no dot, no %,  no \ and no
10968
  // character needing percent encoding. Otherwise, we check that we have no %,
10969
  // no dot, and no character needing percent encoding.
10970
18.4k
  constexpr uint8_t need_encoding = 1;
10971
18.4k
  constexpr uint8_t backslash_char = 2;
10972
18.4k
  constexpr uint8_t dot_char = 4;
10973
18.4k
  constexpr uint8_t percent_char = 8;
10974
18.4k
  bool special = type != ada::scheme::NOT_SPECIAL;
10975
18.4k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
10976
18.4k
                                      checkers::is_windows_drive_letter(input));
10977
18.4k
  bool trivial_path =
10978
18.4k
      (special ? (accumulator == 0)
10979
18.4k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
10980
2.31k
                  0)) &&
10981
18.4k
      (!may_need_slow_file_handling);
10982
18.4k
  if (accumulator == dot_char && !may_need_slow_file_handling) {
10983
    // '4' means that we have at least one dot, but nothing that requires
10984
    // percent encoding or decoding. The only part that is not trivial is
10985
    // that we may have single dots and double dots path segments.
10986
    // If we have such segments, then we either have a path that begins
10987
    // with '.' (easy to check), or we have the sequence './'.
10988
    // Note: input cannot be empty, it must at least contain one character ('.')
10989
    // Note: we know that '\' is not present.
10990
2.43k
    if (input[0] != '.') {
10991
1.85k
      size_t slashdot = input.find("/.");
10992
1.85k
      if (slashdot == std::string_view::npos) {  // common case
10993
1.08k
        trivial_path = true;
10994
1.08k
      } else {  // uncommon
10995
        // only three cases matter: /./, /.. or a final /
10996
766
        trivial_path =
10997
766
            !(slashdot + 2 == input.size() || input[slashdot + 2] == '.' ||
10998
766
              input[slashdot + 2] == '/');
10999
766
      }
11000
1.85k
    }
11001
2.43k
  }
11002
18.4k
  if (trivial_path) {
11003
7.99k
    ada_log("parse_path trivial");
11004
7.99k
    path += '/';
11005
7.99k
    path += input;
11006
7.99k
    return;
11007
7.99k
  }
11008
  // We are going to need to look a bit at the path, but let us see if we can
11009
  // ignore percent encoding *and* backslashes *and* percent characters.
11010
  // Except for the trivial case, this is likely to capture 99% of paths out
11011
  // there.
11012
10.4k
  bool fast_path =
11013
10.4k
      (special &&
11014
10.4k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
11015
10.4k
      (type != ada::scheme::type::FILE);
11016
10.4k
  if (fast_path) {
11017
488
    ada_log("parse_prepared_path fast");
11018
    // Here we don't need to worry about \ or percent encoding.
11019
    // We also do not have a file protocol. We might have dots, however,
11020
    // but dots must as appear as '.', and they cannot be encoded because
11021
    // the symbol '%' is not present.
11022
488
    size_t previous_location = 0;  // We start at 0.
11023
4.45k
    do {
11024
4.45k
      size_t new_location = input.find('/', previous_location);
11025
      // std::string_view path_view = input;
11026
      //  We process the last segment separately:
11027
4.45k
      if (new_location == std::string_view::npos) {
11028
488
        std::string_view path_view = input.substr(previous_location);
11029
488
        if (path_view == "..") {  // The path ends with ..
11030
          // e.g., if you receive ".." with an empty path, you go to "/".
11031
30
          if (path.empty()) {
11032
11
            path = '/';
11033
11
            return;
11034
11
          }
11035
          // Fast case where we have nothing to do:
11036
19
          if (path.back() == '/') {
11037
9
            return;
11038
9
          }
11039
          // If you have the path "/joe/myfriend",
11040
          // then you delete 'myfriend'.
11041
10
          path.resize(path.rfind('/') + 1);
11042
10
          return;
11043
19
        }
11044
458
        path += '/';
11045
458
        if (path_view != ".") {
11046
309
          path.append(path_view);
11047
309
        }
11048
458
        return;
11049
3.96k
      } else {
11050
        // This is a non-final segment.
11051
3.96k
        std::string_view path_view =
11052
3.96k
            input.substr(previous_location, new_location - previous_location);
11053
3.96k
        previous_location = new_location + 1;
11054
3.96k
        if (path_view == "..") {
11055
557
          size_t last_delimiter = path.rfind('/');
11056
557
          if (last_delimiter != std::string::npos) {
11057
295
            path.erase(last_delimiter);
11058
295
          }
11059
3.41k
        } else if (path_view != ".") {
11060
2.92k
          path += '/';
11061
2.92k
          path.append(path_view);
11062
2.92k
        }
11063
3.96k
      }
11064
4.45k
    } while (true);
11065
9.97k
  } else {
11066
9.97k
    ada_log("parse_path slow");
11067
    // we have reached the general case
11068
9.97k
    bool needs_percent_encoding = (accumulator & 1);
11069
9.97k
    std::string path_buffer_tmp;
11070
53.5k
    do {
11071
53.5k
      size_t location = (special && (accumulator & 2))
11072
53.5k
                            ? input.find_first_of("/\\")
11073
53.5k
                            : input.find('/');
11074
53.5k
      std::string_view path_view = input;
11075
53.5k
      if (location != std::string_view::npos) {
11076
43.5k
        path_view.remove_suffix(path_view.size() - location);
11077
43.5k
        input.remove_prefix(location + 1);
11078
43.5k
      }
11079
      // path_buffer is either path_view or it might point at a percent encoded
11080
      // temporary file.
11081
53.5k
      std::string_view path_buffer =
11082
53.5k
          (needs_percent_encoding &&
11083
53.5k
           ada::unicode::percent_encode<false>(
11084
26.5k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
11085
53.5k
              ? path_buffer_tmp
11086
53.5k
              : path_view;
11087
53.5k
      if (unicode::is_double_dot_path_segment(path_buffer)) {
11088
8.18k
        if ((helpers::shorten_path(path, type) || special) &&
11089
8.18k
            location == std::string_view::npos) {
11090
594
          path += '/';
11091
594
        }
11092
45.3k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
11093
45.3k
                 (location == std::string_view::npos)) {
11094
314
        path += '/';
11095
314
      }
11096
      // Otherwise, if path_buffer is not a single-dot path segment, then:
11097
45.0k
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
11098
        // If url's scheme is "file", url's path is empty, and path_buffer is a
11099
        // Windows drive letter, then replace the second code point in
11100
        // path_buffer with U+003A (:).
11101
41.0k
        if (type == ada::scheme::type::FILE && path.empty() &&
11102
41.0k
            checkers::is_windows_drive_letter(path_buffer)) {
11103
2.23k
          path += '/';
11104
2.23k
          path += path_buffer[0];
11105
2.23k
          path += ':';
11106
2.23k
          path_buffer.remove_prefix(2);
11107
2.23k
          path.append(path_buffer);
11108
38.7k
        } else {
11109
          // Append path_buffer to url's path.
11110
38.7k
          path += '/';
11111
38.7k
          path.append(path_buffer);
11112
38.7k
        }
11113
41.0k
      }
11114
53.5k
      if (location == std::string_view::npos) {
11115
9.97k
        return;
11116
9.97k
      }
11117
53.5k
    } while (true);
11118
9.97k
  }
11119
10.4k
}
11120
11121
0
bool overlaps(std::string_view input1, const std::string& input2) noexcept {
11122
0
  ada_log("helpers::overlaps check if string_view '", input1, "' [",
11123
0
          input1.size(), " bytes] is part of string '", input2, "' [",
11124
0
          input2.size(), " bytes]");
11125
0
  return !input1.empty() && !input2.empty() && input1.data() >= input2.data() &&
11126
0
         input1.data() < input2.data() + input2.size();
11127
0
}
11128
11129
template <class url_type>
11130
ada_really_inline void strip_trailing_spaces_from_opaque_path(
11131
23.0k
    url_type& url) noexcept {
11132
23.0k
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
11133
23.0k
  if (!url.has_opaque_path) return;
11134
3.48k
  if (url.has_hash()) return;
11135
3.33k
  if (url.has_search()) return;
11136
11137
3.33k
  auto path = std::string(url.get_pathname());
11138
5.08k
  while (!path.empty() && path.back() == ' ') {
11139
1.74k
    path.resize(path.size() - 1);
11140
1.74k
  }
11141
3.33k
  url.update_base_pathname(path);
11142
3.33k
}
void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url>(ada::url&)
Line
Count
Source
11131
10.1k
    url_type& url) noexcept {
11132
10.1k
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
11133
10.1k
  if (!url.has_opaque_path) return;
11134
1.75k
  if (url.has_hash()) return;
11135
1.67k
  if (url.has_search()) return;
11136
11137
1.67k
  auto path = std::string(url.get_pathname());
11138
2.54k
  while (!path.empty() && path.back() == ' ') {
11139
873
    path.resize(path.size() - 1);
11140
873
  }
11141
1.67k
  url.update_base_pathname(path);
11142
1.67k
}
void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url_aggregator>(ada::url_aggregator&)
Line
Count
Source
11131
12.8k
    url_type& url) noexcept {
11132
12.8k
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
11133
12.8k
  if (!url.has_opaque_path) return;
11134
1.73k
  if (url.has_hash()) return;
11135
1.66k
  if (url.has_search()) return;
11136
11137
1.66k
  auto path = std::string(url.get_pathname());
11138
2.54k
  while (!path.empty() && path.back() == ' ') {
11139
873
    path.resize(path.size() - 1);
11140
873
  }
11141
1.66k
  url.update_base_pathname(path);
11142
1.66k
}
11143
11144
// @ / \\ ?
11145
static constexpr std::array<uint8_t, 256> authority_delimiter_special =
11146
    []() constexpr {
11147
      std::array<uint8_t, 256> result{};
11148
      for (int i : {'@', '/', '\\', '?'}) {
11149
        result[i] = 1;
11150
      }
11151
      return result;
11152
    }();
11153
// credit: @the-moisrex recommended a table-based approach
11154
ada_really_inline size_t
11155
8.69k
find_authority_delimiter_special(std::string_view view) noexcept {
11156
  // performance note: we might be able to gain further performance
11157
  // with SIMD instrinsics.
11158
49.2k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
11159
48.2k
    if (authority_delimiter_special[(uint8_t)*pos]) {
11160
7.73k
      return pos - view.begin();
11161
7.73k
    }
11162
48.2k
  }
11163
961
  return size_t(view.size());
11164
8.69k
}
11165
11166
// @ / ?
11167
static constexpr std::array<uint8_t, 256> authority_delimiter = []() constexpr {
11168
  std::array<uint8_t, 256> result{};
11169
  for (int i : {'@', '/', '?'}) {
11170
    result[i] = 1;
11171
  }
11172
  return result;
11173
}();
11174
// credit: @the-moisrex recommended a table-based approach
11175
ada_really_inline size_t
11176
2.01k
find_authority_delimiter(std::string_view view) noexcept {
11177
  // performance note: we might be able to gain further performance
11178
  // with SIMD instrinsics.
11179
7.50k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
11180
7.32k
    if (authority_delimiter[(uint8_t)*pos]) {
11181
1.83k
      return pos - view.begin();
11182
1.83k
    }
11183
7.32k
  }
11184
181
  return size_t(view.size());
11185
2.01k
}
11186
11187
}  // namespace ada::helpers
11188
11189
namespace ada {
11190
0
ada_warn_unused std::string to_string(ada::state state) {
11191
0
  return ada::helpers::get_state(state);
11192
0
}
11193
}  // namespace ada
11194
/* end file src/helpers.cpp */
11195
/* begin file src/url.cpp */
11196
11197
#include <numeric>
11198
#include <algorithm>
11199
#include <string>
11200
11201
namespace ada {
11202
11203
1.05k
bool url::parse_opaque_host(std::string_view input) {
11204
1.05k
  ada_log("parse_opaque_host ", input, "[", input.size(), " bytes]");
11205
1.05k
  if (std::any_of(input.begin(), input.end(),
11206
1.05k
                  ada::unicode::is_forbidden_host_code_point)) {
11207
162
    return is_valid = false;
11208
162
  }
11209
11210
  // Return the result of running UTF-8 percent-encode on input using the C0
11211
  // control percent-encode set.
11212
892
  host = ada::unicode::percent_encode(
11213
892
      input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
11214
892
  return true;
11215
1.05k
}
11216
11217
2.04k
bool url::parse_ipv4(std::string_view input) {
11218
2.04k
  ada_log("parse_ipv4 ", input, "[", input.size(), " bytes]");
11219
2.04k
  if (input.back() == '.') {
11220
24
    input.remove_suffix(1);
11221
24
  }
11222
2.04k
  size_t digit_count{0};
11223
2.04k
  int pure_decimal_count = 0;  // entries that are decimal
11224
2.04k
  std::string_view original_input =
11225
2.04k
      input;  // we might use this if pure_decimal_count == 4.
11226
2.04k
  uint64_t ipv4{0};
11227
  // we could unroll for better performance?
11228
2.55k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
11229
2.52k
    uint32_t
11230
2.52k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
11231
2.52k
    bool is_hex = checkers::has_hex_prefix(input);
11232
2.52k
    if (is_hex && ((input.length() == 2) ||
11233
780
                   ((input.length() > 2) && (input[2] == '.')))) {
11234
      // special case
11235
59
      segment_result = 0;
11236
59
      input.remove_prefix(2);
11237
2.47k
    } else {
11238
2.47k
      std::from_chars_result r;
11239
2.47k
      if (is_hex) {
11240
721
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
11241
721
                            segment_result, 16);
11242
1.74k
      } else if ((input.length() >= 2) && input[0] == '0' &&
11243
1.74k
                 checkers::is_digit(input[1])) {
11244
330
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
11245
330
                            segment_result, 8);
11246
1.41k
      } else {
11247
1.41k
        pure_decimal_count++;
11248
1.41k
        r = std::from_chars(input.data(), input.data() + input.size(),
11249
1.41k
                            segment_result, 10);
11250
1.41k
      }
11251
2.47k
      if (r.ec != std::errc()) {
11252
484
        return is_valid = false;
11253
484
      }
11254
1.98k
      input.remove_prefix(r.ptr - input.data());
11255
1.98k
    }
11256
2.04k
    if (input.empty()) {
11257
      // We have the last value.
11258
      // At this stage, ipv4 contains digit_count*8 bits.
11259
      // So we have 32-digit_count*8 bits left.
11260
1.41k
      if (segment_result > (uint64_t(1) << (32 - digit_count * 8))) {
11261
15
        return is_valid = false;
11262
15
      }
11263
1.39k
      ipv4 <<= (32 - digit_count * 8);
11264
1.39k
      ipv4 |= segment_result;
11265
1.39k
      goto final;
11266
1.41k
    } else {
11267
      // There is more, so that the value must no be larger than 255
11268
      // and we must have a '.'.
11269
635
      if ((segment_result > 255) || (input[0] != '.')) {
11270
125
        return is_valid = false;
11271
125
      }
11272
510
      ipv4 <<= 8;
11273
510
      ipv4 |= segment_result;
11274
510
      input.remove_prefix(1);  // remove '.'
11275
510
    }
11276
2.04k
  }
11277
24
  if ((digit_count != 4) || (!input.empty())) {
11278
24
    return is_valid = false;
11279
24
  }
11280
1.39k
final:
11281
  // We could also check r.ptr to see where the parsing ended.
11282
1.39k
  if (pure_decimal_count == 4) {
11283
50
    host = original_input;  // The original input was already all decimal and we
11284
                            // validated it.
11285
1.34k
  } else {
11286
1.34k
    host = ada::serializers::ipv4(ipv4);  // We have to reserialize the address.
11287
1.34k
  }
11288
1.39k
  host_type = IPV4;
11289
1.39k
  return true;
11290
24
}
11291
11292
557
bool url::parse_ipv6(std::string_view input) {
11293
557
  ada_log("parse_ipv6 ", input, "[", input.size(), " bytes]");
11294
11295
557
  if (input.empty()) {
11296
30
    return is_valid = false;
11297
30
  }
11298
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
11299
527
  std::array<uint16_t, 8> address{};
11300
11301
  // Let pieceIndex be 0.
11302
527
  int piece_index = 0;
11303
11304
  // Let compress be null.
11305
527
  std::optional<int> compress{};
11306
11307
  // Let pointer be a pointer for input.
11308
527
  std::string_view::iterator pointer = input.begin();
11309
11310
  // If c is U+003A (:), then:
11311
527
  if (input[0] == ':') {
11312
    // If remaining does not start with U+003A (:), validation error, return
11313
    // failure.
11314
125
    if (input.size() == 1 || input[1] != ':') {
11315
21
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
11316
21
      return is_valid = false;
11317
21
    }
11318
11319
    // Increase pointer by 2.
11320
104
    pointer += 2;
11321
11322
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
11323
104
    compress = ++piece_index;
11324
104
  }
11325
11326
  // While c is not the EOF code point:
11327
1.46k
  while (pointer != input.end()) {
11328
    // If pieceIndex is 8, validation error, return failure.
11329
1.21k
    if (piece_index == 8) {
11330
7
      ada_log("parse_ipv6 piece_index == 8");
11331
7
      return is_valid = false;
11332
7
    }
11333
11334
    // If c is U+003A (:), then:
11335
1.20k
    if (*pointer == ':') {
11336
      // If compress is non-null, validation error, return failure.
11337
91
      if (compress.has_value()) {
11338
7
        ada_log("parse_ipv6 compress is non-null");
11339
7
        return is_valid = false;
11340
7
      }
11341
11342
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
11343
      // then continue.
11344
84
      pointer++;
11345
84
      compress = ++piece_index;
11346
84
      continue;
11347
91
    }
11348
11349
    // Let value and length be 0.
11350
1.11k
    uint16_t value = 0, length = 0;
11351
11352
    // While length is less than 4 and c is an ASCII hex digit,
11353
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
11354
    // increase pointer and length by 1.
11355
2.83k
    while (length < 4 && pointer != input.end() &&
11356
2.83k
           unicode::is_ascii_hex_digit(*pointer)) {
11357
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
11358
1.72k
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
11359
1.72k
      pointer++;
11360
1.72k
      length++;
11361
1.72k
    }
11362
11363
    // If c is U+002E (.), then:
11364
1.11k
    if (pointer != input.end() && *pointer == '.') {
11365
      // If length is 0, validation error, return failure.
11366
112
      if (length == 0) {
11367
8
        ada_log("parse_ipv6 length is 0");
11368
8
        return is_valid = false;
11369
8
      }
11370
11371
      // Decrease pointer by length.
11372
104
      pointer -= length;
11373
11374
      // If pieceIndex is greater than 6, validation error, return failure.
11375
104
      if (piece_index > 6) {
11376
4
        ada_log("parse_ipv6 piece_index > 6");
11377
4
        return is_valid = false;
11378
4
      }
11379
11380
      // Let numbersSeen be 0.
11381
100
      int numbers_seen = 0;
11382
11383
      // While c is not the EOF code point:
11384
307
      while (pointer != input.end()) {
11385
        // Let ipv4Piece be null.
11386
268
        std::optional<uint16_t> ipv4_piece{};
11387
11388
        // If numbersSeen is greater than 0, then:
11389
268
        if (numbers_seen > 0) {
11390
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
11391
          // pointer by 1.
11392
168
          if (*pointer == '.' && numbers_seen < 4) {
11393
156
            pointer++;
11394
156
          }
11395
          // Otherwise, validation error, return failure.
11396
12
          else {
11397
12
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
11398
12
            return is_valid = false;
11399
12
          }
11400
168
        }
11401
11402
        // If c is not an ASCII digit, validation error, return failure.
11403
256
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
11404
27
          ada_log(
11405
27
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
11406
27
              "failure");
11407
27
          return is_valid = false;
11408
27
        }
11409
11410
        // While c is an ASCII digit:
11411
585
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
11412
          // Let number be c interpreted as decimal number.
11413
378
          int number = *pointer - '0';
11414
11415
          // If ipv4Piece is null, then set ipv4Piece to number.
11416
378
          if (!ipv4_piece.has_value()) {
11417
229
            ipv4_piece = number;
11418
229
          }
11419
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
11420
149
          else if (ipv4_piece == 0) {
11421
4
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
11422
4
            return is_valid = false;
11423
4
          }
11424
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
11425
145
          else {
11426
145
            ipv4_piece = *ipv4_piece * 10 + number;
11427
145
          }
11428
11429
          // If ipv4Piece is greater than 255, validation error, return failure.
11430
374
          if (ipv4_piece > 255) {
11431
18
            ada_log("parse_ipv6 ipv4_piece > 255");
11432
18
            return is_valid = false;
11433
18
          }
11434
11435
          // Increase pointer by 1.
11436
356
          pointer++;
11437
356
        }
11438
11439
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
11440
        // ipv4Piece.
11441
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
11442
207
        address[piece_index] =
11443
207
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
11444
11445
        // Increase numbersSeen by 1.
11446
207
        numbers_seen++;
11447
11448
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
11449
207
        if (numbers_seen == 2 || numbers_seen == 4) {
11450
86
          piece_index++;
11451
86
        }
11452
207
      }
11453
11454
      // If numbersSeen is not 4, validation error, return failure.
11455
39
      if (numbers_seen != 4) {
11456
16
        return is_valid = false;
11457
16
      }
11458
11459
      // Break.
11460
23
      break;
11461
39
    }
11462
    // Otherwise, if c is U+003A (:):
11463
1.00k
    else if ((pointer != input.end()) && (*pointer == ':')) {
11464
      // Increase pointer by 1.
11465
694
      pointer++;
11466
11467
      // If c is the EOF code point, validation error, return failure.
11468
694
      if (pointer == input.end()) {
11469
6
        ada_log(
11470
6
            "parse_ipv6 If c is the EOF code point, validation error, return "
11471
6
            "failure");
11472
6
        return is_valid = false;
11473
6
      }
11474
694
    }
11475
    // Otherwise, if c is not the EOF code point, validation error, return
11476
    // failure.
11477
309
    else if (pointer != input.end()) {
11478
126
      ada_log(
11479
126
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
11480
126
          "error, return failure");
11481
126
      return is_valid = false;
11482
126
    }
11483
11484
    // Set address[pieceIndex] to value.
11485
871
    address[piece_index] = value;
11486
11487
    // Increase pieceIndex by 1.
11488
871
    piece_index++;
11489
871
  }
11490
11491
  // If compress is non-null, then:
11492
271
  if (compress.has_value()) {
11493
    // Let swaps be pieceIndex - compress.
11494
171
    int swaps = piece_index - *compress;
11495
11496
    // Set pieceIndex to 7.
11497
171
    piece_index = 7;
11498
11499
    // While pieceIndex is not 0 and swaps is greater than 0,
11500
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
11501
    // decrease both pieceIndex and swaps by 1.
11502
463
    while (piece_index != 0 && swaps > 0) {
11503
292
      std::swap(address[piece_index], address[*compress + swaps - 1]);
11504
292
      piece_index--;
11505
292
      swaps--;
11506
292
    }
11507
171
  }
11508
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
11509
  // return failure.
11510
100
  else if (piece_index != 8) {
11511
75
    ada_log(
11512
75
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
11513
75
        "error, return failure");
11514
75
    return is_valid = false;
11515
75
  }
11516
196
  host = ada::serializers::ipv6(address);
11517
196
  ada_log("parse_ipv6 ", *host);
11518
196
  host_type = IPV6;
11519
196
  return true;
11520
271
}
11521
11522
template <bool has_state_override>
11523
10.2k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
11524
10.2k
  auto parsed_type = ada::scheme::get_scheme_type(input);
11525
10.2k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
11526
  /**
11527
   * In the common case, we will immediately recognize a special scheme (e.g.,
11528
   *http, https), in which case, we can go really fast.
11529
   **/
11530
10.2k
  if (is_input_special) {  // fast path!!!
11531
3.79k
    if (has_state_override) {
11532
      // If url's scheme is not a special scheme and buffer is a special scheme,
11533
      // then return.
11534
33
      if (is_special() != is_input_special) {
11535
1
        return true;
11536
1
      }
11537
11538
      // If url includes credentials or has a non-null port, and buffer is
11539
      // "file", then return.
11540
32
      if ((has_credentials() || port.has_value()) &&
11541
32
          parsed_type == ada::scheme::type::FILE) {
11542
1
        return true;
11543
1
      }
11544
11545
      // If url's scheme is "file" and its host is an empty host, then return.
11546
      // An empty host is the empty string.
11547
31
      if (type == ada::scheme::type::FILE && host.has_value() &&
11548
31
          host.value().empty()) {
11549
1
        return true;
11550
1
      }
11551
31
    }
11552
11553
3.78k
    type = parsed_type;
11554
11555
3.78k
    if (has_state_override) {
11556
      // This is uncommon.
11557
30
      uint16_t urls_scheme_port = get_special_port();
11558
11559
30
      if (urls_scheme_port) {
11560
        // If url's port is url's scheme's default port, then set url's port to
11561
        // null.
11562
25
        if (port.has_value() && *port == urls_scheme_port) {
11563
1
          port = std::nullopt;
11564
1
        }
11565
25
      }
11566
30
    }
11567
6.44k
  } else {  // slow path
11568
6.44k
    std::string _buffer = std::string(input);
11569
    // Next function is only valid if the input is ASCII and returns false
11570
    // otherwise, but it seems that we always have ascii content so we do not
11571
    // need to check the return value.
11572
    // bool is_ascii =
11573
6.44k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
11574
11575
6.44k
    if (has_state_override) {
11576
      // If url's scheme is a special scheme and buffer is not a special scheme,
11577
      // then return. If url's scheme is not a special scheme and buffer is a
11578
      // special scheme, then return.
11579
253
      if (is_special() != ada::scheme::is_special(_buffer)) {
11580
122
        return true;
11581
122
      }
11582
11583
      // If url includes credentials or has a non-null port, and buffer is
11584
      // "file", then return.
11585
131
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
11586
1
        return true;
11587
1
      }
11588
11589
      // If url's scheme is "file" and its host is an empty host, then return.
11590
      // An empty host is the empty string.
11591
130
      if (type == ada::scheme::type::FILE && host.has_value() &&
11592
130
          host.value().empty()) {
11593
1
        return true;
11594
1
      }
11595
130
    }
11596
11597
6.32k
    set_scheme(std::move(_buffer));
11598
11599
6.32k
    if (has_state_override) {
11600
      // This is uncommon.
11601
129
      uint16_t urls_scheme_port = get_special_port();
11602
11603
129
      if (urls_scheme_port) {
11604
        // If url's port is url's scheme's default port, then set url's port to
11605
        // null.
11606
10
        if (port.has_value() && *port == urls_scheme_port) {
11607
1
          port = std::nullopt;
11608
1
        }
11609
10
      }
11610
129
    }
11611
6.32k
  }
11612
11613
10.1k
  return true;
11614
10.2k
}
bool ada::url::parse_scheme<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
11523
286
ada_really_inline bool url::parse_scheme(const std::string_view input) {
11524
286
  auto parsed_type = ada::scheme::get_scheme_type(input);
11525
286
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
11526
  /**
11527
   * In the common case, we will immediately recognize a special scheme (e.g.,
11528
   *http, https), in which case, we can go really fast.
11529
   **/
11530
286
  if (is_input_special) {  // fast path!!!
11531
33
    if (has_state_override) {
11532
      // If url's scheme is not a special scheme and buffer is a special scheme,
11533
      // then return.
11534
33
      if (is_special() != is_input_special) {
11535
1
        return true;
11536
1
      }
11537
11538
      // If url includes credentials or has a non-null port, and buffer is
11539
      // "file", then return.
11540
32
      if ((has_credentials() || port.has_value()) &&
11541
32
          parsed_type == ada::scheme::type::FILE) {
11542
1
        return true;
11543
1
      }
11544
11545
      // If url's scheme is "file" and its host is an empty host, then return.
11546
      // An empty host is the empty string.
11547
31
      if (type == ada::scheme::type::FILE && host.has_value() &&
11548
31
          host.value().empty()) {
11549
1
        return true;
11550
1
      }
11551
31
    }
11552
11553
30
    type = parsed_type;
11554
11555
30
    if (has_state_override) {
11556
      // This is uncommon.
11557
30
      uint16_t urls_scheme_port = get_special_port();
11558
11559
30
      if (urls_scheme_port) {
11560
        // If url's port is url's scheme's default port, then set url's port to
11561
        // null.
11562
25
        if (port.has_value() && *port == urls_scheme_port) {
11563
1
          port = std::nullopt;
11564
1
        }
11565
25
      }
11566
30
    }
11567
253
  } else {  // slow path
11568
253
    std::string _buffer = std::string(input);
11569
    // Next function is only valid if the input is ASCII and returns false
11570
    // otherwise, but it seems that we always have ascii content so we do not
11571
    // need to check the return value.
11572
    // bool is_ascii =
11573
253
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
11574
11575
253
    if (has_state_override) {
11576
      // If url's scheme is a special scheme and buffer is not a special scheme,
11577
      // then return. If url's scheme is not a special scheme and buffer is a
11578
      // special scheme, then return.
11579
253
      if (is_special() != ada::scheme::is_special(_buffer)) {
11580
122
        return true;
11581
122
      }
11582
11583
      // If url includes credentials or has a non-null port, and buffer is
11584
      // "file", then return.
11585
131
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
11586
1
        return true;
11587
1
      }
11588
11589
      // If url's scheme is "file" and its host is an empty host, then return.
11590
      // An empty host is the empty string.
11591
130
      if (type == ada::scheme::type::FILE && host.has_value() &&
11592
130
          host.value().empty()) {
11593
1
        return true;
11594
1
      }
11595
130
    }
11596
11597
129
    set_scheme(std::move(_buffer));
11598
11599
129
    if (has_state_override) {
11600
      // This is uncommon.
11601
129
      uint16_t urls_scheme_port = get_special_port();
11602
11603
129
      if (urls_scheme_port) {
11604
        // If url's port is url's scheme's default port, then set url's port to
11605
        // null.
11606
10
        if (port.has_value() && *port == urls_scheme_port) {
11607
1
          port = std::nullopt;
11608
1
        }
11609
10
      }
11610
129
    }
11611
129
  }
11612
11613
159
  return true;
11614
286
}
bool ada::url::parse_scheme<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
11523
9.95k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
11524
9.95k
  auto parsed_type = ada::scheme::get_scheme_type(input);
11525
9.95k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
11526
  /**
11527
   * In the common case, we will immediately recognize a special scheme (e.g.,
11528
   *http, https), in which case, we can go really fast.
11529
   **/
11530
9.95k
  if (is_input_special) {  // fast path!!!
11531
3.75k
    if (has_state_override) {
11532
      // If url's scheme is not a special scheme and buffer is a special scheme,
11533
      // then return.
11534
0
      if (is_special() != is_input_special) {
11535
0
        return true;
11536
0
      }
11537
11538
      // If url includes credentials or has a non-null port, and buffer is
11539
      // "file", then return.
11540
0
      if ((has_credentials() || port.has_value()) &&
11541
0
          parsed_type == ada::scheme::type::FILE) {
11542
0
        return true;
11543
0
      }
11544
11545
      // If url's scheme is "file" and its host is an empty host, then return.
11546
      // An empty host is the empty string.
11547
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
11548
0
          host.value().empty()) {
11549
0
        return true;
11550
0
      }
11551
0
    }
11552
11553
3.75k
    type = parsed_type;
11554
11555
3.75k
    if (has_state_override) {
11556
      // This is uncommon.
11557
0
      uint16_t urls_scheme_port = get_special_port();
11558
11559
0
      if (urls_scheme_port) {
11560
        // If url's port is url's scheme's default port, then set url's port to
11561
        // null.
11562
0
        if (port.has_value() && *port == urls_scheme_port) {
11563
0
          port = std::nullopt;
11564
0
        }
11565
0
      }
11566
0
    }
11567
6.19k
  } else {  // slow path
11568
6.19k
    std::string _buffer = std::string(input);
11569
    // Next function is only valid if the input is ASCII and returns false
11570
    // otherwise, but it seems that we always have ascii content so we do not
11571
    // need to check the return value.
11572
    // bool is_ascii =
11573
6.19k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
11574
11575
6.19k
    if (has_state_override) {
11576
      // If url's scheme is a special scheme and buffer is not a special scheme,
11577
      // then return. If url's scheme is not a special scheme and buffer is a
11578
      // special scheme, then return.
11579
0
      if (is_special() != ada::scheme::is_special(_buffer)) {
11580
0
        return true;
11581
0
      }
11582
11583
      // If url includes credentials or has a non-null port, and buffer is
11584
      // "file", then return.
11585
0
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
11586
0
        return true;
11587
0
      }
11588
11589
      // If url's scheme is "file" and its host is an empty host, then return.
11590
      // An empty host is the empty string.
11591
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
11592
0
          host.value().empty()) {
11593
0
        return true;
11594
0
      }
11595
0
    }
11596
11597
6.19k
    set_scheme(std::move(_buffer));
11598
11599
6.19k
    if (has_state_override) {
11600
      // This is uncommon.
11601
0
      uint16_t urls_scheme_port = get_special_port();
11602
11603
0
      if (urls_scheme_port) {
11604
        // If url's port is url's scheme's default port, then set url's port to
11605
        // null.
11606
0
        if (port.has_value() && *port == urls_scheme_port) {
11607
0
          port = std::nullopt;
11608
0
        }
11609
0
      }
11610
0
    }
11611
6.19k
  }
11612
11613
9.95k
  return true;
11614
9.95k
}
11615
11616
9.91k
ada_really_inline bool url::parse_host(std::string_view input) {
11617
9.91k
  ada_log("parse_host ", input, "[", input.size(), " bytes]");
11618
9.91k
  if (input.empty()) {
11619
39
    return is_valid = false;
11620
39
  }  // technically unnecessary.
11621
  // If input starts with U+005B ([), then:
11622
9.87k
  if (input[0] == '[') {
11623
    // If input does not end with U+005D (]), validation error, return failure.
11624
989
    if (input.back() != ']') {
11625
432
      return is_valid = false;
11626
432
    }
11627
557
    ada_log("parse_host ipv6");
11628
11629
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
11630
    // trailing U+005D (]) removed.
11631
557
    input.remove_prefix(1);
11632
557
    input.remove_suffix(1);
11633
557
    return parse_ipv6(input);
11634
989
  }
11635
11636
  // If isNotSpecial is true, then return the result of opaque-host parsing
11637
  // input.
11638
8.88k
  if (!is_special()) {
11639
1.05k
    return parse_opaque_host(input);
11640
1.05k
  }
11641
  // Let domain be the result of running UTF-8 decode without BOM on the
11642
  // percent-decoding of input. Let asciiDomain be the result of running domain
11643
  // to ASCII with domain and false. The most common case is an ASCII input, in
11644
  // which case we do not need to call the expensive 'to_ascii' if a few
11645
  // conditions are met: no '%' and no 'xn-' subsequence.
11646
7.83k
  std::string buffer = std::string(input);
11647
  // This next function checks that the result is ascii, but we are going to
11648
  // to check anyhow with is_forbidden.
11649
  // bool is_ascii =
11650
7.83k
  unicode::to_lower_ascii(buffer.data(), buffer.size());
11651
7.83k
  bool is_forbidden = unicode::contains_forbidden_domain_code_point(
11652
7.83k
      buffer.data(), buffer.size());
11653
7.83k
  if (is_forbidden == 0 && buffer.find("xn-") == std::string_view::npos) {
11654
    // fast path
11655
4.90k
    host = std::move(buffer);
11656
4.90k
    if (checkers::is_ipv4(host.value())) {
11657
1.72k
      ada_log("parse_host fast path ipv4");
11658
1.72k
      return parse_ipv4(host.value());
11659
1.72k
    }
11660
3.17k
    ada_log("parse_host fast path ", *host);
11661
3.17k
    return true;
11662
4.90k
  }
11663
2.92k
  ada_log("parse_host calling to_ascii");
11664
2.92k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
11665
2.92k
  if (!is_valid) {
11666
1.36k
    ada_log("parse_host to_ascii returns false");
11667
1.36k
    return is_valid = false;
11668
1.36k
  }
11669
11670
1.56k
  if (std::any_of(host.value().begin(), host.value().end(),
11671
1.56k
                  ada::unicode::is_forbidden_domain_code_point)) {
11672
0
    host = std::nullopt;
11673
0
    return is_valid = false;
11674
0
  }
11675
11676
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
11677
  // asciiDomain.
11678
1.56k
  if (checkers::is_ipv4(host.value())) {
11679
317
    ada_log("parse_host got ipv4", *host);
11680
317
    return parse_ipv4(host.value());
11681
317
  }
11682
11683
1.24k
  return true;
11684
1.56k
}
11685
11686
6.97k
ada_really_inline void url::parse_path(std::string_view input) {
11687
6.97k
  ada_log("parse_path ", input);
11688
6.97k
  std::string tmp_buffer;
11689
6.97k
  std::string_view internal_input;
11690
6.97k
  if (unicode::has_tabs_or_newline(input)) {
11691
93
    tmp_buffer = input;
11692
    // Optimization opportunity: Instead of copying and then pruning, we could
11693
    // just directly build the string from user_input.
11694
93
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
11695
93
    internal_input = tmp_buffer;
11696
6.88k
  } else {
11697
6.88k
    internal_input = input;
11698
6.88k
  }
11699
11700
  // If url is special, then:
11701
6.97k
  if (is_special()) {
11702
5.25k
    if (internal_input.empty()) {
11703
3.31k
      path = "/";
11704
3.31k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
11705
510
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
11706
510
      return;
11707
1.43k
    } else {
11708
1.43k
      helpers::parse_prepared_path(internal_input, type, path);
11709
1.43k
      return;
11710
1.43k
    }
11711
5.25k
  } else if (!internal_input.empty()) {
11712
797
    if (internal_input[0] == '/') {
11713
266
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
11714
266
      return;
11715
531
    } else {
11716
531
      helpers::parse_prepared_path(internal_input, type, path);
11717
531
      return;
11718
531
    }
11719
923
  } else {
11720
923
    if (!host.has_value()) {
11721
0
      path = "/";
11722
0
    }
11723
923
  }
11724
6.97k
}
11725
11726
0
[[nodiscard]] std::string url::to_string() const {
11727
0
  if (!is_valid) {
11728
0
    return "null";
11729
0
  }
11730
0
  std::string answer;
11731
0
  auto back = std::back_insert_iterator(answer);
11732
0
  answer.append("{\n");
11733
0
  answer.append("\t\"protocol\":\"");
11734
0
  helpers::encode_json(get_protocol(), back);
11735
0
  answer.append("\",\n");
11736
0
  if (has_credentials()) {
11737
0
    answer.append("\t\"username\":\"");
11738
0
    helpers::encode_json(username, back);
11739
0
    answer.append("\",\n");
11740
0
    answer.append("\t\"password\":\"");
11741
0
    helpers::encode_json(password, back);
11742
0
    answer.append("\",\n");
11743
0
  }
11744
0
  if (host.has_value()) {
11745
0
    answer.append("\t\"host\":\"");
11746
0
    helpers::encode_json(host.value(), back);
11747
0
    answer.append("\",\n");
11748
0
  }
11749
0
  if (port.has_value()) {
11750
0
    answer.append("\t\"port\":\"");
11751
0
    answer.append(std::to_string(port.value()));
11752
0
    answer.append("\",\n");
11753
0
  }
11754
0
  answer.append("\t\"path\":\"");
11755
0
  helpers::encode_json(path, back);
11756
0
  answer.append("\",\n");
11757
0
  answer.append("\t\"opaque path\":");
11758
0
  answer.append((has_opaque_path ? "true" : "false"));
11759
0
  if (has_search()) {
11760
0
    answer.append(",\n");
11761
0
    answer.append("\t\"query\":\"");
11762
0
    helpers::encode_json(query.value(), back);
11763
0
    answer.append("\"");
11764
0
  }
11765
0
  if (hash.has_value()) {
11766
0
    answer.append(",\n");
11767
0
    answer.append("\t\"hash\":\"");
11768
0
    helpers::encode_json(hash.value(), back);
11769
0
    answer.append("\"");
11770
0
  }
11771
0
  answer.append("\n}");
11772
0
  return answer;
11773
0
}
11774
11775
0
[[nodiscard]] bool url::has_valid_domain() const noexcept {
11776
0
  if (!host.has_value()) {
11777
0
    return false;
11778
0
  }
11779
0
  return checkers::verify_dns_length(host.value());
11780
0
}
11781
11782
}  // namespace ada
11783
/* end file src/url.cpp */
11784
/* begin file src/url-getters.cpp */
11785
/**
11786
 * @file url-getters.cpp
11787
 * Includes all the getters of `ada::url`
11788
 */
11789
11790
#include <algorithm>
11791
#include <string>
11792
11793
namespace ada {
11794
7.99k
[[nodiscard]] std::string url::get_origin() const noexcept {
11795
7.99k
  if (is_special()) {
11796
    // Return a new opaque origin.
11797
5.25k
    if (type == scheme::FILE) {
11798
1.40k
      return "null";
11799
1.40k
    }
11800
3.85k
    return ada::helpers::concat(get_protocol(), "//", get_host());
11801
5.25k
  }
11802
11803
2.74k
  if (non_special_scheme == "blob") {
11804
406
    if (!path.empty()) {
11805
400
      auto result = ada::parse<ada::url>(path);
11806
400
      if (result &&
11807
400
          (result->type == scheme::HTTP || result->type == scheme::HTTPS)) {
11808
        // If pathURL's scheme is not "http" and not "https", then return a
11809
        // new opaque origin.
11810
13
        return ada::helpers::concat(result->get_protocol(), "//",
11811
13
                                    result->get_host());
11812
13
      }
11813
400
    }
11814
406
  }
11815
11816
  // Return a new opaque origin.
11817
2.72k
  return "null";
11818
2.74k
}
11819
11820
11.8k
[[nodiscard]] std::string url::get_protocol() const noexcept {
11821
11.8k
  if (is_special()) {
11822
9.12k
    return helpers::concat(ada::scheme::details::is_special_list[type], ":");
11823
9.12k
  }
11824
  // We only move the 'scheme' if it is non-special.
11825
2.74k
  return helpers::concat(non_special_scheme, ":");
11826
11.8k
}
11827
11828
11.8k
[[nodiscard]] std::string url::get_host() const noexcept {
11829
  // If url's host is null, then return the empty string.
11830
  // If url's port is null, return url's host, serialized.
11831
  // Return url's host, serialized, followed by U+003A (:) and url's port,
11832
  // serialized.
11833
11.8k
  if (!host.has_value()) {
11834
1.19k
    return "";
11835
1.19k
  }
11836
10.6k
  if (port.has_value()) {
11837
383
    return host.value() + ":" + get_port();
11838
383
  }
11839
10.2k
  return host.value();
11840
10.6k
}
11841
11842
7.99k
[[nodiscard]] std::string url::get_hostname() const noexcept {
11843
7.99k
  return host.value_or("");
11844
7.99k
}
11845
11846
9.67k
[[nodiscard]] std::string_view url::get_pathname() const noexcept {
11847
9.67k
  return path;
11848
9.67k
}
11849
11850
7.99k
[[nodiscard]] std::string url::get_search() const noexcept {
11851
  // If this's URL's query is either null or the empty string, then return the
11852
  // empty string. Return U+003F (?), followed by this's URL's query.
11853
7.99k
  return (!query.has_value() || (query.value().empty())) ? ""
11854
7.99k
                                                         : "?" + query.value();
11855
7.99k
}
11856
11857
7.99k
[[nodiscard]] const std::string& url::get_username() const noexcept {
11858
7.99k
  return username;
11859
7.99k
}
11860
11861
7.99k
[[nodiscard]] const std::string& url::get_password() const noexcept {
11862
7.99k
  return password;
11863
7.99k
}
11864
11865
8.38k
[[nodiscard]] std::string url::get_port() const noexcept {
11866
8.38k
  return port.has_value() ? std::to_string(port.value()) : "";
11867
8.38k
}
11868
11869
7.99k
[[nodiscard]] std::string url::get_hash() const noexcept {
11870
  // If this's URL's fragment is either null or the empty string, then return
11871
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
11872
7.99k
  return (!hash.has_value() || (hash.value().empty())) ? ""
11873
7.99k
                                                       : "#" + hash.value();
11874
7.99k
}
11875
11876
}  // namespace ada
11877
/* end file src/url-getters.cpp */
11878
/* begin file src/url-setters.cpp */
11879
/**
11880
 * @file url-setters.cpp
11881
 * Includes all the setters of `ada::url`
11882
 */
11883
11884
#include <optional>
11885
#include <string>
11886
11887
namespace ada {
11888
11889
template <bool override_hostname>
11890
15.9k
bool url::set_host_or_hostname(const std::string_view input) {
11891
15.9k
  if (has_opaque_path) {
11892
2.04k
    return false;
11893
2.04k
  }
11894
11895
13.9k
  std::optional<std::string> previous_host = host;
11896
13.9k
  std::optional<uint16_t> previous_port = port;
11897
11898
13.9k
  size_t host_end_pos = input.find('#');
11899
13.9k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
11900
13.9k
                                      ? host_end_pos
11901
13.9k
                                      : input.size());
11902
13.9k
  helpers::remove_ascii_tab_or_newline(_host);
11903
13.9k
  std::string_view new_host(_host);
11904
11905
  // If url's scheme is "file", then set state to file host state, instead of
11906
  // host state.
11907
13.9k
  if (type != ada::scheme::type::FILE) {
11908
11.1k
    std::string_view host_view(_host.data(), _host.length());
11909
11.1k
    auto [location, found_colon] =
11910
11.1k
        helpers::get_host_delimiter_location(is_special(), host_view);
11911
11912
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
11913
    // Note: the 'found_colon' value is true if and only if a colon was
11914
    // encountered while not inside brackets.
11915
11.1k
    if (found_colon) {
11916
200
      if (override_hostname) {
11917
100
        return false;
11918
100
      }
11919
100
      std::string_view buffer = new_host.substr(location + 1);
11920
100
      if (!buffer.empty()) {
11921
92
        set_port(buffer);
11922
92
      }
11923
100
    }
11924
    // If url is special and host_view is the empty string, validation error,
11925
    // return failure. Otherwise, if state override is given, host_view is the
11926
    // empty string, and either url includes credentials or url's port is
11927
    // non-null, return.
11928
10.9k
    else if (host_view.empty() &&
11929
10.9k
             (is_special() || has_credentials() || port.has_value())) {
11930
5.72k
      return false;
11931
5.72k
    }
11932
11933
    // Let host be the result of host parsing host_view with url is not special.
11934
5.32k
    if (host_view.empty() && !is_special()) {
11935
2.30k
      host = "";
11936
2.30k
      return true;
11937
2.30k
    }
11938
11939
3.01k
    bool succeeded = parse_host(host_view);
11940
3.01k
    if (!succeeded) {
11941
1.15k
      host = previous_host;
11942
1.15k
      update_base_port(previous_port);
11943
1.15k
    }
11944
3.01k
    return succeeded;
11945
5.32k
  }
11946
11947
2.80k
  size_t location = new_host.find_first_of("/\\?");
11948
2.80k
  if (location != std::string_view::npos) {
11949
570
    new_host.remove_suffix(new_host.length() - location);
11950
570
  }
11951
11952
2.80k
  if (new_host.empty()) {
11953
    // Set url's host to the empty string.
11954
2.02k
    host = "";
11955
2.02k
  } else {
11956
    // Let host be the result of host parsing buffer with url is not special.
11957
776
    if (!parse_host(new_host)) {
11958
324
      host = previous_host;
11959
324
      update_base_port(previous_port);
11960
324
      return false;
11961
324
    }
11962
11963
    // If host is "localhost", then set host to the empty string.
11964
452
    if (host.has_value() && host.value() == "localhost") {
11965
2
      host = "";
11966
2
    }
11967
452
  }
11968
2.48k
  return true;
11969
2.80k
}
bool ada::url::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
11890
7.99k
bool url::set_host_or_hostname(const std::string_view input) {
11891
7.99k
  if (has_opaque_path) {
11892
1.02k
    return false;
11893
1.02k
  }
11894
11895
6.97k
  std::optional<std::string> previous_host = host;
11896
6.97k
  std::optional<uint16_t> previous_port = port;
11897
11898
6.97k
  size_t host_end_pos = input.find('#');
11899
6.97k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
11900
6.97k
                                      ? host_end_pos
11901
6.97k
                                      : input.size());
11902
6.97k
  helpers::remove_ascii_tab_or_newline(_host);
11903
6.97k
  std::string_view new_host(_host);
11904
11905
  // If url's scheme is "file", then set state to file host state, instead of
11906
  // host state.
11907
6.97k
  if (type != ada::scheme::type::FILE) {
11908
5.57k
    std::string_view host_view(_host.data(), _host.length());
11909
5.57k
    auto [location, found_colon] =
11910
5.57k
        helpers::get_host_delimiter_location(is_special(), host_view);
11911
11912
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
11913
    // Note: the 'found_colon' value is true if and only if a colon was
11914
    // encountered while not inside brackets.
11915
5.57k
    if (found_colon) {
11916
100
      if (override_hostname) {
11917
0
        return false;
11918
0
      }
11919
100
      std::string_view buffer = new_host.substr(location + 1);
11920
100
      if (!buffer.empty()) {
11921
92
        set_port(buffer);
11922
92
      }
11923
100
    }
11924
    // If url is special and host_view is the empty string, validation error,
11925
    // return failure. Otherwise, if state override is given, host_view is the
11926
    // empty string, and either url includes credentials or url's port is
11927
    // non-null, return.
11928
5.47k
    else if (host_view.empty() &&
11929
5.47k
             (is_special() || has_credentials() || port.has_value())) {
11930
2.86k
      return false;
11931
2.86k
    }
11932
11933
    // Let host be the result of host parsing host_view with url is not special.
11934
2.71k
    if (host_view.empty() && !is_special()) {
11935
1.16k
      host = "";
11936
1.16k
      return true;
11937
1.16k
    }
11938
11939
1.55k
    bool succeeded = parse_host(host_view);
11940
1.55k
    if (!succeeded) {
11941
602
      host = previous_host;
11942
602
      update_base_port(previous_port);
11943
602
    }
11944
1.55k
    return succeeded;
11945
2.71k
  }
11946
11947
1.40k
  size_t location = new_host.find_first_of("/\\?");
11948
1.40k
  if (location != std::string_view::npos) {
11949
285
    new_host.remove_suffix(new_host.length() - location);
11950
285
  }
11951
11952
1.40k
  if (new_host.empty()) {
11953
    // Set url's host to the empty string.
11954
1.01k
    host = "";
11955
1.01k
  } else {
11956
    // Let host be the result of host parsing buffer with url is not special.
11957
388
    if (!parse_host(new_host)) {
11958
162
      host = previous_host;
11959
162
      update_base_port(previous_port);
11960
162
      return false;
11961
162
    }
11962
11963
    // If host is "localhost", then set host to the empty string.
11964
226
    if (host.has_value() && host.value() == "localhost") {
11965
1
      host = "";
11966
1
    }
11967
226
  }
11968
1.24k
  return true;
11969
1.40k
}
bool ada::url::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
11890
7.99k
bool url::set_host_or_hostname(const std::string_view input) {
11891
7.99k
  if (has_opaque_path) {
11892
1.02k
    return false;
11893
1.02k
  }
11894
11895
6.97k
  std::optional<std::string> previous_host = host;
11896
6.97k
  std::optional<uint16_t> previous_port = port;
11897
11898
6.97k
  size_t host_end_pos = input.find('#');
11899
6.97k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
11900
6.97k
                                      ? host_end_pos
11901
6.97k
                                      : input.size());
11902
6.97k
  helpers::remove_ascii_tab_or_newline(_host);
11903
6.97k
  std::string_view new_host(_host);
11904
11905
  // If url's scheme is "file", then set state to file host state, instead of
11906
  // host state.
11907
6.97k
  if (type != ada::scheme::type::FILE) {
11908
5.57k
    std::string_view host_view(_host.data(), _host.length());
11909
5.57k
    auto [location, found_colon] =
11910
5.57k
        helpers::get_host_delimiter_location(is_special(), host_view);
11911
11912
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
11913
    // Note: the 'found_colon' value is true if and only if a colon was
11914
    // encountered while not inside brackets.
11915
5.57k
    if (found_colon) {
11916
100
      if (override_hostname) {
11917
100
        return false;
11918
100
      }
11919
0
      std::string_view buffer = new_host.substr(location + 1);
11920
0
      if (!buffer.empty()) {
11921
0
        set_port(buffer);
11922
0
      }
11923
0
    }
11924
    // If url is special and host_view is the empty string, validation error,
11925
    // return failure. Otherwise, if state override is given, host_view is the
11926
    // empty string, and either url includes credentials or url's port is
11927
    // non-null, return.
11928
5.47k
    else if (host_view.empty() &&
11929
5.47k
             (is_special() || has_credentials() || port.has_value())) {
11930
2.86k
      return false;
11931
2.86k
    }
11932
11933
    // Let host be the result of host parsing host_view with url is not special.
11934
2.61k
    if (host_view.empty() && !is_special()) {
11935
1.14k
      host = "";
11936
1.14k
      return true;
11937
1.14k
    }
11938
11939
1.46k
    bool succeeded = parse_host(host_view);
11940
1.46k
    if (!succeeded) {
11941
557
      host = previous_host;
11942
557
      update_base_port(previous_port);
11943
557
    }
11944
1.46k
    return succeeded;
11945
2.61k
  }
11946
11947
1.40k
  size_t location = new_host.find_first_of("/\\?");
11948
1.40k
  if (location != std::string_view::npos) {
11949
285
    new_host.remove_suffix(new_host.length() - location);
11950
285
  }
11951
11952
1.40k
  if (new_host.empty()) {
11953
    // Set url's host to the empty string.
11954
1.01k
    host = "";
11955
1.01k
  } else {
11956
    // Let host be the result of host parsing buffer with url is not special.
11957
388
    if (!parse_host(new_host)) {
11958
162
      host = previous_host;
11959
162
      update_base_port(previous_port);
11960
162
      return false;
11961
162
    }
11962
11963
    // If host is "localhost", then set host to the empty string.
11964
226
    if (host.has_value() && host.value() == "localhost") {
11965
1
      host = "";
11966
1
    }
11967
226
  }
11968
1.24k
  return true;
11969
1.40k
}
11970
11971
7.99k
bool url::set_host(const std::string_view input) {
11972
7.99k
  return set_host_or_hostname<false>(input);
11973
7.99k
}
11974
11975
7.99k
bool url::set_hostname(const std::string_view input) {
11976
7.99k
  return set_host_or_hostname<true>(input);
11977
7.99k
}
11978
11979
7.99k
bool url::set_username(const std::string_view input) {
11980
7.99k
  if (cannot_have_credentials_or_port()) {
11981
3.92k
    return false;
11982
3.92k
  }
11983
4.07k
  username = ada::unicode::percent_encode(
11984
4.07k
      input, character_sets::USERINFO_PERCENT_ENCODE);
11985
4.07k
  return true;
11986
7.99k
}
11987
11988
7.99k
bool url::set_password(const std::string_view input) {
11989
7.99k
  if (cannot_have_credentials_or_port()) {
11990
3.92k
    return false;
11991
3.92k
  }
11992
4.07k
  password = ada::unicode::percent_encode(
11993
4.07k
      input, character_sets::USERINFO_PERCENT_ENCODE);
11994
4.07k
  return true;
11995
7.99k
}
11996
11997
8.09k
bool url::set_port(const std::string_view input) {
11998
8.09k
  if (cannot_have_credentials_or_port()) {
11999
3.78k
    return false;
12000
3.78k
  }
12001
4.30k
  std::string trimmed(input);
12002
4.30k
  helpers::remove_ascii_tab_or_newline(trimmed);
12003
4.30k
  if (trimmed.empty()) {
12004
2.49k
    port = std::nullopt;
12005
2.49k
    return true;
12006
2.49k
  }
12007
  // Input should not start with control characters.
12008
1.81k
  if (ada::unicode::is_c0_control_or_space(trimmed.front())) {
12009
63
    return false;
12010
63
  }
12011
  // Input should contain at least one ascii digit.
12012
1.74k
  if (input.find_first_of("0123456789") == std::string_view::npos) {
12013
1.02k
    return false;
12014
1.02k
  }
12015
12016
  // Revert changes if parse_port fails.
12017
725
  std::optional<uint16_t> previous_port = port;
12018
725
  parse_port(trimmed);
12019
725
  if (is_valid) {
12020
529
    return true;
12021
529
  }
12022
196
  port = previous_port;
12023
196
  is_valid = true;
12024
196
  return false;
12025
725
}
12026
12027
7.99k
void url::set_hash(const std::string_view input) {
12028
7.99k
  if (input.empty()) {
12029
5.08k
    hash = std::nullopt;
12030
5.08k
    helpers::strip_trailing_spaces_from_opaque_path(*this);
12031
5.08k
    return;
12032
5.08k
  }
12033
12034
2.91k
  std::string new_value;
12035
2.91k
  new_value = input[0] == '#' ? input.substr(1) : input;
12036
2.91k
  helpers::remove_ascii_tab_or_newline(new_value);
12037
2.91k
  hash = unicode::percent_encode(new_value,
12038
2.91k
                                 ada::character_sets::FRAGMENT_PERCENT_ENCODE);
12039
2.91k
  return;
12040
7.99k
}
12041
12042
7.99k
void url::set_search(const std::string_view input) {
12043
7.99k
  if (input.empty()) {
12044
5.08k
    query = std::nullopt;
12045
5.08k
    helpers::strip_trailing_spaces_from_opaque_path(*this);
12046
5.08k
    return;
12047
5.08k
  }
12048
12049
2.91k
  std::string new_value;
12050
2.91k
  new_value = input[0] == '?' ? input.substr(1) : input;
12051
2.91k
  helpers::remove_ascii_tab_or_newline(new_value);
12052
12053
2.91k
  auto query_percent_encode_set =
12054
2.91k
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12055
2.91k
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
12056
12057
2.91k
  query = ada::unicode::percent_encode(std::string_view(new_value),
12058
2.91k
                                       query_percent_encode_set);
12059
2.91k
}
12060
12061
7.99k
bool url::set_pathname(const std::string_view input) {
12062
7.99k
  if (has_opaque_path) {
12063
1.02k
    return false;
12064
1.02k
  }
12065
6.97k
  path = "";
12066
6.97k
  parse_path(input);
12067
6.97k
  return true;
12068
7.99k
}
12069
12070
7.99k
bool url::set_protocol(const std::string_view input) {
12071
7.99k
  std::string view(input);
12072
7.99k
  helpers::remove_ascii_tab_or_newline(view);
12073
7.99k
  if (view.empty()) {
12074
5.13k
    return true;
12075
5.13k
  }
12076
12077
  // Schemes should start with alpha values.
12078
2.86k
  if (!checkers::is_alpha(view[0])) {
12079
2.41k
    return false;
12080
2.41k
  }
12081
12082
457
  view.append(":");
12083
12084
457
  std::string::iterator pointer =
12085
457
      std::find_if_not(view.begin(), view.end(), unicode::is_alnum_plus);
12086
12087
457
  if (pointer != view.end() && *pointer == ':') {
12088
286
    return parse_scheme<true>(
12089
286
        std::string_view(view.data(), pointer - view.begin()));
12090
286
  }
12091
171
  return false;
12092
457
}
12093
12094
0
bool url::set_href(const std::string_view input) {
12095
0
  ada::result<ada::url> out = ada::parse<ada::url>(input);
12096
12097
0
  if (out) {
12098
0
    username = out->username;
12099
0
    password = out->password;
12100
0
    host = out->host;
12101
0
    port = out->port;
12102
0
    path = out->path;
12103
0
    query = out->query;
12104
0
    hash = out->hash;
12105
0
    type = out->type;
12106
0
    non_special_scheme = out->non_special_scheme;
12107
0
    has_opaque_path = out->has_opaque_path;
12108
0
  }
12109
12110
0
  return out.has_value();
12111
0
}
12112
12113
}  // namespace ada
12114
/* end file src/url-setters.cpp */
12115
/* begin file src/parser.cpp */
12116
12117
#include <numeric>
12118
#include <limits>
12119
12120
namespace ada::parser {
12121
12122
template <class result_type>
12123
result_type parse_url(std::string_view user_input,
12124
59.1k
                      const result_type* base_url) {
12125
  // We can specialize the implementation per type.
12126
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
12127
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
12128
  // something else } is free (at runtime). This means that ada::url_aggregator
12129
  // and ada::url **do not have to support the exact same API**.
12130
59.1k
  constexpr bool result_type_is_ada_url =
12131
59.1k
      std::is_same<ada::url, result_type>::value;
12132
59.1k
  constexpr bool result_type_is_ada_url_aggregator =
12133
59.1k
      std::is_same<ada::url_aggregator, result_type>::value;
12134
59.1k
  static_assert(result_type_is_ada_url ||
12135
59.1k
                result_type_is_ada_url_aggregator);  // We don't support
12136
                                                     // anything else for now.
12137
12138
59.1k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
12139
59.1k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
12140
59.1k
          ")");
12141
12142
59.1k
  ada::state state = ada::state::SCHEME_START;
12143
59.1k
  result_type url{};
12144
12145
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
12146
  // surely the result of a bug or are otherwise a security concern.
12147
59.1k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) {
12148
2
    url.is_valid = false;
12149
2
  }
12150
  // Going forward, user_input.size() is in [0,
12151
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
12152
  // base, or the optional_url was invalid, we must return.
12153
59.1k
  if (base_url != nullptr) {
12154
2.61k
    url.is_valid &= base_url->is_valid;
12155
2.61k
  }
12156
59.1k
  if (!url.is_valid) {
12157
2
    return url;
12158
2
  }
12159
59.1k
  if constexpr (result_type_is_ada_url_aggregator) {
12160
    // Most of the time, we just need user_input.size().
12161
    // In some instances, we may need a bit more.
12162
    ///////////////////////////
12163
    // This is *very* important. This line should *not* be removed
12164
    // hastily. There are principled reasons why reserve is important
12165
    // for performance. If you have a benchmark with small inputs,
12166
    // it may not matter, but in other instances, it could.
12167
    ////
12168
    // This rounds up to the next power of two.
12169
    // We know that user_input.size() is in [0,
12170
    // std::numeric_limits<uint32_t>::max).
12171
44.8k
    uint32_t reserve_capacity =
12172
44.8k
        (0xFFFFFFFF >>
12173
44.8k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
12174
44.8k
        1;
12175
44.8k
    url.reserve(reserve_capacity);
12176
    //
12177
    //
12178
    //
12179
44.8k
  }
12180
59.1k
  std::string tmp_buffer;
12181
59.1k
  std::string_view internal_input;
12182
59.1k
  if (unicode::has_tabs_or_newline(user_input)) {
12183
702
    tmp_buffer = user_input;
12184
    // Optimization opportunity: Instead of copying and then pruning, we could
12185
    // just directly build the string from user_input.
12186
702
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12187
702
    internal_input = tmp_buffer;
12188
58.4k
  } else {
12189
58.4k
    internal_input = user_input;
12190
58.4k
  }
12191
12192
  // Leading and trailing control characters are uncommon and easy to deal with
12193
  // (no performance concern).
12194
59.1k
  std::string_view url_data = internal_input;
12195
59.1k
  helpers::trim_c0_whitespace(url_data);
12196
12197
  // Optimization opportunity. Most websites do not have fragment.
12198
59.1k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
12199
  // We add it last so that an implementation like ada::url_aggregator
12200
  // can append it last to its internal buffer, thus improving performance.
12201
12202
  // Here url_data no longer has its fragment.
12203
  // We are going to access the data from url_data (it is immutable).
12204
  // At any given time, we are pointing at byte 'input_position' in url_data.
12205
  // The input_position variable should range from 0 to input_size.
12206
  // It is illegal to access url_data at input_size.
12207
59.1k
  size_t input_position = 0;
12208
59.1k
  const size_t input_size = url_data.size();
12209
  // Keep running the following state machine by switching on state.
12210
  // If after a run pointer points to the EOF code point, go to the next step.
12211
  // Otherwise, increase pointer by 1 and continue with the state machine.
12212
  // We never decrement input_position.
12213
239k
  while (input_position <= input_size) {
12214
225k
    ada_log("In parsing at ", input_position, " out of ", input_size,
12215
225k
            " in state ", ada::to_string(state));
12216
225k
    switch (state) {
12217
59.1k
      case ada::state::SCHEME_START: {
12218
59.1k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
12219
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
12220
        // state to scheme state.
12221
59.1k
        if ((input_position != input_size) &&
12222
59.1k
            checkers::is_alpha(url_data[input_position])) {
12223
36.7k
          state = ada::state::SCHEME;
12224
36.7k
          input_position++;
12225
36.7k
        } else {
12226
          // Otherwise, if state override is not given, set state to no scheme
12227
          // state and decrease pointer by 1.
12228
22.3k
          state = ada::state::NO_SCHEME;
12229
22.3k
        }
12230
59.1k
        break;
12231
0
      }
12232
36.7k
      case ada::state::SCHEME: {
12233
36.7k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
12234
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
12235
        // append c, lowercased, to buffer.
12236
116k
        while ((input_position != input_size) &&
12237
116k
               (ada::unicode::is_alnum_plus(url_data[input_position]))) {
12238
79.6k
          input_position++;
12239
79.6k
        }
12240
        // Otherwise, if c is U+003A (:), then:
12241
36.7k
        if ((input_position != input_size) &&
12242
36.7k
            (url_data[input_position] == ':')) {
12243
33.6k
          ada_log("SCHEME the scheme should be ",
12244
33.6k
                  url_data.substr(0, input_position));
12245
33.6k
          if constexpr (result_type_is_ada_url) {
12246
23.6k
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
12247
0
              return url;
12248
0
            }
12249
23.6k
          } else {
12250
            // we pass the colon along instead of painfully adding it back.
12251
23.6k
            if (!url.parse_scheme_with_colon(
12252
23.6k
                    url_data.substr(0, input_position + 1))) {
12253
0
              return url;
12254
0
            }
12255
23.6k
          }
12256
33.6k
          ada_log("SCHEME the scheme is ", url.get_protocol());
12257
12258
          // If url's scheme is "file", then:
12259
33.6k
          if (url.type == ada::scheme::type::FILE) {
12260
            // Set state to file state.
12261
5.41k
            state = ada::state::FILE;
12262
5.41k
          }
12263
          // Otherwise, if url is special, base is non-null, and base's scheme
12264
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
12265
          // != nullptr is false.
12266
28.2k
          else if (url.is_special() && base_url != nullptr &&
12267
28.2k
                   base_url->type == url.type) {
12268
            // Set state to special relative or authority state.
12269
94
            state = ada::state::SPECIAL_RELATIVE_OR_AUTHORITY;
12270
94
          }
12271
          // Otherwise, if url is special, set state to special authority
12272
          // slashes state.
12273
28.1k
          else if (url.is_special()) {
12274
17.7k
            state = ada::state::SPECIAL_AUTHORITY_SLASHES;
12275
17.7k
          }
12276
          // Otherwise, if remaining starts with an U+002F (/), set state to
12277
          // path or authority state and increase pointer by 1.
12278
10.3k
          else if (input_position + 1 < input_size &&
12279
10.3k
                   url_data[input_position + 1] == '/') {
12280
6.04k
            state = ada::state::PATH_OR_AUTHORITY;
12281
6.04k
            input_position++;
12282
6.04k
          }
12283
          // Otherwise, set url's path to the empty string and set state to
12284
          // opaque path state.
12285
4.32k
          else {
12286
4.32k
            state = ada::state::OPAQUE_PATH;
12287
4.32k
          }
12288
33.6k
        }
12289
        // Otherwise, if state override is not given, set buffer to the empty
12290
        // string, state to no scheme state, and start over (from the first code
12291
        // point in input).
12292
3.13k
        else {
12293
3.13k
          state = ada::state::NO_SCHEME;
12294
3.13k
          input_position = 0;
12295
3.13k
          break;
12296
3.13k
        }
12297
33.6k
        input_position++;
12298
33.6k
        break;
12299
36.7k
      }
12300
25.5k
      case ada::state::NO_SCHEME: {
12301
25.5k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
12302
        // If base is null, or base has an opaque path and c is not U+0023 (#),
12303
        // validation error, return failure.
12304
25.5k
        if (base_url == nullptr ||
12305
25.5k
            (base_url->has_opaque_path && !fragment.has_value())) {
12306
24.3k
          ada_log("NO_SCHEME validation error");
12307
24.3k
          url.is_valid = false;
12308
24.3k
          return url;
12309
24.3k
        }
12310
        // Otherwise, if base has an opaque path and c is U+0023 (#),
12311
        // set url's scheme to base's scheme, url's path to base's path, url's
12312
        // query to base's query, and set state to fragment state.
12313
1.16k
        else if (base_url->has_opaque_path && fragment.has_value() &&
12314
1.16k
                 input_position == input_size) {
12315
30
          ada_log("NO_SCHEME opaque base with fragment");
12316
30
          url.copy_scheme(*base_url);
12317
30
          url.has_opaque_path = base_url->has_opaque_path;
12318
12319
30
          if constexpr (result_type_is_ada_url) {
12320
30
            url.path = base_url->path;
12321
30
            url.query = base_url->query;
12322
30
          } else {
12323
30
            url.update_base_pathname(base_url->get_pathname());
12324
30
            url.update_base_search(base_url->get_search());
12325
30
          }
12326
30
          url.update_unencoded_base_hash(*fragment);
12327
30
          return url;
12328
30
        }
12329
        // Otherwise, if base's scheme is not "file", set state to relative
12330
        // state and decrease pointer by 1.
12331
1.13k
        else if (base_url->type != ada::scheme::type::FILE) {
12332
655
          ada_log("NO_SCHEME non-file relative path");
12333
655
          state = ada::state::RELATIVE_SCHEME;
12334
655
        }
12335
        // Otherwise, set state to file state and decrease pointer by 1.
12336
477
        else {
12337
477
          ada_log("NO_SCHEME file base type");
12338
477
          state = ada::state::FILE;
12339
477
        }
12340
1.13k
        break;
12341
25.5k
      }
12342
19.1k
      case ada::state::AUTHORITY: {
12343
19.1k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
12344
        // most URLs have no @. Having no @ tells us that we don't have to worry
12345
        // about AUTHORITY. Of course, we could have @ and still not have to
12346
        // worry about AUTHORITY.
12347
        // TODO: Instead of just collecting a bool, collect the location of the
12348
        // '@' and do something useful with it.
12349
        // TODO: We could do various processing early on, using a single pass
12350
        // over the string to collect information about it, e.g., telling us
12351
        // whether there is a @ and if so, where (or how many).
12352
19.1k
        const bool contains_ampersand =
12353
19.1k
            (url_data.find('@', input_position) != std::string_view::npos);
12354
12355
19.1k
        if (!contains_ampersand) {
12356
17.8k
          state = ada::state::HOST;
12357
17.8k
          break;
12358
17.8k
        }
12359
1.28k
        bool at_sign_seen{false};
12360
1.28k
        bool password_token_seen{false};
12361
        /**
12362
         * We expect something of the sort...
12363
         * https://user:pass@example.com:1234/foo/bar?baz#quux
12364
         * --------^
12365
         */
12366
10.7k
        do {
12367
10.7k
          std::string_view view = helpers::substring(url_data, input_position);
12368
          // The delimiters are @, /, ? \\.
12369
10.7k
          size_t location =
12370
10.7k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
12371
10.7k
                               : helpers::find_authority_delimiter(view);
12372
10.7k
          std::string_view authority_view(view.data(), location);
12373
10.7k
          size_t end_of_authority = input_position + authority_view.size();
12374
          // If c is U+0040 (@), then:
12375
10.7k
          if ((end_of_authority != input_size) &&
12376
10.7k
              (url_data[end_of_authority] == '@')) {
12377
            // If atSignSeen is true, then prepend "%40" to buffer.
12378
9.42k
            if (at_sign_seen) {
12379
8.18k
              if (password_token_seen) {
12380
2.28k
                if constexpr (result_type_is_ada_url) {
12381
1.61k
                  url.password += "%40";
12382
1.61k
                } else {
12383
1.61k
                  url.append_base_password("%40");
12384
1.61k
                }
12385
5.89k
              } else {
12386
5.89k
                if constexpr (result_type_is_ada_url) {
12387
4.14k
                  url.username += "%40";
12388
4.14k
                } else {
12389
4.14k
                  url.append_base_username("%40");
12390
4.14k
                }
12391
5.89k
              }
12392
8.18k
            }
12393
12394
9.42k
            at_sign_seen = true;
12395
12396
9.42k
            if (!password_token_seen) {
12397
7.14k
              size_t password_token_location = authority_view.find(':');
12398
7.14k
              password_token_seen =
12399
7.14k
                  password_token_location != std::string_view::npos;
12400
12401
7.14k
              if (!password_token_seen) {
12402
6.67k
                if constexpr (result_type_is_ada_url) {
12403
4.68k
                  url.username += unicode::percent_encode(
12404
4.68k
                      authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12405
4.68k
                } else {
12406
4.68k
                  url.append_base_username(unicode::percent_encode(
12407
4.68k
                      authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12408
4.68k
                }
12409
6.67k
              } else {
12410
471
                if constexpr (result_type_is_ada_url) {
12411
332
                  url.username += unicode::percent_encode(
12412
332
                      authority_view.substr(0, password_token_location),
12413
332
                      character_sets::USERINFO_PERCENT_ENCODE);
12414
332
                  url.password += unicode::percent_encode(
12415
332
                      authority_view.substr(password_token_location + 1),
12416
332
                      character_sets::USERINFO_PERCENT_ENCODE);
12417
332
                } else {
12418
332
                  url.append_base_username(unicode::percent_encode(
12419
332
                      authority_view.substr(0, password_token_location),
12420
332
                      character_sets::USERINFO_PERCENT_ENCODE));
12421
332
                  url.append_base_password(unicode::percent_encode(
12422
332
                      authority_view.substr(password_token_location + 1),
12423
332
                      character_sets::USERINFO_PERCENT_ENCODE));
12424
332
                }
12425
471
              }
12426
7.14k
            } else {
12427
2.28k
              if constexpr (result_type_is_ada_url) {
12428
1.61k
                url.password += unicode::percent_encode(
12429
1.61k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12430
1.61k
              } else {
12431
1.61k
                url.append_base_password(unicode::percent_encode(
12432
1.61k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12433
1.61k
              }
12434
2.28k
            }
12435
9.42k
          }
12436
          // Otherwise, if one of the following is true:
12437
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12438
          // - url is special and c is U+005C (\)
12439
1.28k
          else if (end_of_authority == input_size ||
12440
1.28k
                   url_data[end_of_authority] == '/' ||
12441
1.28k
                   url_data[end_of_authority] == '?' ||
12442
1.28k
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
12443
            // If atSignSeen is true and authority_view is the empty string,
12444
            // validation error, return failure.
12445
1.28k
            if (at_sign_seen && authority_view.empty()) {
12446
678
              url.is_valid = false;
12447
678
              return url;
12448
678
            }
12449
603
            state = ada::state::HOST;
12450
603
            break;
12451
1.28k
          }
12452
9.42k
          if (end_of_authority == input_size) {
12453
0
            if (fragment.has_value()) {
12454
0
              url.update_unencoded_base_hash(*fragment);
12455
0
            }
12456
0
            return url;
12457
0
          }
12458
9.42k
          input_position = end_of_authority + 1;
12459
9.42k
        } while (true);
12460
12461
603
        break;
12462
1.28k
      }
12463
603
      case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY: {
12464
94
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
12465
94
                helpers::substring(url_data, input_position));
12466
12467
        // If c is U+002F (/) and remaining starts with U+002F (/),
12468
        // then set state to special authority ignore slashes state and increase
12469
        // pointer by 1.
12470
94
        std::string_view view = helpers::substring(url_data, input_position);
12471
94
        if (ada::checkers::begins_with(view, "//")) {
12472
1
          state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12473
1
          input_position += 2;
12474
93
        } else {
12475
          // Otherwise, validation error, set state to relative state and
12476
          // decrease pointer by 1.
12477
93
          state = ada::state::RELATIVE_SCHEME;
12478
93
        }
12479
12480
94
        break;
12481
1.28k
      }
12482
6.04k
      case ada::state::PATH_OR_AUTHORITY: {
12483
6.04k
        ada_log("PATH_OR_AUTHORITY ",
12484
6.04k
                helpers::substring(url_data, input_position));
12485
12486
        // If c is U+002F (/), then set state to authority state.
12487
6.04k
        if ((input_position != input_size) &&
12488
6.04k
            (url_data[input_position] == '/')) {
12489
1.38k
          state = ada::state::AUTHORITY;
12490
1.38k
          input_position++;
12491
4.65k
        } else {
12492
          // Otherwise, set state to path state, and decrease pointer by 1.
12493
4.65k
          state = ada::state::PATH;
12494
4.65k
        }
12495
12496
6.04k
        break;
12497
1.28k
      }
12498
748
      case ada::state::RELATIVE_SCHEME: {
12499
748
        ada_log("RELATIVE_SCHEME ",
12500
748
                helpers::substring(url_data, input_position));
12501
12502
        // Set url's scheme to base's scheme.
12503
748
        url.copy_scheme(*base_url);
12504
12505
        // If c is U+002F (/), then set state to relative slash state.
12506
748
        if ((input_position != input_size) &&
12507
748
            (url_data[input_position] == '/')) {
12508
41
          ada_log(
12509
41
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
12510
41
              "slash state");
12511
41
          state = ada::state::RELATIVE_SLASH;
12512
707
        } else if (url.is_special() && (input_position != input_size) &&
12513
707
                   (url_data[input_position] == '\\')) {
12514
          // Otherwise, if url is special and c is U+005C (\), validation error,
12515
          // set state to relative slash state.
12516
1
          ada_log(
12517
1
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
12518
1
              "error, set state to relative slash state");
12519
1
          state = ada::state::RELATIVE_SLASH;
12520
706
        } else {
12521
706
          ada_log("RELATIVE_SCHEME otherwise");
12522
          // Set url's username to base's username, url's password to base's
12523
          // password, url's host to base's host, url's port to base's port,
12524
          // url's path to a clone of base's path, and url's query to base's
12525
          // query.
12526
706
          if constexpr (result_type_is_ada_url) {
12527
706
            url.username = base_url->username;
12528
706
            url.password = base_url->password;
12529
706
            url.host = base_url->host;
12530
706
            url.port = base_url->port;
12531
            // cloning the base path includes cloning the has_opaque_path flag
12532
0
            url.has_opaque_path = base_url->has_opaque_path;
12533
0
            url.path = base_url->path;
12534
0
            url.query = base_url->query;
12535
706
          } else {
12536
706
            url.update_base_authority(base_url->get_href(),
12537
706
                                      base_url->get_components());
12538
            // TODO: Get rid of set_hostname and replace it with
12539
            // update_base_hostname
12540
706
            url.set_hostname(base_url->get_hostname());
12541
706
            url.update_base_port(base_url->retrieve_base_port());
12542
            // cloning the base path includes cloning the has_opaque_path flag
12543
706
            url.has_opaque_path = base_url->has_opaque_path;
12544
706
            url.update_base_pathname(base_url->get_pathname());
12545
706
            url.update_base_search(base_url->get_search());
12546
706
          }
12547
12548
706
          url.has_opaque_path = base_url->has_opaque_path;
12549
12550
          // If c is U+003F (?), then set url's query to the empty string, and
12551
          // state to query state.
12552
706
          if ((input_position != input_size) &&
12553
706
              (url_data[input_position] == '?')) {
12554
5
            state = ada::state::QUERY;
12555
5
          }
12556
          // Otherwise, if c is not the EOF code point:
12557
701
          else if (input_position != input_size) {
12558
            // Set url's query to null.
12559
209
            url.clear_search();
12560
209
            if constexpr (result_type_is_ada_url) {
12561
              // Shorten url's path.
12562
0
              helpers::shorten_path(url.path, url.type);
12563
209
            } else {
12564
209
              std::string_view path = url.get_pathname();
12565
209
              if (helpers::shorten_path(path, url.type)) {
12566
172
                url.update_base_pathname(std::string(path));
12567
172
              }
12568
209
            }
12569
            // Set state to path state and decrease pointer by 1.
12570
209
            state = ada::state::PATH;
12571
209
            break;
12572
209
          }
12573
706
        }
12574
539
        input_position++;
12575
539
        break;
12576
748
      }
12577
42
      case ada::state::RELATIVE_SLASH: {
12578
42
        ada_log("RELATIVE_SLASH ",
12579
42
                helpers::substring(url_data, input_position));
12580
12581
        // If url is special and c is U+002F (/) or U+005C (\), then:
12582
42
        if (url.is_special() && (input_position != input_size) &&
12583
42
            (url_data[input_position] == '/' ||
12584
13
             url_data[input_position] == '\\')) {
12585
          // Set state to special authority ignore slashes state.
12586
2
          state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12587
2
        }
12588
        // Otherwise, if c is U+002F (/), then set state to authority state.
12589
40
        else if ((input_position != input_size) &&
12590
40
                 (url_data[input_position] == '/')) {
12591
6
          state = ada::state::AUTHORITY;
12592
6
        }
12593
        // Otherwise, set
12594
        // - url's username to base's username,
12595
        // - url's password to base's password,
12596
        // - url's host to base's host,
12597
        // - url's port to base's port,
12598
        // - state to path state, and then, decrease pointer by 1.
12599
34
        else {
12600
34
          if constexpr (result_type_is_ada_url) {
12601
34
            url.username = base_url->username;
12602
34
            url.password = base_url->password;
12603
34
            url.host = base_url->host;
12604
34
            url.port = base_url->port;
12605
34
          } else {
12606
34
            url.update_base_authority(base_url->get_href(),
12607
34
                                      base_url->get_components());
12608
            // TODO: Get rid of set_hostname and replace it with
12609
            // update_base_hostname
12610
34
            url.set_hostname(base_url->get_hostname());
12611
34
            url.update_base_port(base_url->retrieve_base_port());
12612
34
          }
12613
34
          state = ada::state::PATH;
12614
34
          break;
12615
34
        }
12616
12617
8
        input_position++;
12618
8
        break;
12619
42
      }
12620
17.7k
      case ada::state::SPECIAL_AUTHORITY_SLASHES: {
12621
17.7k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
12622
17.7k
                helpers::substring(url_data, input_position));
12623
12624
        // If c is U+002F (/) and remaining starts with U+002F (/),
12625
        // then set state to special authority ignore slashes state and increase
12626
        // pointer by 1.
12627
17.7k
        std::string_view view = helpers::substring(url_data, input_position);
12628
17.7k
        if (ada::checkers::begins_with(view, "//")) {
12629
39
          input_position += 2;
12630
39
        }
12631
12632
17.7k
        [[fallthrough]];
12633
17.7k
      }
12634
17.7k
      case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
12635
17.7k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
12636
17.7k
                helpers::substring(url_data, input_position));
12637
12638
        // If c is neither U+002F (/) nor U+005C (\), then set state to
12639
        // authority state and decrease pointer by 1.
12640
19.5k
        while ((input_position != input_size) &&
12641
19.5k
               ((url_data[input_position] == '/') ||
12642
19.4k
                (url_data[input_position] == '\\'))) {
12643
1.77k
          input_position++;
12644
1.77k
        }
12645
17.7k
        state = ada::state::AUTHORITY;
12646
12647
17.7k
        break;
12648
17.7k
      }
12649
955
      case ada::state::QUERY: {
12650
955
        ada_log("QUERY ", helpers::substring(url_data, input_position));
12651
        // Let queryPercentEncodeSet be the special-query percent-encode set if
12652
        // url is special; otherwise the query percent-encode set.
12653
955
        const uint8_t* query_percent_encode_set =
12654
955
            url.is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12655
955
                             : ada::character_sets::QUERY_PERCENT_ENCODE;
12656
12657
        // Percent-encode after encoding, with encoding, buffer, and
12658
        // queryPercentEncodeSet, and append the result to url's query.
12659
955
        url.update_base_search(helpers::substring(url_data, input_position),
12660
955
                               query_percent_encode_set);
12661
955
        ada_log("QUERY update_base_search completed ");
12662
955
        if (fragment.has_value()) {
12663
110
          url.update_unencoded_base_hash(*fragment);
12664
110
        }
12665
955
        return url;
12666
17.7k
      }
12667
18.4k
      case ada::state::HOST: {
12668
18.4k
        ada_log("HOST ", helpers::substring(url_data, input_position));
12669
12670
18.4k
        std::string_view host_view =
12671
18.4k
            helpers::substring(url_data, input_position);
12672
18.4k
        auto [location, found_colon] =
12673
18.4k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
12674
18.4k
        input_position = (location != std::string_view::npos)
12675
18.4k
                             ? input_position + location
12676
18.4k
                             : input_size;
12677
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12678
        // Note: the 'found_colon' value is true if and only if a colon was
12679
        // encountered while not inside brackets.
12680
18.4k
        if (found_colon) {
12681
          // If buffer is the empty string, validation error, return failure.
12682
          // Let host be the result of host parsing buffer with url is not
12683
          // special.
12684
2.63k
          ada_log("HOST parsing ", host_view);
12685
2.63k
          if (!url.parse_host(host_view)) {
12686
535
            return url;
12687
535
          }
12688
2.10k
          ada_log("HOST parsing results in ", url.get_hostname());
12689
          // Set url's host to host, buffer to the empty string, and state to
12690
          // port state.
12691
2.10k
          state = ada::state::PORT;
12692
2.10k
          input_position++;
12693
2.10k
        }
12694
        // Otherwise, if one of the following is true:
12695
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12696
        // - url is special and c is U+005C (\)
12697
        // The get_host_delimiter_location function either brings us to
12698
        // the colon outside of the bracket, or to one of those characters.
12699
15.8k
        else {
12700
          // If url is special and host_view is the empty string, validation
12701
          // error, return failure.
12702
15.8k
          if (url.is_special() && host_view.empty()) {
12703
131
            url.is_valid = false;
12704
131
            return url;
12705
131
          }
12706
15.7k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
12707
          // Let host be the result of host parsing host_view with url is not
12708
          // special.
12709
15.7k
          if (host_view.empty()) {
12710
65
            url.update_base_hostname("");
12711
15.6k
          } else if (!url.parse_host(host_view)) {
12712
3.88k
            return url;
12713
3.88k
          }
12714
11.8k
          ada_log("HOST parsing results in ", url.get_hostname(),
12715
11.8k
                  " href=", url.get_href());
12716
12717
          // Set url's host to host, and state to path start state.
12718
11.8k
          state = ada::state::PATH_START;
12719
11.8k
        }
12720
12721
13.9k
        break;
12722
18.4k
      }
12723
13.9k
      case ada::state::OPAQUE_PATH: {
12724
4.32k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
12725
4.32k
        std::string_view view = helpers::substring(url_data, input_position);
12726
        // If c is U+003F (?), then set url's query to the empty string and
12727
        // state to query state.
12728
4.32k
        size_t location = view.find('?');
12729
4.32k
        if (location != std::string_view::npos) {
12730
258
          view.remove_suffix(view.size() - location);
12731
258
          state = ada::state::QUERY;
12732
258
          input_position += location + 1;
12733
4.06k
        } else {
12734
4.06k
          input_position = input_size + 1;
12735
4.06k
        }
12736
4.32k
        url.has_opaque_path = true;
12737
        // This is a really unlikely scenario in real world. We should not seek
12738
        // to optimize it.
12739
4.32k
        url.update_base_pathname(unicode::percent_encode(
12740
4.32k
            view, character_sets::C0_CONTROL_PERCENT_ENCODE));
12741
4.32k
        break;
12742
18.4k
      }
12743
2.10k
      case ada::state::PORT: {
12744
2.10k
        ada_log("PORT ", helpers::substring(url_data, input_position));
12745
2.10k
        std::string_view port_view =
12746
2.10k
            helpers::substring(url_data, input_position);
12747
2.10k
        size_t consumed_bytes = url.parse_port(port_view, true);
12748
2.10k
        input_position += consumed_bytes;
12749
2.10k
        if (!url.is_valid) {
12750
227
          return url;
12751
227
        }
12752
1.87k
        state = state::PATH_START;
12753
1.87k
        [[fallthrough]];
12754
1.87k
      }
12755
15.3k
      case ada::state::PATH_START: {
12756
15.3k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
12757
12758
        // If url is special, then:
12759
15.3k
        if (url.is_special()) {
12760
          // Set state to path state.
12761
14.4k
          state = ada::state::PATH;
12762
12763
          // Optimization: Avoiding going into PATH state improves the
12764
          // performance of urls ending with /.
12765
14.4k
          if (input_position == input_size) {
12766
13.1k
            url.update_base_pathname("/");
12767
13.1k
            if (fragment.has_value()) {
12768
195
              url.update_unencoded_base_hash(*fragment);
12769
195
            }
12770
13.1k
            return url;
12771
13.1k
          }
12772
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
12773
          // by 1. We know that (input_position == input_size) is impossible
12774
          // here, because of the previous if-check.
12775
1.34k
          if ((url_data[input_position] != '/') &&
12776
1.34k
              (url_data[input_position] != '\\')) {
12777
321
            break;
12778
321
          }
12779
1.34k
        }
12780
        // Otherwise, if state override is not given and c is U+003F (?),
12781
        // set url's query to the empty string and state to query state.
12782
879
        else if ((input_position != input_size) &&
12783
879
                 (url_data[input_position] == '?')) {
12784
108
          state = ada::state::QUERY;
12785
108
        }
12786
        // Otherwise, if c is not the EOF code point:
12787
771
        else if (input_position != input_size) {
12788
          // Set state to path state.
12789
54
          state = ada::state::PATH;
12790
12791
          // If c is not U+002F (/), then decrease pointer by 1.
12792
54
          if (url_data[input_position] != '/') {
12793
0
            break;
12794
0
          }
12795
54
        }
12796
12797
1.90k
        input_position++;
12798
1.90k
        break;
12799
15.3k
      }
12800
9.89k
      case ada::state::PATH: {
12801
9.89k
        std::string_view view = helpers::substring(url_data, input_position);
12802
9.89k
        ada_log("PATH ", helpers::substring(url_data, input_position));
12803
12804
        // Most time, we do not need percent encoding.
12805
        // Furthermore, we can immediately locate the '?'.
12806
9.89k
        size_t locofquestionmark = view.find('?');
12807
9.89k
        if (locofquestionmark != std::string_view::npos) {
12808
582
          state = ada::state::QUERY;
12809
582
          view.remove_suffix(view.size() - locofquestionmark);
12810
582
          input_position += locofquestionmark + 1;
12811
9.31k
        } else {
12812
9.31k
          input_position = input_size + 1;
12813
9.31k
        }
12814
9.89k
        if constexpr (result_type_is_ada_url) {
12815
6.97k
          helpers::parse_prepared_path(view, url.type, url.path);
12816
6.97k
        } else {
12817
6.97k
          url.consume_prepared_path(view);
12818
6.97k
          ADA_ASSERT_TRUE(url.validate());
12819
6.97k
        }
12820
9.89k
        break;
12821
15.3k
      }
12822
2.48k
      case ada::state::FILE_SLASH: {
12823
2.48k
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
12824
12825
        // If c is U+002F (/) or U+005C (\), then:
12826
2.48k
        if ((input_position != input_size) &&
12827
2.48k
            (url_data[input_position] == '/' ||
12828
2.16k
             url_data[input_position] == '\\')) {
12829
2.06k
          ada_log("FILE_SLASH c is U+002F or U+005C");
12830
          // Set state to file host state.
12831
2.06k
          state = ada::state::FILE_HOST;
12832
2.06k
          input_position++;
12833
2.06k
        } else {
12834
419
          ada_log("FILE_SLASH otherwise");
12835
          // If base is non-null and base's scheme is "file", then:
12836
          // Note: it is unsafe to do base_url->scheme unless you know that
12837
          // base_url_has_value() is true.
12838
419
          if (base_url != nullptr &&
12839
419
              base_url->type == ada::scheme::type::FILE) {
12840
            // Set url's host to base's host.
12841
222
            if constexpr (result_type_is_ada_url) {
12842
222
              url.host = base_url->host;
12843
222
            } else {
12844
              // TODO: Optimization opportunity.
12845
222
              url.set_host(base_url->get_host());
12846
222
            }
12847
            // If the code point substring from pointer to the end of input does
12848
            // not start with a Windows drive letter and base's path[0] is a
12849
            // normalized Windows drive letter, then append base's path[0] to
12850
            // url's path.
12851
222
            if (!base_url->get_pathname().empty()) {
12852
222
              if (!checkers::is_windows_drive_letter(
12853
222
                      helpers::substring(url_data, input_position))) {
12854
215
                std::string_view first_base_url_path =
12855
215
                    base_url->get_pathname().substr(1);
12856
215
                size_t loc = first_base_url_path.find('/');
12857
215
                if (loc != std::string_view::npos) {
12858
12
                  helpers::resize(first_base_url_path, loc);
12859
12
                }
12860
215
                if (checkers::is_normalized_windows_drive_letter(
12861
215
                        first_base_url_path)) {
12862
3
                  if constexpr (result_type_is_ada_url) {
12863
3
                    url.path += '/';
12864
3
                    url.path += first_base_url_path;
12865
3
                  } else {
12866
3
                    url.append_base_pathname(
12867
3
                        helpers::concat("/", first_base_url_path));
12868
3
                  }
12869
3
                }
12870
215
              }
12871
222
            }
12872
222
          }
12873
12874
          // Set state to path state, and decrease pointer by 1.
12875
419
          state = ada::state::PATH;
12876
419
        }
12877
12878
2.48k
        break;
12879
15.3k
      }
12880
2.06k
      case ada::state::FILE_HOST: {
12881
2.06k
        std::string_view view = helpers::substring(url_data, input_position);
12882
2.06k
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
12883
12884
2.06k
        size_t location = view.find_first_of("/\\?");
12885
2.06k
        std::string_view file_host_buffer(
12886
2.06k
            view.data(),
12887
2.06k
            (location != std::string_view::npos) ? location : view.size());
12888
12889
2.06k
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
12890
26
          state = ada::state::PATH;
12891
2.04k
        } else if (file_host_buffer.empty()) {
12892
          // Set url's host to the empty string.
12893
52
          if constexpr (result_type_is_ada_url) {
12894
40
            url.host = "";
12895
40
          } else {
12896
40
            url.update_base_hostname("");
12897
40
          }
12898
          // Set state to path start state.
12899
52
          state = ada::state::PATH_START;
12900
1.99k
        } else {
12901
1.99k
          size_t consumed_bytes = file_host_buffer.size();
12902
1.99k
          input_position += consumed_bytes;
12903
          // Let host be the result of host parsing buffer with url is not
12904
          // special.
12905
1.99k
          if (!url.parse_host(file_host_buffer)) {
12906
385
            return url;
12907
385
          }
12908
12909
1.60k
          if constexpr (result_type_is_ada_url) {
12910
            // If host is "localhost", then set host to the empty string.
12911
1.24k
            if (url.host.has_value() && url.host.value() == "localhost") {
12912
3
              url.host = "";
12913
3
            }
12914
1.24k
          } else {
12915
1.24k
            if (url.get_hostname() == "localhost") {
12916
10
              url.update_base_hostname("");
12917
10
            }
12918
1.24k
          }
12919
12920
          // Set buffer to the empty string and state to path start state.
12921
1.60k
          state = ada::state::PATH_START;
12922
1.60k
        }
12923
12924
1.68k
        break;
12925
2.06k
      }
12926
5.89k
      case ada::state::FILE: {
12927
5.89k
        ada_log("FILE ", helpers::substring(url_data, input_position));
12928
5.89k
        std::string_view file_view =
12929
5.89k
            helpers::substring(url_data, input_position);
12930
12931
5.89k
        url.set_protocol_as_file();
12932
5.89k
        if constexpr (result_type_is_ada_url) {
12933
          // Set url's host to the empty string.
12934
1.51k
          url.host = "";
12935
4.37k
        } else {
12936
4.37k
          url.update_base_hostname("");
12937
4.37k
        }
12938
        // If c is U+002F (/) or U+005C (\), then:
12939
5.89k
        if (input_position != input_size &&
12940
5.89k
            (url_data[input_position] == '/' ||
12941
3.72k
             url_data[input_position] == '\\')) {
12942
2.48k
          ada_log("FILE c is U+002F or U+005C");
12943
          // Set state to file slash state.
12944
2.48k
          state = ada::state::FILE_SLASH;
12945
2.48k
        }
12946
        // Otherwise, if base is non-null and base's scheme is "file":
12947
3.40k
        else if (base_url != nullptr &&
12948
3.40k
                 base_url->type == ada::scheme::type::FILE) {
12949
          // Set url's host to base's host, url's path to a clone of base's
12950
          // path, and url's query to base's query.
12951
345
          ada_log("FILE base non-null");
12952
345
          if constexpr (result_type_is_ada_url) {
12953
345
            url.host = base_url->host;
12954
345
            url.path = base_url->path;
12955
345
            url.query = base_url->query;
12956
345
          } else {
12957
            // TODO: Get rid of set_hostname and replace it with
12958
            // update_base_hostname
12959
345
            url.set_hostname(base_url->get_hostname());
12960
345
            url.update_base_pathname(base_url->get_pathname());
12961
345
            url.update_base_search(base_url->get_search());
12962
345
          }
12963
345
          url.has_opaque_path = base_url->has_opaque_path;
12964
12965
          // If c is U+003F (?), then set url's query to the empty string and
12966
          // state to query state.
12967
345
          if (input_position != input_size && url_data[input_position] == '?') {
12968
2
            state = ada::state::QUERY;
12969
2
          }
12970
          // Otherwise, if c is not the EOF code point:
12971
343
          else if (input_position != input_size) {
12972
            // Set url's query to null.
12973
93
            url.clear_search();
12974
            // If the code point substring from pointer to the end of input does
12975
            // not start with a Windows drive letter, then shorten url's path.
12976
93
            if (!checkers::is_windows_drive_letter(file_view)) {
12977
81
              if constexpr (result_type_is_ada_url) {
12978
81
                helpers::shorten_path(url.path, url.type);
12979
81
              } else {
12980
81
                std::string_view path = url.get_pathname();
12981
81
                if (helpers::shorten_path(path, url.type)) {
12982
76
                  url.update_base_pathname(std::string(path));
12983
76
                }
12984
81
              }
12985
81
            }
12986
            // Otherwise:
12987
12
            else {
12988
              // Set url's path to an empty list.
12989
12
              url.clear_pathname();
12990
12
              url.has_opaque_path = true;
12991
12
            }
12992
12993
            // Set state to path state and decrease pointer by 1.
12994
93
            state = ada::state::PATH;
12995
93
            break;
12996
93
          }
12997
345
        }
12998
        // Otherwise, set state to path state, and decrease pointer by 1.
12999
3.05k
        else {
13000
3.05k
          ada_log("FILE go to path");
13001
3.05k
          state = ada::state::PATH;
13002
3.05k
          break;
13003
3.05k
        }
13004
13005
2.73k
        input_position++;
13006
2.73k
        break;
13007
5.89k
      }
13008
0
      default:
13009
0
        ada::unreachable();
13010
225k
    }
13011
225k
  }
13012
14.8k
  if (fragment.has_value()) {
13013
611
    url.update_unencoded_base_hash(*fragment);
13014
611
  }
13015
14.8k
  return url;
13016
59.1k
}
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
12124
14.3k
                      const result_type* base_url) {
12125
  // We can specialize the implementation per type.
12126
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
12127
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
12128
  // something else } is free (at runtime). This means that ada::url_aggregator
12129
  // and ada::url **do not have to support the exact same API**.
12130
14.3k
  constexpr bool result_type_is_ada_url =
12131
14.3k
      std::is_same<ada::url, result_type>::value;
12132
14.3k
  constexpr bool result_type_is_ada_url_aggregator =
12133
14.3k
      std::is_same<ada::url_aggregator, result_type>::value;
12134
14.3k
  static_assert(result_type_is_ada_url ||
12135
14.3k
                result_type_is_ada_url_aggregator);  // We don't support
12136
                                                     // anything else for now.
12137
12138
14.3k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
12139
14.3k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
12140
14.3k
          ")");
12141
12142
14.3k
  ada::state state = ada::state::SCHEME_START;
12143
14.3k
  result_type url{};
12144
12145
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
12146
  // surely the result of a bug or are otherwise a security concern.
12147
14.3k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) {
12148
0
    url.is_valid = false;
12149
0
  }
12150
  // Going forward, user_input.size() is in [0,
12151
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
12152
  // base, or the optional_url was invalid, we must return.
12153
14.3k
  if (base_url != nullptr) {
12154
0
    url.is_valid &= base_url->is_valid;
12155
0
  }
12156
14.3k
  if (!url.is_valid) {
12157
0
    return url;
12158
0
  }
12159
14.3k
  if constexpr (result_type_is_ada_url_aggregator) {
12160
    // Most of the time, we just need user_input.size().
12161
    // In some instances, we may need a bit more.
12162
    ///////////////////////////
12163
    // This is *very* important. This line should *not* be removed
12164
    // hastily. There are principled reasons why reserve is important
12165
    // for performance. If you have a benchmark with small inputs,
12166
    // it may not matter, but in other instances, it could.
12167
    ////
12168
    // This rounds up to the next power of two.
12169
    // We know that user_input.size() is in [0,
12170
    // std::numeric_limits<uint32_t>::max).
12171
14.3k
    uint32_t reserve_capacity =
12172
14.3k
        (0xFFFFFFFF >>
12173
14.3k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
12174
14.3k
        1;
12175
14.3k
    url.reserve(reserve_capacity);
12176
    //
12177
    //
12178
    //
12179
14.3k
  }
12180
14.3k
  std::string tmp_buffer;
12181
14.3k
  std::string_view internal_input;
12182
14.3k
  if (unicode::has_tabs_or_newline(user_input)) {
12183
208
    tmp_buffer = user_input;
12184
    // Optimization opportunity: Instead of copying and then pruning, we could
12185
    // just directly build the string from user_input.
12186
208
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12187
208
    internal_input = tmp_buffer;
12188
14.1k
  } else {
12189
14.1k
    internal_input = user_input;
12190
14.1k
  }
12191
12192
  // Leading and trailing control characters are uncommon and easy to deal with
12193
  // (no performance concern).
12194
14.3k
  std::string_view url_data = internal_input;
12195
14.3k
  helpers::trim_c0_whitespace(url_data);
12196
12197
  // Optimization opportunity. Most websites do not have fragment.
12198
14.3k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
12199
  // We add it last so that an implementation like ada::url_aggregator
12200
  // can append it last to its internal buffer, thus improving performance.
12201
12202
  // Here url_data no longer has its fragment.
12203
  // We are going to access the data from url_data (it is immutable).
12204
  // At any given time, we are pointing at byte 'input_position' in url_data.
12205
  // The input_position variable should range from 0 to input_size.
12206
  // It is illegal to access url_data at input_size.
12207
14.3k
  size_t input_position = 0;
12208
14.3k
  const size_t input_size = url_data.size();
12209
  // Keep running the following state machine by switching on state.
12210
  // If after a run pointer points to the EOF code point, go to the next step.
12211
  // Otherwise, increase pointer by 1 and continue with the state machine.
12212
  // We never decrement input_position.
12213
64.0k
  while (input_position <= input_size) {
12214
60.0k
    ada_log("In parsing at ", input_position, " out of ", input_size,
12215
60.0k
            " in state ", ada::to_string(state));
12216
60.0k
    switch (state) {
12217
14.3k
      case ada::state::SCHEME_START: {
12218
14.3k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
12219
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
12220
        // state to scheme state.
12221
14.3k
        if ((input_position != input_size) &&
12222
14.3k
            checkers::is_alpha(url_data[input_position])) {
12223
10.9k
          state = ada::state::SCHEME;
12224
10.9k
          input_position++;
12225
10.9k
        } else {
12226
          // Otherwise, if state override is not given, set state to no scheme
12227
          // state and decrease pointer by 1.
12228
3.38k
          state = ada::state::NO_SCHEME;
12229
3.38k
        }
12230
14.3k
        break;
12231
0
      }
12232
10.9k
      case ada::state::SCHEME: {
12233
10.9k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
12234
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
12235
        // append c, lowercased, to buffer.
12236
35.7k
        while ((input_position != input_size) &&
12237
35.7k
               (ada::unicode::is_alnum_plus(url_data[input_position]))) {
12238
24.7k
          input_position++;
12239
24.7k
        }
12240
        // Otherwise, if c is U+003A (:), then:
12241
10.9k
        if ((input_position != input_size) &&
12242
10.9k
            (url_data[input_position] == ':')) {
12243
9.95k
          ada_log("SCHEME the scheme should be ",
12244
9.95k
                  url_data.substr(0, input_position));
12245
9.95k
          if constexpr (result_type_is_ada_url) {
12246
9.95k
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
12247
0
              return url;
12248
0
            }
12249
9.95k
          } else {
12250
            // we pass the colon along instead of painfully adding it back.
12251
9.95k
            if (!url.parse_scheme_with_colon(
12252
9.95k
                    url_data.substr(0, input_position + 1))) {
12253
9.95k
              return url;
12254
9.95k
            }
12255
9.95k
          }
12256
9.95k
          ada_log("SCHEME the scheme is ", url.get_protocol());
12257
12258
          // If url's scheme is "file", then:
12259
9.95k
          if (url.type == ada::scheme::type::FILE) {
12260
            // Set state to file state.
12261
1.51k
            state = ada::state::FILE;
12262
1.51k
          }
12263
          // Otherwise, if url is special, base is non-null, and base's scheme
12264
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
12265
          // != nullptr is false.
12266
8.43k
          else if (url.is_special() && base_url != nullptr &&
12267
8.43k
                   base_url->type == url.type) {
12268
            // Set state to special relative or authority state.
12269
0
            state = ada::state::SPECIAL_RELATIVE_OR_AUTHORITY;
12270
0
          }
12271
          // Otherwise, if url is special, set state to special authority
12272
          // slashes state.
12273
8.43k
          else if (url.is_special()) {
12274
5.45k
            state = ada::state::SPECIAL_AUTHORITY_SLASHES;
12275
5.45k
          }
12276
          // Otherwise, if remaining starts with an U+002F (/), set state to
12277
          // path or authority state and increase pointer by 1.
12278
2.98k
          else if (input_position + 1 < input_size &&
12279
2.98k
                   url_data[input_position + 1] == '/') {
12280
1.93k
            state = ada::state::PATH_OR_AUTHORITY;
12281
1.93k
            input_position++;
12282
1.93k
          }
12283
          // Otherwise, set url's path to the empty string and set state to
12284
          // opaque path state.
12285
1.04k
          else {
12286
1.04k
            state = ada::state::OPAQUE_PATH;
12287
1.04k
          }
12288
9.95k
        }
12289
        // Otherwise, if state override is not given, set buffer to the empty
12290
        // string, state to no scheme state, and start over (from the first code
12291
        // point in input).
12292
994
        else {
12293
994
          state = ada::state::NO_SCHEME;
12294
994
          input_position = 0;
12295
994
          break;
12296
994
        }
12297
9.95k
        input_position++;
12298
9.95k
        break;
12299
10.9k
      }
12300
4.38k
      case ada::state::NO_SCHEME: {
12301
4.38k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
12302
        // If base is null, or base has an opaque path and c is not U+0023 (#),
12303
        // validation error, return failure.
12304
4.38k
        if (base_url == nullptr ||
12305
4.38k
            (base_url->has_opaque_path && !fragment.has_value())) {
12306
4.38k
          ada_log("NO_SCHEME validation error");
12307
4.38k
          url.is_valid = false;
12308
4.38k
          return url;
12309
4.38k
        }
12310
        // Otherwise, if base has an opaque path and c is U+0023 (#),
12311
        // set url's scheme to base's scheme, url's path to base's path, url's
12312
        // query to base's query, and set state to fragment state.
12313
0
        else if (base_url->has_opaque_path && fragment.has_value() &&
12314
0
                 input_position == input_size) {
12315
0
          ada_log("NO_SCHEME opaque base with fragment");
12316
0
          url.copy_scheme(*base_url);
12317
0
          url.has_opaque_path = base_url->has_opaque_path;
12318
12319
0
          if constexpr (result_type_is_ada_url) {
12320
0
            url.path = base_url->path;
12321
0
            url.query = base_url->query;
12322
0
          } else {
12323
0
            url.update_base_pathname(base_url->get_pathname());
12324
0
            url.update_base_search(base_url->get_search());
12325
0
          }
12326
0
          url.update_unencoded_base_hash(*fragment);
12327
0
          return url;
12328
0
        }
12329
        // Otherwise, if base's scheme is not "file", set state to relative
12330
        // state and decrease pointer by 1.
12331
0
        else if (base_url->type != ada::scheme::type::FILE) {
12332
0
          ada_log("NO_SCHEME non-file relative path");
12333
0
          state = ada::state::RELATIVE_SCHEME;
12334
0
        }
12335
        // Otherwise, set state to file state and decrease pointer by 1.
12336
0
        else {
12337
0
          ada_log("NO_SCHEME file base type");
12338
0
          state = ada::state::FILE;
12339
0
        }
12340
0
        break;
12341
4.38k
      }
12342
5.88k
      case ada::state::AUTHORITY: {
12343
5.88k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
12344
        // most URLs have no @. Having no @ tells us that we don't have to worry
12345
        // about AUTHORITY. Of course, we could have @ and still not have to
12346
        // worry about AUTHORITY.
12347
        // TODO: Instead of just collecting a bool, collect the location of the
12348
        // '@' and do something useful with it.
12349
        // TODO: We could do various processing early on, using a single pass
12350
        // over the string to collect information about it, e.g., telling us
12351
        // whether there is a @ and if so, where (or how many).
12352
5.88k
        const bool contains_ampersand =
12353
5.88k
            (url_data.find('@', input_position) != std::string_view::npos);
12354
12355
5.88k
        if (!contains_ampersand) {
12356
5.50k
          state = ada::state::HOST;
12357
5.50k
          break;
12358
5.50k
        }
12359
384
        bool at_sign_seen{false};
12360
384
        bool password_token_seen{false};
12361
        /**
12362
         * We expect something of the sort...
12363
         * https://user:pass@example.com:1234/foo/bar?baz#quux
12364
         * --------^
12365
         */
12366
3.18k
        do {
12367
3.18k
          std::string_view view = helpers::substring(url_data, input_position);
12368
          // The delimiters are @, /, ? \\.
12369
3.18k
          size_t location =
12370
3.18k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
12371
3.18k
                               : helpers::find_authority_delimiter(view);
12372
3.18k
          std::string_view authority_view(view.data(), location);
12373
3.18k
          size_t end_of_authority = input_position + authority_view.size();
12374
          // If c is U+0040 (@), then:
12375
3.18k
          if ((end_of_authority != input_size) &&
12376
3.18k
              (url_data[end_of_authority] == '@')) {
12377
            // If atSignSeen is true, then prepend "%40" to buffer.
12378
2.79k
            if (at_sign_seen) {
12379
2.42k
              if (password_token_seen) {
12380
665
                if constexpr (result_type_is_ada_url) {
12381
665
                  url.password += "%40";
12382
665
                } else {
12383
665
                  url.append_base_password("%40");
12384
665
                }
12385
1.75k
              } else {
12386
1.75k
                if constexpr (result_type_is_ada_url) {
12387
1.75k
                  url.username += "%40";
12388
1.75k
                } else {
12389
1.75k
                  url.append_base_username("%40");
12390
1.75k
                }
12391
1.75k
              }
12392
2.42k
            }
12393
12394
2.79k
            at_sign_seen = true;
12395
12396
2.79k
            if (!password_token_seen) {
12397
2.13k
              size_t password_token_location = authority_view.find(':');
12398
2.13k
              password_token_seen =
12399
2.13k
                  password_token_location != std::string_view::npos;
12400
12401
2.13k
              if (!password_token_seen) {
12402
1.99k
                if constexpr (result_type_is_ada_url) {
12403
1.99k
                  url.username += unicode::percent_encode(
12404
1.99k
                      authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12405
1.99k
                } else {
12406
1.99k
                  url.append_base_username(unicode::percent_encode(
12407
1.99k
                      authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12408
1.99k
                }
12409
1.99k
              } else {
12410
139
                if constexpr (result_type_is_ada_url) {
12411
139
                  url.username += unicode::percent_encode(
12412
139
                      authority_view.substr(0, password_token_location),
12413
139
                      character_sets::USERINFO_PERCENT_ENCODE);
12414
139
                  url.password += unicode::percent_encode(
12415
139
                      authority_view.substr(password_token_location + 1),
12416
139
                      character_sets::USERINFO_PERCENT_ENCODE);
12417
139
                } else {
12418
139
                  url.append_base_username(unicode::percent_encode(
12419
139
                      authority_view.substr(0, password_token_location),
12420
139
                      character_sets::USERINFO_PERCENT_ENCODE));
12421
139
                  url.append_base_password(unicode::percent_encode(
12422
139
                      authority_view.substr(password_token_location + 1),
12423
139
                      character_sets::USERINFO_PERCENT_ENCODE));
12424
139
                }
12425
139
              }
12426
2.13k
            } else {
12427
665
              if constexpr (result_type_is_ada_url) {
12428
665
                url.password += unicode::percent_encode(
12429
665
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12430
665
              } else {
12431
665
                url.append_base_password(unicode::percent_encode(
12432
665
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12433
665
              }
12434
665
            }
12435
2.79k
          }
12436
          // Otherwise, if one of the following is true:
12437
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12438
          // - url is special and c is U+005C (\)
12439
384
          else if (end_of_authority == input_size ||
12440
384
                   url_data[end_of_authority] == '/' ||
12441
384
                   url_data[end_of_authority] == '?' ||
12442
384
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
12443
            // If atSignSeen is true and authority_view is the empty string,
12444
            // validation error, return failure.
12445
384
            if (at_sign_seen && authority_view.empty()) {
12446
209
              url.is_valid = false;
12447
209
              return url;
12448
209
            }
12449
175
            state = ada::state::HOST;
12450
175
            break;
12451
384
          }
12452
2.79k
          if (end_of_authority == input_size) {
12453
0
            if (fragment.has_value()) {
12454
0
              url.update_unencoded_base_hash(*fragment);
12455
0
            }
12456
0
            return url;
12457
0
          }
12458
2.79k
          input_position = end_of_authority + 1;
12459
2.79k
        } while (true);
12460
12461
175
        break;
12462
384
      }
12463
175
      case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY: {
12464
0
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
12465
0
                helpers::substring(url_data, input_position));
12466
12467
        // If c is U+002F (/) and remaining starts with U+002F (/),
12468
        // then set state to special authority ignore slashes state and increase
12469
        // pointer by 1.
12470
0
        std::string_view view = helpers::substring(url_data, input_position);
12471
0
        if (ada::checkers::begins_with(view, "//")) {
12472
0
          state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12473
0
          input_position += 2;
12474
0
        } else {
12475
          // Otherwise, validation error, set state to relative state and
12476
          // decrease pointer by 1.
12477
0
          state = ada::state::RELATIVE_SCHEME;
12478
0
        }
12479
12480
0
        break;
12481
384
      }
12482
1.93k
      case ada::state::PATH_OR_AUTHORITY: {
12483
1.93k
        ada_log("PATH_OR_AUTHORITY ",
12484
1.93k
                helpers::substring(url_data, input_position));
12485
12486
        // If c is U+002F (/), then set state to authority state.
12487
1.93k
        if ((input_position != input_size) &&
12488
1.93k
            (url_data[input_position] == '/')) {
12489
438
          state = ada::state::AUTHORITY;
12490
438
          input_position++;
12491
1.50k
        } else {
12492
          // Otherwise, set state to path state, and decrease pointer by 1.
12493
1.50k
          state = ada::state::PATH;
12494
1.50k
        }
12495
12496
1.93k
        break;
12497
384
      }
12498
0
      case ada::state::RELATIVE_SCHEME: {
12499
0
        ada_log("RELATIVE_SCHEME ",
12500
0
                helpers::substring(url_data, input_position));
12501
12502
        // Set url's scheme to base's scheme.
12503
0
        url.copy_scheme(*base_url);
12504
12505
        // If c is U+002F (/), then set state to relative slash state.
12506
0
        if ((input_position != input_size) &&
12507
0
            (url_data[input_position] == '/')) {
12508
0
          ada_log(
12509
0
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
12510
0
              "slash state");
12511
0
          state = ada::state::RELATIVE_SLASH;
12512
0
        } else if (url.is_special() && (input_position != input_size) &&
12513
0
                   (url_data[input_position] == '\\')) {
12514
          // Otherwise, if url is special and c is U+005C (\), validation error,
12515
          // set state to relative slash state.
12516
0
          ada_log(
12517
0
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
12518
0
              "error, set state to relative slash state");
12519
0
          state = ada::state::RELATIVE_SLASH;
12520
0
        } else {
12521
0
          ada_log("RELATIVE_SCHEME otherwise");
12522
          // Set url's username to base's username, url's password to base's
12523
          // password, url's host to base's host, url's port to base's port,
12524
          // url's path to a clone of base's path, and url's query to base's
12525
          // query.
12526
0
          if constexpr (result_type_is_ada_url) {
12527
0
            url.username = base_url->username;
12528
0
            url.password = base_url->password;
12529
0
            url.host = base_url->host;
12530
0
            url.port = base_url->port;
12531
            // cloning the base path includes cloning the has_opaque_path flag
12532
0
            url.has_opaque_path = base_url->has_opaque_path;
12533
0
            url.path = base_url->path;
12534
0
            url.query = base_url->query;
12535
0
          } else {
12536
0
            url.update_base_authority(base_url->get_href(),
12537
0
                                      base_url->get_components());
12538
            // TODO: Get rid of set_hostname and replace it with
12539
            // update_base_hostname
12540
0
            url.set_hostname(base_url->get_hostname());
12541
0
            url.update_base_port(base_url->retrieve_base_port());
12542
            // cloning the base path includes cloning the has_opaque_path flag
12543
0
            url.has_opaque_path = base_url->has_opaque_path;
12544
0
            url.update_base_pathname(base_url->get_pathname());
12545
0
            url.update_base_search(base_url->get_search());
12546
0
          }
12547
12548
0
          url.has_opaque_path = base_url->has_opaque_path;
12549
12550
          // If c is U+003F (?), then set url's query to the empty string, and
12551
          // state to query state.
12552
0
          if ((input_position != input_size) &&
12553
0
              (url_data[input_position] == '?')) {
12554
0
            state = ada::state::QUERY;
12555
0
          }
12556
          // Otherwise, if c is not the EOF code point:
12557
0
          else if (input_position != input_size) {
12558
            // Set url's query to null.
12559
0
            url.clear_search();
12560
0
            if constexpr (result_type_is_ada_url) {
12561
              // Shorten url's path.
12562
0
              helpers::shorten_path(url.path, url.type);
12563
0
            } else {
12564
0
              std::string_view path = url.get_pathname();
12565
0
              if (helpers::shorten_path(path, url.type)) {
12566
0
                url.update_base_pathname(std::string(path));
12567
0
              }
12568
0
            }
12569
            // Set state to path state and decrease pointer by 1.
12570
0
            state = ada::state::PATH;
12571
0
            break;
12572
0
          }
12573
0
        }
12574
0
        input_position++;
12575
0
        break;
12576
0
      }
12577
0
      case ada::state::RELATIVE_SLASH: {
12578
0
        ada_log("RELATIVE_SLASH ",
12579
0
                helpers::substring(url_data, input_position));
12580
12581
        // If url is special and c is U+002F (/) or U+005C (\), then:
12582
0
        if (url.is_special() && (input_position != input_size) &&
12583
0
            (url_data[input_position] == '/' ||
12584
0
             url_data[input_position] == '\\')) {
12585
          // Set state to special authority ignore slashes state.
12586
0
          state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12587
0
        }
12588
        // Otherwise, if c is U+002F (/), then set state to authority state.
12589
0
        else if ((input_position != input_size) &&
12590
0
                 (url_data[input_position] == '/')) {
12591
0
          state = ada::state::AUTHORITY;
12592
0
        }
12593
        // Otherwise, set
12594
        // - url's username to base's username,
12595
        // - url's password to base's password,
12596
        // - url's host to base's host,
12597
        // - url's port to base's port,
12598
        // - state to path state, and then, decrease pointer by 1.
12599
0
        else {
12600
0
          if constexpr (result_type_is_ada_url) {
12601
0
            url.username = base_url->username;
12602
0
            url.password = base_url->password;
12603
0
            url.host = base_url->host;
12604
0
            url.port = base_url->port;
12605
0
          } else {
12606
0
            url.update_base_authority(base_url->get_href(),
12607
0
                                      base_url->get_components());
12608
            // TODO: Get rid of set_hostname and replace it with
12609
            // update_base_hostname
12610
0
            url.set_hostname(base_url->get_hostname());
12611
0
            url.update_base_port(base_url->retrieve_base_port());
12612
0
          }
12613
0
          state = ada::state::PATH;
12614
0
          break;
12615
0
        }
12616
12617
0
        input_position++;
12618
0
        break;
12619
0
      }
12620
5.45k
      case ada::state::SPECIAL_AUTHORITY_SLASHES: {
12621
5.45k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
12622
5.45k
                helpers::substring(url_data, input_position));
12623
12624
        // If c is U+002F (/) and remaining starts with U+002F (/),
12625
        // then set state to special authority ignore slashes state and increase
12626
        // pointer by 1.
12627
5.45k
        std::string_view view = helpers::substring(url_data, input_position);
12628
5.45k
        if (ada::checkers::begins_with(view, "//")) {
12629
11
          input_position += 2;
12630
11
        }
12631
12632
5.45k
        [[fallthrough]];
12633
5.45k
      }
12634
5.45k
      case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
12635
5.45k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
12636
5.45k
                helpers::substring(url_data, input_position));
12637
12638
        // If c is neither U+002F (/) nor U+005C (\), then set state to
12639
        // authority state and decrease pointer by 1.
12640
6.00k
        while ((input_position != input_size) &&
12641
6.00k
               ((url_data[input_position] == '/') ||
12642
5.97k
                (url_data[input_position] == '\\'))) {
12643
555
          input_position++;
12644
555
        }
12645
5.45k
        state = ada::state::AUTHORITY;
12646
12647
5.45k
        break;
12648
5.45k
      }
12649
268
      case ada::state::QUERY: {
12650
268
        ada_log("QUERY ", helpers::substring(url_data, input_position));
12651
        // Let queryPercentEncodeSet be the special-query percent-encode set if
12652
        // url is special; otherwise the query percent-encode set.
12653
268
        const uint8_t* query_percent_encode_set =
12654
268
            url.is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12655
268
                             : ada::character_sets::QUERY_PERCENT_ENCODE;
12656
12657
        // Percent-encode after encoding, with encoding, buffer, and
12658
        // queryPercentEncodeSet, and append the result to url's query.
12659
268
        url.update_base_search(helpers::substring(url_data, input_position),
12660
268
                               query_percent_encode_set);
12661
268
        ada_log("QUERY update_base_search completed ");
12662
268
        if (fragment.has_value()) {
12663
27
          url.update_unencoded_base_hash(*fragment);
12664
27
        }
12665
268
        return url;
12666
5.45k
      }
12667
5.68k
      case ada::state::HOST: {
12668
5.68k
        ada_log("HOST ", helpers::substring(url_data, input_position));
12669
12670
5.68k
        std::string_view host_view =
12671
5.68k
            helpers::substring(url_data, input_position);
12672
5.68k
        auto [location, found_colon] =
12673
5.68k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
12674
5.68k
        input_position = (location != std::string_view::npos)
12675
5.68k
                             ? input_position + location
12676
5.68k
                             : input_size;
12677
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12678
        // Note: the 'found_colon' value is true if and only if a colon was
12679
        // encountered while not inside brackets.
12680
5.68k
        if (found_colon) {
12681
          // If buffer is the empty string, validation error, return failure.
12682
          // Let host be the result of host parsing buffer with url is not
12683
          // special.
12684
804
          ada_log("HOST parsing ", host_view);
12685
804
          if (!url.parse_host(host_view)) {
12686
171
            return url;
12687
171
          }
12688
633
          ada_log("HOST parsing results in ", url.get_hostname());
12689
          // Set url's host to host, buffer to the empty string, and state to
12690
          // port state.
12691
633
          state = ada::state::PORT;
12692
633
          input_position++;
12693
633
        }
12694
        // Otherwise, if one of the following is true:
12695
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12696
        // - url is special and c is U+005C (\)
12697
        // The get_host_delimiter_location function either brings us to
12698
        // the colon outside of the bracket, or to one of those characters.
12699
4.87k
        else {
12700
          // If url is special and host_view is the empty string, validation
12701
          // error, return failure.
12702
4.87k
          if (url.is_special() && host_view.empty()) {
12703
37
            url.is_valid = false;
12704
37
            return url;
12705
37
          }
12706
4.83k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
12707
          // Let host be the result of host parsing host_view with url is not
12708
          // special.
12709
4.83k
          if (host_view.empty()) {
12710
16
            url.update_base_hostname("");
12711
4.82k
          } else if (!url.parse_host(host_view)) {
12712
1.22k
            return url;
12713
1.22k
          }
12714
3.61k
          ada_log("HOST parsing results in ", url.get_hostname(),
12715
3.61k
                  " href=", url.get_href());
12716
12717
          // Set url's host to host, and state to path start state.
12718
3.61k
          state = ada::state::PATH_START;
12719
3.61k
        }
12720
12721
4.24k
        break;
12722
5.68k
      }
12723
4.24k
      case ada::state::OPAQUE_PATH: {
12724
1.04k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
12725
1.04k
        std::string_view view = helpers::substring(url_data, input_position);
12726
        // If c is U+003F (?), then set url's query to the empty string and
12727
        // state to query state.
12728
1.04k
        size_t location = view.find('?');
12729
1.04k
        if (location != std::string_view::npos) {
12730
70
          view.remove_suffix(view.size() - location);
12731
70
          state = ada::state::QUERY;
12732
70
          input_position += location + 1;
12733
977
        } else {
12734
977
          input_position = input_size + 1;
12735
977
        }
12736
1.04k
        url.has_opaque_path = true;
12737
        // This is a really unlikely scenario in real world. We should not seek
12738
        // to optimize it.
12739
1.04k
        url.update_base_pathname(unicode::percent_encode(
12740
1.04k
            view, character_sets::C0_CONTROL_PERCENT_ENCODE));
12741
1.04k
        break;
12742
5.68k
      }
12743
633
      case ada::state::PORT: {
12744
633
        ada_log("PORT ", helpers::substring(url_data, input_position));
12745
633
        std::string_view port_view =
12746
633
            helpers::substring(url_data, input_position);
12747
633
        size_t consumed_bytes = url.parse_port(port_view, true);
12748
633
        input_position += consumed_bytes;
12749
633
        if (!url.is_valid) {
12750
76
          return url;
12751
76
        }
12752
557
        state = state::PATH_START;
12753
557
        [[fallthrough]];
12754
557
      }
12755
4.54k
      case ada::state::PATH_START: {
12756
4.54k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
12757
12758
        // If url is special, then:
12759
4.54k
        if (url.is_special()) {
12760
          // Set state to path state.
12761
4.27k
          state = ada::state::PATH;
12762
12763
          // Optimization: Avoiding going into PATH state improves the
12764
          // performance of urls ending with /.
12765
4.27k
          if (input_position == input_size) {
12766
3.88k
            url.update_base_pathname("/");
12767
3.88k
            if (fragment.has_value()) {
12768
60
              url.update_unencoded_base_hash(*fragment);
12769
60
            }
12770
3.88k
            return url;
12771
3.88k
          }
12772
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
12773
          // by 1. We know that (input_position == input_size) is impossible
12774
          // here, because of the previous if-check.
12775
394
          if ((url_data[input_position] != '/') &&
12776
394
              (url_data[input_position] != '\\')) {
12777
95
            break;
12778
95
          }
12779
394
        }
12780
        // Otherwise, if state override is not given and c is U+003F (?),
12781
        // set url's query to the empty string and state to query state.
12782
265
        else if ((input_position != input_size) &&
12783
265
                 (url_data[input_position] == '?')) {
12784
34
          state = ada::state::QUERY;
12785
34
        }
12786
        // Otherwise, if c is not the EOF code point:
12787
231
        else if (input_position != input_size) {
12788
          // Set state to path state.
12789
15
          state = ada::state::PATH;
12790
12791
          // If c is not U+002F (/), then decrease pointer by 1.
12792
15
          if (url_data[input_position] != '/') {
12793
0
            break;
12794
0
          }
12795
15
        }
12796
12797
564
        input_position++;
12798
564
        break;
12799
4.54k
      }
12800
2.92k
      case ada::state::PATH: {
12801
2.92k
        std::string_view view = helpers::substring(url_data, input_position);
12802
2.92k
        ada_log("PATH ", helpers::substring(url_data, input_position));
12803
12804
        // Most time, we do not need percent encoding.
12805
        // Furthermore, we can immediately locate the '?'.
12806
2.92k
        size_t locofquestionmark = view.find('?');
12807
2.92k
        if (locofquestionmark != std::string_view::npos) {
12808
164
          state = ada::state::QUERY;
12809
164
          view.remove_suffix(view.size() - locofquestionmark);
12810
164
          input_position += locofquestionmark + 1;
12811
2.75k
        } else {
12812
2.75k
          input_position = input_size + 1;
12813
2.75k
        }
12814
2.92k
        if constexpr (result_type_is_ada_url) {
12815
2.92k
          helpers::parse_prepared_path(view, url.type, url.path);
12816
2.92k
        } else {
12817
2.92k
          url.consume_prepared_path(view);
12818
2.92k
          ADA_ASSERT_TRUE(url.validate());
12819
2.92k
        }
12820
2.92k
        break;
12821
4.54k
      }
12822
573
      case ada::state::FILE_SLASH: {
12823
573
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
12824
12825
        // If c is U+002F (/) or U+005C (\), then:
12826
573
        if ((input_position != input_size) &&
12827
573
            (url_data[input_position] == '/' ||
12828
528
             url_data[input_position] == '\\')) {
12829
510
          ada_log("FILE_SLASH c is U+002F or U+005C");
12830
          // Set state to file host state.
12831
510
          state = ada::state::FILE_HOST;
12832
510
          input_position++;
12833
510
        } else {
12834
63
          ada_log("FILE_SLASH otherwise");
12835
          // If base is non-null and base's scheme is "file", then:
12836
          // Note: it is unsafe to do base_url->scheme unless you know that
12837
          // base_url_has_value() is true.
12838
63
          if (base_url != nullptr &&
12839
63
              base_url->type == ada::scheme::type::FILE) {
12840
            // Set url's host to base's host.
12841
0
            if constexpr (result_type_is_ada_url) {
12842
0
              url.host = base_url->host;
12843
0
            } else {
12844
              // TODO: Optimization opportunity.
12845
0
              url.set_host(base_url->get_host());
12846
0
            }
12847
            // If the code point substring from pointer to the end of input does
12848
            // not start with a Windows drive letter and base's path[0] is a
12849
            // normalized Windows drive letter, then append base's path[0] to
12850
            // url's path.
12851
0
            if (!base_url->get_pathname().empty()) {
12852
0
              if (!checkers::is_windows_drive_letter(
12853
0
                      helpers::substring(url_data, input_position))) {
12854
0
                std::string_view first_base_url_path =
12855
0
                    base_url->get_pathname().substr(1);
12856
0
                size_t loc = first_base_url_path.find('/');
12857
0
                if (loc != std::string_view::npos) {
12858
0
                  helpers::resize(first_base_url_path, loc);
12859
0
                }
12860
0
                if (checkers::is_normalized_windows_drive_letter(
12861
0
                        first_base_url_path)) {
12862
0
                  if constexpr (result_type_is_ada_url) {
12863
0
                    url.path += '/';
12864
0
                    url.path += first_base_url_path;
12865
0
                  } else {
12866
0
                    url.append_base_pathname(
12867
0
                        helpers::concat("/", first_base_url_path));
12868
0
                  }
12869
0
                }
12870
0
              }
12871
0
            }
12872
0
          }
12873
12874
          // Set state to path state, and decrease pointer by 1.
12875
63
          state = ada::state::PATH;
12876
63
        }
12877
12878
573
        break;
12879
4.54k
      }
12880
510
      case ada::state::FILE_HOST: {
12881
510
        std::string_view view = helpers::substring(url_data, input_position);
12882
510
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
12883
12884
510
        size_t location = view.find_first_of("/\\?");
12885
510
        std::string_view file_host_buffer(
12886
510
            view.data(),
12887
510
            (location != std::string_view::npos) ? location : view.size());
12888
12889
510
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
12890
6
          state = ada::state::PATH;
12891
504
        } else if (file_host_buffer.empty()) {
12892
          // Set url's host to the empty string.
12893
12
          if constexpr (result_type_is_ada_url) {
12894
12
            url.host = "";
12895
12
          } else {
12896
12
            url.update_base_hostname("");
12897
12
          }
12898
          // Set state to path start state.
12899
12
          state = ada::state::PATH_START;
12900
492
        } else {
12901
492
          size_t consumed_bytes = file_host_buffer.size();
12902
492
          input_position += consumed_bytes;
12903
          // Let host be the result of host parsing buffer with url is not
12904
          // special.
12905
492
          if (!url.parse_host(file_host_buffer)) {
12906
127
            return url;
12907
127
          }
12908
12909
365
          if constexpr (result_type_is_ada_url) {
12910
            // If host is "localhost", then set host to the empty string.
12911
365
            if (url.host.has_value() && url.host.value() == "localhost") {
12912
3
              url.host = "";
12913
3
            }
12914
365
          } else {
12915
365
            if (url.get_hostname() == "localhost") {
12916
365
              url.update_base_hostname("");
12917
365
            }
12918
365
          }
12919
12920
          // Set buffer to the empty string and state to path start state.
12921
365
          state = ada::state::PATH_START;
12922
365
        }
12923
12924
383
        break;
12925
510
      }
12926
1.51k
      case ada::state::FILE: {
12927
1.51k
        ada_log("FILE ", helpers::substring(url_data, input_position));
12928
1.51k
        std::string_view file_view =
12929
1.51k
            helpers::substring(url_data, input_position);
12930
12931
1.51k
        url.set_protocol_as_file();
12932
1.51k
        if constexpr (result_type_is_ada_url) {
12933
          // Set url's host to the empty string.
12934
1.51k
          url.host = "";
12935
1.51k
        } else {
12936
1.51k
          url.update_base_hostname("");
12937
1.51k
        }
12938
        // If c is U+002F (/) or U+005C (\), then:
12939
1.51k
        if (input_position != input_size &&
12940
1.51k
            (url_data[input_position] == '/' ||
12941
899
             url_data[input_position] == '\\')) {
12942
573
          ada_log("FILE c is U+002F or U+005C");
12943
          // Set state to file slash state.
12944
573
          state = ada::state::FILE_SLASH;
12945
573
        }
12946
        // Otherwise, if base is non-null and base's scheme is "file":
12947
943
        else if (base_url != nullptr &&
12948
943
                 base_url->type == ada::scheme::type::FILE) {
12949
          // Set url's host to base's host, url's path to a clone of base's
12950
          // path, and url's query to base's query.
12951
0
          ada_log("FILE base non-null");
12952
0
          if constexpr (result_type_is_ada_url) {
12953
0
            url.host = base_url->host;
12954
0
            url.path = base_url->path;
12955
0
            url.query = base_url->query;
12956
0
          } else {
12957
            // TODO: Get rid of set_hostname and replace it with
12958
            // update_base_hostname
12959
0
            url.set_hostname(base_url->get_hostname());
12960
0
            url.update_base_pathname(base_url->get_pathname());
12961
0
            url.update_base_search(base_url->get_search());
12962
0
          }
12963
0
          url.has_opaque_path = base_url->has_opaque_path;
12964
12965
          // If c is U+003F (?), then set url's query to the empty string and
12966
          // state to query state.
12967
0
          if (input_position != input_size && url_data[input_position] == '?') {
12968
0
            state = ada::state::QUERY;
12969
0
          }
12970
          // Otherwise, if c is not the EOF code point:
12971
0
          else if (input_position != input_size) {
12972
            // Set url's query to null.
12973
0
            url.clear_search();
12974
            // If the code point substring from pointer to the end of input does
12975
            // not start with a Windows drive letter, then shorten url's path.
12976
0
            if (!checkers::is_windows_drive_letter(file_view)) {
12977
0
              if constexpr (result_type_is_ada_url) {
12978
0
                helpers::shorten_path(url.path, url.type);
12979
0
              } else {
12980
0
                std::string_view path = url.get_pathname();
12981
0
                if (helpers::shorten_path(path, url.type)) {
12982
0
                  url.update_base_pathname(std::string(path));
12983
0
                }
12984
0
              }
12985
0
            }
12986
            // Otherwise:
12987
0
            else {
12988
              // Set url's path to an empty list.
12989
0
              url.clear_pathname();
12990
0
              url.has_opaque_path = true;
12991
0
            }
12992
12993
            // Set state to path state and decrease pointer by 1.
12994
0
            state = ada::state::PATH;
12995
0
            break;
12996
0
          }
12997
0
        }
12998
        // Otherwise, set state to path state, and decrease pointer by 1.
12999
943
        else {
13000
943
          ada_log("FILE go to path");
13001
943
          state = ada::state::PATH;
13002
943
          break;
13003
943
        }
13004
13005
573
        input_position++;
13006
573
        break;
13007
1.51k
      }
13008
0
      default:
13009
0
        ada::unreachable();
13010
60.0k
    }
13011
60.0k
  }
13012
3.95k
  if (fragment.has_value()) {
13013
173
    url.update_unencoded_base_hash(*fragment);
13014
173
  }
13015
3.95k
  return url;
13016
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
12124
44.8k
                      const result_type* base_url) {
12125
  // We can specialize the implementation per type.
12126
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
12127
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
12128
  // something else } is free (at runtime). This means that ada::url_aggregator
12129
  // and ada::url **do not have to support the exact same API**.
12130
44.8k
  constexpr bool result_type_is_ada_url =
12131
44.8k
      std::is_same<ada::url, result_type>::value;
12132
44.8k
  constexpr bool result_type_is_ada_url_aggregator =
12133
44.8k
      std::is_same<ada::url_aggregator, result_type>::value;
12134
44.8k
  static_assert(result_type_is_ada_url ||
12135
44.8k
                result_type_is_ada_url_aggregator);  // We don't support
12136
                                                     // anything else for now.
12137
12138
44.8k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
12139
44.8k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
12140
44.8k
          ")");
12141
12142
44.8k
  ada::state state = ada::state::SCHEME_START;
12143
44.8k
  result_type url{};
12144
12145
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
12146
  // surely the result of a bug or are otherwise a security concern.
12147
44.8k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) {
12148
2
    url.is_valid = false;
12149
2
  }
12150
  // Going forward, user_input.size() is in [0,
12151
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
12152
  // base, or the optional_url was invalid, we must return.
12153
44.8k
  if (base_url != nullptr) {
12154
2.61k
    url.is_valid &= base_url->is_valid;
12155
2.61k
  }
12156
44.8k
  if (!url.is_valid) {
12157
2
    return url;
12158
2
  }
12159
44.8k
  if constexpr (result_type_is_ada_url_aggregator) {
12160
    // Most of the time, we just need user_input.size().
12161
    // In some instances, we may need a bit more.
12162
    ///////////////////////////
12163
    // This is *very* important. This line should *not* be removed
12164
    // hastily. There are principled reasons why reserve is important
12165
    // for performance. If you have a benchmark with small inputs,
12166
    // it may not matter, but in other instances, it could.
12167
    ////
12168
    // This rounds up to the next power of two.
12169
    // We know that user_input.size() is in [0,
12170
    // std::numeric_limits<uint32_t>::max).
12171
44.8k
    uint32_t reserve_capacity =
12172
44.8k
        (0xFFFFFFFF >>
12173
44.8k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
12174
44.8k
        1;
12175
44.8k
    url.reserve(reserve_capacity);
12176
    //
12177
    //
12178
    //
12179
44.8k
  }
12180
44.8k
  std::string tmp_buffer;
12181
44.8k
  std::string_view internal_input;
12182
44.8k
  if (unicode::has_tabs_or_newline(user_input)) {
12183
494
    tmp_buffer = user_input;
12184
    // Optimization opportunity: Instead of copying and then pruning, we could
12185
    // just directly build the string from user_input.
12186
494
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12187
494
    internal_input = tmp_buffer;
12188
44.3k
  } else {
12189
44.3k
    internal_input = user_input;
12190
44.3k
  }
12191
12192
  // Leading and trailing control characters are uncommon and easy to deal with
12193
  // (no performance concern).
12194
44.8k
  std::string_view url_data = internal_input;
12195
44.8k
  helpers::trim_c0_whitespace(url_data);
12196
12197
  // Optimization opportunity. Most websites do not have fragment.
12198
44.8k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
12199
  // We add it last so that an implementation like ada::url_aggregator
12200
  // can append it last to its internal buffer, thus improving performance.
12201
12202
  // Here url_data no longer has its fragment.
12203
  // We are going to access the data from url_data (it is immutable).
12204
  // At any given time, we are pointing at byte 'input_position' in url_data.
12205
  // The input_position variable should range from 0 to input_size.
12206
  // It is illegal to access url_data at input_size.
12207
44.8k
  size_t input_position = 0;
12208
44.8k
  const size_t input_size = url_data.size();
12209
  // Keep running the following state machine by switching on state.
12210
  // If after a run pointer points to the EOF code point, go to the next step.
12211
  // Otherwise, increase pointer by 1 and continue with the state machine.
12212
  // We never decrement input_position.
12213
175k
  while (input_position <= input_size) {
12214
164k
    ada_log("In parsing at ", input_position, " out of ", input_size,
12215
164k
            " in state ", ada::to_string(state));
12216
164k
    switch (state) {
12217
44.8k
      case ada::state::SCHEME_START: {
12218
44.8k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
12219
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
12220
        // state to scheme state.
12221
44.8k
        if ((input_position != input_size) &&
12222
44.8k
            checkers::is_alpha(url_data[input_position])) {
12223
25.8k
          state = ada::state::SCHEME;
12224
25.8k
          input_position++;
12225
25.8k
        } else {
12226
          // Otherwise, if state override is not given, set state to no scheme
12227
          // state and decrease pointer by 1.
12228
18.9k
          state = ada::state::NO_SCHEME;
12229
18.9k
        }
12230
44.8k
        break;
12231
0
      }
12232
25.8k
      case ada::state::SCHEME: {
12233
25.8k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
12234
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
12235
        // append c, lowercased, to buffer.
12236
80.7k
        while ((input_position != input_size) &&
12237
80.7k
               (ada::unicode::is_alnum_plus(url_data[input_position]))) {
12238
54.8k
          input_position++;
12239
54.8k
        }
12240
        // Otherwise, if c is U+003A (:), then:
12241
25.8k
        if ((input_position != input_size) &&
12242
25.8k
            (url_data[input_position] == ':')) {
12243
23.6k
          ada_log("SCHEME the scheme should be ",
12244
23.6k
                  url_data.substr(0, input_position));
12245
23.6k
          if constexpr (result_type_is_ada_url) {
12246
23.6k
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
12247
23.6k
              return url;
12248
23.6k
            }
12249
23.6k
          } else {
12250
            // we pass the colon along instead of painfully adding it back.
12251
23.6k
            if (!url.parse_scheme_with_colon(
12252
23.6k
                    url_data.substr(0, input_position + 1))) {
12253
0
              return url;
12254
0
            }
12255
23.6k
          }
12256
23.6k
          ada_log("SCHEME the scheme is ", url.get_protocol());
12257
12258
          // If url's scheme is "file", then:
12259
23.6k
          if (url.type == ada::scheme::type::FILE) {
12260
            // Set state to file state.
12261
3.89k
            state = ada::state::FILE;
12262
3.89k
          }
12263
          // Otherwise, if url is special, base is non-null, and base's scheme
12264
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
12265
          // != nullptr is false.
12266
19.8k
          else if (url.is_special() && base_url != nullptr &&
12267
19.8k
                   base_url->type == url.type) {
12268
            // Set state to special relative or authority state.
12269
94
            state = ada::state::SPECIAL_RELATIVE_OR_AUTHORITY;
12270
94
          }
12271
          // Otherwise, if url is special, set state to special authority
12272
          // slashes state.
12273
19.7k
          else if (url.is_special()) {
12274
12.3k
            state = ada::state::SPECIAL_AUTHORITY_SLASHES;
12275
12.3k
          }
12276
          // Otherwise, if remaining starts with an U+002F (/), set state to
12277
          // path or authority state and increase pointer by 1.
12278
7.38k
          else if (input_position + 1 < input_size &&
12279
7.38k
                   url_data[input_position + 1] == '/') {
12280
4.10k
            state = ada::state::PATH_OR_AUTHORITY;
12281
4.10k
            input_position++;
12282
4.10k
          }
12283
          // Otherwise, set url's path to the empty string and set state to
12284
          // opaque path state.
12285
3.27k
          else {
12286
3.27k
            state = ada::state::OPAQUE_PATH;
12287
3.27k
          }
12288
23.6k
        }
12289
        // Otherwise, if state override is not given, set buffer to the empty
12290
        // string, state to no scheme state, and start over (from the first code
12291
        // point in input).
12292
2.13k
        else {
12293
2.13k
          state = ada::state::NO_SCHEME;
12294
2.13k
          input_position = 0;
12295
2.13k
          break;
12296
2.13k
        }
12297
23.6k
        input_position++;
12298
23.6k
        break;
12299
25.8k
      }
12300
21.1k
      case ada::state::NO_SCHEME: {
12301
21.1k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
12302
        // If base is null, or base has an opaque path and c is not U+0023 (#),
12303
        // validation error, return failure.
12304
21.1k
        if (base_url == nullptr ||
12305
21.1k
            (base_url->has_opaque_path && !fragment.has_value())) {
12306
19.9k
          ada_log("NO_SCHEME validation error");
12307
19.9k
          url.is_valid = false;
12308
19.9k
          return url;
12309
19.9k
        }
12310
        // Otherwise, if base has an opaque path and c is U+0023 (#),
12311
        // set url's scheme to base's scheme, url's path to base's path, url's
12312
        // query to base's query, and set state to fragment state.
12313
1.16k
        else if (base_url->has_opaque_path && fragment.has_value() &&
12314
1.16k
                 input_position == input_size) {
12315
30
          ada_log("NO_SCHEME opaque base with fragment");
12316
30
          url.copy_scheme(*base_url);
12317
30
          url.has_opaque_path = base_url->has_opaque_path;
12318
12319
30
          if constexpr (result_type_is_ada_url) {
12320
30
            url.path = base_url->path;
12321
30
            url.query = base_url->query;
12322
30
          } else {
12323
30
            url.update_base_pathname(base_url->get_pathname());
12324
30
            url.update_base_search(base_url->get_search());
12325
30
          }
12326
30
          url.update_unencoded_base_hash(*fragment);
12327
30
          return url;
12328
30
        }
12329
        // Otherwise, if base's scheme is not "file", set state to relative
12330
        // state and decrease pointer by 1.
12331
1.13k
        else if (base_url->type != ada::scheme::type::FILE) {
12332
655
          ada_log("NO_SCHEME non-file relative path");
12333
655
          state = ada::state::RELATIVE_SCHEME;
12334
655
        }
12335
        // Otherwise, set state to file state and decrease pointer by 1.
12336
477
        else {
12337
477
          ada_log("NO_SCHEME file base type");
12338
477
          state = ada::state::FILE;
12339
477
        }
12340
1.13k
        break;
12341
21.1k
      }
12342
13.2k
      case ada::state::AUTHORITY: {
12343
13.2k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
12344
        // most URLs have no @. Having no @ tells us that we don't have to worry
12345
        // about AUTHORITY. Of course, we could have @ and still not have to
12346
        // worry about AUTHORITY.
12347
        // TODO: Instead of just collecting a bool, collect the location of the
12348
        // '@' and do something useful with it.
12349
        // TODO: We could do various processing early on, using a single pass
12350
        // over the string to collect information about it, e.g., telling us
12351
        // whether there is a @ and if so, where (or how many).
12352
13.2k
        const bool contains_ampersand =
12353
13.2k
            (url_data.find('@', input_position) != std::string_view::npos);
12354
12355
13.2k
        if (!contains_ampersand) {
12356
12.3k
          state = ada::state::HOST;
12357
12.3k
          break;
12358
12.3k
        }
12359
897
        bool at_sign_seen{false};
12360
897
        bool password_token_seen{false};
12361
        /**
12362
         * We expect something of the sort...
12363
         * https://user:pass@example.com:1234/foo/bar?baz#quux
12364
         * --------^
12365
         */
12366
7.53k
        do {
12367
7.53k
          std::string_view view = helpers::substring(url_data, input_position);
12368
          // The delimiters are @, /, ? \\.
12369
7.53k
          size_t location =
12370
7.53k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
12371
7.53k
                               : helpers::find_authority_delimiter(view);
12372
7.53k
          std::string_view authority_view(view.data(), location);
12373
7.53k
          size_t end_of_authority = input_position + authority_view.size();
12374
          // If c is U+0040 (@), then:
12375
7.53k
          if ((end_of_authority != input_size) &&
12376
7.53k
              (url_data[end_of_authority] == '@')) {
12377
            // If atSignSeen is true, then prepend "%40" to buffer.
12378
6.63k
            if (at_sign_seen) {
12379
5.76k
              if (password_token_seen) {
12380
1.61k
                if constexpr (result_type_is_ada_url) {
12381
1.61k
                  url.password += "%40";
12382
1.61k
                } else {
12383
1.61k
                  url.append_base_password("%40");
12384
1.61k
                }
12385
4.14k
              } else {
12386
4.14k
                if constexpr (result_type_is_ada_url) {
12387
4.14k
                  url.username += "%40";
12388
4.14k
                } else {
12389
4.14k
                  url.append_base_username("%40");
12390
4.14k
                }
12391
4.14k
              }
12392
5.76k
            }
12393
12394
6.63k
            at_sign_seen = true;
12395
12396
6.63k
            if (!password_token_seen) {
12397
5.01k
              size_t password_token_location = authority_view.find(':');
12398
5.01k
              password_token_seen =
12399
5.01k
                  password_token_location != std::string_view::npos;
12400
12401
5.01k
              if (!password_token_seen) {
12402
4.68k
                if constexpr (result_type_is_ada_url) {
12403
4.68k
                  url.username += unicode::percent_encode(
12404
4.68k
                      authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12405
4.68k
                } else {
12406
4.68k
                  url.append_base_username(unicode::percent_encode(
12407
4.68k
                      authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12408
4.68k
                }
12409
4.68k
              } else {
12410
332
                if constexpr (result_type_is_ada_url) {
12411
332
                  url.username += unicode::percent_encode(
12412
332
                      authority_view.substr(0, password_token_location),
12413
332
                      character_sets::USERINFO_PERCENT_ENCODE);
12414
332
                  url.password += unicode::percent_encode(
12415
332
                      authority_view.substr(password_token_location + 1),
12416
332
                      character_sets::USERINFO_PERCENT_ENCODE);
12417
332
                } else {
12418
332
                  url.append_base_username(unicode::percent_encode(
12419
332
                      authority_view.substr(0, password_token_location),
12420
332
                      character_sets::USERINFO_PERCENT_ENCODE));
12421
332
                  url.append_base_password(unicode::percent_encode(
12422
332
                      authority_view.substr(password_token_location + 1),
12423
332
                      character_sets::USERINFO_PERCENT_ENCODE));
12424
332
                }
12425
332
              }
12426
5.01k
            } else {
12427
1.61k
              if constexpr (result_type_is_ada_url) {
12428
1.61k
                url.password += unicode::percent_encode(
12429
1.61k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12430
1.61k
              } else {
12431
1.61k
                url.append_base_password(unicode::percent_encode(
12432
1.61k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12433
1.61k
              }
12434
1.61k
            }
12435
6.63k
          }
12436
          // Otherwise, if one of the following is true:
12437
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12438
          // - url is special and c is U+005C (\)
12439
897
          else if (end_of_authority == input_size ||
12440
897
                   url_data[end_of_authority] == '/' ||
12441
897
                   url_data[end_of_authority] == '?' ||
12442
897
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
12443
            // If atSignSeen is true and authority_view is the empty string,
12444
            // validation error, return failure.
12445
897
            if (at_sign_seen && authority_view.empty()) {
12446
469
              url.is_valid = false;
12447
469
              return url;
12448
469
            }
12449
428
            state = ada::state::HOST;
12450
428
            break;
12451
897
          }
12452
6.63k
          if (end_of_authority == input_size) {
12453
0
            if (fragment.has_value()) {
12454
0
              url.update_unencoded_base_hash(*fragment);
12455
0
            }
12456
0
            return url;
12457
0
          }
12458
6.63k
          input_position = end_of_authority + 1;
12459
6.63k
        } while (true);
12460
12461
428
        break;
12462
897
      }
12463
428
      case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY: {
12464
94
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
12465
94
                helpers::substring(url_data, input_position));
12466
12467
        // If c is U+002F (/) and remaining starts with U+002F (/),
12468
        // then set state to special authority ignore slashes state and increase
12469
        // pointer by 1.
12470
94
        std::string_view view = helpers::substring(url_data, input_position);
12471
94
        if (ada::checkers::begins_with(view, "//")) {
12472
1
          state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12473
1
          input_position += 2;
12474
93
        } else {
12475
          // Otherwise, validation error, set state to relative state and
12476
          // decrease pointer by 1.
12477
93
          state = ada::state::RELATIVE_SCHEME;
12478
93
        }
12479
12480
94
        break;
12481
897
      }
12482
4.10k
      case ada::state::PATH_OR_AUTHORITY: {
12483
4.10k
        ada_log("PATH_OR_AUTHORITY ",
12484
4.10k
                helpers::substring(url_data, input_position));
12485
12486
        // If c is U+002F (/), then set state to authority state.
12487
4.10k
        if ((input_position != input_size) &&
12488
4.10k
            (url_data[input_position] == '/')) {
12489
946
          state = ada::state::AUTHORITY;
12490
946
          input_position++;
12491
3.15k
        } else {
12492
          // Otherwise, set state to path state, and decrease pointer by 1.
12493
3.15k
          state = ada::state::PATH;
12494
3.15k
        }
12495
12496
4.10k
        break;
12497
897
      }
12498
748
      case ada::state::RELATIVE_SCHEME: {
12499
748
        ada_log("RELATIVE_SCHEME ",
12500
748
                helpers::substring(url_data, input_position));
12501
12502
        // Set url's scheme to base's scheme.
12503
748
        url.copy_scheme(*base_url);
12504
12505
        // If c is U+002F (/), then set state to relative slash state.
12506
748
        if ((input_position != input_size) &&
12507
748
            (url_data[input_position] == '/')) {
12508
41
          ada_log(
12509
41
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
12510
41
              "slash state");
12511
41
          state = ada::state::RELATIVE_SLASH;
12512
707
        } else if (url.is_special() && (input_position != input_size) &&
12513
707
                   (url_data[input_position] == '\\')) {
12514
          // Otherwise, if url is special and c is U+005C (\), validation error,
12515
          // set state to relative slash state.
12516
1
          ada_log(
12517
1
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
12518
1
              "error, set state to relative slash state");
12519
1
          state = ada::state::RELATIVE_SLASH;
12520
706
        } else {
12521
706
          ada_log("RELATIVE_SCHEME otherwise");
12522
          // Set url's username to base's username, url's password to base's
12523
          // password, url's host to base's host, url's port to base's port,
12524
          // url's path to a clone of base's path, and url's query to base's
12525
          // query.
12526
706
          if constexpr (result_type_is_ada_url) {
12527
706
            url.username = base_url->username;
12528
706
            url.password = base_url->password;
12529
706
            url.host = base_url->host;
12530
706
            url.port = base_url->port;
12531
            // cloning the base path includes cloning the has_opaque_path flag
12532
706
            url.has_opaque_path = base_url->has_opaque_path;
12533
706
            url.path = base_url->path;
12534
706
            url.query = base_url->query;
12535
706
          } else {
12536
706
            url.update_base_authority(base_url->get_href(),
12537
706
                                      base_url->get_components());
12538
            // TODO: Get rid of set_hostname and replace it with
12539
            // update_base_hostname
12540
706
            url.set_hostname(base_url->get_hostname());
12541
706
            url.update_base_port(base_url->retrieve_base_port());
12542
            // cloning the base path includes cloning the has_opaque_path flag
12543
706
            url.has_opaque_path = base_url->has_opaque_path;
12544
706
            url.update_base_pathname(base_url->get_pathname());
12545
706
            url.update_base_search(base_url->get_search());
12546
706
          }
12547
12548
706
          url.has_opaque_path = base_url->has_opaque_path;
12549
12550
          // If c is U+003F (?), then set url's query to the empty string, and
12551
          // state to query state.
12552
706
          if ((input_position != input_size) &&
12553
706
              (url_data[input_position] == '?')) {
12554
5
            state = ada::state::QUERY;
12555
5
          }
12556
          // Otherwise, if c is not the EOF code point:
12557
701
          else if (input_position != input_size) {
12558
            // Set url's query to null.
12559
209
            url.clear_search();
12560
209
            if constexpr (result_type_is_ada_url) {
12561
              // Shorten url's path.
12562
209
              helpers::shorten_path(url.path, url.type);
12563
209
            } else {
12564
209
              std::string_view path = url.get_pathname();
12565
209
              if (helpers::shorten_path(path, url.type)) {
12566
172
                url.update_base_pathname(std::string(path));
12567
172
              }
12568
209
            }
12569
            // Set state to path state and decrease pointer by 1.
12570
209
            state = ada::state::PATH;
12571
209
            break;
12572
209
          }
12573
706
        }
12574
539
        input_position++;
12575
539
        break;
12576
748
      }
12577
42
      case ada::state::RELATIVE_SLASH: {
12578
42
        ada_log("RELATIVE_SLASH ",
12579
42
                helpers::substring(url_data, input_position));
12580
12581
        // If url is special and c is U+002F (/) or U+005C (\), then:
12582
42
        if (url.is_special() && (input_position != input_size) &&
12583
42
            (url_data[input_position] == '/' ||
12584
13
             url_data[input_position] == '\\')) {
12585
          // Set state to special authority ignore slashes state.
12586
2
          state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12587
2
        }
12588
        // Otherwise, if c is U+002F (/), then set state to authority state.
12589
40
        else if ((input_position != input_size) &&
12590
40
                 (url_data[input_position] == '/')) {
12591
6
          state = ada::state::AUTHORITY;
12592
6
        }
12593
        // Otherwise, set
12594
        // - url's username to base's username,
12595
        // - url's password to base's password,
12596
        // - url's host to base's host,
12597
        // - url's port to base's port,
12598
        // - state to path state, and then, decrease pointer by 1.
12599
34
        else {
12600
34
          if constexpr (result_type_is_ada_url) {
12601
34
            url.username = base_url->username;
12602
34
            url.password = base_url->password;
12603
34
            url.host = base_url->host;
12604
34
            url.port = base_url->port;
12605
34
          } else {
12606
34
            url.update_base_authority(base_url->get_href(),
12607
34
                                      base_url->get_components());
12608
            // TODO: Get rid of set_hostname and replace it with
12609
            // update_base_hostname
12610
34
            url.set_hostname(base_url->get_hostname());
12611
34
            url.update_base_port(base_url->retrieve_base_port());
12612
34
          }
12613
34
          state = ada::state::PATH;
12614
34
          break;
12615
34
        }
12616
12617
8
        input_position++;
12618
8
        break;
12619
42
      }
12620
12.3k
      case ada::state::SPECIAL_AUTHORITY_SLASHES: {
12621
12.3k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
12622
12.3k
                helpers::substring(url_data, input_position));
12623
12624
        // If c is U+002F (/) and remaining starts with U+002F (/),
12625
        // then set state to special authority ignore slashes state and increase
12626
        // pointer by 1.
12627
12.3k
        std::string_view view = helpers::substring(url_data, input_position);
12628
12.3k
        if (ada::checkers::begins_with(view, "//")) {
12629
28
          input_position += 2;
12630
28
        }
12631
12632
12.3k
        [[fallthrough]];
12633
12.3k
      }
12634
12.3k
      case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
12635
12.3k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
12636
12.3k
                helpers::substring(url_data, input_position));
12637
12638
        // If c is neither U+002F (/) nor U+005C (\), then set state to
12639
        // authority state and decrease pointer by 1.
12640
13.5k
        while ((input_position != input_size) &&
12641
13.5k
               ((url_data[input_position] == '/') ||
12642
13.4k
                (url_data[input_position] == '\\'))) {
12643
1.22k
          input_position++;
12644
1.22k
        }
12645
12.3k
        state = ada::state::AUTHORITY;
12646
12647
12.3k
        break;
12648
12.3k
      }
12649
687
      case ada::state::QUERY: {
12650
687
        ada_log("QUERY ", helpers::substring(url_data, input_position));
12651
        // Let queryPercentEncodeSet be the special-query percent-encode set if
12652
        // url is special; otherwise the query percent-encode set.
12653
687
        const uint8_t* query_percent_encode_set =
12654
687
            url.is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12655
687
                             : ada::character_sets::QUERY_PERCENT_ENCODE;
12656
12657
        // Percent-encode after encoding, with encoding, buffer, and
12658
        // queryPercentEncodeSet, and append the result to url's query.
12659
687
        url.update_base_search(helpers::substring(url_data, input_position),
12660
687
                               query_percent_encode_set);
12661
687
        ada_log("QUERY update_base_search completed ");
12662
687
        if (fragment.has_value()) {
12663
83
          url.update_unencoded_base_hash(*fragment);
12664
83
        }
12665
687
        return url;
12666
12.3k
      }
12667
12.8k
      case ada::state::HOST: {
12668
12.8k
        ada_log("HOST ", helpers::substring(url_data, input_position));
12669
12670
12.8k
        std::string_view host_view =
12671
12.8k
            helpers::substring(url_data, input_position);
12672
12.8k
        auto [location, found_colon] =
12673
12.8k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
12674
12.8k
        input_position = (location != std::string_view::npos)
12675
12.8k
                             ? input_position + location
12676
12.8k
                             : input_size;
12677
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12678
        // Note: the 'found_colon' value is true if and only if a colon was
12679
        // encountered while not inside brackets.
12680
12.8k
        if (found_colon) {
12681
          // If buffer is the empty string, validation error, return failure.
12682
          // Let host be the result of host parsing buffer with url is not
12683
          // special.
12684
1.83k
          ada_log("HOST parsing ", host_view);
12685
1.83k
          if (!url.parse_host(host_view)) {
12686
364
            return url;
12687
364
          }
12688
1.46k
          ada_log("HOST parsing results in ", url.get_hostname());
12689
          // Set url's host to host, buffer to the empty string, and state to
12690
          // port state.
12691
1.46k
          state = ada::state::PORT;
12692
1.46k
          input_position++;
12693
1.46k
        }
12694
        // Otherwise, if one of the following is true:
12695
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12696
        // - url is special and c is U+005C (\)
12697
        // The get_host_delimiter_location function either brings us to
12698
        // the colon outside of the bracket, or to one of those characters.
12699
10.9k
        else {
12700
          // If url is special and host_view is the empty string, validation
12701
          // error, return failure.
12702
10.9k
          if (url.is_special() && host_view.empty()) {
12703
94
            url.is_valid = false;
12704
94
            return url;
12705
94
          }
12706
10.8k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
12707
          // Let host be the result of host parsing host_view with url is not
12708
          // special.
12709
10.8k
          if (host_view.empty()) {
12710
49
            url.update_base_hostname("");
12711
10.8k
          } else if (!url.parse_host(host_view)) {
12712
2.66k
            return url;
12713
2.66k
          }
12714
8.22k
          ada_log("HOST parsing results in ", url.get_hostname(),
12715
8.22k
                  " href=", url.get_href());
12716
12717
          // Set url's host to host, and state to path start state.
12718
8.22k
          state = ada::state::PATH_START;
12719
8.22k
        }
12720
12721
9.69k
        break;
12722
12.8k
      }
12723
9.69k
      case ada::state::OPAQUE_PATH: {
12724
3.27k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
12725
3.27k
        std::string_view view = helpers::substring(url_data, input_position);
12726
        // If c is U+003F (?), then set url's query to the empty string and
12727
        // state to query state.
12728
3.27k
        size_t location = view.find('?');
12729
3.27k
        if (location != std::string_view::npos) {
12730
188
          view.remove_suffix(view.size() - location);
12731
188
          state = ada::state::QUERY;
12732
188
          input_position += location + 1;
12733
3.09k
        } else {
12734
3.09k
          input_position = input_size + 1;
12735
3.09k
        }
12736
3.27k
        url.has_opaque_path = true;
12737
        // This is a really unlikely scenario in real world. We should not seek
12738
        // to optimize it.
12739
3.27k
        url.update_base_pathname(unicode::percent_encode(
12740
3.27k
            view, character_sets::C0_CONTROL_PERCENT_ENCODE));
12741
3.27k
        break;
12742
12.8k
      }
12743
1.46k
      case ada::state::PORT: {
12744
1.46k
        ada_log("PORT ", helpers::substring(url_data, input_position));
12745
1.46k
        std::string_view port_view =
12746
1.46k
            helpers::substring(url_data, input_position);
12747
1.46k
        size_t consumed_bytes = url.parse_port(port_view, true);
12748
1.46k
        input_position += consumed_bytes;
12749
1.46k
        if (!url.is_valid) {
12750
151
          return url;
12751
151
        }
12752
1.31k
        state = state::PATH_START;
12753
1.31k
        [[fallthrough]];
12754
1.31k
      }
12755
10.8k
      case ada::state::PATH_START: {
12756
10.8k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
12757
12758
        // If url is special, then:
12759
10.8k
        if (url.is_special()) {
12760
          // Set state to path state.
12761
10.2k
          state = ada::state::PATH;
12762
12763
          // Optimization: Avoiding going into PATH state improves the
12764
          // performance of urls ending with /.
12765
10.2k
          if (input_position == input_size) {
12766
9.25k
            url.update_base_pathname("/");
12767
9.25k
            if (fragment.has_value()) {
12768
135
              url.update_unencoded_base_hash(*fragment);
12769
135
            }
12770
9.25k
            return url;
12771
9.25k
          }
12772
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
12773
          // by 1. We know that (input_position == input_size) is impossible
12774
          // here, because of the previous if-check.
12775
949
          if ((url_data[input_position] != '/') &&
12776
949
              (url_data[input_position] != '\\')) {
12777
226
            break;
12778
226
          }
12779
949
        }
12780
        // Otherwise, if state override is not given and c is U+003F (?),
12781
        // set url's query to the empty string and state to query state.
12782
614
        else if ((input_position != input_size) &&
12783
614
                 (url_data[input_position] == '?')) {
12784
74
          state = ada::state::QUERY;
12785
74
        }
12786
        // Otherwise, if c is not the EOF code point:
12787
540
        else if (input_position != input_size) {
12788
          // Set state to path state.
12789
39
          state = ada::state::PATH;
12790
12791
          // If c is not U+002F (/), then decrease pointer by 1.
12792
39
          if (url_data[input_position] != '/') {
12793
0
            break;
12794
0
          }
12795
39
        }
12796
12797
1.33k
        input_position++;
12798
1.33k
        break;
12799
10.8k
      }
12800
6.97k
      case ada::state::PATH: {
12801
6.97k
        std::string_view view = helpers::substring(url_data, input_position);
12802
6.97k
        ada_log("PATH ", helpers::substring(url_data, input_position));
12803
12804
        // Most time, we do not need percent encoding.
12805
        // Furthermore, we can immediately locate the '?'.
12806
6.97k
        size_t locofquestionmark = view.find('?');
12807
6.97k
        if (locofquestionmark != std::string_view::npos) {
12808
418
          state = ada::state::QUERY;
12809
418
          view.remove_suffix(view.size() - locofquestionmark);
12810
418
          input_position += locofquestionmark + 1;
12811
6.55k
        } else {
12812
6.55k
          input_position = input_size + 1;
12813
6.55k
        }
12814
6.97k
        if constexpr (result_type_is_ada_url) {
12815
6.97k
          helpers::parse_prepared_path(view, url.type, url.path);
12816
6.97k
        } else {
12817
6.97k
          url.consume_prepared_path(view);
12818
6.97k
          ADA_ASSERT_TRUE(url.validate());
12819
6.97k
        }
12820
6.97k
        break;
12821
10.8k
      }
12822
1.91k
      case ada::state::FILE_SLASH: {
12823
1.91k
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
12824
12825
        // If c is U+002F (/) or U+005C (\), then:
12826
1.91k
        if ((input_position != input_size) &&
12827
1.91k
            (url_data[input_position] == '/' ||
12828
1.63k
             url_data[input_position] == '\\')) {
12829
1.55k
          ada_log("FILE_SLASH c is U+002F or U+005C");
12830
          // Set state to file host state.
12831
1.55k
          state = ada::state::FILE_HOST;
12832
1.55k
          input_position++;
12833
1.55k
        } else {
12834
356
          ada_log("FILE_SLASH otherwise");
12835
          // If base is non-null and base's scheme is "file", then:
12836
          // Note: it is unsafe to do base_url->scheme unless you know that
12837
          // base_url_has_value() is true.
12838
356
          if (base_url != nullptr &&
12839
356
              base_url->type == ada::scheme::type::FILE) {
12840
            // Set url's host to base's host.
12841
222
            if constexpr (result_type_is_ada_url) {
12842
222
              url.host = base_url->host;
12843
222
            } else {
12844
              // TODO: Optimization opportunity.
12845
222
              url.set_host(base_url->get_host());
12846
222
            }
12847
            // If the code point substring from pointer to the end of input does
12848
            // not start with a Windows drive letter and base's path[0] is a
12849
            // normalized Windows drive letter, then append base's path[0] to
12850
            // url's path.
12851
222
            if (!base_url->get_pathname().empty()) {
12852
222
              if (!checkers::is_windows_drive_letter(
12853
222
                      helpers::substring(url_data, input_position))) {
12854
215
                std::string_view first_base_url_path =
12855
215
                    base_url->get_pathname().substr(1);
12856
215
                size_t loc = first_base_url_path.find('/');
12857
215
                if (loc != std::string_view::npos) {
12858
12
                  helpers::resize(first_base_url_path, loc);
12859
12
                }
12860
215
                if (checkers::is_normalized_windows_drive_letter(
12861
215
                        first_base_url_path)) {
12862
3
                  if constexpr (result_type_is_ada_url) {
12863
3
                    url.path += '/';
12864
3
                    url.path += first_base_url_path;
12865
3
                  } else {
12866
3
                    url.append_base_pathname(
12867
3
                        helpers::concat("/", first_base_url_path));
12868
3
                  }
12869
3
                }
12870
215
              }
12871
222
            }
12872
222
          }
12873
12874
          // Set state to path state, and decrease pointer by 1.
12875
356
          state = ada::state::PATH;
12876
356
        }
12877
12878
1.91k
        break;
12879
10.8k
      }
12880
1.55k
      case ada::state::FILE_HOST: {
12881
1.55k
        std::string_view view = helpers::substring(url_data, input_position);
12882
1.55k
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
12883
12884
1.55k
        size_t location = view.find_first_of("/\\?");
12885
1.55k
        std::string_view file_host_buffer(
12886
1.55k
            view.data(),
12887
1.55k
            (location != std::string_view::npos) ? location : view.size());
12888
12889
1.55k
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
12890
20
          state = ada::state::PATH;
12891
1.53k
        } else if (file_host_buffer.empty()) {
12892
          // Set url's host to the empty string.
12893
40
          if constexpr (result_type_is_ada_url) {
12894
40
            url.host = "";
12895
40
          } else {
12896
40
            url.update_base_hostname("");
12897
40
          }
12898
          // Set state to path start state.
12899
40
          state = ada::state::PATH_START;
12900
1.49k
        } else {
12901
1.49k
          size_t consumed_bytes = file_host_buffer.size();
12902
1.49k
          input_position += consumed_bytes;
12903
          // Let host be the result of host parsing buffer with url is not
12904
          // special.
12905
1.49k
          if (!url.parse_host(file_host_buffer)) {
12906
258
            return url;
12907
258
          }
12908
12909
1.24k
          if constexpr (result_type_is_ada_url) {
12910
            // If host is "localhost", then set host to the empty string.
12911
1.24k
            if (url.host.has_value() && url.host.value() == "localhost") {
12912
1.24k
              url.host = "";
12913
1.24k
            }
12914
1.24k
          } else {
12915
1.24k
            if (url.get_hostname() == "localhost") {
12916
10
              url.update_base_hostname("");
12917
10
            }
12918
1.24k
          }
12919
12920
          // Set buffer to the empty string and state to path start state.
12921
1.24k
          state = ada::state::PATH_START;
12922
1.24k
        }
12923
12924
1.30k
        break;
12925
1.55k
      }
12926
4.37k
      case ada::state::FILE: {
12927
4.37k
        ada_log("FILE ", helpers::substring(url_data, input_position));
12928
4.37k
        std::string_view file_view =
12929
4.37k
            helpers::substring(url_data, input_position);
12930
12931
4.37k
        url.set_protocol_as_file();
12932
4.37k
        if constexpr (result_type_is_ada_url) {
12933
          // Set url's host to the empty string.
12934
4.37k
          url.host = "";
12935
4.37k
        } else {
12936
4.37k
          url.update_base_hostname("");
12937
4.37k
        }
12938
        // If c is U+002F (/) or U+005C (\), then:
12939
4.37k
        if (input_position != input_size &&
12940
4.37k
            (url_data[input_position] == '/' ||
12941
2.82k
             url_data[input_position] == '\\')) {
12942
1.91k
          ada_log("FILE c is U+002F or U+005C");
12943
          // Set state to file slash state.
12944
1.91k
          state = ada::state::FILE_SLASH;
12945
1.91k
        }
12946
        // Otherwise, if base is non-null and base's scheme is "file":
12947
2.46k
        else if (base_url != nullptr &&
12948
2.46k
                 base_url->type == ada::scheme::type::FILE) {
12949
          // Set url's host to base's host, url's path to a clone of base's
12950
          // path, and url's query to base's query.
12951
345
          ada_log("FILE base non-null");
12952
345
          if constexpr (result_type_is_ada_url) {
12953
345
            url.host = base_url->host;
12954
345
            url.path = base_url->path;
12955
345
            url.query = base_url->query;
12956
345
          } else {
12957
            // TODO: Get rid of set_hostname and replace it with
12958
            // update_base_hostname
12959
345
            url.set_hostname(base_url->get_hostname());
12960
345
            url.update_base_pathname(base_url->get_pathname());
12961
345
            url.update_base_search(base_url->get_search());
12962
345
          }
12963
345
          url.has_opaque_path = base_url->has_opaque_path;
12964
12965
          // If c is U+003F (?), then set url's query to the empty string and
12966
          // state to query state.
12967
345
          if (input_position != input_size && url_data[input_position] == '?') {
12968
2
            state = ada::state::QUERY;
12969
2
          }
12970
          // Otherwise, if c is not the EOF code point:
12971
343
          else if (input_position != input_size) {
12972
            // Set url's query to null.
12973
93
            url.clear_search();
12974
            // If the code point substring from pointer to the end of input does
12975
            // not start with a Windows drive letter, then shorten url's path.
12976
93
            if (!checkers::is_windows_drive_letter(file_view)) {
12977
81
              if constexpr (result_type_is_ada_url) {
12978
81
                helpers::shorten_path(url.path, url.type);
12979
81
              } else {
12980
81
                std::string_view path = url.get_pathname();
12981
81
                if (helpers::shorten_path(path, url.type)) {
12982
76
                  url.update_base_pathname(std::string(path));
12983
76
                }
12984
81
              }
12985
81
            }
12986
            // Otherwise:
12987
12
            else {
12988
              // Set url's path to an empty list.
12989
12
              url.clear_pathname();
12990
12
              url.has_opaque_path = true;
12991
12
            }
12992
12993
            // Set state to path state and decrease pointer by 1.
12994
93
            state = ada::state::PATH;
12995
93
            break;
12996
93
          }
12997
345
        }
12998
        // Otherwise, set state to path state, and decrease pointer by 1.
12999
2.11k
        else {
13000
2.11k
          ada_log("FILE go to path");
13001
2.11k
          state = ada::state::PATH;
13002
2.11k
          break;
13003
2.11k
        }
13004
13005
2.16k
        input_position++;
13006
2.16k
        break;
13007
4.37k
      }
13008
0
      default:
13009
0
        ada::unreachable();
13010
164k
    }
13011
164k
  }
13012
10.8k
  if (fragment.has_value()) {
13013
438
    url.update_unencoded_base_hash(*fragment);
13014
438
  }
13015
10.8k
  return url;
13016
44.8k
}
13017
13018
template url parse_url<url>(std::string_view user_input,
13019
                            const url* base_url = nullptr);
13020
template url_aggregator parse_url<url_aggregator>(
13021
    std::string_view user_input, const url_aggregator* base_url = nullptr);
13022
13023
}  // namespace ada::parser
13024
/* end file src/parser.cpp */
13025
/* begin file src/url_components.cpp */
13026
13027
#include <numeric>
13028
#include <string>
13029
13030
namespace ada {
13031
13032
0
[[nodiscard]] bool url_components::check_offset_consistency() const noexcept {
13033
  /**
13034
   * https://user:pass@example.com:1234/foo/bar?baz#quux
13035
   *       |     |    |          | ^^^^|       |   |
13036
   *       |     |    |          | |   |       |   `----- hash_start
13037
   *       |     |    |          | |   |       `--------- search_start
13038
   *       |     |    |          | |   `----------------- pathname_start
13039
   *       |     |    |          | `--------------------- port
13040
   *       |     |    |          `----------------------- host_end
13041
   *       |     |    `---------------------------------- host_start
13042
   *       |     `--------------------------------------- username_end
13043
   *       `--------------------------------------------- protocol_end
13044
   */
13045
  // These conditions can be made more strict.
13046
0
  uint32_t index = 0;
13047
13048
0
  if (protocol_end == url_components::omitted) {
13049
0
    return false;
13050
0
  }
13051
0
  if (protocol_end < index) {
13052
0
    return false;
13053
0
  }
13054
0
  index = protocol_end;
13055
13056
0
  if (username_end == url_components::omitted) {
13057
0
    return false;
13058
0
  }
13059
0
  if (username_end < index) {
13060
0
    return false;
13061
0
  }
13062
0
  index = username_end;
13063
13064
0
  if (host_start == url_components::omitted) {
13065
0
    return false;
13066
0
  }
13067
0
  if (host_start < index) {
13068
0
    return false;
13069
0
  }
13070
0
  index = host_start;
13071
13072
0
  if (port != url_components::omitted) {
13073
0
    if (port > 0xffff) {
13074
0
      return false;
13075
0
    }
13076
0
    uint32_t port_length = helpers::fast_digit_count(port) + 1;
13077
0
    if (index + port_length < index) {
13078
0
      return false;
13079
0
    }
13080
0
    index += port_length;
13081
0
  }
13082
13083
0
  if (pathname_start == url_components::omitted) {
13084
0
    return false;
13085
0
  }
13086
0
  if (pathname_start < index) {
13087
0
    return false;
13088
0
  }
13089
0
  index = pathname_start;
13090
13091
0
  if (search_start != url_components::omitted) {
13092
0
    if (search_start < index) {
13093
0
      return false;
13094
0
    }
13095
0
    index = search_start;
13096
0
  }
13097
13098
0
  if (hash_start != url_components::omitted) {
13099
0
    if (hash_start < index) {
13100
0
      return false;
13101
0
    }
13102
0
    index = hash_start;
13103
0
  }
13104
13105
0
  return true;
13106
0
}
13107
13108
0
[[nodiscard]] std::string url_components::to_string() const {
13109
0
  std::string answer;
13110
0
  auto back = std::back_insert_iterator(answer);
13111
0
  answer.append("{\n");
13112
13113
0
  answer.append("\t\"protocol_end\":\"");
13114
0
  helpers::encode_json(std::to_string(protocol_end), back);
13115
0
  answer.append("\",\n");
13116
13117
0
  answer.append("\t\"username_end\":\"");
13118
0
  helpers::encode_json(std::to_string(username_end), back);
13119
0
  answer.append("\",\n");
13120
13121
0
  answer.append("\t\"host_start\":\"");
13122
0
  helpers::encode_json(std::to_string(host_start), back);
13123
0
  answer.append("\",\n");
13124
13125
0
  answer.append("\t\"host_end\":\"");
13126
0
  helpers::encode_json(std::to_string(host_end), back);
13127
0
  answer.append("\",\n");
13128
13129
0
  answer.append("\t\"port\":\"");
13130
0
  helpers::encode_json(std::to_string(port), back);
13131
0
  answer.append("\",\n");
13132
13133
0
  answer.append("\t\"pathname_start\":\"");
13134
0
  helpers::encode_json(std::to_string(pathname_start), back);
13135
0
  answer.append("\",\n");
13136
13137
0
  answer.append("\t\"search_start\":\"");
13138
0
  helpers::encode_json(std::to_string(search_start), back);
13139
0
  answer.append("\",\n");
13140
13141
0
  answer.append("\t\"hash_start\":\"");
13142
0
  helpers::encode_json(std::to_string(hash_start), back);
13143
0
  answer.append("\",\n");
13144
13145
0
  answer.append("\n}");
13146
0
  return answer;
13147
0
}
13148
13149
}  // namespace ada
13150
/* end file src/url_components.cpp */
13151
/* begin file src/url_aggregator.cpp */
13152
13153
#include <string>
13154
#include <string_view>
13155
13156
namespace ada {
13157
template <bool has_state_override>
13158
[[nodiscard]] ada_really_inline bool url_aggregator::parse_scheme_with_colon(
13159
24.0k
    const std::string_view input_with_colon) {
13160
24.0k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
13161
24.0k
  ADA_ASSERT_TRUE(validate());
13162
24.0k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
13163
24.0k
  std::string_view input{input_with_colon};
13164
24.0k
  input.remove_suffix(1);
13165
24.0k
  auto parsed_type = ada::scheme::get_scheme_type(input);
13166
24.0k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
13167
  /**
13168
   * In the common case, we will immediately recognize a special scheme (e.g.,
13169
   *http, https), in which case, we can go really fast.
13170
   **/
13171
24.0k
  if (is_input_special) {  // fast path!!!
13172
8.85k
    if (has_state_override) {
13173
      // If url's scheme is not a special scheme and buffer is a special scheme,
13174
      // then return.
13175
78
      if (is_special() != is_input_special) {
13176
3
        return true;
13177
3
      }
13178
13179
      // If url includes credentials or has a non-null port, and buffer is
13180
      // "file", then return.
13181
75
      if ((has_credentials() || components.port != url_components::omitted) &&
13182
75
          parsed_type == ada::scheme::type::FILE) {
13183
1
        return true;
13184
1
      }
13185
13186
      // If url's scheme is "file" and its host is an empty host, then return.
13187
      // An empty host is the empty string.
13188
74
      if (type == ada::scheme::type::FILE &&
13189
74
          components.host_start == components.host_end) {
13190
1
        return true;
13191
1
      }
13192
74
    }
13193
13194
8.85k
    type = parsed_type;
13195
8.85k
    set_scheme_from_view_with_colon(input_with_colon);
13196
13197
8.85k
    if (has_state_override) {
13198
      // This is uncommon.
13199
73
      uint16_t urls_scheme_port = get_special_port();
13200
13201
      // If url's port is url's scheme's default port, then set url's port to
13202
      // null.
13203
73
      if (components.port == urls_scheme_port) {
13204
6
        clear_port();
13205
6
      }
13206
73
    }
13207
15.2k
  } else {  // slow path
13208
15.2k
    std::string _buffer = std::string(input);
13209
    // Next function is only valid if the input is ASCII and returns false
13210
    // otherwise, but it seems that we always have ascii content so we do not
13211
    // need to check the return value.
13212
15.2k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
13213
13214
15.2k
    if (has_state_override) {
13215
      // If url's scheme is a special scheme and buffer is not a special scheme,
13216
      // then return. If url's scheme is not a special scheme and buffer is a
13217
      // special scheme, then return.
13218
298
      if (is_special() != ada::scheme::is_special(_buffer)) {
13219
138
        return true;
13220
138
      }
13221
13222
      // If url includes credentials or has a non-null port, and buffer is
13223
      // "file", then return.
13224
160
      if ((has_credentials() || components.port != url_components::omitted) &&
13225
160
          _buffer == "file") {
13226
1
        return true;
13227
1
      }
13228
13229
      // If url's scheme is "file" and its host is an empty host, then return.
13230
      // An empty host is the empty string.
13231
159
      if (type == ada::scheme::type::FILE &&
13232
159
          components.host_start == components.host_end) {
13233
1
        return true;
13234
1
      }
13235
159
    }
13236
13237
15.0k
    set_scheme(_buffer);
13238
13239
15.0k
    if (has_state_override) {
13240
      // This is uncommon.
13241
158
      uint16_t urls_scheme_port = get_special_port();
13242
13243
      // If url's port is url's scheme's default port, then set url's port to
13244
      // null.
13245
158
      if (components.port == urls_scheme_port) {
13246
22
        clear_port();
13247
22
      }
13248
158
    }
13249
15.0k
  }
13250
23.9k
  ADA_ASSERT_TRUE(validate());
13251
23.9k
  return true;
13252
24.0k
}
bool ada::url_aggregator::parse_scheme_with_colon<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
13159
23.6k
    const std::string_view input_with_colon) {
13160
23.6k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
13161
23.6k
  ADA_ASSERT_TRUE(validate());
13162
23.6k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
13163
23.6k
  std::string_view input{input_with_colon};
13164
23.6k
  input.remove_suffix(1);
13165
23.6k
  auto parsed_type = ada::scheme::get_scheme_type(input);
13166
23.6k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
13167
  /**
13168
   * In the common case, we will immediately recognize a special scheme (e.g.,
13169
   *http, https), in which case, we can go really fast.
13170
   **/
13171
23.6k
  if (is_input_special) {  // fast path!!!
13172
8.77k
    if (has_state_override) {
13173
      // If url's scheme is not a special scheme and buffer is a special scheme,
13174
      // then return.
13175
0
      if (is_special() != is_input_special) {
13176
0
        return true;
13177
0
      }
13178
13179
      // If url includes credentials or has a non-null port, and buffer is
13180
      // "file", then return.
13181
0
      if ((has_credentials() || components.port != url_components::omitted) &&
13182
0
          parsed_type == ada::scheme::type::FILE) {
13183
0
        return true;
13184
0
      }
13185
13186
      // If url's scheme is "file" and its host is an empty host, then return.
13187
      // An empty host is the empty string.
13188
0
      if (type == ada::scheme::type::FILE &&
13189
0
          components.host_start == components.host_end) {
13190
0
        return true;
13191
0
      }
13192
0
    }
13193
13194
8.77k
    type = parsed_type;
13195
8.77k
    set_scheme_from_view_with_colon(input_with_colon);
13196
13197
8.77k
    if (has_state_override) {
13198
      // This is uncommon.
13199
0
      uint16_t urls_scheme_port = get_special_port();
13200
13201
      // If url's port is url's scheme's default port, then set url's port to
13202
      // null.
13203
0
      if (components.port == urls_scheme_port) {
13204
0
        clear_port();
13205
0
      }
13206
0
    }
13207
14.9k
  } else {  // slow path
13208
14.9k
    std::string _buffer = std::string(input);
13209
    // Next function is only valid if the input is ASCII and returns false
13210
    // otherwise, but it seems that we always have ascii content so we do not
13211
    // need to check the return value.
13212
14.9k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
13213
13214
14.9k
    if (has_state_override) {
13215
      // If url's scheme is a special scheme and buffer is not a special scheme,
13216
      // then return. If url's scheme is not a special scheme and buffer is a
13217
      // special scheme, then return.
13218
0
      if (is_special() != ada::scheme::is_special(_buffer)) {
13219
0
        return true;
13220
0
      }
13221
13222
      // If url includes credentials or has a non-null port, and buffer is
13223
      // "file", then return.
13224
0
      if ((has_credentials() || components.port != url_components::omitted) &&
13225
0
          _buffer == "file") {
13226
0
        return true;
13227
0
      }
13228
13229
      // If url's scheme is "file" and its host is an empty host, then return.
13230
      // An empty host is the empty string.
13231
0
      if (type == ada::scheme::type::FILE &&
13232
0
          components.host_start == components.host_end) {
13233
0
        return true;
13234
0
      }
13235
0
    }
13236
13237
14.9k
    set_scheme(_buffer);
13238
13239
14.9k
    if (has_state_override) {
13240
      // This is uncommon.
13241
0
      uint16_t urls_scheme_port = get_special_port();
13242
13243
      // If url's port is url's scheme's default port, then set url's port to
13244
      // null.
13245
0
      if (components.port == urls_scheme_port) {
13246
0
        clear_port();
13247
0
      }
13248
0
    }
13249
14.9k
  }
13250
23.6k
  ADA_ASSERT_TRUE(validate());
13251
23.6k
  return true;
13252
23.6k
}
bool ada::url_aggregator::parse_scheme_with_colon<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
13159
376
    const std::string_view input_with_colon) {
13160
376
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
13161
376
  ADA_ASSERT_TRUE(validate());
13162
376
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
13163
376
  std::string_view input{input_with_colon};
13164
376
  input.remove_suffix(1);
13165
376
  auto parsed_type = ada::scheme::get_scheme_type(input);
13166
376
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
13167
  /**
13168
   * In the common case, we will immediately recognize a special scheme (e.g.,
13169
   *http, https), in which case, we can go really fast.
13170
   **/
13171
376
  if (is_input_special) {  // fast path!!!
13172
78
    if (has_state_override) {
13173
      // If url's scheme is not a special scheme and buffer is a special scheme,
13174
      // then return.
13175
78
      if (is_special() != is_input_special) {
13176
3
        return true;
13177
3
      }
13178
13179
      // If url includes credentials or has a non-null port, and buffer is
13180
      // "file", then return.
13181
75
      if ((has_credentials() || components.port != url_components::omitted) &&
13182
75
          parsed_type == ada::scheme::type::FILE) {
13183
1
        return true;
13184
1
      }
13185
13186
      // If url's scheme is "file" and its host is an empty host, then return.
13187
      // An empty host is the empty string.
13188
74
      if (type == ada::scheme::type::FILE &&
13189
74
          components.host_start == components.host_end) {
13190
1
        return true;
13191
1
      }
13192
74
    }
13193
13194
73
    type = parsed_type;
13195
73
    set_scheme_from_view_with_colon(input_with_colon);
13196
13197
73
    if (has_state_override) {
13198
      // This is uncommon.
13199
73
      uint16_t urls_scheme_port = get_special_port();
13200
13201
      // If url's port is url's scheme's default port, then set url's port to
13202
      // null.
13203
73
      if (components.port == urls_scheme_port) {
13204
6
        clear_port();
13205
6
      }
13206
73
    }
13207
298
  } else {  // slow path
13208
298
    std::string _buffer = std::string(input);
13209
    // Next function is only valid if the input is ASCII and returns false
13210
    // otherwise, but it seems that we always have ascii content so we do not
13211
    // need to check the return value.
13212
298
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
13213
13214
298
    if (has_state_override) {
13215
      // If url's scheme is a special scheme and buffer is not a special scheme,
13216
      // then return. If url's scheme is not a special scheme and buffer is a
13217
      // special scheme, then return.
13218
298
      if (is_special() != ada::scheme::is_special(_buffer)) {
13219
138
        return true;
13220
138
      }
13221
13222
      // If url includes credentials or has a non-null port, and buffer is
13223
      // "file", then return.
13224
160
      if ((has_credentials() || components.port != url_components::omitted) &&
13225
160
          _buffer == "file") {
13226
1
        return true;
13227
1
      }
13228
13229
      // If url's scheme is "file" and its host is an empty host, then return.
13230
      // An empty host is the empty string.
13231
159
      if (type == ada::scheme::type::FILE &&
13232
159
          components.host_start == components.host_end) {
13233
1
        return true;
13234
1
      }
13235
159
    }
13236
13237
158
    set_scheme(_buffer);
13238
13239
158
    if (has_state_override) {
13240
      // This is uncommon.
13241
158
      uint16_t urls_scheme_port = get_special_port();
13242
13243
      // If url's port is url's scheme's default port, then set url's port to
13244
      // null.
13245
158
      if (components.port == urls_scheme_port) {
13246
22
        clear_port();
13247
22
      }
13248
158
    }
13249
158
  }
13250
231
  ADA_ASSERT_TRUE(validate());
13251
231
  return true;
13252
376
}
13253
13254
778
inline void url_aggregator::copy_scheme(const url_aggregator& u) noexcept {
13255
778
  ada_log("url_aggregator::copy_scheme ", u.buffer);
13256
778
  ADA_ASSERT_TRUE(validate());
13257
  // next line could overflow but unsigned arithmetic has well-defined
13258
  // overflows.
13259
778
  uint32_t new_difference = u.components.protocol_end - components.protocol_end;
13260
778
  type = u.type;
13261
778
  buffer.erase(0, components.protocol_end);
13262
778
  buffer.insert(0, u.get_protocol());
13263
778
  components.protocol_end = u.components.protocol_end;
13264
13265
  // No need to update the components
13266
778
  if (new_difference == 0) {
13267
93
    return;
13268
93
  }
13269
13270
  // Update the rest of the components.
13271
685
  components.username_end += new_difference;
13272
685
  components.host_start += new_difference;
13273
685
  components.host_end += new_difference;
13274
685
  components.pathname_start += new_difference;
13275
685
  if (components.search_start != url_components::omitted) {
13276
0
    components.search_start += new_difference;
13277
0
  }
13278
685
  if (components.hash_start != url_components::omitted) {
13279
0
    components.hash_start += new_difference;
13280
0
  }
13281
685
  ADA_ASSERT_TRUE(validate());
13282
685
}
13283
13284
inline void url_aggregator::set_scheme_from_view_with_colon(
13285
8.85k
    std::string_view new_scheme_with_colon) noexcept {
13286
8.85k
  ada_log("url_aggregator::set_scheme_from_view_with_colon ",
13287
8.85k
          new_scheme_with_colon);
13288
8.85k
  ADA_ASSERT_TRUE(validate());
13289
8.85k
  ADA_ASSERT_TRUE(!new_scheme_with_colon.empty() &&
13290
8.85k
                  new_scheme_with_colon.back() == ':');
13291
  // next line could overflow but unsigned arithmetic has well-defined
13292
  // overflows.
13293
8.85k
  uint32_t new_difference =
13294
8.85k
      uint32_t(new_scheme_with_colon.size()) - components.protocol_end;
13295
13296
8.85k
  if (buffer.empty()) {
13297
8.77k
    buffer.append(new_scheme_with_colon);
13298
8.77k
  } else {
13299
73
    buffer.erase(0, components.protocol_end);
13300
73
    buffer.insert(0, new_scheme_with_colon);
13301
73
  }
13302
8.85k
  components.protocol_end += new_difference;
13303
13304
  // Update the rest of the components.
13305
8.85k
  components.username_end += new_difference;
13306
8.85k
  components.host_start += new_difference;
13307
8.85k
  components.host_end += new_difference;
13308
8.85k
  components.pathname_start += new_difference;
13309
8.85k
  if (components.search_start != url_components::omitted) {
13310
16
    components.search_start += new_difference;
13311
16
  }
13312
8.85k
  if (components.hash_start != url_components::omitted) {
13313
16
    components.hash_start += new_difference;
13314
16
  }
13315
8.85k
  ADA_ASSERT_TRUE(validate());
13316
8.85k
}
13317
13318
15.0k
inline void url_aggregator::set_scheme(std::string_view new_scheme) noexcept {
13319
15.0k
  ada_log("url_aggregator::set_scheme ", new_scheme);
13320
15.0k
  ADA_ASSERT_TRUE(validate());
13321
15.0k
  ADA_ASSERT_TRUE(new_scheme.empty() || new_scheme.back() != ':');
13322
  // next line could overflow but unsigned arithmetic has well-defined
13323
  // overflows.
13324
15.0k
  uint32_t new_difference =
13325
15.0k
      uint32_t(new_scheme.size()) - components.protocol_end + 1;
13326
13327
15.0k
  type = ada::scheme::get_scheme_type(new_scheme);
13328
15.0k
  if (buffer.empty()) {
13329
14.9k
    buffer.append(helpers::concat(new_scheme, ":"));
13330
14.9k
  } else {
13331
158
    buffer.erase(0, components.protocol_end);
13332
158
    buffer.insert(0, helpers::concat(new_scheme, ":"));
13333
158
  }
13334
15.0k
  components.protocol_end = uint32_t(new_scheme.size() + 1);
13335
13336
  // Update the rest of the components.
13337
15.0k
  components.username_end += new_difference;
13338
15.0k
  components.host_start += new_difference;
13339
15.0k
  components.host_end += new_difference;
13340
15.0k
  components.pathname_start += new_difference;
13341
15.0k
  if (components.search_start != url_components::omitted) {
13342
21
    components.search_start += new_difference;
13343
21
  }
13344
15.0k
  if (components.hash_start != url_components::omitted) {
13345
24
    components.hash_start += new_difference;
13346
24
  }
13347
15.0k
  ADA_ASSERT_TRUE(validate());
13348
15.0k
}
13349
13350
7.98k
bool url_aggregator::set_protocol(const std::string_view input) {
13351
7.98k
  ada_log("url_aggregator::set_protocol ", input);
13352
7.98k
  ADA_ASSERT_TRUE(validate());
13353
7.98k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13354
7.98k
  std::string view(input);
13355
7.98k
  helpers::remove_ascii_tab_or_newline(view);
13356
7.98k
  if (view.empty()) {
13357
6.49k
    return true;
13358
6.49k
  }
13359
13360
  // Schemes should start with alpha values.
13361
1.49k
  if (!checkers::is_alpha(view[0])) {
13362
1.05k
    return false;
13363
1.05k
  }
13364
13365
441
  view.append(":");
13366
13367
441
  std::string::iterator pointer =
13368
441
      std::find_if_not(view.begin(), view.end(), unicode::is_alnum_plus);
13369
13370
441
  if (pointer != view.end() && *pointer == ':') {
13371
376
    return parse_scheme_with_colon<true>(
13372
376
        std::string_view(view.data(), pointer - view.begin() + 1));
13373
376
  }
13374
65
  return false;
13375
441
}
13376
13377
7.98k
bool url_aggregator::set_username(const std::string_view input) {
13378
7.98k
  ada_log("url_aggregator::set_username '", input, "' ");
13379
7.98k
  ADA_ASSERT_TRUE(validate());
13380
7.98k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13381
7.98k
  if (cannot_have_credentials_or_port()) {
13382
3.90k
    return false;
13383
3.90k
  }
13384
4.08k
  size_t idx = ada::unicode::percent_encode_index(
13385
4.08k
      input, character_sets::USERINFO_PERCENT_ENCODE);
13386
4.08k
  if (idx == input.size()) {
13387
3.56k
    update_base_username(input);
13388
3.56k
  } else {
13389
    // We only create a temporary string if we have to!
13390
514
    update_base_username(ada::unicode::percent_encode(
13391
514
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
13392
514
  }
13393
4.08k
  ADA_ASSERT_TRUE(validate());
13394
4.08k
  return true;
13395
7.98k
}
13396
13397
7.98k
bool url_aggregator::set_password(const std::string_view input) {
13398
7.98k
  ada_log("url_aggregator::set_password '", input, "'");
13399
7.98k
  ADA_ASSERT_TRUE(validate());
13400
7.98k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13401
7.98k
  if (cannot_have_credentials_or_port()) {
13402
3.90k
    return false;
13403
3.90k
  }
13404
4.08k
  size_t idx = ada::unicode::percent_encode_index(
13405
4.08k
      input, character_sets::USERINFO_PERCENT_ENCODE);
13406
4.08k
  if (idx == input.size()) {
13407
3.56k
    update_base_password(input);
13408
3.56k
  } else {
13409
    // We only create a temporary string if we have to!
13410
514
    update_base_password(ada::unicode::percent_encode(
13411
514
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
13412
514
  }
13413
4.08k
  ADA_ASSERT_TRUE(validate());
13414
4.08k
  return true;
13415
7.98k
}
13416
13417
8.14k
bool url_aggregator::set_port(const std::string_view input) {
13418
8.14k
  ada_log("url_aggregator::set_port ", input);
13419
8.14k
  ADA_ASSERT_TRUE(validate());
13420
8.14k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13421
8.14k
  if (cannot_have_credentials_or_port()) {
13422
3.87k
    return false;
13423
3.87k
  }
13424
4.27k
  std::string trimmed(input);
13425
4.27k
  helpers::remove_ascii_tab_or_newline(trimmed);
13426
4.27k
  if (trimmed.empty()) {
13427
3.13k
    clear_port();
13428
3.13k
    return true;
13429
3.13k
  }
13430
  // Input should not start with control characters.
13431
1.13k
  if (ada::unicode::is_c0_control_or_space(trimmed.front())) {
13432
52
    return false;
13433
52
  }
13434
  // Input should contain at least one ascii digit.
13435
1.08k
  if (input.find_first_of("0123456789") == std::string_view::npos) {
13436
550
    return false;
13437
550
  }
13438
13439
  // Revert changes if parse_port fails.
13440
532
  uint32_t previous_port = components.port;
13441
532
  parse_port(trimmed);
13442
532
  if (is_valid) {
13443
389
    return true;
13444
389
  }
13445
143
  update_base_port(previous_port);
13446
143
  is_valid = true;
13447
143
  ADA_ASSERT_TRUE(validate());
13448
143
  return false;
13449
532
}
13450
13451
7.98k
bool url_aggregator::set_pathname(const std::string_view input) {
13452
7.98k
  ada_log("url_aggregator::set_pathname ", input);
13453
7.98k
  ADA_ASSERT_TRUE(validate());
13454
7.98k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13455
7.98k
  if (has_opaque_path) {
13456
1.02k
    return false;
13457
1.02k
  }
13458
6.96k
  clear_pathname();
13459
6.96k
  parse_path(input);
13460
6.96k
  if (checkers::begins_with(input, "//") && !has_authority() &&
13461
6.96k
      !has_dash_dot()) {
13462
4
    buffer.insert(components.pathname_start, "/.");
13463
4
    components.pathname_start += 2;
13464
4
  }
13465
6.96k
  ADA_ASSERT_TRUE(validate());
13466
6.96k
  return true;
13467
7.98k
}
13468
13469
6.96k
ada_really_inline void url_aggregator::parse_path(std::string_view input) {
13470
6.96k
  ada_log("url_aggregator::parse_path ", input);
13471
6.96k
  ADA_ASSERT_TRUE(validate());
13472
6.96k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13473
6.96k
  std::string tmp_buffer;
13474
6.96k
  std::string_view internal_input;
13475
6.96k
  if (unicode::has_tabs_or_newline(input)) {
13476
114
    tmp_buffer = input;
13477
    // Optimization opportunity: Instead of copying and then pruning, we could
13478
    // just directly build the string from user_input.
13479
114
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13480
114
    internal_input = tmp_buffer;
13481
6.85k
  } else {
13482
6.85k
    internal_input = input;
13483
6.85k
  }
13484
13485
  // If url is special, then:
13486
6.96k
  if (is_special()) {
13487
5.24k
    if (internal_input.empty()) {
13488
4.26k
      update_base_pathname("/");
13489
4.26k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
13490
15
      consume_prepared_path(internal_input.substr(1));
13491
966
    } else {
13492
966
      consume_prepared_path(internal_input);
13493
966
    }
13494
5.24k
  } else if (!internal_input.empty()) {
13495
380
    if (internal_input[0] == '/') {
13496
19
      consume_prepared_path(internal_input.substr(1));
13497
361
    } else {
13498
361
      consume_prepared_path(internal_input);
13499
361
    }
13500
1.34k
  } else {
13501
    // Non-special URLs with an empty host can have their paths erased
13502
    // Path-only URLs cannot have their paths erased
13503
1.34k
    if (components.host_start == components.host_end && !has_authority()) {
13504
1.18k
      update_base_pathname("/");
13505
1.18k
    }
13506
1.34k
  }
13507
6.96k
  ADA_ASSERT_TRUE(validate());
13508
6.96k
}
13509
13510
7.98k
void url_aggregator::set_search(const std::string_view input) {
13511
7.98k
  ada_log("url_aggregator::set_search ", input);
13512
7.98k
  ADA_ASSERT_TRUE(validate());
13513
7.98k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13514
7.98k
  if (input.empty()) {
13515
6.43k
    clear_search();
13516
6.43k
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13517
6.43k
    return;
13518
6.43k
  }
13519
13520
1.55k
  std::string new_value;
13521
1.55k
  new_value = input[0] == '?' ? input.substr(1) : input;
13522
1.55k
  helpers::remove_ascii_tab_or_newline(new_value);
13523
13524
1.55k
  auto query_percent_encode_set =
13525
1.55k
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13526
1.55k
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
13527
13528
1.55k
  update_base_search(new_value, query_percent_encode_set);
13529
1.55k
  ADA_ASSERT_TRUE(validate());
13530
1.55k
}
13531
13532
7.98k
void url_aggregator::set_hash(const std::string_view input) {
13533
7.98k
  ada_log("url_aggregator::set_hash ", input);
13534
7.98k
  ADA_ASSERT_TRUE(validate());
13535
7.98k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13536
7.98k
  if (input.empty()) {
13537
6.43k
    if (components.hash_start != url_components::omitted) {
13538
136
      buffer.resize(components.hash_start);
13539
136
      components.hash_start = url_components::omitted;
13540
136
    }
13541
6.43k
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13542
6.43k
    return;
13543
6.43k
  }
13544
13545
1.55k
  std::string new_value;
13546
1.55k
  new_value = input[0] == '#' ? input.substr(1) : input;
13547
1.55k
  helpers::remove_ascii_tab_or_newline(new_value);
13548
1.55k
  update_unencoded_base_hash(new_value);
13549
1.55k
  ADA_ASSERT_TRUE(validate());
13550
1.55k
}
13551
13552
0
bool url_aggregator::set_href(const std::string_view input) {
13553
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13554
0
  ada_log("url_aggregator::set_href ", input, "[", input.size(), " bytes]");
13555
0
  ada::result<url_aggregator> out = ada::parse<url_aggregator>(input);
13556
0
  ada_log("url_aggregator::set_href, success :", out.has_value());
13557
13558
0
  if (out) {
13559
0
    ada_log("url_aggregator::set_href, parsed ", out->to_string());
13560
    // TODO: Figure out why the following line puts test to never finish.
13561
0
    *this = *out;
13562
0
  }
13563
13564
0
  return out.has_value();
13565
0
}
13566
13567
17.5k
ada_really_inline bool url_aggregator::parse_host(std::string_view input) {
13568
17.5k
  ada_log("url_aggregator:parse_host ", input, "[", input.size(), " bytes]");
13569
17.5k
  ADA_ASSERT_TRUE(validate());
13570
17.5k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13571
17.5k
  if (input.empty()) {
13572
77
    return is_valid = false;
13573
77
  }  // technically unnecessary.
13574
  // If input starts with U+005B ([), then:
13575
17.5k
  if (input[0] == '[') {
13576
    // If input does not end with U+005D (]), validation error, return failure.
13577
1.53k
    if (input.back() != ']') {
13578
575
      return is_valid = false;
13579
575
    }
13580
959
    ada_log("parse_host ipv6");
13581
13582
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
13583
    // trailing U+005D (]) removed.
13584
959
    input.remove_prefix(1);
13585
959
    input.remove_suffix(1);
13586
959
    return parse_ipv6(input);
13587
1.53k
  }
13588
13589
  // If isNotSpecial is true, then return the result of opaque-host parsing
13590
  // input.
13591
15.9k
  if (!is_special()) {
13592
1.13k
    return parse_opaque_host(input);
13593
1.13k
  }
13594
  // Let domain be the result of running UTF-8 decode without BOM on the
13595
  // percent-decoding of input. Let asciiDomain be the result of running domain
13596
  // to ASCII with domain and false. The most common case is an ASCII input, in
13597
  // which case we do not need to call the expensive 'to_ascii' if a few
13598
  // conditions are met: no '%' and no 'xn-' subsequence.
13599
13600
  // Often, the input does not contain any forbidden code points, and no upper
13601
  // case ASCII letter, then we can just copy it to the buffer. We want to
13602
  // optimize for such a common case.
13603
14.8k
  uint8_t is_forbidden_or_upper =
13604
14.8k
      unicode::contains_forbidden_domain_code_point_or_upper(input.data(),
13605
14.8k
                                                             input.size());
13606
  // Minor optimization opportunity:
13607
  // contains_forbidden_domain_code_point_or_upper could be extend to check for
13608
  // the presence of characters that cannot appear in the ipv4 address and we
13609
  // could also check whether x and n and - are present, and so we could skip
13610
  // some of the checks below. However, the gains are likely to be small, and
13611
  // the code would be more complex.
13612
14.8k
  if (is_forbidden_or_upper == 0 &&
13613
14.8k
      input.find("xn-") == std::string_view::npos) {
13614
    // fast path
13615
7.64k
    update_base_hostname(input);
13616
7.64k
    if (checkers::is_ipv4(get_hostname())) {
13617
2.88k
      ada_log("parse_host fast path ipv4");
13618
2.88k
      return parse_ipv4(get_hostname());
13619
2.88k
    }
13620
4.76k
    ada_log("parse_host fast path ", get_hostname());
13621
4.76k
    return true;
13622
7.64k
  }
13623
  // We have encountered at least one forbidden code point or the input contains
13624
  // 'xn-' (case insensitive), so we need to call 'to_ascii' to perform the full
13625
  // conversion.
13626
13627
7.19k
  ada_log("parse_host calling to_ascii");
13628
7.19k
  std::optional<std::string> host = std::string(get_hostname());
13629
7.19k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
13630
7.19k
  if (!is_valid) {
13631
1.81k
    ada_log("parse_host to_ascii returns false");
13632
1.81k
    return is_valid = false;
13633
1.81k
  }
13634
13635
5.37k
  if (std::any_of(host.value().begin(), host.value().end(),
13636
5.37k
                  ada::unicode::is_forbidden_domain_code_point)) {
13637
0
    return is_valid = false;
13638
0
  }
13639
13640
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
13641
  // asciiDomain.
13642
5.37k
  if (checkers::is_ipv4(host.value())) {
13643
941
    ada_log("parse_host got ipv4", *host);
13644
941
    return parse_ipv4(host.value());
13645
941
  }
13646
13647
4.43k
  update_base_hostname(host.value());
13648
4.43k
  ADA_ASSERT_TRUE(validate());
13649
4.43k
  return true;
13650
5.37k
}
13651
13652
template <bool override_hostname>
13653
17.2k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
13654
17.2k
  ada_log("url_aggregator::set_host_or_hostname ", input);
13655
17.2k
  ADA_ASSERT_TRUE(validate());
13656
17.2k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13657
17.2k
  if (has_opaque_path) {
13658
2.04k
    return false;
13659
2.04k
  }
13660
13661
15.2k
  std::string previous_host = std::string(get_hostname());
13662
15.2k
  uint32_t previous_port = components.port;
13663
13664
15.2k
  size_t host_end_pos = input.find('#');
13665
15.2k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
13666
15.2k
                                      ? host_end_pos
13667
15.2k
                                      : input.size());
13668
15.2k
  helpers::remove_ascii_tab_or_newline(_host);
13669
15.2k
  std::string_view new_host(_host);
13670
13671
  // If url's scheme is "file", then set state to file host state, instead of
13672
  // host state.
13673
15.2k
  if (type != ada::scheme::type::FILE) {
13674
11.9k
    std::string_view host_view(_host.data(), _host.length());
13675
11.9k
    auto [location, found_colon] =
13676
11.9k
        helpers::get_host_delimiter_location(is_special(), host_view);
13677
13678
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13679
    // Note: the 'found_colon' value is true if and only if a colon was
13680
    // encountered while not inside brackets.
13681
11.9k
    if (found_colon) {
13682
376
      if (override_hostname) {
13683
188
        return false;
13684
188
      }
13685
188
      std::string_view sub_buffer = new_host.substr(location + 1);
13686
188
      if (!sub_buffer.empty()) {
13687
158
        set_port(sub_buffer);
13688
158
      }
13689
188
    }
13690
    // If url is special and host_view is the empty string, validation error,
13691
    // return failure. Otherwise, if state override is given, host_view is the
13692
    // empty string, and either url includes credentials or url's port is
13693
    // non-null, return.
13694
11.5k
    else if (host_view.empty() &&
13695
11.5k
             (is_special() || has_credentials() || has_port())) {
13696
6.33k
      return false;
13697
6.33k
    }
13698
13699
    // Let host be the result of host parsing host_view with url is not special.
13700
5.41k
    if (host_view.empty() && !is_special()) {
13701
2.82k
      if (has_hostname()) {
13702
260
        clear_hostname();  // easy!
13703
2.56k
      } else if (has_dash_dot()) {
13704
38
        add_authority_slashes_if_needed();
13705
38
        delete_dash_dot();
13706
38
      }
13707
2.82k
      return true;
13708
2.82k
    }
13709
13710
2.58k
    bool succeeded = parse_host(host_view);
13711
2.58k
    if (!succeeded) {
13712
732
      update_base_hostname(previous_host);
13713
732
      update_base_port(previous_port);
13714
1.85k
    } else if (has_dash_dot()) {
13715
      // Should remove dash_dot from pathname
13716
13
      delete_dash_dot();
13717
13
    }
13718
2.58k
    return succeeded;
13719
5.41k
  }
13720
13721
3.30k
  size_t location = new_host.find_first_of("/\\?");
13722
3.30k
  if (location != std::string_view::npos) {
13723
38
    new_host.remove_suffix(new_host.length() - location);
13724
38
  }
13725
13726
3.30k
  if (new_host.empty()) {
13727
    // Set url's host to the empty string.
13728
2.46k
    clear_hostname();
13729
2.46k
  } else {
13730
    // Let host be the result of host parsing buffer with url is not special.
13731
838
    if (!parse_host(new_host)) {
13732
140
      update_base_hostname(previous_host);
13733
140
      update_base_port(previous_port);
13734
140
      return false;
13735
140
    }
13736
13737
    // If host is "localhost", then set host to the empty string.
13738
698
    if (helpers::substring(buffer, components.host_start,
13739
698
                           components.host_end) == "localhost") {
13740
36
      clear_hostname();
13741
36
    }
13742
698
  }
13743
3.16k
  ADA_ASSERT_TRUE(validate());
13744
3.16k
  return true;
13745
3.30k
}
bool ada::url_aggregator::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
13653
8.20k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
13654
8.20k
  ada_log("url_aggregator::set_host_or_hostname ", input);
13655
8.20k
  ADA_ASSERT_TRUE(validate());
13656
8.20k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13657
8.20k
  if (has_opaque_path) {
13658
1.02k
    return false;
13659
1.02k
  }
13660
13661
7.18k
  std::string previous_host = std::string(get_hostname());
13662
7.18k
  uint32_t previous_port = components.port;
13663
13664
7.18k
  size_t host_end_pos = input.find('#');
13665
7.18k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
13666
7.18k
                                      ? host_end_pos
13667
7.18k
                                      : input.size());
13668
7.18k
  helpers::remove_ascii_tab_or_newline(_host);
13669
7.18k
  std::string_view new_host(_host);
13670
13671
  // If url's scheme is "file", then set state to file host state, instead of
13672
  // host state.
13673
7.18k
  if (type != ada::scheme::type::FILE) {
13674
5.59k
    std::string_view host_view(_host.data(), _host.length());
13675
5.59k
    auto [location, found_colon] =
13676
5.59k
        helpers::get_host_delimiter_location(is_special(), host_view);
13677
13678
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13679
    // Note: the 'found_colon' value is true if and only if a colon was
13680
    // encountered while not inside brackets.
13681
5.59k
    if (found_colon) {
13682
188
      if (override_hostname) {
13683
0
        return false;
13684
0
      }
13685
188
      std::string_view sub_buffer = new_host.substr(location + 1);
13686
188
      if (!sub_buffer.empty()) {
13687
158
        set_port(sub_buffer);
13688
158
      }
13689
188
    }
13690
    // If url is special and host_view is the empty string, validation error,
13691
    // return failure. Otherwise, if state override is given, host_view is the
13692
    // empty string, and either url includes credentials or url's port is
13693
    // non-null, return.
13694
5.40k
    else if (host_view.empty() &&
13695
5.40k
             (is_special() || has_credentials() || has_port())) {
13696
3.16k
      return false;
13697
3.16k
    }
13698
13699
    // Let host be the result of host parsing host_view with url is not special.
13700
2.43k
    if (host_view.empty() && !is_special()) {
13701
1.36k
      if (has_hostname()) {
13702
156
        clear_hostname();  // easy!
13703
1.21k
      } else if (has_dash_dot()) {
13704
1
        add_authority_slashes_if_needed();
13705
1
        delete_dash_dot();
13706
1
      }
13707
1.36k
      return true;
13708
1.36k
    }
13709
13710
1.06k
    bool succeeded = parse_host(host_view);
13711
1.06k
    if (!succeeded) {
13712
404
      update_base_hostname(previous_host);
13713
404
      update_base_port(previous_port);
13714
662
    } else if (has_dash_dot()) {
13715
      // Should remove dash_dot from pathname
13716
12
      delete_dash_dot();
13717
12
    }
13718
1.06k
    return succeeded;
13719
2.43k
  }
13720
13721
1.59k
  size_t location = new_host.find_first_of("/\\?");
13722
1.59k
  if (location != std::string_view::npos) {
13723
19
    new_host.remove_suffix(new_host.length() - location);
13724
19
  }
13725
13726
1.59k
  if (new_host.empty()) {
13727
    // Set url's host to the empty string.
13728
1.19k
    clear_hostname();
13729
1.19k
  } else {
13730
    // Let host be the result of host parsing buffer with url is not special.
13731
394
    if (!parse_host(new_host)) {
13732
70
      update_base_hostname(previous_host);
13733
70
      update_base_port(previous_port);
13734
70
      return false;
13735
70
    }
13736
13737
    // If host is "localhost", then set host to the empty string.
13738
324
    if (helpers::substring(buffer, components.host_start,
13739
324
                           components.host_end) == "localhost") {
13740
18
      clear_hostname();
13741
18
    }
13742
324
  }
13743
1.52k
  ADA_ASSERT_TRUE(validate());
13744
1.52k
  return true;
13745
1.59k
}
bool ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
13653
9.07k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
13654
9.07k
  ada_log("url_aggregator::set_host_or_hostname ", input);
13655
9.07k
  ADA_ASSERT_TRUE(validate());
13656
9.07k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13657
9.07k
  if (has_opaque_path) {
13658
1.02k
    return false;
13659
1.02k
  }
13660
13661
8.05k
  std::string previous_host = std::string(get_hostname());
13662
8.05k
  uint32_t previous_port = components.port;
13663
13664
8.05k
  size_t host_end_pos = input.find('#');
13665
8.05k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
13666
8.05k
                                      ? host_end_pos
13667
8.05k
                                      : input.size());
13668
8.05k
  helpers::remove_ascii_tab_or_newline(_host);
13669
8.05k
  std::string_view new_host(_host);
13670
13671
  // If url's scheme is "file", then set state to file host state, instead of
13672
  // host state.
13673
8.05k
  if (type != ada::scheme::type::FILE) {
13674
6.33k
    std::string_view host_view(_host.data(), _host.length());
13675
6.33k
    auto [location, found_colon] =
13676
6.33k
        helpers::get_host_delimiter_location(is_special(), host_view);
13677
13678
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13679
    // Note: the 'found_colon' value is true if and only if a colon was
13680
    // encountered while not inside brackets.
13681
6.33k
    if (found_colon) {
13682
188
      if (override_hostname) {
13683
188
        return false;
13684
188
      }
13685
0
      std::string_view sub_buffer = new_host.substr(location + 1);
13686
0
      if (!sub_buffer.empty()) {
13687
0
        set_port(sub_buffer);
13688
0
      }
13689
0
    }
13690
    // If url is special and host_view is the empty string, validation error,
13691
    // return failure. Otherwise, if state override is given, host_view is the
13692
    // empty string, and either url includes credentials or url's port is
13693
    // non-null, return.
13694
6.14k
    else if (host_view.empty() &&
13695
6.14k
             (is_special() || has_credentials() || has_port())) {
13696
3.16k
      return false;
13697
3.16k
    }
13698
13699
    // Let host be the result of host parsing host_view with url is not special.
13700
2.97k
    if (host_view.empty() && !is_special()) {
13701
1.45k
      if (has_hostname()) {
13702
104
        clear_hostname();  // easy!
13703
1.35k
      } else if (has_dash_dot()) {
13704
37
        add_authority_slashes_if_needed();
13705
37
        delete_dash_dot();
13706
37
      }
13707
1.45k
      return true;
13708
1.45k
    }
13709
13710
1.52k
    bool succeeded = parse_host(host_view);
13711
1.52k
    if (!succeeded) {
13712
328
      update_base_hostname(previous_host);
13713
328
      update_base_port(previous_port);
13714
1.19k
    } else if (has_dash_dot()) {
13715
      // Should remove dash_dot from pathname
13716
1
      delete_dash_dot();
13717
1
    }
13718
1.52k
    return succeeded;
13719
2.97k
  }
13720
13721
1.71k
  size_t location = new_host.find_first_of("/\\?");
13722
1.71k
  if (location != std::string_view::npos) {
13723
19
    new_host.remove_suffix(new_host.length() - location);
13724
19
  }
13725
13726
1.71k
  if (new_host.empty()) {
13727
    // Set url's host to the empty string.
13728
1.27k
    clear_hostname();
13729
1.27k
  } else {
13730
    // Let host be the result of host parsing buffer with url is not special.
13731
444
    if (!parse_host(new_host)) {
13732
70
      update_base_hostname(previous_host);
13733
70
      update_base_port(previous_port);
13734
70
      return false;
13735
70
    }
13736
13737
    // If host is "localhost", then set host to the empty string.
13738
374
    if (helpers::substring(buffer, components.host_start,
13739
374
                           components.host_end) == "localhost") {
13740
18
      clear_hostname();
13741
18
    }
13742
374
  }
13743
1.64k
  ADA_ASSERT_TRUE(validate());
13744
1.64k
  return true;
13745
1.71k
}
13746
13747
8.20k
bool url_aggregator::set_host(const std::string_view input) {
13748
8.20k
  ada_log("url_aggregator::set_host '", input, "'");
13749
8.20k
  ADA_ASSERT_TRUE(validate());
13750
8.20k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13751
8.20k
  return set_host_or_hostname<false>(input);
13752
8.20k
}
13753
13754
9.07k
bool url_aggregator::set_hostname(const std::string_view input) {
13755
9.07k
  ada_log("url_aggregator::set_hostname '", input, "'");
13756
9.07k
  ADA_ASSERT_TRUE(validate());
13757
9.07k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13758
9.07k
  return set_host_or_hostname<true>(input);
13759
9.07k
}
13760
13761
7.98k
[[nodiscard]] std::string url_aggregator::get_origin() const noexcept {
13762
7.98k
  ada_log("url_aggregator::get_origin");
13763
7.98k
  if (is_special()) {
13764
    // Return a new opaque origin.
13765
5.24k
    if (type == scheme::FILE) {
13766
1.37k
      return "null";
13767
1.37k
    }
13768
13769
3.87k
    return helpers::concat(get_protocol(), "//", get_host());
13770
5.24k
  }
13771
13772
2.74k
  if (get_protocol() == "blob:") {
13773
406
    std::string_view path = get_pathname();
13774
406
    if (!path.empty()) {
13775
404
      auto out = ada::parse<ada::url_aggregator>(path);
13776
404
      if (out && (out->type == scheme::HTTP || out->type == scheme::HTTPS)) {
13777
        // If pathURL's scheme is not "http" and not "https", then return a
13778
        // new opaque origin.
13779
13
        return helpers::concat(out->get_protocol(), "//", out->get_host());
13780
13
      }
13781
404
    }
13782
406
  }
13783
13784
  // Return a new opaque origin.
13785
2.72k
  return "null";
13786
2.74k
}
13787
13788
7.98k
[[nodiscard]] std::string_view url_aggregator::get_username() const noexcept {
13789
7.98k
  ada_log("url_aggregator::get_username");
13790
7.98k
  if (has_non_empty_username()) {
13791
877
    return helpers::substring(buffer, components.protocol_end + 2,
13792
877
                              components.username_end);
13793
877
  }
13794
7.11k
  return "";
13795
7.98k
}
13796
13797
7.98k
[[nodiscard]] std::string_view url_aggregator::get_password() const noexcept {
13798
7.98k
  ada_log("url_aggregator::get_password");
13799
7.98k
  if (has_non_empty_password()) {
13800
877
    return helpers::substring(buffer, components.username_end + 1,
13801
877
                              components.host_start);
13802
877
  }
13803
7.11k
  return "";
13804
7.98k
}
13805
13806
7.98k
[[nodiscard]] std::string_view url_aggregator::get_port() const noexcept {
13807
7.98k
  ada_log("url_aggregator::get_port");
13808
7.98k
  if (components.port == url_components::omitted) {
13809
7.72k
    return "";
13810
7.72k
  }
13811
266
  return helpers::substring(buffer, components.host_end + 1,
13812
266
                            components.pathname_start);
13813
7.98k
}
13814
13815
7.98k
[[nodiscard]] std::string_view url_aggregator::get_hash() const noexcept {
13816
7.98k
  ada_log("url_aggregator::get_hash");
13817
  // If this's URL's fragment is either null or the empty string, then return
13818
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
13819
7.98k
  if (components.hash_start == url_components::omitted) {
13820
6.43k
    return "";
13821
6.43k
  }
13822
1.55k
  if (buffer.size() - components.hash_start <= 1) {
13823
57
    return "";
13824
57
  }
13825
1.49k
  return helpers::substring(buffer, components.hash_start);
13826
1.55k
}
13827
13828
12.0k
[[nodiscard]] std::string_view url_aggregator::get_host() const noexcept {
13829
12.0k
  ada_log("url_aggregator::get_host");
13830
  // Technically, we should check if there is a hostname, but
13831
  // the code below works even if there isn't.
13832
  // if(!has_hostname()) { return ""; }
13833
12.0k
  size_t start = components.host_start;
13834
12.0k
  if (components.host_end > components.host_start &&
13835
12.0k
      buffer[components.host_start] == '@') {
13836
1.63k
    start++;
13837
1.63k
  }
13838
  // if we have an empty host, then the space between components.host_end and
13839
  // components.pathname_start may be occupied by /.
13840
12.0k
  if (start == components.host_end) {
13841
3.78k
    return std::string_view();
13842
3.78k
  }
13843
8.31k
  return helpers::substring(buffer, start, components.pathname_start);
13844
12.0k
}
13845
13846
43.2k
[[nodiscard]] std::string_view url_aggregator::get_hostname() const noexcept {
13847
43.2k
  ada_log("url_aggregator::get_hostname");
13848
  // Technically, we should check if there is a hostname, but
13849
  // the code below works even if there isn't.
13850
  // if(!has_hostname()) { return ""; }
13851
43.2k
  size_t start = components.host_start;
13852
  // So host_start is not where the host begins.
13853
43.2k
  if (components.host_end > components.host_start &&
13854
43.2k
      buffer[components.host_start] == '@') {
13855
4.41k
    start++;
13856
4.41k
  }
13857
43.2k
  return helpers::substring(buffer, start, components.host_end);
13858
43.2k
}
13859
13860
15.2k
[[nodiscard]] std::string_view url_aggregator::get_pathname() const noexcept {
13861
15.2k
  ada_log("url_aggregator::get_pathname pathname_start = ",
13862
15.2k
          components.pathname_start, " buffer.size() = ", buffer.size(),
13863
15.2k
          " components.search_start = ", components.search_start,
13864
15.2k
          " components.hash_start = ", components.hash_start);
13865
15.2k
  uint32_t ending_index = uint32_t(buffer.size());
13866
15.2k
  if (components.search_start != url_components::omitted) {
13867
1.75k
    ending_index = components.search_start;
13868
13.4k
  } else if (components.hash_start != url_components::omitted) {
13869
141
    ending_index = components.hash_start;
13870
141
  }
13871
15.2k
  return helpers::substring(buffer, components.pathname_start, ending_index);
13872
15.2k
}
13873
13874
9.06k
[[nodiscard]] std::string_view url_aggregator::get_search() const noexcept {
13875
9.06k
  ada_log("url_aggregator::get_search");
13876
  // If this's URL's query is either null or the empty string, then return the
13877
  // empty string. Return U+003F (?), followed by this's URL's query.
13878
9.06k
  if (components.search_start == url_components::omitted) {
13879
7.44k
    return "";
13880
7.44k
  }
13881
1.62k
  uint32_t ending_index = uint32_t(buffer.size());
13882
1.62k
  if (components.hash_start != url_components::omitted) {
13883
1.57k
    ending_index = components.hash_start;
13884
1.57k
  }
13885
1.62k
  if (ending_index - components.search_start <= 1) {
13886
100
    return "";
13887
100
  }
13888
1.52k
  return helpers::substring(buffer, components.search_start, ending_index);
13889
1.62k
}
13890
13891
15.3k
[[nodiscard]] std::string_view url_aggregator::get_protocol() const noexcept {
13892
15.3k
  ada_log("url_aggregator::get_protocol");
13893
15.3k
  return helpers::substring(buffer, 0, components.protocol_end);
13894
15.3k
}
13895
13896
0
[[nodiscard]] std::string ada::url_aggregator::to_string() const {
13897
0
  ada_log("url_aggregator::to_string buffer:", buffer, "[", buffer.size(),
13898
0
          " bytes]");
13899
0
  if (!is_valid) {
13900
0
    return "null";
13901
0
  }
13902
13903
0
  std::string answer;
13904
0
  auto back = std::back_insert_iterator(answer);
13905
0
  answer.append("{\n");
13906
13907
0
  answer.append("\t\"buffer\":\"");
13908
0
  helpers::encode_json(buffer, back);
13909
0
  answer.append("\",\n");
13910
13911
0
  answer.append("\t\"protocol\":\"");
13912
0
  helpers::encode_json(get_protocol(), back);
13913
0
  answer.append("\",\n");
13914
13915
0
  if (has_credentials()) {
13916
0
    answer.append("\t\"username\":\"");
13917
0
    helpers::encode_json(get_username(), back);
13918
0
    answer.append("\",\n");
13919
0
    answer.append("\t\"password\":\"");
13920
0
    helpers::encode_json(get_password(), back);
13921
0
    answer.append("\",\n");
13922
0
  }
13923
13924
0
  answer.append("\t\"host\":\"");
13925
0
  helpers::encode_json(get_host(), back);
13926
0
  answer.append("\",\n");
13927
13928
0
  answer.append("\t\"path\":\"");
13929
0
  helpers::encode_json(get_pathname(), back);
13930
0
  answer.append("\",\n");
13931
0
  answer.append("\t\"opaque path\":");
13932
0
  answer.append((has_opaque_path ? "true" : "false"));
13933
0
  answer.append(",\n");
13934
13935
0
  if (components.search_start != url_components::omitted) {
13936
0
    answer.append("\t\"query\":\"");
13937
0
    helpers::encode_json(get_search(), back);
13938
0
    answer.append("\",\n");
13939
0
  }
13940
0
  if (components.hash_start != url_components::omitted) {
13941
0
    answer.append("\t\"fragment\":\"");
13942
0
    helpers::encode_json(get_hash(), back);
13943
0
    answer.append("\",\n");
13944
0
  }
13945
13946
0
  auto convert_offset_to_string = [](uint32_t offset) -> std::string {
13947
0
    if (offset == url_components::omitted) {
13948
0
      return "null";
13949
0
    } else {
13950
0
      return std::to_string(offset);
13951
0
    }
13952
0
  };
13953
13954
0
  answer.append("\t\"protocol_end\":");
13955
0
  answer.append(convert_offset_to_string(components.protocol_end));
13956
0
  answer.append(",\n");
13957
13958
0
  answer.append("\t\"username_end\":");
13959
0
  answer.append(convert_offset_to_string(components.username_end));
13960
0
  answer.append(",\n");
13961
13962
0
  answer.append("\t\"host_start\":");
13963
0
  answer.append(convert_offset_to_string(components.host_start));
13964
0
  answer.append(",\n");
13965
13966
0
  answer.append("\t\"host_end\":");
13967
0
  answer.append(convert_offset_to_string(components.host_end));
13968
0
  answer.append(",\n");
13969
13970
0
  answer.append("\t\"port\":");
13971
0
  answer.append(convert_offset_to_string(components.port));
13972
0
  answer.append(",\n");
13973
13974
0
  answer.append("\t\"pathname_start\":");
13975
0
  answer.append(convert_offset_to_string(components.pathname_start));
13976
0
  answer.append(",\n");
13977
13978
0
  answer.append("\t\"search_start\":");
13979
0
  answer.append(convert_offset_to_string(components.search_start));
13980
0
  answer.append(",\n");
13981
13982
0
  answer.append("\t\"hash_start\":");
13983
0
  answer.append(convert_offset_to_string(components.hash_start));
13984
0
  answer.append("\n}");
13985
13986
0
  return answer;
13987
0
}
13988
13989
0
[[nodiscard]] bool url_aggregator::has_valid_domain() const noexcept {
13990
0
  if (components.host_start == components.host_end) {
13991
0
    return false;
13992
0
  }
13993
0
  return checkers::verify_dns_length(get_hostname());
13994
0
}
13995
13996
3.82k
bool url_aggregator::parse_ipv4(std::string_view input) {
13997
3.82k
  ada_log("parse_ipv4 ", input, "[", input.size(),
13998
3.82k
          " bytes], overlaps with buffer: ",
13999
3.82k
          helpers::overlaps(input, buffer) ? "yes" : "no");
14000
3.82k
  ADA_ASSERT_TRUE(validate());
14001
3.82k
  const bool trailing_dot = (input.back() == '.');
14002
3.82k
  if (trailing_dot) {
14003
42
    input.remove_suffix(1);
14004
42
  }
14005
3.82k
  size_t digit_count{0};
14006
3.82k
  int pure_decimal_count = 0;  // entries that are decimal
14007
3.82k
  uint64_t ipv4{0};
14008
  // we could unroll for better performance?
14009
5.08k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
14010
5.05k
    uint32_t
14011
5.05k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
14012
5.05k
    bool is_hex = checkers::has_hex_prefix(input);
14013
5.05k
    if (is_hex && ((input.length() == 2) ||
14014
1.36k
                   ((input.length() > 2) && (input[2] == '.')))) {
14015
      // special case
14016
132
      segment_result = 0;
14017
132
      input.remove_prefix(2);
14018
4.91k
    } else {
14019
4.91k
      std::from_chars_result r;
14020
4.91k
      if (is_hex) {
14021
1.23k
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
14022
1.23k
                            segment_result, 16);
14023
3.68k
      } else if ((input.length() >= 2) && input[0] == '0' &&
14024
3.68k
                 checkers::is_digit(input[1])) {
14025
490
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
14026
490
                            segment_result, 8);
14027
3.19k
      } else {
14028
3.19k
        pure_decimal_count++;
14029
3.19k
        r = std::from_chars(input.data(), input.data() + input.size(),
14030
3.19k
                            segment_result, 10);
14031
3.19k
      }
14032
4.91k
      if (r.ec != std::errc()) {
14033
743
        return is_valid = false;
14034
743
      }
14035
4.17k
      input.remove_prefix(r.ptr - input.data());
14036
4.17k
    }
14037
4.30k
    if (input.empty()) {
14038
      // We have the last value.
14039
      // At this stage, ipv4 contains digit_count*8 bits.
14040
      // So we have 32-digit_count*8 bits left.
14041
2.82k
      if (segment_result > (uint64_t(1) << (32 - digit_count * 8))) {
14042
23
        return is_valid = false;
14043
23
      }
14044
2.80k
      ipv4 <<= (32 - digit_count * 8);
14045
2.80k
      ipv4 |= segment_result;
14046
2.80k
      goto final;
14047
2.82k
    } else {
14048
      // There is more, so that the value must no be larger than 255
14049
      // and we must have a '.'.
14050
1.48k
      if ((segment_result > 255) || (input[0] != '.')) {
14051
214
        return is_valid = false;
14052
214
      }
14053
1.26k
      ipv4 <<= 8;
14054
1.26k
      ipv4 |= segment_result;
14055
1.26k
      input.remove_prefix(1);  // remove '.'
14056
1.26k
    }
14057
4.30k
  }
14058
39
  if ((digit_count != 4) || (!input.empty())) {
14059
39
    return is_valid = false;
14060
39
  }
14061
2.80k
final:
14062
2.80k
  ada_log("url_aggregator::parse_ipv4 completed ", get_href(),
14063
2.80k
          " host: ", get_host());
14064
14065
  // We could also check r.ptr to see where the parsing ended.
14066
2.80k
  if (pure_decimal_count == 4 && !trailing_dot) {
14067
    // The original input was already all decimal and we validated it. So we
14068
    // don't need to do anything.
14069
2.57k
  } else {
14070
    // Optimization opportunity: Get rid of unnecessary string return in ipv4
14071
    // serializer.
14072
    // TODO: This is likely a bug because it goes back update_base_hostname, not
14073
    // what we want to do.
14074
2.57k
    update_base_hostname(
14075
2.57k
        ada::serializers::ipv4(ipv4));  // We have to reserialize the address.
14076
2.57k
  }
14077
2.80k
  host_type = IPV4;
14078
2.80k
  ADA_ASSERT_TRUE(validate());
14079
2.80k
  return true;
14080
39
}
14081
14082
959
bool url_aggregator::parse_ipv6(std::string_view input) {
14083
  // TODO: Find a way to merge parse_ipv6 with url.cpp implementation.
14084
959
  ada_log("parse_ipv6 ", input, "[", input.size(), " bytes]");
14085
959
  ADA_ASSERT_TRUE(validate());
14086
959
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14087
959
  if (input.empty()) {
14088
66
    return is_valid = false;
14089
66
  }
14090
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
14091
893
  std::array<uint16_t, 8> address{};
14092
14093
  // Let pieceIndex be 0.
14094
893
  int piece_index = 0;
14095
14096
  // Let compress be null.
14097
893
  std::optional<int> compress{};
14098
14099
  // Let pointer be a pointer for input.
14100
893
  std::string_view::iterator pointer = input.begin();
14101
14102
  // If c is U+003A (:), then:
14103
893
  if (input[0] == ':') {
14104
    // If remaining does not start with U+003A (:), validation error, return
14105
    // failure.
14106
246
    if (input.size() == 1 || input[1] != ':') {
14107
32
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
14108
32
      return is_valid = false;
14109
32
    }
14110
14111
    // Increase pointer by 2.
14112
214
    pointer += 2;
14113
14114
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
14115
214
    compress = ++piece_index;
14116
214
  }
14117
14118
  // While c is not the EOF code point:
14119
2.59k
  while (pointer != input.end()) {
14120
    // If pieceIndex is 8, validation error, return failure.
14121
2.12k
    if (piece_index == 8) {
14122
8
      ada_log("parse_ipv6 piece_index == 8");
14123
8
      return is_valid = false;
14124
8
    }
14125
14126
    // If c is U+003A (:), then:
14127
2.11k
    if (*pointer == ':') {
14128
      // If compress is non-null, validation error, return failure.
14129
175
      if (compress.has_value()) {
14130
9
        ada_log("parse_ipv6 compress is non-null");
14131
9
        return is_valid = false;
14132
9
      }
14133
14134
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
14135
      // then continue.
14136
166
      pointer++;
14137
166
      compress = ++piece_index;
14138
166
      continue;
14139
175
    }
14140
14141
    // Let value and length be 0.
14142
1.94k
    uint16_t value = 0, length = 0;
14143
14144
    // While length is less than 4 and c is an ASCII hex digit,
14145
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
14146
    // increase pointer and length by 1.
14147
5.04k
    while (length < 4 && pointer != input.end() &&
14148
5.04k
           unicode::is_ascii_hex_digit(*pointer)) {
14149
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
14150
3.10k
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
14151
3.10k
      pointer++;
14152
3.10k
      length++;
14153
3.10k
    }
14154
14155
    // If c is U+002E (.), then:
14156
1.94k
    if (pointer != input.end() && *pointer == '.') {
14157
      // If length is 0, validation error, return failure.
14158
174
      if (length == 0) {
14159
8
        ada_log("parse_ipv6 length is 0");
14160
8
        return is_valid = false;
14161
8
      }
14162
14163
      // Decrease pointer by length.
14164
166
      pointer -= length;
14165
14166
      // If pieceIndex is greater than 6, validation error, return failure.
14167
166
      if (piece_index > 6) {
14168
6
        ada_log("parse_ipv6 piece_index > 6");
14169
6
        return is_valid = false;
14170
6
      }
14171
14172
      // Let numbersSeen be 0.
14173
160
      int numbers_seen = 0;
14174
14175
      // While c is not the EOF code point:
14176
491
      while (pointer != input.end()) {
14177
        // Let ipv4Piece be null.
14178
427
        std::optional<uint16_t> ipv4_piece{};
14179
14180
        // If numbersSeen is greater than 0, then:
14181
427
        if (numbers_seen > 0) {
14182
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
14183
          // pointer by 1.
14184
267
          if (*pointer == '.' && numbers_seen < 4) {
14185
245
            pointer++;
14186
245
          } else {
14187
            // Otherwise, validation error, return failure.
14188
22
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
14189
22
            return is_valid = false;
14190
22
          }
14191
267
        }
14192
14193
        // If c is not an ASCII digit, validation error, return failure.
14194
405
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
14195
49
          ada_log(
14196
49
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
14197
49
              "failure");
14198
49
          return is_valid = false;
14199
49
        }
14200
14201
        // While c is an ASCII digit:
14202
844
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
14203
          // Let number be c interpreted as decimal number.
14204
513
          int number = *pointer - '0';
14205
14206
          // If ipv4Piece is null, then set ipv4Piece to number.
14207
513
          if (!ipv4_piece.has_value()) {
14208
356
            ipv4_piece = number;
14209
356
          }
14210
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
14211
157
          else if (ipv4_piece == 0) {
14212
6
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
14213
6
            return is_valid = false;
14214
6
          }
14215
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
14216
151
          else {
14217
151
            ipv4_piece = *ipv4_piece * 10 + number;
14218
151
          }
14219
14220
          // If ipv4Piece is greater than 255, validation error, return failure.
14221
507
          if (ipv4_piece > 255) {
14222
19
            ada_log("parse_ipv6 ipv4_piece > 255");
14223
19
            return is_valid = false;
14224
19
          }
14225
14226
          // Increase pointer by 1.
14227
488
          pointer++;
14228
488
        }
14229
14230
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
14231
        // ipv4Piece.
14232
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
14233
331
        address[piece_index] =
14234
331
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
14235
14236
        // Increase numbersSeen by 1.
14237
331
        numbers_seen++;
14238
14239
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
14240
331
        if (numbers_seen == 2 || numbers_seen == 4) {
14241
142
          piece_index++;
14242
142
        }
14243
331
      }
14244
14245
      // If numbersSeen is not 4, validation error, return failure.
14246
64
      if (numbers_seen != 4) {
14247
20
        return is_valid = false;
14248
20
      }
14249
14250
      // Break.
14251
44
      break;
14252
64
    }
14253
    // Otherwise, if c is U+003A (:):
14254
1.76k
    else if ((pointer != input.end()) && (*pointer == ':')) {
14255
      // Increase pointer by 1.
14256
1.23k
      pointer++;
14257
14258
      // If c is the EOF code point, validation error, return failure.
14259
1.23k
      if (pointer == input.end()) {
14260
6
        ada_log(
14261
6
            "parse_ipv6 If c is the EOF code point, validation error, return "
14262
6
            "failure");
14263
6
        return is_valid = false;
14264
6
      }
14265
1.23k
    }
14266
    // Otherwise, if c is not the EOF code point, validation error, return
14267
    // failure.
14268
533
    else if (pointer != input.end()) {
14269
195
      ada_log(
14270
195
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
14271
195
          "error, return failure");
14272
195
      return is_valid = false;
14273
195
    }
14274
14275
    // Set address[pieceIndex] to value.
14276
1.56k
    address[piece_index] = value;
14277
14278
    // Increase pieceIndex by 1.
14279
1.56k
    piece_index++;
14280
1.56k
  }
14281
14282
  // If compress is non-null, then:
14283
513
  if (compress.has_value()) {
14284
    // Let swaps be pieceIndex - compress.
14285
358
    int swaps = piece_index - *compress;
14286
14287
    // Set pieceIndex to 7.
14288
358
    piece_index = 7;
14289
14290
    // While pieceIndex is not 0 and swaps is greater than 0,
14291
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
14292
    // decrease both pieceIndex and swaps by 1.
14293
913
    while (piece_index != 0 && swaps > 0) {
14294
555
      std::swap(address[piece_index], address[*compress + swaps - 1]);
14295
555
      piece_index--;
14296
555
      swaps--;
14297
555
    }
14298
358
  }
14299
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
14300
  // return failure.
14301
155
  else if (piece_index != 8) {
14302
106
    ada_log(
14303
106
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
14304
106
        "error, return failure");
14305
106
    return is_valid = false;
14306
106
  }
14307
  // TODO: Optimization opportunity: Get rid of unnecessary string creation.
14308
  // TODO: This is likely a bug because it goes back update_base_hostname, not
14309
  // what we want to do.
14310
407
  update_base_hostname(ada::serializers::ipv6(address));
14311
407
  ada_log("parse_ipv6 ", get_hostname());
14312
407
  ADA_ASSERT_TRUE(validate());
14313
407
  host_type = IPV6;
14314
407
  return true;
14315
513
}
14316
14317
1.13k
bool url_aggregator::parse_opaque_host(std::string_view input) {
14318
1.13k
  ada_log("parse_opaque_host ", input, "[", input.size(), " bytes]");
14319
1.13k
  ADA_ASSERT_TRUE(validate());
14320
1.13k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14321
1.13k
  if (std::any_of(input.begin(), input.end(),
14322
1.13k
                  ada::unicode::is_forbidden_host_code_point)) {
14323
115
    return is_valid = false;
14324
115
  }
14325
14326
  // Return the result of running UTF-8 percent-encode on input using the C0
14327
  // control percent-encode set.
14328
1.02k
  size_t idx = ada::unicode::percent_encode_index(
14329
1.02k
      input, character_sets::C0_CONTROL_PERCENT_ENCODE);
14330
1.02k
  if (idx == input.size()) {
14331
515
    update_base_hostname(input);
14332
515
  } else {
14333
    // We only create a temporary string if we need to.
14334
508
    update_base_hostname(ada::unicode::percent_encode(
14335
508
        input, character_sets::C0_CONTROL_PERCENT_ENCODE, idx));
14336
508
  }
14337
1.02k
  ADA_ASSERT_TRUE(validate());
14338
1.02k
  return true;
14339
1.13k
}
14340
14341
0
[[nodiscard]] std::string url_aggregator::to_diagram() const {
14342
0
  if (!is_valid) {
14343
0
    return "invalid";
14344
0
  }
14345
0
  std::string answer;
14346
0
  answer.append(buffer);
14347
0
  answer.append(" [");
14348
0
  answer.append(std::to_string(buffer.size()));
14349
0
  answer.append(" bytes]");
14350
0
  answer.append("\n");
14351
  // first line
14352
0
  std::string line1;
14353
0
  line1.resize(buffer.size(), ' ');
14354
0
  if (components.hash_start != url_components::omitted) {
14355
0
    line1[components.hash_start] = '|';
14356
0
  }
14357
0
  if (components.search_start != url_components::omitted) {
14358
0
    line1[components.search_start] = '|';
14359
0
  }
14360
0
  if (components.pathname_start != buffer.size()) {
14361
0
    line1[components.pathname_start] = '|';
14362
0
  }
14363
0
  if (components.host_end != buffer.size()) {
14364
0
    line1[components.host_end] = '|';
14365
0
  }
14366
0
  if (components.host_start != buffer.size()) {
14367
0
    line1[components.host_start] = '|';
14368
0
  }
14369
0
  if (components.username_end != buffer.size()) {
14370
0
    line1[components.username_end] = '|';
14371
0
  }
14372
0
  if (components.protocol_end != buffer.size()) {
14373
0
    line1[components.protocol_end] = '|';
14374
0
  }
14375
0
  answer.append(line1);
14376
0
  answer.append("\n");
14377
14378
0
  std::string line2 = line1;
14379
0
  if (components.hash_start != url_components::omitted) {
14380
0
    line2[components.hash_start] = '`';
14381
0
    line1[components.hash_start] = ' ';
14382
14383
0
    for (size_t i = components.hash_start + 1; i < line2.size(); i++) {
14384
0
      line2[i] = '-';
14385
0
    }
14386
0
    line2.append(" hash_start");
14387
0
    answer.append(line2);
14388
0
    answer.append("\n");
14389
0
  }
14390
14391
0
  std::string line3 = line1;
14392
0
  if (components.search_start != url_components::omitted) {
14393
0
    line3[components.search_start] = '`';
14394
0
    line1[components.search_start] = ' ';
14395
14396
0
    for (size_t i = components.search_start + 1; i < line3.size(); i++) {
14397
0
      line3[i] = '-';
14398
0
    }
14399
0
    line3.append(" search_start ");
14400
0
    line3.append(std::to_string(components.search_start));
14401
0
    answer.append(line3);
14402
0
    answer.append("\n");
14403
0
  }
14404
14405
0
  std::string line4 = line1;
14406
0
  if (components.pathname_start != buffer.size()) {
14407
0
    line4[components.pathname_start] = '`';
14408
0
    line1[components.pathname_start] = ' ';
14409
0
    for (size_t i = components.pathname_start + 1; i < line4.size(); i++) {
14410
0
      line4[i] = '-';
14411
0
    }
14412
0
    line4.append(" pathname_start ");
14413
0
    line4.append(std::to_string(components.pathname_start));
14414
0
    answer.append(line4);
14415
0
    answer.append("\n");
14416
0
  }
14417
14418
0
  std::string line5 = line1;
14419
0
  if (components.host_end != buffer.size()) {
14420
0
    line5[components.host_end] = '`';
14421
0
    line1[components.host_end] = ' ';
14422
14423
0
    for (size_t i = components.host_end + 1; i < line5.size(); i++) {
14424
0
      line5[i] = '-';
14425
0
    }
14426
0
    line5.append(" host_end ");
14427
0
    line5.append(std::to_string(components.host_end));
14428
0
    answer.append(line5);
14429
0
    answer.append("\n");
14430
0
  }
14431
14432
0
  std::string line6 = line1;
14433
0
  if (components.host_start != buffer.size()) {
14434
0
    line6[components.host_start] = '`';
14435
0
    line1[components.host_start] = ' ';
14436
14437
0
    for (size_t i = components.host_start + 1; i < line6.size(); i++) {
14438
0
      line6[i] = '-';
14439
0
    }
14440
0
    line6.append(" host_start ");
14441
0
    line6.append(std::to_string(components.host_start));
14442
0
    answer.append(line6);
14443
0
    answer.append("\n");
14444
0
  }
14445
14446
0
  std::string line7 = line1;
14447
0
  if (components.username_end != buffer.size()) {
14448
0
    line7[components.username_end] = '`';
14449
0
    line1[components.username_end] = ' ';
14450
14451
0
    for (size_t i = components.username_end + 1; i < line7.size(); i++) {
14452
0
      line7[i] = '-';
14453
0
    }
14454
0
    line7.append(" username_end ");
14455
0
    line7.append(std::to_string(components.username_end));
14456
0
    answer.append(line7);
14457
0
    answer.append("\n");
14458
0
  }
14459
14460
0
  std::string line8 = line1;
14461
0
  if (components.protocol_end != buffer.size()) {
14462
0
    line8[components.protocol_end] = '`';
14463
0
    line1[components.protocol_end] = ' ';
14464
14465
0
    for (size_t i = components.protocol_end + 1; i < line8.size(); i++) {
14466
0
      line8[i] = '-';
14467
0
    }
14468
0
    line8.append(" protocol_end ");
14469
0
    line8.append(std::to_string(components.protocol_end));
14470
0
    answer.append(line8);
14471
0
    answer.append("\n");
14472
0
  }
14473
14474
0
  if (components.hash_start == url_components::omitted) {
14475
0
    answer.append("note: hash omitted\n");
14476
0
  }
14477
0
  if (components.search_start == url_components::omitted) {
14478
0
    answer.append("note: search omitted\n");
14479
0
  }
14480
0
  if (components.protocol_end > buffer.size()) {
14481
0
    answer.append("warning: protocol_end overflows\n");
14482
0
  }
14483
0
  if (components.username_end > buffer.size()) {
14484
0
    answer.append("warning: username_end overflows\n");
14485
0
  }
14486
0
  if (components.host_start > buffer.size()) {
14487
0
    answer.append("warning: host_start overflows\n");
14488
0
  }
14489
0
  if (components.host_end > buffer.size()) {
14490
0
    answer.append("warning: host_end overflows\n");
14491
0
  }
14492
0
  if (components.pathname_start > buffer.size()) {
14493
0
    answer.append("warning: pathname_start overflows\n");
14494
0
  }
14495
0
  return answer;
14496
0
}
14497
14498
0
[[nodiscard]] bool url_aggregator::validate() const noexcept {
14499
0
  if (!is_valid) {
14500
0
    return true;
14501
0
  }
14502
0
  if (!components.check_offset_consistency()) {
14503
0
    ada_log("url_aggregator::validate inconsistent components \n",
14504
0
            to_diagram());
14505
0
    return false;
14506
0
  }
14507
  // We have a credible components struct, but let us investivate more
14508
  // carefully:
14509
  /**
14510
   * https://user:pass@example.com:1234/foo/bar?baz#quux
14511
   *       |     |    |          | ^^^^|       |   |
14512
   *       |     |    |          | |   |       |   `----- hash_start
14513
   *       |     |    |          | |   |       `--------- search_start
14514
   *       |     |    |          | |   `----------------- pathname_start
14515
   *       |     |    |          | `--------------------- port
14516
   *       |     |    |          `----------------------- host_end
14517
   *       |     |    `---------------------------------- host_start
14518
   *       |     `--------------------------------------- username_end
14519
   *       `--------------------------------------------- protocol_end
14520
   */
14521
0
  if (components.protocol_end == url_components::omitted) {
14522
0
    ada_log("url_aggregator::validate omitted protocol_end \n", to_diagram());
14523
0
    return false;
14524
0
  }
14525
0
  if (components.username_end == url_components::omitted) {
14526
0
    ada_log("url_aggregator::validate omitted username_end \n", to_diagram());
14527
0
    return false;
14528
0
  }
14529
0
  if (components.host_start == url_components::omitted) {
14530
0
    ada_log("url_aggregator::validate omitted host_start \n", to_diagram());
14531
0
    return false;
14532
0
  }
14533
0
  if (components.host_end == url_components::omitted) {
14534
0
    ada_log("url_aggregator::validate omitted host_end \n", to_diagram());
14535
0
    return false;
14536
0
  }
14537
0
  if (components.pathname_start == url_components::omitted) {
14538
0
    ada_log("url_aggregator::validate omitted pathname_start \n", to_diagram());
14539
0
    return false;
14540
0
  }
14541
14542
0
  if (components.protocol_end > buffer.size()) {
14543
0
    ada_log("url_aggregator::validate protocol_end overflow \n", to_diagram());
14544
0
    return false;
14545
0
  }
14546
0
  if (components.username_end > buffer.size()) {
14547
0
    ada_log("url_aggregator::validate username_end overflow \n", to_diagram());
14548
0
    return false;
14549
0
  }
14550
0
  if (components.host_start > buffer.size()) {
14551
0
    ada_log("url_aggregator::validate host_start overflow \n", to_diagram());
14552
0
    return false;
14553
0
  }
14554
0
  if (components.host_end > buffer.size()) {
14555
0
    ada_log("url_aggregator::validate host_end overflow \n", to_diagram());
14556
0
    return false;
14557
0
  }
14558
0
  if (components.pathname_start > buffer.size()) {
14559
0
    ada_log("url_aggregator::validate pathname_start overflow \n",
14560
0
            to_diagram());
14561
0
    return false;
14562
0
  }
14563
14564
0
  if (components.protocol_end > 0) {
14565
0
    if (buffer[components.protocol_end - 1] != ':') {
14566
0
      ada_log(
14567
0
          "url_aggregator::validate missing : at the end of the protocol \n",
14568
0
          to_diagram());
14569
0
      return false;
14570
0
    }
14571
0
  }
14572
14573
0
  if (components.username_end != buffer.size() &&
14574
0
      components.username_end > components.protocol_end + 2) {
14575
0
    if (buffer[components.username_end] != ':' &&
14576
0
        buffer[components.username_end] != '@') {
14577
0
      ada_log(
14578
0
          "url_aggregator::validate missing : or @ at the end of the username "
14579
0
          "\n",
14580
0
          to_diagram());
14581
0
      return false;
14582
0
    }
14583
0
  }
14584
14585
0
  if (components.host_start != buffer.size()) {
14586
0
    if (components.host_start > components.username_end) {
14587
0
      if (buffer[components.host_start] != '@') {
14588
0
        ada_log(
14589
0
            "url_aggregator::validate missing @ at the end of the password \n",
14590
0
            to_diagram());
14591
0
        return false;
14592
0
      }
14593
0
    } else if (components.host_start == components.username_end &&
14594
0
               components.host_end > components.host_start) {
14595
0
      if (components.host_start == components.protocol_end + 2) {
14596
0
        if (buffer[components.protocol_end] != '/' ||
14597
0
            buffer[components.protocol_end + 1] != '/') {
14598
0
          ada_log(
14599
0
              "url_aggregator::validate missing // between protocol and host "
14600
0
              "\n",
14601
0
              to_diagram());
14602
0
          return false;
14603
0
        }
14604
0
      } else {
14605
0
        if (components.host_start > components.protocol_end &&
14606
0
            buffer[components.host_start] != '@') {
14607
0
          ada_log(
14608
0
              "url_aggregator::validate missing @ at the end of the username "
14609
0
              "\n",
14610
0
              to_diagram());
14611
0
          return false;
14612
0
        }
14613
0
      }
14614
0
    } else {
14615
0
      if (components.host_end != components.host_start) {
14616
0
        ada_log("url_aggregator::validate expected omitted host \n",
14617
0
                to_diagram());
14618
0
        return false;
14619
0
      }
14620
0
    }
14621
0
  }
14622
0
  if (components.host_end != buffer.size() &&
14623
0
      components.pathname_start > components.host_end) {
14624
0
    if (components.pathname_start == components.host_end + 2 &&
14625
0
        buffer[components.host_end] == '/' &&
14626
0
        buffer[components.host_end + 1] == '.') {
14627
0
      if (components.pathname_start + 1 >= buffer.size() ||
14628
0
          buffer[components.pathname_start] != '/' ||
14629
0
          buffer[components.pathname_start + 1] != '/') {
14630
0
        ada_log(
14631
0
            "url_aggregator::validate expected the path to begin with // \n",
14632
0
            to_diagram());
14633
0
        return false;
14634
0
      }
14635
0
    } else if (buffer[components.host_end] != ':') {
14636
0
      ada_log("url_aggregator::validate missing : at the port \n",
14637
0
              to_diagram());
14638
0
      return false;
14639
0
    }
14640
0
  }
14641
0
  if (components.pathname_start != buffer.size() &&
14642
0
      components.pathname_start < components.search_start &&
14643
0
      components.pathname_start < components.hash_start && !has_opaque_path) {
14644
0
    if (buffer[components.pathname_start] != '/') {
14645
0
      ada_log("url_aggregator::validate missing / at the path \n",
14646
0
              to_diagram());
14647
0
      return false;
14648
0
    }
14649
0
  }
14650
0
  if (components.search_start != url_components::omitted) {
14651
0
    if (buffer[components.search_start] != '?') {
14652
0
      ada_log("url_aggregator::validate missing ? at the search \n",
14653
0
              to_diagram());
14654
0
      return false;
14655
0
    }
14656
0
  }
14657
0
  if (components.hash_start != url_components::omitted) {
14658
0
    if (buffer[components.hash_start] != '#') {
14659
0
      ada_log("url_aggregator::validate missing # at the hash \n",
14660
0
              to_diagram());
14661
0
      return false;
14662
0
    }
14663
0
  }
14664
14665
0
  return true;
14666
0
}
14667
14668
55
void url_aggregator::delete_dash_dot() {
14669
55
  ada_log("url_aggregator::delete_dash_dot");
14670
55
  ADA_ASSERT_TRUE(validate());
14671
55
  ADA_ASSERT_TRUE(has_dash_dot());
14672
55
  buffer.erase(components.host_end, 2);
14673
55
  components.pathname_start -= 2;
14674
55
  if (components.search_start != url_components::omitted) {
14675
17
    components.search_start -= 2;
14676
17
  }
14677
55
  if (components.hash_start != url_components::omitted) {
14678
26
    components.hash_start -= 2;
14679
26
  }
14680
55
  ADA_ASSERT_TRUE(validate());
14681
55
  ADA_ASSERT_TRUE(!has_dash_dot());
14682
55
}
14683
14684
8.33k
inline void url_aggregator::consume_prepared_path(std::string_view input) {
14685
8.33k
  ada_log("url_aggregator::consume_prepared_path ", input);
14686
  /***
14687
   * This is largely duplicated code from helpers::parse_prepared_path, which is
14688
   * unfortunate. This particular function is nearly identical, except that it
14689
   * is a method on url_aggregator. The idea is that the trivial path (which is
14690
   * very common) merely appends to the buffer. This is the same trivial path as
14691
   * with helpers::parse_prepared_path, except that we have the additional check
14692
   * for is_at_path(). Otherwise, we grab a copy of the current path and we
14693
   * modify it, and then insert it back into the buffer.
14694
   */
14695
8.33k
  uint8_t accumulator = checkers::path_signature(input);
14696
  // Let us first detect a trivial case.
14697
  // If it is special, we check that we have no dot, no %,  no \ and no
14698
  // character needing percent encoding. Otherwise, we check that we have no %,
14699
  // no dot, and no character needing percent encoding.
14700
8.33k
  constexpr uint8_t need_encoding = 1;
14701
8.33k
  constexpr uint8_t backslash_char = 2;
14702
8.33k
  constexpr uint8_t dot_char = 4;
14703
8.33k
  constexpr uint8_t percent_char = 8;
14704
8.33k
  bool special = type != ada::scheme::NOT_SPECIAL;
14705
8.33k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
14706
8.33k
                                      checkers::is_windows_drive_letter(input));
14707
8.33k
  bool trivial_path =
14708
8.33k
      (special ? (accumulator == 0)
14709
8.33k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
14710
3.67k
                  0)) &&
14711
8.33k
      (!may_need_slow_file_handling);
14712
8.33k
  if (accumulator == dot_char && !may_need_slow_file_handling) {
14713
    // '4' means that we have at least one dot, but nothing that requires
14714
    // percent encoding or decoding. The only part that is not trivial is
14715
    // that we may have single dots and double dots path segments.
14716
    // If we have such segments, then we either have a path that begins
14717
    // with '.' (easy to check), or we have the sequence './'.
14718
    // Note: input cannot be empty, it must at least contain one character ('.')
14719
    // Note: we know that '\' is not present.
14720
966
    if (input[0] != '.') {
14721
469
      size_t slashdot = input.find("/.");
14722
469
      if (slashdot == std::string_view::npos) {  // common case
14723
101
        trivial_path = true;
14724
368
      } else {  // uncommon
14725
        // only three cases matter: /./, /.. or a final /
14726
368
        trivial_path =
14727
368
            !(slashdot + 2 == input.size() || input[slashdot + 2] == '.' ||
14728
368
              input[slashdot + 2] == '/');
14729
368
      }
14730
469
    }
14731
966
  }
14732
8.33k
  if (trivial_path && is_at_path()) {
14733
4.96k
    ada_log("parse_path trivial");
14734
4.96k
    buffer += '/';
14735
4.96k
    buffer += input;
14736
4.96k
    return;
14737
4.96k
  }
14738
3.36k
  std::string path = std::string(get_pathname());
14739
  // We are going to need to look a bit at the path, but let us see if we can
14740
  // ignore percent encoding *and* backslashes *and* percent characters.
14741
  // Except for the trivial case, this is likely to capture 99% of paths out
14742
  // there.
14743
3.36k
  bool fast_path =
14744
3.36k
      (special &&
14745
3.36k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
14746
3.36k
      (type != ada::scheme::type::FILE);
14747
3.36k
  if (fast_path) {
14748
538
    ada_log("parse_prepared_path fast");
14749
    // Here we don't need to worry about \ or percent encoding.
14750
    // We also do not have a file protocol. We might have dots, however,
14751
    // but dots must as appear as '.', and they cannot be encoded because
14752
    // the symbol '%' is not present.
14753
538
    size_t previous_location = 0;  // We start at 0.
14754
4.01k
    do {
14755
4.01k
      size_t new_location = input.find('/', previous_location);
14756
      // std::string_view path_view = input;
14757
      //  We process the last segment separately:
14758
4.01k
      if (new_location == std::string_view::npos) {
14759
538
        std::string_view path_view = input.substr(previous_location);
14760
538
        if (path_view == "..") {  // The path ends with ..
14761
          // e.g., if you receive ".." with an empty path, you go to "/".
14762
66
          if (path.empty()) {
14763
23
            path = '/';
14764
23
            update_base_pathname(path);
14765
23
            return;
14766
23
          }
14767
          // Fast case where we have nothing to do:
14768
43
          if (path.back() == '/') {
14769
21
            update_base_pathname(path);
14770
21
            return;
14771
21
          }
14772
          // If you have the path "/joe/myfriend",
14773
          // then you delete 'myfriend'.
14774
22
          path.resize(path.rfind('/') + 1);
14775
22
          update_base_pathname(path);
14776
22
          return;
14777
43
        }
14778
472
        path += '/';
14779
472
        if (path_view != ".") {
14780
349
          path.append(path_view);
14781
349
        }
14782
472
        update_base_pathname(path);
14783
472
        return;
14784
3.48k
      } else {
14785
        // This is a non-final segment.
14786
3.48k
        std::string_view path_view =
14787
3.48k
            input.substr(previous_location, new_location - previous_location);
14788
3.48k
        previous_location = new_location + 1;
14789
3.48k
        if (path_view == "..") {
14790
674
          size_t last_delimiter = path.rfind('/');
14791
674
          if (last_delimiter != std::string::npos) {
14792
354
            path.erase(last_delimiter);
14793
354
          }
14794
2.80k
        } else if (path_view != ".") {
14795
2.41k
          path += '/';
14796
2.41k
          path.append(path_view);
14797
2.41k
        }
14798
3.48k
      }
14799
4.01k
    } while (true);
14800
2.83k
  } else {
14801
2.83k
    ada_log("parse_path slow");
14802
    // we have reached the general case
14803
2.83k
    bool needs_percent_encoding = (accumulator & 1);
14804
2.83k
    std::string path_buffer_tmp;
14805
21.6k
    do {
14806
21.6k
      size_t location = (special && (accumulator & 2))
14807
21.6k
                            ? input.find_first_of("/\\")
14808
21.6k
                            : input.find('/');
14809
21.6k
      std::string_view path_view = input;
14810
21.6k
      if (location != std::string_view::npos) {
14811
18.8k
        path_view.remove_suffix(path_view.size() - location);
14812
18.8k
        input.remove_prefix(location + 1);
14813
18.8k
      }
14814
      // path_buffer is either path_view or it might point at a percent encoded
14815
      // temporary string.
14816
21.6k
      std::string_view path_buffer =
14817
21.6k
          (needs_percent_encoding &&
14818
21.6k
           ada::unicode::percent_encode<false>(
14819
11.8k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
14820
21.6k
              ? path_buffer_tmp
14821
21.6k
              : path_view;
14822
21.6k
      if (unicode::is_double_dot_path_segment(path_buffer)) {
14823
4.75k
        if ((helpers::shorten_path(path, type) || special) &&
14824
4.75k
            location == std::string_view::npos) {
14825
256
          path += '/';
14826
256
        }
14827
16.8k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
14828
16.8k
                 (location == std::string_view::npos)) {
14829
127
        path += '/';
14830
127
      }
14831
      // Otherwise, if path_buffer is not a single-dot path segment, then:
14832
16.7k
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
14833
        // If url's scheme is "file", url's path is empty, and path_buffer is a
14834
        // Windows drive letter, then replace the second code point in
14835
        // path_buffer with U+003A (:).
14836
15.5k
        if (type == ada::scheme::type::FILE && path.empty() &&
14837
15.5k
            checkers::is_windows_drive_letter(path_buffer)) {
14838
133
          path += '/';
14839
133
          path += path_buffer[0];
14840
133
          path += ':';
14841
133
          path_buffer.remove_prefix(2);
14842
133
          path.append(path_buffer);
14843
15.3k
        } else {
14844
          // Append path_buffer to url's path.
14845
15.3k
          path += '/';
14846
15.3k
          path.append(path_buffer);
14847
15.3k
        }
14848
15.5k
      }
14849
21.6k
      if (location == std::string_view::npos) {
14850
2.83k
        update_base_pathname(path);
14851
2.83k
        return;
14852
2.83k
      }
14853
21.6k
    } while (true);
14854
2.83k
  }
14855
3.36k
}
14856
}  // namespace ada
14857
/* end file src/url_aggregator.cpp */
14858
/* begin file src/ada_c.cpp */
14859
14860
0
ada::result<ada::url_aggregator>& get_instance(void* result) noexcept {
14861
0
  return *(ada::result<ada::url_aggregator>*)result;
14862
0
}
14863
14864
extern "C" {
14865
typedef void* ada_url;
14866
typedef void* ada_url_search_params;
14867
typedef void* ada_strings;
14868
typedef void* ada_url_search_params_keys_iter;
14869
typedef void* ada_url_search_params_values_iter;
14870
typedef void* ada_url_search_params_entries_iter;
14871
14872
struct ada_string {
14873
  const char* data;
14874
  size_t length;
14875
};
14876
14877
struct ada_owned_string {
14878
  const char* data;
14879
  size_t length;
14880
};
14881
14882
struct ada_string_pair {
14883
  ada_string key;
14884
  ada_string value;
14885
};
14886
14887
0
ada_string ada_string_create(const char* data, size_t length) {
14888
0
  ada_string out{};
14889
0
  out.data = data;
14890
0
  out.length = length;
14891
0
  return out;
14892
0
}
14893
14894
struct ada_url_components {
14895
  /*
14896
   * By using 32-bit integers, we implicitly assume that the URL string
14897
   * cannot exceed 4 GB.
14898
   *
14899
   * https://user:pass@example.com:1234/foo/bar?baz#quux
14900
   *       |     |    |          | ^^^^|       |   |
14901
   *       |     |    |          | |   |       |   `----- hash_start
14902
   *       |     |    |          | |   |       `--------- search_start
14903
   *       |     |    |          | |   `----------------- pathname_start
14904
   *       |     |    |          | `--------------------- port
14905
   *       |     |    |          `----------------------- host_end
14906
   *       |     |    `---------------------------------- host_start
14907
   *       |     `--------------------------------------- username_end
14908
   *       `--------------------------------------------- protocol_end
14909
   */
14910
  uint32_t protocol_end;
14911
  /**
14912
   * Username end is not `omitted` by default (-1) to make username and password
14913
   * getters less costly to implement.
14914
   */
14915
  uint32_t username_end;
14916
  uint32_t host_start;
14917
  uint32_t host_end;
14918
  uint32_t port;
14919
  uint32_t pathname_start;
14920
  uint32_t search_start;
14921
  uint32_t hash_start;
14922
};
14923
14924
0
ada_url ada_parse(const char* input, size_t length) noexcept {
14925
0
  return new ada::result<ada::url_aggregator>(
14926
0
      ada::parse<ada::url_aggregator>(std::string_view(input, length)));
14927
0
}
14928
14929
ada_url ada_parse_with_base(const char* input, size_t input_length,
14930
0
                            const char* base, size_t base_length) noexcept {
14931
0
  auto base_out =
14932
0
      ada::parse<ada::url_aggregator>(std::string_view(base, base_length));
14933
14934
0
  if (!base_out) {
14935
0
    return new ada::result<ada::url_aggregator>(base_out);
14936
0
  }
14937
14938
0
  return new ada::result<ada::url_aggregator>(ada::parse<ada::url_aggregator>(
14939
0
      std::string_view(input, input_length), &base_out.value()));
14940
0
}
14941
14942
0
bool ada_can_parse(const char* input, size_t length) noexcept {
14943
0
  return ada::can_parse(std::string_view(input, length));
14944
0
}
14945
14946
bool ada_can_parse_with_base(const char* input, size_t input_length,
14947
0
                             const char* base, size_t base_length) noexcept {
14948
0
  auto base_view = std::string_view(base, base_length);
14949
0
  return ada::can_parse(std::string_view(input, input_length), &base_view);
14950
0
}
14951
14952
0
void ada_free(ada_url result) noexcept {
14953
0
  ada::result<ada::url_aggregator>* r =
14954
0
      (ada::result<ada::url_aggregator>*)result;
14955
0
  delete r;
14956
0
}
14957
14958
0
ada_url ada_copy(ada_url input) noexcept {
14959
0
  ada::result<ada::url_aggregator>& r = get_instance(input);
14960
0
  return new ada::result<ada::url_aggregator>(r);
14961
0
}
14962
14963
0
bool ada_is_valid(ada_url result) noexcept {
14964
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
14965
0
  return r.has_value();
14966
0
}
14967
14968
// caller must free the result with ada_free_owned_string
14969
0
ada_owned_string ada_get_origin(ada_url result) noexcept {
14970
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
14971
0
  ada_owned_string owned;
14972
0
  if (!r) {
14973
0
    owned.data = nullptr;
14974
0
    owned.length = 0;
14975
0
    return owned;
14976
0
  }
14977
0
  std::string out = r->get_origin();
14978
0
  owned.length = out.size();
14979
0
  owned.data = new char[owned.length];
14980
0
  memcpy((void*)owned.data, out.data(), owned.length);
14981
0
  return owned;
14982
0
}
14983
14984
0
void ada_free_owned_string(ada_owned_string owned) noexcept {
14985
0
  delete[] owned.data;
14986
0
  owned.data = nullptr;
14987
0
  owned.length = 0;
14988
0
}
14989
14990
0
ada_string ada_get_href(ada_url result) noexcept {
14991
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
14992
0
  if (!r) {
14993
0
    return ada_string_create(NULL, 0);
14994
0
  }
14995
0
  std::string_view out = r->get_href();
14996
0
  return ada_string_create(out.data(), out.length());
14997
0
}
14998
14999
0
ada_string ada_get_username(ada_url result) noexcept {
15000
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15001
0
  if (!r) {
15002
0
    return ada_string_create(NULL, 0);
15003
0
  }
15004
0
  std::string_view out = r->get_username();
15005
0
  return ada_string_create(out.data(), out.length());
15006
0
}
15007
15008
0
ada_string ada_get_password(ada_url result) noexcept {
15009
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15010
0
  if (!r) {
15011
0
    return ada_string_create(NULL, 0);
15012
0
  }
15013
0
  std::string_view out = r->get_password();
15014
0
  return ada_string_create(out.data(), out.length());
15015
0
}
15016
15017
0
ada_string ada_get_port(ada_url result) noexcept {
15018
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15019
0
  if (!r) {
15020
0
    return ada_string_create(NULL, 0);
15021
0
  }
15022
0
  std::string_view out = r->get_port();
15023
0
  return ada_string_create(out.data(), out.length());
15024
0
}
15025
15026
0
ada_string ada_get_hash(ada_url result) noexcept {
15027
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15028
0
  if (!r) {
15029
0
    return ada_string_create(NULL, 0);
15030
0
  }
15031
0
  std::string_view out = r->get_hash();
15032
0
  return ada_string_create(out.data(), out.length());
15033
0
}
15034
15035
0
ada_string ada_get_host(ada_url result) noexcept {
15036
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15037
0
  if (!r) {
15038
0
    return ada_string_create(NULL, 0);
15039
0
  }
15040
0
  std::string_view out = r->get_host();
15041
0
  return ada_string_create(out.data(), out.length());
15042
0
}
15043
15044
0
ada_string ada_get_hostname(ada_url result) noexcept {
15045
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15046
0
  if (!r) {
15047
0
    return ada_string_create(NULL, 0);
15048
0
  }
15049
0
  std::string_view out = r->get_hostname();
15050
0
  return ada_string_create(out.data(), out.length());
15051
0
}
15052
15053
0
ada_string ada_get_pathname(ada_url result) noexcept {
15054
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15055
0
  if (!r) {
15056
0
    return ada_string_create(NULL, 0);
15057
0
  }
15058
0
  std::string_view out = r->get_pathname();
15059
0
  return ada_string_create(out.data(), out.length());
15060
0
}
15061
15062
0
ada_string ada_get_search(ada_url result) noexcept {
15063
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15064
0
  if (!r) {
15065
0
    return ada_string_create(NULL, 0);
15066
0
  }
15067
0
  std::string_view out = r->get_search();
15068
0
  return ada_string_create(out.data(), out.length());
15069
0
}
15070
15071
0
ada_string ada_get_protocol(ada_url result) noexcept {
15072
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15073
0
  if (!r) {
15074
0
    return ada_string_create(NULL, 0);
15075
0
  }
15076
0
  std::string_view out = r->get_protocol();
15077
0
  return ada_string_create(out.data(), out.length());
15078
0
}
15079
15080
0
uint8_t ada_get_host_type(ada_url result) noexcept {
15081
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15082
0
  if (!r) {
15083
0
    return 0;
15084
0
  }
15085
0
  return r->host_type;
15086
0
}
15087
15088
0
uint8_t ada_get_scheme_type(ada_url result) noexcept {
15089
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15090
0
  if (!r) {
15091
0
    return 0;
15092
0
  }
15093
0
  return r->type;
15094
0
}
15095
15096
0
bool ada_set_href(ada_url result, const char* input, size_t length) noexcept {
15097
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15098
0
  if (!r) {
15099
0
    return false;
15100
0
  }
15101
0
  return r->set_href(std::string_view(input, length));
15102
0
}
15103
15104
0
bool ada_set_host(ada_url result, const char* input, size_t length) noexcept {
15105
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15106
0
  if (!r) {
15107
0
    return false;
15108
0
  }
15109
0
  return r->set_host(std::string_view(input, length));
15110
0
}
15111
15112
bool ada_set_hostname(ada_url result, const char* input,
15113
0
                      size_t length) noexcept {
15114
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15115
0
  if (!r) {
15116
0
    return false;
15117
0
  }
15118
0
  return r->set_hostname(std::string_view(input, length));
15119
0
}
15120
15121
bool ada_set_protocol(ada_url result, const char* input,
15122
0
                      size_t length) noexcept {
15123
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15124
0
  if (!r) {
15125
0
    return false;
15126
0
  }
15127
0
  return r->set_protocol(std::string_view(input, length));
15128
0
}
15129
15130
bool ada_set_username(ada_url result, const char* input,
15131
0
                      size_t length) noexcept {
15132
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15133
0
  if (!r) {
15134
0
    return false;
15135
0
  }
15136
0
  return r->set_username(std::string_view(input, length));
15137
0
}
15138
15139
bool ada_set_password(ada_url result, const char* input,
15140
0
                      size_t length) noexcept {
15141
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15142
0
  if (!r) {
15143
0
    return false;
15144
0
  }
15145
0
  return r->set_password(std::string_view(input, length));
15146
0
}
15147
15148
0
bool ada_set_port(ada_url result, const char* input, size_t length) noexcept {
15149
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15150
0
  if (!r) {
15151
0
    return false;
15152
0
  }
15153
0
  return r->set_port(std::string_view(input, length));
15154
0
}
15155
15156
bool ada_set_pathname(ada_url result, const char* input,
15157
0
                      size_t length) noexcept {
15158
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15159
0
  if (!r) {
15160
0
    return false;
15161
0
  }
15162
0
  return r->set_pathname(std::string_view(input, length));
15163
0
}
15164
15165
/**
15166
 * Update the search/query of the URL.
15167
 *
15168
 * If a URL has `?` as the search value, passing empty string to this function
15169
 * does not remove the attribute. If you need to remove it, please use
15170
 * `ada_clear_search` method.
15171
 */
15172
0
void ada_set_search(ada_url result, const char* input, size_t length) noexcept {
15173
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15174
0
  if (r) {
15175
0
    r->set_search(std::string_view(input, length));
15176
0
  }
15177
0
}
15178
15179
/**
15180
 * Update the hash/fragment of the URL.
15181
 *
15182
 * If a URL has `#` as the hash value, passing empty string to this function
15183
 * does not remove the attribute. If you need to remove it, please use
15184
 * `ada_clear_hash` method.
15185
 */
15186
0
void ada_set_hash(ada_url result, const char* input, size_t length) noexcept {
15187
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15188
0
  if (r) {
15189
0
    r->set_hash(std::string_view(input, length));
15190
0
  }
15191
0
}
15192
15193
0
void ada_clear_port(ada_url result) noexcept {
15194
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15195
0
  if (r) {
15196
0
    r->clear_port();
15197
0
  }
15198
0
}
15199
15200
/**
15201
 * Removes the hash of the URL.
15202
 *
15203
 * Despite `ada_set_hash` method, this function allows the complete
15204
 * removal of the hash attribute, even if it has a value of `#`.
15205
 */
15206
0
void ada_clear_hash(ada_url result) noexcept {
15207
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15208
0
  if (r) {
15209
0
    r->clear_hash();
15210
0
  }
15211
0
}
15212
15213
/**
15214
 * Removes the search of the URL.
15215
 *
15216
 * Despite `ada_set_search` method, this function allows the complete
15217
 * removal of the search attribute, even if it has a value of `?`.
15218
 */
15219
0
void ada_clear_search(ada_url result) noexcept {
15220
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15221
0
  if (r) {
15222
0
    r->clear_search();
15223
0
  }
15224
0
}
15225
15226
0
bool ada_has_credentials(ada_url result) noexcept {
15227
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15228
0
  if (!r) {
15229
0
    return false;
15230
0
  }
15231
0
  return r->has_credentials();
15232
0
}
15233
15234
0
bool ada_has_empty_hostname(ada_url result) noexcept {
15235
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15236
0
  if (!r) {
15237
0
    return false;
15238
0
  }
15239
0
  return r->has_empty_hostname();
15240
0
}
15241
15242
0
bool ada_has_hostname(ada_url result) noexcept {
15243
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15244
0
  if (!r) {
15245
0
    return false;
15246
0
  }
15247
0
  return r->has_hostname();
15248
0
}
15249
15250
0
bool ada_has_non_empty_username(ada_url result) noexcept {
15251
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15252
0
  if (!r) {
15253
0
    return false;
15254
0
  }
15255
0
  return r->has_non_empty_username();
15256
0
}
15257
15258
0
bool ada_has_non_empty_password(ada_url result) noexcept {
15259
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15260
0
  if (!r) {
15261
0
    return false;
15262
0
  }
15263
0
  return r->has_non_empty_password();
15264
0
}
15265
15266
0
bool ada_has_port(ada_url result) noexcept {
15267
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15268
0
  if (!r) {
15269
0
    return false;
15270
0
  }
15271
0
  return r->has_port();
15272
0
}
15273
15274
0
bool ada_has_password(ada_url result) noexcept {
15275
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15276
0
  if (!r) {
15277
0
    return false;
15278
0
  }
15279
0
  return r->has_password();
15280
0
}
15281
15282
0
bool ada_has_hash(ada_url result) noexcept {
15283
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15284
0
  if (!r) {
15285
0
    return false;
15286
0
  }
15287
0
  return r->has_hash();
15288
0
}
15289
15290
0
bool ada_has_search(ada_url result) noexcept {
15291
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15292
0
  if (!r) {
15293
0
    return false;
15294
0
  }
15295
0
  return r->has_search();
15296
0
}
15297
15298
// returns a pointer to the internal url_aggregator::url_components
15299
0
const ada_url_components* ada_get_components(ada_url result) noexcept {
15300
0
  static_assert(sizeof(ada_url_components) == sizeof(ada::url_components));
15301
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15302
0
  if (!r) {
15303
0
    return nullptr;
15304
0
  }
15305
0
  return reinterpret_cast<const ada_url_components*>(&r->get_components());
15306
0
}
15307
15308
0
ada_owned_string ada_idna_to_unicode(const char* input, size_t length) {
15309
0
  std::string out = ada::idna::to_unicode(std::string_view(input, length));
15310
0
  ada_owned_string owned{};
15311
0
  owned.length = out.length();
15312
0
  owned.data = new char[owned.length];
15313
0
  memcpy((void*)owned.data, out.data(), owned.length);
15314
0
  return owned;
15315
0
}
15316
15317
0
ada_owned_string ada_idna_to_ascii(const char* input, size_t length) {
15318
0
  std::string out = ada::idna::to_ascii(std::string_view(input, length));
15319
0
  ada_owned_string owned{};
15320
0
  owned.length = out.size();
15321
0
  owned.data = new char[owned.length];
15322
0
  memcpy((void*)owned.data, out.data(), owned.length);
15323
0
  return owned;
15324
0
}
15325
15326
ada_url_search_params ada_parse_search_params(const char* input,
15327
0
                                              size_t length) {
15328
0
  return new ada::result<ada::url_search_params>(
15329
0
      ada::url_search_params(std::string_view(input, length)));
15330
0
}
15331
15332
0
void ada_free_search_params(ada_url_search_params result) {
15333
0
  ada::result<ada::url_search_params>* r =
15334
0
      (ada::result<ada::url_search_params>*)result;
15335
0
  delete r;
15336
0
}
15337
15338
0
ada_owned_string ada_search_params_to_string(ada_url_search_params result) {
15339
0
  ada::result<ada::url_search_params>& r =
15340
0
      *(ada::result<ada::url_search_params>*)result;
15341
0
  if (!r) return ada_owned_string{NULL, 0};
15342
0
  std::string out = r->to_string();
15343
0
  ada_owned_string owned{};
15344
0
  owned.length = out.size();
15345
0
  owned.data = new char[owned.length];
15346
0
  memcpy((void*)owned.data, out.data(), owned.length);
15347
0
  return owned;
15348
0
}
15349
15350
0
size_t ada_search_params_size(ada_url_search_params result) {
15351
0
  ada::result<ada::url_search_params>& r =
15352
0
      *(ada::result<ada::url_search_params>*)result;
15353
0
  if (!r) return 0;
15354
0
  return r->size();
15355
0
}
15356
15357
0
void ada_search_params_sort(ada_url_search_params result) {
15358
0
  ada::result<ada::url_search_params>& r =
15359
0
      *(ada::result<ada::url_search_params>*)result;
15360
0
  if (r) r->sort();
15361
0
}
15362
15363
void ada_search_params_append(ada_url_search_params result, const char* key,
15364
                              size_t key_length, const char* value,
15365
0
                              size_t value_length) {
15366
0
  ada::result<ada::url_search_params>& r =
15367
0
      *(ada::result<ada::url_search_params>*)result;
15368
0
  if (r) {
15369
0
    r->append(std::string_view(key, key_length),
15370
0
              std::string_view(value, value_length));
15371
0
  }
15372
0
}
15373
15374
void ada_search_params_set(ada_url_search_params result, const char* key,
15375
                           size_t key_length, const char* value,
15376
0
                           size_t value_length) {
15377
0
  ada::result<ada::url_search_params>& r =
15378
0
      *(ada::result<ada::url_search_params>*)result;
15379
0
  if (r) {
15380
0
    r->set(std::string_view(key, key_length),
15381
0
           std::string_view(value, value_length));
15382
0
  }
15383
0
}
15384
15385
void ada_search_params_remove(ada_url_search_params result, const char* key,
15386
0
                              size_t key_length) {
15387
0
  ada::result<ada::url_search_params>& r =
15388
0
      *(ada::result<ada::url_search_params>*)result;
15389
0
  if (r) {
15390
0
    r->remove(std::string_view(key, key_length));
15391
0
  }
15392
0
}
15393
15394
void ada_search_params_remove_value(ada_url_search_params result,
15395
                                    const char* key, size_t key_length,
15396
0
                                    const char* value, 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->remove(std::string_view(key, key_length),
15401
0
              std::string_view(value, value_length));
15402
0
  }
15403
0
}
15404
15405
bool ada_search_params_has(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) return false;
15410
0
  return r->has(std::string_view(key, key_length));
15411
0
}
15412
15413
bool ada_search_params_has_value(ada_url_search_params result, const char* key,
15414
                                 size_t key_length, const char* value,
15415
0
                                 size_t value_length) {
15416
0
  ada::result<ada::url_search_params>& r =
15417
0
      *(ada::result<ada::url_search_params>*)result;
15418
0
  if (!r) return false;
15419
0
  return r->has(std::string_view(key, key_length),
15420
0
                std::string_view(value, value_length));
15421
0
}
15422
15423
ada_string ada_search_params_get(ada_url_search_params result, const char* key,
15424
0
                                 size_t key_length) {
15425
0
  ada::result<ada::url_search_params>& r =
15426
0
      *(ada::result<ada::url_search_params>*)result;
15427
0
  if (!r) return ada_string_create(NULL, 0);
15428
0
  auto found = r->get(std::string_view(key, key_length));
15429
0
  if (!found.has_value()) return ada_string_create(NULL, 0);
15430
0
  return ada_string_create(found->data(), found->length());
15431
0
}
15432
15433
ada_strings ada_search_params_get_all(ada_url_search_params result,
15434
0
                                      const char* key, size_t key_length) {
15435
0
  ada::result<ada::url_search_params>& r =
15436
0
      *(ada::result<ada::url_search_params>*)result;
15437
0
  if (!r) {
15438
0
    return new ada::result<std::vector<std::string>>(
15439
0
        std::vector<std::string>());
15440
0
  }
15441
0
  return new ada::result<std::vector<std::string>>(
15442
0
      r->get_all(std::string_view(key, key_length)));
15443
0
}
15444
15445
ada_url_search_params_keys_iter ada_search_params_get_keys(
15446
0
    ada_url_search_params result) {
15447
0
  ada::result<ada::url_search_params>& r =
15448
0
      *(ada::result<ada::url_search_params>*)result;
15449
0
  if (!r) {
15450
0
    return new ada::result<ada::url_search_params_keys_iter>(
15451
0
        ada::url_search_params_keys_iter());
15452
0
  }
15453
0
  return new ada::result<ada::url_search_params_keys_iter>(r->get_keys());
15454
0
}
15455
15456
ada_url_search_params_values_iter ada_search_params_get_values(
15457
0
    ada_url_search_params result) {
15458
0
  ada::result<ada::url_search_params>& r =
15459
0
      *(ada::result<ada::url_search_params>*)result;
15460
0
  if (!r) {
15461
0
    return new ada::result<ada::url_search_params_values_iter>(
15462
0
        ada::url_search_params_values_iter());
15463
0
  }
15464
0
  return new ada::result<ada::url_search_params_values_iter>(r->get_values());
15465
0
}
15466
15467
ada_url_search_params_entries_iter ada_search_params_get_entries(
15468
0
    ada_url_search_params result) {
15469
0
  ada::result<ada::url_search_params>& r =
15470
0
      *(ada::result<ada::url_search_params>*)result;
15471
0
  if (!r) {
15472
0
    return new ada::result<ada::url_search_params_entries_iter>(
15473
0
        ada::url_search_params_entries_iter());
15474
0
  }
15475
0
  return new ada::result<ada::url_search_params_entries_iter>(r->get_entries());
15476
0
}
15477
15478
0
void ada_free_strings(ada_strings result) {
15479
0
  ada::result<std::vector<std::string>>* r =
15480
0
      (ada::result<std::vector<std::string>>*)result;
15481
0
  delete r;
15482
0
}
15483
15484
0
size_t ada_strings_size(ada_strings result) {
15485
0
  ada::result<std::vector<std::string>>* r =
15486
0
      (ada::result<std::vector<std::string>>*)result;
15487
0
  if (!r) return 0;
15488
0
  return (*r)->size();
15489
0
}
15490
15491
0
ada_string ada_strings_get(ada_strings result, size_t index) {
15492
0
  ada::result<std::vector<std::string>>* r =
15493
0
      (ada::result<std::vector<std::string>>*)result;
15494
0
  if (!r) return ada_string_create(NULL, 0);
15495
0
  std::string_view view = (*r)->at(index);
15496
0
  return ada_string_create(view.data(), view.length());
15497
0
}
15498
15499
0
void ada_free_search_params_keys_iter(ada_url_search_params_keys_iter result) {
15500
0
  ada::result<ada::url_search_params_keys_iter>* r =
15501
0
      (ada::result<ada::url_search_params_keys_iter>*)result;
15502
0
  delete r;
15503
0
}
15504
15505
ada_string ada_search_params_keys_iter_next(
15506
0
    ada_url_search_params_keys_iter result) {
15507
0
  ada::result<ada::url_search_params_keys_iter>* r =
15508
0
      (ada::result<ada::url_search_params_keys_iter>*)result;
15509
0
  if (!r) return ada_string_create(NULL, 0);
15510
0
  auto next = (*r)->next();
15511
0
  if (!next.has_value()) return ada_string_create(NULL, 0);
15512
0
  return ada_string_create(next->data(), next->length());
15513
0
}
15514
15515
bool ada_search_params_keys_iter_has_next(
15516
0
    ada_url_search_params_keys_iter result) {
15517
0
  ada::result<ada::url_search_params_keys_iter>* r =
15518
0
      (ada::result<ada::url_search_params_keys_iter>*)result;
15519
0
  if (!r) return false;
15520
0
  return (*r)->has_next();
15521
0
}
15522
15523
void ada_free_search_params_values_iter(
15524
0
    ada_url_search_params_values_iter result) {
15525
0
  ada::result<ada::url_search_params_values_iter>* r =
15526
0
      (ada::result<ada::url_search_params_values_iter>*)result;
15527
0
  delete r;
15528
0
}
15529
15530
ada_string ada_search_params_values_iter_next(
15531
0
    ada_url_search_params_values_iter result) {
15532
0
  ada::result<ada::url_search_params_values_iter>* r =
15533
0
      (ada::result<ada::url_search_params_values_iter>*)result;
15534
0
  if (!r) return ada_string_create(NULL, 0);
15535
0
  auto next = (*r)->next();
15536
0
  if (!next.has_value()) return ada_string_create(NULL, 0);
15537
0
  return ada_string_create(next->data(), next->length());
15538
0
}
15539
15540
bool ada_search_params_values_iter_has_next(
15541
0
    ada_url_search_params_values_iter result) {
15542
0
  ada::result<ada::url_search_params_values_iter>* r =
15543
0
      (ada::result<ada::url_search_params_values_iter>*)result;
15544
0
  if (!r) return false;
15545
0
  return (*r)->has_next();
15546
0
}
15547
15548
void ada_free_search_params_entries_iter(
15549
0
    ada_url_search_params_entries_iter result) {
15550
0
  ada::result<ada::url_search_params_entries_iter>* r =
15551
0
      (ada::result<ada::url_search_params_entries_iter>*)result;
15552
0
  delete r;
15553
0
}
15554
15555
ada_string_pair ada_search_params_entries_iter_next(
15556
0
    ada_url_search_params_entries_iter result) {
15557
0
  ada::result<ada::url_search_params_entries_iter>* r =
15558
0
      (ada::result<ada::url_search_params_entries_iter>*)result;
15559
0
  if (!r) return {ada_string_create(NULL, 0), ada_string_create(NULL, 0)};
15560
0
  auto next = (*r)->next();
15561
0
  if (!next.has_value())
15562
0
    return {ada_string_create(NULL, 0), ada_string_create(NULL, 0)};
15563
0
  return ada_string_pair{
15564
0
      ada_string_create(next->first.data(), next->first.length()),
15565
0
      ada_string_create(next->second.data(), next->second.length())};
15566
0
}
15567
15568
bool ada_search_params_entries_iter_has_next(
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
  if (!r) return false;
15573
0
  return (*r)->has_next();
15574
0
}
15575
15576
}  // extern "C"
15577
/* end file src/ada_c.cpp */
15578
/* end file src/ada.cpp */