Coverage Report

Created: 2023-06-07 06:10

/src/ada-url/build/singleheader/ada.cpp
Line
Count
Source (jump to first uncovered line)
1
/* auto-generated on 2023-06-04 13:08:26 -0400. 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
20.2k
ada_really_inline ada_constexpr bool is_ipv4(std::string_view view) noexcept {
10
20.2k
  size_t last_dot = view.rfind('.');
11
20.2k
  if (last_dot == view.size() - 1) {
12
2.42k
    view.remove_suffix(1);
13
2.42k
    last_dot = view.rfind('.');
14
2.42k
  }
15
20.2k
  std::string_view number =
16
20.2k
      (last_dot == std::string_view::npos) ? view : view.substr(last_dot + 1);
17
20.2k
  if (number.empty()) {
18
1.59k
    return false;
19
1.59k
  }
20
  /** Optimization opportunity: we have basically identified the last number of
21
     the ipv4 if we return true here. We might as well parse it and have at
22
     least one number parsed when we get to parse_ipv4. */
23
18.6k
  if (std::all_of(number.begin(), number.end(), ada::checkers::is_digit)) {
24
4.77k
    return true;
25
4.77k
  }
26
13.8k
  return (checkers::has_hex_prefix(number) &&
27
13.8k
          std::all_of(number.begin() + 2, number.end(),
28
2.26k
                      ada::unicode::is_lowercase_hex));
29
18.6k
}
30
31
// for use with path_signature, we include all characters that need percent
32
// encoding.
33
static constexpr uint8_t path_signature_table[256] = {
34
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
35
    1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0,
36
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
37
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
38
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
39
    0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
40
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
41
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
42
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
43
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
44
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
45
static_assert(path_signature_table[uint8_t('?')] == 1);
46
static_assert(path_signature_table[uint8_t('`')] == 1);
47
static_assert(path_signature_table[uint8_t('{')] == 1);
48
static_assert(path_signature_table[uint8_t('}')] == 1);
49
//
50
static_assert(path_signature_table[uint8_t(' ')] == 1);
51
static_assert(path_signature_table[uint8_t('?')] == 1);
52
static_assert(path_signature_table[uint8_t('"')] == 1);
53
static_assert(path_signature_table[uint8_t('#')] == 1);
54
static_assert(path_signature_table[uint8_t('<')] == 1);
55
static_assert(path_signature_table[uint8_t('>')] == 1);
56
static_assert(path_signature_table[uint8_t('\\')] == 2);
57
static_assert(path_signature_table[uint8_t('.')] == 4);
58
static_assert(path_signature_table[uint8_t('%')] == 8);
59
60
//
61
static_assert(path_signature_table[0] == 1);
62
static_assert(path_signature_table[31] == 1);
63
static_assert(path_signature_table[127] == 1);
64
static_assert(path_signature_table[128] == 1);
65
static_assert(path_signature_table[255] == 1);
66
67
ada_really_inline constexpr uint8_t path_signature(
68
27.6k
    std::string_view input) noexcept {
69
  // The path percent-encode set is the query percent-encode set and U+003F (?),
70
  // U+0060 (`), U+007B ({), and U+007D (}). The query percent-encode set is the
71
  // C0 control percent-encode set and U+0020 SPACE, U+0022 ("), U+0023 (#),
72
  // U+003C (<), and U+003E (>). The C0 control percent-encode set are the C0
73
  // controls and all code points greater than U+007E (~).
74
27.6k
  size_t i = 0;
75
27.6k
  uint8_t accumulator{};
76
78.0k
  for (; i + 7 < input.size(); i += 8) {
77
50.4k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])] |
78
50.4k
                           path_signature_table[uint8_t(input[i + 1])] |
79
50.4k
                           path_signature_table[uint8_t(input[i + 2])] |
80
50.4k
                           path_signature_table[uint8_t(input[i + 3])] |
81
50.4k
                           path_signature_table[uint8_t(input[i + 4])] |
82
50.4k
                           path_signature_table[uint8_t(input[i + 5])] |
83
50.4k
                           path_signature_table[uint8_t(input[i + 6])] |
84
50.4k
                           path_signature_table[uint8_t(input[i + 7])]);
85
50.4k
  }
86
98.4k
  for (; i < input.size(); i++) {
87
70.8k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])]);
88
70.8k
  }
89
27.6k
  return accumulator;
90
27.6k
}
91
92
ada_really_inline constexpr bool verify_dns_length(
93
0
    std::string_view input) noexcept {
94
0
  if (input.back() == '.') {
95
0
    if (input.size() > 254) return false;
96
0
  } else if (input.size() > 253)
97
0
    return false;
98
99
0
  size_t start = 0;
100
0
  while (start < input.size()) {
101
0
    auto dot_location = input.find('.', start);
102
    // If not found, it's likely the end of the domain
103
0
    if (dot_location == std::string_view::npos) dot_location = input.size();
104
105
0
    auto label_size = dot_location - start;
106
0
    if (label_size > 63 || label_size == 0) return false;
107
108
0
    start = dot_location + 1;
109
0
  }
110
111
0
  return true;
112
0
}
113
}  // namespace ada::checkers
114
/* end file src/checkers.cpp */
115
/* begin file src/unicode.cpp */
116
117
ADA_PUSH_DISABLE_ALL_WARNINGS
118
/* begin file src/ada_idna.cpp */
119
/* auto-generated on 2023-05-07 19:12:14 -0400. Do not edit! */
120
/* begin file src/idna.cpp */
121
/* begin file src/unicode_transcoding.cpp */
122
123
#include <cstdint>
124
#include <cstring>
125
126
namespace ada::idna {
127
128
9.77k
size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) {
129
9.77k
  const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
130
9.77k
  size_t pos = 0;
131
9.77k
  char32_t* start{utf32_output};
132
125k
  while (pos < len) {
133
    // try to convert the next block of 16 ASCII bytes
134
118k
    if (pos + 16 <= len) {  // if it is safe to read 16 more
135
                            // bytes, check that they are ascii
136
75.9k
      uint64_t v1;
137
75.9k
      std::memcpy(&v1, data + pos, sizeof(uint64_t));
138
75.9k
      uint64_t v2;
139
75.9k
      std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
140
75.9k
      uint64_t v{v1 | v2};
141
75.9k
      if ((v & 0x8080808080808080) == 0) {
142
3.00k
        size_t final_pos = pos + 16;
143
51.0k
        while (pos < final_pos) {
144
48.0k
          *utf32_output++ = char32_t(buf[pos]);
145
48.0k
          pos++;
146
48.0k
        }
147
3.00k
        continue;
148
3.00k
      }
149
75.9k
    }
150
115k
    uint8_t leading_byte = data[pos];  // leading byte
151
115k
    if (leading_byte < 0b10000000) {
152
      // converting one ASCII byte !!!
153
70.5k
      *utf32_output++ = char32_t(leading_byte);
154
70.5k
      pos++;
155
70.5k
    } else if ((leading_byte & 0b11100000) == 0b11000000) {
156
      // We have a two-byte UTF-8
157
11.6k
      if (pos + 1 >= len) {
158
249
        return 0;
159
249
      }  // minimal bound checking
160
11.3k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
161
328
        return 0;
162
328
      }
163
      // range check
164
11.0k
      uint32_t code_point =
165
11.0k
          (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
166
11.0k
      if (code_point < 0x80 || 0x7ff < code_point) {
167
27
        return 0;
168
27
      }
169
10.9k
      *utf32_output++ = char32_t(code_point);
170
10.9k
      pos += 2;
171
33.2k
    } else if ((leading_byte & 0b11110000) == 0b11100000) {
172
      // We have a three-byte UTF-8
173
30.5k
      if (pos + 2 >= len) {
174
111
        return 0;
175
111
      }  // minimal bound checking
176
177
30.4k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
178
165
        return 0;
179
165
      }
180
30.3k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
181
32
        return 0;
182
32
      }
183
      // range check
184
30.2k
      uint32_t code_point = (leading_byte & 0b00001111) << 12 |
185
30.2k
                            (data[pos + 1] & 0b00111111) << 6 |
186
30.2k
                            (data[pos + 2] & 0b00111111);
187
30.2k
      if (code_point < 0x800 || 0xffff < code_point ||
188
30.2k
          (0xd7ff < code_point && code_point < 0xe000)) {
189
43
        return 0;
190
43
      }
191
30.2k
      *utf32_output++ = char32_t(code_point);
192
30.2k
      pos += 3;
193
30.2k
    } else if ((leading_byte & 0b11111000) == 0b11110000) {  // 0b11110000
194
      // we have a 4-byte UTF-8 word.
195
871
      if (pos + 3 >= len) {
196
84
        return 0;
197
84
      }  // minimal bound checking
198
787
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
199
92
        return 0;
200
92
      }
201
695
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
202
11
        return 0;
203
11
      }
204
684
      if ((data[pos + 3] & 0b11000000) != 0b10000000) {
205
20
        return 0;
206
20
      }
207
208
      // range check
209
664
      uint32_t code_point = (leading_byte & 0b00000111) << 18 |
210
664
                            (data[pos + 1] & 0b00111111) << 12 |
211
664
                            (data[pos + 2] & 0b00111111) << 6 |
212
664
                            (data[pos + 3] & 0b00111111);
213
664
      if (code_point <= 0xffff || 0x10ffff < code_point) {
214
40
        return 0;
215
40
      }
216
624
      *utf32_output++ = char32_t(code_point);
217
624
      pos += 4;
218
1.81k
    } else {
219
1.81k
      return 0;
220
1.81k
    }
221
115k
  }
222
6.75k
  return utf32_output - start;
223
9.77k
}
224
225
1.43k
size_t utf8_length_from_utf32(const char32_t* buf, size_t len) {
226
  // We are not BOM aware.
227
1.43k
  const uint32_t* p = reinterpret_cast<const uint32_t*>(buf);
228
1.43k
  size_t counter{0};
229
7.25k
  for (size_t i = 0; i < len; i++) {
230
    /** ASCII **/
231
5.82k
    if (p[i] <= 0x7F) {
232
1.97k
      counter++;
233
1.97k
    }
234
    /** two-byte **/
235
3.84k
    else if (p[i] <= 0x7FF) {
236
804
      counter += 2;
237
804
    }
238
    /** three-byte **/
239
3.04k
    else if (p[i] <= 0xFFFF) {
240
1.91k
      counter += 3;
241
1.91k
    }
242
    /** four-bytes **/
243
1.12k
    else {
244
1.12k
      counter += 4;
245
1.12k
    }
246
5.82k
  }
247
1.43k
  return counter;
248
1.43k
}
249
250
9.77k
size_t utf32_length_from_utf8(const char* buf, size_t len) {
251
9.77k
  const int8_t* p = reinterpret_cast<const int8_t*>(buf);
252
9.77k
  size_t counter{0};
253
330k
  for (size_t i = 0; i < len; i++) {
254
    // -65 is 0b10111111, anything larger in two-complement's
255
    // should start a new code point.
256
320k
    if (p[i] > -65) {
257
233k
      counter++;
258
233k
    }
259
320k
  }
260
9.77k
  return counter;
261
9.77k
}
262
263
1.43k
size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) {
264
1.43k
  const uint32_t* data = reinterpret_cast<const uint32_t*>(buf);
265
1.43k
  size_t pos = 0;
266
1.43k
  char* start{utf8_output};
267
6.22k
  while (pos < len) {
268
    // try to convert the next block of 2 ASCII characters
269
4.95k
    if (pos + 2 <= len) {  // if it is safe to read 8 more
270
                           // bytes, check that they are ascii
271
3.85k
      uint64_t v;
272
3.85k
      std::memcpy(&v, data + pos, sizeof(uint64_t));
273
3.85k
      if ((v & 0xFFFFFF80FFFFFF80) == 0) {
274
755
        *utf8_output++ = char(buf[pos]);
275
755
        *utf8_output++ = char(buf[pos + 1]);
276
755
        pos += 2;
277
755
        continue;
278
755
      }
279
3.85k
    }
280
4.20k
    uint32_t word = data[pos];
281
4.20k
    if ((word & 0xFFFFFF80) == 0) {
282
      // will generate one UTF-8 bytes
283
467
      *utf8_output++ = char(word);
284
467
      pos++;
285
3.73k
    } else if ((word & 0xFFFFF800) == 0) {
286
      // will generate two UTF-8 bytes
287
      // we have 0b110XXXXX 0b10XXXXXX
288
796
      *utf8_output++ = char((word >> 6) | 0b11000000);
289
796
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
290
796
      pos++;
291
2.94k
    } else if ((word & 0xFFFF0000) == 0) {
292
      // will generate three UTF-8 bytes
293
      // we have 0b1110XXXX 0b10XXXXXX 0b10XXXXXX
294
1.91k
      if (word >= 0xD800 && word <= 0xDFFF) {
295
42
        return 0;
296
42
      }
297
1.86k
      *utf8_output++ = char((word >> 12) | 0b11100000);
298
1.86k
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
299
1.86k
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
300
1.86k
      pos++;
301
1.86k
    } else {
302
      // will generate four UTF-8 bytes
303
      // we have 0b11110XXX 0b10XXXXXX 0b10XXXXXX
304
      // 0b10XXXXXX
305
1.02k
      if (word > 0x10FFFF) {
306
129
        return 0;
307
129
      }
308
900
      *utf8_output++ = char((word >> 18) | 0b11110000);
309
900
      *utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
310
900
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
311
900
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
312
900
      pos++;
313
900
    }
314
4.20k
  }
315
1.26k
  return utf8_output - start;
316
1.43k
}
317
}  // namespace ada::idna
318
/* end file src/unicode_transcoding.cpp */
319
/* begin file src/mapping.cpp */
320
321
#include <algorithm>
322
#include <array>
323
#include <string>
324
325
/* begin file src/mapping_tables.cpp */
326
// IDNA  15.0.0
327
328
// clang-format off
329
#ifndef ADA_IDNA_TABLES_H
330
#define ADA_IDNA_TABLES_H
331
#include <cstdint>
332
333
namespace ada::idna {
334
335
const uint32_t mappings[5164] =
336
{
337
  97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
338
  114, 115, 116, 117, 118, 119, 120, 121, 122, 32, 32, 776, 32, 772, 50, 51, 32, 769,
339
  956, 32, 807, 49, 49, 8260, 52, 49, 8260, 50, 51, 8260, 52, 224, 225, 226, 227,
340
  228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
341
  244, 245, 246, 248, 249, 250, 251, 252, 253, 254, 257, 259, 261, 263, 265, 267,
342
  269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299,
343
  301, 303, 105, 775, 309, 311, 314, 316, 318, 108, 183, 322, 324, 326, 328, 700,
344
  110, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359,
345
  361, 363, 365, 367, 369, 371, 373, 375, 255, 378, 380, 382, 595, 387, 389, 596,
346
  392, 598, 599, 396, 477, 601, 603, 402, 608, 611, 617, 616, 409, 623, 626, 629,
347
  417, 419, 421, 640, 424, 643, 429, 648, 432, 650, 651, 436, 438, 658, 441, 445,
348
  100, 382, 108, 106, 110, 106, 462, 464, 466, 468, 470, 472, 474, 476, 479, 481,
349
  483, 485, 487, 489, 491, 493, 495, 100, 122, 501, 405, 447, 505, 507, 509, 511,
350
  513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535, 537, 539, 541, 543,
351
  414, 547, 549, 551, 553, 555, 557, 559, 561, 563, 11365, 572, 410, 11366, 578, 384,
352
  649, 652, 583, 585, 587, 589, 591, 614, 633, 635, 641, 32, 774, 32, 775, 32, 778,
353
  32, 808, 32, 771, 32, 779, 661, 768, 787, 776, 769, 953, 881, 883, 697, 887, 32,
354
  953, 59, 1011, 32, 776, 769, 940, 941, 942, 943, 972, 973, 974, 945, 946, 947, 948,
355
  949, 950, 951, 952, 954, 955, 957, 958, 959, 960, 961, 963, 964, 965, 966, 967,
356
  968, 969, 970, 971, 983, 985, 987, 989, 991, 993, 995, 997, 999, 1001, 1003, 1005,
357
  1007, 1016, 1019, 891, 892, 893, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111,
358
  1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1072, 1073, 1074, 1075, 1076, 1077,
359
  1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091,
360
  1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1121, 1123,
361
  1125, 1127, 1129, 1131, 1133, 1135, 1137, 1139, 1141, 1143, 1145, 1147, 1149, 1151,
362
  1153, 1163, 1165, 1167, 1169, 1171, 1173, 1175, 1177, 1179, 1181, 1183, 1185, 1187,
363
  1189, 1191, 1193, 1195, 1197, 1199, 1201, 1203, 1205, 1207, 1209, 1211, 1213, 1215,
364
  1218, 1220, 1222, 1224, 1226, 1228, 1230, 1233, 1235, 1237, 1239, 1241, 1243, 1245,
365
  1247, 1249, 1251, 1253, 1255, 1257, 1259, 1261, 1263, 1265, 1267, 1269, 1271, 1273,
366
  1275, 1277, 1279, 1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, 1297, 1299, 1301,
367
  1303, 1305, 1307, 1309, 1311, 1313, 1315, 1317, 1319, 1321, 1323, 1325, 1327, 1377,
368
  1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391,
369
  1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405,
370
  1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1381, 1410, 1575, 1652, 1608,
371
  1652, 1735, 1652, 1610, 1652, 2325, 2364, 2326, 2364, 2327, 2364, 2332, 2364, 2337,
372
  2364, 2338, 2364, 2347, 2364, 2351, 2364, 2465, 2492, 2466, 2492, 2479, 2492, 2610,
373
  2620, 2616, 2620, 2582, 2620, 2583, 2620, 2588, 2620, 2603, 2620, 2849, 2876, 2850,
374
  2876, 3661, 3634, 3789, 3762, 3755, 3737, 3755, 3745, 3851, 3906, 4023, 3916, 4023,
375
  3921, 4023, 3926, 4023, 3931, 4023, 3904, 4021, 3953, 3954, 3953, 3956, 4018, 3968,
376
  4018, 3953, 3968, 4019, 3968, 4019, 3953, 3968, 3986, 4023, 3996, 4023, 4001, 4023,
377
  4006, 4023, 4011, 4023, 3984, 4021, 11559, 11565, 4316, 5104, 5105, 5106, 5107,
378
  5108, 5109, 42571, 4304, 4305, 4306, 4307, 4308, 4309, 4310, 4311, 4312, 4313, 4314,
379
  4315, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329,
380
  4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343,
381
  4344, 4345, 4346, 4349, 4350, 4351, 592, 593, 7426, 604, 7446, 7447, 7453, 7461,
382
  594, 597, 607, 609, 613, 618, 7547, 669, 621, 7557, 671, 625, 624, 627, 628, 632,
383
  642, 427, 7452, 656, 657, 7681, 7683, 7685, 7687, 7689, 7691, 7693, 7695, 7697,
384
  7699, 7701, 7703, 7705, 7707, 7709, 7711, 7713, 7715, 7717, 7719, 7721, 7723, 7725,
385
  7727, 7729, 7731, 7733, 7735, 7737, 7739, 7741, 7743, 7745, 7747, 7749, 7751, 7753,
386
  7755, 7757, 7759, 7761, 7763, 7765, 7767, 7769, 7771, 7773, 7775, 7777, 7779, 7781,
387
  7783, 7785, 7787, 7789, 7791, 7793, 7795, 7797, 7799, 7801, 7803, 7805, 7807, 7809,
388
  7811, 7813, 7815, 7817, 7819, 7821, 7823, 7825, 7827, 7829, 97, 702, 115, 115, 7841,
389
  7843, 7845, 7847, 7849, 7851, 7853, 7855, 7857, 7859, 7861, 7863, 7865, 7867, 7869,
390
  7871, 7873, 7875, 7877, 7879, 7881, 7883, 7885, 7887, 7889, 7891, 7893, 7895, 7897,
391
  7899, 7901, 7903, 7905, 7907, 7909, 7911, 7913, 7915, 7917, 7919, 7921, 7923, 7925,
392
  7927, 7929, 7931, 7933, 7935, 7936, 7937, 7938, 7939, 7940, 7941, 7942, 7943, 7952,
393
  7953, 7954, 7955, 7956, 7957, 7968, 7969, 7970, 7971, 7972, 7973, 7974, 7975, 7984,
394
  7985, 7986, 7987, 7988, 7989, 7990, 7991, 8000, 8001, 8002, 8003, 8004, 8005, 8017,
395
  8019, 8021, 8023, 8032, 8033, 8034, 8035, 8036, 8037, 8038, 8039, 7936, 953, 7937,
396
  953, 7938, 953, 7939, 953, 7940, 953, 7941, 953, 7942, 953, 7943, 953, 7968, 953,
397
  7969, 953, 7970, 953, 7971, 953, 7972, 953, 7973, 953, 7974, 953, 7975, 953, 8032,
398
  953, 8033, 953, 8034, 953, 8035, 953, 8036, 953, 8037, 953, 8038, 953, 8039, 953,
399
  8048, 953, 945, 953, 940, 953, 8118, 953, 8112, 8113, 32, 787, 32, 834, 32, 776,
400
  834, 8052, 953, 951, 953, 942, 953, 8134, 953, 8050, 32, 787, 768, 32, 787, 769,
401
  32, 787, 834, 912, 8144, 8145, 8054, 32, 788, 768, 32, 788, 769, 32, 788, 834, 944,
402
  8160, 8161, 8058, 8165, 32, 776, 768, 96, 8060, 953, 969, 953, 974, 953, 8182, 953,
403
  8056, 8208, 32, 819, 8242, 8242, 8242, 8242, 8242, 8245, 8245, 8245, 8245, 8245,
404
  33, 33, 32, 773, 63, 63, 63, 33, 33, 63, 48, 53, 54, 55, 56, 57, 43, 8722, 61, 40,
405
  41, 97, 47, 99, 97, 47, 115, 176, 99, 99, 47, 111, 99, 47, 117, 176, 102, 115, 109,
406
  116, 101, 108, 116, 109, 1488, 1489, 1490, 1491, 102, 97, 120, 8721, 49, 8260, 55,
407
  49, 8260, 57, 49, 8260, 49, 48, 49, 8260, 51, 50, 8260, 51, 49, 8260, 53, 50, 8260,
408
  53, 51, 8260, 53, 52, 8260, 53, 49, 8260, 54, 53, 8260, 54, 49, 8260, 56, 51, 8260,
409
  56, 53, 8260, 56, 55, 8260, 56, 105, 105, 105, 105, 105, 105, 118, 118, 105, 118,
410
  105, 105, 118, 105, 105, 105, 105, 120, 120, 105, 120, 105, 105, 48, 8260, 51, 8747,
411
  8747, 8747, 8747, 8747, 8750, 8750, 8750, 8750, 8750, 12296, 12297, 49, 50, 49,
412
  51, 49, 52, 49, 53, 49, 54, 49, 55, 49, 56, 49, 57, 50, 48, 40, 49, 41, 40, 50,
413
  41, 40, 51, 41, 40, 52, 41, 40, 53, 41, 40, 54, 41, 40, 55, 41, 40, 56, 41, 40,
414
  57, 41, 40, 49, 48, 41, 40, 49, 49, 41, 40, 49, 50, 41, 40, 49, 51, 41, 40, 49,
415
  52, 41, 40, 49, 53, 41, 40, 49, 54, 41, 40, 49, 55, 41, 40, 49, 56, 41, 40, 49,
416
  57, 41, 40, 50, 48, 41, 40, 97, 41, 40, 98, 41, 40, 99, 41, 40, 100, 41, 40, 101,
417
  41, 40, 102, 41, 40, 103, 41, 40, 104, 41, 40, 105, 41, 40, 106, 41, 40, 107, 41,
418
  40, 108, 41, 40, 109, 41, 40, 110, 41, 40, 111, 41, 40, 112, 41, 40, 113, 41, 40,
419
  114, 41, 40, 115, 41, 40, 116, 41, 40, 117, 41, 40, 118, 41, 40, 119, 41, 40, 120,
420
  41, 40, 121, 41, 40, 122, 41, 58, 58, 61, 61, 61, 10973, 824, 11312, 11313, 11314,
421
  11315, 11316, 11317, 11318, 11319, 11320, 11321, 11322, 11323, 11324, 11325, 11326,
422
  11327, 11328, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 11337, 11338,
423
  11339, 11340, 11341, 11342, 11343, 11344, 11345, 11346, 11347, 11348, 11349, 11350,
424
  11351, 11352, 11353, 11354, 11355, 11356, 11357, 11358, 11359, 11361, 619, 7549,
425
  637, 11368, 11370, 11372, 11379, 11382, 575, 576, 11393, 11395, 11397, 11399, 11401,
426
  11403, 11405, 11407, 11409, 11411, 11413, 11415, 11417, 11419, 11421, 11423, 11425,
427
  11427, 11429, 11431, 11433, 11435, 11437, 11439, 11441, 11443, 11445, 11447, 11449,
428
  11451, 11453, 11455, 11457, 11459, 11461, 11463, 11465, 11467, 11469, 11471, 11473,
429
  11475, 11477, 11479, 11481, 11483, 11485, 11487, 11489, 11491, 11500, 11502, 11507,
430
  11617, 27597, 40863, 19968, 20008, 20022, 20031, 20057, 20101, 20108, 20128, 20154,
431
  20799, 20837, 20843, 20866, 20886, 20907, 20960, 20981, 20992, 21147, 21241, 21269,
432
  21274, 21304, 21313, 21340, 21353, 21378, 21430, 21448, 21475, 22231, 22303, 22763,
433
  22786, 22794, 22805, 22823, 22899, 23376, 23424, 23544, 23567, 23586, 23608, 23662,
434
  23665, 24027, 24037, 24049, 24062, 24178, 24186, 24191, 24308, 24318, 24331, 24339,
435
  24400, 24417, 24435, 24515, 25096, 25142, 25163, 25903, 25908, 25991, 26007, 26020,
436
  26041, 26080, 26085, 26352, 26376, 26408, 27424, 27490, 27513, 27571, 27595, 27604,
437
  27611, 27663, 27668, 27700, 28779, 29226, 29238, 29243, 29247, 29255, 29273, 29275,
438
  29356, 29572, 29577, 29916, 29926, 29976, 29983, 29992, 30000, 30091, 30098, 30326,
439
  30333, 30382, 30399, 30446, 30683, 30690, 30707, 31034, 31160, 31166, 31348, 31435,
440
  31481, 31859, 31992, 32566, 32593, 32650, 32701, 32769, 32780, 32786, 32819, 32895,
441
  32905, 33251, 33258, 33267, 33276, 33292, 33307, 33311, 33390, 33394, 33400, 34381,
442
  34411, 34880, 34892, 34915, 35198, 35211, 35282, 35328, 35895, 35910, 35925, 35960,
443
  35997, 36196, 36208, 36275, 36523, 36554, 36763, 36784, 36789, 37009, 37193, 37318,
444
  37324, 37329, 38263, 38272, 38428, 38582, 38585, 38632, 38737, 38750, 38754, 38761,
445
  38859, 38893, 38899, 38913, 39080, 39131, 39135, 39318, 39321, 39340, 39592, 39640,
446
  39647, 39717, 39727, 39730, 39740, 39770, 40165, 40565, 40575, 40613, 40635, 40643,
447
  40653, 40657, 40697, 40701, 40718, 40723, 40736, 40763, 40778, 40786, 40845, 40860,
448
  40864, 46, 12306, 21316, 21317, 32, 12441, 32, 12442, 12424, 12426, 12467, 12488,
449
  4352, 4353, 4522, 4354, 4524, 4525, 4355, 4356, 4357, 4528, 4529, 4530, 4531, 4532,
450
  4533, 4378, 4358, 4359, 4360, 4385, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368,
451
  4369, 4370, 4449, 4450, 4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460,
452
  4461, 4462, 4463, 4464, 4465, 4466, 4467, 4468, 4469, 4372, 4373, 4551, 4552, 4556,
453
  4558, 4563, 4567, 4569, 4380, 4573, 4575, 4381, 4382, 4384, 4386, 4387, 4391, 4393,
454
  4395, 4396, 4397, 4398, 4399, 4402, 4406, 4416, 4423, 4428, 4593, 4594, 4439, 4440,
455
  4441, 4484, 4485, 4488, 4497, 4498, 4500, 4510, 4513, 19977, 22235, 19978, 20013,
456
  19979, 30002, 19993, 19969, 22825, 22320, 40, 4352, 41, 40, 4354, 41, 40, 4355,
457
  41, 40, 4357, 41, 40, 4358, 41, 40, 4359, 41, 40, 4361, 41, 40, 4363, 41, 40, 4364,
458
  41, 40, 4366, 41, 40, 4367, 41, 40, 4368, 41, 40, 4369, 41, 40, 4370, 41, 40, 44032,
459
  41, 40, 45208, 41, 40, 45796, 41, 40, 46972, 41, 40, 47560, 41, 40, 48148, 41, 40,
460
  49324, 41, 40, 50500, 41, 40, 51088, 41, 40, 52264, 41, 40, 52852, 41, 40, 53440,
461
  41, 40, 54028, 41, 40, 54616, 41, 40, 51452, 41, 40, 50724, 51204, 41, 40, 50724,
462
  54980, 41, 40, 19968, 41, 40, 20108, 41, 40, 19977, 41, 40, 22235, 41, 40, 20116,
463
  41, 40, 20845, 41, 40, 19971, 41, 40, 20843, 41, 40, 20061, 41, 40, 21313, 41, 40,
464
  26376, 41, 40, 28779, 41, 40, 27700, 41, 40, 26408, 41, 40, 37329, 41, 40, 22303,
465
  41, 40, 26085, 41, 40, 26666, 41, 40, 26377, 41, 40, 31038, 41, 40, 21517, 41, 40,
466
  29305, 41, 40, 36001, 41, 40, 31069, 41, 40, 21172, 41, 40, 20195, 41, 40, 21628,
467
  41, 40, 23398, 41, 40, 30435, 41, 40, 20225, 41, 40, 36039, 41, 40, 21332, 41, 40,
468
  31085, 41, 40, 20241, 41, 40, 33258, 41, 40, 33267, 41, 21839, 24188, 31631, 112,
469
  116, 101, 50, 50, 50, 52, 50, 53, 50, 54, 50, 55, 50, 56, 50, 57, 51, 48, 51, 51,
470
  51, 52, 51, 53, 52280, 44256, 51452, 51032, 50864, 31192, 30007, 36969, 20778, 21360,
471
  27880, 38917, 20889, 27491, 24038, 21491, 21307, 23447, 22812, 51, 54, 51, 55, 51,
472
  56, 51, 57, 52, 48, 52, 52, 52, 53, 52, 54, 52, 55, 52, 56, 52, 57, 53, 48, 49,
473
  26376, 50, 26376, 51, 26376, 52, 26376, 53, 26376, 54, 26376, 55, 26376, 56, 26376,
474
  57, 26376, 49, 48, 26376, 49, 49, 26376, 49, 50, 26376, 104, 103, 101, 114, 103,
475
  101, 118, 108, 116, 100, 12450, 12452, 12454, 12456, 12458, 12459, 12461, 12463,
476
  12465, 12469, 12471, 12473, 12475, 12477, 12479, 12481, 12484, 12486, 12490, 12491,
477
  12492, 12493, 12494, 12495, 12498, 12501, 12504, 12507, 12510, 12511, 12512, 12513,
478
  12514, 12516, 12518, 12520, 12521, 12522, 12523, 12524, 12525, 12527, 12528, 12529,
479
  12530, 20196, 21644, 12450, 12497, 12540, 12488, 12450, 12523, 12501, 12449, 12450,
480
  12531, 12506, 12450, 12450, 12540, 12523, 12452, 12491, 12531, 12464, 12452, 12531,
481
  12481, 12454, 12457, 12531, 12456, 12473, 12463, 12540, 12489, 12456, 12540, 12459,
482
  12540, 12458, 12531, 12473, 12458, 12540, 12512, 12459, 12452, 12522, 12459, 12521,
483
  12483, 12488, 12459, 12525, 12522, 12540, 12460, 12525, 12531, 12460, 12531, 12510,
484
  12462, 12460, 12462, 12491, 12540, 12461, 12517, 12522, 12540, 12462, 12523, 12480,
485
  12540, 12461, 12525, 12461, 12525, 12464, 12521, 12512, 12461, 12525, 12513, 12540,
486
  12488, 12523, 12461, 12525, 12527, 12483, 12488, 12464, 12521, 12512, 12488, 12531,
487
  12463, 12523, 12476, 12452, 12525, 12463, 12525, 12540, 12493, 12465, 12540, 12473,
488
  12467, 12523, 12490, 12467, 12540, 12509, 12469, 12452, 12463, 12523, 12469, 12531,
489
  12481, 12540, 12512, 12471, 12522, 12531, 12464, 12475, 12531, 12481, 12475, 12531,
490
  12488, 12480, 12540, 12473, 12487, 12471, 12489, 12523, 12490, 12494, 12494, 12483,
491
  12488, 12495, 12452, 12484, 12497, 12540, 12475, 12531, 12488, 12497, 12540, 12484,
492
  12496, 12540, 12524, 12523, 12500, 12450, 12473, 12488, 12523, 12500, 12463, 12523,
493
  12500, 12467, 12499, 12523, 12501, 12449, 12521, 12483, 12489, 12501, 12451, 12540,
494
  12488, 12502, 12483, 12471, 12455, 12523, 12501, 12521, 12531, 12504, 12463, 12479,
495
  12540, 12523, 12506, 12477, 12506, 12491, 12498, 12504, 12523, 12484, 12506, 12531,
496
  12473, 12506, 12540, 12472, 12505, 12540, 12479, 12509, 12452, 12531, 12488, 12508,
497
  12523, 12488, 12507, 12531, 12509, 12531, 12489, 12507, 12540, 12523, 12507, 12540,
498
  12531, 12510, 12452, 12463, 12525, 12510, 12452, 12523, 12510, 12483, 12495, 12510,
499
  12523, 12463, 12510, 12531, 12471, 12519, 12531, 12511, 12463, 12525, 12531, 12511,
500
  12522, 12511, 12522, 12496, 12540, 12523, 12513, 12460, 12513, 12460, 12488, 12531,
501
  12516, 12540, 12489, 12516, 12540, 12523, 12518, 12450, 12531, 12522, 12483, 12488,
502
  12523, 12522, 12521, 12523, 12500, 12540, 12523, 12540, 12502, 12523, 12524, 12512,
503
  12524, 12531, 12488, 12466, 12531, 48, 28857, 49, 28857, 50, 28857, 51, 28857, 52,
504
  28857, 53, 28857, 54, 28857, 55, 28857, 56, 28857, 57, 28857, 49, 48, 28857, 49,
505
  49, 28857, 49, 50, 28857, 49, 51, 28857, 49, 52, 28857, 49, 53, 28857, 49, 54, 28857,
506
  49, 55, 28857, 49, 56, 28857, 49, 57, 28857, 50, 48, 28857, 50, 49, 28857, 50, 50,
507
  28857, 50, 51, 28857, 50, 52, 28857, 104, 112, 97, 100, 97, 97, 117, 98, 97, 114,
508
  111, 118, 112, 99, 100, 109, 100, 109, 50, 100, 109, 51, 105, 117, 24179, 25104,
509
  26157, 21644, 22823, 27491, 26126, 27835, 26666, 24335, 20250, 31038, 110, 97, 956,
510
  97, 109, 97, 107, 97, 107, 98, 109, 98, 103, 98, 99, 97, 108, 107, 99, 97, 108,
511
  112, 102, 110, 102, 956, 102, 956, 103, 109, 103, 107, 103, 104, 122, 107, 104,
512
  122, 109, 104, 122, 116, 104, 122, 956, 108, 109, 108, 100, 108, 102, 109, 110,
513
  109, 956, 109, 109, 109, 99, 109, 107, 109, 109, 109, 50, 99, 109, 50, 107, 109,
514
  50, 109, 109, 51, 99, 109, 51, 107, 109, 51, 109, 8725, 115, 109, 8725, 115, 50,
515
  107, 112, 97, 109, 112, 97, 103, 112, 97, 114, 97, 100, 114, 97, 100, 8725, 115,
516
  114, 97, 100, 8725, 115, 50, 112, 115, 110, 115, 956, 115, 109, 115, 112, 118, 110,
517
  118, 956, 118, 109, 118, 107, 118, 112, 119, 110, 119, 956, 119, 109, 119, 107,
518
  119, 107, 969, 109, 969, 98, 113, 99, 8725, 107, 103, 100, 98, 103, 121, 104, 97,
519
  105, 110, 107, 107, 107, 116, 108, 110, 108, 111, 103, 108, 120, 109, 105, 108,
520
  109, 111, 108, 112, 104, 112, 112, 109, 112, 114, 115, 118, 119, 98, 118, 8725,
521
  109, 97, 8725, 109, 49, 26085, 50, 26085, 51, 26085, 52, 26085, 53, 26085, 54, 26085,
522
  55, 26085, 56, 26085, 57, 26085, 49, 48, 26085, 49, 49, 26085, 49, 50, 26085, 49,
523
  51, 26085, 49, 52, 26085, 49, 53, 26085, 49, 54, 26085, 49, 55, 26085, 49, 56, 26085,
524
  49, 57, 26085, 50, 48, 26085, 50, 49, 26085, 50, 50, 26085, 50, 51, 26085, 50, 52,
525
  26085, 50, 53, 26085, 50, 54, 26085, 50, 55, 26085, 50, 56, 26085, 50, 57, 26085,
526
  51, 48, 26085, 51, 49, 26085, 103, 97, 108, 42561, 42563, 42565, 42567, 42569, 42573,
527
  42575, 42577, 42579, 42581, 42583, 42585, 42587, 42589, 42591, 42593, 42595, 42597,
528
  42599, 42601, 42603, 42605, 42625, 42627, 42629, 42631, 42633, 42635, 42637, 42639,
529
  42641, 42643, 42645, 42647, 42649, 42651, 42787, 42789, 42791, 42793, 42795, 42797,
530
  42799, 42803, 42805, 42807, 42809, 42811, 42813, 42815, 42817, 42819, 42821, 42823,
531
  42825, 42827, 42829, 42831, 42833, 42835, 42837, 42839, 42841, 42843, 42845, 42847,
532
  42849, 42851, 42853, 42855, 42857, 42859, 42861, 42863, 42874, 42876, 7545, 42879,
533
  42881, 42883, 42885, 42887, 42892, 42897, 42899, 42903, 42905, 42907, 42909, 42911,
534
  42913, 42915, 42917, 42919, 42921, 620, 670, 647, 43859, 42933, 42935, 42937, 42939,
535
  42941, 42943, 42945, 42947, 42900, 7566, 42952, 42954, 42961, 42967, 42969, 42998,
536
  43831, 43858, 653, 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034,
537
  5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044, 5045, 5046, 5047, 5048,
538
  5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058, 5059, 5060, 5061, 5062,
539
  5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072, 5073, 5074, 5075, 5076,
540
  5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086, 5087, 5088, 5089, 5090,
541
  5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103, 35912,
542
  26356, 36040, 28369, 20018, 21477, 22865, 21895, 22856, 25078, 30313, 32645, 34367,
543
  34746, 35064, 37007, 27138, 27931, 28889, 29662, 33853, 37226, 39409, 20098, 21365,
544
  27396, 29211, 34349, 40478, 23888, 28651, 34253, 35172, 25289, 33240, 34847, 24266,
545
  26391, 28010, 29436, 37070, 20358, 20919, 21214, 25796, 27347, 29200, 30439, 34310,
546
  34396, 36335, 38706, 39791, 40442, 30860, 31103, 32160, 33737, 37636, 35542, 22751,
547
  24324, 31840, 32894, 29282, 30922, 36034, 38647, 22744, 23650, 27155, 28122, 28431,
548
  32047, 32311, 38475, 21202, 32907, 20956, 20940, 31260, 32190, 33777, 38517, 35712,
549
  25295, 35582, 20025, 23527, 24594, 29575, 30064, 21271, 30971, 20415, 24489, 19981,
550
  27852, 25976, 32034, 21443, 22622, 30465, 33865, 35498, 27578, 27784, 25342, 33509,
551
  25504, 30053, 20142, 20841, 20937, 26753, 31975, 33391, 35538, 37327, 21237, 21570,
552
  24300, 26053, 28670, 31018, 38317, 39530, 40599, 40654, 26310, 27511, 36706, 24180,
553
  24976, 25088, 25754, 28451, 29001, 29833, 31178, 32244, 32879, 36646, 34030, 36899,
554
  37706, 21015, 21155, 21693, 28872, 35010, 24265, 24565, 25467, 27566, 31806, 29557,
555
  22265, 23994, 24604, 29618, 29801, 32666, 32838, 37428, 38646, 38728, 38936, 20363,
556
  31150, 37300, 38584, 24801, 20102, 20698, 23534, 23615, 26009, 29134, 30274, 34044,
557
  36988, 26248, 38446, 21129, 26491, 26611, 27969, 28316, 29705, 30041, 30827, 32016,
558
  39006, 25134, 38520, 20523, 23833, 28138, 36650, 24459, 24900, 26647, 38534, 21033,
559
  21519, 23653, 26131, 26446, 26792, 27877, 29702, 30178, 32633, 35023, 35041, 38626,
560
  21311, 28346, 21533, 29136, 29848, 34298, 38563, 40023, 40607, 26519, 28107, 33256,
561
  31520, 31890, 29376, 28825, 35672, 20160, 33590, 21050, 20999, 24230, 25299, 31958,
562
  23429, 27934, 26292, 36667, 38477, 24275, 20800, 21952, 22618, 26228, 20958, 29482,
563
  30410, 31036, 31070, 31077, 31119, 38742, 31934, 34322, 35576, 36920, 37117, 39151,
564
  39164, 39208, 40372, 37086, 38583, 20398, 20711, 20813, 21193, 21220, 21329, 21917,
565
  22022, 22120, 22592, 22696, 23652, 24724, 24936, 24974, 25074, 25935, 26082, 26257,
566
  26757, 28023, 28186, 28450, 29038, 29227, 29730, 30865, 31049, 31048, 31056, 31062,
567
  31117, 31118, 31296, 31361, 31680, 32265, 32321, 32626, 32773, 33261, 33401, 33879,
568
  35088, 35222, 35585, 35641, 36051, 36104, 36790, 38627, 38911, 38971, 24693, 148206,
569
  33304, 20006, 20917, 20840, 20352, 20805, 20864, 21191, 21242, 21845, 21913, 21986,
570
  22707, 22852, 22868, 23138, 23336, 24274, 24281, 24425, 24493, 24792, 24910, 24840,
571
  24928, 25140, 25540, 25628, 25682, 25942, 26395, 26454, 28379, 28363, 28702, 30631,
572
  29237, 29359, 29809, 29958, 30011, 30237, 30239, 30427, 30452, 30538, 30528, 30924,
573
  31409, 31867, 32091, 32574, 33618, 33775, 34681, 35137, 35206, 35519, 35531, 35565,
574
  35722, 36664, 36978, 37273, 37494, 38524, 38875, 38923, 39698, 141386, 141380, 144341,
575
  15261, 16408, 16441, 152137, 154832, 163539, 40771, 40846, 102, 102, 102, 105, 102,
576
  108, 102, 102, 108, 1396, 1398, 1396, 1381, 1396, 1387, 1406, 1398, 1396, 1389,
577
  1497, 1460, 1522, 1463, 1506, 1492, 1499, 1500, 1501, 1512, 1514, 1513, 1473, 1513,
578
  1474, 1513, 1468, 1473, 1513, 1468, 1474, 1488, 1463, 1488, 1464, 1488, 1468, 1489,
579
  1468, 1490, 1468, 1491, 1468, 1492, 1468, 1493, 1468, 1494, 1468, 1496, 1468, 1497,
580
  1468, 1498, 1468, 1499, 1468, 1500, 1468, 1502, 1468, 1504, 1468, 1505, 1468, 1507,
581
  1468, 1508, 1468, 1510, 1468, 1511, 1468, 1512, 1468, 1514, 1468, 1493, 1465, 1489,
582
  1471, 1499, 1471, 1508, 1471, 1488, 1500, 1649, 1659, 1662, 1664, 1658, 1663, 1657,
583
  1700, 1702, 1668, 1667, 1670, 1671, 1677, 1676, 1678, 1672, 1688, 1681, 1705, 1711,
584
  1715, 1713, 1722, 1723, 1728, 1729, 1726, 1746, 1747, 1709, 1734, 1736, 1739, 1733,
585
  1737, 1744, 1609, 1574, 1575, 1574, 1749, 1574, 1608, 1574, 1735, 1574, 1734, 1574,
586
  1736, 1574, 1744, 1574, 1609, 1740, 1574, 1580, 1574, 1581, 1574, 1605, 1574, 1610,
587
  1576, 1580, 1576, 1581, 1576, 1582, 1576, 1605, 1576, 1609, 1576, 1610, 1578, 1580,
588
  1578, 1581, 1578, 1582, 1578, 1605, 1578, 1609, 1578, 1610, 1579, 1580, 1579, 1605,
589
  1579, 1609, 1579, 1610, 1580, 1581, 1580, 1605, 1581, 1605, 1582, 1580, 1582, 1581,
590
  1582, 1605, 1587, 1580, 1587, 1581, 1587, 1582, 1587, 1605, 1589, 1581, 1589, 1605,
591
  1590, 1580, 1590, 1581, 1590, 1582, 1590, 1605, 1591, 1581, 1591, 1605, 1592, 1605,
592
  1593, 1580, 1593, 1605, 1594, 1580, 1594, 1605, 1601, 1580, 1601, 1581, 1601, 1582,
593
  1601, 1605, 1601, 1609, 1601, 1610, 1602, 1581, 1602, 1605, 1602, 1609, 1602, 1610,
594
  1603, 1575, 1603, 1580, 1603, 1581, 1603, 1582, 1603, 1604, 1603, 1605, 1603, 1609,
595
  1603, 1610, 1604, 1580, 1604, 1581, 1604, 1582, 1604, 1605, 1604, 1609, 1604, 1610,
596
  1605, 1580, 1605, 1605, 1605, 1609, 1605, 1610, 1606, 1580, 1606, 1581, 1606, 1582,
597
  1606, 1605, 1606, 1609, 1606, 1610, 1607, 1580, 1607, 1605, 1607, 1609, 1607, 1610,
598
  1610, 1581, 1610, 1582, 1610, 1609, 1584, 1648, 1585, 1648, 1609, 1648, 32, 1612,
599
  1617, 32, 1613, 1617, 32, 1614, 1617, 32, 1615, 1617, 32, 1616, 1617, 32, 1617,
600
  1648, 1574, 1585, 1574, 1586, 1574, 1606, 1576, 1585, 1576, 1586, 1576, 1606, 1578,
601
  1585, 1578, 1586, 1578, 1606, 1579, 1585, 1579, 1586, 1579, 1606, 1605, 1575, 1606,
602
  1585, 1606, 1586, 1606, 1606, 1610, 1585, 1610, 1586, 1574, 1582, 1574, 1607, 1576,
603
  1607, 1578, 1607, 1589, 1582, 1604, 1607, 1606, 1607, 1607, 1648, 1579, 1607, 1587,
604
  1607, 1588, 1605, 1588, 1607, 1600, 1614, 1617, 1600, 1615, 1617, 1600, 1616, 1617,
605
  1591, 1609, 1591, 1610, 1593, 1609, 1593, 1610, 1594, 1609, 1594, 1610, 1587, 1609,
606
  1587, 1610, 1588, 1609, 1588, 1610, 1581, 1609, 1580, 1609, 1580, 1610, 1582, 1609,
607
  1589, 1609, 1589, 1610, 1590, 1609, 1590, 1610, 1588, 1580, 1588, 1581, 1588, 1582,
608
  1588, 1585, 1587, 1585, 1589, 1585, 1590, 1585, 1575, 1611, 1578, 1580, 1605, 1578,
609
  1581, 1580, 1578, 1581, 1605, 1578, 1582, 1605, 1578, 1605, 1580, 1578, 1605, 1581,
610
  1578, 1605, 1582, 1581, 1605, 1610, 1581, 1605, 1609, 1587, 1581, 1580, 1587, 1580,
611
  1581, 1587, 1580, 1609, 1587, 1605, 1581, 1587, 1605, 1580, 1587, 1605, 1605, 1589,
612
  1581, 1581, 1589, 1605, 1605, 1588, 1581, 1605, 1588, 1580, 1610, 1588, 1605, 1582,
613
  1588, 1605, 1605, 1590, 1581, 1609, 1590, 1582, 1605, 1591, 1605, 1581, 1591, 1605,
614
  1605, 1591, 1605, 1610, 1593, 1580, 1605, 1593, 1605, 1605, 1593, 1605, 1609, 1594,
615
  1605, 1605, 1594, 1605, 1610, 1594, 1605, 1609, 1601, 1582, 1605, 1602, 1605, 1581,
616
  1602, 1605, 1605, 1604, 1581, 1605, 1604, 1581, 1610, 1604, 1581, 1609, 1604, 1580,
617
  1580, 1604, 1582, 1605, 1604, 1605, 1581, 1605, 1581, 1580, 1605, 1581, 1610, 1605,
618
  1580, 1581, 1605, 1582, 1605, 1605, 1580, 1582, 1607, 1605, 1580, 1607, 1605, 1605,
619
  1606, 1581, 1605, 1606, 1581, 1609, 1606, 1580, 1605, 1606, 1580, 1609, 1606, 1605,
620
  1610, 1606, 1605, 1609, 1610, 1605, 1605, 1576, 1582, 1610, 1578, 1580, 1610, 1578,
621
  1580, 1609, 1578, 1582, 1610, 1578, 1582, 1609, 1578, 1605, 1610, 1578, 1605, 1609,
622
  1580, 1605, 1610, 1580, 1581, 1609, 1580, 1605, 1609, 1587, 1582, 1609, 1589, 1581,
623
  1610, 1588, 1581, 1610, 1590, 1581, 1610, 1604, 1580, 1610, 1604, 1605, 1610, 1610,
624
  1580, 1610, 1610, 1605, 1610, 1605, 1605, 1610, 1602, 1605, 1610, 1606, 1581, 1610,
625
  1593, 1605, 1610, 1603, 1605, 1610, 1606, 1580, 1581, 1605, 1582, 1610, 1604, 1580,
626
  1605, 1603, 1605, 1605, 1580, 1581, 1610, 1581, 1580, 1610, 1605, 1580, 1610, 1601,
627
  1605, 1610, 1576, 1581, 1610, 1587, 1582, 1610, 1606, 1580, 1610, 1589, 1604, 1746,
628
  1602, 1604, 1746, 1575, 1604, 1604, 1607, 1575, 1603, 1576, 1585, 1605, 1581, 1605,
629
  1583, 1589, 1604, 1593, 1605, 1585, 1587, 1608, 1604, 1593, 1604, 1610, 1607, 1608,
630
  1587, 1604, 1605, 1589, 1604, 1609, 1589, 1604, 1609, 32, 1575, 1604, 1604, 1607,
631
  32, 1593, 1604, 1610, 1607, 32, 1608, 1587, 1604, 1605, 1580, 1604, 32, 1580, 1604,
632
  1575, 1604, 1607, 1585, 1740, 1575, 1604, 44, 12289, 12310, 12311, 8212, 8211, 95,
633
  123, 125, 12308, 12309, 12304, 12305, 12298, 12299, 12300, 12301, 12302, 12303,
634
  91, 93, 35, 38, 42, 45, 60, 62, 92, 36, 37, 64, 32, 1611, 1600, 1611, 1600, 1617,
635
  32, 1618, 1600, 1618, 1569, 1570, 1571, 1572, 1573, 1577, 1604, 1570, 1604, 1571,
636
  1604, 1573, 34, 39, 94, 124, 126, 10629, 10630, 12539, 12453, 12515, 162, 163, 172,
637
  166, 165, 8361, 9474, 8592, 8593, 8594, 8595, 9632, 9675, 66600, 66601, 66602, 66603,
638
  66604, 66605, 66606, 66607, 66608, 66609, 66610, 66611, 66612, 66613, 66614, 66615,
639
  66616, 66617, 66618, 66619, 66620, 66621, 66622, 66623, 66624, 66625, 66626, 66627,
640
  66628, 66629, 66630, 66631, 66632, 66633, 66634, 66635, 66636, 66637, 66638, 66639,
641
  66776, 66777, 66778, 66779, 66780, 66781, 66782, 66783, 66784, 66785, 66786, 66787,
642
  66788, 66789, 66790, 66791, 66792, 66793, 66794, 66795, 66796, 66797, 66798, 66799,
643
  66800, 66801, 66802, 66803, 66804, 66805, 66806, 66807, 66808, 66809, 66810, 66811,
644
  66967, 66968, 66969, 66970, 66971, 66972, 66973, 66974, 66975, 66976, 66977, 66979,
645
  66980, 66981, 66982, 66983, 66984, 66985, 66986, 66987, 66988, 66989, 66990, 66991,
646
  66992, 66993, 66995, 66996, 66997, 66998, 66999, 67000, 67001, 67003, 67004, 720,
647
  721, 665, 675, 43878, 677, 676, 7569, 600, 606, 681, 612, 610, 667, 668, 615, 644,
648
  682, 683, 122628, 42894, 622, 122629, 654, 122630, 630, 631, 634, 122632, 638, 680,
649
  678, 43879, 679, 11377, 655, 673, 674, 664, 448, 449, 450, 122634, 122654, 68800,
650
  68801, 68802, 68803, 68804, 68805, 68806, 68807, 68808, 68809, 68810, 68811, 68812,
651
  68813, 68814, 68815, 68816, 68817, 68818, 68819, 68820, 68821, 68822, 68823, 68824,
652
  68825, 68826, 68827, 68828, 68829, 68830, 68831, 68832, 68833, 68834, 68835, 68836,
653
  68837, 68838, 68839, 68840, 68841, 68842, 68843, 68844, 68845, 68846, 68847, 68848,
654
  68849, 68850, 71872, 71873, 71874, 71875, 71876, 71877, 71878, 71879, 71880, 71881,
655
  71882, 71883, 71884, 71885, 71886, 71887, 71888, 71889, 71890, 71891, 71892, 71893,
656
  71894, 71895, 71896, 71897, 71898, 71899, 71900, 71901, 71902, 71903, 93792, 93793,
657
  93794, 93795, 93796, 93797, 93798, 93799, 93800, 93801, 93802, 93803, 93804, 93805,
658
  93806, 93807, 93808, 93809, 93810, 93811, 93812, 93813, 93814, 93815, 93816, 93817,
659
  93818, 93819, 93820, 93821, 93822, 93823, 119127, 119141, 119128, 119141, 119128,
660
  119141, 119150, 119128, 119141, 119151, 119128, 119141, 119152, 119128, 119141,
661
  119153, 119128, 119141, 119154, 119225, 119141, 119226, 119141, 119225, 119141,
662
  119150, 119226, 119141, 119150, 119225, 119141, 119151, 119226, 119141, 119151,
663
  305, 567, 8711, 8706, 1231, 125218, 125219, 125220, 125221, 125222, 125223, 125224,
664
  125225, 125226, 125227, 125228, 125229, 125230, 125231, 125232, 125233, 125234,
665
  125235, 125236, 125237, 125238, 125239, 125240, 125241, 125242, 125243, 125244,
666
  125245, 125246, 125247, 125248, 125249, 125250, 125251, 1646, 1697, 1647, 48, 44,
667
  49, 44, 50, 44, 51, 44, 52, 44, 53, 44, 54, 44, 55, 44, 56, 44, 57, 44, 12308, 115,
668
  12309, 119, 122, 104, 118, 115, 100, 112, 112, 118, 119, 99, 109, 114, 100, 106,
669
  12411, 12363, 12467, 12467, 23383, 21452, 22810, 35299, 20132, 26144, 28961, 21069,
670
  24460, 20877, 26032, 21021, 32066, 36009, 22768, 21561, 28436, 25237, 25429, 36938,
671
  25351, 25171, 31105, 31354, 21512, 28288, 30003, 21106, 21942, 37197, 12308, 26412,
672
  12309, 12308, 19977, 12309, 12308, 20108, 12309, 12308, 23433, 12309, 12308, 28857,
673
  12309, 12308, 25171, 12309, 12308, 30423, 12309, 12308, 21213, 12309, 12308, 25943,
674
  12309, 24471, 21487, 20029, 20024, 20033, 131362, 20320, 20411, 20482, 20602, 20633,
675
  20687, 13470, 132666, 20820, 20836, 20855, 132380, 13497, 20839, 132427, 20887,
676
  20900, 20172, 20908, 168415, 20995, 13535, 21051, 21062, 21111, 13589, 21253, 21254,
677
  21321, 21338, 21363, 21373, 21375, 133676, 28784, 21450, 21471, 133987, 21483, 21489,
678
  21510, 21662, 21560, 21576, 21608, 21666, 21750, 21776, 21843, 21859, 21892, 21931,
679
  21939, 21954, 22294, 22295, 22097, 22132, 22766, 22478, 22516, 22541, 22411, 22578,
680
  22577, 22700, 136420, 22770, 22775, 22790, 22818, 22882, 136872, 136938, 23020,
681
  23067, 23079, 23000, 23142, 14062, 23304, 23358, 137672, 23491, 23512, 23539, 138008,
682
  23551, 23558, 14209, 23648, 23744, 23693, 138724, 23875, 138726, 23918, 23915, 23932,
683
  24033, 24034, 14383, 24061, 24104, 24125, 24169, 14434, 139651, 14460, 24240, 24243,
684
  24246, 172946, 140081, 33281, 24354, 14535, 144056, 156122, 24418, 24427, 14563,
685
  24474, 24525, 24535, 24569, 24705, 14650, 14620, 141012, 24775, 24904, 24908, 24954,
686
  25010, 24996, 25007, 25054, 25115, 25181, 25265, 25300, 25424, 142092, 25405, 25340,
687
  25448, 25475, 25572, 142321, 25634, 25541, 25513, 14894, 25705, 25726, 25757, 25719,
688
  14956, 25964, 143370, 26083, 26360, 26185, 15129, 15112, 15076, 20882, 20885, 26368,
689
  26268, 32941, 17369, 26401, 26462, 26451, 144323, 15177, 26618, 26501, 26706, 144493,
690
  26766, 26655, 26900, 26946, 27043, 27114, 27304, 145059, 27355, 15384, 27425, 145575,
691
  27476, 15438, 27506, 27551, 27579, 146061, 138507, 146170, 27726, 146620, 27839,
692
  27853, 27751, 27926, 27966, 28009, 28024, 28037, 146718, 27956, 28207, 28270, 15667,
693
  28359, 147153, 28153, 28526, 147294, 147342, 28614, 28729, 28699, 15766, 28746,
694
  28797, 28791, 28845, 132389, 28997, 148067, 29084, 29224, 29264, 149000, 29312,
695
  29333, 149301, 149524, 29562, 29579, 16044, 29605, 16056, 29767, 29788, 29829, 29898,
696
  16155, 29988, 150582, 30014, 150674, 139679, 30224, 151457, 151480, 151620, 16380,
697
  16392, 151795, 151794, 151833, 151859, 30494, 30495, 30603, 16454, 16534, 152605,
698
  30798, 16611, 153126, 153242, 153285, 31211, 16687, 31306, 31311, 153980, 154279,
699
  16898, 154539, 31686, 31689, 16935, 154752, 31954, 17056, 31976, 31971, 32000, 155526,
700
  32099, 17153, 32199, 32258, 32325, 17204, 156200, 156231, 17241, 156377, 32634,
701
  156478, 32661, 32762, 156890, 156963, 32864, 157096, 32880, 144223, 17365, 32946,
702
  33027, 17419, 33086, 23221, 157607, 157621, 144275, 144284, 33284, 36766, 17515,
703
  33425, 33419, 33437, 21171, 33457, 33459, 33469, 33510, 158524, 33565, 33635, 33709,
704
  33571, 33725, 33767, 33619, 33738, 33740, 33756, 158774, 159083, 158933, 17707,
705
  34033, 34035, 34070, 160714, 34148, 159532, 17757, 17761, 159665, 159954, 17771,
706
  34384, 34407, 34409, 34473, 34440, 34574, 34530, 34600, 34667, 34694, 34785, 34817,
707
  17913, 34912, 161383, 35031, 35038, 17973, 35066, 13499, 161966, 162150, 18110,
708
  18119, 35488, 162984, 36011, 36033, 36123, 36215, 163631, 133124, 36299, 36284,
709
  36336, 133342, 36564, 165330, 165357, 37012, 37105, 37137, 165678, 37147, 37432,
710
  37591, 37592, 37500, 37881, 37909, 166906, 38283, 18837, 38327, 167287, 18918, 38595,
711
  23986, 38691, 168261, 168474, 19054, 19062, 38880, 168970, 19122, 169110, 38953,
712
  169398, 39138, 19251, 39209, 39335, 39362, 39422, 19406, 170800, 40000, 40189, 19662,
713
  19693, 40295, 172238, 19704, 172293, 172558, 172689, 19798, 40702, 40709, 40719,
714
  40726, 173568,
715
716
};
717
const uint32_t table[8000][2] =
718
{
719
  {0, 1}, {65, 16777219}, {66, 16777475}, {67, 16777731},
720
  {68, 16777987}, {69, 16778243}, {70, 16778499}, {71, 16778755},
721
  {72, 16779011}, {73, 16779267}, {74, 16779523}, {75, 16779779},
722
  {76, 16780035}, {77, 16780291}, {78, 16780547}, {79, 16780803},
723
  {80, 16781059}, {81, 16781315}, {82, 16781571}, {83, 16781827},
724
  {84, 16782083}, {85, 16782339}, {86, 16782595}, {87, 16782851},
725
  {88, 16783107}, {89, 16783363}, {90, 16783619}, {91, 1},
726
  {128, 2}, {160, 16783875}, {161, 1}, {168, 33561347},
727
  {169, 1}, {170, 16777219}, {171, 1}, {173, 0},
728
  {174, 1}, {175, 33561859}, {176, 1}, {178, 16785155},
729
  {179, 16785411}, {180, 33562883}, {181, 16786179}, {182, 1},
730
  {184, 33563651}, {185, 16786947}, {186, 16780803}, {187, 1},
731
  {188, 50341635}, {189, 50342403}, {190, 50343171}, {191, 1},
732
  {192, 16789507}, {193, 16789763}, {194, 16790019}, {195, 16790275},
733
  {196, 16790531}, {197, 16790787}, {198, 16791043}, {199, 16791299},
734
  {200, 16791555}, {201, 16791811}, {202, 16792067}, {203, 16792323},
735
  {204, 16792579}, {205, 16792835}, {206, 16793091}, {207, 16793347},
736
  {208, 16793603}, {209, 16793859}, {210, 16794115}, {211, 16794371},
737
  {212, 16794627}, {213, 16794883}, {214, 16795139}, {215, 1},
738
  {216, 16795395}, {217, 16795651}, {218, 16795907}, {219, 16796163},
739
  {220, 16796419}, {221, 16796675}, {222, 16796931}, {223, 1},
740
  {256, 16797187}, {257, 1}, {258, 16797443}, {259, 1},
741
  {260, 16797699}, {261, 1}, {262, 16797955}, {263, 1},
742
  {264, 16798211}, {265, 1}, {266, 16798467}, {267, 1},
743
  {268, 16798723}, {269, 1}, {270, 16798979}, {271, 1},
744
  {272, 16799235}, {273, 1}, {274, 16799491}, {275, 1},
745
  {276, 16799747}, {277, 1}, {278, 16800003}, {279, 1},
746
  {280, 16800259}, {281, 1}, {282, 16800515}, {283, 1},
747
  {284, 16800771}, {285, 1}, {286, 16801027}, {287, 1},
748
  {288, 16801283}, {289, 1}, {290, 16801539}, {291, 1},
749
  {292, 16801795}, {293, 1}, {294, 16802051}, {295, 1},
750
  {296, 16802307}, {297, 1}, {298, 16802563}, {299, 1},
751
  {300, 16802819}, {301, 1}, {302, 16803075}, {303, 1},
752
  {304, 33580547}, {305, 1}, {306, 33556483}, {308, 16803843},
753
  {309, 1}, {310, 16804099}, {311, 1}, {313, 16804355},
754
  {314, 1}, {315, 16804611}, {316, 1}, {317, 16804867},
755
  {318, 1}, {319, 33582339}, {321, 16805635}, {322, 1},
756
  {323, 16805891}, {324, 1}, {325, 16806147}, {326, 1},
757
  {327, 16806403}, {328, 1}, {329, 33583875}, {330, 16807171},
758
  {331, 1}, {332, 16807427}, {333, 1}, {334, 16807683},
759
  {335, 1}, {336, 16807939}, {337, 1}, {338, 16808195},
760
  {339, 1}, {340, 16808451}, {341, 1}, {342, 16808707},
761
  {343, 1}, {344, 16808963}, {345, 1}, {346, 16809219},
762
  {347, 1}, {348, 16809475}, {349, 1}, {350, 16809731},
763
  {351, 1}, {352, 16809987}, {353, 1}, {354, 16810243},
764
  {355, 1}, {356, 16810499}, {357, 1}, {358, 16810755},
765
  {359, 1}, {360, 16811011}, {361, 1}, {362, 16811267},
766
  {363, 1}, {364, 16811523}, {365, 1}, {366, 16811779},
767
  {367, 1}, {368, 16812035}, {369, 1}, {370, 16812291},
768
  {371, 1}, {372, 16812547}, {373, 1}, {374, 16812803},
769
  {375, 1}, {376, 16813059}, {377, 16813315}, {378, 1},
770
  {379, 16813571}, {380, 1}, {381, 16813827}, {382, 1},
771
  {383, 16781827}, {384, 1}, {385, 16814083}, {386, 16814339},
772
  {387, 1}, {388, 16814595}, {389, 1}, {390, 16814851},
773
  {391, 16815107}, {392, 1}, {393, 16815363}, {394, 16815619},
774
  {395, 16815875}, {396, 1}, {398, 16816131}, {399, 16816387},
775
  {400, 16816643}, {401, 16816899}, {402, 1}, {403, 16817155},
776
  {404, 16817411}, {405, 1}, {406, 16817667}, {407, 16817923},
777
  {408, 16818179}, {409, 1}, {412, 16818435}, {413, 16818691},
778
  {414, 1}, {415, 16818947}, {416, 16819203}, {417, 1},
779
  {418, 16819459}, {419, 1}, {420, 16819715}, {421, 1},
780
  {422, 16819971}, {423, 16820227}, {424, 1}, {425, 16820483},
781
  {426, 1}, {428, 16820739}, {429, 1}, {430, 16820995},
782
  {431, 16821251}, {432, 1}, {433, 16821507}, {434, 16821763},
783
  {435, 16822019}, {436, 1}, {437, 16822275}, {438, 1},
784
  {439, 16822531}, {440, 16822787}, {441, 1}, {444, 16823043},
785
  {445, 1}, {452, 33600515}, {455, 33601027}, {458, 33601539},
786
  {461, 16824835}, {462, 1}, {463, 16825091}, {464, 1},
787
  {465, 16825347}, {466, 1}, {467, 16825603}, {468, 1},
788
  {469, 16825859}, {470, 1}, {471, 16826115}, {472, 1},
789
  {473, 16826371}, {474, 1}, {475, 16826627}, {476, 1},
790
  {478, 16826883}, {479, 1}, {480, 16827139}, {481, 1},
791
  {482, 16827395}, {483, 1}, {484, 16827651}, {485, 1},
792
  {486, 16827907}, {487, 1}, {488, 16828163}, {489, 1},
793
  {490, 16828419}, {491, 1}, {492, 16828675}, {493, 1},
794
  {494, 16828931}, {495, 1}, {497, 33606403}, {500, 16829699},
795
  {501, 1}, {502, 16829955}, {503, 16830211}, {504, 16830467},
796
  {505, 1}, {506, 16830723}, {507, 1}, {508, 16830979},
797
  {509, 1}, {510, 16831235}, {511, 1}, {512, 16831491},
798
  {513, 1}, {514, 16831747}, {515, 1}, {516, 16832003},
799
  {517, 1}, {518, 16832259}, {519, 1}, {520, 16832515},
800
  {521, 1}, {522, 16832771}, {523, 1}, {524, 16833027},
801
  {525, 1}, {526, 16833283}, {527, 1}, {528, 16833539},
802
  {529, 1}, {530, 16833795}, {531, 1}, {532, 16834051},
803
  {533, 1}, {534, 16834307}, {535, 1}, {536, 16834563},
804
  {537, 1}, {538, 16834819}, {539, 1}, {540, 16835075},
805
  {541, 1}, {542, 16835331}, {543, 1}, {544, 16835587},
806
  {545, 1}, {546, 16835843}, {547, 1}, {548, 16836099},
807
  {549, 1}, {550, 16836355}, {551, 1}, {552, 16836611},
808
  {553, 1}, {554, 16836867}, {555, 1}, {556, 16837123},
809
  {557, 1}, {558, 16837379}, {559, 1}, {560, 16837635},
810
  {561, 1}, {562, 16837891}, {563, 1}, {570, 16838147},
811
  {571, 16838403}, {572, 1}, {573, 16838659}, {574, 16838915},
812
  {575, 1}, {577, 16839171}, {578, 1}, {579, 16839427},
813
  {580, 16839683}, {581, 16839939}, {582, 16840195}, {583, 1},
814
  {584, 16840451}, {585, 1}, {586, 16840707}, {587, 1},
815
  {588, 16840963}, {589, 1}, {590, 16841219}, {591, 1},
816
  {688, 16779011}, {689, 16841475}, {690, 16779523}, {691, 16781571},
817
  {692, 16841731}, {693, 16841987}, {694, 16842243}, {695, 16782851},
818
  {696, 16783363}, {697, 1}, {728, 33619715}, {729, 33620227},
819
  {730, 33620739}, {731, 33621251}, {732, 33621763}, {733, 33622275},
820
  {734, 1}, {736, 16817411}, {737, 16780035}, {738, 16781827},
821
  {739, 16783107}, {740, 16845571}, {741, 1}, {832, 16845827},
822
  {833, 16785923}, {834, 1}, {835, 16846083}, {836, 33623555},
823
  {837, 16846851}, {838, 1}, {847, 0}, {848, 1},
824
  {880, 16847107}, {881, 1}, {882, 16847363}, {883, 1},
825
  {884, 16847619}, {885, 1}, {886, 16847875}, {887, 1},
826
  {888, 2}, {890, 33625347}, {891, 1}, {894, 16848643},
827
  {895, 16848899}, {896, 2}, {900, 33562883}, {901, 50403587},
828
  {902, 16849923}, {903, 16805379}, {904, 16850179}, {905, 16850435},
829
  {906, 16850691}, {907, 2}, {908, 16850947}, {909, 2},
830
  {910, 16851203}, {911, 16851459}, {912, 1}, {913, 16851715},
831
  {914, 16851971}, {915, 16852227}, {916, 16852483}, {917, 16852739},
832
  {918, 16852995}, {919, 16853251}, {920, 16853507}, {921, 16846851},
833
  {922, 16853763}, {923, 16854019}, {924, 16786179}, {925, 16854275},
834
  {926, 16854531}, {927, 16854787}, {928, 16855043}, {929, 16855299},
835
  {930, 2}, {931, 16855555}, {932, 16855811}, {933, 16856067},
836
  {934, 16856323}, {935, 16856579}, {936, 16856835}, {937, 16857091},
837
  {938, 16857347}, {939, 16857603}, {940, 1}, {975, 16857859},
838
  {976, 16851971}, {977, 16853507}, {978, 16856067}, {979, 16851203},
839
  {980, 16857603}, {981, 16856323}, {982, 16855043}, {983, 1},
840
  {984, 16858115}, {985, 1}, {986, 16858371}, {987, 1},
841
  {988, 16858627}, {989, 1}, {990, 16858883}, {991, 1},
842
  {992, 16859139}, {993, 1}, {994, 16859395}, {995, 1},
843
  {996, 16859651}, {997, 1}, {998, 16859907}, {999, 1},
844
  {1000, 16860163}, {1001, 1}, {1002, 16860419}, {1003, 1},
845
  {1004, 16860675}, {1005, 1}, {1006, 16860931}, {1007, 1},
846
  {1008, 16853763}, {1009, 16855299}, {1010, 16855555}, {1011, 1},
847
  {1012, 16853507}, {1013, 16852739}, {1014, 1}, {1015, 16861187},
848
  {1016, 1}, {1017, 16855555}, {1018, 16861443}, {1019, 1},
849
  {1021, 16861699}, {1022, 16861955}, {1023, 16862211}, {1024, 16862467},
850
  {1025, 16862723}, {1026, 16862979}, {1027, 16863235}, {1028, 16863491},
851
  {1029, 16863747}, {1030, 16864003}, {1031, 16864259}, {1032, 16864515},
852
  {1033, 16864771}, {1034, 16865027}, {1035, 16865283}, {1036, 16865539},
853
  {1037, 16865795}, {1038, 16866051}, {1039, 16866307}, {1040, 16866563},
854
  {1041, 16866819}, {1042, 16867075}, {1043, 16867331}, {1044, 16867587},
855
  {1045, 16867843}, {1046, 16868099}, {1047, 16868355}, {1048, 16868611},
856
  {1049, 16868867}, {1050, 16869123}, {1051, 16869379}, {1052, 16869635},
857
  {1053, 16869891}, {1054, 16870147}, {1055, 16870403}, {1056, 16870659},
858
  {1057, 16870915}, {1058, 16871171}, {1059, 16871427}, {1060, 16871683},
859
  {1061, 16871939}, {1062, 16872195}, {1063, 16872451}, {1064, 16872707},
860
  {1065, 16872963}, {1066, 16873219}, {1067, 16873475}, {1068, 16873731},
861
  {1069, 16873987}, {1070, 16874243}, {1071, 16874499}, {1072, 1},
862
  {1120, 16874755}, {1121, 1}, {1122, 16875011}, {1123, 1},
863
  {1124, 16875267}, {1125, 1}, {1126, 16875523}, {1127, 1},
864
  {1128, 16875779}, {1129, 1}, {1130, 16876035}, {1131, 1},
865
  {1132, 16876291}, {1133, 1}, {1134, 16876547}, {1135, 1},
866
  {1136, 16876803}, {1137, 1}, {1138, 16877059}, {1139, 1},
867
  {1140, 16877315}, {1141, 1}, {1142, 16877571}, {1143, 1},
868
  {1144, 16877827}, {1145, 1}, {1146, 16878083}, {1147, 1},
869
  {1148, 16878339}, {1149, 1}, {1150, 16878595}, {1151, 1},
870
  {1152, 16878851}, {1153, 1}, {1162, 16879107}, {1163, 1},
871
  {1164, 16879363}, {1165, 1}, {1166, 16879619}, {1167, 1},
872
  {1168, 16879875}, {1169, 1}, {1170, 16880131}, {1171, 1},
873
  {1172, 16880387}, {1173, 1}, {1174, 16880643}, {1175, 1},
874
  {1176, 16880899}, {1177, 1}, {1178, 16881155}, {1179, 1},
875
  {1180, 16881411}, {1181, 1}, {1182, 16881667}, {1183, 1},
876
  {1184, 16881923}, {1185, 1}, {1186, 16882179}, {1187, 1},
877
  {1188, 16882435}, {1189, 1}, {1190, 16882691}, {1191, 1},
878
  {1192, 16882947}, {1193, 1}, {1194, 16883203}, {1195, 1},
879
  {1196, 16883459}, {1197, 1}, {1198, 16883715}, {1199, 1},
880
  {1200, 16883971}, {1201, 1}, {1202, 16884227}, {1203, 1},
881
  {1204, 16884483}, {1205, 1}, {1206, 16884739}, {1207, 1},
882
  {1208, 16884995}, {1209, 1}, {1210, 16885251}, {1211, 1},
883
  {1212, 16885507}, {1213, 1}, {1214, 16885763}, {1215, 1},
884
  {1216, 2}, {1217, 16886019}, {1218, 1}, {1219, 16886275},
885
  {1220, 1}, {1221, 16886531}, {1222, 1}, {1223, 16886787},
886
  {1224, 1}, {1225, 16887043}, {1226, 1}, {1227, 16887299},
887
  {1228, 1}, {1229, 16887555}, {1230, 1}, {1232, 16887811},
888
  {1233, 1}, {1234, 16888067}, {1235, 1}, {1236, 16888323},
889
  {1237, 1}, {1238, 16888579}, {1239, 1}, {1240, 16888835},
890
  {1241, 1}, {1242, 16889091}, {1243, 1}, {1244, 16889347},
891
  {1245, 1}, {1246, 16889603}, {1247, 1}, {1248, 16889859},
892
  {1249, 1}, {1250, 16890115}, {1251, 1}, {1252, 16890371},
893
  {1253, 1}, {1254, 16890627}, {1255, 1}, {1256, 16890883},
894
  {1257, 1}, {1258, 16891139}, {1259, 1}, {1260, 16891395},
895
  {1261, 1}, {1262, 16891651}, {1263, 1}, {1264, 16891907},
896
  {1265, 1}, {1266, 16892163}, {1267, 1}, {1268, 16892419},
897
  {1269, 1}, {1270, 16892675}, {1271, 1}, {1272, 16892931},
898
  {1273, 1}, {1274, 16893187}, {1275, 1}, {1276, 16893443},
899
  {1277, 1}, {1278, 16893699}, {1279, 1}, {1280, 16893955},
900
  {1281, 1}, {1282, 16894211}, {1283, 1}, {1284, 16894467},
901
  {1285, 1}, {1286, 16894723}, {1287, 1}, {1288, 16894979},
902
  {1289, 1}, {1290, 16895235}, {1291, 1}, {1292, 16895491},
903
  {1293, 1}, {1294, 16895747}, {1295, 1}, {1296, 16896003},
904
  {1297, 1}, {1298, 16896259}, {1299, 1}, {1300, 16896515},
905
  {1301, 1}, {1302, 16896771}, {1303, 1}, {1304, 16897027},
906
  {1305, 1}, {1306, 16897283}, {1307, 1}, {1308, 16897539},
907
  {1309, 1}, {1310, 16897795}, {1311, 1}, {1312, 16898051},
908
  {1313, 1}, {1314, 16898307}, {1315, 1}, {1316, 16898563},
909
  {1317, 1}, {1318, 16898819}, {1319, 1}, {1320, 16899075},
910
  {1321, 1}, {1322, 16899331}, {1323, 1}, {1324, 16899587},
911
  {1325, 1}, {1326, 16899843}, {1327, 1}, {1328, 2},
912
  {1329, 16900099}, {1330, 16900355}, {1331, 16900611}, {1332, 16900867},
913
  {1333, 16901123}, {1334, 16901379}, {1335, 16901635}, {1336, 16901891},
914
  {1337, 16902147}, {1338, 16902403}, {1339, 16902659}, {1340, 16902915},
915
  {1341, 16903171}, {1342, 16903427}, {1343, 16903683}, {1344, 16903939},
916
  {1345, 16904195}, {1346, 16904451}, {1347, 16904707}, {1348, 16904963},
917
  {1349, 16905219}, {1350, 16905475}, {1351, 16905731}, {1352, 16905987},
918
  {1353, 16906243}, {1354, 16906499}, {1355, 16906755}, {1356, 16907011},
919
  {1357, 16907267}, {1358, 16907523}, {1359, 16907779}, {1360, 16908035},
920
  {1361, 16908291}, {1362, 16908547}, {1363, 16908803}, {1364, 16909059},
921
  {1365, 16909315}, {1366, 16909571}, {1367, 2}, {1369, 1},
922
  {1415, 33687043}, {1416, 1}, {1419, 2}, {1421, 1},
923
  {1424, 2}, {1425, 1}, {1480, 2}, {1488, 1},
924
  {1515, 2}, {1519, 1}, {1525, 2}, {1542, 1},
925
  {1564, 2}, {1565, 1}, {1653, 33687555}, {1654, 33688067},
926
  {1655, 33688579}, {1656, 33689091}, {1657, 1}, {1757, 2},
927
  {1758, 1}, {1806, 2}, {1808, 1}, {1867, 2},
928
  {1869, 1}, {1970, 2}, {1984, 1}, {2043, 2},
929
  {2045, 1}, {2094, 2}, {2096, 1}, {2111, 2},
930
  {2112, 1}, {2140, 2}, {2142, 1}, {2143, 2},
931
  {2144, 1}, {2155, 2}, {2160, 1}, {2191, 2},
932
  {2200, 1}, {2274, 2}, {2275, 1}, {2392, 33689603},
933
  {2393, 33690115}, {2394, 33690627}, {2395, 33691139}, {2396, 33691651},
934
  {2397, 33692163}, {2398, 33692675}, {2399, 33693187}, {2400, 1},
935
  {2436, 2}, {2437, 1}, {2445, 2}, {2447, 1},
936
  {2449, 2}, {2451, 1}, {2473, 2}, {2474, 1},
937
  {2481, 2}, {2482, 1}, {2483, 2}, {2486, 1},
938
  {2490, 2}, {2492, 1}, {2501, 2}, {2503, 1},
939
  {2505, 2}, {2507, 1}, {2511, 2}, {2519, 1},
940
  {2520, 2}, {2524, 33693699}, {2525, 33694211}, {2526, 2},
941
  {2527, 33694723}, {2528, 1}, {2532, 2}, {2534, 1},
942
  {2559, 2}, {2561, 1}, {2564, 2}, {2565, 1},
943
  {2571, 2}, {2575, 1}, {2577, 2}, {2579, 1},
944
  {2601, 2}, {2602, 1}, {2609, 2}, {2610, 1},
945
  {2611, 33695235}, {2612, 2}, {2613, 1}, {2614, 33695747},
946
  {2615, 2}, {2616, 1}, {2618, 2}, {2620, 1},
947
  {2621, 2}, {2622, 1}, {2627, 2}, {2631, 1},
948
  {2633, 2}, {2635, 1}, {2638, 2}, {2641, 1},
949
  {2642, 2}, {2649, 33696259}, {2650, 33696771}, {2651, 33697283},
950
  {2652, 1}, {2653, 2}, {2654, 33697795}, {2655, 2},
951
  {2662, 1}, {2679, 2}, {2689, 1}, {2692, 2},
952
  {2693, 1}, {2702, 2}, {2703, 1}, {2706, 2},
953
  {2707, 1}, {2729, 2}, {2730, 1}, {2737, 2},
954
  {2738, 1}, {2740, 2}, {2741, 1}, {2746, 2},
955
  {2748, 1}, {2758, 2}, {2759, 1}, {2762, 2},
956
  {2763, 1}, {2766, 2}, {2768, 1}, {2769, 2},
957
  {2784, 1}, {2788, 2}, {2790, 1}, {2802, 2},
958
  {2809, 1}, {2816, 2}, {2817, 1}, {2820, 2},
959
  {2821, 1}, {2829, 2}, {2831, 1}, {2833, 2},
960
  {2835, 1}, {2857, 2}, {2858, 1}, {2865, 2},
961
  {2866, 1}, {2868, 2}, {2869, 1}, {2874, 2},
962
  {2876, 1}, {2885, 2}, {2887, 1}, {2889, 2},
963
  {2891, 1}, {2894, 2}, {2901, 1}, {2904, 2},
964
  {2908, 33698307}, {2909, 33698819}, {2910, 2}, {2911, 1},
965
  {2916, 2}, {2918, 1}, {2936, 2}, {2946, 1},
966
  {2948, 2}, {2949, 1}, {2955, 2}, {2958, 1},
967
  {2961, 2}, {2962, 1}, {2966, 2}, {2969, 1},
968
  {2971, 2}, {2972, 1}, {2973, 2}, {2974, 1},
969
  {2976, 2}, {2979, 1}, {2981, 2}, {2984, 1},
970
  {2987, 2}, {2990, 1}, {3002, 2}, {3006, 1},
971
  {3011, 2}, {3014, 1}, {3017, 2}, {3018, 1},
972
  {3022, 2}, {3024, 1}, {3025, 2}, {3031, 1},
973
  {3032, 2}, {3046, 1}, {3067, 2}, {3072, 1},
974
  {3085, 2}, {3086, 1}, {3089, 2}, {3090, 1},
975
  {3113, 2}, {3114, 1}, {3130, 2}, {3132, 1},
976
  {3141, 2}, {3142, 1}, {3145, 2}, {3146, 1},
977
  {3150, 2}, {3157, 1}, {3159, 2}, {3160, 1},
978
  {3163, 2}, {3165, 1}, {3166, 2}, {3168, 1},
979
  {3172, 2}, {3174, 1}, {3184, 2}, {3191, 1},
980
  {3213, 2}, {3214, 1}, {3217, 2}, {3218, 1},
981
  {3241, 2}, {3242, 1}, {3252, 2}, {3253, 1},
982
  {3258, 2}, {3260, 1}, {3269, 2}, {3270, 1},
983
  {3273, 2}, {3274, 1}, {3278, 2}, {3285, 1},
984
  {3287, 2}, {3293, 1}, {3295, 2}, {3296, 1},
985
  {3300, 2}, {3302, 1}, {3312, 2}, {3313, 1},
986
  {3316, 2}, {3328, 1}, {3341, 2}, {3342, 1},
987
  {3345, 2}, {3346, 1}, {3397, 2}, {3398, 1},
988
  {3401, 2}, {3402, 1}, {3408, 2}, {3412, 1},
989
  {3428, 2}, {3430, 1}, {3456, 2}, {3457, 1},
990
  {3460, 2}, {3461, 1}, {3479, 2}, {3482, 1},
991
  {3506, 2}, {3507, 1}, {3516, 2}, {3517, 1},
992
  {3518, 2}, {3520, 1}, {3527, 2}, {3530, 1},
993
  {3531, 2}, {3535, 1}, {3541, 2}, {3542, 1},
994
  {3543, 2}, {3544, 1}, {3552, 2}, {3558, 1},
995
  {3568, 2}, {3570, 1}, {3573, 2}, {3585, 1},
996
  {3635, 33699331}, {3636, 1}, {3643, 2}, {3647, 1},
997
  {3676, 2}, {3713, 1}, {3715, 2}, {3716, 1},
998
  {3717, 2}, {3718, 1}, {3723, 2}, {3724, 1},
999
  {3748, 2}, {3749, 1}, {3750, 2}, {3751, 1},
1000
  {3763, 33699843}, {3764, 1}, {3774, 2}, {3776, 1},
1001
  {3781, 2}, {3782, 1}, {3783, 2}, {3784, 1},
1002
  {3791, 2}, {3792, 1}, {3802, 2}, {3804, 33700355},
1003
  {3805, 33700867}, {3806, 1}, {3808, 2}, {3840, 1},
1004
  {3852, 16924163}, {3853, 1}, {3907, 33701635}, {3908, 1},
1005
  {3912, 2}, {3913, 1}, {3917, 33702147}, {3918, 1},
1006
  {3922, 33702659}, {3923, 1}, {3927, 33703171}, {3928, 1},
1007
  {3932, 33703683}, {3933, 1}, {3945, 33704195}, {3946, 1},
1008
  {3949, 2}, {3953, 1}, {3955, 33704707}, {3956, 1},
1009
  {3957, 33705219}, {3958, 33705731}, {3959, 50483459}, {3960, 33707011},
1010
  {3961, 50484739}, {3962, 1}, {3969, 33706499}, {3970, 1},
1011
  {3987, 33708291}, {3988, 1}, {3992, 2}, {3993, 1},
1012
  {3997, 33708803}, {3998, 1}, {4002, 33709315}, {4003, 1},
1013
  {4007, 33709827}, {4008, 1}, {4012, 33710339}, {4013, 1},
1014
  {4025, 33710851}, {4026, 1}, {4029, 2}, {4030, 1},
1015
  {4045, 2}, {4046, 1}, {4059, 2}, {4096, 1},
1016
  {4256, 2}, {4295, 16934147}, {4296, 2}, {4301, 16934403},
1017
  {4302, 2}, {4304, 1}, {4348, 16934659}, {4349, 1},
1018
  {4447, 2}, {4449, 1}, {4681, 2}, {4682, 1},
1019
  {4686, 2}, {4688, 1}, {4695, 2}, {4696, 1},
1020
  {4697, 2}, {4698, 1}, {4702, 2}, {4704, 1},
1021
  {4745, 2}, {4746, 1}, {4750, 2}, {4752, 1},
1022
  {4785, 2}, {4786, 1}, {4790, 2}, {4792, 1},
1023
  {4799, 2}, {4800, 1}, {4801, 2}, {4802, 1},
1024
  {4806, 2}, {4808, 1}, {4823, 2}, {4824, 1},
1025
  {4881, 2}, {4882, 1}, {4886, 2}, {4888, 1},
1026
  {4955, 2}, {4957, 1}, {4989, 2}, {4992, 1},
1027
  {5018, 2}, {5024, 1}, {5110, 2}, {5112, 16934915},
1028
  {5113, 16935171}, {5114, 16935427}, {5115, 16935683}, {5116, 16935939},
1029
  {5117, 16936195}, {5118, 2}, {5120, 1}, {5760, 2},
1030
  {5761, 1}, {5789, 2}, {5792, 1}, {5881, 2},
1031
  {5888, 1}, {5910, 2}, {5919, 1}, {5943, 2},
1032
  {5952, 1}, {5972, 2}, {5984, 1}, {5997, 2},
1033
  {5998, 1}, {6001, 2}, {6002, 1}, {6004, 2},
1034
  {6016, 1}, {6068, 2}, {6070, 1}, {6110, 2},
1035
  {6112, 1}, {6122, 2}, {6128, 1}, {6138, 2},
1036
  {6144, 1}, {6150, 2}, {6151, 1}, {6155, 0},
1037
  {6158, 2}, {6159, 0}, {6160, 1}, {6170, 2},
1038
  {6176, 1}, {6265, 2}, {6272, 1}, {6315, 2},
1039
  {6320, 1}, {6390, 2}, {6400, 1}, {6431, 2},
1040
  {6432, 1}, {6444, 2}, {6448, 1}, {6460, 2},
1041
  {6464, 1}, {6465, 2}, {6468, 1}, {6510, 2},
1042
  {6512, 1}, {6517, 2}, {6528, 1}, {6572, 2},
1043
  {6576, 1}, {6602, 2}, {6608, 1}, {6619, 2},
1044
  {6622, 1}, {6684, 2}, {6686, 1}, {6751, 2},
1045
  {6752, 1}, {6781, 2}, {6783, 1}, {6794, 2},
1046
  {6800, 1}, {6810, 2}, {6816, 1}, {6830, 2},
1047
  {6832, 1}, {6863, 2}, {6912, 1}, {6989, 2},
1048
  {6992, 1}, {7039, 2}, {7040, 1}, {7156, 2},
1049
  {7164, 1}, {7224, 2}, {7227, 1}, {7242, 2},
1050
  {7245, 1}, {7296, 16867075}, {7297, 16867587}, {7298, 16870147},
1051
  {7299, 16870915}, {7300, 16871171}, {7302, 16873219}, {7303, 16875011},
1052
  {7304, 16936451}, {7305, 2}, {7312, 16936707}, {7313, 16936963},
1053
  {7314, 16937219}, {7315, 16937475}, {7316, 16937731}, {7317, 16937987},
1054
  {7318, 16938243}, {7319, 16938499}, {7320, 16938755}, {7321, 16939011},
1055
  {7322, 16939267}, {7323, 16939523}, {7324, 16934659}, {7325, 16939779},
1056
  {7326, 16940035}, {7327, 16940291}, {7328, 16940547}, {7329, 16940803},
1057
  {7330, 16941059}, {7331, 16941315}, {7332, 16941571}, {7333, 16941827},
1058
  {7334, 16942083}, {7335, 16942339}, {7336, 16942595}, {7337, 16942851},
1059
  {7338, 16943107}, {7339, 16943363}, {7340, 16943619}, {7341, 16943875},
1060
  {7342, 16944131}, {7343, 16944387}, {7344, 16944643}, {7345, 16944899},
1061
  {7346, 16945155}, {7347, 16945411}, {7348, 16945667}, {7349, 16945923},
1062
  {7350, 16946179}, {7351, 16946435}, {7352, 16946691}, {7353, 16946947},
1063
  {7354, 16947203}, {7355, 2}, {7357, 16947459}, {7358, 16947715},
1064
  {7359, 16947971}, {7360, 1}, {7368, 2}, {7376, 1},
1065
  {7419, 2}, {7424, 1}, {7468, 16777219}, {7469, 16791043},
1066
  {7470, 16777475}, {7471, 1}, {7472, 16777987}, {7473, 16778243},
1067
  {7474, 16816131}, {7475, 16778755}, {7476, 16779011}, {7477, 16779267},
1068
  {7478, 16779523}, {7479, 16779779}, {7480, 16780035}, {7481, 16780291},
1069
  {7482, 16780547}, {7483, 1}, {7484, 16780803}, {7485, 16835843},
1070
  {7486, 16781059}, {7487, 16781571}, {7488, 16782083}, {7489, 16782339},
1071
  {7490, 16782851}, {7491, 16777219}, {7492, 16948227}, {7493, 16948483},
1072
  {7494, 16948739}, {7495, 16777475}, {7496, 16777987}, {7497, 16778243},
1073
  {7498, 16816387}, {7499, 16816643}, {7500, 16948995}, {7501, 16778755},
1074
  {7502, 1}, {7503, 16779779}, {7504, 16780291}, {7505, 16807171},
1075
  {7506, 16780803}, {7507, 16814851}, {7508, 16949251}, {7509, 16949507},
1076
  {7510, 16781059}, {7511, 16782083}, {7512, 16782339}, {7513, 16949763},
1077
  {7514, 16818435}, {7515, 16782595}, {7516, 16950019}, {7517, 16851971},
1078
  {7518, 16852227}, {7519, 16852483}, {7520, 16856323}, {7521, 16856579},
1079
  {7522, 16779267}, {7523, 16781571}, {7524, 16782339}, {7525, 16782595},
1080
  {7526, 16851971}, {7527, 16852227}, {7528, 16855299}, {7529, 16856323},
1081
  {7530, 16856579}, {7531, 1}, {7544, 16869891}, {7545, 1},
1082
  {7579, 16950275}, {7580, 16777731}, {7581, 16950531}, {7582, 16793603},
1083
  {7583, 16948995}, {7584, 16778499}, {7585, 16950787}, {7586, 16951043},
1084
  {7587, 16951299}, {7588, 16817923}, {7589, 16817667}, {7590, 16951555},
1085
  {7591, 16951811}, {7592, 16952067}, {7593, 16952323}, {7594, 16952579},
1086
  {7595, 16952835}, {7596, 16953091}, {7597, 16953347}, {7598, 16818691},
1087
  {7599, 16953603}, {7600, 16953859}, {7601, 16818947}, {7602, 16954115},
1088
  {7603, 16954371}, {7604, 16820483}, {7605, 16954627}, {7606, 16839683},
1089
  {7607, 16821507}, {7608, 16954883}, {7609, 16821763}, {7610, 16839939},
1090
  {7611, 16783619}, {7612, 16955139}, {7613, 16955395}, {7614, 16822531},
1091
  {7615, 16853507}, {7616, 1}, {7680, 16955651}, {7681, 1},
1092
  {7682, 16955907}, {7683, 1}, {7684, 16956163}, {7685, 1},
1093
  {7686, 16956419}, {7687, 1}, {7688, 16956675}, {7689, 1},
1094
  {7690, 16956931}, {7691, 1}, {7692, 16957187}, {7693, 1},
1095
  {7694, 16957443}, {7695, 1}, {7696, 16957699}, {7697, 1},
1096
  {7698, 16957955}, {7699, 1}, {7700, 16958211}, {7701, 1},
1097
  {7702, 16958467}, {7703, 1}, {7704, 16958723}, {7705, 1},
1098
  {7706, 16958979}, {7707, 1}, {7708, 16959235}, {7709, 1},
1099
  {7710, 16959491}, {7711, 1}, {7712, 16959747}, {7713, 1},
1100
  {7714, 16960003}, {7715, 1}, {7716, 16960259}, {7717, 1},
1101
  {7718, 16960515}, {7719, 1}, {7720, 16960771}, {7721, 1},
1102
  {7722, 16961027}, {7723, 1}, {7724, 16961283}, {7725, 1},
1103
  {7726, 16961539}, {7727, 1}, {7728, 16961795}, {7729, 1},
1104
  {7730, 16962051}, {7731, 1}, {7732, 16962307}, {7733, 1},
1105
  {7734, 16962563}, {7735, 1}, {7736, 16962819}, {7737, 1},
1106
  {7738, 16963075}, {7739, 1}, {7740, 16963331}, {7741, 1},
1107
  {7742, 16963587}, {7743, 1}, {7744, 16963843}, {7745, 1},
1108
  {7746, 16964099}, {7747, 1}, {7748, 16964355}, {7749, 1},
1109
  {7750, 16964611}, {7751, 1}, {7752, 16964867}, {7753, 1},
1110
  {7754, 16965123}, {7755, 1}, {7756, 16965379}, {7757, 1},
1111
  {7758, 16965635}, {7759, 1}, {7760, 16965891}, {7761, 1},
1112
  {7762, 16966147}, {7763, 1}, {7764, 16966403}, {7765, 1},
1113
  {7766, 16966659}, {7767, 1}, {7768, 16966915}, {7769, 1},
1114
  {7770, 16967171}, {7771, 1}, {7772, 16967427}, {7773, 1},
1115
  {7774, 16967683}, {7775, 1}, {7776, 16967939}, {7777, 1},
1116
  {7778, 16968195}, {7779, 1}, {7780, 16968451}, {7781, 1},
1117
  {7782, 16968707}, {7783, 1}, {7784, 16968963}, {7785, 1},
1118
  {7786, 16969219}, {7787, 1}, {7788, 16969475}, {7789, 1},
1119
  {7790, 16969731}, {7791, 1}, {7792, 16969987}, {7793, 1},
1120
  {7794, 16970243}, {7795, 1}, {7796, 16970499}, {7797, 1},
1121
  {7798, 16970755}, {7799, 1}, {7800, 16971011}, {7801, 1},
1122
  {7802, 16971267}, {7803, 1}, {7804, 16971523}, {7805, 1},
1123
  {7806, 16971779}, {7807, 1}, {7808, 16972035}, {7809, 1},
1124
  {7810, 16972291}, {7811, 1}, {7812, 16972547}, {7813, 1},
1125
  {7814, 16972803}, {7815, 1}, {7816, 16973059}, {7817, 1},
1126
  {7818, 16973315}, {7819, 1}, {7820, 16973571}, {7821, 1},
1127
  {7822, 16973827}, {7823, 1}, {7824, 16974083}, {7825, 1},
1128
  {7826, 16974339}, {7827, 1}, {7828, 16974595}, {7829, 1},
1129
  {7834, 33752067}, {7835, 16967939}, {7836, 1}, {7838, 33752579},
1130
  {7839, 1}, {7840, 16975875}, {7841, 1}, {7842, 16976131},
1131
  {7843, 1}, {7844, 16976387}, {7845, 1}, {7846, 16976643},
1132
  {7847, 1}, {7848, 16976899}, {7849, 1}, {7850, 16977155},
1133
  {7851, 1}, {7852, 16977411}, {7853, 1}, {7854, 16977667},
1134
  {7855, 1}, {7856, 16977923}, {7857, 1}, {7858, 16978179},
1135
  {7859, 1}, {7860, 16978435}, {7861, 1}, {7862, 16978691},
1136
  {7863, 1}, {7864, 16978947}, {7865, 1}, {7866, 16979203},
1137
  {7867, 1}, {7868, 16979459}, {7869, 1}, {7870, 16979715},
1138
  {7871, 1}, {7872, 16979971}, {7873, 1}, {7874, 16980227},
1139
  {7875, 1}, {7876, 16980483}, {7877, 1}, {7878, 16980739},
1140
  {7879, 1}, {7880, 16980995}, {7881, 1}, {7882, 16981251},
1141
  {7883, 1}, {7884, 16981507}, {7885, 1}, {7886, 16981763},
1142
  {7887, 1}, {7888, 16982019}, {7889, 1}, {7890, 16982275},
1143
  {7891, 1}, {7892, 16982531}, {7893, 1}, {7894, 16982787},
1144
  {7895, 1}, {7896, 16983043}, {7897, 1}, {7898, 16983299},
1145
  {7899, 1}, {7900, 16983555}, {7901, 1}, {7902, 16983811},
1146
  {7903, 1}, {7904, 16984067}, {7905, 1}, {7906, 16984323},
1147
  {7907, 1}, {7908, 16984579}, {7909, 1}, {7910, 16984835},
1148
  {7911, 1}, {7912, 16985091}, {7913, 1}, {7914, 16985347},
1149
  {7915, 1}, {7916, 16985603}, {7917, 1}, {7918, 16985859},
1150
  {7919, 1}, {7920, 16986115}, {7921, 1}, {7922, 16986371},
1151
  {7923, 1}, {7924, 16986627}, {7925, 1}, {7926, 16986883},
1152
  {7927, 1}, {7928, 16987139}, {7929, 1}, {7930, 16987395},
1153
  {7931, 1}, {7932, 16987651}, {7933, 1}, {7934, 16987907},
1154
  {7935, 1}, {7944, 16988163}, {7945, 16988419}, {7946, 16988675},
1155
  {7947, 16988931}, {7948, 16989187}, {7949, 16989443}, {7950, 16989699},
1156
  {7951, 16989955}, {7952, 1}, {7958, 2}, {7960, 16990211},
1157
  {7961, 16990467}, {7962, 16990723}, {7963, 16990979}, {7964, 16991235},
1158
  {7965, 16991491}, {7966, 2}, {7968, 1}, {7976, 16991747},
1159
  {7977, 16992003}, {7978, 16992259}, {7979, 16992515}, {7980, 16992771},
1160
  {7981, 16993027}, {7982, 16993283}, {7983, 16993539}, {7984, 1},
1161
  {7992, 16993795}, {7993, 16994051}, {7994, 16994307}, {7995, 16994563},
1162
  {7996, 16994819}, {7997, 16995075}, {7998, 16995331}, {7999, 16995587},
1163
  {8000, 1}, {8006, 2}, {8008, 16995843}, {8009, 16996099},
1164
  {8010, 16996355}, {8011, 16996611}, {8012, 16996867}, {8013, 16997123},
1165
  {8014, 2}, {8016, 1}, {8024, 2}, {8025, 16997379},
1166
  {8026, 2}, {8027, 16997635}, {8028, 2}, {8029, 16997891},
1167
  {8030, 2}, {8031, 16998147}, {8032, 1}, {8040, 16998403},
1168
  {8041, 16998659}, {8042, 16998915}, {8043, 16999171}, {8044, 16999427},
1169
  {8045, 16999683}, {8046, 16999939}, {8047, 17000195}, {8048, 1},
1170
  {8049, 16849923}, {8050, 1}, {8051, 16850179}, {8052, 1},
1171
  {8053, 16850435}, {8054, 1}, {8055, 16850691}, {8056, 1},
1172
  {8057, 16850947}, {8058, 1}, {8059, 16851203}, {8060, 1},
1173
  {8061, 16851459}, {8062, 2}, {8064, 33777667}, {8065, 33778179},
1174
  {8066, 33778691}, {8067, 33779203}, {8068, 33779715}, {8069, 33780227},
1175
  {8070, 33780739}, {8071, 33781251}, {8072, 33777667}, {8073, 33778179},
1176
  {8074, 33778691}, {8075, 33779203}, {8076, 33779715}, {8077, 33780227},
1177
  {8078, 33780739}, {8079, 33781251}, {8080, 33781763}, {8081, 33782275},
1178
  {8082, 33782787}, {8083, 33783299}, {8084, 33783811}, {8085, 33784323},
1179
  {8086, 33784835}, {8087, 33785347}, {8088, 33781763}, {8089, 33782275},
1180
  {8090, 33782787}, {8091, 33783299}, {8092, 33783811}, {8093, 33784323},
1181
  {8094, 33784835}, {8095, 33785347}, {8096, 33785859}, {8097, 33786371},
1182
  {8098, 33786883}, {8099, 33787395}, {8100, 33787907}, {8101, 33788419},
1183
  {8102, 33788931}, {8103, 33789443}, {8104, 33785859}, {8105, 33786371},
1184
  {8106, 33786883}, {8107, 33787395}, {8108, 33787907}, {8109, 33788419},
1185
  {8110, 33788931}, {8111, 33789443}, {8112, 1}, {8114, 33789955},
1186
  {8115, 33790467}, {8116, 33790979}, {8117, 2}, {8118, 1},
1187
  {8119, 33791491}, {8120, 17014787}, {8121, 17015043}, {8122, 17012739},
1188
  {8123, 16849923}, {8124, 33790467}, {8125, 33792515}, {8126, 16846851},
1189
  {8127, 33792515}, {8128, 33793027}, {8129, 50570755}, {8130, 33794307},
1190
  {8131, 33794819}, {8132, 33795331}, {8133, 2}, {8134, 1},
1191
  {8135, 33795843}, {8136, 17019139}, {8137, 16850179}, {8138, 17017091},
1192
  {8139, 16850435}, {8140, 33794819}, {8141, 50573827}, {8142, 50574595},
1193
  {8143, 50575363}, {8144, 1}, {8147, 17021699}, {8148, 2},
1194
  {8150, 1}, {8152, 17021955}, {8153, 17022211}, {8154, 17022467},
1195
  {8155, 16850691}, {8156, 2}, {8157, 50577155}, {8158, 50577923},
1196
  {8159, 50578691}, {8160, 1}, {8163, 17025027}, {8164, 1},
1197
  {8168, 17025283}, {8169, 17025539}, {8170, 17025795}, {8171, 16851203},
1198
  {8172, 17026051}, {8173, 50580739}, {8174, 50403587}, {8175, 17027075},
1199
  {8176, 2}, {8178, 33804547}, {8179, 33805059}, {8180, 33805571},
1200
  {8181, 2}, {8182, 1}, {8183, 33806083}, {8184, 17029379},
1201
  {8185, 16850947}, {8186, 17027331}, {8187, 16851459}, {8188, 33805059},
1202
  {8189, 33562883}, {8190, 33799939}, {8191, 2}, {8192, 16783875},
1203
  {8203, 0}, {8204, 1}, {8206, 2}, {8208, 1},
1204
  {8209, 17029635}, {8210, 1}, {8215, 33807107}, {8216, 1},
1205
  {8228, 2}, {8231, 1}, {8232, 2}, {8239, 16783875},
1206
  {8240, 1}, {8243, 33807619}, {8244, 50585347}, {8245, 1},
1207
  {8246, 33808899}, {8247, 50586627}, {8248, 1}, {8252, 33810179},
1208
  {8253, 1}, {8254, 33810691}, {8255, 1}, {8263, 33811203},
1209
  {8264, 33811715}, {8265, 33812227}, {8266, 1}, {8279, 67362051},
1210
  {8280, 1}, {8287, 16783875}, {8288, 0}, {8289, 2},
1211
  {8292, 0}, {8293, 2}, {8304, 17035523}, {8305, 16779267},
1212
  {8306, 2}, {8308, 16787715}, {8309, 17035779}, {8310, 17036035},
1213
  {8311, 17036291}, {8312, 17036547}, {8313, 17036803}, {8314, 17037059},
1214
  {8315, 17037315}, {8316, 17037571}, {8317, 17037827}, {8318, 17038083},
1215
  {8319, 16780547}, {8320, 17035523}, {8321, 16786947}, {8322, 16785155},
1216
  {8323, 16785411}, {8324, 16787715}, {8325, 17035779}, {8326, 17036035},
1217
  {8327, 17036291}, {8328, 17036547}, {8329, 17036803}, {8330, 17037059},
1218
  {8331, 17037315}, {8332, 17037571}, {8333, 17037827}, {8334, 17038083},
1219
  {8335, 2}, {8336, 16777219}, {8337, 16778243}, {8338, 16780803},
1220
  {8339, 16783107}, {8340, 16816387}, {8341, 16779011}, {8342, 16779779},
1221
  {8343, 16780035}, {8344, 16780291}, {8345, 16780547}, {8346, 16781059},
1222
  {8347, 16781827}, {8348, 16782083}, {8349, 2}, {8352, 1},
1223
  {8360, 33558787}, {8361, 1}, {8385, 2}, {8400, 1},
1224
  {8433, 2}, {8448, 50592771}, {8449, 50593539}, {8450, 16777731},
1225
  {8451, 33817091}, {8452, 1}, {8453, 50594819}, {8454, 50595587},
1226
  {8455, 16816643}, {8456, 1}, {8457, 33819139}, {8458, 16778755},
1227
  {8459, 16779011}, {8463, 16802051}, {8464, 16779267}, {8466, 16780035},
1228
  {8468, 1}, {8469, 16780547}, {8470, 33557763}, {8471, 1},
1229
  {8473, 16781059}, {8474, 16781315}, {8475, 16781571}, {8478, 1},
1230
  {8480, 33819651}, {8481, 50597379}, {8482, 33820931}, {8483, 1},
1231
  {8484, 16783619}, {8485, 1}, {8486, 16857091}, {8487, 1},
1232
  {8488, 16783619}, {8489, 1}, {8490, 16779779}, {8491, 16790787},
1233
  {8492, 16777475}, {8493, 16777731}, {8494, 1}, {8495, 16778243},
1234
  {8497, 16778499}, {8498, 2}, {8499, 16780291}, {8500, 16780803},
1235
  {8501, 17044227}, {8502, 17044483}, {8503, 17044739}, {8504, 17044995},
1236
  {8505, 16779267}, {8506, 1}, {8507, 50599683}, {8508, 16855043},
1237
  {8509, 16852227}, {8511, 16855043}, {8512, 17046019}, {8513, 1},
1238
  {8517, 16777987}, {8519, 16778243}, {8520, 16779267}, {8521, 16779523},
1239
  {8522, 1}, {8528, 50600707}, {8529, 50601475}, {8530, 67379459},
1240
  {8531, 50603267}, {8532, 50604035}, {8533, 50604803}, {8534, 50605571},
1241
  {8535, 50606339}, {8536, 50607107}, {8537, 50607875}, {8538, 50608643},
1242
  {8539, 50609411}, {8540, 50610179}, {8541, 50610947}, {8542, 50611715},
1243
  {8543, 33564419}, {8544, 16779267}, {8545, 33835267}, {8546, 50612995},
1244
  {8547, 33836547}, {8548, 16782595}, {8549, 33837059}, {8550, 50614787},
1245
  {8551, 67392771}, {8552, 33839363}, {8553, 16783107}, {8554, 33839875},
1246
  {8555, 50617603}, {8556, 16780035}, {8557, 16777731}, {8558, 16777987},
1247
  {8559, 16780291}, {8560, 16779267}, {8561, 33835267}, {8562, 50612483},
1248
  {8563, 33836547}, {8564, 16782595}, {8565, 33837059}, {8566, 50614787},
1249
  {8567, 67392771}, {8568, 33839363}, {8569, 16783107}, {8570, 33839875},
1250
  {8571, 50617603}, {8572, 16780035}, {8573, 16777731}, {8574, 16777987},
1251
  {8575, 16780291}, {8576, 1}, {8579, 2}, {8580, 1},
1252
  {8585, 50618371}, {8586, 1}, {8588, 2}, {8592, 1},
1253
  {8748, 33841923}, {8749, 50619651}, {8750, 1}, {8751, 33843203},
1254
  {8752, 50620931}, {8753, 1}, {9001, 17067267}, {9002, 17067523},
1255
  {9003, 1}, {9255, 2}, {9280, 1}, {9291, 2},
1256
  {9312, 16786947}, {9313, 16785155}, {9314, 16785411}, {9315, 16787715},
1257
  {9316, 17035779}, {9317, 17036035}, {9318, 17036291}, {9319, 17036547},
1258
  {9320, 17036803}, {9321, 33825539}, {9322, 33564163}, {9323, 33844995},
1259
  {9324, 33845507}, {9325, 33846019}, {9326, 33846531}, {9327, 33847043},
1260
  {9328, 33847555}, {9329, 33848067}, {9330, 33848579}, {9331, 33849091},
1261
  {9332, 50626819}, {9333, 50627587}, {9334, 50628355}, {9335, 50629123},
1262
  {9336, 50629891}, {9337, 50630659}, {9338, 50631427}, {9339, 50632195},
1263
  {9340, 50632963}, {9341, 67410947}, {9342, 67411971}, {9343, 67412995},
1264
  {9344, 67414019}, {9345, 67415043}, {9346, 67416067}, {9347, 67417091},
1265
  {9348, 67418115}, {9349, 67419139}, {9350, 67420163}, {9351, 67421187},
1266
  {9352, 2}, {9372, 50644995}, {9373, 50645763}, {9374, 50646531},
1267
  {9375, 50647299}, {9376, 50648067}, {9377, 50648835}, {9378, 50649603},
1268
  {9379, 50650371}, {9380, 50651139}, {9381, 50651907}, {9382, 50652675},
1269
  {9383, 50653443}, {9384, 50654211}, {9385, 50654979}, {9386, 50655747},
1270
  {9387, 50656515}, {9388, 50657283}, {9389, 50658051}, {9390, 50658819},
1271
  {9391, 50659587}, {9392, 50660355}, {9393, 50661123}, {9394, 50661891},
1272
  {9395, 50662659}, {9396, 50663427}, {9397, 50664195}, {9398, 16777219},
1273
  {9399, 16777475}, {9400, 16777731}, {9401, 16777987}, {9402, 16778243},
1274
  {9403, 16778499}, {9404, 16778755}, {9405, 16779011}, {9406, 16779267},
1275
  {9407, 16779523}, {9408, 16779779}, {9409, 16780035}, {9410, 16780291},
1276
  {9411, 16780547}, {9412, 16780803}, {9413, 16781059}, {9414, 16781315},
1277
  {9415, 16781571}, {9416, 16781827}, {9417, 16782083}, {9418, 16782339},
1278
  {9419, 16782595}, {9420, 16782851}, {9421, 16783107}, {9422, 16783363},
1279
  {9423, 16783619}, {9424, 16777219}, {9425, 16777475}, {9426, 16777731},
1280
  {9427, 16777987}, {9428, 16778243}, {9429, 16778499}, {9430, 16778755},
1281
  {9431, 16779011}, {9432, 16779267}, {9433, 16779523}, {9434, 16779779},
1282
  {9435, 16780035}, {9436, 16780291}, {9437, 16780547}, {9438, 16780803},
1283
  {9439, 16781059}, {9440, 16781315}, {9441, 16781571}, {9442, 16781827},
1284
  {9443, 16782083}, {9444, 16782339}, {9445, 16782595}, {9446, 16782851},
1285
  {9447, 16783107}, {9448, 16783363}, {9449, 16783619}, {9450, 17035523},
1286
  {9451, 1}, {10764, 67396355}, {10765, 1}, {10868, 50664963},
1287
  {10869, 33888515}, {10870, 50665475}, {10871, 1}, {10972, 33889027},
1288
  {10973, 1}, {11124, 2}, {11126, 1}, {11158, 2},
1289
  {11159, 1}, {11264, 17112323}, {11265, 17112579}, {11266, 17112835},
1290
  {11267, 17113091}, {11268, 17113347}, {11269, 17113603}, {11270, 17113859},
1291
  {11271, 17114115}, {11272, 17114371}, {11273, 17114627}, {11274, 17114883},
1292
  {11275, 17115139}, {11276, 17115395}, {11277, 17115651}, {11278, 17115907},
1293
  {11279, 17116163}, {11280, 17116419}, {11281, 17116675}, {11282, 17116931},
1294
  {11283, 17117187}, {11284, 17117443}, {11285, 17117699}, {11286, 17117955},
1295
  {11287, 17118211}, {11288, 17118467}, {11289, 17118723}, {11290, 17118979},
1296
  {11291, 17119235}, {11292, 17119491}, {11293, 17119747}, {11294, 17120003},
1297
  {11295, 17120259}, {11296, 17120515}, {11297, 17120771}, {11298, 17121027},
1298
  {11299, 17121283}, {11300, 17121539}, {11301, 17121795}, {11302, 17122051},
1299
  {11303, 17122307}, {11304, 17122563}, {11305, 17122819}, {11306, 17123075},
1300
  {11307, 17123331}, {11308, 17123587}, {11309, 17123843}, {11310, 17124099},
1301
  {11311, 17124355}, {11312, 1}, {11360, 17124611}, {11361, 1},
1302
  {11362, 17124867}, {11363, 17125123}, {11364, 17125379}, {11365, 1},
1303
  {11367, 17125635}, {11368, 1}, {11369, 17125891}, {11370, 1},
1304
  {11371, 17126147}, {11372, 1}, {11373, 16948483}, {11374, 16953091},
1305
  {11375, 16948227}, {11376, 16950275}, {11377, 1}, {11378, 17126403},
1306
  {11379, 1}, {11381, 17126659}, {11382, 1}, {11388, 16779523},
1307
  {11389, 16782595}, {11390, 17126915}, {11391, 17127171}, {11392, 17127427},
1308
  {11393, 1}, {11394, 17127683}, {11395, 1}, {11396, 17127939},
1309
  {11397, 1}, {11398, 17128195}, {11399, 1}, {11400, 17128451},
1310
  {11401, 1}, {11402, 17128707}, {11403, 1}, {11404, 17128963},
1311
  {11405, 1}, {11406, 17129219}, {11407, 1}, {11408, 17129475},
1312
  {11409, 1}, {11410, 17129731}, {11411, 1}, {11412, 17129987},
1313
  {11413, 1}, {11414, 17130243}, {11415, 1}, {11416, 17130499},
1314
  {11417, 1}, {11418, 17130755}, {11419, 1}, {11420, 17131011},
1315
  {11421, 1}, {11422, 17131267}, {11423, 1}, {11424, 17131523},
1316
  {11425, 1}, {11426, 17131779}, {11427, 1}, {11428, 17132035},
1317
  {11429, 1}, {11430, 17132291}, {11431, 1}, {11432, 17132547},
1318
  {11433, 1}, {11434, 17132803}, {11435, 1}, {11436, 17133059},
1319
  {11437, 1}, {11438, 17133315}, {11439, 1}, {11440, 17133571},
1320
  {11441, 1}, {11442, 17133827}, {11443, 1}, {11444, 17134083},
1321
  {11445, 1}, {11446, 17134339}, {11447, 1}, {11448, 17134595},
1322
  {11449, 1}, {11450, 17134851}, {11451, 1}, {11452, 17135107},
1323
  {11453, 1}, {11454, 17135363}, {11455, 1}, {11456, 17135619},
1324
  {11457, 1}, {11458, 17135875}, {11459, 1}, {11460, 17136131},
1325
  {11461, 1}, {11462, 17136387}, {11463, 1}, {11464, 17136643},
1326
  {11465, 1}, {11466, 17136899}, {11467, 1}, {11468, 17137155},
1327
  {11469, 1}, {11470, 17137411}, {11471, 1}, {11472, 17137667},
1328
  {11473, 1}, {11474, 17137923}, {11475, 1}, {11476, 17138179},
1329
  {11477, 1}, {11478, 17138435}, {11479, 1}, {11480, 17138691},
1330
  {11481, 1}, {11482, 17138947}, {11483, 1}, {11484, 17139203},
1331
  {11485, 1}, {11486, 17139459}, {11487, 1}, {11488, 17139715},
1332
  {11489, 1}, {11490, 17139971}, {11491, 1}, {11499, 17140227},
1333
  {11500, 1}, {11501, 17140483}, {11502, 1}, {11506, 17140739},
1334
  {11507, 1}, {11508, 2}, {11513, 1}, {11558, 2},
1335
  {11559, 1}, {11560, 2}, {11565, 1}, {11566, 2},
1336
  {11568, 1}, {11624, 2}, {11631, 17140995}, {11632, 1},
1337
  {11633, 2}, {11647, 1}, {11671, 2}, {11680, 1},
1338
  {11687, 2}, {11688, 1}, {11695, 2}, {11696, 1},
1339
  {11703, 2}, {11704, 1}, {11711, 2}, {11712, 1},
1340
  {11719, 2}, {11720, 1}, {11727, 2}, {11728, 1},
1341
  {11735, 2}, {11736, 1}, {11743, 2}, {11744, 1},
1342
  {11870, 2}, {11904, 1}, {11930, 2}, {11931, 1},
1343
  {11935, 17141251}, {11936, 1}, {12019, 17141507}, {12020, 2},
1344
  {12032, 17141763}, {12033, 17142019}, {12034, 17142275}, {12035, 17142531},
1345
  {12036, 17142787}, {12037, 17143043}, {12038, 17143299}, {12039, 17143555},
1346
  {12040, 17143811}, {12041, 17144067}, {12042, 17144323}, {12043, 17144579},
1347
  {12044, 17144835}, {12045, 17145091}, {12046, 17145347}, {12047, 17145603},
1348
  {12048, 17145859}, {12049, 17146115}, {12050, 17146371}, {12051, 17146627},
1349
  {12052, 17146883}, {12053, 17147139}, {12054, 17147395}, {12055, 17147651},
1350
  {12056, 17147907}, {12057, 17148163}, {12058, 17148419}, {12059, 17148675},
1351
  {12060, 17148931}, {12061, 17149187}, {12062, 17149443}, {12063, 17149699},
1352
  {12064, 17149955}, {12065, 17150211}, {12066, 17150467}, {12067, 17150723},
1353
  {12068, 17150979}, {12069, 17151235}, {12070, 17151491}, {12071, 17151747},
1354
  {12072, 17152003}, {12073, 17152259}, {12074, 17152515}, {12075, 17152771},
1355
  {12076, 17153027}, {12077, 17153283}, {12078, 17153539}, {12079, 17153795},
1356
  {12080, 17154051}, {12081, 17154307}, {12082, 17154563}, {12083, 17154819},
1357
  {12084, 17155075}, {12085, 17155331}, {12086, 17155587}, {12087, 17155843},
1358
  {12088, 17156099}, {12089, 17156355}, {12090, 17156611}, {12091, 17156867},
1359
  {12092, 17157123}, {12093, 17157379}, {12094, 17157635}, {12095, 17157891},
1360
  {12096, 17158147}, {12097, 17158403}, {12098, 17158659}, {12099, 17158915},
1361
  {12100, 17159171}, {12101, 17159427}, {12102, 17159683}, {12103, 17159939},
1362
  {12104, 17160195}, {12105, 17160451}, {12106, 17160707}, {12107, 17160963},
1363
  {12108, 17161219}, {12109, 17161475}, {12110, 17161731}, {12111, 17161987},
1364
  {12112, 17162243}, {12113, 17162499}, {12114, 17162755}, {12115, 17163011},
1365
  {12116, 17163267}, {12117, 17163523}, {12118, 17163779}, {12119, 17164035},
1366
  {12120, 17164291}, {12121, 17164547}, {12122, 17164803}, {12123, 17165059},
1367
  {12124, 17165315}, {12125, 17165571}, {12126, 17165827}, {12127, 17166083},
1368
  {12128, 17166339}, {12129, 17166595}, {12130, 17166851}, {12131, 17167107},
1369
  {12132, 17167363}, {12133, 17167619}, {12134, 17167875}, {12135, 17168131},
1370
  {12136, 17168387}, {12137, 17168643}, {12138, 17168899}, {12139, 17169155},
1371
  {12140, 17169411}, {12141, 17169667}, {12142, 17169923}, {12143, 17170179},
1372
  {12144, 17170435}, {12145, 17170691}, {12146, 17170947}, {12147, 17171203},
1373
  {12148, 17171459}, {12149, 17171715}, {12150, 17171971}, {12151, 17172227},
1374
  {12152, 17172483}, {12153, 17172739}, {12154, 17172995}, {12155, 17173251},
1375
  {12156, 17173507}, {12157, 17173763}, {12158, 17174019}, {12159, 17174275},
1376
  {12160, 17174531}, {12161, 17174787}, {12162, 17175043}, {12163, 17175299},
1377
  {12164, 17175555}, {12165, 17175811}, {12166, 17176067}, {12167, 17176323},
1378
  {12168, 17176579}, {12169, 17176835}, {12170, 17177091}, {12171, 17177347},
1379
  {12172, 17177603}, {12173, 17177859}, {12174, 17178115}, {12175, 17178371},
1380
  {12176, 17178627}, {12177, 17178883}, {12178, 17179139}, {12179, 17179395},
1381
  {12180, 17179651}, {12181, 17179907}, {12182, 17180163}, {12183, 17180419},
1382
  {12184, 17180675}, {12185, 17180931}, {12186, 17181187}, {12187, 17181443},
1383
  {12188, 17181699}, {12189, 17181955}, {12190, 17182211}, {12191, 17182467},
1384
  {12192, 17182723}, {12193, 17182979}, {12194, 17183235}, {12195, 17183491},
1385
  {12196, 17183747}, {12197, 17184003}, {12198, 17184259}, {12199, 17184515},
1386
  {12200, 17184771}, {12201, 17185027}, {12202, 17185283}, {12203, 17185539},
1387
  {12204, 17185795}, {12205, 17186051}, {12206, 17186307}, {12207, 17186563},
1388
  {12208, 17186819}, {12209, 17187075}, {12210, 17187331}, {12211, 17187587},
1389
  {12212, 17187843}, {12213, 17188099}, {12214, 17188355}, {12215, 17188611},
1390
  {12216, 17188867}, {12217, 17189123}, {12218, 17189379}, {12219, 17189635},
1391
  {12220, 17189891}, {12221, 17190147}, {12222, 17190403}, {12223, 17190659},
1392
  {12224, 17190915}, {12225, 17191171}, {12226, 17191427}, {12227, 17191683},
1393
  {12228, 17191939}, {12229, 17192195}, {12230, 17192451}, {12231, 17192707},
1394
  {12232, 17192963}, {12233, 17193219}, {12234, 17193475}, {12235, 17193731},
1395
  {12236, 17193987}, {12237, 17194243}, {12238, 17194499}, {12239, 17194755},
1396
  {12240, 17195011}, {12241, 17195267}, {12242, 17195523}, {12243, 17195779},
1397
  {12244, 17196035}, {12245, 17196291}, {12246, 2}, {12288, 16783875},
1398
  {12289, 1}, {12290, 17196547}, {12291, 1}, {12342, 17196803},
1399
  {12343, 1}, {12344, 17147651}, {12345, 17197059}, {12346, 17197315},
1400
  {12347, 1}, {12352, 2}, {12353, 1}, {12439, 2},
1401
  {12441, 1}, {12443, 33974787}, {12444, 33975299}, {12445, 1},
1402
  {12447, 33975811}, {12448, 1}, {12543, 33976323}, {12544, 2},
1403
  {12549, 1}, {12592, 2}, {12593, 17199619}, {12594, 17199875},
1404
  {12595, 17200131}, {12596, 17200387}, {12597, 17200643}, {12598, 17200899},
1405
  {12599, 17201155}, {12600, 17201411}, {12601, 17201667}, {12602, 17201923},
1406
  {12603, 17202179}, {12604, 17202435}, {12605, 17202691}, {12606, 17202947},
1407
  {12607, 17203203}, {12608, 17203459}, {12609, 17203715}, {12610, 17203971},
1408
  {12611, 17204227}, {12612, 17204483}, {12613, 17204739}, {12614, 17204995},
1409
  {12615, 17205251}, {12616, 17205507}, {12617, 17205763}, {12618, 17206019},
1410
  {12619, 17206275}, {12620, 17206531}, {12621, 17206787}, {12622, 17207043},
1411
  {12623, 17207299}, {12624, 17207555}, {12625, 17207811}, {12626, 17208067},
1412
  {12627, 17208323}, {12628, 17208579}, {12629, 17208835}, {12630, 17209091},
1413
  {12631, 17209347}, {12632, 17209603}, {12633, 17209859}, {12634, 17210115},
1414
  {12635, 17210371}, {12636, 17210627}, {12637, 17210883}, {12638, 17211139},
1415
  {12639, 17211395}, {12640, 17211651}, {12641, 17211907}, {12642, 17212163},
1416
  {12643, 17212419}, {12644, 2}, {12645, 17212675}, {12646, 17212931},
1417
  {12647, 17213187}, {12648, 17213443}, {12649, 17213699}, {12650, 17213955},
1418
  {12651, 17214211}, {12652, 17214467}, {12653, 17214723}, {12654, 17214979},
1419
  {12655, 17215235}, {12656, 17215491}, {12657, 17215747}, {12658, 17216003},
1420
  {12659, 17216259}, {12660, 17216515}, {12661, 17216771}, {12662, 17217027},
1421
  {12663, 17217283}, {12664, 17217539}, {12665, 17217795}, {12666, 17218051},
1422
  {12667, 17218307}, {12668, 17218563}, {12669, 17218819}, {12670, 17219075},
1423
  {12671, 17219331}, {12672, 17219587}, {12673, 17219843}, {12674, 17220099},
1424
  {12675, 17220355}, {12676, 17220611}, {12677, 17220867}, {12678, 17221123},
1425
  {12679, 17221379}, {12680, 17221635}, {12681, 17221891}, {12682, 17222147},
1426
  {12683, 17222403}, {12684, 17222659}, {12685, 17222915}, {12686, 17223171},
1427
  {12687, 2}, {12688, 1}, {12690, 17141763}, {12691, 17143299},
1428
  {12692, 17223427}, {12693, 17223683}, {12694, 17223939}, {12695, 17224195},
1429
  {12696, 17224451}, {12697, 17224707}, {12698, 17142787}, {12699, 17224963},
1430
  {12700, 17225219}, {12701, 17225475}, {12702, 17225731}, {12703, 17143811},
1431
  {12704, 1}, {12772, 2}, {12784, 1}, {12800, 50780419},
1432
  {12801, 50781187}, {12802, 50781955}, {12803, 50782723}, {12804, 50783491},
1433
  {12805, 50784259}, {12806, 50785027}, {12807, 50785795}, {12808, 50786563},
1434
  {12809, 50787331}, {12810, 50788099}, {12811, 50788867}, {12812, 50789635},
1435
  {12813, 50790403}, {12814, 50791171}, {12815, 50791939}, {12816, 50792707},
1436
  {12817, 50793475}, {12818, 50794243}, {12819, 50795011}, {12820, 50795779},
1437
  {12821, 50796547}, {12822, 50797315}, {12823, 50798083}, {12824, 50798851},
1438
  {12825, 50799619}, {12826, 50800387}, {12827, 50801155}, {12828, 50801923},
1439
  {12829, 67579907}, {12830, 67580931}, {12831, 2}, {12832, 50804739},
1440
  {12833, 50805507}, {12834, 50806275}, {12835, 50807043}, {12836, 50807811},
1441
  {12837, 50808579}, {12838, 50809347}, {12839, 50810115}, {12840, 50810883},
1442
  {12841, 50811651}, {12842, 50812419}, {12843, 50813187}, {12844, 50813955},
1443
  {12845, 50814723}, {12846, 50815491}, {12847, 50816259}, {12848, 50817027},
1444
  {12849, 50817795}, {12850, 50818563}, {12851, 50819331}, {12852, 50820099},
1445
  {12853, 50820867}, {12854, 50821635}, {12855, 50822403}, {12856, 50823171},
1446
  {12857, 50823939}, {12858, 50824707}, {12859, 50825475}, {12860, 50826243},
1447
  {12861, 50827011}, {12862, 50827779}, {12863, 50828547}, {12864, 50829315},
1448
  {12865, 50830083}, {12866, 50830851}, {12867, 50831619}, {12868, 17277955},
1449
  {12869, 17278211}, {12870, 17158659}, {12871, 17278467}, {12872, 1},
1450
  {12880, 50833155}, {12881, 33845251}, {12882, 34056707}, {12883, 33562371},
1451
  {12884, 34057219}, {12885, 34057731}, {12886, 34058243}, {12887, 34058755},
1452
  {12888, 34059267}, {12889, 34059779}, {12890, 34060291}, {12891, 33827331},
1453
  {12892, 33826563}, {12893, 34060803}, {12894, 34061315}, {12895, 34061827},
1454
  {12896, 17199619}, {12897, 17200387}, {12898, 17201155}, {12899, 17201667},
1455
  {12900, 17203715}, {12901, 17203971}, {12902, 17204739}, {12903, 17205251},
1456
  {12904, 17205507}, {12905, 17206019}, {12906, 17206275}, {12907, 17206531},
1457
  {12908, 17206787}, {12909, 17207043}, {12910, 17236995}, {12911, 17237763},
1458
  {12912, 17238531}, {12913, 17239299}, {12914, 17240067}, {12915, 17240835},
1459
  {12916, 17241603}, {12917, 17242371}, {12918, 17243139}, {12919, 17243907},
1460
  {12920, 17244675}, {12921, 17245443}, {12922, 17246211}, {12923, 17246979},
1461
  {12924, 34062339}, {12925, 34062851}, {12926, 17286147}, {12927, 1},
1462
  {12928, 17141763}, {12929, 17143299}, {12930, 17223427}, {12931, 17223683},
1463
  {12932, 17253635}, {12933, 17254403}, {12934, 17255171}, {12935, 17144579},
1464
  {12936, 17256707}, {12937, 17147651}, {12938, 17160451}, {12939, 17163523},
1465
  {12940, 17163267}, {12941, 17160707}, {12942, 17184259}, {12943, 17149699},
1466
  {12944, 17159939}, {12945, 17263619}, {12946, 17264387}, {12947, 17265155},
1467
  {12948, 17265923}, {12949, 17266691}, {12950, 17267459}, {12951, 17268227},
1468
  {12952, 17268995}, {12953, 17286403}, {12954, 17286659}, {12955, 17151235},
1469
  {12956, 17286915}, {12957, 17287171}, {12958, 17287427}, {12959, 17287683},
1470
  {12960, 17287939}, {12961, 17275907}, {12962, 17288195}, {12963, 17288451},
1471
  {12964, 17223939}, {12965, 17224195}, {12966, 17224451}, {12967, 17288707},
1472
  {12968, 17288963}, {12969, 17289219}, {12970, 17289475}, {12971, 17271299},
1473
  {12972, 17272067}, {12973, 17272835}, {12974, 17273603}, {12975, 17274371},
1474
  {12976, 17289731}, {12977, 34067203}, {12978, 34067715}, {12979, 34068227},
1475
  {12980, 34068739}, {12981, 34069251}, {12982, 33564931}, {12983, 34057475},
1476
  {12984, 34061571}, {12985, 34069763}, {12986, 34070275}, {12987, 34070787},
1477
  {12988, 34071299}, {12989, 34071811}, {12990, 34072323}, {12991, 34072835},
1478
  {12992, 34073347}, {12993, 34073859}, {12994, 34074371}, {12995, 34074883},
1479
  {12996, 34075395}, {12997, 34075907}, {12998, 34076419}, {12999, 34076931},
1480
  {13000, 34077443}, {13001, 50855171}, {13002, 50855939}, {13003, 50856707},
1481
  {13004, 34080259}, {13005, 50857987}, {13006, 34081539}, {13007, 50859267},
1482
  {13008, 17305603}, {13009, 17305859}, {13010, 17306115}, {13011, 17306371},
1483
  {13012, 17306627}, {13013, 17306883}, {13014, 17307139}, {13015, 17307395},
1484
  {13016, 17307651}, {13017, 17199107}, {13018, 17307907}, {13019, 17308163},
1485
  {13020, 17308419}, {13021, 17308675}, {13022, 17308931}, {13023, 17309187},
1486
  {13024, 17309443}, {13025, 17309699}, {13026, 17309955}, {13027, 17199363},
1487
  {13028, 17310211}, {13029, 17310467}, {13030, 17310723}, {13031, 17310979},
1488
  {13032, 17311235}, {13033, 17311491}, {13034, 17311747}, {13035, 17312003},
1489
  {13036, 17312259}, {13037, 17312515}, {13038, 17312771}, {13039, 17313027},
1490
  {13040, 17313283}, {13041, 17313539}, {13042, 17313795}, {13043, 17314051},
1491
  {13044, 17314307}, {13045, 17314563}, {13046, 17314819}, {13047, 17315075},
1492
  {13048, 17315331}, {13049, 17315587}, {13050, 17315843}, {13051, 17316099},
1493
  {13052, 17316355}, {13053, 17316611}, {13054, 17316867}, {13055, 34094339},
1494
  {13056, 67649283}, {13057, 67650307}, {13058, 67651331}, {13059, 50875139},
1495
  {13060, 67653123}, {13061, 50876931}, {13062, 50877699}, {13063, 84432899},
1496
  {13064, 67656963}, {13065, 50880771}, {13066, 50881539}, {13067, 50882307},
1497
  {13068, 67660291}, {13069, 67661315}, {13070, 50885123}, {13071, 50885891},
1498
  {13072, 34109443}, {13073, 50887171}, {13074, 67665155}, {13075, 67666179},
1499
  {13076, 34112771}, {13077, 84444931}, {13078, 101223427}, {13079, 84447747},
1500
  {13080, 50891011}, {13081, 84449027}, {13082, 84450307}, {13083, 67674371},
1501
  {13084, 50898179}, {13085, 50898947}, {13086, 50899715}, {13087, 67677699},
1502
  {13088, 84455939}, {13089, 67680003}, {13090, 50903811}, {13091, 50904579},
1503
  {13092, 50905347}, {13093, 34128899}, {13094, 34129411}, {13095, 34118147},
1504
  {13096, 34129923}, {13097, 50907651}, {13098, 50908419}, {13099, 84463619},
1505
  {13100, 50910467}, {13101, 67688451}, {13102, 84466691}, {13103, 50913539},
1506
  {13104, 34137091}, {13105, 34137603}, {13106, 84469763}, {13107, 67693827},
1507
  {13108, 84472067}, {13109, 50918915}, {13110, 84474115}, {13111, 34143747},
1508
  {13112, 50921475}, {13113, 50922243}, {13114, 50923011}, {13115, 50923779},
1509
  {13116, 50924547}, {13117, 67702531}, {13118, 50926339}, {13119, 34149891},
1510
  {13120, 50927619}, {13121, 50928387}, {13122, 50929155}, {13123, 67707139},
1511
  {13124, 50930947}, {13125, 50931715}, {13126, 50932483}, {13127, 84487683},
1512
  {13128, 67711747}, {13129, 34158339}, {13130, 84490499}, {13131, 34160131},
1513
  {13132, 67715075}, {13133, 67669507}, {13134, 50938883}, {13135, 50939651},
1514
  {13136, 50940419}, {13137, 67718403}, {13138, 34164995}, {13139, 50942723},
1515
  {13140, 67720707}, {13141, 34167299}, {13142, 84499459}, {13143, 50893827},
1516
  {13144, 34169091}, {13145, 34169603}, {13146, 34170115}, {13147, 34170627},
1517
  {13148, 34171139}, {13149, 34171651}, {13150, 34172163}, {13151, 34172675},
1518
  {13152, 34173187}, {13153, 34173699}, {13154, 50951427}, {13155, 50952195},
1519
  {13156, 50952963}, {13157, 50953731}, {13158, 50954499}, {13159, 50955267},
1520
  {13160, 50956035}, {13161, 50956803}, {13162, 50957571}, {13163, 50958339},
1521
  {13164, 50959107}, {13165, 50959875}, {13166, 50960643}, {13167, 50961411},
1522
  {13168, 50962179}, {13169, 50962947}, {13170, 34186499}, {13171, 34187011},
1523
  {13172, 50964739}, {13173, 34188291}, {13174, 34188803}, {13175, 34189315},
1524
  {13176, 50967043}, {13177, 50967811}, {13178, 34191363}, {13179, 34191875},
1525
  {13180, 34192387}, {13181, 34192899}, {13182, 34193411}, {13183, 67748355},
1526
  {13184, 34185987}, {13185, 34194947}, {13186, 34195459}, {13187, 34195971},
1527
  {13188, 34196483}, {13189, 34196995}, {13190, 34197507}, {13191, 34198019},
1528
  {13192, 50975747}, {13193, 67753731}, {13194, 34200323}, {13195, 34200835},
1529
  {13196, 34201347}, {13197, 34201859}, {13198, 34202371}, {13199, 34202883},
1530
  {13200, 34203395}, {13201, 50981123}, {13202, 50981891}, {13203, 50980355},
1531
  {13204, 50982659}, {13205, 34206211}, {13206, 34206723}, {13207, 34207235},
1532
  {13208, 33556995}, {13209, 34207747}, {13210, 34208259}, {13211, 34208771},
1533
  {13212, 34209283}, {13213, 34209795}, {13214, 34210307}, {13215, 50988035},
1534
  {13216, 50988803}, {13217, 34190083}, {13218, 50989571}, {13219, 50990339},
1535
  {13220, 50991107}, {13221, 34190851}, {13222, 50991875}, {13223, 50992643},
1536
  {13224, 67770627}, {13225, 34185987}, {13226, 50994435}, {13227, 50995203},
1537
  {13228, 50995971}, {13229, 50996739}, {13230, 84551939}, {13231, 101330435},
1538
  {13232, 34223107}, {13233, 34223619}, {13234, 34224131}, {13235, 34224643},
1539
  {13236, 34225155}, {13237, 34225667}, {13238, 34226179}, {13239, 34226691},
1540
  {13240, 34227203}, {13241, 34226691}, {13242, 34227715}, {13243, 34228227},
1541
  {13244, 34228739}, {13245, 34229251}, {13246, 34229763}, {13247, 34229251},
1542
  {13248, 34230275}, {13249, 34230787}, {13250, 2}, {13251, 34231299},
1543
  {13252, 33817347}, {13253, 33554947}, {13254, 67786243}, {13255, 2},
1544
  {13256, 34232835}, {13257, 34233347}, {13258, 34233859}, {13259, 34185731},
1545
  {13260, 34234371}, {13261, 34234883}, {13262, 34210307}, {13263, 34235395},
1546
  {13264, 33557251}, {13265, 34235907}, {13266, 51013635}, {13267, 34237187},
1547
  {13268, 34197507}, {13269, 51014915}, {13270, 51015683}, {13271, 34239235},
1548
  {13272, 2}, {13273, 51016963}, {13274, 34240515}, {13275, 34221315},
1549
  {13276, 34241027}, {13277, 34241539}, {13278, 51019267}, {13279, 51020035},
1550
  {13280, 34243587}, {13281, 34244099}, {13282, 34244611}, {13283, 34245123},
1551
  {13284, 34245635}, {13285, 34246147}, {13286, 34246659}, {13287, 34247171},
1552
  {13288, 34247683}, {13289, 51025411}, {13290, 51026179}, {13291, 51026947},
1553
  {13292, 51027715}, {13293, 51028483}, {13294, 51029251}, {13295, 51030019},
1554
  {13296, 51030787}, {13297, 51031555}, {13298, 51032323}, {13299, 51033091},
1555
  {13300, 51033859}, {13301, 51034627}, {13302, 51035395}, {13303, 51036163},
1556
  {13304, 51036931}, {13305, 51037699}, {13306, 51038467}, {13307, 51039235},
1557
  {13308, 51040003}, {13309, 51040771}, {13310, 51041539}, {13311, 51042307},
1558
  {13312, 1}, {42125, 2}, {42128, 1}, {42183, 2},
1559
  {42192, 1}, {42540, 2}, {42560, 17488643}, {42561, 1},
1560
  {42562, 17488899}, {42563, 1}, {42564, 17489155}, {42565, 1},
1561
  {42566, 17489411}, {42567, 1}, {42568, 17489667}, {42569, 1},
1562
  {42570, 16936451}, {42571, 1}, {42572, 17489923}, {42573, 1},
1563
  {42574, 17490179}, {42575, 1}, {42576, 17490435}, {42577, 1},
1564
  {42578, 17490691}, {42579, 1}, {42580, 17490947}, {42581, 1},
1565
  {42582, 17491203}, {42583, 1}, {42584, 17491459}, {42585, 1},
1566
  {42586, 17491715}, {42587, 1}, {42588, 17491971}, {42589, 1},
1567
  {42590, 17492227}, {42591, 1}, {42592, 17492483}, {42593, 1},
1568
  {42594, 17492739}, {42595, 1}, {42596, 17492995}, {42597, 1},
1569
  {42598, 17493251}, {42599, 1}, {42600, 17493507}, {42601, 1},
1570
  {42602, 17493763}, {42603, 1}, {42604, 17494019}, {42605, 1},
1571
  {42624, 17494275}, {42625, 1}, {42626, 17494531}, {42627, 1},
1572
  {42628, 17494787}, {42629, 1}, {42630, 17495043}, {42631, 1},
1573
  {42632, 17495299}, {42633, 1}, {42634, 17495555}, {42635, 1},
1574
  {42636, 17495811}, {42637, 1}, {42638, 17496067}, {42639, 1},
1575
  {42640, 17496323}, {42641, 1}, {42642, 17496579}, {42643, 1},
1576
  {42644, 17496835}, {42645, 1}, {42646, 17497091}, {42647, 1},
1577
  {42648, 17497347}, {42649, 1}, {42650, 17497603}, {42651, 1},
1578
  {42652, 16873219}, {42653, 16873731}, {42654, 1}, {42744, 2},
1579
  {42752, 1}, {42786, 17497859}, {42787, 1}, {42788, 17498115},
1580
  {42789, 1}, {42790, 17498371}, {42791, 1}, {42792, 17498627},
1581
  {42793, 1}, {42794, 17498883}, {42795, 1}, {42796, 17499139},
1582
  {42797, 1}, {42798, 17499395}, {42799, 1}, {42802, 17499651},
1583
  {42803, 1}, {42804, 17499907}, {42805, 1}, {42806, 17500163},
1584
  {42807, 1}, {42808, 17500419}, {42809, 1}, {42810, 17500675},
1585
  {42811, 1}, {42812, 17500931}, {42813, 1}, {42814, 17501187},
1586
  {42815, 1}, {42816, 17501443}, {42817, 1}, {42818, 17501699},
1587
  {42819, 1}, {42820, 17501955}, {42821, 1}, {42822, 17502211},
1588
  {42823, 1}, {42824, 17502467}, {42825, 1}, {42826, 17502723},
1589
  {42827, 1}, {42828, 17502979}, {42829, 1}, {42830, 17503235},
1590
  {42831, 1}, {42832, 17503491}, {42833, 1}, {42834, 17503747},
1591
  {42835, 1}, {42836, 17504003}, {42837, 1}, {42838, 17504259},
1592
  {42839, 1}, {42840, 17504515}, {42841, 1}, {42842, 17504771},
1593
  {42843, 1}, {42844, 17505027}, {42845, 1}, {42846, 17505283},
1594
  {42847, 1}, {42848, 17505539}, {42849, 1}, {42850, 17505795},
1595
  {42851, 1}, {42852, 17506051}, {42853, 1}, {42854, 17506307},
1596
  {42855, 1}, {42856, 17506563}, {42857, 1}, {42858, 17506819},
1597
  {42859, 1}, {42860, 17507075}, {42861, 1}, {42862, 17507331},
1598
  {42863, 1}, {42864, 17507331}, {42865, 1}, {42873, 17507587},
1599
  {42874, 1}, {42875, 17507843}, {42876, 1}, {42877, 17508099},
1600
  {42878, 17508355}, {42879, 1}, {42880, 17508611}, {42881, 1},
1601
  {42882, 17508867}, {42883, 1}, {42884, 17509123}, {42885, 1},
1602
  {42886, 17509379}, {42887, 1}, {42891, 17509635}, {42892, 1},
1603
  {42893, 16951299}, {42894, 1}, {42896, 17509891}, {42897, 1},
1604
  {42898, 17510147}, {42899, 1}, {42902, 17510403}, {42903, 1},
1605
  {42904, 17510659}, {42905, 1}, {42906, 17510915}, {42907, 1},
1606
  {42908, 17511171}, {42909, 1}, {42910, 17511427}, {42911, 1},
1607
  {42912, 17511683}, {42913, 1}, {42914, 17511939}, {42915, 1},
1608
  {42916, 17512195}, {42917, 1}, {42918, 17512451}, {42919, 1},
1609
  {42920, 17512707}, {42921, 1}, {42922, 16841475}, {42923, 16948995},
1610
  {42924, 16951043}, {42925, 17512963}, {42926, 16951555}, {42927, 1},
1611
  {42928, 17513219}, {42929, 17513475}, {42930, 16952067}, {42931, 17513731},
1612
  {42932, 17513987}, {42933, 1}, {42934, 17514243}, {42935, 1},
1613
  {42936, 17514499}, {42937, 1}, {42938, 17514755}, {42939, 1},
1614
  {42940, 17515011}, {42941, 1}, {42942, 17515267}, {42943, 1},
1615
  {42944, 17515523}, {42945, 1}, {42946, 17515779}, {42947, 1},
1616
  {42948, 17516035}, {42949, 16954371}, {42950, 17516291}, {42951, 17516547},
1617
  {42952, 1}, {42953, 17516803}, {42954, 1}, {42955, 2},
1618
  {42960, 17517059}, {42961, 1}, {42962, 2}, {42963, 1},
1619
  {42964, 2}, {42965, 1}, {42966, 17517315}, {42967, 1},
1620
  {42968, 17517571}, {42969, 1}, {42970, 2}, {42994, 16777731},
1621
  {42995, 16778499}, {42996, 16781315}, {42997, 17517827}, {42998, 1},
1622
  {43000, 16802051}, {43001, 16808195}, {43002, 1}, {43053, 2},
1623
  {43056, 1}, {43066, 2}, {43072, 1}, {43128, 2},
1624
  {43136, 1}, {43206, 2}, {43214, 1}, {43226, 2},
1625
  {43232, 1}, {43348, 2}, {43359, 1}, {43389, 2},
1626
  {43392, 1}, {43470, 2}, {43471, 1}, {43482, 2},
1627
  {43486, 1}, {43519, 2}, {43520, 1}, {43575, 2},
1628
  {43584, 1}, {43598, 2}, {43600, 1}, {43610, 2},
1629
  {43612, 1}, {43715, 2}, {43739, 1}, {43767, 2},
1630
  {43777, 1}, {43783, 2}, {43785, 1}, {43791, 2},
1631
  {43793, 1}, {43799, 2}, {43808, 1}, {43815, 2},
1632
  {43816, 1}, {43823, 2}, {43824, 1}, {43868, 17498371},
1633
  {43869, 17518083}, {43870, 17124867}, {43871, 17518339}, {43872, 1},
1634
  {43881, 17518595}, {43882, 1}, {43884, 2}, {43888, 17518851},
1635
  {43889, 17519107}, {43890, 17519363}, {43891, 17519619}, {43892, 17519875},
1636
  {43893, 17520131}, {43894, 17520387}, {43895, 17520643}, {43896, 17520899},
1637
  {43897, 17521155}, {43898, 17521411}, {43899, 17521667}, {43900, 17521923},
1638
  {43901, 17522179}, {43902, 17522435}, {43903, 17522691}, {43904, 17522947},
1639
  {43905, 17523203}, {43906, 17523459}, {43907, 17523715}, {43908, 17523971},
1640
  {43909, 17524227}, {43910, 17524483}, {43911, 17524739}, {43912, 17524995},
1641
  {43913, 17525251}, {43914, 17525507}, {43915, 17525763}, {43916, 17526019},
1642
  {43917, 17526275}, {43918, 17526531}, {43919, 17526787}, {43920, 17527043},
1643
  {43921, 17527299}, {43922, 17527555}, {43923, 17527811}, {43924, 17528067},
1644
  {43925, 17528323}, {43926, 17528579}, {43927, 17528835}, {43928, 17529091},
1645
  {43929, 17529347}, {43930, 17529603}, {43931, 17529859}, {43932, 17530115},
1646
  {43933, 17530371}, {43934, 17530627}, {43935, 17530883}, {43936, 17531139},
1647
  {43937, 17531395}, {43938, 17531651}, {43939, 17531907}, {43940, 17532163},
1648
  {43941, 17532419}, {43942, 17532675}, {43943, 17532931}, {43944, 17533187},
1649
  {43945, 17533443}, {43946, 17533699}, {43947, 17533955}, {43948, 17534211},
1650
  {43949, 17534467}, {43950, 17534723}, {43951, 17534979}, {43952, 17535235},
1651
  {43953, 17535491}, {43954, 17535747}, {43955, 17536003}, {43956, 17536259},
1652
  {43957, 17536515}, {43958, 17536771}, {43959, 17537027}, {43960, 17537283},
1653
  {43961, 17537539}, {43962, 17537795}, {43963, 17538051}, {43964, 17538307},
1654
  {43965, 17538563}, {43966, 17538819}, {43967, 17539075}, {43968, 1},
1655
  {44014, 2}, {44016, 1}, {44026, 2}, {44032, 1},
1656
  {55204, 2}, {55216, 1}, {55239, 2}, {55243, 1},
1657
  {55292, 2}, {63744, 17539331}, {63745, 17539587}, {63746, 17182211},
1658
  {63747, 17539843}, {63748, 17540099}, {63749, 17540355}, {63750, 17540611},
1659
  {63751, 17196035}, {63753, 17540867}, {63754, 17184259}, {63755, 17541123},
1660
  {63756, 17541379}, {63757, 17541635}, {63758, 17541891}, {63759, 17542147},
1661
  {63760, 17542403}, {63761, 17542659}, {63762, 17542915}, {63763, 17543171},
1662
  {63764, 17543427}, {63765, 17543683}, {63766, 17543939}, {63767, 17544195},
1663
  {63768, 17544451}, {63769, 17544707}, {63770, 17544963}, {63771, 17545219},
1664
  {63772, 17545475}, {63773, 17545731}, {63774, 17545987}, {63775, 17546243},
1665
  {63776, 17546499}, {63777, 17546755}, {63778, 17547011}, {63779, 17547267},
1666
  {63780, 17547523}, {63781, 17547779}, {63782, 17548035}, {63783, 17548291},
1667
  {63784, 17548547}, {63785, 17548803}, {63786, 17549059}, {63787, 17549315},
1668
  {63788, 17549571}, {63789, 17549827}, {63790, 17550083}, {63791, 17550339},
1669
  {63792, 17550595}, {63793, 17550851}, {63794, 17551107}, {63795, 17551363},
1670
  {63796, 17173507}, {63797, 17551619}, {63798, 17551875}, {63799, 17552131},
1671
  {63800, 17552387}, {63801, 17552643}, {63802, 17552899}, {63803, 17553155},
1672
  {63804, 17553411}, {63805, 17553667}, {63806, 17553923}, {63807, 17554179},
1673
  {63808, 17192195}, {63809, 17554435}, {63810, 17554691}, {63811, 17554947},
1674
  {63812, 17555203}, {63813, 17555459}, {63814, 17555715}, {63815, 17555971},
1675
  {63816, 17556227}, {63817, 17556483}, {63818, 17556739}, {63819, 17556995},
1676
  {63820, 17557251}, {63821, 17557507}, {63822, 17557763}, {63823, 17558019},
1677
  {63824, 17558275}, {63825, 17558531}, {63826, 17558787}, {63827, 17559043},
1678
  {63828, 17559299}, {63829, 17559555}, {63830, 17559811}, {63831, 17560067},
1679
  {63832, 17560323}, {63833, 17560579}, {63834, 17560835}, {63835, 17561091},
1680
  {63836, 17543427}, {63837, 17561347}, {63838, 17561603}, {63839, 17561859},
1681
  {63840, 17562115}, {63841, 17562371}, {63842, 17562627}, {63843, 17562883},
1682
  {63844, 17563139}, {63845, 17563395}, {63846, 17563651}, {63847, 17563907},
1683
  {63848, 17564163}, {63849, 17564419}, {63850, 17564675}, {63851, 17564931},
1684
  {63852, 17565187}, {63853, 17565443}, {63854, 17565699}, {63855, 17565955},
1685
  {63856, 17566211}, {63857, 17182723}, {63858, 17566467}, {63859, 17566723},
1686
  {63860, 17566979}, {63861, 17567235}, {63862, 17567491}, {63863, 17567747},
1687
  {63864, 17568003}, {63865, 17568259}, {63866, 17568515}, {63867, 17568771},
1688
  {63868, 17569027}, {63869, 17569283}, {63870, 17569539}, {63871, 17569795},
1689
  {63872, 17570051}, {63873, 17151235}, {63874, 17570307}, {63875, 17570563},
1690
  {63876, 17570819}, {63877, 17571075}, {63878, 17571331}, {63879, 17571587},
1691
  {63880, 17571843}, {63881, 17572099}, {63882, 17146371}, {63883, 17572355},
1692
  {63884, 17572611}, {63885, 17572867}, {63886, 17573123}, {63887, 17573379},
1693
  {63888, 17573635}, {63889, 17573891}, {63890, 17574147}, {63891, 17574403},
1694
  {63892, 17574659}, {63893, 17574915}, {63894, 17575171}, {63895, 17575427},
1695
  {63896, 17575683}, {63897, 17575939}, {63898, 17576195}, {63899, 17576451},
1696
  {63900, 17576707}, {63901, 17576963}, {63902, 17577219}, {63903, 17577475},
1697
  {63904, 17577731}, {63905, 17565955}, {63906, 17577987}, {63907, 17578243},
1698
  {63908, 17578499}, {63909, 17578755}, {63910, 17579011}, {63911, 17579267},
1699
  {63912, 17317123}, {63913, 17579523}, {63914, 17561859}, {63915, 17579779},
1700
  {63916, 17580035}, {63917, 17580291}, {63918, 17580547}, {63919, 17580803},
1701
  {63920, 17581059}, {63921, 17581315}, {63922, 17581571}, {63923, 17581827},
1702
  {63924, 17582083}, {63925, 17582339}, {63926, 17582595}, {63927, 17582851},
1703
  {63928, 17583107}, {63929, 17583363}, {63930, 17583619}, {63931, 17583875},
1704
  {63932, 17584131}, {63933, 17584387}, {63934, 17584643}, {63935, 17543427},
1705
  {63936, 17584899}, {63937, 17585155}, {63938, 17585411}, {63939, 17585667},
1706
  {63940, 17195779}, {63941, 17585923}, {63942, 17586179}, {63943, 17586435},
1707
  {63944, 17586691}, {63945, 17586947}, {63946, 17587203}, {63947, 17587459},
1708
  {63948, 17587715}, {63949, 17587971}, {63950, 17588227}, {63951, 17588483},
1709
  {63952, 17588739}, {63953, 17254403}, {63954, 17588995}, {63955, 17589251},
1710
  {63956, 17589507}, {63957, 17589763}, {63958, 17590019}, {63959, 17590275},
1711
  {63960, 17590531}, {63961, 17590787}, {63962, 17591043}, {63963, 17562371},
1712
  {63964, 17591299}, {63965, 17591555}, {63966, 17591811}, {63967, 17592067},
1713
  {63968, 17592323}, {63969, 17592579}, {63970, 17592835}, {63971, 17593091},
1714
  {63972, 17593347}, {63973, 17593603}, {63974, 17593859}, {63975, 17594115},
1715
  {63976, 17594371}, {63977, 17184003}, {63978, 17594627}, {63979, 17594883},
1716
  {63980, 17595139}, {63981, 17595395}, {63982, 17595651}, {63983, 17595907},
1717
  {63984, 17596163}, {63985, 17596419}, {63986, 17596675}, {63987, 17596931},
1718
  {63988, 17597187}, {63989, 17597443}, {63990, 17597699}, {63991, 17171459},
1719
  {63992, 17597955}, {63993, 17598211}, {63994, 17598467}, {63995, 17598723},
1720
  {63996, 17598979}, {63997, 17599235}, {63998, 17599491}, {63999, 17599747},
1721
  {64000, 17600003}, {64001, 17600259}, {64002, 17600515}, {64003, 17600771},
1722
  {64004, 17601027}, {64005, 17601283}, {64006, 17601539}, {64007, 17601795},
1723
  {64008, 17178371}, {64009, 17602051}, {64010, 17179139}, {64011, 17602307},
1724
  {64012, 17602563}, {64013, 17602819}, {64014, 1}, {64016, 17603075},
1725
  {64017, 1}, {64018, 17603331}, {64019, 1}, {64021, 17603587},
1726
  {64022, 17603843}, {64023, 17604099}, {64024, 17604355}, {64025, 17604611},
1727
  {64026, 17604867}, {64027, 17605123}, {64028, 17605379}, {64029, 17605635},
1728
  {64030, 17173251}, {64031, 1}, {64032, 17605891}, {64033, 1},
1729
  {64034, 17606147}, {64035, 1}, {64037, 17606403}, {64038, 17606659},
1730
  {64039, 1}, {64042, 17606915}, {64043, 17607171}, {64044, 17607427},
1731
  {64045, 17607683}, {64046, 17607939}, {64047, 17608195}, {64048, 17608451},
1732
  {64049, 17608707}, {64050, 17608963}, {64051, 17609219}, {64052, 17609475},
1733
  {64053, 17609731}, {64054, 17609987}, {64055, 17610243}, {64056, 17610499},
1734
  {64057, 17610755}, {64058, 17611011}, {64059, 17611267}, {64060, 17153027},
1735
  {64061, 17611523}, {64062, 17611779}, {64063, 17612035}, {64064, 17612291},
1736
  {64065, 17612547}, {64066, 17612803}, {64067, 17613059}, {64068, 17613315},
1737
  {64069, 17613571}, {64070, 17613827}, {64071, 17614083}, {64072, 17614339},
1738
  {64073, 17614595}, {64074, 17614851}, {64075, 17615107}, {64076, 17265155},
1739
  {64077, 17615363}, {64078, 17615619}, {64079, 17615875}, {64080, 17616131},
1740
  {64081, 17268227}, {64082, 17616387}, {64083, 17616643}, {64084, 17616899},
1741
  {64085, 17617155}, {64086, 17617411}, {64087, 17575171}, {64088, 17617667},
1742
  {64089, 17617923}, {64090, 17618179}, {64091, 17618435}, {64092, 17618691},
1743
  {64093, 17618947}, {64095, 17619203}, {64096, 17619459}, {64097, 17619715},
1744
  {64098, 17619971}, {64099, 17620227}, {64100, 17620483}, {64101, 17620739},
1745
  {64102, 17620995}, {64103, 17606403}, {64104, 17621251}, {64105, 17621507},
1746
  {64106, 17621763}, {64107, 17622019}, {64108, 17622275}, {64109, 17622531},
1747
  {64110, 2}, {64112, 17622787}, {64113, 17623043}, {64114, 17623299},
1748
  {64115, 17623555}, {64116, 17623811}, {64117, 17624067}, {64118, 17624323},
1749
  {64119, 17624579}, {64120, 17609987}, {64121, 17624835}, {64122, 17625091},
1750
  {64123, 17625347}, {64124, 17603075}, {64125, 17625603}, {64126, 17625859},
1751
  {64127, 17626115}, {64128, 17626371}, {64129, 17626627}, {64130, 17626883},
1752
  {64131, 17627139}, {64132, 17627395}, {64133, 17627651}, {64134, 17627907},
1753
  {64135, 17628163}, {64136, 17628419}, {64137, 17612035}, {64138, 17628675},
1754
  {64139, 17612291}, {64140, 17628931}, {64141, 17629187}, {64142, 17629443},
1755
  {64143, 17629699}, {64144, 17629955}, {64145, 17603331}, {64146, 17548803},
1756
  {64147, 17630211}, {64148, 17630467}, {64149, 17161475}, {64150, 17566211},
1757
  {64151, 17587203}, {64152, 17630723}, {64153, 17630979}, {64154, 17614083},
1758
  {64155, 17631235}, {64156, 17614339}, {64157, 17631491}, {64158, 17631747},
1759
  {64159, 17632003}, {64160, 17603843}, {64161, 17632259}, {64162, 17632515},
1760
  {64163, 17632771}, {64164, 17633027}, {64165, 17633283}, {64166, 17604099},
1761
  {64167, 17633539}, {64168, 17633795}, {64169, 17634051}, {64170, 17634307},
1762
  {64171, 17634563}, {64172, 17634819}, {64173, 17617411}, {64174, 17635075},
1763
  {64175, 17635331}, {64176, 17575171}, {64177, 17635587}, {64178, 17618435},
1764
  {64179, 17635843}, {64180, 17636099}, {64181, 17636355}, {64182, 17636611},
1765
  {64183, 17636867}, {64184, 17619715}, {64185, 17637123}, {64186, 17606147},
1766
  {64187, 17637379}, {64188, 17619971}, {64189, 17561347}, {64190, 17637635},
1767
  {64191, 17620227}, {64192, 17637891}, {64193, 17620739}, {64194, 17638147},
1768
  {64195, 17638403}, {64196, 17638659}, {64197, 17638915}, {64198, 17639171},
1769
  {64199, 17621251}, {64200, 17605379}, {64201, 17639427}, {64202, 17621507},
1770
  {64203, 17639683}, {64204, 17621763}, {64205, 17639939}, {64206, 17196035},
1771
  {64207, 17640195}, {64208, 17640451}, {64209, 17640707}, {64210, 17640963},
1772
  {64211, 17641219}, {64212, 17641475}, {64213, 17641731}, {64214, 17641987},
1773
  {64215, 17642243}, {64216, 17642499}, {64217, 17642755}, {64218, 2},
1774
  {64256, 34420227}, {64257, 34420739}, {64258, 34421251}, {64259, 51197699},
1775
  {64260, 51198979}, {64261, 33559043}, {64263, 2}, {64275, 34422531},
1776
  {64276, 34423043}, {64277, 34423555}, {64278, 34424067}, {64279, 34424579},
1777
  {64280, 2}, {64285, 34425091}, {64286, 1}, {64287, 34425603},
1778
  {64288, 17648899}, {64289, 17044227}, {64290, 17044995}, {64291, 17649155},
1779
  {64292, 17649411}, {64293, 17649667}, {64294, 17649923}, {64295, 17650179},
1780
  {64296, 17650435}, {64297, 17037059}, {64298, 34427907}, {64299, 34428419},
1781
  {64300, 51206147}, {64301, 51206915}, {64302, 34430467}, {64303, 34430979},
1782
  {64304, 34431491}, {64305, 34432003}, {64306, 34432515}, {64307, 34433027},
1783
  {64308, 34433539}, {64309, 34434051}, {64310, 34434563}, {64311, 2},
1784
  {64312, 34435075}, {64313, 34435587}, {64314, 34436099}, {64315, 34436611},
1785
  {64316, 34437123}, {64317, 2}, {64318, 34437635}, {64319, 2},
1786
  {64320, 34438147}, {64321, 34438659}, {64322, 2}, {64323, 34439171},
1787
  {64324, 34439683}, {64325, 2}, {64326, 34440195}, {64327, 34440707},
1788
  {64328, 34441219}, {64329, 34428931}, {64330, 34441731}, {64331, 34442243},
1789
  {64332, 34442755}, {64333, 34443267}, {64334, 34443779}, {64335, 34444291},
1790
  {64336, 17667587}, {64338, 17667843}, {64342, 17668099}, {64346, 17668355},
1791
  {64350, 17668611}, {64354, 17668867}, {64358, 17669123}, {64362, 17669379},
1792
  {64366, 17669635}, {64370, 17669891}, {64374, 17670147}, {64378, 17670403},
1793
  {64382, 17670659}, {64386, 17670915}, {64388, 17671171}, {64390, 17671427},
1794
  {64392, 17671683}, {64394, 17671939}, {64396, 17672195}, {64398, 17672451},
1795
  {64402, 17672707}, {64406, 17672963}, {64410, 17673219}, {64414, 17673475},
1796
  {64416, 17673731}, {64420, 17673987}, {64422, 17674243}, {64426, 17674499},
1797
  {64430, 17674755}, {64432, 17675011}, {64434, 1}, {64451, 2},
1798
  {64467, 17675267}, {64471, 16911363}, {64473, 17675523}, {64475, 17675779},
1799
  {64477, 33688579}, {64478, 17676035}, {64480, 17676291}, {64482, 17676547},
1800
  {64484, 17676803}, {64488, 17677059}, {64490, 34454531}, {64492, 34455043},
1801
  {64494, 34455555}, {64496, 34456067}, {64498, 34456579}, {64500, 34457091},
1802
  {64502, 34457603}, {64505, 34458115}, {64508, 17681411}, {64512, 34458883},
1803
  {64513, 34459395}, {64514, 34459907}, {64515, 34458115}, {64516, 34460419},
1804
  {64517, 34460931}, {64518, 34461443}, {64519, 34461955}, {64520, 34462467},
1805
  {64521, 34462979}, {64522, 34463491}, {64523, 34464003}, {64524, 34464515},
1806
  {64525, 34465027}, {64526, 34465539}, {64527, 34466051}, {64528, 34466563},
1807
  {64529, 34467075}, {64530, 34467587}, {64531, 34468099}, {64532, 34468611},
1808
  {64533, 34469123}, {64534, 34469635}, {64535, 34469379}, {64536, 34470147},
1809
  {64537, 34470659}, {64538, 34471171}, {64539, 34471683}, {64540, 34472195},
1810
  {64541, 34472707}, {64542, 34473219}, {64543, 34473731}, {64544, 34474243},
1811
  {64545, 34474755}, {64546, 34475267}, {64547, 34475779}, {64548, 34476291},
1812
  {64549, 34476803}, {64550, 34477315}, {64551, 34477827}, {64552, 34478339},
1813
  {64553, 34478851}, {64554, 34479363}, {64555, 34479875}, {64556, 34480387},
1814
  {64557, 34480899}, {64558, 34481411}, {64559, 34481923}, {64560, 34482435},
1815
  {64561, 34482947}, {64562, 34483459}, {64563, 34483971}, {64564, 34484483},
1816
  {64565, 34484995}, {64566, 34485507}, {64567, 34486019}, {64568, 34486531},
1817
  {64569, 34487043}, {64570, 34487555}, {64571, 34488067}, {64572, 34488579},
1818
  {64573, 34489091}, {64574, 34489603}, {64575, 34490115}, {64576, 34490627},
1819
  {64577, 34491139}, {64578, 34491651}, {64579, 34492163}, {64580, 34492675},
1820
  {64581, 34493187}, {64582, 34469891}, {64583, 34470403}, {64584, 34493699},
1821
  {64585, 34494211}, {64586, 34494723}, {64587, 34495235}, {64588, 34495747},
1822
  {64589, 34496259}, {64590, 34496771}, {64591, 34497283}, {64592, 34497795},
1823
  {64593, 34498307}, {64594, 34498819}, {64595, 34499331}, {64596, 34499843},
1824
  {64597, 34468867}, {64598, 34500355}, {64599, 34500867}, {64600, 34492931},
1825
  {64601, 34501379}, {64602, 34500099}, {64603, 34501891}, {64604, 34502403},
1826
  {64605, 34502915}, {64606, 51280643}, {64607, 51281411}, {64608, 51282179},
1827
  {64609, 51282947}, {64610, 51283715}, {64611, 51284483}, {64612, 34508035},
1828
  {64613, 34508547}, {64614, 34459907}, {64615, 34509059}, {64616, 34458115},
1829
  {64617, 34460419}, {64618, 34509571}, {64619, 34510083}, {64620, 34462467},
1830
  {64621, 34510595}, {64622, 34462979}, {64623, 34463491}, {64624, 34511107},
1831
  {64625, 34511619}, {64626, 34465539}, {64627, 34512131}, {64628, 34466051},
1832
  {64629, 34466563}, {64630, 34512643}, {64631, 34513155}, {64632, 34467587},
1833
  {64633, 34513667}, {64634, 34468099}, {64635, 34468611}, {64636, 34482947},
1834
  {64637, 34483459}, {64638, 34484995}, {64639, 34485507}, {64640, 34486019},
1835
  {64641, 34488067}, {64642, 34488579}, {64643, 34489091}, {64644, 34489603},
1836
  {64645, 34491651}, {64646, 34492163}, {64647, 34492675}, {64648, 34514179},
1837
  {64649, 34493699}, {64650, 34514691}, {64651, 34515203}, {64652, 34496771},
1838
  {64653, 34515715}, {64654, 34497283}, {64655, 34497795}, {64656, 34502915},
1839
  {64657, 34516227}, {64658, 34516739}, {64659, 34492931}, {64660, 34494979},
1840
  {64661, 34501379}, {64662, 34500099}, {64663, 34458883}, {64664, 34459395},
1841
  {64665, 34517251}, {64666, 34459907}, {64667, 34517763}, {64668, 34460931},
1842
  {64669, 34461443}, {64670, 34461955}, {64671, 34462467}, {64672, 34518275},
1843
  {64673, 34464003}, {64674, 34464515}, {64675, 34465027}, {64676, 34465539},
1844
  {64677, 34518787}, {64678, 34467587}, {64679, 34469123}, {64680, 34469635},
1845
  {64681, 34469379}, {64682, 34470147}, {64683, 34470659}, {64684, 34471683},
1846
  {64685, 34472195}, {64686, 34472707}, {64687, 34473219}, {64688, 34473731},
1847
  {64689, 34474243}, {64690, 34519299}, {64691, 34474755}, {64692, 34475267},
1848
  {64693, 34475779}, {64694, 34476291}, {64695, 34476803}, {64696, 34477315},
1849
  {64697, 34478339}, {64698, 34478851}, {64699, 34479363}, {64700, 34479875},
1850
  {64701, 34480387}, {64702, 34480899}, {64703, 34481411}, {64704, 34481923},
1851
  {64705, 34482435}, {64706, 34483971}, {64707, 34484483}, {64708, 34486531},
1852
  {64709, 34487043}, {64710, 34487555}, {64711, 34488067}, {64712, 34488579},
1853
  {64713, 34490115}, {64714, 34490627}, {64715, 34491139}, {64716, 34491651},
1854
  {64717, 34519811}, {64718, 34493187}, {64719, 34469891}, {64720, 34470403},
1855
  {64721, 34493699}, {64722, 34495235}, {64723, 34495747}, {64724, 34496259},
1856
  {64725, 34496771}, {64726, 34520323}, {64727, 34498307}, {64728, 34498819},
1857
  {64729, 34520835}, {64730, 34468867}, {64731, 34500355}, {64732, 34500867},
1858
  {64733, 34492931}, {64734, 34498051}, {64735, 34459907}, {64736, 34517763},
1859
  {64737, 34462467}, {64738, 34518275}, {64739, 34465539}, {64740, 34518787},
1860
  {64741, 34467587}, {64742, 34521347}, {64743, 34473731}, {64744, 34521859},
1861
  {64745, 34522371}, {64746, 34522883}, {64747, 34488067}, {64748, 34488579},
1862
  {64749, 34491651}, {64750, 34496771}, {64751, 34520323}, {64752, 34492931},
1863
  {64753, 34498051}, {64754, 51300611}, {64755, 51301379}, {64756, 51302147},
1864
  {64757, 34525699}, {64758, 34526211}, {64759, 34526723}, {64760, 34527235},
1865
  {64761, 34527747}, {64762, 34528259}, {64763, 34528771}, {64764, 34529283},
1866
  {64765, 34529795}, {64766, 34530307}, {64767, 34530819}, {64768, 34500611},
1867
  {64769, 34531331}, {64770, 34531843}, {64771, 34532355}, {64772, 34501123},
1868
  {64773, 34532867}, {64774, 34533379}, {64775, 34533891}, {64776, 34534403},
1869
  {64777, 34534915}, {64778, 34535427}, {64779, 34535939}, {64780, 34522371},
1870
  {64781, 34536451}, {64782, 34536963}, {64783, 34537475}, {64784, 34537987},
1871
  {64785, 34525699}, {64786, 34526211}, {64787, 34526723}, {64788, 34527235},
1872
  {64789, 34527747}, {64790, 34528259}, {64791, 34528771}, {64792, 34529283},
1873
  {64793, 34529795}, {64794, 34530307}, {64795, 34530819}, {64796, 34500611},
1874
  {64797, 34531331}, {64798, 34531843}, {64799, 34532355}, {64800, 34501123},
1875
  {64801, 34532867}, {64802, 34533379}, {64803, 34533891}, {64804, 34534403},
1876
  {64805, 34534915}, {64806, 34535427}, {64807, 34535939}, {64808, 34522371},
1877
  {64809, 34536451}, {64810, 34536963}, {64811, 34537475}, {64812, 34537987},
1878
  {64813, 34534915}, {64814, 34535427}, {64815, 34535939}, {64816, 34522371},
1879
  {64817, 34521859}, {64818, 34522883}, {64819, 34477827}, {64820, 34472195},
1880
  {64821, 34472707}, {64822, 34473219}, {64823, 34534915}, {64824, 34535427},
1881
  {64825, 34535939}, {64826, 34477827}, {64827, 34478339}, {64828, 34538499},
1882
  {64830, 1}, {64848, 51316227}, {64849, 51316995}, {64851, 51317763},
1883
  {64852, 51318531}, {64853, 51319299}, {64854, 51320067}, {64855, 51320835},
1884
  {64856, 51246851}, {64858, 51321603}, {64859, 51322371}, {64860, 51323139},
1885
  {64861, 51323907}, {64862, 51324675}, {64863, 51325443}, {64865, 51326211},
1886
  {64866, 51326979}, {64868, 51327747}, {64870, 51328515}, {64871, 51329283},
1887
  {64873, 51330051}, {64874, 51330819}, {64876, 51331587}, {64878, 51332355},
1888
  {64879, 51333123}, {64881, 51333891}, {64883, 51334659}, {64884, 51335427},
1889
  {64885, 51336195}, {64886, 51336963}, {64888, 51337731}, {64889, 51338499},
1890
  {64890, 51339267}, {64891, 51340035}, {64892, 51340803}, {64894, 51341571},
1891
  {64895, 51342339}, {64896, 51343107}, {64897, 51343875}, {64898, 51344643},
1892
  {64899, 51345411}, {64901, 51346179}, {64903, 51346947}, {64905, 51347715},
1893
  {64906, 51247107}, {64907, 51348483}, {64908, 51349251}, {64909, 51270403},
1894
  {64910, 51247619}, {64911, 51350019}, {64912, 2}, {64914, 51350787},
1895
  {64915, 51351555}, {64916, 51352323}, {64917, 51353091}, {64918, 51353859},
1896
  {64919, 51354627}, {64921, 51355395}, {64922, 51356163}, {64923, 51356931},
1897
  {64924, 51357699}, {64926, 51358467}, {64927, 51359235}, {64928, 51360003},
1898
  {64929, 51360771}, {64930, 51361539}, {64931, 51362307}, {64932, 51363075},
1899
  {64933, 51363843}, {64934, 51364611}, {64935, 51365379}, {64936, 51366147},
1900
  {64937, 51366915}, {64938, 51367683}, {64939, 51368451}, {64940, 51369219},
1901
  {64941, 51369987}, {64942, 51277571}, {64943, 51370755}, {64944, 51371523},
1902
  {64945, 51372291}, {64946, 51373059}, {64947, 51373827}, {64948, 51341571},
1903
  {64949, 51343107}, {64950, 51374595}, {64951, 51375363}, {64952, 51376131},
1904
  {64953, 51376899}, {64954, 51377667}, {64955, 51378435}, {64956, 51377667},
1905
  {64957, 51376131}, {64958, 51379203}, {64959, 51379971}, {64960, 51380739},
1906
  {64961, 51381507}, {64962, 51382275}, {64963, 51378435}, {64964, 51336195},
1907
  {64965, 51328515}, {64966, 51383043}, {64967, 51383811}, {64968, 2},
1908
  {64975, 1}, {64976, 2}, {65008, 51384579}, {65009, 51385347},
1909
  {65010, 68163331}, {65011, 68164355}, {65012, 68165379}, {65013, 68166403},
1910
  {65014, 68167427}, {65015, 68168451}, {65016, 68169475}, {65017, 51393283},
1911
  {65018, 303052291}, {65019, 135284739}, {65020, 68177923}, {65021, 1},
1912
  {65024, 0}, {65040, 17847299}, {65041, 17847555}, {65042, 2},
1913
  {65043, 17110531}, {65044, 16848643}, {65045, 17032963}, {65046, 17033987},
1914
  {65047, 17847811}, {65048, 17848067}, {65049, 2}, {65056, 1},
1915
  {65072, 2}, {65073, 17848323}, {65074, 17848579}, {65075, 17848835},
1916
  {65077, 17037827}, {65078, 17038083}, {65079, 17849091}, {65080, 17849347},
1917
  {65081, 17849603}, {65082, 17849859}, {65083, 17850115}, {65084, 17850371},
1918
  {65085, 17850627}, {65086, 17850883}, {65087, 17067267}, {65088, 17067523},
1919
  {65089, 17851139}, {65090, 17851395}, {65091, 17851651}, {65092, 17851907},
1920
  {65093, 1}, {65095, 17852163}, {65096, 17852419}, {65097, 33810691},
1921
  {65101, 17848835}, {65104, 17847299}, {65105, 17847555}, {65106, 2},
1922
  {65108, 16848643}, {65109, 17110531}, {65110, 17033987}, {65111, 17032963},
1923
  {65112, 17848323}, {65113, 17037827}, {65114, 17038083}, {65115, 17849091},
1924
  {65116, 17849347}, {65117, 17849603}, {65118, 17849859}, {65119, 17852675},
1925
  {65120, 17852931}, {65121, 17853187}, {65122, 17037059}, {65123, 17853443},
1926
  {65124, 17853699}, {65125, 17853955}, {65126, 17037571}, {65127, 2},
1927
  {65128, 17854211}, {65129, 17854467}, {65130, 17854723}, {65131, 17854979},
1928
  {65132, 2}, {65136, 34632451}, {65137, 34632963}, {65138, 34503427},
1929
  {65139, 1}, {65140, 34504195}, {65141, 2}, {65142, 34504963},
1930
  {65143, 34523395}, {65144, 34505731}, {65145, 34524163}, {65146, 34506499},
1931
  {65147, 34524931}, {65148, 34507267}, {65149, 34633475}, {65150, 34633987},
1932
  {65151, 34634499}, {65152, 17857795}, {65153, 17858051}, {65155, 17858307},
1933
  {65157, 17858563}, {65159, 17858819}, {65161, 17677315}, {65165, 16910339},
1934
  {65167, 17683715}, {65171, 17859075}, {65173, 17686787}, {65177, 17689859},
1935
  {65181, 17681923}, {65185, 17682435}, {65189, 17684995}, {65193, 17834499},
1936
  {65195, 17724675}, {65197, 17725187}, {65199, 17731587}, {65201, 17694979},
1937
  {65205, 17745155}, {65209, 17697027}, {65213, 17698051}, {65217, 17700099},
1938
  {65221, 17701123}, {65225, 17701635}, {65229, 17702659}, {65233, 17703683},
1939
  {65237, 17706755}, {65241, 17708803}, {65245, 17711107}, {65249, 17682947},
1940
  {65253, 17718019}, {65257, 17721091}, {65261, 16910851}, {65263, 17677059},
1941
  {65265, 16911875}, {65269, 34636547}, {65271, 34637059}, {65273, 34637571},
1942
  {65275, 34622467}, {65277, 2}, {65279, 0}, {65280, 2},
1943
  {65281, 17032963}, {65282, 17860867}, {65283, 17852675}, {65284, 17854467},
1944
  {65285, 17854723}, {65286, 17852931}, {65287, 17861123}, {65288, 17037827},
1945
  {65289, 17038083}, {65290, 17853187}, {65291, 17037059}, {65292, 17847299},
1946
  {65293, 17853443}, {65294, 17196547}, {65295, 17038595}, {65296, 17035523},
1947
  {65297, 16786947}, {65298, 16785155}, {65299, 16785411}, {65300, 16787715},
1948
  {65301, 17035779}, {65302, 17036035}, {65303, 17036291}, {65304, 17036547},
1949
  {65305, 17036803}, {65306, 17110531}, {65307, 16848643}, {65308, 17853699},
1950
  {65309, 17037571}, {65310, 17853955}, {65311, 17033987}, {65312, 17854979},
1951
  {65313, 16777219}, {65314, 16777475}, {65315, 16777731}, {65316, 16777987},
1952
  {65317, 16778243}, {65318, 16778499}, {65319, 16778755}, {65320, 16779011},
1953
  {65321, 16779267}, {65322, 16779523}, {65323, 16779779}, {65324, 16780035},
1954
  {65325, 16780291}, {65326, 16780547}, {65327, 16780803}, {65328, 16781059},
1955
  {65329, 16781315}, {65330, 16781571}, {65331, 16781827}, {65332, 16782083},
1956
  {65333, 16782339}, {65334, 16782595}, {65335, 16782851}, {65336, 16783107},
1957
  {65337, 16783363}, {65338, 16783619}, {65339, 17852163}, {65340, 17854211},
1958
  {65341, 17852419}, {65342, 17861379}, {65343, 17848835}, {65344, 17027075},
1959
  {65345, 16777219}, {65346, 16777475}, {65347, 16777731}, {65348, 16777987},
1960
  {65349, 16778243}, {65350, 16778499}, {65351, 16778755}, {65352, 16779011},
1961
  {65353, 16779267}, {65354, 16779523}, {65355, 16779779}, {65356, 16780035},
1962
  {65357, 16780291}, {65358, 16780547}, {65359, 16780803}, {65360, 16781059},
1963
  {65361, 16781315}, {65362, 16781571}, {65363, 16781827}, {65364, 16782083},
1964
  {65365, 16782339}, {65366, 16782595}, {65367, 16782851}, {65368, 16783107},
1965
  {65369, 16783363}, {65370, 16783619}, {65371, 17849091}, {65372, 17861635},
1966
  {65373, 17849347}, {65374, 17861891}, {65375, 17862147}, {65376, 17862403},
1967
  {65377, 17196547}, {65378, 17851139}, {65379, 17851395}, {65380, 17847555},
1968
  {65381, 17862659}, {65382, 17316867}, {65383, 17319427}, {65384, 17362435},
1969
  {65385, 17862915}, {65386, 17363971}, {65387, 17323523}, {65388, 17863171},
1970
  {65389, 17333763}, {65390, 17379587}, {65391, 17329155}, {65392, 17318147},
1971
  {65393, 17305603}, {65394, 17305859}, {65395, 17306115}, {65396, 17306371},
1972
  {65397, 17306627}, {65398, 17306883}, {65399, 17307139}, {65400, 17307395},
1973
  {65401, 17307651}, {65402, 17199107}, {65403, 17307907}, {65404, 17308163},
1974
  {65405, 17308419}, {65406, 17308675}, {65407, 17308931}, {65408, 17309187},
1975
  {65409, 17309443}, {65410, 17309699}, {65411, 17309955}, {65412, 17199363},
1976
  {65413, 17310211}, {65414, 17310467}, {65415, 17310723}, {65416, 17310979},
1977
  {65417, 17311235}, {65418, 17311491}, {65419, 17311747}, {65420, 17312003},
1978
  {65421, 17312259}, {65422, 17312515}, {65423, 17312771}, {65424, 17313027},
1979
  {65425, 17313283}, {65426, 17313539}, {65427, 17313795}, {65428, 17314051},
1980
  {65429, 17314307}, {65430, 17314563}, {65431, 17314819}, {65432, 17315075},
1981
  {65433, 17315331}, {65434, 17315587}, {65435, 17315843}, {65436, 17316099},
1982
  {65437, 17319939}, {65438, 17197827}, {65439, 17198339}, {65440, 2},
1983
  {65441, 17199619}, {65442, 17199875}, {65443, 17200131}, {65444, 17200387},
1984
  {65445, 17200643}, {65446, 17200899}, {65447, 17201155}, {65448, 17201411},
1985
  {65449, 17201667}, {65450, 17201923}, {65451, 17202179}, {65452, 17202435},
1986
  {65453, 17202691}, {65454, 17202947}, {65455, 17203203}, {65456, 17203459},
1987
  {65457, 17203715}, {65458, 17203971}, {65459, 17204227}, {65460, 17204483},
1988
  {65461, 17204739}, {65462, 17204995}, {65463, 17205251}, {65464, 17205507},
1989
  {65465, 17205763}, {65466, 17206019}, {65467, 17206275}, {65468, 17206531},
1990
  {65469, 17206787}, {65470, 17207043}, {65471, 2}, {65474, 17207299},
1991
  {65475, 17207555}, {65476, 17207811}, {65477, 17208067}, {65478, 17208323},
1992
  {65479, 17208579}, {65480, 2}, {65482, 17208835}, {65483, 17209091},
1993
  {65484, 17209347}, {65485, 17209603}, {65486, 17209859}, {65487, 17210115},
1994
  {65488, 2}, {65490, 17210371}, {65491, 17210627}, {65492, 17210883},
1995
  {65493, 17211139}, {65494, 17211395}, {65495, 17211651}, {65496, 2},
1996
  {65498, 17211907}, {65499, 17212163}, {65500, 17212419}, {65501, 2},
1997
  {65504, 17863427}, {65505, 17863683}, {65506, 17863939}, {65507, 33561859},
1998
  {65508, 17864195}, {65509, 17864451}, {65510, 17864707}, {65511, 2},
1999
  {65512, 17864963}, {65513, 17865219}, {65514, 17865475}, {65515, 17865731},
2000
  {65516, 17865987}, {65517, 17866243}, {65518, 17866499}, {65519, 2},
2001
  {65536, 1}, {65548, 2}, {65549, 1}, {65575, 2},
2002
  {65576, 1}, {65595, 2}, {65596, 1}, {65598, 2},
2003
  {65599, 1}, {65614, 2}, {65616, 1}, {65630, 2},
2004
  {65664, 1}, {65787, 2}, {65792, 1}, {65795, 2},
2005
  {65799, 1}, {65844, 2}, {65847, 1}, {65935, 2},
2006
  {65936, 1}, {65949, 2}, {65952, 1}, {65953, 2},
2007
  {66000, 1}, {66046, 2}, {66176, 1}, {66205, 2},
2008
  {66208, 1}, {66257, 2}, {66272, 1}, {66300, 2},
2009
  {66304, 1}, {66340, 2}, {66349, 1}, {66379, 2},
2010
  {66384, 1}, {66427, 2}, {66432, 1}, {66462, 2},
2011
  {66463, 1}, {66500, 2}, {66504, 1}, {66518, 2},
2012
  {66560, 17866755}, {66561, 17867011}, {66562, 17867267}, {66563, 17867523},
2013
  {66564, 17867779}, {66565, 17868035}, {66566, 17868291}, {66567, 17868547},
2014
  {66568, 17868803}, {66569, 17869059}, {66570, 17869315}, {66571, 17869571},
2015
  {66572, 17869827}, {66573, 17870083}, {66574, 17870339}, {66575, 17870595},
2016
  {66576, 17870851}, {66577, 17871107}, {66578, 17871363}, {66579, 17871619},
2017
  {66580, 17871875}, {66581, 17872131}, {66582, 17872387}, {66583, 17872643},
2018
  {66584, 17872899}, {66585, 17873155}, {66586, 17873411}, {66587, 17873667},
2019
  {66588, 17873923}, {66589, 17874179}, {66590, 17874435}, {66591, 17874691},
2020
  {66592, 17874947}, {66593, 17875203}, {66594, 17875459}, {66595, 17875715},
2021
  {66596, 17875971}, {66597, 17876227}, {66598, 17876483}, {66599, 17876739},
2022
  {66600, 1}, {66718, 2}, {66720, 1}, {66730, 2},
2023
  {66736, 17876995}, {66737, 17877251}, {66738, 17877507}, {66739, 17877763},
2024
  {66740, 17878019}, {66741, 17878275}, {66742, 17878531}, {66743, 17878787},
2025
  {66744, 17879043}, {66745, 17879299}, {66746, 17879555}, {66747, 17879811},
2026
  {66748, 17880067}, {66749, 17880323}, {66750, 17880579}, {66751, 17880835},
2027
  {66752, 17881091}, {66753, 17881347}, {66754, 17881603}, {66755, 17881859},
2028
  {66756, 17882115}, {66757, 17882371}, {66758, 17882627}, {66759, 17882883},
2029
  {66760, 17883139}, {66761, 17883395}, {66762, 17883651}, {66763, 17883907},
2030
  {66764, 17884163}, {66765, 17884419}, {66766, 17884675}, {66767, 17884931},
2031
  {66768, 17885187}, {66769, 17885443}, {66770, 17885699}, {66771, 17885955},
2032
  {66772, 2}, {66776, 1}, {66812, 2}, {66816, 1},
2033
  {66856, 2}, {66864, 1}, {66916, 2}, {66927, 1},
2034
  {66928, 17886211}, {66929, 17886467}, {66930, 17886723}, {66931, 17886979},
2035
  {66932, 17887235}, {66933, 17887491}, {66934, 17887747}, {66935, 17888003},
2036
  {66936, 17888259}, {66937, 17888515}, {66938, 17888771}, {66939, 2},
2037
  {66940, 17889027}, {66941, 17889283}, {66942, 17889539}, {66943, 17889795},
2038
  {66944, 17890051}, {66945, 17890307}, {66946, 17890563}, {66947, 17890819},
2039
  {66948, 17891075}, {66949, 17891331}, {66950, 17891587}, {66951, 17891843},
2040
  {66952, 17892099}, {66953, 17892355}, {66954, 17892611}, {66955, 2},
2041
  {66956, 17892867}, {66957, 17893123}, {66958, 17893379}, {66959, 17893635},
2042
  {66960, 17893891}, {66961, 17894147}, {66962, 17894403}, {66963, 2},
2043
  {66964, 17894659}, {66965, 17894915}, {66966, 2}, {66967, 1},
2044
  {66978, 2}, {66979, 1}, {66994, 2}, {66995, 1},
2045
  {67002, 2}, {67003, 1}, {67005, 2}, {67072, 1},
2046
  {67383, 2}, {67392, 1}, {67414, 2}, {67424, 1},
2047
  {67432, 2}, {67456, 1}, {67457, 17895171}, {67458, 17895427},
2048
  {67459, 16791043}, {67460, 17895683}, {67461, 16814083}, {67462, 2},
2049
  {67463, 17895939}, {67464, 17896195}, {67465, 17896451}, {67466, 17896707},
2050
  {67467, 16815363}, {67468, 16815619}, {67469, 17896963}, {67470, 17897219},
2051
  {67471, 17897475}, {67472, 17897731}, {67473, 17897987}, {67474, 17898243},
2052
  {67475, 16817155}, {67476, 17898499}, {67477, 16802051}, {67478, 17898755},
2053
  {67479, 17899011}, {67480, 17899267}, {67481, 17899523}, {67482, 17899779},
2054
  {67483, 17512963}, {67484, 17900035}, {67485, 17900291}, {67486, 17900547},
2055
  {67487, 17900803}, {67488, 17901059}, {67489, 17901315}, {67490, 16795395},
2056
  {67491, 17901571}, {67492, 17901827}, {67493, 16781315}, {67494, 17902083},
2057
  {67495, 17902339}, {67496, 17125379}, {67497, 17902595}, {67498, 16819971},
2058
  {67499, 17902851}, {67500, 17903107}, {67501, 17903363}, {67502, 17903619},
2059
  {67503, 16820995}, {67504, 17903875}, {67505, 2}, {67506, 17904131},
2060
  {67507, 17904387}, {67508, 17904643}, {67509, 17904899}, {67510, 17905155},
2061
  {67511, 17905411}, {67512, 17905667}, {67513, 17905923}, {67514, 17906179},
2062
  {67515, 2}, {67584, 1}, {67590, 2}, {67592, 1},
2063
  {67593, 2}, {67594, 1}, {67638, 2}, {67639, 1},
2064
  {67641, 2}, {67644, 1}, {67645, 2}, {67647, 1},
2065
  {67670, 2}, {67671, 1}, {67743, 2}, {67751, 1},
2066
  {67760, 2}, {67808, 1}, {67827, 2}, {67828, 1},
2067
  {67830, 2}, {67835, 1}, {67868, 2}, {67871, 1},
2068
  {67898, 2}, {67903, 1}, {67904, 2}, {67968, 1},
2069
  {68024, 2}, {68028, 1}, {68048, 2}, {68050, 1},
2070
  {68100, 2}, {68101, 1}, {68103, 2}, {68108, 1},
2071
  {68116, 2}, {68117, 1}, {68120, 2}, {68121, 1},
2072
  {68150, 2}, {68152, 1}, {68155, 2}, {68159, 1},
2073
  {68169, 2}, {68176, 1}, {68185, 2}, {68192, 1},
2074
  {68256, 2}, {68288, 1}, {68327, 2}, {68331, 1},
2075
  {68343, 2}, {68352, 1}, {68406, 2}, {68409, 1},
2076
  {68438, 2}, {68440, 1}, {68467, 2}, {68472, 1},
2077
  {68498, 2}, {68505, 1}, {68509, 2}, {68521, 1},
2078
  {68528, 2}, {68608, 1}, {68681, 2}, {68736, 17906435},
2079
  {68737, 17906691}, {68738, 17906947}, {68739, 17907203}, {68740, 17907459},
2080
  {68741, 17907715}, {68742, 17907971}, {68743, 17908227}, {68744, 17908483},
2081
  {68745, 17908739}, {68746, 17908995}, {68747, 17909251}, {68748, 17909507},
2082
  {68749, 17909763}, {68750, 17910019}, {68751, 17910275}, {68752, 17910531},
2083
  {68753, 17910787}, {68754, 17911043}, {68755, 17911299}, {68756, 17911555},
2084
  {68757, 17911811}, {68758, 17912067}, {68759, 17912323}, {68760, 17912579},
2085
  {68761, 17912835}, {68762, 17913091}, {68763, 17913347}, {68764, 17913603},
2086
  {68765, 17913859}, {68766, 17914115}, {68767, 17914371}, {68768, 17914627},
2087
  {68769, 17914883}, {68770, 17915139}, {68771, 17915395}, {68772, 17915651},
2088
  {68773, 17915907}, {68774, 17916163}, {68775, 17916419}, {68776, 17916675},
2089
  {68777, 17916931}, {68778, 17917187}, {68779, 17917443}, {68780, 17917699},
2090
  {68781, 17917955}, {68782, 17918211}, {68783, 17918467}, {68784, 17918723},
2091
  {68785, 17918979}, {68786, 17919235}, {68787, 2}, {68800, 1},
2092
  {68851, 2}, {68858, 1}, {68904, 2}, {68912, 1},
2093
  {68922, 2}, {69216, 1}, {69247, 2}, {69248, 1},
2094
  {69290, 2}, {69291, 1}, {69294, 2}, {69296, 1},
2095
  {69298, 2}, {69373, 1}, {69416, 2}, {69424, 1},
2096
  {69466, 2}, {69488, 1}, {69514, 2}, {69552, 1},
2097
  {69580, 2}, {69600, 1}, {69623, 2}, {69632, 1},
2098
  {69710, 2}, {69714, 1}, {69750, 2}, {69759, 1},
2099
  {69821, 2}, {69822, 1}, {69827, 2}, {69840, 1},
2100
  {69865, 2}, {69872, 1}, {69882, 2}, {69888, 1},
2101
  {69941, 2}, {69942, 1}, {69960, 2}, {69968, 1},
2102
  {70007, 2}, {70016, 1}, {70112, 2}, {70113, 1},
2103
  {70133, 2}, {70144, 1}, {70162, 2}, {70163, 1},
2104
  {70210, 2}, {70272, 1}, {70279, 2}, {70280, 1},
2105
  {70281, 2}, {70282, 1}, {70286, 2}, {70287, 1},
2106
  {70302, 2}, {70303, 1}, {70314, 2}, {70320, 1},
2107
  {70379, 2}, {70384, 1}, {70394, 2}, {70400, 1},
2108
  {70404, 2}, {70405, 1}, {70413, 2}, {70415, 1},
2109
  {70417, 2}, {70419, 1}, {70441, 2}, {70442, 1},
2110
  {70449, 2}, {70450, 1}, {70452, 2}, {70453, 1},
2111
  {70458, 2}, {70459, 1}, {70469, 2}, {70471, 1},
2112
  {70473, 2}, {70475, 1}, {70478, 2}, {70480, 1},
2113
  {70481, 2}, {70487, 1}, {70488, 2}, {70493, 1},
2114
  {70500, 2}, {70502, 1}, {70509, 2}, {70512, 1},
2115
  {70517, 2}, {70656, 1}, {70748, 2}, {70749, 1},
2116
  {70754, 2}, {70784, 1}, {70856, 2}, {70864, 1},
2117
  {70874, 2}, {71040, 1}, {71094, 2}, {71096, 1},
2118
  {71134, 2}, {71168, 1}, {71237, 2}, {71248, 1},
2119
  {71258, 2}, {71264, 1}, {71277, 2}, {71296, 1},
2120
  {71354, 2}, {71360, 1}, {71370, 2}, {71424, 1},
2121
  {71451, 2}, {71453, 1}, {71468, 2}, {71472, 1},
2122
  {71495, 2}, {71680, 1}, {71740, 2}, {71840, 17919491},
2123
  {71841, 17919747}, {71842, 17920003}, {71843, 17920259}, {71844, 17920515},
2124
  {71845, 17920771}, {71846, 17921027}, {71847, 17921283}, {71848, 17921539},
2125
  {71849, 17921795}, {71850, 17922051}, {71851, 17922307}, {71852, 17922563},
2126
  {71853, 17922819}, {71854, 17923075}, {71855, 17923331}, {71856, 17923587},
2127
  {71857, 17923843}, {71858, 17924099}, {71859, 17924355}, {71860, 17924611},
2128
  {71861, 17924867}, {71862, 17925123}, {71863, 17925379}, {71864, 17925635},
2129
  {71865, 17925891}, {71866, 17926147}, {71867, 17926403}, {71868, 17926659},
2130
  {71869, 17926915}, {71870, 17927171}, {71871, 17927427}, {71872, 1},
2131
  {71923, 2}, {71935, 1}, {71943, 2}, {71945, 1},
2132
  {71946, 2}, {71948, 1}, {71956, 2}, {71957, 1},
2133
  {71959, 2}, {71960, 1}, {71990, 2}, {71991, 1},
2134
  {71993, 2}, {71995, 1}, {72007, 2}, {72016, 1},
2135
  {72026, 2}, {72096, 1}, {72104, 2}, {72106, 1},
2136
  {72152, 2}, {72154, 1}, {72165, 2}, {72192, 1},
2137
  {72264, 2}, {72272, 1}, {72355, 2}, {72368, 1},
2138
  {72441, 2}, {72448, 1}, {72458, 2}, {72704, 1},
2139
  {72713, 2}, {72714, 1}, {72759, 2}, {72760, 1},
2140
  {72774, 2}, {72784, 1}, {72813, 2}, {72816, 1},
2141
  {72848, 2}, {72850, 1}, {72872, 2}, {72873, 1},
2142
  {72887, 2}, {72960, 1}, {72967, 2}, {72968, 1},
2143
  {72970, 2}, {72971, 1}, {73015, 2}, {73018, 1},
2144
  {73019, 2}, {73020, 1}, {73022, 2}, {73023, 1},
2145
  {73032, 2}, {73040, 1}, {73050, 2}, {73056, 1},
2146
  {73062, 2}, {73063, 1}, {73065, 2}, {73066, 1},
2147
  {73103, 2}, {73104, 1}, {73106, 2}, {73107, 1},
2148
  {73113, 2}, {73120, 1}, {73130, 2}, {73440, 1},
2149
  {73465, 2}, {73472, 1}, {73489, 2}, {73490, 1},
2150
  {73531, 2}, {73534, 1}, {73562, 2}, {73648, 1},
2151
  {73649, 2}, {73664, 1}, {73714, 2}, {73727, 1},
2152
  {74650, 2}, {74752, 1}, {74863, 2}, {74864, 1},
2153
  {74869, 2}, {74880, 1}, {75076, 2}, {77712, 1},
2154
  {77811, 2}, {77824, 1}, {78896, 2}, {78912, 1},
2155
  {78934, 2}, {82944, 1}, {83527, 2}, {92160, 1},
2156
  {92729, 2}, {92736, 1}, {92767, 2}, {92768, 1},
2157
  {92778, 2}, {92782, 1}, {92863, 2}, {92864, 1},
2158
  {92874, 2}, {92880, 1}, {92910, 2}, {92912, 1},
2159
  {92918, 2}, {92928, 1}, {92998, 2}, {93008, 1},
2160
  {93018, 2}, {93019, 1}, {93026, 2}, {93027, 1},
2161
  {93048, 2}, {93053, 1}, {93072, 2}, {93760, 17927683},
2162
  {93761, 17927939}, {93762, 17928195}, {93763, 17928451}, {93764, 17928707},
2163
  {93765, 17928963}, {93766, 17929219}, {93767, 17929475}, {93768, 17929731},
2164
  {93769, 17929987}, {93770, 17930243}, {93771, 17930499}, {93772, 17930755},
2165
  {93773, 17931011}, {93774, 17931267}, {93775, 17931523}, {93776, 17931779},
2166
  {93777, 17932035}, {93778, 17932291}, {93779, 17932547}, {93780, 17932803},
2167
  {93781, 17933059}, {93782, 17933315}, {93783, 17933571}, {93784, 17933827},
2168
  {93785, 17934083}, {93786, 17934339}, {93787, 17934595}, {93788, 17934851},
2169
  {93789, 17935107}, {93790, 17935363}, {93791, 17935619}, {93792, 1},
2170
  {93851, 2}, {93952, 1}, {94027, 2}, {94031, 1},
2171
  {94088, 2}, {94095, 1}, {94112, 2}, {94176, 1},
2172
  {94181, 2}, {94192, 1}, {94194, 2}, {94208, 1},
2173
  {100344, 2}, {100352, 1}, {101590, 2}, {101632, 1},
2174
  {101641, 2}, {110576, 1}, {110580, 2}, {110581, 1},
2175
  {110588, 2}, {110589, 1}, {110591, 2}, {110592, 1},
2176
  {110883, 2}, {110898, 1}, {110899, 2}, {110928, 1},
2177
  {110931, 2}, {110933, 1}, {110934, 2}, {110948, 1},
2178
  {110952, 2}, {110960, 1}, {111356, 2}, {113664, 1},
2179
  {113771, 2}, {113776, 1}, {113789, 2}, {113792, 1},
2180
  {113801, 2}, {113808, 1}, {113818, 2}, {113820, 1},
2181
  {113824, 0}, {113828, 2}, {118528, 1}, {118574, 2},
2182
  {118576, 1}, {118599, 2}, {118608, 1}, {118724, 2},
2183
  {118784, 1}, {119030, 2}, {119040, 1}, {119079, 2},
2184
  {119081, 1}, {119134, 34713091}, {119135, 34713603}, {119136, 51491331},
2185
  {119137, 51492099}, {119138, 51492867}, {119139, 51493635}, {119140, 51494403},
2186
  {119141, 1}, {119155, 2}, {119163, 1}, {119227, 34717955},
2187
  {119228, 34718467}, {119229, 51496195}, {119230, 51496963}, {119231, 51497731},
2188
  {119232, 51498499}, {119233, 1}, {119275, 2}, {119296, 1},
2189
  {119366, 2}, {119488, 1}, {119508, 2}, {119520, 1},
2190
  {119540, 2}, {119552, 1}, {119639, 2}, {119648, 1},
2191
  {119673, 2}, {119808, 16777219}, {119809, 16777475}, {119810, 16777731},
2192
  {119811, 16777987}, {119812, 16778243}, {119813, 16778499}, {119814, 16778755},
2193
  {119815, 16779011}, {119816, 16779267}, {119817, 16779523}, {119818, 16779779},
2194
  {119819, 16780035}, {119820, 16780291}, {119821, 16780547}, {119822, 16780803},
2195
  {119823, 16781059}, {119824, 16781315}, {119825, 16781571}, {119826, 16781827},
2196
  {119827, 16782083}, {119828, 16782339}, {119829, 16782595}, {119830, 16782851},
2197
  {119831, 16783107}, {119832, 16783363}, {119833, 16783619}, {119834, 16777219},
2198
  {119835, 16777475}, {119836, 16777731}, {119837, 16777987}, {119838, 16778243},
2199
  {119839, 16778499}, {119840, 16778755}, {119841, 16779011}, {119842, 16779267},
2200
  {119843, 16779523}, {119844, 16779779}, {119845, 16780035}, {119846, 16780291},
2201
  {119847, 16780547}, {119848, 16780803}, {119849, 16781059}, {119850, 16781315},
2202
  {119851, 16781571}, {119852, 16781827}, {119853, 16782083}, {119854, 16782339},
2203
  {119855, 16782595}, {119856, 16782851}, {119857, 16783107}, {119858, 16783363},
2204
  {119859, 16783619}, {119860, 16777219}, {119861, 16777475}, {119862, 16777731},
2205
  {119863, 16777987}, {119864, 16778243}, {119865, 16778499}, {119866, 16778755},
2206
  {119867, 16779011}, {119868, 16779267}, {119869, 16779523}, {119870, 16779779},
2207
  {119871, 16780035}, {119872, 16780291}, {119873, 16780547}, {119874, 16780803},
2208
  {119875, 16781059}, {119876, 16781315}, {119877, 16781571}, {119878, 16781827},
2209
  {119879, 16782083}, {119880, 16782339}, {119881, 16782595}, {119882, 16782851},
2210
  {119883, 16783107}, {119884, 16783363}, {119885, 16783619}, {119886, 16777219},
2211
  {119887, 16777475}, {119888, 16777731}, {119889, 16777987}, {119890, 16778243},
2212
  {119891, 16778499}, {119892, 16778755}, {119893, 2}, {119894, 16779267},
2213
  {119895, 16779523}, {119896, 16779779}, {119897, 16780035}, {119898, 16780291},
2214
  {119899, 16780547}, {119900, 16780803}, {119901, 16781059}, {119902, 16781315},
2215
  {119903, 16781571}, {119904, 16781827}, {119905, 16782083}, {119906, 16782339},
2216
  {119907, 16782595}, {119908, 16782851}, {119909, 16783107}, {119910, 16783363},
2217
  {119911, 16783619}, {119912, 16777219}, {119913, 16777475}, {119914, 16777731},
2218
  {119915, 16777987}, {119916, 16778243}, {119917, 16778499}, {119918, 16778755},
2219
  {119919, 16779011}, {119920, 16779267}, {119921, 16779523}, {119922, 16779779},
2220
  {119923, 16780035}, {119924, 16780291}, {119925, 16780547}, {119926, 16780803},
2221
  {119927, 16781059}, {119928, 16781315}, {119929, 16781571}, {119930, 16781827},
2222
  {119931, 16782083}, {119932, 16782339}, {119933, 16782595}, {119934, 16782851},
2223
  {119935, 16783107}, {119936, 16783363}, {119937, 16783619}, {119938, 16777219},
2224
  {119939, 16777475}, {119940, 16777731}, {119941, 16777987}, {119942, 16778243},
2225
  {119943, 16778499}, {119944, 16778755}, {119945, 16779011}, {119946, 16779267},
2226
  {119947, 16779523}, {119948, 16779779}, {119949, 16780035}, {119950, 16780291},
2227
  {119951, 16780547}, {119952, 16780803}, {119953, 16781059}, {119954, 16781315},
2228
  {119955, 16781571}, {119956, 16781827}, {119957, 16782083}, {119958, 16782339},
2229
  {119959, 16782595}, {119960, 16782851}, {119961, 16783107}, {119962, 16783363},
2230
  {119963, 16783619}, {119964, 16777219}, {119965, 2}, {119966, 16777731},
2231
  {119967, 16777987}, {119968, 2}, {119970, 16778755}, {119971, 2},
2232
  {119973, 16779523}, {119974, 16779779}, {119975, 2}, {119977, 16780547},
2233
  {119978, 16780803}, {119979, 16781059}, {119980, 16781315}, {119981, 2},
2234
  {119982, 16781827}, {119983, 16782083}, {119984, 16782339}, {119985, 16782595},
2235
  {119986, 16782851}, {119987, 16783107}, {119988, 16783363}, {119989, 16783619},
2236
  {119990, 16777219}, {119991, 16777475}, {119992, 16777731}, {119993, 16777987},
2237
  {119994, 2}, {119995, 16778499}, {119996, 2}, {119997, 16779011},
2238
  {119998, 16779267}, {119999, 16779523}, {120000, 16779779}, {120001, 16780035},
2239
  {120002, 16780291}, {120003, 16780547}, {120004, 2}, {120005, 16781059},
2240
  {120006, 16781315}, {120007, 16781571}, {120008, 16781827}, {120009, 16782083},
2241
  {120010, 16782339}, {120011, 16782595}, {120012, 16782851}, {120013, 16783107},
2242
  {120014, 16783363}, {120015, 16783619}, {120016, 16777219}, {120017, 16777475},
2243
  {120018, 16777731}, {120019, 16777987}, {120020, 16778243}, {120021, 16778499},
2244
  {120022, 16778755}, {120023, 16779011}, {120024, 16779267}, {120025, 16779523},
2245
  {120026, 16779779}, {120027, 16780035}, {120028, 16780291}, {120029, 16780547},
2246
  {120030, 16780803}, {120031, 16781059}, {120032, 16781315}, {120033, 16781571},
2247
  {120034, 16781827}, {120035, 16782083}, {120036, 16782339}, {120037, 16782595},
2248
  {120038, 16782851}, {120039, 16783107}, {120040, 16783363}, {120041, 16783619},
2249
  {120042, 16777219}, {120043, 16777475}, {120044, 16777731}, {120045, 16777987},
2250
  {120046, 16778243}, {120047, 16778499}, {120048, 16778755}, {120049, 16779011},
2251
  {120050, 16779267}, {120051, 16779523}, {120052, 16779779}, {120053, 16780035},
2252
  {120054, 16780291}, {120055, 16780547}, {120056, 16780803}, {120057, 16781059},
2253
  {120058, 16781315}, {120059, 16781571}, {120060, 16781827}, {120061, 16782083},
2254
  {120062, 16782339}, {120063, 16782595}, {120064, 16782851}, {120065, 16783107},
2255
  {120066, 16783363}, {120067, 16783619}, {120068, 16777219}, {120069, 16777475},
2256
  {120070, 2}, {120071, 16777987}, {120072, 16778243}, {120073, 16778499},
2257
  {120074, 16778755}, {120075, 2}, {120077, 16779523}, {120078, 16779779},
2258
  {120079, 16780035}, {120080, 16780291}, {120081, 16780547}, {120082, 16780803},
2259
  {120083, 16781059}, {120084, 16781315}, {120085, 2}, {120086, 16781827},
2260
  {120087, 16782083}, {120088, 16782339}, {120089, 16782595}, {120090, 16782851},
2261
  {120091, 16783107}, {120092, 16783363}, {120093, 2}, {120094, 16777219},
2262
  {120095, 16777475}, {120096, 16777731}, {120097, 16777987}, {120098, 16778243},
2263
  {120099, 16778499}, {120100, 16778755}, {120101, 16779011}, {120102, 16779267},
2264
  {120103, 16779523}, {120104, 16779779}, {120105, 16780035}, {120106, 16780291},
2265
  {120107, 16780547}, {120108, 16780803}, {120109, 16781059}, {120110, 16781315},
2266
  {120111, 16781571}, {120112, 16781827}, {120113, 16782083}, {120114, 16782339},
2267
  {120115, 16782595}, {120116, 16782851}, {120117, 16783107}, {120118, 16783363},
2268
  {120119, 16783619}, {120120, 16777219}, {120121, 16777475}, {120122, 2},
2269
  {120123, 16777987}, {120124, 16778243}, {120125, 16778499}, {120126, 16778755},
2270
  {120127, 2}, {120128, 16779267}, {120129, 16779523}, {120130, 16779779},
2271
  {120131, 16780035}, {120132, 16780291}, {120133, 2}, {120134, 16780803},
2272
  {120135, 2}, {120138, 16781827}, {120139, 16782083}, {120140, 16782339},
2273
  {120141, 16782595}, {120142, 16782851}, {120143, 16783107}, {120144, 16783363},
2274
  {120145, 2}, {120146, 16777219}, {120147, 16777475}, {120148, 16777731},
2275
  {120149, 16777987}, {120150, 16778243}, {120151, 16778499}, {120152, 16778755},
2276
  {120153, 16779011}, {120154, 16779267}, {120155, 16779523}, {120156, 16779779},
2277
  {120157, 16780035}, {120158, 16780291}, {120159, 16780547}, {120160, 16780803},
2278
  {120161, 16781059}, {120162, 16781315}, {120163, 16781571}, {120164, 16781827},
2279
  {120165, 16782083}, {120166, 16782339}, {120167, 16782595}, {120168, 16782851},
2280
  {120169, 16783107}, {120170, 16783363}, {120171, 16783619}, {120172, 16777219},
2281
  {120173, 16777475}, {120174, 16777731}, {120175, 16777987}, {120176, 16778243},
2282
  {120177, 16778499}, {120178, 16778755}, {120179, 16779011}, {120180, 16779267},
2283
  {120181, 16779523}, {120182, 16779779}, {120183, 16780035}, {120184, 16780291},
2284
  {120185, 16780547}, {120186, 16780803}, {120187, 16781059}, {120188, 16781315},
2285
  {120189, 16781571}, {120190, 16781827}, {120191, 16782083}, {120192, 16782339},
2286
  {120193, 16782595}, {120194, 16782851}, {120195, 16783107}, {120196, 16783363},
2287
  {120197, 16783619}, {120198, 16777219}, {120199, 16777475}, {120200, 16777731},
2288
  {120201, 16777987}, {120202, 16778243}, {120203, 16778499}, {120204, 16778755},
2289
  {120205, 16779011}, {120206, 16779267}, {120207, 16779523}, {120208, 16779779},
2290
  {120209, 16780035}, {120210, 16780291}, {120211, 16780547}, {120212, 16780803},
2291
  {120213, 16781059}, {120214, 16781315}, {120215, 16781571}, {120216, 16781827},
2292
  {120217, 16782083}, {120218, 16782339}, {120219, 16782595}, {120220, 16782851},
2293
  {120221, 16783107}, {120222, 16783363}, {120223, 16783619}, {120224, 16777219},
2294
  {120225, 16777475}, {120226, 16777731}, {120227, 16777987}, {120228, 16778243},
2295
  {120229, 16778499}, {120230, 16778755}, {120231, 16779011}, {120232, 16779267},
2296
  {120233, 16779523}, {120234, 16779779}, {120235, 16780035}, {120236, 16780291},
2297
  {120237, 16780547}, {120238, 16780803}, {120239, 16781059}, {120240, 16781315},
2298
  {120241, 16781571}, {120242, 16781827}, {120243, 16782083}, {120244, 16782339},
2299
  {120245, 16782595}, {120246, 16782851}, {120247, 16783107}, {120248, 16783363},
2300
  {120249, 16783619}, {120250, 16777219}, {120251, 16777475}, {120252, 16777731},
2301
  {120253, 16777987}, {120254, 16778243}, {120255, 16778499}, {120256, 16778755},
2302
  {120257, 16779011}, {120258, 16779267}, {120259, 16779523}, {120260, 16779779},
2303
  {120261, 16780035}, {120262, 16780291}, {120263, 16780547}, {120264, 16780803},
2304
  {120265, 16781059}, {120266, 16781315}, {120267, 16781571}, {120268, 16781827},
2305
  {120269, 16782083}, {120270, 16782339}, {120271, 16782595}, {120272, 16782851},
2306
  {120273, 16783107}, {120274, 16783363}, {120275, 16783619}, {120276, 16777219},
2307
  {120277, 16777475}, {120278, 16777731}, {120279, 16777987}, {120280, 16778243},
2308
  {120281, 16778499}, {120282, 16778755}, {120283, 16779011}, {120284, 16779267},
2309
  {120285, 16779523}, {120286, 16779779}, {120287, 16780035}, {120288, 16780291},
2310
  {120289, 16780547}, {120290, 16780803}, {120291, 16781059}, {120292, 16781315},
2311
  {120293, 16781571}, {120294, 16781827}, {120295, 16782083}, {120296, 16782339},
2312
  {120297, 16782595}, {120298, 16782851}, {120299, 16783107}, {120300, 16783363},
2313
  {120301, 16783619}, {120302, 16777219}, {120303, 16777475}, {120304, 16777731},
2314
  {120305, 16777987}, {120306, 16778243}, {120307, 16778499}, {120308, 16778755},
2315
  {120309, 16779011}, {120310, 16779267}, {120311, 16779523}, {120312, 16779779},
2316
  {120313, 16780035}, {120314, 16780291}, {120315, 16780547}, {120316, 16780803},
2317
  {120317, 16781059}, {120318, 16781315}, {120319, 16781571}, {120320, 16781827},
2318
  {120321, 16782083}, {120322, 16782339}, {120323, 16782595}, {120324, 16782851},
2319
  {120325, 16783107}, {120326, 16783363}, {120327, 16783619}, {120328, 16777219},
2320
  {120329, 16777475}, {120330, 16777731}, {120331, 16777987}, {120332, 16778243},
2321
  {120333, 16778499}, {120334, 16778755}, {120335, 16779011}, {120336, 16779267},
2322
  {120337, 16779523}, {120338, 16779779}, {120339, 16780035}, {120340, 16780291},
2323
  {120341, 16780547}, {120342, 16780803}, {120343, 16781059}, {120344, 16781315},
2324
  {120345, 16781571}, {120346, 16781827}, {120347, 16782083}, {120348, 16782339},
2325
  {120349, 16782595}, {120350, 16782851}, {120351, 16783107}, {120352, 16783363},
2326
  {120353, 16783619}, {120354, 16777219}, {120355, 16777475}, {120356, 16777731},
2327
  {120357, 16777987}, {120358, 16778243}, {120359, 16778499}, {120360, 16778755},
2328
  {120361, 16779011}, {120362, 16779267}, {120363, 16779523}, {120364, 16779779},
2329
  {120365, 16780035}, {120366, 16780291}, {120367, 16780547}, {120368, 16780803},
2330
  {120369, 16781059}, {120370, 16781315}, {120371, 16781571}, {120372, 16781827},
2331
  {120373, 16782083}, {120374, 16782339}, {120375, 16782595}, {120376, 16782851},
2332
  {120377, 16783107}, {120378, 16783363}, {120379, 16783619}, {120380, 16777219},
2333
  {120381, 16777475}, {120382, 16777731}, {120383, 16777987}, {120384, 16778243},
2334
  {120385, 16778499}, {120386, 16778755}, {120387, 16779011}, {120388, 16779267},
2335
  {120389, 16779523}, {120390, 16779779}, {120391, 16780035}, {120392, 16780291},
2336
  {120393, 16780547}, {120394, 16780803}, {120395, 16781059}, {120396, 16781315},
2337
  {120397, 16781571}, {120398, 16781827}, {120399, 16782083}, {120400, 16782339},
2338
  {120401, 16782595}, {120402, 16782851}, {120403, 16783107}, {120404, 16783363},
2339
  {120405, 16783619}, {120406, 16777219}, {120407, 16777475}, {120408, 16777731},
2340
  {120409, 16777987}, {120410, 16778243}, {120411, 16778499}, {120412, 16778755},
2341
  {120413, 16779011}, {120414, 16779267}, {120415, 16779523}, {120416, 16779779},
2342
  {120417, 16780035}, {120418, 16780291}, {120419, 16780547}, {120420, 16780803},
2343
  {120421, 16781059}, {120422, 16781315}, {120423, 16781571}, {120424, 16781827},
2344
  {120425, 16782083}, {120426, 16782339}, {120427, 16782595}, {120428, 16782851},
2345
  {120429, 16783107}, {120430, 16783363}, {120431, 16783619}, {120432, 16777219},
2346
  {120433, 16777475}, {120434, 16777731}, {120435, 16777987}, {120436, 16778243},
2347
  {120437, 16778499}, {120438, 16778755}, {120439, 16779011}, {120440, 16779267},
2348
  {120441, 16779523}, {120442, 16779779}, {120443, 16780035}, {120444, 16780291},
2349
  {120445, 16780547}, {120446, 16780803}, {120447, 16781059}, {120448, 16781315},
2350
  {120449, 16781571}, {120450, 16781827}, {120451, 16782083}, {120452, 16782339},
2351
  {120453, 16782595}, {120454, 16782851}, {120455, 16783107}, {120456, 16783363},
2352
  {120457, 16783619}, {120458, 16777219}, {120459, 16777475}, {120460, 16777731},
2353
  {120461, 16777987}, {120462, 16778243}, {120463, 16778499}, {120464, 16778755},
2354
  {120465, 16779011}, {120466, 16779267}, {120467, 16779523}, {120468, 16779779},
2355
  {120469, 16780035}, {120470, 16780291}, {120471, 16780547}, {120472, 16780803},
2356
  {120473, 16781059}, {120474, 16781315}, {120475, 16781571}, {120476, 16781827},
2357
  {120477, 16782083}, {120478, 16782339}, {120479, 16782595}, {120480, 16782851},
2358
  {120481, 16783107}, {120482, 16783363}, {120483, 16783619}, {120484, 17944835},
2359
  {120485, 17945091}, {120486, 2}, {120488, 16851715}, {120489, 16851971},
2360
  {120490, 16852227}, {120491, 16852483}, {120492, 16852739}, {120493, 16852995},
2361
  {120494, 16853251}, {120495, 16853507}, {120496, 16846851}, {120497, 16853763},
2362
  {120498, 16854019}, {120499, 16786179}, {120500, 16854275}, {120501, 16854531},
2363
  {120502, 16854787}, {120503, 16855043}, {120504, 16855299}, {120505, 16853507},
2364
  {120506, 16855555}, {120507, 16855811}, {120508, 16856067}, {120509, 16856323},
2365
  {120510, 16856579}, {120511, 16856835}, {120512, 16857091}, {120513, 17945347},
2366
  {120514, 16851715}, {120515, 16851971}, {120516, 16852227}, {120517, 16852483},
2367
  {120518, 16852739}, {120519, 16852995}, {120520, 16853251}, {120521, 16853507},
2368
  {120522, 16846851}, {120523, 16853763}, {120524, 16854019}, {120525, 16786179},
2369
  {120526, 16854275}, {120527, 16854531}, {120528, 16854787}, {120529, 16855043},
2370
  {120530, 16855299}, {120531, 16855555}, {120533, 16855811}, {120534, 16856067},
2371
  {120535, 16856323}, {120536, 16856579}, {120537, 16856835}, {120538, 16857091},
2372
  {120539, 17945603}, {120540, 16852739}, {120541, 16853507}, {120542, 16853763},
2373
  {120543, 16856323}, {120544, 16855299}, {120545, 16855043}, {120546, 16851715},
2374
  {120547, 16851971}, {120548, 16852227}, {120549, 16852483}, {120550, 16852739},
2375
  {120551, 16852995}, {120552, 16853251}, {120553, 16853507}, {120554, 16846851},
2376
  {120555, 16853763}, {120556, 16854019}, {120557, 16786179}, {120558, 16854275},
2377
  {120559, 16854531}, {120560, 16854787}, {120561, 16855043}, {120562, 16855299},
2378
  {120563, 16853507}, {120564, 16855555}, {120565, 16855811}, {120566, 16856067},
2379
  {120567, 16856323}, {120568, 16856579}, {120569, 16856835}, {120570, 16857091},
2380
  {120571, 17945347}, {120572, 16851715}, {120573, 16851971}, {120574, 16852227},
2381
  {120575, 16852483}, {120576, 16852739}, {120577, 16852995}, {120578, 16853251},
2382
  {120579, 16853507}, {120580, 16846851}, {120581, 16853763}, {120582, 16854019},
2383
  {120583, 16786179}, {120584, 16854275}, {120585, 16854531}, {120586, 16854787},
2384
  {120587, 16855043}, {120588, 16855299}, {120589, 16855555}, {120591, 16855811},
2385
  {120592, 16856067}, {120593, 16856323}, {120594, 16856579}, {120595, 16856835},
2386
  {120596, 16857091}, {120597, 17945603}, {120598, 16852739}, {120599, 16853507},
2387
  {120600, 16853763}, {120601, 16856323}, {120602, 16855299}, {120603, 16855043},
2388
  {120604, 16851715}, {120605, 16851971}, {120606, 16852227}, {120607, 16852483},
2389
  {120608, 16852739}, {120609, 16852995}, {120610, 16853251}, {120611, 16853507},
2390
  {120612, 16846851}, {120613, 16853763}, {120614, 16854019}, {120615, 16786179},
2391
  {120616, 16854275}, {120617, 16854531}, {120618, 16854787}, {120619, 16855043},
2392
  {120620, 16855299}, {120621, 16853507}, {120622, 16855555}, {120623, 16855811},
2393
  {120624, 16856067}, {120625, 16856323}, {120626, 16856579}, {120627, 16856835},
2394
  {120628, 16857091}, {120629, 17945347}, {120630, 16851715}, {120631, 16851971},
2395
  {120632, 16852227}, {120633, 16852483}, {120634, 16852739}, {120635, 16852995},
2396
  {120636, 16853251}, {120637, 16853507}, {120638, 16846851}, {120639, 16853763},
2397
  {120640, 16854019}, {120641, 16786179}, {120642, 16854275}, {120643, 16854531},
2398
  {120644, 16854787}, {120645, 16855043}, {120646, 16855299}, {120647, 16855555},
2399
  {120649, 16855811}, {120650, 16856067}, {120651, 16856323}, {120652, 16856579},
2400
  {120653, 16856835}, {120654, 16857091}, {120655, 17945603}, {120656, 16852739},
2401
  {120657, 16853507}, {120658, 16853763}, {120659, 16856323}, {120660, 16855299},
2402
  {120661, 16855043}, {120662, 16851715}, {120663, 16851971}, {120664, 16852227},
2403
  {120665, 16852483}, {120666, 16852739}, {120667, 16852995}, {120668, 16853251},
2404
  {120669, 16853507}, {120670, 16846851}, {120671, 16853763}, {120672, 16854019},
2405
  {120673, 16786179}, {120674, 16854275}, {120675, 16854531}, {120676, 16854787},
2406
  {120677, 16855043}, {120678, 16855299}, {120679, 16853507}, {120680, 16855555},
2407
  {120681, 16855811}, {120682, 16856067}, {120683, 16856323}, {120684, 16856579},
2408
  {120685, 16856835}, {120686, 16857091}, {120687, 17945347}, {120688, 16851715},
2409
  {120689, 16851971}, {120690, 16852227}, {120691, 16852483}, {120692, 16852739},
2410
  {120693, 16852995}, {120694, 16853251}, {120695, 16853507}, {120696, 16846851},
2411
  {120697, 16853763}, {120698, 16854019}, {120699, 16786179}, {120700, 16854275},
2412
  {120701, 16854531}, {120702, 16854787}, {120703, 16855043}, {120704, 16855299},
2413
  {120705, 16855555}, {120707, 16855811}, {120708, 16856067}, {120709, 16856323},
2414
  {120710, 16856579}, {120711, 16856835}, {120712, 16857091}, {120713, 17945603},
2415
  {120714, 16852739}, {120715, 16853507}, {120716, 16853763}, {120717, 16856323},
2416
  {120718, 16855299}, {120719, 16855043}, {120720, 16851715}, {120721, 16851971},
2417
  {120722, 16852227}, {120723, 16852483}, {120724, 16852739}, {120725, 16852995},
2418
  {120726, 16853251}, {120727, 16853507}, {120728, 16846851}, {120729, 16853763},
2419
  {120730, 16854019}, {120731, 16786179}, {120732, 16854275}, {120733, 16854531},
2420
  {120734, 16854787}, {120735, 16855043}, {120736, 16855299}, {120737, 16853507},
2421
  {120738, 16855555}, {120739, 16855811}, {120740, 16856067}, {120741, 16856323},
2422
  {120742, 16856579}, {120743, 16856835}, {120744, 16857091}, {120745, 17945347},
2423
  {120746, 16851715}, {120747, 16851971}, {120748, 16852227}, {120749, 16852483},
2424
  {120750, 16852739}, {120751, 16852995}, {120752, 16853251}, {120753, 16853507},
2425
  {120754, 16846851}, {120755, 16853763}, {120756, 16854019}, {120757, 16786179},
2426
  {120758, 16854275}, {120759, 16854531}, {120760, 16854787}, {120761, 16855043},
2427
  {120762, 16855299}, {120763, 16855555}, {120765, 16855811}, {120766, 16856067},
2428
  {120767, 16856323}, {120768, 16856579}, {120769, 16856835}, {120770, 16857091},
2429
  {120771, 17945603}, {120772, 16852739}, {120773, 16853507}, {120774, 16853763},
2430
  {120775, 16856323}, {120776, 16855299}, {120777, 16855043}, {120778, 16858627},
2431
  {120780, 2}, {120782, 17035523}, {120783, 16786947}, {120784, 16785155},
2432
  {120785, 16785411}, {120786, 16787715}, {120787, 17035779}, {120788, 17036035},
2433
  {120789, 17036291}, {120790, 17036547}, {120791, 17036803}, {120792, 17035523},
2434
  {120793, 16786947}, {120794, 16785155}, {120795, 16785411}, {120796, 16787715},
2435
  {120797, 17035779}, {120798, 17036035}, {120799, 17036291}, {120800, 17036547},
2436
  {120801, 17036803}, {120802, 17035523}, {120803, 16786947}, {120804, 16785155},
2437
  {120805, 16785411}, {120806, 16787715}, {120807, 17035779}, {120808, 17036035},
2438
  {120809, 17036291}, {120810, 17036547}, {120811, 17036803}, {120812, 17035523},
2439
  {120813, 16786947}, {120814, 16785155}, {120815, 16785411}, {120816, 16787715},
2440
  {120817, 17035779}, {120818, 17036035}, {120819, 17036291}, {120820, 17036547},
2441
  {120821, 17036803}, {120822, 17035523}, {120823, 16786947}, {120824, 16785155},
2442
  {120825, 16785411}, {120826, 16787715}, {120827, 17035779}, {120828, 17036035},
2443
  {120829, 17036291}, {120830, 17036547}, {120831, 17036803}, {120832, 1},
2444
  {121484, 2}, {121499, 1}, {121504, 2}, {121505, 1},
2445
  {121520, 2}, {122624, 1}, {122655, 2}, {122661, 1},
2446
  {122667, 2}, {122880, 1}, {122887, 2}, {122888, 1},
2447
  {122905, 2}, {122907, 1}, {122914, 2}, {122915, 1},
2448
  {122917, 2}, {122918, 1}, {122923, 2}, {122928, 16866563},
2449
  {122929, 16866819}, {122930, 16867075}, {122931, 16867331}, {122932, 16867587},
2450
  {122933, 16867843}, {122934, 16868099}, {122935, 16868355}, {122936, 16868611},
2451
  {122937, 16869123}, {122938, 16869379}, {122939, 16869635}, {122940, 16870147},
2452
  {122941, 16870403}, {122942, 16870659}, {122943, 16870915}, {122944, 16871171},
2453
  {122945, 16871427}, {122946, 16871683}, {122947, 16871939}, {122948, 16872195},
2454
  {122949, 16872451}, {122950, 16872707}, {122951, 16873475}, {122952, 16873987},
2455
  {122953, 16874243}, {122954, 17495299}, {122955, 16888835}, {122956, 16864003},
2456
  {122957, 16864515}, {122958, 16890883}, {122959, 16883715}, {122960, 17945859},
2457
  {122961, 16866563}, {122962, 16866819}, {122963, 16867075}, {122964, 16867331},
2458
  {122965, 16867587}, {122966, 16867843}, {122967, 16868099}, {122968, 16868355},
2459
  {122969, 16868611}, {122970, 16869123}, {122971, 16869379}, {122972, 16870147},
2460
  {122973, 16870403}, {122974, 16870915}, {122975, 16871427}, {122976, 16871683},
2461
  {122977, 16871939}, {122978, 16872195}, {122979, 16872451}, {122980, 16872707},
2462
  {122981, 16873219}, {122982, 16873475}, {122983, 16879875}, {122984, 16864003},
2463
  {122985, 16863747}, {122986, 16866307}, {122987, 16883203}, {122988, 17490435},
2464
  {122989, 16883971}, {122990, 2}, {123023, 1}, {123024, 2},
2465
  {123136, 1}, {123181, 2}, {123184, 1}, {123198, 2},
2466
  {123200, 1}, {123210, 2}, {123214, 1}, {123216, 2},
2467
  {123536, 1}, {123567, 2}, {123584, 1}, {123642, 2},
2468
  {123647, 1}, {123648, 2}, {124112, 1}, {124154, 2},
2469
  {124896, 1}, {124903, 2}, {124904, 1}, {124908, 2},
2470
  {124909, 1}, {124911, 2}, {124912, 1}, {124927, 2},
2471
  {124928, 1}, {125125, 2}, {125127, 1}, {125143, 2},
2472
  {125184, 17946115}, {125185, 17946371}, {125186, 17946627}, {125187, 17946883},
2473
  {125188, 17947139}, {125189, 17947395}, {125190, 17947651}, {125191, 17947907},
2474
  {125192, 17948163}, {125193, 17948419}, {125194, 17948675}, {125195, 17948931},
2475
  {125196, 17949187}, {125197, 17949443}, {125198, 17949699}, {125199, 17949955},
2476
  {125200, 17950211}, {125201, 17950467}, {125202, 17950723}, {125203, 17950979},
2477
  {125204, 17951235}, {125205, 17951491}, {125206, 17951747}, {125207, 17952003},
2478
  {125208, 17952259}, {125209, 17952515}, {125210, 17952771}, {125211, 17953027},
2479
  {125212, 17953283}, {125213, 17953539}, {125214, 17953795}, {125215, 17954051},
2480
  {125216, 17954307}, {125217, 17954563}, {125218, 1}, {125260, 2},
2481
  {125264, 1}, {125274, 2}, {125278, 1}, {125280, 2},
2482
  {126065, 1}, {126133, 2}, {126209, 1}, {126270, 2},
2483
  {126464, 16910339}, {126465, 17683715}, {126466, 17681923}, {126467, 17834499},
2484
  {126468, 2}, {126469, 16910851}, {126470, 17731587}, {126471, 17682435},
2485
  {126472, 17700099}, {126473, 16911875}, {126474, 17708803}, {126475, 17711107},
2486
  {126476, 17682947}, {126477, 17718019}, {126478, 17694979}, {126479, 17701635},
2487
  {126480, 17703683}, {126481, 17697027}, {126482, 17706755}, {126483, 17725187},
2488
  {126484, 17745155}, {126485, 17686787}, {126486, 17689859}, {126487, 17684995},
2489
  {126488, 17724675}, {126489, 17698051}, {126490, 17701123}, {126491, 17702659},
2490
  {126492, 17954819}, {126493, 17673475}, {126494, 17955075}, {126495, 17955331},
2491
  {126496, 2}, {126497, 17683715}, {126498, 17681923}, {126499, 2},
2492
  {126500, 17721091}, {126501, 2}, {126503, 17682435}, {126504, 2},
2493
  {126505, 16911875}, {126506, 17708803}, {126507, 17711107}, {126508, 17682947},
2494
  {126509, 17718019}, {126510, 17694979}, {126511, 17701635}, {126512, 17703683},
2495
  {126513, 17697027}, {126514, 17706755}, {126515, 2}, {126516, 17745155},
2496
  {126517, 17686787}, {126518, 17689859}, {126519, 17684995}, {126520, 2},
2497
  {126521, 17698051}, {126522, 2}, {126523, 17702659}, {126524, 2},
2498
  {126530, 17681923}, {126531, 2}, {126535, 17682435}, {126536, 2},
2499
  {126537, 16911875}, {126538, 2}, {126539, 17711107}, {126540, 2},
2500
  {126541, 17718019}, {126542, 17694979}, {126543, 17701635}, {126544, 2},
2501
  {126545, 17697027}, {126546, 17706755}, {126547, 2}, {126548, 17745155},
2502
  {126549, 2}, {126551, 17684995}, {126552, 2}, {126553, 17698051},
2503
  {126554, 2}, {126555, 17702659}, {126556, 2}, {126557, 17673475},
2504
  {126558, 2}, {126559, 17955331}, {126560, 2}, {126561, 17683715},
2505
  {126562, 17681923}, {126563, 2}, {126564, 17721091}, {126565, 2},
2506
  {126567, 17682435}, {126568, 17700099}, {126569, 16911875}, {126570, 17708803},
2507
  {126571, 2}, {126572, 17682947}, {126573, 17718019}, {126574, 17694979},
2508
  {126575, 17701635}, {126576, 17703683}, {126577, 17697027}, {126578, 17706755},
2509
  {126579, 2}, {126580, 17745155}, {126581, 17686787}, {126582, 17689859},
2510
  {126583, 17684995}, {126584, 2}, {126585, 17698051}, {126586, 17701123},
2511
  {126587, 17702659}, {126588, 17954819}, {126589, 2}, {126590, 17955075},
2512
  {126591, 2}, {126592, 16910339}, {126593, 17683715}, {126594, 17681923},
2513
  {126595, 17834499}, {126596, 17721091}, {126597, 16910851}, {126598, 17731587},
2514
  {126599, 17682435}, {126600, 17700099}, {126601, 16911875}, {126602, 2},
2515
  {126603, 17711107}, {126604, 17682947}, {126605, 17718019}, {126606, 17694979},
2516
  {126607, 17701635}, {126608, 17703683}, {126609, 17697027}, {126610, 17706755},
2517
  {126611, 17725187}, {126612, 17745155}, {126613, 17686787}, {126614, 17689859},
2518
  {126615, 17684995}, {126616, 17724675}, {126617, 17698051}, {126618, 17701123},
2519
  {126619, 17702659}, {126620, 2}, {126625, 17683715}, {126626, 17681923},
2520
  {126627, 17834499}, {126628, 2}, {126629, 16910851}, {126630, 17731587},
2521
  {126631, 17682435}, {126632, 17700099}, {126633, 16911875}, {126634, 2},
2522
  {126635, 17711107}, {126636, 17682947}, {126637, 17718019}, {126638, 17694979},
2523
  {126639, 17701635}, {126640, 17703683}, {126641, 17697027}, {126642, 17706755},
2524
  {126643, 17725187}, {126644, 17745155}, {126645, 17686787}, {126646, 17689859},
2525
  {126647, 17684995}, {126648, 17724675}, {126649, 17698051}, {126650, 17701123},
2526
  {126651, 17702659}, {126652, 2}, {126704, 1}, {126706, 2},
2527
  {126976, 1}, {127020, 2}, {127024, 1}, {127124, 2},
2528
  {127136, 1}, {127151, 2}, {127153, 1}, {127168, 2},
2529
  {127169, 1}, {127184, 2}, {127185, 1}, {127222, 2},
2530
  {127233, 34732803}, {127234, 34733315}, {127235, 34733827}, {127236, 34734339},
2531
  {127237, 34734851}, {127238, 34735363}, {127239, 34735875}, {127240, 34736387},
2532
  {127241, 34736899}, {127242, 34737411}, {127243, 1}, {127248, 50644995},
2533
  {127249, 50645763}, {127250, 50646531}, {127251, 50647299}, {127252, 50648067},
2534
  {127253, 50648835}, {127254, 50649603}, {127255, 50650371}, {127256, 50651139},
2535
  {127257, 50651907}, {127258, 50652675}, {127259, 50653443}, {127260, 50654211},
2536
  {127261, 50654979}, {127262, 50655747}, {127263, 50656515}, {127264, 50657283},
2537
  {127265, 50658051}, {127266, 50658819}, {127267, 50659587}, {127268, 50660355},
2538
  {127269, 50661123}, {127270, 50661891}, {127271, 50662659}, {127272, 50663427},
2539
  {127273, 50664195}, {127274, 51515139}, {127275, 16777731}, {127276, 16781571},
2540
  {127277, 33554947}, {127278, 34738691}, {127279, 1}, {127280, 16777219},
2541
  {127281, 16777475}, {127282, 16777731}, {127283, 16777987}, {127284, 16778243},
2542
  {127285, 16778499}, {127286, 16778755}, {127287, 16779011}, {127288, 16779267},
2543
  {127289, 16779523}, {127290, 16779779}, {127291, 16780035}, {127292, 16780291},
2544
  {127293, 16780547}, {127294, 16780803}, {127295, 16781059}, {127296, 16781315},
2545
  {127297, 16781571}, {127298, 16781827}, {127299, 16782083}, {127300, 16782339},
2546
  {127301, 16782595}, {127302, 16782851}, {127303, 16783107}, {127304, 16783363},
2547
  {127305, 16783619}, {127306, 34739203}, {127307, 34226691}, {127308, 34739715},
2548
  {127309, 33752579}, {127310, 51517443}, {127311, 34740995}, {127312, 1},
2549
  {127338, 34209539}, {127339, 34189571}, {127340, 34741507}, {127341, 1},
2550
  {127376, 34742019}, {127377, 1}, {127406, 2}, {127462, 1},
2551
  {127488, 34742531}, {127489, 34743043}, {127490, 17307907}, {127491, 2},
2552
  {127504, 17157891}, {127505, 17966339}, {127506, 17966595}, {127507, 17351683},
2553
  {127508, 17143299}, {127509, 17966851}, {127510, 17967107}, {127511, 17225475},
2554
  {127512, 17967363}, {127513, 17967619}, {127514, 17967875}, {127515, 17584643},
2555
  {127516, 17968131}, {127517, 17968387}, {127518, 17968643}, {127519, 17968899},
2556
  {127520, 17969155}, {127521, 17969411}, {127522, 17167107}, {127523, 17969667},
2557
  {127524, 17969923}, {127525, 17970179}, {127526, 17970435}, {127527, 17970691},
2558
  {127528, 17970947}, {127529, 17141763}, {127530, 17223427}, {127531, 17971203},
2559
  {127532, 17288707}, {127533, 17224195}, {127534, 17288963}, {127535, 17971459},
2560
  {127536, 17181443}, {127537, 17971715}, {127538, 17971971}, {127539, 17972227},
2561
  {127540, 17972483}, {127541, 17972739}, {127542, 17264387}, {127543, 17160451},
2562
  {127544, 17972995}, {127545, 17973251}, {127546, 17973507}, {127547, 17973763},
2563
  {127548, 2}, {127552, 51528451}, {127553, 51529219}, {127554, 51529987},
2564
  {127555, 51530755}, {127556, 51531523}, {127557, 51532291}, {127558, 51533059},
2565
  {127559, 51533827}, {127560, 51534595}, {127561, 2}, {127568, 17980931},
2566
  {127569, 17981187}, {127570, 2}, {127584, 1}, {127590, 2},
2567
  {127744, 1}, {128728, 2}, {128732, 1}, {128749, 2},
2568
  {128752, 1}, {128765, 2}, {128768, 1}, {128887, 2},
2569
  {128891, 1}, {128986, 2}, {128992, 1}, {129004, 2},
2570
  {129008, 1}, {129009, 2}, {129024, 1}, {129036, 2},
2571
  {129040, 1}, {129096, 2}, {129104, 1}, {129114, 2},
2572
  {129120, 1}, {129160, 2}, {129168, 1}, {129198, 2},
2573
  {129200, 1}, {129202, 2}, {129280, 1}, {129620, 2},
2574
  {129632, 1}, {129646, 2}, {129648, 1}, {129661, 2},
2575
  {129664, 1}, {129673, 2}, {129680, 1}, {129726, 2},
2576
  {129727, 1}, {129734, 2}, {129742, 1}, {129756, 2},
2577
  {129760, 1}, {129769, 2}, {129776, 1}, {129785, 2},
2578
  {129792, 1}, {129939, 2}, {129940, 1}, {129995, 2},
2579
  {130032, 17035523}, {130033, 16786947}, {130034, 16785155}, {130035, 16785411},
2580
  {130036, 16787715}, {130037, 17035779}, {130038, 17036035}, {130039, 17036291},
2581
  {130040, 17036547}, {130041, 17036803}, {130042, 2}, {131072, 1},
2582
  {173792, 2}, {173824, 1}, {177978, 2}, {177984, 1},
2583
  {178206, 2}, {178208, 1}, {183970, 2}, {183984, 1},
2584
  {191457, 2}, {194560, 17981443}, {194561, 17981699}, {194562, 17981955},
2585
  {194563, 17982211}, {194564, 17982467}, {194565, 17608451}, {194566, 17982723},
2586
  {194567, 17982979}, {194568, 17983235}, {194569, 17983491}, {194570, 17608707},
2587
  {194571, 17983747}, {194572, 17984003}, {194573, 17984259}, {194574, 17608963},
2588
  {194575, 17984515}, {194576, 17984771}, {194577, 17985027}, {194578, 17985283},
2589
  {194579, 17985539}, {194580, 17985795}, {194581, 17968643}, {194582, 17986051},
2590
  {194583, 17986307}, {194584, 17986563}, {194585, 17986819}, {194586, 17987075},
2591
  {194587, 17623043}, {194588, 17987331}, {194589, 17145859}, {194590, 17987587},
2592
  {194591, 17987843}, {194592, 17988099}, {194593, 17988355}, {194594, 17973251},
2593
  {194595, 17988611}, {194596, 17988867}, {194597, 17624323}, {194598, 17609219},
2594
  {194599, 17609475}, {194600, 17624579}, {194601, 17989123}, {194602, 17989379},
2595
  {194603, 17562883}, {194604, 17989635}, {194605, 17609731}, {194606, 17989891},
2596
  {194607, 17990147}, {194608, 17990403}, {194609, 17990659}, {194612, 17990915},
2597
  {194613, 17991171}, {194614, 17991427}, {194615, 17991683}, {194616, 17991939},
2598
  {194617, 17992195}, {194618, 17992451}, {194619, 17992707}, {194620, 17992963},
2599
  {194621, 17993219}, {194622, 17993475}, {194623, 17993731}, {194624, 17993987},
2600
  {194625, 17994243}, {194626, 17994499}, {194627, 17994755}, {194628, 17995011},
2601
  {194629, 17995267}, {194631, 17625091}, {194632, 17995523}, {194633, 17995779},
2602
  {194634, 17996035}, {194635, 17996291}, {194636, 17610243}, {194637, 17996547},
2603
  {194638, 17996803}, {194639, 17997059}, {194640, 17600003}, {194641, 17997315},
2604
  {194642, 17997571}, {194643, 17997827}, {194644, 17998083}, {194645, 17998339},
2605
  {194646, 17998595}, {194647, 17998851}, {194648, 17999107}, {194649, 17999363},
2606
  {194650, 17999619}, {194651, 17999875}, {194652, 18000131}, {194653, 17966851},
2607
  {194654, 18000387}, {194655, 18000643}, {194656, 18000899}, {194657, 18001155},
2608
  {194658, 18001411}, {194659, 18001667}, {194660, 18001923}, {194661, 18002179},
2609
  {194662, 18002435}, {194663, 18002691}, {194664, 2}, {194665, 18002947},
2610
  {194666, 18003203}, {194668, 18003459}, {194669, 18003715}, {194670, 18003971},
2611
  {194671, 17561859}, {194672, 18004227}, {194673, 18004483}, {194674, 18004739},
2612
  {194675, 18004995}, {194676, 2}, {194677, 17152515}, {194678, 18005251},
2613
  {194679, 18005507}, {194680, 17153027}, {194681, 18005763}, {194682, 18006019},
2614
  {194683, 18006275}, {194684, 18006531}, {194685, 18006787}, {194686, 18007043},
2615
  {194687, 18007299}, {194688, 18007555}, {194689, 18007811}, {194690, 18008067},
2616
  {194691, 18008323}, {194692, 18008579}, {194693, 18008835}, {194694, 18009091},
2617
  {194695, 18009347}, {194696, 18009603}, {194697, 18009859}, {194698, 18010115},
2618
  {194699, 18010371}, {194700, 18010627}, {194701, 18010883}, {194702, 17548547},
2619
  {194703, 18011139}, {194704, 17155587}, {194705, 18011395}, {194707, 18011651},
2620
  {194708, 18011907}, {194710, 18012163}, {194711, 18012419}, {194712, 18012675},
2621
  {194713, 18012931}, {194714, 18013187}, {194715, 18013443}, {194716, 18013699},
2622
  {194717, 18013955}, {194718, 18014211}, {194719, 18014467}, {194720, 18014723},
2623
  {194721, 18014979}, {194722, 18015235}, {194723, 17611523}, {194724, 18015491},
2624
  {194725, 18015747}, {194726, 18016003}, {194727, 18016259}, {194728, 17628163},
2625
  {194729, 18016259}, {194730, 18016515}, {194731, 17612035}, {194732, 18016771},
2626
  {194733, 18017027}, {194734, 18017283}, {194735, 18017539}, {194736, 17612291},
2627
  {194737, 17541635}, {194738, 17414915}, {194739, 18017795}, {194740, 18018051},
2628
  {194741, 18018307}, {194742, 18018563}, {194743, 18018819}, {194744, 18019075},
2629
  {194745, 18019331}, {194746, 18019587}, {194747, 18019843}, {194748, 18020099},
2630
  {194749, 18020355}, {194750, 18020611}, {194751, 18020867}, {194752, 18021123},
2631
  {194753, 18021379}, {194754, 18021635}, {194755, 18021891}, {194756, 18022147},
2632
  {194757, 18022403}, {194758, 18022659}, {194759, 18022915}, {194760, 17612547},
2633
  {194761, 18023171}, {194762, 18023427}, {194763, 18023683}, {194764, 18023939},
2634
  {194765, 18024195}, {194766, 18024451}, {194767, 17613059}, {194768, 18024707},
2635
  {194769, 18024963}, {194770, 18025219}, {194771, 18025475}, {194772, 18025731},
2636
  {194773, 18025987}, {194774, 18026243}, {194775, 18026499}, {194776, 17548803},
2637
  {194777, 17630211}, {194778, 18026755}, {194779, 18027011}, {194780, 18027267},
2638
  {194781, 18027523}, {194782, 18027779}, {194783, 18028035}, {194784, 18028291},
2639
  {194785, 18028547}, {194786, 17613315}, {194787, 18028803}, {194788, 18029059},
2640
  {194789, 18029315}, {194790, 18029571}, {194791, 17640963}, {194792, 18029827},
2641
  {194793, 18030083}, {194794, 18030339}, {194795, 18030595}, {194796, 18030851},
2642
  {194797, 18031107}, {194798, 18031363}, {194799, 18031619}, {194800, 18031875},
2643
  {194801, 18032131}, {194802, 18032387}, {194803, 18032643}, {194804, 18032899},
2644
  {194805, 17566211}, {194806, 18033155}, {194807, 18033411}, {194808, 18033667},
2645
  {194809, 18033923}, {194810, 18034179}, {194811, 18034435}, {194812, 18034691},
2646
  {194813, 18034947}, {194814, 18035203}, {194815, 18035459}, {194816, 18035715},
2647
  {194817, 17613571}, {194818, 17587203}, {194819, 18035971}, {194820, 18036227},
2648
  {194821, 18036483}, {194822, 18036739}, {194823, 18036995}, {194824, 18037251},
2649
  {194825, 18037507}, {194826, 18037763}, {194827, 17630979}, {194828, 18038019},
2650
  {194829, 18038275}, {194830, 18038531}, {194831, 18038787}, {194832, 18039043},
2651
  {194833, 18039299}, {194834, 18039555}, {194835, 18039811}, {194836, 17631235},
2652
  {194837, 18040067}, {194838, 18040323}, {194839, 18040579}, {194840, 18040835},
2653
  {194841, 18041091}, {194842, 18041347}, {194843, 18041603}, {194844, 18041859},
2654
  {194845, 18042115}, {194846, 18042371}, {194847, 2}, {194848, 18042627},
2655
  {194849, 17631747}, {194850, 18042883}, {194851, 18043139}, {194852, 18043395},
2656
  {194853, 18043651}, {194854, 18043907}, {194855, 18044163}, {194856, 18044419},
2657
  {194857, 18044675}, {194858, 18044931}, {194859, 18045187}, {194860, 18045443},
2658
  {194862, 18045699}, {194863, 18045955}, {194864, 17632259}, {194865, 18046211},
2659
  {194866, 18046467}, {194867, 18046723}, {194868, 18046979}, {194869, 18047235},
2660
  {194870, 18047491}, {194871, 18047747}, {194872, 17562627}, {194873, 18048003},
2661
  {194874, 18048259}, {194875, 18048515}, {194876, 18048771}, {194877, 18049027},
2662
  {194878, 18049283}, {194879, 18049539}, {194880, 17633795}, {194881, 18049795},
2663
  {194882, 18050051}, {194883, 18050307}, {194884, 18050563}, {194885, 18050819},
2664
  {194886, 18051075}, {194888, 17634051}, {194889, 17641475}, {194890, 18051331},
2665
  {194891, 18051587}, {194892, 18051843}, {194893, 18052099}, {194894, 18052355},
2666
  {194895, 17553155}, {194896, 17634563}, {194897, 18052611}, {194898, 18052867},
2667
  {194899, 17616131}, {194900, 18053123}, {194901, 18053379}, {194902, 17605123},
2668
  {194903, 18053635}, {194904, 18053891}, {194905, 17616899}, {194906, 18054147},
2669
  {194907, 18054403}, {194908, 18054659}, {194909, 18054915}, {194911, 2},
2670
  {194912, 18055171}, {194913, 18055427}, {194914, 18055683}, {194915, 18055939},
2671
  {194916, 18056195}, {194917, 18056451}, {194918, 18056707}, {194919, 18056963},
2672
  {194920, 18057219}, {194921, 18057475}, {194922, 18057731}, {194923, 18057987},
2673
  {194924, 18058243}, {194925, 18058499}, {194926, 18058755}, {194927, 18059011},
2674
  {194928, 18059267}, {194929, 18059523}, {194930, 18059779}, {194931, 18060035},
2675
  {194932, 18060291}, {194933, 18060547}, {194934, 18060803}, {194935, 18061059},
2676
  {194936, 18061315}, {194937, 18061571}, {194938, 17618435}, {194939, 18061827},
2677
  {194940, 18062083}, {194941, 18062339}, {194942, 18062595}, {194943, 18062851},
2678
  {194944, 18063107}, {194945, 18063363}, {194946, 18063619}, {194947, 18063875},
2679
  {194948, 18064131}, {194949, 18064387}, {194950, 18064643}, {194951, 18064899},
2680
  {194952, 18065155}, {194953, 18065411}, {194954, 18065667}, {194955, 18011651},
2681
  {194956, 18065923}, {194957, 18066179}, {194958, 18066435}, {194959, 18066691},
2682
  {194960, 18066947}, {194961, 18067203}, {194962, 18067459}, {194963, 18067715},
2683
  {194964, 18067971}, {194965, 18068227}, {194966, 18068483}, {194967, 18068739},
2684
  {194968, 17566979}, {194969, 18068995}, {194970, 18069251}, {194971, 18069507},
2685
  {194972, 18069763}, {194973, 18070019}, {194974, 18070275}, {194975, 17619203},
2686
  {194976, 18070531}, {194977, 18070787}, {194978, 18071043}, {194979, 18071299},
2687
  {194980, 18071555}, {194981, 18071811}, {194982, 18072067}, {194983, 18072323},
2688
  {194984, 18072579}, {194985, 18072835}, {194986, 18073091}, {194987, 18073347},
2689
  {194988, 18073603}, {194989, 18073859}, {194990, 18074115}, {194991, 18074371},
2690
  {194992, 18074627}, {194993, 18074883}, {194994, 18075139}, {194995, 18075395},
2691
  {194996, 17551875}, {194997, 18075651}, {194998, 18075907}, {194999, 18076163},
2692
  {195000, 18076419}, {195001, 18076675}, {195002, 18076931}, {195003, 17636355},
2693
  {195004, 18077187}, {195005, 18077443}, {195006, 18077699}, {195007, 2},
2694
  {195008, 18077955}, {195009, 18078211}, {195010, 18078467}, {195011, 18078723},
2695
  {195012, 17178627}, {195013, 18078979}, {195014, 18079235}, {195015, 18079491},
2696
  {195016, 18079747}, {195017, 18080003}, {195018, 18080259}, {195019, 18080515},
2697
  {195020, 18080771}, {195021, 18081027}, {195022, 18081283}, {195023, 18081539},
2698
  {195024, 17637635}, {195025, 17637891}, {195026, 17180419}, {195027, 18081795},
2699
  {195028, 18082051}, {195029, 18082307}, {195030, 18082563}, {195031, 18082819},
2700
  {195032, 18083075}, {195033, 18083331}, {195034, 18083587}, {195035, 18083843},
2701
  {195036, 18084099}, {195037, 18084355}, {195038, 18084611}, {195039, 17638147},
2702
  {195040, 18084867}, {195041, 18085123}, {195042, 18085379}, {195043, 18085635},
2703
  {195044, 18085891}, {195045, 18086147}, {195046, 18086403}, {195047, 18086659},
2704
  {195048, 18086915}, {195049, 18087171}, {195050, 18087427}, {195051, 18087683},
2705
  {195052, 18087939}, {195053, 18088195}, {195054, 18088451}, {195055, 18088707},
2706
  {195056, 18088963}, {195057, 18089219}, {195058, 18089475}, {195059, 18089731},
2707
  {195060, 18089987}, {195061, 18090243}, {195062, 18090499}, {195063, 18090755},
2708
  {195064, 18091011}, {195065, 18091267}, {195066, 18091523}, {195067, 18091779},
2709
  {195068, 18092035}, {195069, 18092291}, {195070, 17639683}, {195072, 18092547},
2710
  {195073, 18092803}, {195074, 18093059}, {195075, 18093315}, {195076, 18093571},
2711
  {195077, 18093827}, {195078, 18094083}, {195079, 18094339}, {195080, 18094595},
2712
  {195081, 18094851}, {195082, 17639939}, {195083, 18095107}, {195084, 18095363},
2713
  {195085, 18095619}, {195086, 18095875}, {195087, 18096131}, {195088, 18096387},
2714
  {195089, 18096643}, {195090, 18096899}, {195091, 18097155}, {195092, 18097411},
2715
  {195093, 17192707}, {195094, 18097667}, {195095, 17193731}, {195096, 18097923},
2716
  {195097, 18098179}, {195098, 18098435}, {195099, 18098691}, {195100, 17195011},
2717
  {195101, 18098947}, {195102, 2}, {196608, 1}, {201547, 2},
2718
  {201552, 1}, {205744, 2}, {917760, 0}, {918000, 2}
2719
};
2720
2721
2722
} // namespace ada::idna
2723
#endif // ADA_IDNA_TABLES_H
2724
2725
/* end file src/mapping_tables.cpp */
2726
2727
namespace ada::idna {
2728
2729
// This can be greatly accelerated. For now we just use a simply
2730
// binary search. In practice, you should *not* do that.
2731
183k
uint32_t find_range_index(uint32_t key) {
2732
  ////////////////
2733
  // This could be implemented with std::lower_bound, but we roll our own
2734
  // because we want to allow further optimizations in the future.
2735
  ////////////////
2736
183k
  uint32_t len = std::size(table);
2737
183k
  uint32_t low = 0;
2738
183k
  uint32_t high = len - 1;
2739
2.44M
  while (low <= high) {
2740
2.31M
    uint32_t middle_index = (low + high) >> 1;  // cannot overflow
2741
2.31M
    uint32_t middle_value = table[middle_index][0];
2742
2.31M
    if (middle_value < key) {
2743
646k
      low = middle_index + 1;
2744
1.67M
    } else if (middle_value > key) {
2745
1.61M
      high = middle_index - 1;
2746
1.61M
    } else {
2747
52.4k
      return middle_index;  // perfect match
2748
52.4k
    }
2749
2.31M
  }
2750
130k
  return low == 0 ? 0 : low - 1;
2751
183k
}
2752
2753
0
bool ascii_has_upper_case(char* input, size_t length) {
2754
0
  auto broadcast = [](uint8_t v) -> uint64_t {
2755
0
    return 0x101010101010101ull * v;
2756
0
  };
2757
0
  uint64_t broadcast_80 = broadcast(0x80);
2758
0
  uint64_t broadcast_Ap = broadcast(128 - 'A');
2759
0
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2760
0
  size_t i = 0;
2761
2762
0
  uint64_t runner{0};
2763
2764
0
  for (; i + 7 < length; i += 8) {
2765
0
    uint64_t word{};
2766
0
    memcpy(&word, input + i, sizeof(word));
2767
0
    runner |= (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80);
2768
0
  }
2769
0
  if (i < length) {
2770
0
    uint64_t word{};
2771
0
    memcpy(&word, input + i, length - i);
2772
0
    runner |= (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80);
2773
0
  }
2774
0
  return runner != 0;
2775
0
}
2776
2777
15.0k
void ascii_map(char* input, size_t length) {
2778
45.2k
  auto broadcast = [](uint8_t v) -> uint64_t {
2779
45.2k
    return 0x101010101010101ull * v;
2780
45.2k
  };
2781
15.0k
  uint64_t broadcast_80 = broadcast(0x80);
2782
15.0k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
2783
15.0k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2784
15.0k
  size_t i = 0;
2785
2786
40.9k
  for (; i + 7 < length; i += 8) {
2787
25.9k
    uint64_t word{};
2788
25.9k
    memcpy(&word, input + i, sizeof(word));
2789
25.9k
    word ^=
2790
25.9k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2791
25.9k
    memcpy(input + i, &word, sizeof(word));
2792
25.9k
  }
2793
15.0k
  if (i < length) {
2794
13.1k
    uint64_t word{};
2795
13.1k
    memcpy(&word, input + i, length - i);
2796
13.1k
    word ^=
2797
13.1k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2798
13.1k
    memcpy(input + i, &word, length - i);
2799
13.1k
  }
2800
15.0k
}
2801
2802
// Map the characters according to IDNA, returning the empty string on error.
2803
16.5k
std::u32string map(std::u32string_view input) {
2804
  //  [Map](https://www.unicode.org/reports/tr46/#ProcessingStepMap).
2805
  //  For each code point in the domain_name string, look up the status
2806
  //  value in Section 5, [IDNA Mapping
2807
  //  Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table),
2808
  //  and take the following actions:
2809
  //    * disallowed: Leave the code point unchanged in the string, and
2810
  //    record that there was an error.
2811
  //    * ignored: Remove the code point from the string. This is
2812
  //    equivalent to mapping the code point to an empty string.
2813
  //    * mapped: Replace the code point in the string by the value for
2814
  //    the mapping in Section 5, [IDNA Mapping
2815
  //    Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table).
2816
  //    * valid: Leave the code point unchanged in the string.
2817
16.5k
  static std::u32string error = U"";
2818
16.5k
  std::u32string answer;
2819
16.5k
  answer.reserve(input.size());
2820
183k
  for (char32_t x : input) {
2821
183k
    size_t index = find_range_index(x);
2822
183k
    uint32_t descriptor = table[index][1];
2823
183k
    uint8_t code = uint8_t(descriptor);
2824
183k
    switch (code) {
2825
218
      case 0:
2826
218
        break;  // nothing to do, ignored
2827
138k
      case 1:
2828
138k
        answer.push_back(x);  // valid, we just copy it to output
2829
138k
        break;
2830
393
      case 2:
2831
393
        return error;  // disallowed
2832
0
        break;
2833
2834
      // case 3 :
2835
44.5k
      default:
2836
        // We have a mapping
2837
44.5k
        {
2838
44.5k
          size_t char_count = (descriptor >> 24);
2839
44.5k
          uint16_t char_index = uint16_t(descriptor >> 8);
2840
252k
          for (size_t idx = char_index; idx < char_index + char_count; idx++) {
2841
208k
            answer.push_back(mappings[idx]);
2842
208k
          }
2843
44.5k
        }
2844
183k
    }
2845
183k
  }
2846
16.1k
  return answer;
2847
16.5k
}
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.composition_count/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.0k
    const std::u32string_view input) noexcept {
7767
16.0k
  bool decomposition_needed{false};
7768
16.0k
  size_t additional_elements{0};
7769
318k
  for (char32_t current_character : input) {
7770
318k
    size_t decomposition_length{0};
7771
7772
318k
    if (current_character >= hangul_sbase &&
7773
318k
        current_character < hangul_sbase + hangul_scount) {
7774
4.81k
      decomposition_length = 2;
7775
4.81k
      if ((current_character - hangul_sbase) % hangul_tcount) {
7776
2.92k
        decomposition_length = 3;
7777
2.92k
      }
7778
313k
    } else if (current_character < 0x110000) {
7779
313k
      const uint8_t di = decomposition_index[current_character >> 8];
7780
313k
      const uint16_t* const decomposition =
7781
313k
          decomposition_block[di] + (current_character % 256);
7782
313k
      decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
7783
313k
      if ((decomposition_length > 0) && (decomposition[0] & 1)) {
7784
0
        decomposition_length = 0;
7785
0
      }
7786
313k
    }
7787
318k
    if (decomposition_length != 0) {
7788
11.1k
      decomposition_needed = true;
7789
11.1k
      additional_elements += decomposition_length - 1;
7790
11.1k
    }
7791
318k
  }
7792
16.0k
  return {decomposition_needed, additional_elements};
7793
16.0k
}
7794
7795
4.17k
void decompose(std::u32string& input, size_t additional_elements) {
7796
4.17k
  input.resize(input.size() + additional_elements);
7797
4.17k
  for (size_t descending_idx = input.size(),
7798
4.17k
              input_count = descending_idx - additional_elements;
7799
78.1k
       input_count--;) {
7800
74.0k
    if (input[input_count] >= hangul_sbase &&
7801
74.0k
        input[input_count] < hangul_sbase + hangul_scount) {
7802
      // Hangul decomposition.
7803
4.81k
      char32_t s_index = input[input_count] - hangul_sbase;
7804
4.81k
      if (s_index % hangul_tcount != 0) {
7805
2.92k
        input[--descending_idx] = hangul_tbase + s_index % hangul_tcount;
7806
2.92k
      }
7807
4.81k
      input[--descending_idx] =
7808
4.81k
          hangul_vbase + (s_index % hangul_ncount) / hangul_tcount;
7809
4.81k
      input[--descending_idx] = hangul_lbase + s_index / hangul_ncount;
7810
69.1k
    } else if (input[input_count] < 0x110000) {
7811
      // Check decomposition_data.
7812
69.1k
      const uint16_t* decomposition =
7813
69.1k
          decomposition_block[decomposition_index[input[input_count] >> 8]] +
7814
69.1k
          (input[input_count] % 256);
7815
69.1k
      uint16_t decomposition_length =
7816
69.1k
          (decomposition[1] >> 2) - (decomposition[0] >> 2);
7817
69.1k
      if (decomposition_length > 0 && (decomposition[0] & 1)) {
7818
0
        decomposition_length = 0;
7819
0
      }
7820
69.1k
      if (decomposition_length > 0) {
7821
        // Non-recursive decomposition.
7822
20.2k
        while (decomposition_length-- > 0) {
7823
13.9k
          input[--descending_idx] = decomposition_data[(decomposition[0] >> 2) +
7824
13.9k
                                                       decomposition_length];
7825
13.9k
        }
7826
62.8k
      } else {
7827
        // No decomposition.
7828
62.8k
        input[--descending_idx] = input[input_count];
7829
62.8k
      }
7830
69.1k
    } else {
7831
      // Non-Unicode character.
7832
0
      input[--descending_idx] = input[input_count];
7833
0
    }
7834
74.0k
  }
7835
4.17k
}
7836
7837
636k
uint8_t get_ccc(char32_t c) noexcept {
7838
636k
  return c < 0x110000 ? canonical_combining_class_block
7839
636k
                            [canonical_combining_class_index[c >> 8]][c % 256]
7840
636k
                      : 0;
7841
636k
}
7842
7843
16.0k
void sort_marks(std::u32string& input) {
7844
334k
  for (size_t idx = 1; idx < input.size(); idx++) {
7845
318k
    uint8_t ccc = get_ccc(input[idx]);
7846
318k
    if (ccc == 0) {
7847
306k
      continue;
7848
306k
    }  // Skip non-combining characters.
7849
11.7k
    auto current_character = input[idx];
7850
11.7k
    size_t back_idx = idx;
7851
12.8k
    while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) {
7852
1.06k
      input[back_idx] = input[back_idx - 1];
7853
1.06k
      back_idx--;
7854
1.06k
    }
7855
11.7k
    input[back_idx] = current_character;
7856
11.7k
  }
7857
16.0k
}
7858
7859
16.0k
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.0k
  auto [decomposition_needed, additional_elements] =
7865
16.0k
      compute_decomposition_length(input);
7866
16.0k
  if (decomposition_needed) {
7867
4.17k
    decompose(input, additional_elements);
7868
4.17k
  }
7869
16.0k
  sort_marks(input);
7870
16.0k
}
7871
7872
16.0k
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.0k
  size_t input_count{0};
7878
16.0k
  size_t composition_count{0};
7879
330k
  for (; input_count < input.size(); input_count++, composition_count++) {
7880
314k
    input[composition_count] = input[input_count];
7881
314k
    if (input[input_count] >= hangul_lbase &&
7882
314k
        input[input_count] < hangul_lbase + hangul_lcount) {
7883
6.16k
      if (input_count + 1 < input.size() &&
7884
6.16k
          input[input_count + 1] >= hangul_vbase &&
7885
6.16k
          input[input_count + 1] < hangul_vbase + hangul_vcount) {
7886
4.81k
        input[composition_count] =
7887
4.81k
            hangul_sbase +
7888
4.81k
            ((input[input_count] - hangul_lbase) * hangul_vcount +
7889
4.81k
             input[input_count + 1] - hangul_vbase) *
7890
4.81k
                hangul_tcount;
7891
4.81k
        input_count++;
7892
4.81k
        if (input_count + 1 < input.size() &&
7893
4.81k
            input[input_count + 1] > hangul_tbase &&
7894
4.81k
            input[input_count + 1] < hangul_tbase + hangul_tcount) {
7895
2.92k
          input[composition_count] += input[++input_count] - hangul_tbase;
7896
2.92k
        }
7897
4.81k
      }
7898
308k
    } else if (input[input_count] >= hangul_sbase &&
7899
308k
               input[input_count] < hangul_sbase + hangul_scount) {
7900
0
      if ((input[input_count] - hangul_sbase) % hangul_tcount &&
7901
0
          input_count + 1 < input.size() &&
7902
0
          input[input_count + 1] > hangul_tbase &&
7903
0
          input[input_count + 1] < hangul_tbase + hangul_tcount) {
7904
0
        input[composition_count] += input[++input_count] - hangul_tbase;
7905
0
      }
7906
308k
    } else if (input[input_count] < 0x110000) {
7907
308k
      const uint16_t* composition =
7908
308k
          &composition_block[composition_index[input[input_count] >> 8]]
7909
308k
                            [input[input_count] % 256];
7910
308k
      size_t initial_composition_count = composition_count;
7911
319k
      for (int32_t previous_ccc = -1; input_count + 1 < input.size();
7912
308k
           input_count++) {
7913
305k
        uint8_t ccc = get_ccc(input[input_count + 1]);
7914
7915
305k
        if (composition[1] != composition[0] && previous_ccc < ccc) {
7916
          // Try finding a composition.
7917
62.1k
          uint16_t left = composition[0];
7918
62.1k
          uint16_t right = composition[1];
7919
149k
          while (left + 2 < right) {
7920
            // mean without overflow
7921
87.2k
            uint16_t middle = left + (((right - left) >> 1) & ~1);
7922
87.2k
            if (composition_data[middle] <= input[input_count + 1]) {
7923
12.8k
              left = middle;
7924
12.8k
            }
7925
87.2k
            if (composition_data[middle] >= input[input_count + 1]) {
7926
78.4k
              right = middle;
7927
78.4k
            }
7928
87.2k
          }
7929
62.1k
          if (composition_data[left] == input[input_count + 1]) {
7930
7.60k
            input[initial_composition_count] = composition_data[left + 1];
7931
7.60k
            composition =
7932
7.60k
                &composition_block
7933
7.60k
                    [composition_index[composition_data[left + 1] >> 8]]
7934
7.60k
                    [composition_data[left + 1] % 256];
7935
7.60k
            continue;
7936
7.60k
          }
7937
62.1k
        }
7938
7939
298k
        if (ccc == 0) {
7940
293k
          break;
7941
293k
        }  // Not a combining character.
7942
4.35k
        previous_ccc = ccc;
7943
4.35k
        input[++composition_count] = input[input_count + 1];
7944
4.35k
      }
7945
308k
    }
7946
314k
  }
7947
7948
16.0k
  if (composition_count < input_count) {
7949
4.19k
    input.resize(composition_count);
7950
4.19k
  }
7951
16.0k
}
7952
7953
16.0k
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.0k
  decompose_nfc(input);
7959
16.0k
  compose(input);
7960
16.0k
}
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
93.7k
static constexpr int32_t char_to_digit_value(char value) {
7979
93.7k
  if (value >= 'a' && value <= 'z') return value - 'a';
7980
24.8k
  if (value >= '0' && value <= '9') return value - '0' + 26;
7981
765
  return -1;
7982
24.8k
}
7983
7984
336k
static constexpr char digit_to_char(int32_t digit) {
7985
336k
  return digit < 26 ? char(digit + 97) : char(digit + 22);
7986
336k
}
7987
7988
175k
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
7989
175k
  if (firsttime) {
7990
33.8k
    d = d / damp;
7991
141k
  } else {
7992
141k
    d = d / 2;
7993
141k
  }
7994
175k
  d += d / n;
7995
175k
  int32_t k = 0;
7996
247k
  while (d > ((base - tmin) * tmax) / 2) {
7997
72.0k
    d /= base - tmin;
7998
72.0k
    k += base;
7999
72.0k
  }
8000
175k
  return k + (((base - tmin + 1) * d) / (d + skew));
8001
175k
}
8002
8003
11.4k
bool punycode_to_utf32(std::string_view input, std::u32string &out) {
8004
11.4k
  int32_t written_out{0};
8005
11.4k
  out.reserve(out.size() + input.size());
8006
11.4k
  uint32_t n = initial_n;
8007
11.4k
  int32_t i = 0;
8008
11.4k
  int32_t bias = initial_bias;
8009
  // grab ascii content
8010
11.4k
  size_t end_of_ascii = input.find_last_of('-');
8011
11.4k
  if (end_of_ascii != std::string_view::npos) {
8012
14.4k
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8013
14.4k
      if (c >= 0x80) {
8014
0
        return false;
8015
0
      }
8016
14.4k
      out.push_back(c);
8017
14.4k
      written_out++;
8018
14.4k
    }
8019
3.96k
    input.remove_prefix(end_of_ascii + 1);
8020
3.96k
  }
8021
50.2k
  while (!input.empty()) {
8022
39.0k
    int32_t oldi = i;
8023
39.0k
    int32_t w = 1;
8024
83.5k
    for (int32_t k = base;; k += base) {
8025
83.5k
      if (input.empty()) {
8026
112
        return false;
8027
112
      }
8028
83.4k
      uint8_t code_point = input.front();
8029
83.4k
      input.remove_prefix(1);
8030
83.4k
      int32_t digit = char_to_digit_value(code_point);
8031
83.4k
      if (digit < 0) {
8032
102
        return false;
8033
102
      }
8034
83.3k
      if (digit > (0x7fffffff - i) / w) {
8035
25
        return false;
8036
25
      }
8037
83.2k
      i = i + digit * w;
8038
83.2k
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8039
83.2k
      if (digit < t) {
8040
38.8k
        break;
8041
38.8k
      }
8042
44.4k
      if (w > 0x7fffffff / (base - t)) {
8043
0
        return false;
8044
0
      }
8045
44.4k
      w = w * (base - t);
8046
44.4k
    }
8047
38.8k
    bias = adapt(i - oldi, written_out + 1, oldi == 0);
8048
38.8k
    if (i / (written_out + 1) > int32_t(0x7fffffff - n)) {
8049
38
      return false;
8050
38
    }
8051
38.7k
    n = n + i / (written_out + 1);
8052
38.7k
    i = i % (written_out + 1);
8053
38.7k
    if (n < 0x80) {
8054
0
      return false;
8055
0
    }
8056
38.7k
    out.insert(out.begin() + i, n);
8057
38.7k
    written_out++;
8058
38.7k
    ++i;
8059
38.7k
  }
8060
8061
11.2k
  return true;
8062
11.4k
}
8063
8064
2.32k
bool verify_punycode(std::string_view input) {
8065
2.32k
  size_t written_out{0};
8066
2.32k
  uint32_t n = initial_n;
8067
2.32k
  int32_t i = 0;
8068
2.32k
  int32_t bias = initial_bias;
8069
  // grab ascii content
8070
2.32k
  size_t end_of_ascii = input.find_last_of('-');
8071
2.32k
  if (end_of_ascii != std::string_view::npos) {
8072
2.15k
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8073
2.15k
      if (c >= 0x80) {
8074
0
        return false;
8075
0
      }
8076
2.15k
      written_out++;
8077
2.15k
    }
8078
650
    input.remove_prefix(end_of_ascii + 1);
8079
650
  }
8080
6.73k
  while (!input.empty()) {
8081
5.30k
    int32_t oldi = i;
8082
5.30k
    int32_t w = 1;
8083
10.4k
    for (int32_t k = base;; k += base) {
8084
10.4k
      if (input.empty()) {
8085
128
        return false;
8086
128
      }
8087
10.3k
      uint8_t code_point = input.front();
8088
10.3k
      input.remove_prefix(1);
8089
10.3k
      int32_t digit = char_to_digit_value(code_point);
8090
10.3k
      if (digit < 0) {
8091
663
        return false;
8092
663
      }
8093
9.65k
      if (digit > (0x7fffffff - i) / w) {
8094
44
        return false;
8095
44
      }
8096
9.61k
      i = i + digit * w;
8097
9.61k
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8098
9.61k
      if (digit < t) {
8099
4.46k
        break;
8100
4.46k
      }
8101
5.14k
      if (w > 0x7fffffff / (base - t)) {
8102
0
        return false;
8103
0
      }
8104
5.14k
      w = w * (base - t);
8105
5.14k
    }
8106
4.46k
    bias = adapt(i - oldi, int32_t(written_out + 1), oldi == 0);
8107
4.46k
    if (i / (written_out + 1) > 0x7fffffff - n) {
8108
57
      return false;
8109
57
    }
8110
4.41k
    n = n + i / int32_t(written_out + 1);
8111
4.41k
    i = i % int32_t(written_out + 1);
8112
4.41k
    if (n < 0x80) {
8113
0
      return false;
8114
0
    }
8115
4.41k
    written_out++;
8116
4.41k
    ++i;
8117
4.41k
  }
8118
8119
1.43k
  return true;
8120
2.32k
}
8121
8122
24.4k
bool utf32_to_punycode(std::u32string_view input, std::string &out) {
8123
24.4k
  out.reserve(input.size() + out.size());
8124
24.4k
  uint32_t n = initial_n;
8125
24.4k
  int32_t d = 0;
8126
24.4k
  int32_t bias = initial_bias;
8127
24.4k
  size_t h = 0;
8128
  // first push the ascii content
8129
169k
  for (uint32_t c : input) {
8130
169k
    if (c < 0x80) {
8131
37.5k
      ++h;
8132
37.5k
      out.push_back(char(c));
8133
37.5k
    }
8134
169k
    if (c > 0x10ffff || (c >= 0xd880 && c < 0xe000)) {
8135
0
      return false;
8136
0
    }
8137
169k
  }
8138
24.4k
  size_t b = h;
8139
24.4k
  if (b > 0) {
8140
7.16k
    out.push_back('-');
8141
7.16k
  }
8142
109k
  while (h < input.size()) {
8143
84.6k
    uint32_t m = 0x10FFFF;
8144
1.30M
    for (auto code_point : input) {
8145
1.30M
      if (code_point >= n && code_point < m) m = code_point;
8146
1.30M
    }
8147
8148
84.6k
    if ((m - n) > (0x7fffffff - d) / (h + 1)) {
8149
0
      return false;
8150
0
    }
8151
84.6k
    d = d + int32_t((m - n) * (h + 1));
8152
84.6k
    n = m;
8153
1.30M
    for (auto c : input) {
8154
1.30M
      if (c < n) {
8155
781k
        if (d == 0x7fffffff) {
8156
0
          return false;
8157
0
        }
8158
781k
        ++d;
8159
781k
      }
8160
1.30M
      if (c == n) {
8161
132k
        int32_t q = d;
8162
336k
        for (int32_t k = base;; k += base) {
8163
336k
          int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8164
8165
336k
          if (q < t) {
8166
132k
            break;
8167
132k
          }
8168
204k
          out.push_back(digit_to_char(t + ((q - t) % (base - t))));
8169
204k
          q = (q - t) / (base - t);
8170
204k
        }
8171
132k
        out.push_back(digit_to_char(q));
8172
132k
        bias = adapt(d, int32_t(h + 1), h == b);
8173
132k
        d = 0;
8174
132k
        ++h;
8175
132k
      }
8176
1.30M
    }
8177
84.6k
    ++d;
8178
84.6k
    ++n;
8179
84.6k
  }
8180
24.4k
  return true;
8181
24.4k
}
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
230k
inline static direction find_direction(uint32_t code_point) noexcept {
8954
230k
  auto it = std::lower_bound(
8955
230k
      std::begin(dir_table), std::end(dir_table), code_point,
8956
2.36M
      [](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
230k
  if (it == std::end(dir_table)) {
8960
0
    return direction::NONE;
8961
0
  }
8962
  // We have that d.final_code >= c.
8963
230k
  if (code_point >= it->start_code) {
8964
229k
    return it->direct;
8965
229k
  }
8966
1.48k
  return direction::NONE;
8967
230k
}
8968
8969
inline static size_t find_last_not_of_nsm(
8970
32.2k
    const std::u32string_view label) noexcept {
8971
33.3k
  for (int i = label.size() - 1; i >= 0; i--)
8972
33.3k
    if (find_direction(label[i]) != direction::NSM) return i;
8973
8974
0
  return std::u32string_view::npos;
8975
32.2k
}
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
32.2k
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
8980
32.2k
  const size_t mask =
8981
32.2k
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
8982
8983
32.2k
  size_t directions = 0;
8984
217k
  for (size_t i = 0; i < label.size(); i++) {
8985
185k
    directions |= 1u << find_direction(label[i]);
8986
185k
  }
8987
32.2k
  return (directions & mask) != 0;
8988
32.2k
}
8989
8990
34.4k
bool is_label_valid(const std::u32string_view label) {
8991
34.4k
  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
34.4k
  constexpr static uint32_t combining[] = {
9017
34.4k
      0x300,   0x301,   0x302,   0x303,   0x304,   0x305,   0x306,   0x307,
9018
34.4k
      0x308,   0x309,   0x30a,   0x30b,   0x30c,   0x30d,   0x30e,   0x30f,
9019
34.4k
      0x310,   0x311,   0x312,   0x313,   0x314,   0x315,   0x316,   0x317,
9020
34.4k
      0x318,   0x319,   0x31a,   0x31b,   0x31c,   0x31d,   0x31e,   0x31f,
9021
34.4k
      0x320,   0x321,   0x322,   0x323,   0x324,   0x325,   0x326,   0x327,
9022
34.4k
      0x328,   0x329,   0x32a,   0x32b,   0x32c,   0x32d,   0x32e,   0x32f,
9023
34.4k
      0x330,   0x331,   0x332,   0x333,   0x334,   0x335,   0x336,   0x337,
9024
34.4k
      0x338,   0x339,   0x33a,   0x33b,   0x33c,   0x33d,   0x33e,   0x33f,
9025
34.4k
      0x340,   0x341,   0x342,   0x343,   0x344,   0x345,   0x346,   0x347,
9026
34.4k
      0x348,   0x349,   0x34a,   0x34b,   0x34c,   0x34d,   0x34e,   0x34f,
9027
34.4k
      0x350,   0x351,   0x352,   0x353,   0x354,   0x355,   0x356,   0x357,
9028
34.4k
      0x358,   0x359,   0x35a,   0x35b,   0x35c,   0x35d,   0x35e,   0x35f,
9029
34.4k
      0x360,   0x361,   0x362,   0x363,   0x364,   0x365,   0x366,   0x367,
9030
34.4k
      0x368,   0x369,   0x36a,   0x36b,   0x36c,   0x36d,   0x36e,   0x36f,
9031
34.4k
      0x483,   0x484,   0x485,   0x486,   0x487,   0x488,   0x489,   0x591,
9032
34.4k
      0x592,   0x593,   0x594,   0x595,   0x596,   0x597,   0x598,   0x599,
9033
34.4k
      0x59a,   0x59b,   0x59c,   0x59d,   0x59e,   0x59f,   0x5a0,   0x5a1,
9034
34.4k
      0x5a2,   0x5a3,   0x5a4,   0x5a5,   0x5a6,   0x5a7,   0x5a8,   0x5a9,
9035
34.4k
      0x5aa,   0x5ab,   0x5ac,   0x5ad,   0x5ae,   0x5af,   0x5b0,   0x5b1,
9036
34.4k
      0x5b2,   0x5b3,   0x5b4,   0x5b5,   0x5b6,   0x5b7,   0x5b8,   0x5b9,
9037
34.4k
      0x5ba,   0x5bb,   0x5bc,   0x5bd,   0x5bf,   0x5c1,   0x5c2,   0x5c4,
9038
34.4k
      0x5c5,   0x5c7,   0x610,   0x611,   0x612,   0x613,   0x614,   0x615,
9039
34.4k
      0x616,   0x617,   0x618,   0x619,   0x61a,   0x64b,   0x64c,   0x64d,
9040
34.4k
      0x64e,   0x64f,   0x650,   0x651,   0x652,   0x653,   0x654,   0x655,
9041
34.4k
      0x656,   0x657,   0x658,   0x659,   0x65a,   0x65b,   0x65c,   0x65d,
9042
34.4k
      0x65e,   0x65f,   0x670,   0x6d6,   0x6d7,   0x6d8,   0x6d9,   0x6da,
9043
34.4k
      0x6db,   0x6dc,   0x6df,   0x6e0,   0x6e1,   0x6e2,   0x6e3,   0x6e4,
9044
34.4k
      0x6e7,   0x6e8,   0x6ea,   0x6eb,   0x6ec,   0x6ed,   0x711,   0x730,
9045
34.4k
      0x731,   0x732,   0x733,   0x734,   0x735,   0x736,   0x737,   0x738,
9046
34.4k
      0x739,   0x73a,   0x73b,   0x73c,   0x73d,   0x73e,   0x73f,   0x740,
9047
34.4k
      0x741,   0x742,   0x743,   0x744,   0x745,   0x746,   0x747,   0x748,
9048
34.4k
      0x749,   0x74a,   0x7a6,   0x7a7,   0x7a8,   0x7a9,   0x7aa,   0x7ab,
9049
34.4k
      0x7ac,   0x7ad,   0x7ae,   0x7af,   0x7b0,   0x7eb,   0x7ec,   0x7ed,
9050
34.4k
      0x7ee,   0x7ef,   0x7f0,   0x7f1,   0x7f2,   0x7f3,   0x7fd,   0x816,
9051
34.4k
      0x817,   0x818,   0x819,   0x81b,   0x81c,   0x81d,   0x81e,   0x81f,
9052
34.4k
      0x820,   0x821,   0x822,   0x823,   0x825,   0x826,   0x827,   0x829,
9053
34.4k
      0x82a,   0x82b,   0x82c,   0x82d,   0x859,   0x85a,   0x85b,   0x8d3,
9054
34.4k
      0x8d4,   0x8d5,   0x8d6,   0x8d7,   0x8d8,   0x8d9,   0x8da,   0x8db,
9055
34.4k
      0x8dc,   0x8dd,   0x8de,   0x8df,   0x8e0,   0x8e1,   0x8e3,   0x8e4,
9056
34.4k
      0x8e5,   0x8e6,   0x8e7,   0x8e8,   0x8e9,   0x8ea,   0x8eb,   0x8ec,
9057
34.4k
      0x8ed,   0x8ee,   0x8ef,   0x8f0,   0x8f1,   0x8f2,   0x8f3,   0x8f4,
9058
34.4k
      0x8f5,   0x8f6,   0x8f7,   0x8f8,   0x8f9,   0x8fa,   0x8fb,   0x8fc,
9059
34.4k
      0x8fd,   0x8fe,   0x8ff,   0x900,   0x901,   0x902,   0x903,   0x93a,
9060
34.4k
      0x93b,   0x93c,   0x93e,   0x93f,   0x940,   0x941,   0x942,   0x943,
9061
34.4k
      0x944,   0x945,   0x946,   0x947,   0x948,   0x949,   0x94a,   0x94b,
9062
34.4k
      0x94c,   0x94d,   0x94e,   0x94f,   0x951,   0x952,   0x953,   0x954,
9063
34.4k
      0x955,   0x956,   0x957,   0x962,   0x963,   0x981,   0x982,   0x983,
9064
34.4k
      0x9bc,   0x9be,   0x9bf,   0x9c0,   0x9c1,   0x9c2,   0x9c3,   0x9c4,
9065
34.4k
      0x9c7,   0x9c8,   0x9cb,   0x9cc,   0x9cd,   0x9d7,   0x9e2,   0x9e3,
9066
34.4k
      0x9fe,   0xa01,   0xa02,   0xa03,   0xa3c,   0xa3e,   0xa3f,   0xa40,
9067
34.4k
      0xa41,   0xa42,   0xa47,   0xa48,   0xa4b,   0xa4c,   0xa4d,   0xa51,
9068
34.4k
      0xa70,   0xa71,   0xa75,   0xa81,   0xa82,   0xa83,   0xabc,   0xabe,
9069
34.4k
      0xabf,   0xac0,   0xac1,   0xac2,   0xac3,   0xac4,   0xac5,   0xac7,
9070
34.4k
      0xac8,   0xac9,   0xacb,   0xacc,   0xacd,   0xae2,   0xae3,   0xafa,
9071
34.4k
      0xafb,   0xafc,   0xafd,   0xafe,   0xaff,   0xb01,   0xb02,   0xb03,
9072
34.4k
      0xb3c,   0xb3e,   0xb3f,   0xb40,   0xb41,   0xb42,   0xb43,   0xb44,
9073
34.4k
      0xb47,   0xb48,   0xb4b,   0xb4c,   0xb4d,   0xb55,   0xb56,   0xb57,
9074
34.4k
      0xb62,   0xb63,   0xb82,   0xbbe,   0xbbf,   0xbc0,   0xbc1,   0xbc2,
9075
34.4k
      0xbc6,   0xbc7,   0xbc8,   0xbca,   0xbcb,   0xbcc,   0xbcd,   0xbd7,
9076
34.4k
      0xc00,   0xc01,   0xc02,   0xc03,   0xc04,   0xc3e,   0xc3f,   0xc40,
9077
34.4k
      0xc41,   0xc42,   0xc43,   0xc44,   0xc46,   0xc47,   0xc48,   0xc4a,
9078
34.4k
      0xc4b,   0xc4c,   0xc4d,   0xc55,   0xc56,   0xc62,   0xc63,   0xc81,
9079
34.4k
      0xc82,   0xc83,   0xcbc,   0xcbe,   0xcbf,   0xcc0,   0xcc1,   0xcc2,
9080
34.4k
      0xcc3,   0xcc4,   0xcc6,   0xcc7,   0xcc8,   0xcca,   0xccb,   0xccc,
9081
34.4k
      0xccd,   0xcd5,   0xcd6,   0xce2,   0xce3,   0xd00,   0xd01,   0xd02,
9082
34.4k
      0xd03,   0xd3b,   0xd3c,   0xd3e,   0xd3f,   0xd40,   0xd41,   0xd42,
9083
34.4k
      0xd43,   0xd44,   0xd46,   0xd47,   0xd48,   0xd4a,   0xd4b,   0xd4c,
9084
34.4k
      0xd4d,   0xd57,   0xd62,   0xd63,   0xd81,   0xd82,   0xd83,   0xdca,
9085
34.4k
      0xdcf,   0xdd0,   0xdd1,   0xdd2,   0xdd3,   0xdd4,   0xdd6,   0xdd8,
9086
34.4k
      0xdd9,   0xdda,   0xddb,   0xddc,   0xddd,   0xdde,   0xddf,   0xdf2,
9087
34.4k
      0xdf3,   0xe31,   0xe34,   0xe35,   0xe36,   0xe37,   0xe38,   0xe39,
9088
34.4k
      0xe3a,   0xe47,   0xe48,   0xe49,   0xe4a,   0xe4b,   0xe4c,   0xe4d,
9089
34.4k
      0xe4e,   0xeb1,   0xeb4,   0xeb5,   0xeb6,   0xeb7,   0xeb8,   0xeb9,
9090
34.4k
      0xeba,   0xebb,   0xebc,   0xec8,   0xec9,   0xeca,   0xecb,   0xecc,
9091
34.4k
      0xecd,   0xf18,   0xf19,   0xf35,   0xf37,   0xf39,   0xf3e,   0xf3f,
9092
34.4k
      0xf71,   0xf72,   0xf73,   0xf74,   0xf75,   0xf76,   0xf77,   0xf78,
9093
34.4k
      0xf79,   0xf7a,   0xf7b,   0xf7c,   0xf7d,   0xf7e,   0xf7f,   0xf80,
9094
34.4k
      0xf81,   0xf82,   0xf83,   0xf84,   0xf86,   0xf87,   0xf8d,   0xf8e,
9095
34.4k
      0xf8f,   0xf90,   0xf91,   0xf92,   0xf93,   0xf94,   0xf95,   0xf96,
9096
34.4k
      0xf97,   0xf99,   0xf9a,   0xf9b,   0xf9c,   0xf9d,   0xf9e,   0xf9f,
9097
34.4k
      0xfa0,   0xfa1,   0xfa2,   0xfa3,   0xfa4,   0xfa5,   0xfa6,   0xfa7,
9098
34.4k
      0xfa8,   0xfa9,   0xfaa,   0xfab,   0xfac,   0xfad,   0xfae,   0xfaf,
9099
34.4k
      0xfb0,   0xfb1,   0xfb2,   0xfb3,   0xfb4,   0xfb5,   0xfb6,   0xfb7,
9100
34.4k
      0xfb8,   0xfb9,   0xfba,   0xfbb,   0xfbc,   0xfc6,   0x102b,  0x102c,
9101
34.4k
      0x102d,  0x102e,  0x102f,  0x1030,  0x1031,  0x1032,  0x1033,  0x1034,
9102
34.4k
      0x1035,  0x1036,  0x1037,  0x1038,  0x1039,  0x103a,  0x103b,  0x103c,
9103
34.4k
      0x103d,  0x103e,  0x1056,  0x1057,  0x1058,  0x1059,  0x105e,  0x105f,
9104
34.4k
      0x1060,  0x1062,  0x1063,  0x1064,  0x1067,  0x1068,  0x1069,  0x106a,
9105
34.4k
      0x106b,  0x106c,  0x106d,  0x1071,  0x1072,  0x1073,  0x1074,  0x1082,
9106
34.4k
      0x1083,  0x1084,  0x1085,  0x1086,  0x1087,  0x1088,  0x1089,  0x108a,
9107
34.4k
      0x108b,  0x108c,  0x108d,  0x108f,  0x109a,  0x109b,  0x109c,  0x109d,
9108
34.4k
      0x135d,  0x135e,  0x135f,  0x1712,  0x1713,  0x1714,  0x1732,  0x1733,
9109
34.4k
      0x1734,  0x1752,  0x1753,  0x1772,  0x1773,  0x17b4,  0x17b5,  0x17b6,
9110
34.4k
      0x17b7,  0x17b8,  0x17b9,  0x17ba,  0x17bb,  0x17bc,  0x17bd,  0x17be,
9111
34.4k
      0x17bf,  0x17c0,  0x17c1,  0x17c2,  0x17c3,  0x17c4,  0x17c5,  0x17c6,
9112
34.4k
      0x17c7,  0x17c8,  0x17c9,  0x17ca,  0x17cb,  0x17cc,  0x17cd,  0x17ce,
9113
34.4k
      0x17cf,  0x17d0,  0x17d1,  0x17d2,  0x17d3,  0x17dd,  0x180b,  0x180c,
9114
34.4k
      0x180d,  0x1885,  0x1886,  0x18a9,  0x1920,  0x1921,  0x1922,  0x1923,
9115
34.4k
      0x1924,  0x1925,  0x1926,  0x1927,  0x1928,  0x1929,  0x192a,  0x192b,
9116
34.4k
      0x1930,  0x1931,  0x1932,  0x1933,  0x1934,  0x1935,  0x1936,  0x1937,
9117
34.4k
      0x1938,  0x1939,  0x193a,  0x193b,  0x1a17,  0x1a18,  0x1a19,  0x1a1a,
9118
34.4k
      0x1a1b,  0x1a55,  0x1a56,  0x1a57,  0x1a58,  0x1a59,  0x1a5a,  0x1a5b,
9119
34.4k
      0x1a5c,  0x1a5d,  0x1a5e,  0x1a60,  0x1a61,  0x1a62,  0x1a63,  0x1a64,
9120
34.4k
      0x1a65,  0x1a66,  0x1a67,  0x1a68,  0x1a69,  0x1a6a,  0x1a6b,  0x1a6c,
9121
34.4k
      0x1a6d,  0x1a6e,  0x1a6f,  0x1a70,  0x1a71,  0x1a72,  0x1a73,  0x1a74,
9122
34.4k
      0x1a75,  0x1a76,  0x1a77,  0x1a78,  0x1a79,  0x1a7a,  0x1a7b,  0x1a7c,
9123
34.4k
      0x1a7f,  0x1ab0,  0x1ab1,  0x1ab2,  0x1ab3,  0x1ab4,  0x1ab5,  0x1ab6,
9124
34.4k
      0x1ab7,  0x1ab8,  0x1ab9,  0x1aba,  0x1abb,  0x1abc,  0x1abd,  0x1abe,
9125
34.4k
      0x1abf,  0x1ac0,  0x1b00,  0x1b01,  0x1b02,  0x1b03,  0x1b04,  0x1b34,
9126
34.4k
      0x1b35,  0x1b36,  0x1b37,  0x1b38,  0x1b39,  0x1b3a,  0x1b3b,  0x1b3c,
9127
34.4k
      0x1b3d,  0x1b3e,  0x1b3f,  0x1b40,  0x1b41,  0x1b42,  0x1b43,  0x1b44,
9128
34.4k
      0x1b6b,  0x1b6c,  0x1b6d,  0x1b6e,  0x1b6f,  0x1b70,  0x1b71,  0x1b72,
9129
34.4k
      0x1b73,  0x1b80,  0x1b81,  0x1b82,  0x1ba1,  0x1ba2,  0x1ba3,  0x1ba4,
9130
34.4k
      0x1ba5,  0x1ba6,  0x1ba7,  0x1ba8,  0x1ba9,  0x1baa,  0x1bab,  0x1bac,
9131
34.4k
      0x1bad,  0x1be6,  0x1be7,  0x1be8,  0x1be9,  0x1bea,  0x1beb,  0x1bec,
9132
34.4k
      0x1bed,  0x1bee,  0x1bef,  0x1bf0,  0x1bf1,  0x1bf2,  0x1bf3,  0x1c24,
9133
34.4k
      0x1c25,  0x1c26,  0x1c27,  0x1c28,  0x1c29,  0x1c2a,  0x1c2b,  0x1c2c,
9134
34.4k
      0x1c2d,  0x1c2e,  0x1c2f,  0x1c30,  0x1c31,  0x1c32,  0x1c33,  0x1c34,
9135
34.4k
      0x1c35,  0x1c36,  0x1c37,  0x1cd0,  0x1cd1,  0x1cd2,  0x1cd4,  0x1cd5,
9136
34.4k
      0x1cd6,  0x1cd7,  0x1cd8,  0x1cd9,  0x1cda,  0x1cdb,  0x1cdc,  0x1cdd,
9137
34.4k
      0x1cde,  0x1cdf,  0x1ce0,  0x1ce1,  0x1ce2,  0x1ce3,  0x1ce4,  0x1ce5,
9138
34.4k
      0x1ce6,  0x1ce7,  0x1ce8,  0x1ced,  0x1cf4,  0x1cf7,  0x1cf8,  0x1cf9,
9139
34.4k
      0x1dc0,  0x1dc1,  0x1dc2,  0x1dc3,  0x1dc4,  0x1dc5,  0x1dc6,  0x1dc7,
9140
34.4k
      0x1dc8,  0x1dc9,  0x1dca,  0x1dcb,  0x1dcc,  0x1dcd,  0x1dce,  0x1dcf,
9141
34.4k
      0x1dd0,  0x1dd1,  0x1dd2,  0x1dd3,  0x1dd4,  0x1dd5,  0x1dd6,  0x1dd7,
9142
34.4k
      0x1dd8,  0x1dd9,  0x1dda,  0x1ddb,  0x1ddc,  0x1ddd,  0x1dde,  0x1ddf,
9143
34.4k
      0x1de0,  0x1de1,  0x1de2,  0x1de3,  0x1de4,  0x1de5,  0x1de6,  0x1de7,
9144
34.4k
      0x1de8,  0x1de9,  0x1dea,  0x1deb,  0x1dec,  0x1ded,  0x1dee,  0x1def,
9145
34.4k
      0x1df0,  0x1df1,  0x1df2,  0x1df3,  0x1df4,  0x1df5,  0x1df6,  0x1df7,
9146
34.4k
      0x1df8,  0x1df9,  0x1dfb,  0x1dfc,  0x1dfd,  0x1dfe,  0x1dff,  0x20d0,
9147
34.4k
      0x20d1,  0x20d2,  0x20d3,  0x20d4,  0x20d5,  0x20d6,  0x20d7,  0x20d8,
9148
34.4k
      0x20d9,  0x20da,  0x20db,  0x20dc,  0x20dd,  0x20de,  0x20df,  0x20e0,
9149
34.4k
      0x20e1,  0x20e2,  0x20e3,  0x20e4,  0x20e5,  0x20e6,  0x20e7,  0x20e8,
9150
34.4k
      0x20e9,  0x20ea,  0x20eb,  0x20ec,  0x20ed,  0x20ee,  0x20ef,  0x20f0,
9151
34.4k
      0x2cef,  0x2cf0,  0x2cf1,  0x2d7f,  0x2de0,  0x2de1,  0x2de2,  0x2de3,
9152
34.4k
      0x2de4,  0x2de5,  0x2de6,  0x2de7,  0x2de8,  0x2de9,  0x2dea,  0x2deb,
9153
34.4k
      0x2dec,  0x2ded,  0x2dee,  0x2def,  0x2df0,  0x2df1,  0x2df2,  0x2df3,
9154
34.4k
      0x2df4,  0x2df5,  0x2df6,  0x2df7,  0x2df8,  0x2df9,  0x2dfa,  0x2dfb,
9155
34.4k
      0x2dfc,  0x2dfd,  0x2dfe,  0x2dff,  0x302a,  0x302b,  0x302c,  0x302d,
9156
34.4k
      0x302e,  0x302f,  0x3099,  0x309a,  0xa66f,  0xa670,  0xa671,  0xa672,
9157
34.4k
      0xa674,  0xa675,  0xa676,  0xa677,  0xa678,  0xa679,  0xa67a,  0xa67b,
9158
34.4k
      0xa67c,  0xa67d,  0xa69e,  0xa69f,  0xa6f0,  0xa6f1,  0xa802,  0xa806,
9159
34.4k
      0xa80b,  0xa823,  0xa824,  0xa825,  0xa826,  0xa827,  0xa82c,  0xa880,
9160
34.4k
      0xa881,  0xa8b4,  0xa8b5,  0xa8b6,  0xa8b7,  0xa8b8,  0xa8b9,  0xa8ba,
9161
34.4k
      0xa8bb,  0xa8bc,  0xa8bd,  0xa8be,  0xa8bf,  0xa8c0,  0xa8c1,  0xa8c2,
9162
34.4k
      0xa8c3,  0xa8c4,  0xa8c5,  0xa8e0,  0xa8e1,  0xa8e2,  0xa8e3,  0xa8e4,
9163
34.4k
      0xa8e5,  0xa8e6,  0xa8e7,  0xa8e8,  0xa8e9,  0xa8ea,  0xa8eb,  0xa8ec,
9164
34.4k
      0xa8ed,  0xa8ee,  0xa8ef,  0xa8f0,  0xa8f1,  0xa8ff,  0xa926,  0xa927,
9165
34.4k
      0xa928,  0xa929,  0xa92a,  0xa92b,  0xa92c,  0xa92d,  0xa947,  0xa948,
9166
34.4k
      0xa949,  0xa94a,  0xa94b,  0xa94c,  0xa94d,  0xa94e,  0xa94f,  0xa950,
9167
34.4k
      0xa951,  0xa952,  0xa953,  0xa980,  0xa981,  0xa982,  0xa983,  0xa9b3,
9168
34.4k
      0xa9b4,  0xa9b5,  0xa9b6,  0xa9b7,  0xa9b8,  0xa9b9,  0xa9ba,  0xa9bb,
9169
34.4k
      0xa9bc,  0xa9bd,  0xa9be,  0xa9bf,  0xa9c0,  0xa9e5,  0xaa29,  0xaa2a,
9170
34.4k
      0xaa2b,  0xaa2c,  0xaa2d,  0xaa2e,  0xaa2f,  0xaa30,  0xaa31,  0xaa32,
9171
34.4k
      0xaa33,  0xaa34,  0xaa35,  0xaa36,  0xaa43,  0xaa4c,  0xaa4d,  0xaa7b,
9172
34.4k
      0xaa7c,  0xaa7d,  0xaab0,  0xaab2,  0xaab3,  0xaab4,  0xaab7,  0xaab8,
9173
34.4k
      0xaabe,  0xaabf,  0xaac1,  0xaaeb,  0xaaec,  0xaaed,  0xaaee,  0xaaef,
9174
34.4k
      0xaaf5,  0xaaf6,  0xabe3,  0xabe4,  0xabe5,  0xabe6,  0xabe7,  0xabe8,
9175
34.4k
      0xabe9,  0xabea,  0xabec,  0xabed,  0xfb1e,  0xfe00,  0xfe01,  0xfe02,
9176
34.4k
      0xfe03,  0xfe04,  0xfe05,  0xfe06,  0xfe07,  0xfe08,  0xfe09,  0xfe0a,
9177
34.4k
      0xfe0b,  0xfe0c,  0xfe0d,  0xfe0e,  0xfe0f,  0xfe20,  0xfe21,  0xfe22,
9178
34.4k
      0xfe23,  0xfe24,  0xfe25,  0xfe26,  0xfe27,  0xfe28,  0xfe29,  0xfe2a,
9179
34.4k
      0xfe2b,  0xfe2c,  0xfe2d,  0xfe2e,  0xfe2f,  0x101fd, 0x102e0, 0x10376,
9180
34.4k
      0x10377, 0x10378, 0x10379, 0x1037a, 0x10a01, 0x10a02, 0x10a03, 0x10a05,
9181
34.4k
      0x10a06, 0x10a0c, 0x10a0d, 0x10a0e, 0x10a0f, 0x10a38, 0x10a39, 0x10a3a,
9182
34.4k
      0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d25, 0x10d26, 0x10d27, 0x10eab,
9183
34.4k
      0x10eac, 0x10f46, 0x10f47, 0x10f48, 0x10f49, 0x10f4a, 0x10f4b, 0x10f4c,
9184
34.4k
      0x10f4d, 0x10f4e, 0x10f4f, 0x10f50, 0x11000, 0x11001, 0x11002, 0x11038,
9185
34.4k
      0x11039, 0x1103a, 0x1103b, 0x1103c, 0x1103d, 0x1103e, 0x1103f, 0x11040,
9186
34.4k
      0x11041, 0x11042, 0x11043, 0x11044, 0x11045, 0x11046, 0x1107f, 0x11080,
9187
34.4k
      0x11081, 0x11082, 0x110b0, 0x110b1, 0x110b2, 0x110b3, 0x110b4, 0x110b5,
9188
34.4k
      0x110b6, 0x110b7, 0x110b8, 0x110b9, 0x110ba, 0x11100, 0x11101, 0x11102,
9189
34.4k
      0x11127, 0x11128, 0x11129, 0x1112a, 0x1112b, 0x1112c, 0x1112d, 0x1112e,
9190
34.4k
      0x1112f, 0x11130, 0x11131, 0x11132, 0x11133, 0x11134, 0x11145, 0x11146,
9191
34.4k
      0x11173, 0x11180, 0x11181, 0x11182, 0x111b3, 0x111b4, 0x111b5, 0x111b6,
9192
34.4k
      0x111b7, 0x111b8, 0x111b9, 0x111ba, 0x111bb, 0x111bc, 0x111bd, 0x111be,
9193
34.4k
      0x111bf, 0x111c0, 0x111c9, 0x111ca, 0x111cb, 0x111cc, 0x111ce, 0x111cf,
9194
34.4k
      0x1122c, 0x1122d, 0x1122e, 0x1122f, 0x11230, 0x11231, 0x11232, 0x11233,
9195
34.4k
      0x11234, 0x11235, 0x11236, 0x11237, 0x1123e, 0x112df, 0x112e0, 0x112e1,
9196
34.4k
      0x112e2, 0x112e3, 0x112e4, 0x112e5, 0x112e6, 0x112e7, 0x112e8, 0x112e9,
9197
34.4k
      0x112ea, 0x11300, 0x11301, 0x11302, 0x11303, 0x1133b, 0x1133c, 0x1133e,
9198
34.4k
      0x1133f, 0x11340, 0x11341, 0x11342, 0x11343, 0x11344, 0x11347, 0x11348,
9199
34.4k
      0x1134b, 0x1134c, 0x1134d, 0x11357, 0x11362, 0x11363, 0x11366, 0x11367,
9200
34.4k
      0x11368, 0x11369, 0x1136a, 0x1136b, 0x1136c, 0x11370, 0x11371, 0x11372,
9201
34.4k
      0x11373, 0x11374, 0x11435, 0x11436, 0x11437, 0x11438, 0x11439, 0x1143a,
9202
34.4k
      0x1143b, 0x1143c, 0x1143d, 0x1143e, 0x1143f, 0x11440, 0x11441, 0x11442,
9203
34.4k
      0x11443, 0x11444, 0x11445, 0x11446, 0x1145e, 0x114b0, 0x114b1, 0x114b2,
9204
34.4k
      0x114b3, 0x114b4, 0x114b5, 0x114b6, 0x114b7, 0x114b8, 0x114b9, 0x114ba,
9205
34.4k
      0x114bb, 0x114bc, 0x114bd, 0x114be, 0x114bf, 0x114c0, 0x114c1, 0x114c2,
9206
34.4k
      0x114c3, 0x115af, 0x115b0, 0x115b1, 0x115b2, 0x115b3, 0x115b4, 0x115b5,
9207
34.4k
      0x115b8, 0x115b9, 0x115ba, 0x115bb, 0x115bc, 0x115bd, 0x115be, 0x115bf,
9208
34.4k
      0x115c0, 0x115dc, 0x115dd, 0x11630, 0x11631, 0x11632, 0x11633, 0x11634,
9209
34.4k
      0x11635, 0x11636, 0x11637, 0x11638, 0x11639, 0x1163a, 0x1163b, 0x1163c,
9210
34.4k
      0x1163d, 0x1163e, 0x1163f, 0x11640, 0x116ab, 0x116ac, 0x116ad, 0x116ae,
9211
34.4k
      0x116af, 0x116b0, 0x116b1, 0x116b2, 0x116b3, 0x116b4, 0x116b5, 0x116b6,
9212
34.4k
      0x116b7, 0x1171d, 0x1171e, 0x1171f, 0x11720, 0x11721, 0x11722, 0x11723,
9213
34.4k
      0x11724, 0x11725, 0x11726, 0x11727, 0x11728, 0x11729, 0x1172a, 0x1172b,
9214
34.4k
      0x1182c, 0x1182d, 0x1182e, 0x1182f, 0x11830, 0x11831, 0x11832, 0x11833,
9215
34.4k
      0x11834, 0x11835, 0x11836, 0x11837, 0x11838, 0x11839, 0x1183a, 0x11930,
9216
34.4k
      0x11931, 0x11932, 0x11933, 0x11934, 0x11935, 0x11937, 0x11938, 0x1193b,
9217
34.4k
      0x1193c, 0x1193d, 0x1193e, 0x11940, 0x11942, 0x11943, 0x119d1, 0x119d2,
9218
34.4k
      0x119d3, 0x119d4, 0x119d5, 0x119d6, 0x119d7, 0x119da, 0x119db, 0x119dc,
9219
34.4k
      0x119dd, 0x119de, 0x119df, 0x119e0, 0x119e4, 0x11a01, 0x11a02, 0x11a03,
9220
34.4k
      0x11a04, 0x11a05, 0x11a06, 0x11a07, 0x11a08, 0x11a09, 0x11a0a, 0x11a33,
9221
34.4k
      0x11a34, 0x11a35, 0x11a36, 0x11a37, 0x11a38, 0x11a39, 0x11a3b, 0x11a3c,
9222
34.4k
      0x11a3d, 0x11a3e, 0x11a47, 0x11a51, 0x11a52, 0x11a53, 0x11a54, 0x11a55,
9223
34.4k
      0x11a56, 0x11a57, 0x11a58, 0x11a59, 0x11a5a, 0x11a5b, 0x11a8a, 0x11a8b,
9224
34.4k
      0x11a8c, 0x11a8d, 0x11a8e, 0x11a8f, 0x11a90, 0x11a91, 0x11a92, 0x11a93,
9225
34.4k
      0x11a94, 0x11a95, 0x11a96, 0x11a97, 0x11a98, 0x11a99, 0x11c2f, 0x11c30,
9226
34.4k
      0x11c31, 0x11c32, 0x11c33, 0x11c34, 0x11c35, 0x11c36, 0x11c38, 0x11c39,
9227
34.4k
      0x11c3a, 0x11c3b, 0x11c3c, 0x11c3d, 0x11c3e, 0x11c3f, 0x11c92, 0x11c93,
9228
34.4k
      0x11c94, 0x11c95, 0x11c96, 0x11c97, 0x11c98, 0x11c99, 0x11c9a, 0x11c9b,
9229
34.4k
      0x11c9c, 0x11c9d, 0x11c9e, 0x11c9f, 0x11ca0, 0x11ca1, 0x11ca2, 0x11ca3,
9230
34.4k
      0x11ca4, 0x11ca5, 0x11ca6, 0x11ca7, 0x11ca9, 0x11caa, 0x11cab, 0x11cac,
9231
34.4k
      0x11cad, 0x11cae, 0x11caf, 0x11cb0, 0x11cb1, 0x11cb2, 0x11cb3, 0x11cb4,
9232
34.4k
      0x11cb5, 0x11cb6, 0x11d31, 0x11d32, 0x11d33, 0x11d34, 0x11d35, 0x11d36,
9233
34.4k
      0x11d3a, 0x11d3c, 0x11d3d, 0x11d3f, 0x11d40, 0x11d41, 0x11d42, 0x11d43,
9234
34.4k
      0x11d44, 0x11d45, 0x11d47, 0x11d8a, 0x11d8b, 0x11d8c, 0x11d8d, 0x11d8e,
9235
34.4k
      0x11d90, 0x11d91, 0x11d93, 0x11d94, 0x11d95, 0x11d96, 0x11d97, 0x11ef3,
9236
34.4k
      0x11ef4, 0x11ef5, 0x11ef6, 0x16af0, 0x16af1, 0x16af2, 0x16af3, 0x16af4,
9237
34.4k
      0x16b30, 0x16b31, 0x16b32, 0x16b33, 0x16b34, 0x16b35, 0x16b36, 0x16f4f,
9238
34.4k
      0x16f51, 0x16f52, 0x16f53, 0x16f54, 0x16f55, 0x16f56, 0x16f57, 0x16f58,
9239
34.4k
      0x16f59, 0x16f5a, 0x16f5b, 0x16f5c, 0x16f5d, 0x16f5e, 0x16f5f, 0x16f60,
9240
34.4k
      0x16f61, 0x16f62, 0x16f63, 0x16f64, 0x16f65, 0x16f66, 0x16f67, 0x16f68,
9241
34.4k
      0x16f69, 0x16f6a, 0x16f6b, 0x16f6c, 0x16f6d, 0x16f6e, 0x16f6f, 0x16f70,
9242
34.4k
      0x16f71, 0x16f72, 0x16f73, 0x16f74, 0x16f75, 0x16f76, 0x16f77, 0x16f78,
9243
34.4k
      0x16f79, 0x16f7a, 0x16f7b, 0x16f7c, 0x16f7d, 0x16f7e, 0x16f7f, 0x16f80,
9244
34.4k
      0x16f81, 0x16f82, 0x16f83, 0x16f84, 0x16f85, 0x16f86, 0x16f87, 0x16f8f,
9245
34.4k
      0x16f90, 0x16f91, 0x16f92, 0x16fe4, 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e,
9246
34.4k
      0x1d165, 0x1d166, 0x1d167, 0x1d168, 0x1d169, 0x1d16d, 0x1d16e, 0x1d16f,
9247
34.4k
      0x1d170, 0x1d171, 0x1d172, 0x1d17b, 0x1d17c, 0x1d17d, 0x1d17e, 0x1d17f,
9248
34.4k
      0x1d180, 0x1d181, 0x1d182, 0x1d185, 0x1d186, 0x1d187, 0x1d188, 0x1d189,
9249
34.4k
      0x1d18a, 0x1d18b, 0x1d1aa, 0x1d1ab, 0x1d1ac, 0x1d1ad, 0x1d242, 0x1d243,
9250
34.4k
      0x1d244, 0x1da00, 0x1da01, 0x1da02, 0x1da03, 0x1da04, 0x1da05, 0x1da06,
9251
34.4k
      0x1da07, 0x1da08, 0x1da09, 0x1da0a, 0x1da0b, 0x1da0c, 0x1da0d, 0x1da0e,
9252
34.4k
      0x1da0f, 0x1da10, 0x1da11, 0x1da12, 0x1da13, 0x1da14, 0x1da15, 0x1da16,
9253
34.4k
      0x1da17, 0x1da18, 0x1da19, 0x1da1a, 0x1da1b, 0x1da1c, 0x1da1d, 0x1da1e,
9254
34.4k
      0x1da1f, 0x1da20, 0x1da21, 0x1da22, 0x1da23, 0x1da24, 0x1da25, 0x1da26,
9255
34.4k
      0x1da27, 0x1da28, 0x1da29, 0x1da2a, 0x1da2b, 0x1da2c, 0x1da2d, 0x1da2e,
9256
34.4k
      0x1da2f, 0x1da30, 0x1da31, 0x1da32, 0x1da33, 0x1da34, 0x1da35, 0x1da36,
9257
34.4k
      0x1da3b, 0x1da3c, 0x1da3d, 0x1da3e, 0x1da3f, 0x1da40, 0x1da41, 0x1da42,
9258
34.4k
      0x1da43, 0x1da44, 0x1da45, 0x1da46, 0x1da47, 0x1da48, 0x1da49, 0x1da4a,
9259
34.4k
      0x1da4b, 0x1da4c, 0x1da4d, 0x1da4e, 0x1da4f, 0x1da50, 0x1da51, 0x1da52,
9260
34.4k
      0x1da53, 0x1da54, 0x1da55, 0x1da56, 0x1da57, 0x1da58, 0x1da59, 0x1da5a,
9261
34.4k
      0x1da5b, 0x1da5c, 0x1da5d, 0x1da5e, 0x1da5f, 0x1da60, 0x1da61, 0x1da62,
9262
34.4k
      0x1da63, 0x1da64, 0x1da65, 0x1da66, 0x1da67, 0x1da68, 0x1da69, 0x1da6a,
9263
34.4k
      0x1da6b, 0x1da6c, 0x1da75, 0x1da84, 0x1da9b, 0x1da9c, 0x1da9d, 0x1da9e,
9264
34.4k
      0x1da9f, 0x1daa1, 0x1daa2, 0x1daa3, 0x1daa4, 0x1daa5, 0x1daa6, 0x1daa7,
9265
34.4k
      0x1daa8, 0x1daa9, 0x1daaa, 0x1daab, 0x1daac, 0x1daad, 0x1daae, 0x1daaf,
9266
34.4k
      0x1e000, 0x1e001, 0x1e002, 0x1e003, 0x1e004, 0x1e005, 0x1e006, 0x1e008,
9267
34.4k
      0x1e009, 0x1e00a, 0x1e00b, 0x1e00c, 0x1e00d, 0x1e00e, 0x1e00f, 0x1e010,
9268
34.4k
      0x1e011, 0x1e012, 0x1e013, 0x1e014, 0x1e015, 0x1e016, 0x1e017, 0x1e018,
9269
34.4k
      0x1e01b, 0x1e01c, 0x1e01d, 0x1e01e, 0x1e01f, 0x1e020, 0x1e021, 0x1e023,
9270
34.4k
      0x1e024, 0x1e026, 0x1e027, 0x1e028, 0x1e029, 0x1e02a, 0x1e130, 0x1e131,
9271
34.4k
      0x1e132, 0x1e133, 0x1e134, 0x1e135, 0x1e136, 0x1e2ec, 0x1e2ed, 0x1e2ee,
9272
34.4k
      0x1e2ef, 0x1e8d0, 0x1e8d1, 0x1e8d2, 0x1e8d3, 0x1e8d4, 0x1e8d5, 0x1e8d6,
9273
34.4k
      0x1e944, 0x1e945, 0x1e946, 0x1e947, 0x1e948, 0x1e949, 0x1e94a, 0xe0100,
9274
34.4k
      0xe0101, 0xe0102, 0xe0103, 0xe0104, 0xe0105, 0xe0106, 0xe0107, 0xe0108,
9275
34.4k
      0xe0109, 0xe010a, 0xe010b, 0xe010c, 0xe010d, 0xe010e, 0xe010f, 0xe0110,
9276
34.4k
      0xe0111, 0xe0112, 0xe0113, 0xe0114, 0xe0115, 0xe0116, 0xe0117, 0xe0118,
9277
34.4k
      0xe0119, 0xe011a, 0xe011b, 0xe011c, 0xe011d, 0xe011e, 0xe011f, 0xe0120,
9278
34.4k
      0xe0121, 0xe0122, 0xe0123, 0xe0124, 0xe0125, 0xe0126, 0xe0127, 0xe0128,
9279
34.4k
      0xe0129, 0xe012a, 0xe012b, 0xe012c, 0xe012d, 0xe012e, 0xe012f, 0xe0130,
9280
34.4k
      0xe0131, 0xe0132, 0xe0133, 0xe0134, 0xe0135, 0xe0136, 0xe0137, 0xe0138,
9281
34.4k
      0xe0139, 0xe013a, 0xe013b, 0xe013c, 0xe013d, 0xe013e, 0xe013f, 0xe0140,
9282
34.4k
      0xe0141, 0xe0142, 0xe0143, 0xe0144, 0xe0145, 0xe0146, 0xe0147, 0xe0148,
9283
34.4k
      0xe0149, 0xe014a, 0xe014b, 0xe014c, 0xe014d, 0xe014e, 0xe014f, 0xe0150,
9284
34.4k
      0xe0151, 0xe0152, 0xe0153, 0xe0154, 0xe0155, 0xe0156, 0xe0157, 0xe0158,
9285
34.4k
      0xe0159, 0xe015a, 0xe015b, 0xe015c, 0xe015d, 0xe015e, 0xe015f, 0xe0160,
9286
34.4k
      0xe0161, 0xe0162, 0xe0163, 0xe0164, 0xe0165, 0xe0166, 0xe0167, 0xe0168,
9287
34.4k
      0xe0169, 0xe016a, 0xe016b, 0xe016c, 0xe016d, 0xe016e, 0xe016f, 0xe0170,
9288
34.4k
      0xe0171, 0xe0172, 0xe0173, 0xe0174, 0xe0175, 0xe0176, 0xe0177, 0xe0178,
9289
34.4k
      0xe0179, 0xe017a, 0xe017b, 0xe017c, 0xe017d, 0xe017e, 0xe017f, 0xe0180,
9290
34.4k
      0xe0181, 0xe0182, 0xe0183, 0xe0184, 0xe0185, 0xe0186, 0xe0187, 0xe0188,
9291
34.4k
      0xe0189, 0xe018a, 0xe018b, 0xe018c, 0xe018d, 0xe018e, 0xe018f, 0xe0190,
9292
34.4k
      0xe0191, 0xe0192, 0xe0193, 0xe0194, 0xe0195, 0xe0196, 0xe0197, 0xe0198,
9293
34.4k
      0xe0199, 0xe019a, 0xe019b, 0xe019c, 0xe019d, 0xe019e, 0xe019f, 0xe01a0,
9294
34.4k
      0xe01a1, 0xe01a2, 0xe01a3, 0xe01a4, 0xe01a5, 0xe01a6, 0xe01a7, 0xe01a8,
9295
34.4k
      0xe01a9, 0xe01aa, 0xe01ab, 0xe01ac, 0xe01ad, 0xe01ae, 0xe01af, 0xe01b0,
9296
34.4k
      0xe01b1, 0xe01b2, 0xe01b3, 0xe01b4, 0xe01b5, 0xe01b6, 0xe01b7, 0xe01b8,
9297
34.4k
      0xe01b9, 0xe01ba, 0xe01bb, 0xe01bc, 0xe01bd, 0xe01be, 0xe01bf, 0xe01c0,
9298
34.4k
      0xe01c1, 0xe01c2, 0xe01c3, 0xe01c4, 0xe01c5, 0xe01c6, 0xe01c7, 0xe01c8,
9299
34.4k
      0xe01c9, 0xe01ca, 0xe01cb, 0xe01cc, 0xe01cd, 0xe01ce, 0xe01cf, 0xe01d0,
9300
34.4k
      0xe01d1, 0xe01d2, 0xe01d3, 0xe01d4, 0xe01d5, 0xe01d6, 0xe01d7, 0xe01d8,
9301
34.4k
      0xe01d9, 0xe01da, 0xe01db, 0xe01dc, 0xe01dd, 0xe01de, 0xe01df, 0xe01e0,
9302
34.4k
      0xe01e1, 0xe01e2, 0xe01e3, 0xe01e4, 0xe01e5, 0xe01e6, 0xe01e7, 0xe01e8,
9303
34.4k
      0xe01e9, 0xe01ea, 0xe01eb, 0xe01ec, 0xe01ed, 0xe01ee, 0xe01ef};
9304
34.4k
  if (std::binary_search(std::begin(combining), std::end(combining),
9305
34.4k
                         label.front())) {
9306
76
    return false;
9307
76
  }
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
34.3k
  constexpr static uint32_t virama[] = {
9320
34.3k
      0x094D,  0x09CD,  0x0A4D,  0x0ACD,  0x0B4D,  0x0BCD,  0x0C4D,  0x0CCD,
9321
34.3k
      0x0D3B,  0x0D3C,  0x0D4D,  0x0DCA,  0x0E3A,  0x0EBA,  0x0F84,  0x1039,
9322
34.3k
      0x103A,  0x1714,  0x1734,  0x17D2,  0x1A60,  0x1B44,  0x1BAA,  0x1BAB,
9323
34.3k
      0x1BF2,  0x1BF3,  0x2D7F,  0xA806,  0xA82C,  0xA8C4,  0xA953,  0xA9C0,
9324
34.3k
      0xAAF6,  0xABED,  0x10A3F, 0x11046, 0x1107F, 0x110B9, 0x11133, 0x11134,
9325
34.3k
      0x111C0, 0x11235, 0x112EA, 0x1134D, 0x11442, 0x114C2, 0x115BF, 0x1163F,
9326
34.3k
      0x116B6, 0x1172B, 0x11839, 0x1193D, 0x1193E, 0x119E0, 0x11A34, 0x11A47,
9327
34.3k
      0x11A99, 0x11C3F, 0x11D44, 0x11D45, 0x11D97};
9328
34.3k
  constexpr static uint32_t R[] = {
9329
34.3k
      0x622, 0x623, 0x624, 0x625, 0x627, 0x629, 0x62f, 0x630, 0x631,
9330
34.3k
      0x632, 0x648, 0x671, 0x672, 0x673, 0x675, 0x676, 0x677, 0x688,
9331
34.3k
      0x689, 0x68a, 0x68b, 0x68c, 0x68d, 0x68e, 0x68f, 0x690, 0x691,
9332
34.3k
      0x692, 0x693, 0x694, 0x695, 0x696, 0x697, 0x698, 0x699, 0x6c0,
9333
34.3k
      0x6c3, 0x6c4, 0x6c5, 0x6c6, 0x6c7, 0x6c8, 0x6c9, 0x6ca, 0x6cb,
9334
34.3k
      0x6cd, 0x6cf, 0x6d2, 0x6d3, 0x6d5, 0x6ee, 0x6ef, 0x710, 0x715,
9335
34.3k
      0x716, 0x717, 0x718, 0x719, 0x71e, 0x728, 0x72a, 0x72c, 0x72f,
9336
34.3k
      0x74d, 0x759, 0x75a, 0x75b, 0x854, 0x8aa, 0x8ab, 0x8ac};
9337
34.3k
  constexpr static uint32_t L[] = {0xa872};
9338
34.3k
  constexpr static uint32_t D[] = {
9339
34.3k
      0x620,  0x626,  0x628,  0x62a,  0x62b,  0x62c,  0x62d,  0x62e,  0x633,
9340
34.3k
      0x634,  0x635,  0x636,  0x637,  0x638,  0x639,  0x63a,  0x63b,  0x63c,
9341
34.3k
      0x63d,  0x63e,  0x63f,  0x641,  0x642,  0x643,  0x644,  0x645,  0x646,
9342
34.3k
      0x647,  0x649,  0x64a,  0x66e,  0x66f,  0x678,  0x679,  0x67a,  0x67b,
9343
34.3k
      0x67c,  0x67d,  0x67e,  0x67f,  0x680,  0x681,  0x682,  0x683,  0x684,
9344
34.3k
      0x685,  0x686,  0x687,  0x69a,  0x69b,  0x69c,  0x69d,  0x69e,  0x69f,
9345
34.3k
      0x6a0,  0x6a1,  0x6a2,  0x6a3,  0x6a4,  0x6a5,  0x6a6,  0x6a7,  0x6a8,
9346
34.3k
      0x6a9,  0x6aa,  0x6ab,  0x6ac,  0x6ad,  0x6ae,  0x6af,  0x6b0,  0x6b1,
9347
34.3k
      0x6b2,  0x6b3,  0x6b4,  0x6b5,  0x6b6,  0x6b7,  0x6b8,  0x6b9,  0x6ba,
9348
34.3k
      0x6bb,  0x6bc,  0x6bd,  0x6be,  0x6bf,  0x6c1,  0x6c2,  0x6cc,  0x6ce,
9349
34.3k
      0x6d0,  0x6d1,  0x6fa,  0x6fb,  0x6fc,  0x6ff,  0x712,  0x713,  0x714,
9350
34.3k
      0x71a,  0x71b,  0x71c,  0x71d,  0x71f,  0x720,  0x721,  0x722,  0x723,
9351
34.3k
      0x724,  0x725,  0x726,  0x727,  0x729,  0x72b,  0x72d,  0x72e,  0x74e,
9352
34.3k
      0x74f,  0x750,  0x751,  0x752,  0x753,  0x754,  0x755,  0x756,  0x757,
9353
34.3k
      0x758,  0x75c,  0x75d,  0x75e,  0x75f,  0x760,  0x761,  0x762,  0x763,
9354
34.3k
      0x764,  0x765,  0x766,  0x850,  0x851,  0x852,  0x853,  0x855,  0x8a0,
9355
34.3k
      0x8a2,  0x8a3,  0x8a4,  0x8a5,  0x8a6,  0x8a7,  0x8a8,  0x8a9,  0x1807,
9356
34.3k
      0x1820, 0x1821, 0x1822, 0x1823, 0x1824, 0x1825, 0x1826, 0x1827, 0x1828,
9357
34.3k
      0x1829, 0x182a, 0x182b, 0x182c, 0x182d, 0x182e, 0x182f, 0x1830, 0x1831,
9358
34.3k
      0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837, 0x1838, 0x1839, 0x183a,
9359
34.3k
      0x183b, 0x183c, 0x183d, 0x183e, 0x183f, 0x1840, 0x1841, 0x1842, 0x1843,
9360
34.3k
      0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x184a, 0x184b, 0x184c,
9361
34.3k
      0x184d, 0x184e, 0x184f, 0x1850, 0x1851, 0x1852, 0x1853, 0x1854, 0x1855,
9362
34.3k
      0x1856, 0x1857, 0x1858, 0x1859, 0x185a, 0x185b, 0x185c, 0x185d, 0x185e,
9363
34.3k
      0x185f, 0x1860, 0x1861, 0x1862, 0x1863, 0x1864, 0x1865, 0x1866, 0x1867,
9364
34.3k
      0x1868, 0x1869, 0x186a, 0x186b, 0x186c, 0x186d, 0x186e, 0x186f, 0x1870,
9365
34.3k
      0x1871, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, 0x1877, 0x1887, 0x1888,
9366
34.3k
      0x1889, 0x188a, 0x188b, 0x188c, 0x188d, 0x188e, 0x188f, 0x1890, 0x1891,
9367
34.3k
      0x1892, 0x1893, 0x1894, 0x1895, 0x1896, 0x1897, 0x1898, 0x1899, 0x189a,
9368
34.3k
      0x189b, 0x189c, 0x189d, 0x189e, 0x189f, 0x18a0, 0x18a1, 0x18a2, 0x18a3,
9369
34.3k
      0x18a4, 0x18a5, 0x18a6, 0x18a7, 0x18a8, 0x18aa, 0xa840, 0xa841, 0xa842,
9370
34.3k
      0xa843, 0xa844, 0xa845, 0xa846, 0xa847, 0xa848, 0xa849, 0xa84a, 0xa84b,
9371
34.3k
      0xa84c, 0xa84d, 0xa84e, 0xa84f, 0xa850, 0xa851, 0xa852, 0xa853, 0xa854,
9372
34.3k
      0xa855, 0xa856, 0xa857, 0xa858, 0xa859, 0xa85a, 0xa85b, 0xa85c, 0xa85d,
9373
34.3k
      0xa85e, 0xa85f, 0xa860, 0xa861, 0xa862, 0xa863, 0xa864, 0xa865, 0xa866,
9374
34.3k
      0xa867, 0xa868, 0xa869, 0xa86a, 0xa86b, 0xa86c, 0xa86d, 0xa86e, 0xa86f,
9375
34.3k
      0xa870, 0xa871};
9376
9377
247k
  for (size_t i = 0; i < label.size(); i++) {
9378
215k
    uint32_t c = label[i];
9379
215k
    if (c == 0x200c) {
9380
1.43k
      if (i > 0) {
9381
1.41k
        if (std::binary_search(std::begin(virama), std::end(virama),
9382
1.41k
                               label[i - 1])) {
9383
247
          return true;
9384
247
        }
9385
1.41k
      }
9386
1.18k
      if ((i == 0) || (i + 1 >= label.size())) {
9387
131
        return false;
9388
131
      }
9389
      // we go backward looking for L or D
9390
2.35k
      auto is_l_or_d = [](uint32_t code) {
9391
2.35k
        return std::binary_search(std::begin(L), std::end(L), code) ||
9392
2.35k
               std::binary_search(std::begin(D), std::end(D), code);
9393
2.35k
      };
9394
1.84k
      auto is_r_or_d = [](uint32_t code) {
9395
1.84k
        return std::binary_search(std::begin(R), std::end(R), code) ||
9396
1.84k
               std::binary_search(std::begin(D), std::end(D), code);
9397
1.84k
      };
9398
1.05k
      std::u32string_view before = label.substr(0, i);
9399
1.05k
      std::u32string_view after = label.substr(i + 1);
9400
1.05k
      return (std::find_if(before.begin(), before.end(), is_l_or_d) !=
9401
1.05k
              before.end()) &&
9402
1.05k
             (std::find_if(after.begin(), after.end(), is_r_or_d) !=
9403
926
              after.end());
9404
213k
    } else if (c == 0x200d) {
9405
689
      if (i > 0) {
9406
675
        if (std::binary_search(std::begin(virama), std::end(virama),
9407
675
                               label[i - 1])) {
9408
583
          return true;
9409
583
        }
9410
675
      }
9411
106
      return false;
9412
689
    }
9413
215k
  }
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
32.2k
  size_t last_non_nsm_char = find_last_not_of_nsm(label);
9446
32.2k
  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
32.2k
  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.75k
    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.79k
      for (size_t i = 0; i < last_non_nsm_char; i++) {
9464
3.32k
        const direction d = find_direction(label[i]);
9465
3.32k
        if (!(d == direction::L || d == direction::EN || d == direction::ES ||
9466
3.32k
              d == direction::CS || d == direction::ET || d == direction::ON ||
9467
3.32k
              d == direction::BN || d == direction::NSM)) {
9468
137
          return false;
9469
137
        }
9470
9471
3.19k
        if ((i == last_non_nsm_char) &&
9472
3.19k
            !(d == direction::L || d == direction::EN)) {
9473
0
          return false;
9474
0
        }
9475
3.19k
      }
9476
9477
461
      return true;
9478
9479
2.15k
    } else {
9480
      // Eval as RTL
9481
9482
2.15k
      bool has_an = false;
9483
2.15k
      bool has_en = false;
9484
7.48k
      for (size_t i = 0; i <= last_non_nsm_char; i++) {
9485
5.57k
        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.57k
        if ((d == direction::EN && ((has_en = true) && has_an)) ||
9490
5.57k
            (d == direction::AN && ((has_an = true) && has_en))) {
9491
20
          return false;
9492
20
        }
9493
9494
5.55k
        if (!(d == direction::R || d == direction::AL || d == direction::AN ||
9495
5.55k
              d == direction::EN || d == direction::ES || d == direction::CS ||
9496
5.55k
              d == direction::ET || d == direction::ON || d == direction::BN ||
9497
5.55k
              d == direction::NSM)) {
9498
164
          return false;
9499
164
        }
9500
9501
5.39k
        if (i == last_non_nsm_char &&
9502
5.39k
            !(d == direction::R || d == direction::AL || d == direction::AN ||
9503
1.97k
              d == direction::EN)) {
9504
65
          return false;
9505
65
        }
9506
5.39k
      }
9507
9508
1.90k
      return true;
9509
2.15k
    }
9510
2.75k
  }
9511
9512
29.5k
  return true;
9513
32.2k
}
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
bool constexpr begins_with(std::u32string_view view,
9526
30.6k
                           std::u32string_view prefix) {
9527
30.6k
  if (view.size() < prefix.size()) {
9528
8.34k
    return false;
9529
8.34k
  }
9530
22.2k
  return view.substr(0, prefix.size()) == prefix;
9531
30.6k
}
9532
9533
56.6k
bool constexpr begins_with(std::string_view view, std::string_view prefix) {
9534
56.6k
  if (view.size() < prefix.size()) {
9535
26.8k
    return false;
9536
26.8k
  }
9537
29.8k
  return view.substr(0, prefix.size()) == prefix;
9538
56.6k
}
9539
9540
28.5k
bool constexpr is_ascii(std::u32string_view view) {
9541
60.0k
  for (uint32_t c : view) {
9542
60.0k
    if (c >= 0x80) {
9543
25.4k
      return false;
9544
25.4k
    }
9545
60.0k
  }
9546
3.15k
  return true;
9547
28.5k
}
9548
9549
27.3k
bool constexpr is_ascii(std::string_view view) {
9550
342k
  for (uint8_t c : view) {
9551
342k
    if (c >= 0x80) {
9552
9.93k
      return false;
9553
9.93k
    }
9554
342k
  }
9555
17.3k
  return true;
9556
27.3k
}
9557
9558
constexpr static uint8_t is_forbidden_domain_code_point_table[] = {
9559
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9560
    1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
9561
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
9562
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
9563
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9564
    0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9565
    1, 1, 1, 1, 1, 1, 1, 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};
9570
9571
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
9572
9573
0
inline bool is_forbidden_domain_code_point(const char c) noexcept {
9574
0
  return is_forbidden_domain_code_point_table[uint8_t(c)];
9575
0
}
9576
9577
0
bool contains_forbidden_domain_code_point(std::string_view view) {
9578
0
  return (
9579
0
      std::any_of(view.begin(), view.end(), is_forbidden_domain_code_point));
9580
0
}
9581
9582
// We return "" on error.
9583
15.0k
static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9584
15.0k
  static const std::string error = "";
9585
  // copy and map
9586
  // we could be more efficient by avoiding the copy when unnecessary.
9587
15.0k
  std::string mapped_string = std::string(ut8_string);
9588
15.0k
  ascii_map(mapped_string.data(), mapped_string.size());
9589
15.0k
  std::string out;
9590
15.0k
  size_t label_start = 0;
9591
9592
44.9k
  while (label_start != mapped_string.size()) {
9593
30.7k
    size_t loc_dot = mapped_string.find('.', label_start);
9594
30.7k
    bool is_last_label = (loc_dot == std::string_view::npos);
9595
30.7k
    size_t label_size = is_last_label ? mapped_string.size() - label_start
9596
30.7k
                                      : loc_dot - label_start;
9597
30.7k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9598
30.7k
    std::string_view label_view(mapped_string.data() + label_start, label_size);
9599
30.7k
    label_start += label_size_with_dot;
9600
30.7k
    if (label_size == 0) {
9601
      // empty label? Nothing to do.
9602
26.1k
    } else if (begins_with(label_view, "xn--")) {
9603
      // The xn-- part is the expensive game.
9604
8.03k
      out.append(label_view);
9605
8.03k
      std::string_view puny_segment_ascii(
9606
8.03k
          out.data() + out.size() - label_view.size() + 4,
9607
8.03k
          label_view.size() - 4);
9608
8.03k
      std::u32string tmp_buffer;
9609
8.03k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9610
8.03k
      if (!is_ok) {
9611
208
        return error;
9612
208
      }
9613
7.82k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9614
7.82k
      if (tmp_buffer != post_map) {
9615
378
        return error;
9616
378
      }
9617
7.44k
      std::u32string pre_normal = post_map;
9618
7.44k
      normalize(post_map);
9619
7.44k
      if (post_map != pre_normal) {
9620
57
        return error;
9621
57
      }
9622
7.39k
      if (post_map.empty()) {
9623
134
        return error;
9624
134
      }
9625
7.25k
      if (!is_label_valid(post_map)) {
9626
27
        return error;
9627
27
      }
9628
18.1k
    } else {
9629
18.1k
      out.append(label_view);
9630
18.1k
    }
9631
29.9k
    if (!is_last_label) {
9632
17.6k
      out.push_back('.');
9633
17.6k
    }
9634
29.9k
  }
9635
14.2k
  return out;
9636
15.0k
}
9637
9638
// We return "" on error.
9639
24.8k
std::string to_ascii(std::string_view ut8_string) {
9640
24.8k
  if (is_ascii(ut8_string)) {
9641
15.0k
    return from_ascii_to_ascii(ut8_string);
9642
15.0k
  }
9643
9.77k
  static const std::string error = "";
9644
  // We convert to UTF-32
9645
9.77k
  size_t utf32_length =
9646
9.77k
      ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9647
9.77k
  std::u32string utf32(utf32_length, '\0');
9648
9.77k
  size_t actual_utf32_length = ada::idna::utf8_to_utf32(
9649
9.77k
      ut8_string.data(), ut8_string.size(), utf32.data());
9650
9.77k
  if (actual_utf32_length == 0) {
9651
3.02k
    return error;
9652
3.02k
  }
9653
  // mapping
9654
6.75k
  utf32 = ada::idna::map(utf32);
9655
6.75k
  normalize(utf32);
9656
6.75k
  std::string out;
9657
6.75k
  size_t label_start = 0;
9658
9659
39.7k
  while (label_start != utf32.size()) {
9660
34.2k
    size_t loc_dot = utf32.find('.', label_start);
9661
34.2k
    bool is_last_label = (loc_dot == std::string_view::npos);
9662
34.2k
    size_t label_size =
9663
34.2k
        is_last_label ? utf32.size() - label_start : loc_dot - label_start;
9664
34.2k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9665
34.2k
    std::u32string_view label_view(utf32.data() + label_start, label_size);
9666
34.2k
    label_start += label_size_with_dot;
9667
34.2k
    if (label_size == 0) {
9668
      // empty label? Nothing to do.
9669
30.6k
    } else if (begins_with(label_view, U"xn--")) {
9670
      // we do not need to check, e.g., Xn-- because mapping goes to lower case
9671
21.4k
      for (char32_t c : label_view) {
9672
21.4k
        if (c >= 0x80) {
9673
28
          return error;
9674
28
        }
9675
21.4k
        out += (unsigned char)(c);
9676
21.4k
      }
9677
2.01k
      std::string_view puny_segment_ascii(
9678
2.01k
          out.data() + out.size() - label_view.size() + 4,
9679
2.01k
          label_view.size() - 4);
9680
2.01k
      std::u32string tmp_buffer;
9681
2.01k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9682
2.01k
      if (!is_ok) {
9683
69
        return error;
9684
69
      }
9685
1.94k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9686
1.94k
      if (tmp_buffer != post_map) {
9687
70
        return error;
9688
70
      }
9689
1.87k
      std::u32string pre_normal = post_map;
9690
1.87k
      normalize(post_map);
9691
1.87k
      if (post_map != pre_normal) {
9692
36
        return error;
9693
36
      }
9694
1.83k
      if (post_map.empty()) {
9695
59
        return error;
9696
59
      }
9697
1.77k
      if (!is_label_valid(post_map)) {
9698
12
        return error;
9699
12
      }
9700
28.5k
    } else {
9701
      // The fast path here is an ascii label.
9702
28.5k
      if (is_ascii(label_view)) {
9703
        // no validation needed.
9704
21.6k
        for (char32_t c : label_view) {
9705
21.6k
          out += (unsigned char)(c);
9706
21.6k
        }
9707
25.4k
      } else {
9708
        // slow path.
9709
        // first check validity.
9710
25.4k
        if (!is_label_valid(label_view)) {
9711
961
          return error;
9712
961
        }
9713
        // It is valid! So now we must encode it as punycode...
9714
24.4k
        out.append("xn--");
9715
24.4k
        bool is_ok = ada::idna::utf32_to_punycode(label_view, out);
9716
24.4k
        if (!is_ok) {
9717
0
          return error;
9718
0
        }
9719
24.4k
      }
9720
28.5k
    }
9721
33.0k
    if (!is_last_label) {
9722
27.9k
      out.push_back('.');
9723
27.9k
    }
9724
33.0k
  }
9725
5.52k
  return out;
9726
6.75k
}
9727
}  // namespace ada::idna
9728
/* end file src/to_ascii.cpp */
9729
/* begin file src/to_unicode.cpp */
9730
9731
#include <algorithm>
9732
#include <string>
9733
9734
9735
namespace ada::idna {
9736
14.1k
std::string to_unicode(std::string_view input) {
9737
14.1k
  std::string output;
9738
14.1k
  output.reserve(input.size());
9739
9740
14.1k
  size_t label_start = 0;
9741
44.5k
  while (label_start < input.size()) {
9742
30.4k
    size_t loc_dot = input.find('.', label_start);
9743
30.4k
    bool is_last_label = (loc_dot == std::string_view::npos);
9744
30.4k
    size_t label_size =
9745
30.4k
        is_last_label ? input.size() - label_start : loc_dot - label_start;
9746
30.4k
    auto label_view = std::string_view(input.data() + label_start, label_size);
9747
9748
30.4k
    if (ada::idna::begins_with(label_view, "xn--") &&
9749
30.4k
        ada::idna::is_ascii(label_view)) {
9750
2.32k
      label_view.remove_prefix(4);
9751
2.32k
      if (ada::idna::verify_punycode(label_view)) {
9752
1.43k
        std::u32string tmp_buffer;
9753
1.43k
        if (ada::idna::punycode_to_utf32(label_view, tmp_buffer)) {
9754
1.43k
          auto utf8_size = ada::idna::utf8_length_from_utf32(tmp_buffer.data(),
9755
1.43k
                                                             tmp_buffer.size());
9756
1.43k
          std::string final_utf8(utf8_size, '\0');
9757
1.43k
          ada::idna::utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9758
1.43k
                                   final_utf8.data());
9759
1.43k
          output.append(final_utf8);
9760
1.43k
        } else {
9761
          // ToUnicode never fails.  If any step fails, then the original input
9762
          // sequence is returned immediately in that step.
9763
0
          output.append(
9764
0
              std::string_view(input.data() + label_start, label_size));
9765
0
        }
9766
1.43k
      } else {
9767
892
        output.append(std::string_view(input.data() + label_start, label_size));
9768
892
      }
9769
28.1k
    } else {
9770
28.1k
      output.append(label_view);
9771
28.1k
    }
9772
9773
30.4k
    if (!is_last_label) {
9774
18.2k
      output.push_back('.');
9775
18.2k
    }
9776
9777
30.4k
    label_start += label_size + 1;
9778
30.4k
  }
9779
9780
14.1k
  return output;
9781
14.1k
}
9782
}  // namespace ada::idna
9783
/* end file src/to_unicode.cpp */
9784
/* end file src/idna.cpp */
9785
/* end file src/ada_idna.cpp */
9786
ADA_POP_DISABLE_WARNINGS
9787
9788
#include <algorithm>
9789
#if ADA_NEON
9790
#include <arm_neon.h>
9791
#elif ADA_SSE2
9792
#include <emmintrin.h>
9793
#endif
9794
9795
namespace ada::unicode {
9796
9797
28.3k
constexpr bool to_lower_ascii(char* input, size_t length) noexcept {
9798
84.9k
  auto broadcast = [](uint8_t v) -> uint64_t {
9799
84.9k
    return 0x101010101010101ull * v;
9800
84.9k
  };
9801
28.3k
  uint64_t broadcast_80 = broadcast(0x80);
9802
28.3k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
9803
28.3k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
9804
28.3k
  uint64_t non_ascii = 0;
9805
28.3k
  size_t i = 0;
9806
9807
45.9k
  for (; i + 7 < length; i += 8) {
9808
17.6k
    uint64_t word{};
9809
17.6k
    memcpy(&word, input + i, sizeof(word));
9810
17.6k
    non_ascii |= (word & broadcast_80);
9811
17.6k
    word ^=
9812
17.6k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
9813
17.6k
    memcpy(input + i, &word, sizeof(word));
9814
17.6k
  }
9815
28.3k
  if (i < length) {
9816
27.7k
    uint64_t word{};
9817
27.7k
    memcpy(&word, input + i, length - i);
9818
27.7k
    non_ascii |= (word & broadcast_80);
9819
27.7k
    word ^=
9820
27.7k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
9821
27.7k
    memcpy(input + i, &word, length - i);
9822
27.7k
  }
9823
28.3k
  return non_ascii == 0;
9824
28.3k
}
9825
#if ADA_NEON
9826
ada_really_inline bool has_tabs_or_newline(
9827
    std::string_view user_input) noexcept {
9828
  size_t i = 0;
9829
  const uint8x16_t mask1 = vmovq_n_u8('\r');
9830
  const uint8x16_t mask2 = vmovq_n_u8('\n');
9831
  const uint8x16_t mask3 = vmovq_n_u8('\t');
9832
  uint8x16_t running{0};
9833
  for (; i + 15 < user_input.size(); i += 16) {
9834
    uint8x16_t word = vld1q_u8((const uint8_t*)user_input.data() + i);
9835
    running = vorrq_u8(vorrq_u8(running, vorrq_u8(vceqq_u8(word, mask1),
9836
                                                  vceqq_u8(word, mask2))),
9837
                       vceqq_u8(word, mask3));
9838
  }
9839
  if (i < user_input.size()) {
9840
    uint8_t buffer[16]{};
9841
    memcpy(buffer, user_input.data() + i, user_input.size() - i);
9842
    uint8x16_t word = vld1q_u8((const uint8_t*)user_input.data() + i);
9843
    running = vorrq_u8(vorrq_u8(running, vorrq_u8(vceqq_u8(word, mask1),
9844
                                                  vceqq_u8(word, mask2))),
9845
                       vceqq_u8(word, mask3));
9846
  }
9847
  return vmaxvq_u8(running) != 0;
9848
}
9849
#elif ADA_SSE2
9850
ada_really_inline bool has_tabs_or_newline(
9851
88.4k
    std::string_view user_input) noexcept {
9852
88.4k
  size_t i = 0;
9853
88.4k
  const __m128i mask1 = _mm_set1_epi8('\r');
9854
88.4k
  const __m128i mask2 = _mm_set1_epi8('\n');
9855
88.4k
  const __m128i mask3 = _mm_set1_epi8('\t');
9856
88.4k
  __m128i running{0};
9857
147k
  for (; i + 15 < user_input.size(); i += 16) {
9858
59.1k
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
9859
59.1k
    running = _mm_or_si128(
9860
59.1k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
9861
59.1k
                                           _mm_cmpeq_epi8(word, mask2))),
9862
59.1k
        _mm_cmpeq_epi8(word, mask3));
9863
59.1k
  }
9864
88.4k
  if (i < user_input.size()) {
9865
60.3k
    alignas(16) uint8_t buffer[16]{};
9866
60.3k
    memcpy(buffer, user_input.data() + i, user_input.size() - i);
9867
60.3k
    __m128i word = _mm_load_si128((const __m128i*)buffer);
9868
60.3k
    running = _mm_or_si128(
9869
60.3k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
9870
60.3k
                                           _mm_cmpeq_epi8(word, mask2))),
9871
60.3k
        _mm_cmpeq_epi8(word, mask3));
9872
60.3k
  }
9873
88.4k
  return _mm_movemask_epi8(running) != 0;
9874
88.4k
}
9875
#else
9876
ada_really_inline bool has_tabs_or_newline(
9877
    std::string_view user_input) noexcept {
9878
  auto has_zero_byte = [](uint64_t v) {
9879
    return ((v - 0x0101010101010101) & ~(v)&0x8080808080808080);
9880
  };
9881
  auto broadcast = [](uint8_t v) -> uint64_t {
9882
    return 0x101010101010101ull * v;
9883
  };
9884
  size_t i = 0;
9885
  uint64_t mask1 = broadcast('\r');
9886
  uint64_t mask2 = broadcast('\n');
9887
  uint64_t mask3 = broadcast('\t');
9888
  uint64_t running{0};
9889
  for (; i + 7 < user_input.size(); i += 8) {
9890
    uint64_t word{};
9891
    memcpy(&word, user_input.data() + i, sizeof(word));
9892
    uint64_t xor1 = word ^ mask1;
9893
    uint64_t xor2 = word ^ mask2;
9894
    uint64_t xor3 = word ^ mask3;
9895
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
9896
  }
9897
  if (i < user_input.size()) {
9898
    uint64_t word{};
9899
    memcpy(&word, user_input.data() + i, user_input.size() - i);
9900
    uint64_t xor1 = word ^ mask1;
9901
    uint64_t xor2 = word ^ mask2;
9902
    uint64_t xor3 = word ^ mask3;
9903
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
9904
  }
9905
  return running;
9906
}
9907
#endif
9908
9909
// A forbidden host code point is U+0000 NULL, U+0009 TAB, U+000A LF, U+000D CR,
9910
// U+0020 SPACE, U+0023 (#), U+002F (/), U+003A (:), U+003C (<), U+003E (>),
9911
// U+003F (?), U+0040 (@), U+005B ([), U+005C (\), U+005D (]), U+005E (^), or
9912
// U+007C (|).
9913
constexpr static bool is_forbidden_host_code_point_table[] = {
9914
    1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9915
    0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
9916
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
9917
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
9918
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9919
    0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9920
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9921
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9922
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9923
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9924
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
9925
static_assert(sizeof(is_forbidden_host_code_point_table) == 256);
9926
9927
ada_really_inline constexpr bool is_forbidden_host_code_point(
9928
33.1k
    const char c) noexcept {
9929
33.1k
  return is_forbidden_host_code_point_table[uint8_t(c)];
9930
33.1k
}
9931
9932
static_assert(unicode::is_forbidden_host_code_point('\0'));
9933
static_assert(unicode::is_forbidden_host_code_point('\t'));
9934
static_assert(unicode::is_forbidden_host_code_point('\n'));
9935
static_assert(unicode::is_forbidden_host_code_point('\r'));
9936
static_assert(unicode::is_forbidden_host_code_point(' '));
9937
static_assert(unicode::is_forbidden_host_code_point('#'));
9938
static_assert(unicode::is_forbidden_host_code_point('/'));
9939
static_assert(unicode::is_forbidden_host_code_point(':'));
9940
static_assert(unicode::is_forbidden_host_code_point('?'));
9941
static_assert(unicode::is_forbidden_host_code_point('@'));
9942
static_assert(unicode::is_forbidden_host_code_point('['));
9943
static_assert(unicode::is_forbidden_host_code_point('?'));
9944
static_assert(unicode::is_forbidden_host_code_point('<'));
9945
static_assert(unicode::is_forbidden_host_code_point('>'));
9946
static_assert(unicode::is_forbidden_host_code_point('\\'));
9947
static_assert(unicode::is_forbidden_host_code_point(']'));
9948
static_assert(unicode::is_forbidden_host_code_point('^'));
9949
static_assert(unicode::is_forbidden_host_code_point('|'));
9950
9951
constexpr static uint8_t is_forbidden_domain_code_point_table[] = {
9952
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9953
    1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
9954
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
9955
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
9956
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9957
    0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9958
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9959
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9960
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9961
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9962
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
9963
9964
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
9965
9966
ada_really_inline constexpr bool is_forbidden_domain_code_point(
9967
499k
    const char c) noexcept {
9968
499k
  return is_forbidden_domain_code_point_table[uint8_t(c)];
9969
499k
}
9970
9971
ada_really_inline constexpr bool contains_forbidden_domain_code_point(
9972
16.7k
    const char* input, size_t length) noexcept {
9973
16.7k
  size_t i = 0;
9974
16.7k
  uint8_t accumulator{};
9975
183k
  for (; i + 4 <= length; i += 4) {
9976
166k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
9977
166k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 1])];
9978
166k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 2])];
9979
166k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 3])];
9980
166k
  }
9981
41.6k
  for (; i < length; i++) {
9982
24.9k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
9983
24.9k
  }
9984
16.7k
  return accumulator;
9985
16.7k
}
9986
9987
constexpr static uint8_t is_forbidden_domain_code_point_table_or_upper[] = {
9988
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9989
    1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
9990
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
9991
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 0,
9992
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9993
    0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9994
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9995
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9996
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9997
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9998
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
9999
10000
static_assert(sizeof(is_forbidden_domain_code_point_table_or_upper) == 256);
10001
static_assert(is_forbidden_domain_code_point_table_or_upper[uint8_t('A')] == 2);
10002
static_assert(is_forbidden_domain_code_point_table_or_upper[uint8_t('Z')] == 2);
10003
10004
ada_really_inline constexpr uint8_t
10005
contains_forbidden_domain_code_point_or_upper(const char* input,
10006
15.4k
                                              size_t length) noexcept {
10007
15.4k
  size_t i = 0;
10008
15.4k
  uint8_t accumulator{};
10009
87.7k
  for (; i + 4 <= length; i += 4) {
10010
72.3k
    accumulator |=
10011
72.3k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10012
72.3k
    accumulator |=
10013
72.3k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 1])];
10014
72.3k
    accumulator |=
10015
72.3k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 2])];
10016
72.3k
    accumulator |=
10017
72.3k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 3])];
10018
72.3k
  }
10019
37.6k
  for (; i < length; i++) {
10020
22.1k
    accumulator |=
10021
22.1k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10022
22.1k
  }
10023
15.4k
  return accumulator;
10024
15.4k
}
10025
10026
static_assert(unicode::is_forbidden_domain_code_point('%'));
10027
static_assert(unicode::is_forbidden_domain_code_point('\x7f'));
10028
static_assert(unicode::is_forbidden_domain_code_point('\0'));
10029
static_assert(unicode::is_forbidden_domain_code_point('\t'));
10030
static_assert(unicode::is_forbidden_domain_code_point('\n'));
10031
static_assert(unicode::is_forbidden_domain_code_point('\r'));
10032
static_assert(unicode::is_forbidden_domain_code_point(' '));
10033
static_assert(unicode::is_forbidden_domain_code_point('#'));
10034
static_assert(unicode::is_forbidden_domain_code_point('/'));
10035
static_assert(unicode::is_forbidden_domain_code_point(':'));
10036
static_assert(unicode::is_forbidden_domain_code_point('?'));
10037
static_assert(unicode::is_forbidden_domain_code_point('@'));
10038
static_assert(unicode::is_forbidden_domain_code_point('['));
10039
static_assert(unicode::is_forbidden_domain_code_point('?'));
10040
static_assert(unicode::is_forbidden_domain_code_point('<'));
10041
static_assert(unicode::is_forbidden_domain_code_point('>'));
10042
static_assert(unicode::is_forbidden_domain_code_point('\\'));
10043
static_assert(unicode::is_forbidden_domain_code_point(']'));
10044
static_assert(unicode::is_forbidden_domain_code_point('^'));
10045
static_assert(unicode::is_forbidden_domain_code_point('|'));
10046
10047
constexpr static bool is_alnum_plus_table[] = {
10048
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10049
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0,
10050
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
10051
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
10052
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
10053
    1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10054
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10055
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10056
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10057
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10058
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
10059
10060
static_assert(sizeof(is_alnum_plus_table) == 256);
10061
10062
134k
ada_really_inline constexpr bool is_alnum_plus(const char c) noexcept {
10063
134k
  return is_alnum_plus_table[uint8_t(c)];
10064
  // A table is almost surely much faster than the
10065
  // following under most compilers: return
10066
  // return (std::isalnum(c) || c == '+' || c == '-' || c == '.');
10067
134k
}
10068
static_assert(unicode::is_alnum_plus('+'));
10069
static_assert(unicode::is_alnum_plus('-'));
10070
static_assert(unicode::is_alnum_plus('.'));
10071
static_assert(unicode::is_alnum_plus('0'));
10072
static_assert(unicode::is_alnum_plus('1'));
10073
static_assert(unicode::is_alnum_plus('a'));
10074
static_assert(unicode::is_alnum_plus('b'));
10075
10076
37.9k
ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept {
10077
37.9k
  return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
10078
37.9k
         (c >= 'a' && c <= 'f');
10079
37.9k
}
10080
10081
98.4k
ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept {
10082
98.4k
  return (unsigned char)c <= ' ';
10083
98.4k
}
10084
10085
ada_really_inline constexpr bool is_ascii_tab_or_newline(
10086
827k
    const char c) noexcept {
10087
827k
  return c == '\t' || c == '\n' || c == '\r';
10088
827k
}
10089
10090
constexpr std::string_view table_is_double_dot_path_segment[] = {
10091
    "..", "%2e.", ".%2e", "%2e%2e"};
10092
10093
ada_really_inline ada_constexpr bool is_double_dot_path_segment(
10094
71.6k
    std::string_view input) noexcept {
10095
  // This will catch most cases:
10096
  // The length must be 2,4 or 6.
10097
  // We divide by two and require
10098
  // that the result be between 1 and 3 inclusively.
10099
71.6k
  uint64_t half_length = uint64_t(input.size()) / 2;
10100
71.6k
  if (half_length - 1 > 2) {
10101
39.6k
    return false;
10102
39.6k
  }
10103
  // We have a string of length 2, 4 or 6.
10104
  // We now check the first character:
10105
31.9k
  if ((input[0] != '.') && (input[0] != '%')) {
10106
7.05k
    return false;
10107
7.05k
  }
10108
  // We are unlikely the get beyond this point.
10109
24.8k
  int hash_value = (input.size() + (unsigned)(input[0])) & 3;
10110
24.8k
  const std::string_view target = table_is_double_dot_path_segment[hash_value];
10111
24.8k
  if (target.size() != input.size()) {
10112
7.86k
    return false;
10113
7.86k
  }
10114
  // We almost never get here.
10115
  // Optimizing the rest is relatively unimportant.
10116
17.0k
  auto prefix_equal_unsafe = [](std::string_view a, std::string_view b) {
10117
17.0k
    uint16_t A, B;
10118
17.0k
    memcpy(&A, a.data(), sizeof(A));
10119
17.0k
    memcpy(&B, b.data(), sizeof(B));
10120
17.0k
    return A == B;
10121
17.0k
  };
10122
17.0k
  if (!prefix_equal_unsafe(input, target)) {
10123
1.58k
    return false;
10124
1.58k
  }
10125
21.7k
  for (size_t i = 2; i < input.size(); i++) {
10126
9.48k
    char c = input[i];
10127
9.48k
    if ((uint8_t((c | 0x20) - 0x61) <= 25 ? (c | 0x20) : c) != target[i]) {
10128
3.15k
      return false;
10129
3.15k
    }
10130
9.48k
  }
10131
12.2k
  return true;
10132
  // The above code might be a bit better than the code below. Compilers
10133
  // are not stupid and may use the fact that these strings have length 2,4 and
10134
  // 6 and other tricks.
10135
  // return input == ".." ||
10136
  //  input == ".%2e" || input == ".%2E" ||
10137
  //  input == "%2e." || input == "%2E." ||
10138
  //  input == "%2e%2e" || input == "%2E%2E" || input == "%2E%2e" || input ==
10139
  //  "%2e%2E";
10140
15.4k
}
10141
10142
ada_really_inline constexpr bool is_single_dot_path_segment(
10143
118k
    std::string_view input) noexcept {
10144
118k
  return input == "." || input == "%2e" || input == "%2E";
10145
118k
}
10146
10147
35.5k
ada_really_inline constexpr bool is_lowercase_hex(const char c) noexcept {
10148
35.5k
  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
10149
35.5k
}
10150
10151
34.1k
unsigned constexpr convert_hex_to_binary(const char c) noexcept {
10152
  // this code can be optimized.
10153
34.1k
  if (c <= '9') {
10154
17.0k
    return c - '0';
10155
17.0k
  }
10156
17.0k
  char del = c >= 'a' ? 'a' : 'A';
10157
17.0k
  return 10 + (c - del);
10158
34.1k
}
10159
10160
1.15k
std::string percent_decode(const std::string_view input, size_t first_percent) {
10161
  // next line is for safety only, we expect users to avoid calling
10162
  // percent_decode when first_percent is outside the range.
10163
1.15k
  if (first_percent == std::string_view::npos) {
10164
0
    return std::string(input);
10165
0
  }
10166
1.15k
  std::string dest(input.substr(0, first_percent));
10167
1.15k
  dest.reserve(input.length());
10168
1.15k
  const char* pointer = input.data() + first_percent;
10169
1.15k
  const char* end = input.data() + input.size();
10170
  // Optimization opportunity: if the following code gets
10171
  // called often, it can be optimized quite a bit.
10172
26.9k
  while (pointer < end) {
10173
25.7k
    const char ch = pointer[0];
10174
25.7k
    size_t remaining = end - pointer - 1;
10175
25.7k
    if (ch != '%' || remaining < 2 ||
10176
25.7k
        (  // ch == '%' && // It is unnecessary to check that ch == '%'.
10177
15.8k
            (!is_ascii_hex_digit(pointer[1]) ||
10178
15.8k
             !is_ascii_hex_digit(pointer[2])))) {
10179
11.1k
      dest += ch;
10180
11.1k
      pointer++;
10181
11.1k
      continue;
10182
14.6k
    } else {
10183
14.6k
      unsigned a = convert_hex_to_binary(pointer[1]);
10184
14.6k
      unsigned b = convert_hex_to_binary(pointer[2]);
10185
14.6k
      char c = static_cast<char>(a * 16 + b);
10186
14.6k
      dest += c;
10187
14.6k
      pointer += 3;
10188
14.6k
    }
10189
25.7k
  }
10190
1.15k
  return dest;
10191
1.15k
}
10192
10193
std::string percent_encode(const std::string_view input,
10194
30.2k
                           const uint8_t character_set[]) {
10195
30.2k
  auto pointer =
10196
152k
      std::find_if(input.begin(), input.end(), [character_set](const char c) {
10197
152k
        return character_sets::bit_at(character_set, c);
10198
152k
      });
10199
  // Optimization: Don't iterate if percent encode is not required
10200
30.2k
  if (pointer == input.end()) {
10201
21.9k
    return std::string(input);
10202
21.9k
  }
10203
10204
8.31k
  std::string result(input.substr(0, std::distance(input.begin(), pointer)));
10205
8.31k
  result.reserve(input.length());  // in the worst case, percent encoding might
10206
                                   // produce 3 characters.
10207
10208
237k
  for (; pointer != input.end(); pointer++) {
10209
229k
    if (character_sets::bit_at(character_set, *pointer)) {
10210
165k
      result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10211
165k
    } else {
10212
64.0k
      result += *pointer;
10213
64.0k
    }
10214
229k
  }
10215
10216
8.31k
  return result;
10217
30.2k
}
10218
10219
template <bool append>
10220
bool percent_encode(const std::string_view input, const uint8_t character_set[],
10221
43.1k
                    std::string& out) {
10222
43.1k
  ada_log("percent_encode ", input, " to output string while ",
10223
43.1k
          append ? "appending" : "overwriting");
10224
43.1k
  auto pointer =
10225
101k
      std::find_if(input.begin(), input.end(), [character_set](const char c) {
10226
101k
        return character_sets::bit_at(character_set, c);
10227
101k
      });
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
10225
70.2k
      std::find_if(input.begin(), input.end(), [character_set](const char c) {
10226
70.2k
        return character_sets::bit_at(character_set, c);
10227
70.2k
      });
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
10225
31.5k
      std::find_if(input.begin(), input.end(), [character_set](const char c) {
10226
31.5k
        return character_sets::bit_at(character_set, c);
10227
31.5k
      });
10228
43.1k
  ada_log("percent_encode done checking, moved to ",
10229
43.1k
          std::distance(input.begin(), pointer));
10230
10231
  // Optimization: Don't iterate if percent encode is not required
10232
43.1k
  if (pointer == input.end()) {
10233
24.8k
    ada_log("percent_encode encoding not needed.");
10234
24.8k
    return false;
10235
24.8k
  }
10236
18.3k
  if (!append) {
10237
16.8k
    out.clear();
10238
16.8k
  }
10239
18.3k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10240
18.3k
          " bytes");
10241
18.3k
  out.append(input.data(), std::distance(input.begin(), pointer));
10242
18.3k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10243
18.3k
          " bytes");
10244
274k
  for (; pointer != input.end(); pointer++) {
10245
256k
    if (character_sets::bit_at(character_set, *pointer)) {
10246
203k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10247
203k
    } else {
10248
52.9k
      out += *pointer;
10249
52.9k
    }
10250
256k
  }
10251
18.3k
  return true;
10252
43.1k
}
bool ada::unicode::percent_encode<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Line
Count
Source
10221
38.7k
                    std::string& out) {
10222
38.7k
  ada_log("percent_encode ", input, " to output string while ",
10223
38.7k
          append ? "appending" : "overwriting");
10224
38.7k
  auto pointer =
10225
38.7k
      std::find_if(input.begin(), input.end(), [character_set](const char c) {
10226
38.7k
        return character_sets::bit_at(character_set, c);
10227
38.7k
      });
10228
38.7k
  ada_log("percent_encode done checking, moved to ",
10229
38.7k
          std::distance(input.begin(), pointer));
10230
10231
  // Optimization: Don't iterate if percent encode is not required
10232
38.7k
  if (pointer == input.end()) {
10233
21.9k
    ada_log("percent_encode encoding not needed.");
10234
21.9k
    return false;
10235
21.9k
  }
10236
16.8k
  if (!append) {
10237
16.8k
    out.clear();
10238
16.8k
  }
10239
16.8k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10240
16.8k
          " bytes");
10241
16.8k
  out.append(input.data(), std::distance(input.begin(), pointer));
10242
16.8k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10243
16.8k
          " bytes");
10244
210k
  for (; pointer != input.end(); pointer++) {
10245
193k
    if (character_sets::bit_at(character_set, *pointer)) {
10246
156k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10247
156k
    } else {
10248
37.2k
      out += *pointer;
10249
37.2k
    }
10250
193k
  }
10251
16.8k
  return true;
10252
38.7k
}
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
10221
4.44k
                    std::string& out) {
10222
4.44k
  ada_log("percent_encode ", input, " to output string while ",
10223
4.44k
          append ? "appending" : "overwriting");
10224
4.44k
  auto pointer =
10225
4.44k
      std::find_if(input.begin(), input.end(), [character_set](const char c) {
10226
4.44k
        return character_sets::bit_at(character_set, c);
10227
4.44k
      });
10228
4.44k
  ada_log("percent_encode done checking, moved to ",
10229
4.44k
          std::distance(input.begin(), pointer));
10230
10231
  // Optimization: Don't iterate if percent encode is not required
10232
4.44k
  if (pointer == input.end()) {
10233
2.95k
    ada_log("percent_encode encoding not needed.");
10234
2.95k
    return false;
10235
2.95k
  }
10236
1.48k
  if (!append) {
10237
0
    out.clear();
10238
0
  }
10239
1.48k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10240
1.48k
          " bytes");
10241
1.48k
  out.append(input.data(), std::distance(input.begin(), pointer));
10242
1.48k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10243
1.48k
          " bytes");
10244
63.5k
  for (; pointer != input.end(); pointer++) {
10245
62.0k
    if (character_sets::bit_at(character_set, *pointer)) {
10246
46.3k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10247
46.3k
    } else {
10248
15.7k
      out += *pointer;
10249
15.7k
    }
10250
62.0k
  }
10251
1.48k
  return true;
10252
4.44k
}
10253
10254
bool to_ascii(std::optional<std::string>& out, const std::string_view plain,
10255
10.7k
              size_t first_percent) {
10256
10.7k
  std::string percent_decoded_buffer;
10257
10.7k
  std::string_view input = plain;
10258
10.7k
  if (first_percent != std::string_view::npos) {
10259
1.15k
    percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
10260
1.15k
    input = percent_decoded_buffer;
10261
1.15k
  }
10262
  // input is a non-empty UTF-8 string, must be percent decoded
10263
10.7k
  std::string idna_ascii = ada::idna::to_ascii(input);
10264
10.7k
  if (idna_ascii.empty() || contains_forbidden_domain_code_point(
10265
8.39k
                                idna_ascii.data(), idna_ascii.size())) {
10266
3.55k
    return false;
10267
3.55k
  }
10268
7.16k
  out = std::move(idna_ascii);
10269
7.16k
  return true;
10270
10.7k
}
10271
10272
std::string percent_encode(const std::string_view input,
10273
1.56k
                           const uint8_t character_set[], size_t index) {
10274
1.56k
  std::string out;
10275
1.56k
  out.append(input.data(), index);
10276
1.56k
  auto pointer = input.begin() + index;
10277
66.7k
  for (; pointer != input.end(); pointer++) {
10278
65.1k
    if (character_sets::bit_at(character_set, *pointer)) {
10279
55.5k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10280
55.5k
    } else {
10281
9.63k
      out += *pointer;
10282
9.63k
    }
10283
65.1k
  }
10284
1.56k
  return out;
10285
1.56k
}
10286
10287
0
std::string to_unicode(std::string_view input) {
10288
0
  return ada::idna::to_unicode(input);
10289
0
}
10290
10291
}  // namespace ada::unicode
10292
/* end file src/unicode.cpp */
10293
/* begin file src/serializers.cpp */
10294
10295
#include <array>
10296
#include <string>
10297
10298
namespace ada::serializers {
10299
10300
void find_longest_sequence_of_ipv6_pieces(
10301
    const std::array<uint16_t, 8>& address, size_t& compress,
10302
600
    size_t& compress_length) noexcept {
10303
2.33k
  for (size_t i = 0; i < 8; i++) {
10304
1.93k
    if (address[i] == 0) {
10305
751
      size_t next = i + 1;
10306
3.34k
      while (next != 8 && address[next] == 0) ++next;
10307
751
      const size_t count = next - i;
10308
751
      if (compress_length < count) {
10309
564
        compress_length = count;
10310
564
        compress = i;
10311
564
        if (next == 8) break;
10312
362
        i = next;
10313
362
      }
10314
751
    }
10315
1.93k
  }
10316
600
}
10317
10318
600
std::string ipv6(const std::array<uint16_t, 8>& address) noexcept {
10319
600
  size_t compress_length = 0;  // The length of a long sequence of zeros.
10320
600
  size_t compress = 0;         // The start of a long sequence of zeros.
10321
600
  find_longest_sequence_of_ipv6_pieces(address, compress, compress_length);
10322
10323
600
  if (compress_length <= 1) {
10324
    // Optimization opportunity: Find a faster way then snprintf for imploding
10325
    // and return here.
10326
112
    compress = compress_length = 8;
10327
112
  }
10328
10329
600
  std::string output(4 * 8 + 7 + 2, '\0');
10330
600
  size_t piece_index = 0;
10331
600
  char* point = output.data();
10332
600
  char* point_end = output.data() + output.size();
10333
600
  *point++ = '[';
10334
2.01k
  while (true) {
10335
2.01k
    if (piece_index == compress) {
10336
488
      *point++ = ':';
10337
      // If we skip a value initially, we need to write '::', otherwise
10338
      // a single ':' will do since it follows a previous ':'.
10339
488
      if (piece_index == 0) {
10340
301
        *point++ = ':';
10341
301
      }
10342
488
      piece_index += compress_length;
10343
488
      if (piece_index == 8) {
10344
198
        break;
10345
198
      }
10346
488
    }
10347
1.81k
    point = std::to_chars(point, point_end, address[piece_index], 16).ptr;
10348
1.81k
    piece_index++;
10349
1.81k
    if (piece_index == 8) {
10350
402
      break;
10351
402
    }
10352
1.41k
    *point++ = ':';
10353
1.41k
  }
10354
600
  *point++ = ']';
10355
600
  output.resize(point - output.data());
10356
600
  return output;
10357
600
}
10358
10359
4.37k
std::string ipv4(const uint64_t address) noexcept {
10360
4.37k
  std::string output(15, '\0');
10361
4.37k
  char* point = output.data();
10362
4.37k
  char* point_end = output.data() + output.size();
10363
4.37k
  point = std::to_chars(point, point_end, uint8_t(address >> 24)).ptr;
10364
17.4k
  for (int i = 2; i >= 0; i--) {
10365
13.1k
    *point++ = '.';
10366
13.1k
    point = std::to_chars(point, point_end, uint8_t(address >> (i * 8))).ptr;
10367
13.1k
  }
10368
4.37k
  output.resize(point - output.data());
10369
4.37k
  return output;
10370
4.37k
}
10371
10372
}  // namespace ada::serializers
10373
/* end file src/serializers.cpp */
10374
/* begin file src/implementation.cpp */
10375
#include <string_view>
10376
10377
10378
namespace ada {
10379
10380
template <class result_type>
10381
ada_warn_unused tl::expected<result_type, ada::errors> parse(
10382
59.9k
    std::string_view input, const result_type* base_url) {
10383
59.9k
  result_type u = ada::parser::parse_url<result_type>(input, base_url);
10384
59.9k
  if (!u.is_valid) {
10385
29.9k
    return tl::unexpected(errors::generic_error);
10386
29.9k
  }
10387
29.9k
  return u;
10388
59.9k
}
tl::expected<ada::url, ada::errors> ada::parse<ada::url>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url const*)
Line
Count
Source
10382
14.5k
    std::string_view input, const result_type* base_url) {
10383
14.5k
  result_type u = ada::parser::parse_url<result_type>(input, base_url);
10384
14.5k
  if (!u.is_valid) {
10385
6.10k
    return tl::unexpected(errors::generic_error);
10386
6.10k
  }
10387
8.40k
  return u;
10388
14.5k
}
tl::expected<ada::url_aggregator, ada::errors> ada::parse<ada::url_aggregator>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator const*)
Line
Count
Source
10382
45.4k
    std::string_view input, const result_type* base_url) {
10383
45.4k
  result_type u = ada::parser::parse_url<result_type>(input, base_url);
10384
45.4k
  if (!u.is_valid) {
10385
23.8k
    return tl::unexpected(errors::generic_error);
10386
23.8k
  }
10387
21.5k
  return u;
10388
45.4k
}
10389
10390
template ada::result<url> parse<url>(std::string_view input,
10391
                                     const url* base_url = nullptr);
10392
template ada::result<url_aggregator> parse<url_aggregator>(
10393
    std::string_view input, const url_aggregator* base_url = nullptr);
10394
10395
14.1k
std::string href_from_file(std::string_view input) {
10396
  // This is going to be much faster than constructing a URL.
10397
14.1k
  std::string tmp_buffer;
10398
14.1k
  std::string_view internal_input;
10399
14.1k
  if (unicode::has_tabs_or_newline(input)) {
10400
202
    tmp_buffer = input;
10401
202
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
10402
202
    internal_input = tmp_buffer;
10403
13.9k
  } else {
10404
13.9k
    internal_input = input;
10405
13.9k
  }
10406
14.1k
  std::string path;
10407
14.1k
  if (internal_input.empty()) {
10408
969
    path = "/";
10409
13.1k
  } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
10410
776
    helpers::parse_prepared_path(internal_input.substr(1),
10411
776
                                 ada::scheme::type::FILE, path);
10412
12.3k
  } else {
10413
12.3k
    helpers::parse_prepared_path(internal_input, ada::scheme::type::FILE, path);
10414
12.3k
  }
10415
14.1k
  return "file://" + path;
10416
14.1k
}
10417
10418
28.2k
bool can_parse(std::string_view input, const std::string_view* base_input) {
10419
28.2k
  ada::result<ada::url_aggregator> base;
10420
28.2k
  ada::url_aggregator* base_pointer = nullptr;
10421
28.2k
  if (base_input != nullptr) {
10422
14.1k
    base = ada::parse<url_aggregator>(*base_input);
10423
14.1k
    if (!base) {
10424
11.4k
      return false;
10425
11.4k
    }
10426
2.66k
    base_pointer = &base.value();
10427
2.66k
  }
10428
16.7k
  return ada::parse<url_aggregator>(input, base_pointer).has_value();
10429
28.2k
}
10430
10431
0
ada_warn_unused std::string to_string(ada::encoding_type type) {
10432
0
  switch (type) {
10433
0
    case ada::encoding_type::UTF8:
10434
0
      return "UTF-8";
10435
0
    case ada::encoding_type::UTF_16LE:
10436
0
      return "UTF-16LE";
10437
0
    case ada::encoding_type::UTF_16BE:
10438
0
      return "UTF-16BE";
10439
0
    default:
10440
0
      unreachable();
10441
0
  }
10442
0
}
10443
10444
}  // namespace ada
10445
/* end file src/implementation.cpp */
10446
/* begin file src/helpers.cpp */
10447
10448
#include <algorithm>
10449
#include <charconv>
10450
#include <cstring>
10451
#include <sstream>
10452
10453
namespace ada::helpers {
10454
10455
template <typename out_iter>
10456
0
void encode_json(std::string_view view, out_iter out) {
10457
  // trivial implementation. could be faster.
10458
0
  const char* hexvalues =
10459
0
      "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
10460
0
  for (uint8_t c : view) {
10461
0
    if (c == '\\') {
10462
0
      *out++ = '\\';
10463
0
      *out++ = '\\';
10464
0
    } else if (c == '"') {
10465
0
      *out++ = '\\';
10466
0
      *out++ = '"';
10467
0
    } else if (c <= 0x1f) {
10468
0
      *out++ = '\\';
10469
0
      *out++ = 'u';
10470
0
      *out++ = '0';
10471
0
      *out++ = '0';
10472
0
      *out++ = hexvalues[2 * c];
10473
0
      *out++ = hexvalues[2 * c + 1];
10474
0
    } else {
10475
0
      *out++ = c;
10476
0
    }
10477
0
  }
10478
0
}
10479
10480
0
ada_unused std::string get_state(ada::state s) {
10481
0
  switch (s) {
10482
0
    case ada::state::AUTHORITY:
10483
0
      return "Authority";
10484
0
    case ada::state::SCHEME_START:
10485
0
      return "Scheme Start";
10486
0
    case ada::state::SCHEME:
10487
0
      return "Scheme";
10488
0
    case ada::state::HOST:
10489
0
      return "Host";
10490
0
    case ada::state::NO_SCHEME:
10491
0
      return "No Scheme";
10492
0
    case ada::state::FRAGMENT:
10493
0
      return "Fragment";
10494
0
    case ada::state::RELATIVE_SCHEME:
10495
0
      return "Relative Scheme";
10496
0
    case ada::state::RELATIVE_SLASH:
10497
0
      return "Relative Slash";
10498
0
    case ada::state::FILE:
10499
0
      return "File";
10500
0
    case ada::state::FILE_HOST:
10501
0
      return "File Host";
10502
0
    case ada::state::FILE_SLASH:
10503
0
      return "File Slash";
10504
0
    case ada::state::PATH_OR_AUTHORITY:
10505
0
      return "Path or Authority";
10506
0
    case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES:
10507
0
      return "Special Authority Ignore Slashes";
10508
0
    case ada::state::SPECIAL_AUTHORITY_SLASHES:
10509
0
      return "Special Authority Slashes";
10510
0
    case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY:
10511
0
      return "Special Relative or Authority";
10512
0
    case ada::state::QUERY:
10513
0
      return "Query";
10514
0
    case ada::state::PATH:
10515
0
      return "Path";
10516
0
    case ada::state::PATH_START:
10517
0
      return "Path Start";
10518
0
    case ada::state::OPAQUE_PATH:
10519
0
      return "Opaque Path";
10520
0
    case ada::state::PORT:
10521
0
      return "Port";
10522
0
    default:
10523
0
      return "unknown state";
10524
0
  }
10525
0
}
10526
10527
ada_really_inline std::optional<std::string_view> prune_hash(
10528
59.9k
    std::string_view& input) noexcept {
10529
  // compiles down to 20--30 instructions including a class to memchr (C
10530
  // function). this function should be quite fast.
10531
59.9k
  size_t location_of_first = input.find('#');
10532
59.9k
  if (location_of_first == std::string_view::npos) {
10533
58.5k
    return std::nullopt;
10534
58.5k
  }
10535
1.32k
  std::string_view hash = input;
10536
1.32k
  hash.remove_prefix(location_of_first + 1);
10537
1.32k
  input.remove_suffix(input.size() - location_of_first);
10538
1.32k
  return hash;
10539
59.9k
}
10540
10541
ada_really_inline bool shorten_path(std::string& path,
10542
12.2k
                                    ada::scheme::type type) noexcept {
10543
12.2k
  size_t first_delimiter = path.find_first_of('/', 1);
10544
10545
  // Let path be url’s path.
10546
  // If url’s scheme is "file", path’s size is 1, and path[0] is a normalized
10547
  // Windows drive letter, then return.
10548
12.2k
  if (type == ada::scheme::type::FILE &&
10549
12.2k
      first_delimiter == std::string_view::npos && !path.empty()) {
10550
5.97k
    if (checkers::is_normalized_windows_drive_letter(
10551
5.97k
            helpers::substring(path, 1))) {
10552
1.64k
      return false;
10553
1.64k
    }
10554
5.97k
  }
10555
10556
  // Remove path’s last item, if any.
10557
10.6k
  size_t last_delimiter = path.rfind('/');
10558
10.6k
  if (last_delimiter != std::string::npos) {
10559
6.16k
    path.erase(last_delimiter);
10560
6.16k
    return true;
10561
6.16k
  }
10562
10563
4.47k
  return false;
10564
10.6k
}
10565
10566
ada_really_inline bool shorten_path(std::string_view& path,
10567
326
                                    ada::scheme::type type) noexcept {
10568
326
  size_t first_delimiter = path.find_first_of('/', 1);
10569
10570
  // Let path be url’s path.
10571
  // If url’s scheme is "file", path’s size is 1, and path[0] is a normalized
10572
  // Windows drive letter, then return.
10573
326
  if (type == ada::scheme::type::FILE &&
10574
326
      first_delimiter == std::string_view::npos && !path.empty()) {
10575
75
    if (checkers::is_normalized_windows_drive_letter(
10576
75
            helpers::substring(path, 1))) {
10577
8
      return false;
10578
8
    }
10579
75
  }
10580
10581
  // Remove path’s last item, if any.
10582
318
  if (!path.empty()) {
10583
308
    size_t slash_loc = path.rfind('/');
10584
308
    if (slash_loc != std::string_view::npos) {
10585
282
      path.remove_suffix(path.size() - slash_loc);
10586
282
      return true;
10587
282
    }
10588
308
  }
10589
10590
36
  return false;
10591
318
}
10592
10593
ada_really_inline void remove_ascii_tab_or_newline(
10594
66.0k
    std::string& input) noexcept {
10595
  // if this ever becomes a performance issue, we could use an approach similar
10596
  // to has_tabs_or_newline
10597
66.0k
  input.erase(std::remove_if(input.begin(), input.end(),
10598
827k
                             [](char c) {
10599
827k
                               return ada::unicode::is_ascii_tab_or_newline(c);
10600
827k
                             }),
10601
66.0k
              input.end());
10602
66.0k
}
10603
10604
ada_really_inline std::string_view substring(std::string_view input,
10605
82.4k
                                             size_t pos) noexcept {
10606
82.4k
  ADA_ASSERT_TRUE(pos <= input.size());
10607
  // The following is safer but unneeded if we have the above line:
10608
  // return pos > input.size() ? std::string_view() : input.substr(pos);
10609
82.4k
  return input.substr(pos);
10610
82.4k
}
10611
10612
12
ada_really_inline void resize(std::string_view& input, size_t pos) noexcept {
10613
12
  ADA_ASSERT_TRUE(pos <= input.size());
10614
12
  input.remove_suffix(input.size() - pos);
10615
12
}
10616
10617
// Reverse the byte order.
10618
0
ada_really_inline uint64_t swap_bytes(uint64_t val) noexcept {
10619
0
  // performance: this often compiles to a single instruction (e.g., bswap)
10620
0
  return ((((val)&0xff00000000000000ull) >> 56) |
10621
0
          (((val)&0x00ff000000000000ull) >> 40) |
10622
0
          (((val)&0x0000ff0000000000ull) >> 24) |
10623
0
          (((val)&0x000000ff00000000ull) >> 8) |
10624
0
          (((val)&0x00000000ff000000ull) << 8) |
10625
0
          (((val)&0x0000000000ff0000ull) << 24) |
10626
0
          (((val)&0x000000000000ff00ull) << 40) |
10627
0
          (((val)&0x00000000000000ffull) << 56));
10628
0
}
10629
10630
88.7k
ada_really_inline uint64_t swap_bytes_if_big_endian(uint64_t val) noexcept {
10631
  // performance: under little-endian systems (most systems), this function
10632
  // is free (just returns the input).
10633
#if ADA_IS_BIG_ENDIAN
10634
  return swap_bytes(val);
10635
#else
10636
88.7k
  return val;  // unchanged (trivial)
10637
88.7k
#endif
10638
88.7k
}
10639
10640
// starting at index location, this finds the next location of a character
10641
// :, /, \\, ? or [. If none is found, view.size() is returned.
10642
// For use within get_host_delimiter_location.
10643
ada_really_inline size_t find_next_host_delimiter_special(
10644
39.4k
    std::string_view view, size_t location) noexcept {
10645
  // performance: if you plan to call find_next_host_delimiter more than once,
10646
  // you *really* want find_next_host_delimiter to be inlined, because
10647
  // otherwise, the constants may get reloaded each time (bad).
10648
307k
  auto has_zero_byte = [](uint64_t v) {
10649
307k
    return ((v - 0x0101010101010101) & ~(v)&0x8080808080808080);
10650
307k
  };
10651
39.4k
  auto index_of_first_set_byte = [](uint64_t v) {
10652
10.8k
    return ((((v - 1) & 0x101010101010101) * 0x101010101010101) >> 56) - 1;
10653
10.8k
  };
10654
197k
  auto broadcast = [](uint8_t v) -> uint64_t {
10655
197k
    return 0x101010101010101ull * v;
10656
197k
  };
10657
39.4k
  size_t i = location;
10658
39.4k
  uint64_t mask1 = broadcast(':');
10659
39.4k
  uint64_t mask2 = broadcast('/');
10660
39.4k
  uint64_t mask3 = broadcast('\\');
10661
39.4k
  uint64_t mask4 = broadcast('?');
10662
39.4k
  uint64_t mask5 = broadcast('[');
10663
  // This loop will get autovectorized under many optimizing compilers,
10664
  // so you get actually SIMD!
10665
74.3k
  for (; i + 7 < view.size(); i += 8) {
10666
40.4k
    uint64_t word{};
10667
    // performance: the next memcpy translates into a single CPU instruction.
10668
40.4k
    memcpy(&word, view.data() + i, sizeof(word));
10669
    // performance: on little-endian systems (most systems), this next line is
10670
    // free.
10671
40.4k
    word = swap_bytes_if_big_endian(word);
10672
40.4k
    uint64_t xor1 = word ^ mask1;
10673
40.4k
    uint64_t xor2 = word ^ mask2;
10674
40.4k
    uint64_t xor3 = word ^ mask3;
10675
40.4k
    uint64_t xor4 = word ^ mask4;
10676
40.4k
    uint64_t xor5 = word ^ mask5;
10677
40.4k
    uint64_t is_match = has_zero_byte(xor1) | has_zero_byte(xor2) |
10678
40.4k
                        has_zero_byte(xor3) | has_zero_byte(xor4) |
10679
40.4k
                        has_zero_byte(xor5);
10680
40.4k
    if (is_match) {
10681
5.61k
      return size_t(i + index_of_first_set_byte(is_match));
10682
5.61k
    }
10683
40.4k
  }
10684
33.8k
  if (i < view.size()) {
10685
21.0k
    uint64_t word{};
10686
    // performance: the next memcpy translates into a function call, but
10687
    // that is difficult to avoid. Might be a bit expensive.
10688
21.0k
    memcpy(&word, view.data() + i, view.size() - i);
10689
21.0k
    word = swap_bytes_if_big_endian(word);
10690
21.0k
    uint64_t xor1 = word ^ mask1;
10691
21.0k
    uint64_t xor2 = word ^ mask2;
10692
21.0k
    uint64_t xor3 = word ^ mask3;
10693
21.0k
    uint64_t xor4 = word ^ mask4;
10694
21.0k
    uint64_t xor5 = word ^ mask5;
10695
21.0k
    uint64_t is_match = has_zero_byte(xor1) | has_zero_byte(xor2) |
10696
21.0k
                        has_zero_byte(xor3) | has_zero_byte(xor4) |
10697
21.0k
                        has_zero_byte(xor5);
10698
21.0k
    if (is_match) {
10699
5.24k
      return size_t(i + index_of_first_set_byte(is_match));
10700
5.24k
    }
10701
21.0k
  }
10702
28.6k
  return view.size();
10703
33.8k
}
10704
10705
// starting at index location, this finds the next location of a character
10706
// :, /, ? or [. If none is found, view.size() is returned.
10707
// For use within get_host_delimiter_location.
10708
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
10709
11.3k
                                                  size_t location) noexcept {
10710
  // performance: if you plan to call find_next_host_delimiter more than once,
10711
  // you *really* want find_next_host_delimiter to be inlined, because
10712
  // otherwise, the constants may get reloaded each time (bad).
10713
47.1k
  auto has_zero_byte = [](uint64_t v) {
10714
47.1k
    return ((v - 0x0101010101010101) & ~(v)&0x8080808080808080);
10715
47.1k
  };
10716
11.3k
  auto index_of_first_set_byte = [](uint64_t v) {
10717
5.14k
    return ((((v - 1) & 0x101010101010101) * 0x101010101010101) >> 56) - 1;
10718
5.14k
  };
10719
45.2k
  auto broadcast = [](uint8_t v) -> uint64_t {
10720
45.2k
    return 0x101010101010101ull * v;
10721
45.2k
  };
10722
11.3k
  size_t i = location;
10723
11.3k
  uint64_t mask1 = broadcast(':');
10724
11.3k
  uint64_t mask2 = broadcast('/');
10725
11.3k
  uint64_t mask4 = broadcast('?');
10726
11.3k
  uint64_t mask5 = broadcast('[');
10727
  // This loop will get autovectorized under many optimizing compilers,
10728
  // so you get actually SIMD!
10729
16.6k
  for (; i + 7 < view.size(); i += 8) {
10730
8.93k
    uint64_t word{};
10731
    // performance: the next memcpy translates into a single CPU instruction.
10732
8.93k
    memcpy(&word, view.data() + i, sizeof(word));
10733
    // performance: on little-endian systems (most systems), this next line is
10734
    // free.
10735
8.93k
    word = swap_bytes_if_big_endian(word);
10736
8.93k
    uint64_t xor1 = word ^ mask1;
10737
8.93k
    uint64_t xor2 = word ^ mask2;
10738
8.93k
    uint64_t xor4 = word ^ mask4;
10739
8.93k
    uint64_t xor5 = word ^ mask5;
10740
8.93k
    uint64_t is_match = has_zero_byte(xor1) | has_zero_byte(xor2) |
10741
8.93k
                        has_zero_byte(xor4) | has_zero_byte(xor5);
10742
8.93k
    if (is_match) {
10743
3.62k
      return size_t(i + index_of_first_set_byte(is_match));
10744
3.62k
    }
10745
8.93k
  }
10746
7.68k
  if (i < view.size()) {
10747
2.85k
    uint64_t word{};
10748
    // performance: the next memcpy translates into a function call, but
10749
    // that is difficult to avoid. Might be a bit expensive.
10750
2.85k
    memcpy(&word, view.data() + i, view.size() - i);
10751
    // performance: on little-endian systems (most systems), this next line is
10752
    // free.
10753
2.85k
    word = swap_bytes_if_big_endian(word);
10754
2.85k
    uint64_t xor1 = word ^ mask1;
10755
2.85k
    uint64_t xor2 = word ^ mask2;
10756
2.85k
    uint64_t xor4 = word ^ mask4;
10757
2.85k
    uint64_t xor5 = word ^ mask5;
10758
2.85k
    uint64_t is_match = has_zero_byte(xor1) | has_zero_byte(xor2) |
10759
2.85k
                        has_zero_byte(xor4) | has_zero_byte(xor5);
10760
2.85k
    if (is_match) {
10761
1.52k
      return size_t(i + index_of_first_set_byte(is_match));
10762
1.52k
    }
10763
2.85k
  }
10764
6.16k
  return view.size();
10765
7.68k
}
10766
10767
ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
10768
42.5k
    const bool is_special, std::string_view& view) noexcept {
10769
  /**
10770
   * The spec at https://url.spec.whatwg.org/#hostname-state expects us to
10771
   * compute a variable called insideBrackets but this variable is only used
10772
   * once, to check whether a ':' character was found outside brackets. Exact
10773
   * text: "Otherwise, if c is U+003A (:) and insideBrackets is false, then:".
10774
   * It is conceptually simpler and arguably more efficient to just return a
10775
   * Boolean indicating whether ':' was found outside brackets.
10776
   */
10777
42.5k
  const size_t view_size = view.size();
10778
42.5k
  size_t location = 0;
10779
42.5k
  bool found_colon = false;
10780
  /**
10781
   * Performance analysis:
10782
   *
10783
   * We are basically seeking the end of the hostname which can be indicated
10784
   * by the end of the view, or by one of the characters ':', '/', '?', '\\'
10785
   * (where '\\' is only applicable for special URLs). However, these must
10786
   * appear outside a bracket range. E.g., if you have [something?]fd: then the
10787
   * '?' does not count.
10788
   *
10789
   * So we can skip ahead to the next delimiter, as long as we include '[' in
10790
   * the set of delimiters, and that we handle it first.
10791
   *
10792
   * So the trick is to have a fast function that locates the next delimiter.
10793
   * Unless we find '[', then it only needs to be called once! Ideally, such a
10794
   * function would be provided by the C++ standard library, but it seems that
10795
   * find_first_of is not very fast, so we are forced to roll our own.
10796
   *
10797
   * We do not break into two loops for speed, but for clarity.
10798
   */
10799
42.5k
  if (is_special) {
10800
    // We move to the next delimiter.
10801
34.5k
    location = find_next_host_delimiter_special(view, location);
10802
    // Unless we find '[' then we are going only going to have to call
10803
    // find_next_host_delimiter_special once.
10804
39.4k
    for (; location < view_size;
10805
34.5k
         location = find_next_host_delimiter_special(view, location)) {
10806
10.8k
      if (view[location] == '[') {
10807
5.24k
        location = view.find(']', location);
10808
5.24k
        if (location == std::string_view::npos) {
10809
          // performance: view.find might get translated to a memchr, which
10810
          // has no notion of std::string_view::npos, so the code does not
10811
          // reflect the assembly.
10812
308
          location = view_size;
10813
308
          break;
10814
308
        }
10815
5.61k
      } else {
10816
5.61k
        found_colon = view[location] == ':';
10817
5.61k
        break;
10818
5.61k
      }
10819
10.8k
    }
10820
34.5k
  } else {
10821
    // We move to the next delimiter.
10822
7.95k
    location = find_next_host_delimiter(view, location);
10823
    // Unless we find '[' then we are going only going to have to call
10824
    // find_next_host_delimiter_special once.
10825
11.3k
    for (; location < view_size;
10826
7.95k
         location = find_next_host_delimiter(view, location)) {
10827
5.14k
      if (view[location] == '[') {
10828
3.53k
        location = view.find(']', location);
10829
3.53k
        if (location == std::string_view::npos) {
10830
          // performance: view.find might get translated to a memchr, which
10831
          // has no notion of std::string_view::npos, so the code does not
10832
          // reflect the assembly.
10833
186
          location = view_size;
10834
186
          break;
10835
186
        }
10836
3.53k
      } else {
10837
1.60k
        found_colon = view[location] == ':';
10838
1.60k
        break;
10839
1.60k
      }
10840
5.14k
    }
10841
7.95k
  }
10842
  // performance: remove_suffix may translate into a single instruction.
10843
42.5k
  view.remove_suffix(view_size - location);
10844
42.5k
  return {location, found_colon};
10845
42.5k
}
10846
10847
59.9k
ada_really_inline void trim_c0_whitespace(std::string_view& input) noexcept {
10848
63.2k
  while (!input.empty() &&
10849
63.2k
         ada::unicode::is_c0_control_or_space(input.front())) {
10850
3.36k
    input.remove_prefix(1);
10851
3.36k
  }
10852
62.1k
  while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
10853
2.27k
    input.remove_suffix(1);
10854
2.27k
  }
10855
59.9k
}
10856
10857
ada_really_inline void parse_prepared_path(std::string_view input,
10858
                                           ada::scheme::type type,
10859
19.0k
                                           std::string& path) {
10860
19.0k
  ada_log("parse_prepared_path ", input);
10861
19.0k
  uint8_t accumulator = checkers::path_signature(input);
10862
  // Let us first detect a trivial case.
10863
  // If it is special, we check that we have no dot, no %,  no \ and no
10864
  // character needing percent encoding. Otherwise, we check that we have no %,
10865
  // no dot, and no character needing percent encoding.
10866
19.0k
  constexpr uint8_t need_encoding = 1;
10867
19.0k
  constexpr uint8_t backslash_char = 2;
10868
19.0k
  constexpr uint8_t dot_char = 4;
10869
19.0k
  constexpr uint8_t percent_char = 8;
10870
19.0k
  bool special = type != ada::scheme::NOT_SPECIAL;
10871
19.0k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
10872
19.0k
                                      checkers::is_windows_drive_letter(input));
10873
19.0k
  bool trivial_path =
10874
19.0k
      (special ? (accumulator == 0)
10875
19.0k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
10876
2.27k
                  0)) &&
10877
19.0k
      (!may_need_slow_file_handling);
10878
19.0k
  if (accumulator == dot_char && !may_need_slow_file_handling) {
10879
    // '4' means that we have at least one dot, but nothing that requires
10880
    // percent encoding or decoding. The only part that is not trivial is
10881
    // that we may have single dots and double dots path segments.
10882
    // If we have such segments, then we either have a path that begins
10883
    // with '.' (easy to check), or we have the sequence './'.
10884
    // Note: input cannot be empty, it must at least contain one character ('.')
10885
    // Note: we know that '\' is not present.
10886
2.62k
    if (input[0] != '.') {
10887
2.04k
      size_t slashdot = input.find("/.");
10888
2.04k
      if (slashdot == std::string_view::npos) {  // common case
10889
1.23k
        trivial_path = true;
10890
1.23k
      } else {  // uncommon
10891
        // only three cases matter: /./, /.. or a final /
10892
811
        trivial_path =
10893
811
            !(slashdot + 2 == input.size() || input[slashdot + 2] == '.' ||
10894
811
              input[slashdot + 2] == '/');
10895
811
      }
10896
2.04k
    }
10897
2.62k
  }
10898
19.0k
  if (trivial_path) {
10899
8.48k
    ada_log("parse_path trivial");
10900
8.48k
    path += '/';
10901
8.48k
    path += input;
10902
8.48k
    return;
10903
8.48k
  }
10904
  // We are going to need to look a bit at the path, but let us see if we can
10905
  // ignore percent encoding *and* backslashes *and* percent characters.
10906
  // Except for the trivial case, this is likely to capture 99% of paths out
10907
  // there.
10908
10.5k
  bool fast_path =
10909
10.5k
      (special &&
10910
10.5k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
10911
10.5k
      (type != ada::scheme::type::FILE);
10912
10.5k
  if (fast_path) {
10913
500
    ada_log("parse_prepared_path fast");
10914
    // Here we don't need to worry about \ or percent encoding.
10915
    // We also do not have a file protocol. We might have dots, however,
10916
    // but dots must as appear as '.', and they cannot be encoded because
10917
    // the symbol '%' is not present.
10918
500
    size_t previous_location = 0;  // We start at 0.
10919
4.89k
    do {
10920
4.89k
      size_t new_location = input.find('/', previous_location);
10921
      // std::string_view path_view = input;
10922
      //  We process the last segment separately:
10923
4.89k
      if (new_location == std::string_view::npos) {
10924
500
        std::string_view path_view = input.substr(previous_location);
10925
500
        if (path_view == "..") {  // The path ends with ..
10926
          // e.g., if you receive ".." with an empty path, you go to "/".
10927
32
          if (path.empty()) {
10928
12
            path = '/';
10929
12
            return;
10930
12
          }
10931
          // Fast case where we have nothing to do:
10932
20
          if (path.back() == '/') {
10933
9
            return;
10934
9
          }
10935
          // If you have the path "/joe/myfriend",
10936
          // then you delete 'myfriend'.
10937
11
          path.resize(path.rfind('/') + 1);
10938
11
          return;
10939
20
        }
10940
468
        path += '/';
10941
468
        if (path_view != ".") {
10942
323
          path.append(path_view);
10943
323
        }
10944
468
        return;
10945
4.39k
      } else {
10946
        // This is a non-final segment.
10947
4.39k
        std::string_view path_view =
10948
4.39k
            input.substr(previous_location, new_location - previous_location);
10949
4.39k
        previous_location = new_location + 1;
10950
4.39k
        if (path_view == "..") {
10951
620
          size_t last_delimiter = path.rfind('/');
10952
620
          if (last_delimiter != std::string::npos) {
10953
334
            path.erase(last_delimiter);
10954
334
          }
10955
3.77k
        } else if (path_view != ".") {
10956
3.23k
          path += '/';
10957
3.23k
          path.append(path_view);
10958
3.23k
        }
10959
4.39k
      }
10960
4.89k
    } while (true);
10961
10.0k
  } else {
10962
10.0k
    ada_log("parse_path slow");
10963
    // we have reached the general case
10964
10.0k
    bool needs_percent_encoding = (accumulator & 1);
10965
10.0k
    std::string path_buffer_tmp;
10966
51.2k
    do {
10967
51.2k
      size_t location = (special && (accumulator & 2))
10968
51.2k
                            ? input.find_first_of("/\\")
10969
51.2k
                            : input.find('/');
10970
51.2k
      std::string_view path_view = input;
10971
51.2k
      if (location != std::string_view::npos) {
10972
41.2k
        path_view.remove_suffix(path_view.size() - location);
10973
41.2k
        input.remove_prefix(location + 1);
10974
41.2k
      }
10975
      // path_buffer is either path_view or it might point at a percent encoded
10976
      // temporary file.
10977
51.2k
      std::string_view path_buffer =
10978
51.2k
          (needs_percent_encoding &&
10979
51.2k
           ada::unicode::percent_encode<false>(
10980
26.8k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
10981
51.2k
              ? path_buffer_tmp
10982
51.2k
              : path_view;
10983
51.2k
      if (unicode::is_double_dot_path_segment(path_buffer)) {
10984
7.75k
        if ((helpers::shorten_path(path, type) || special) &&
10985
7.75k
            location == std::string_view::npos) {
10986
623
          path += '/';
10987
623
        }
10988
43.4k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
10989
43.4k
                 (location == std::string_view::npos)) {
10990
315
        path += '/';
10991
315
      }
10992
      // Otherwise, if path_buffer is not a single-dot path segment, then:
10993
43.1k
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
10994
        // If url’s scheme is "file", url’s path is empty, and path_buffer is a
10995
        // Windows drive letter, then replace the second code point in
10996
        // path_buffer with U+003A (:).
10997
39.3k
        if (type == ada::scheme::type::FILE && path.empty() &&
10998
39.3k
            checkers::is_windows_drive_letter(path_buffer)) {
10999
2.15k
          path += '/';
11000
2.15k
          path += path_buffer[0];
11001
2.15k
          path += ':';
11002
2.15k
          path_buffer.remove_prefix(2);
11003
2.15k
          path.append(path_buffer);
11004
37.1k
        } else {
11005
          // Append path_buffer to url’s path.
11006
37.1k
          path += '/';
11007
37.1k
          path.append(path_buffer);
11008
37.1k
        }
11009
39.3k
      }
11010
51.2k
      if (location == std::string_view::npos) {
11011
10.0k
        return;
11012
10.0k
      }
11013
51.2k
    } while (true);
11014
10.0k
  }
11015
10.5k
}
11016
11017
0
bool overlaps(std::string_view input1, const std::string& input2) noexcept {
11018
0
  ada_log("helpers::overlaps check if string_view '", input1, "' [",
11019
0
          input1.size(), " bytes] is part of string '", input2, "' [",
11020
0
          input2.size(), " bytes]");
11021
0
  return !input1.empty() && !input2.empty() && input1.data() >= input2.data() &&
11022
0
         input1.data() < input2.data() + input2.size();
11023
0
}
11024
11025
template <class url_type>
11026
ada_really_inline void strip_trailing_spaces_from_opaque_path(
11027
23.8k
    url_type& url) noexcept {
11028
23.8k
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
11029
23.8k
  if (!url.has_opaque_path) return;
11030
3.61k
  if (url.has_hash()) return;
11031
3.45k
  if (url.has_search()) return;
11032
11033
3.45k
  auto path = std::string(url.get_pathname());
11034
5.19k
  while (!path.empty() && path.back() == ' ') {
11035
1.73k
    path.resize(path.size() - 1);
11036
1.73k
  }
11037
3.45k
  url.update_base_pathname(path);
11038
3.45k
}
void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url>(ada::url&)
Line
Count
Source
11027
10.4k
    url_type& url) noexcept {
11028
10.4k
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
11029
10.4k
  if (!url.has_opaque_path) return;
11030
1.82k
  if (url.has_hash()) return;
11031
1.73k
  if (url.has_search()) return;
11032
11033
1.73k
  auto path = std::string(url.get_pathname());
11034
2.60k
  while (!path.empty() && path.back() == ' ') {
11035
868
    path.resize(path.size() - 1);
11036
868
  }
11037
1.73k
  url.update_base_pathname(path);
11038
1.73k
}
void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url_aggregator>(ada::url_aggregator&)
Line
Count
Source
11027
13.3k
    url_type& url) noexcept {
11028
13.3k
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
11029
13.3k
  if (!url.has_opaque_path) return;
11030
1.79k
  if (url.has_hash()) return;
11031
1.72k
  if (url.has_search()) return;
11032
11033
1.72k
  auto path = std::string(url.get_pathname());
11034
2.59k
  while (!path.empty() && path.back() == ' ') {
11035
868
    path.resize(path.size() - 1);
11036
868
  }
11037
1.72k
  url.update_base_pathname(path);
11038
1.72k
}
11039
11040
ada_really_inline size_t
11041
9.03k
find_authority_delimiter_special(std::string_view view) noexcept {
11042
51.1k
  auto has_zero_byte = [](uint64_t v) {
11043
51.1k
    return ((v - 0x0101010101010101) & ~(v)&0x8080808080808080);
11044
51.1k
  };
11045
9.03k
  auto index_of_first_set_byte = [](uint64_t v) {
11046
8.00k
    return ((((v - 1) & 0x101010101010101) * 0x101010101010101) >> 56) - 1;
11047
8.00k
  };
11048
36.1k
  auto broadcast = [](uint8_t v) -> uint64_t {
11049
36.1k
    return 0x101010101010101ull * v;
11050
36.1k
  };
11051
9.03k
  size_t i = 0;
11052
9.03k
  uint64_t mask1 = broadcast('@');
11053
9.03k
  uint64_t mask2 = broadcast('/');
11054
9.03k
  uint64_t mask3 = broadcast('?');
11055
9.03k
  uint64_t mask4 = broadcast('\\');
11056
11057
13.4k
  for (; i + 7 < view.size(); i += 8) {
11058
9.96k
    uint64_t word{};
11059
9.96k
    memcpy(&word, view.data() + i, sizeof(word));
11060
9.96k
    word = swap_bytes_if_big_endian(word);
11061
9.96k
    uint64_t xor1 = word ^ mask1;
11062
9.96k
    uint64_t xor2 = word ^ mask2;
11063
9.96k
    uint64_t xor3 = word ^ mask3;
11064
9.96k
    uint64_t xor4 = word ^ mask4;
11065
9.96k
    uint64_t is_match = has_zero_byte(xor1) | has_zero_byte(xor2) |
11066
9.96k
                        has_zero_byte(xor3) | has_zero_byte(xor4);
11067
9.96k
    if (is_match) {
11068
5.57k
      return size_t(i + index_of_first_set_byte(is_match));
11069
5.57k
    }
11070
9.96k
  }
11071
11072
3.46k
  if (i < view.size()) {
11073
2.83k
    uint64_t word{};
11074
2.83k
    memcpy(&word, view.data() + i, view.size() - i);
11075
2.83k
    word = swap_bytes_if_big_endian(word);
11076
2.83k
    uint64_t xor1 = word ^ mask1;
11077
2.83k
    uint64_t xor2 = word ^ mask2;
11078
2.83k
    uint64_t xor3 = word ^ mask3;
11079
2.83k
    uint64_t xor4 = word ^ mask4;
11080
2.83k
    uint64_t is_match = has_zero_byte(xor1) | has_zero_byte(xor2) |
11081
2.83k
                        has_zero_byte(xor3) | has_zero_byte(xor4);
11082
2.83k
    if (is_match) {
11083
2.43k
      return size_t(i + index_of_first_set_byte(is_match));
11084
2.43k
    }
11085
2.83k
  }
11086
11087
1.03k
  return view.size();
11088
3.46k
}
11089
11090
ada_really_inline size_t
11091
1.72k
find_authority_delimiter(std::string_view view) noexcept {
11092
7.93k
  auto has_zero_byte = [](uint64_t v) {
11093
7.93k
    return ((v - 0x0101010101010101) & ~(v)&0x8080808080808080);
11094
7.93k
  };
11095
1.72k
  auto index_of_first_set_byte = [](uint64_t v) {
11096
1.54k
    return ((((v - 1) & 0x101010101010101) * 0x101010101010101) >> 56) - 1;
11097
1.54k
  };
11098
5.17k
  auto broadcast = [](uint8_t v) -> uint64_t {
11099
5.17k
    return 0x101010101010101ull * v;
11100
5.17k
  };
11101
1.72k
  size_t i = 0;
11102
1.72k
  uint64_t mask1 = broadcast('@');
11103
1.72k
  uint64_t mask2 = broadcast('/');
11104
1.72k
  uint64_t mask3 = broadcast('?');
11105
11106
2.75k
  for (; i + 7 < view.size(); i += 8) {
11107
2.19k
    uint64_t word{};
11108
2.19k
    memcpy(&word, view.data() + i, sizeof(word));
11109
2.19k
    word = swap_bytes_if_big_endian(word);
11110
2.19k
    uint64_t xor1 = word ^ mask1;
11111
2.19k
    uint64_t xor2 = word ^ mask2;
11112
2.19k
    uint64_t xor3 = word ^ mask3;
11113
2.19k
    uint64_t is_match =
11114
2.19k
        has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
11115
2.19k
    if (is_match) {
11116
1.16k
      return size_t(i + index_of_first_set_byte(is_match));
11117
1.16k
    }
11118
2.19k
  }
11119
11120
564
  if (i < view.size()) {
11121
455
    uint64_t word{};
11122
455
    memcpy(&word, view.data() + i, view.size() - i);
11123
455
    word = swap_bytes_if_big_endian(word);
11124
455
    uint64_t xor1 = word ^ mask1;
11125
455
    uint64_t xor2 = word ^ mask2;
11126
455
    uint64_t xor3 = word ^ mask3;
11127
455
    uint64_t is_match =
11128
455
        has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
11129
455
    if (is_match) {
11130
384
      return size_t(i + index_of_first_set_byte(is_match));
11131
384
    }
11132
455
  }
11133
11134
180
  return view.size();
11135
564
}
11136
11137
}  // namespace ada::helpers
11138
11139
namespace ada {
11140
0
ada_warn_unused std::string to_string(ada::state state) {
11141
0
  return ada::helpers::get_state(state);
11142
0
}
11143
}  // namespace ada
11144
/* end file src/helpers.cpp */
11145
/* begin file src/url.cpp */
11146
11147
#include <numeric>
11148
#include <algorithm>
11149
#include <string>
11150
11151
namespace ada {
11152
11153
1.00k
bool url::parse_opaque_host(std::string_view input) {
11154
1.00k
  ada_log("parse_opaque_host ", input, "[", input.size(), " bytes]");
11155
1.00k
  if (std::any_of(input.begin(), input.end(),
11156
1.00k
                  ada::unicode::is_forbidden_host_code_point)) {
11157
132
    return is_valid = false;
11158
132
  }
11159
11160
  // Return the result of running UTF-8 percent-encode on input using the C0
11161
  // control percent-encode set.
11162
876
  host = ada::unicode::percent_encode(
11163
876
      input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
11164
876
  return true;
11165
1.00k
}
11166
11167
2.15k
bool url::parse_ipv4(std::string_view input) {
11168
2.15k
  ada_log("parse_ipv4 ", input, "[", input.size(), " bytes]");
11169
2.15k
  if (input.back() == '.') {
11170
34
    input.remove_suffix(1);
11171
34
  }
11172
2.15k
  size_t digit_count{0};
11173
2.15k
  int pure_decimal_count = 0;  // entries that are decimal
11174
2.15k
  std::string_view original_input =
11175
2.15k
      input;  // we might use this if pure_decimal_count == 4.
11176
2.15k
  uint64_t ipv4{0};
11177
  // we could unroll for better performance?
11178
2.67k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
11179
2.65k
    uint32_t
11180
2.65k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
11181
2.65k
    bool is_hex = checkers::has_hex_prefix(input);
11182
2.65k
    if (is_hex && ((input.length() == 2) ||
11183
691
                   ((input.length() > 2) && (input[2] == '.')))) {
11184
      // special case
11185
59
      segment_result = 0;
11186
59
      input.remove_prefix(2);
11187
2.59k
    } else {
11188
2.59k
      std::from_chars_result r;
11189
2.59k
      if (is_hex) {
11190
632
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
11191
632
                            segment_result, 16);
11192
1.96k
      } else if ((input.length() >= 2) && input[0] == '0' &&
11193
1.96k
                 checkers::is_digit(input[1])) {
11194
347
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
11195
347
                            segment_result, 8);
11196
1.61k
      } else {
11197
1.61k
        pure_decimal_count++;
11198
1.61k
        r = std::from_chars(input.data(), input.data() + input.size(),
11199
1.61k
                            segment_result, 10);
11200
1.61k
      }
11201
2.59k
      if (r.ec != std::errc()) {
11202
436
        return is_valid = false;
11203
436
      }
11204
2.15k
      input.remove_prefix(r.ptr - input.data());
11205
2.15k
    }
11206
2.21k
    if (input.empty()) {
11207
      // We have the last value.
11208
      // At this stage, ipv4 contains digit_count*8 bits.
11209
      // So we have 32-digit_count*8 bits left.
11210
1.57k
      if (segment_result > (uint64_t(1) << (32 - digit_count * 8))) {
11211
13
        return is_valid = false;
11212
13
      }
11213
1.55k
      ipv4 <<= (32 - digit_count * 8);
11214
1.55k
      ipv4 |= segment_result;
11215
1.55k
      goto final;
11216
1.57k
    } else {
11217
      // There is more, so that the value must no be larger than 255
11218
      // and we must have a '.'.
11219
645
      if ((segment_result > 255) || (input[0] != '.')) {
11220
123
        return is_valid = false;
11221
123
      }
11222
522
      ipv4 <<= 8;
11223
522
      ipv4 |= segment_result;
11224
522
      input.remove_prefix(1);  // remove '.'
11225
522
    }
11226
2.21k
  }
11227
26
  if ((digit_count != 4) || (!input.empty())) {
11228
26
    return is_valid = false;
11229
26
  }
11230
1.55k
final:
11231
  // We could also check r.ptr to see where the parsing ended.
11232
1.55k
  if (pure_decimal_count == 4) {
11233
43
    host = original_input;  // The original input was already all decimal and we
11234
                            // validated it.
11235
1.51k
  } else {
11236
1.51k
    host = ada::serializers::ipv4(ipv4);  // We have to reserialize the address.
11237
1.51k
  }
11238
1.55k
  return true;
11239
26
}
11240
11241
532
bool url::parse_ipv6(std::string_view input) {
11242
532
  ada_log("parse_ipv6 ", input, "[", input.size(), " bytes]");
11243
11244
532
  if (input.empty()) {
11245
24
    return is_valid = false;
11246
24
  }
11247
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
11248
508
  std::array<uint16_t, 8> address{};
11249
11250
  // Let pieceIndex be 0.
11251
508
  int piece_index = 0;
11252
11253
  // Let compress be null.
11254
508
  std::optional<int> compress{};
11255
11256
  // Let pointer be a pointer for input.
11257
508
  std::string_view::iterator pointer = input.begin();
11258
11259
  // If c is U+003A (:), then:
11260
508
  if (input[0] == ':') {
11261
    // If remaining does not start with U+003A (:), validation error, return
11262
    // failure.
11263
119
    if (input.size() == 1 || input[1] != ':') {
11264
10
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
11265
10
      return is_valid = false;
11266
10
    }
11267
11268
    // Increase pointer by 2.
11269
109
    pointer += 2;
11270
11271
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
11272
109
    compress = ++piece_index;
11273
109
  }
11274
11275
  // While c is not the EOF code point:
11276
1.41k
  while (pointer != input.end()) {
11277
    // If pieceIndex is 8, validation error, return failure.
11278
1.17k
    if (piece_index == 8) {
11279
7
      ada_log("parse_ipv6 piece_index == 8");
11280
7
      return is_valid = false;
11281
7
    }
11282
11283
    // If c is U+003A (:), then:
11284
1.17k
    if (*pointer == ':') {
11285
      // If compress is non-null, validation error, return failure.
11286
82
      if (compress.has_value()) {
11287
6
        ada_log("parse_ipv6 compress is non-null");
11288
6
        return is_valid = false;
11289
6
      }
11290
11291
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
11292
      // then continue.
11293
76
      pointer++;
11294
76
      compress = ++piece_index;
11295
76
      continue;
11296
82
    }
11297
11298
    // Let value and length be 0.
11299
1.08k
    uint16_t value = 0, length = 0;
11300
11301
    // While length is less than 4 and c is an ASCII hex digit,
11302
    // set value to value × 0x10 + c interpreted as hexadecimal number, and
11303
    // increase pointer and length by 1.
11304
2.84k
    while (length < 4 && pointer != input.end() &&
11305
2.84k
           unicode::is_ascii_hex_digit(*pointer)) {
11306
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
11307
1.75k
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
11308
1.75k
      pointer++;
11309
1.75k
      length++;
11310
1.75k
    }
11311
11312
    // If c is U+002E (.), then:
11313
1.08k
    if (pointer != input.end() && *pointer == '.') {
11314
      // If length is 0, validation error, return failure.
11315
119
      if (length == 0) {
11316
6
        ada_log("parse_ipv6 length is 0");
11317
6
        return is_valid = false;
11318
6
      }
11319
11320
      // Decrease pointer by length.
11321
113
      pointer -= length;
11322
11323
      // If pieceIndex is greater than 6, validation error, return failure.
11324
113
      if (piece_index > 6) {
11325
4
        ada_log("parse_ipv6 piece_index > 6");
11326
4
        return is_valid = false;
11327
4
      }
11328
11329
      // Let numbersSeen be 0.
11330
109
      int numbers_seen = 0;
11331
11332
      // While c is not the EOF code point:
11333
341
      while (pointer != input.end()) {
11334
        // Let ipv4Piece be null.
11335
300
        std::optional<uint16_t> ipv4_piece{};
11336
11337
        // If numbersSeen is greater than 0, then:
11338
300
        if (numbers_seen > 0) {
11339
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
11340
          // pointer by 1.
11341
191
          if (*pointer == '.' && numbers_seen < 4) {
11342
169
            pointer++;
11343
169
          }
11344
          // Otherwise, validation error, return failure.
11345
22
          else {
11346
22
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
11347
22
            return is_valid = false;
11348
22
          }
11349
191
        }
11350
11351
        // If c is not an ASCII digit, validation error, return failure.
11352
278
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
11353
28
          ada_log(
11354
28
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
11355
28
              "failure");
11356
28
          return is_valid = false;
11357
28
        }
11358
11359
        // While c is an ASCII digit:
11360
615
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
11361
          // Let number be c interpreted as decimal number.
11362
383
          int number = *pointer - '0';
11363
11364
          // If ipv4Piece is null, then set ipv4Piece to number.
11365
383
          if (!ipv4_piece.has_value()) {
11366
250
            ipv4_piece = number;
11367
250
          }
11368
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
11369
133
          else if (ipv4_piece == 0) {
11370
4
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
11371
4
            return is_valid = false;
11372
4
          }
11373
          // Otherwise, set ipv4Piece to ipv4Piece × 10 + number.
11374
129
          else {
11375
129
            ipv4_piece = *ipv4_piece * 10 + number;
11376
129
          }
11377
11378
          // If ipv4Piece is greater than 255, validation error, return failure.
11379
379
          if (ipv4_piece > 255) {
11380
14
            ada_log("parse_ipv6 ipv4_piece > 255");
11381
14
            return is_valid = false;
11382
14
          }
11383
11384
          // Increase pointer by 1.
11385
365
          pointer++;
11386
365
        }
11387
11388
        // Set address[pieceIndex] to address[pieceIndex] × 0x100 + ipv4Piece.
11389
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
11390
232
        address[piece_index] =
11391
232
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
11392
11393
        // Increase numbersSeen by 1.
11394
232
        numbers_seen++;
11395
11396
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
11397
232
        if (numbers_seen == 2 || numbers_seen == 4) {
11398
97
          piece_index++;
11399
97
        }
11400
232
      }
11401
11402
      // If numbersSeen is not 4, validation error, return failure.
11403
41
      if (numbers_seen != 4) {
11404
15
        return is_valid = false;
11405
15
      }
11406
11407
      // Break.
11408
26
      break;
11409
41
    }
11410
    // Otherwise, if c is U+003A (:):
11411
970
    else if ((pointer != input.end()) && (*pointer == ':')) {
11412
      // Increase pointer by 1.
11413
671
      pointer++;
11414
11415
      // If c is the EOF code point, validation error, return failure.
11416
671
      if (pointer == input.end()) {
11417
8
        ada_log(
11418
8
            "parse_ipv6 If c is the EOF code point, validation error, return "
11419
8
            "failure");
11420
8
        return is_valid = false;
11421
8
      }
11422
671
    }
11423
    // Otherwise, if c is not the EOF code point, validation error, return
11424
    // failure.
11425
299
    else if (pointer != input.end()) {
11426
117
      ada_log(
11427
117
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
11428
117
          "error, return failure");
11429
117
      return is_valid = false;
11430
117
    }
11431
11432
    // Set address[pieceIndex] to value.
11433
845
    address[piece_index] = value;
11434
11435
    // Increase pieceIndex by 1.
11436
845
    piece_index++;
11437
845
  }
11438
11439
  // If compress is non-null, then:
11440
267
  if (compress.has_value()) {
11441
    // Let swaps be pieceIndex − compress.
11442
167
    int swaps = piece_index - *compress;
11443
11444
    // Set pieceIndex to 7.
11445
167
    piece_index = 7;
11446
11447
    // While pieceIndex is not 0 and swaps is greater than 0,
11448
    // swap address[pieceIndex] with address[compress + swaps − 1], and then
11449
    // decrease both pieceIndex and swaps by 1.
11450
460
    while (piece_index != 0 && swaps > 0) {
11451
293
      std::swap(address[piece_index], address[*compress + swaps - 1]);
11452
293
      piece_index--;
11453
293
      swaps--;
11454
293
    }
11455
167
  }
11456
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
11457
  // return failure.
11458
100
  else if (piece_index != 8) {
11459
79
    ada_log(
11460
79
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
11461
79
        "error, return failure");
11462
79
    return is_valid = false;
11463
79
  }
11464
188
  host = ada::serializers::ipv6(address);
11465
188
  ada_log("parse_ipv6 ", *host);
11466
188
  return true;
11467
267
}
11468
11469
template <bool has_state_override>
11470
10.5k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
11471
10.5k
  auto parsed_type = ada::scheme::get_scheme_type(input);
11472
10.5k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
11473
  /**
11474
   * In the common case, we will immediately recognize a special scheme (e.g.,
11475
   *http, https), in which case, we can go really fast.
11476
   **/
11477
10.5k
  if (is_input_special) {  // fast path!!!
11478
4.56k
    if (has_state_override) {
11479
      // If url’s scheme is not a special scheme and buffer is a special scheme,
11480
      // then return.
11481
55
      if (is_special() != is_input_special) {
11482
1
        return true;
11483
1
      }
11484
11485
      // If url includes credentials or has a non-null port, and buffer is
11486
      // "file", then return.
11487
54
      if ((has_credentials() || port.has_value()) &&
11488
54
          parsed_type == ada::scheme::type::FILE) {
11489
1
        return true;
11490
1
      }
11491
11492
      // If url’s scheme is "file" and its host is an empty host, then return.
11493
      // An empty host is the empty string.
11494
53
      if (type == ada::scheme::type::FILE && host.has_value() &&
11495
53
          host.value().empty()) {
11496
1
        return true;
11497
1
      }
11498
53
    }
11499
11500
4.56k
    type = parsed_type;
11501
11502
4.56k
    if (has_state_override) {
11503
      // This is uncommon.
11504
52
      uint16_t urls_scheme_port = get_special_port();
11505
11506
52
      if (urls_scheme_port) {
11507
        // If url’s port is url’s scheme’s default port, then set url’s port to
11508
        // null.
11509
24
        if (port.has_value() && *port == urls_scheme_port) {
11510
1
          port = std::nullopt;
11511
1
        }
11512
24
      }
11513
52
    }
11514
6.01k
  } else {  // slow path
11515
6.01k
    std::string _buffer = std::string(input);
11516
    // Next function is only valid if the input is ASCII and returns false
11517
    // otherwise, but it seems that we always have ascii content so we do not
11518
    // need to check the return value.
11519
    // bool is_ascii =
11520
6.01k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
11521
11522
6.01k
    if (has_state_override) {
11523
      // If url’s scheme is a special scheme and buffer is not a special scheme,
11524
      // then return. If url’s scheme is not a special scheme and buffer is a
11525
      // special scheme, then return.
11526
305
      if (is_special() != ada::scheme::is_special(_buffer)) {
11527
162
        return true;
11528
162
      }
11529
11530
      // If url includes credentials or has a non-null port, and buffer is
11531
      // "file", then return.
11532
143
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
11533
1
        return true;
11534
1
      }
11535
11536
      // If url’s scheme is "file" and its host is an empty host, then return.
11537
      // An empty host is the empty string.
11538
142
      if (type == ada::scheme::type::FILE && host.has_value() &&
11539
142
          host.value().empty()) {
11540
1
        return true;
11541
1
      }
11542
142
    }
11543
11544
5.85k
    set_scheme(std::move(_buffer));
11545
11546
5.85k
    if (has_state_override) {
11547
      // This is uncommon.
11548
141
      uint16_t urls_scheme_port = get_special_port();
11549
11550
141
      if (urls_scheme_port) {
11551
        // If url’s port is url’s scheme’s default port, then set url’s port to
11552
        // null.
11553
26
        if (port.has_value() && *port == urls_scheme_port) {
11554
1
          port = std::nullopt;
11555
1
        }
11556
26
      }
11557
141
    }
11558
5.85k
  }
11559
11560
10.4k
  return true;
11561
10.5k
}
bool ada::url::parse_scheme<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
11470
360
ada_really_inline bool url::parse_scheme(const std::string_view input) {
11471
360
  auto parsed_type = ada::scheme::get_scheme_type(input);
11472
360
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
11473
  /**
11474
   * In the common case, we will immediately recognize a special scheme (e.g.,
11475
   *http, https), in which case, we can go really fast.
11476
   **/
11477
360
  if (is_input_special) {  // fast path!!!
11478
55
    if (has_state_override) {
11479
      // If url’s scheme is not a special scheme and buffer is a special scheme,
11480
      // then return.
11481
55
      if (is_special() != is_input_special) {
11482
1
        return true;
11483
1
      }
11484
11485
      // If url includes credentials or has a non-null port, and buffer is
11486
      // "file", then return.
11487
54
      if ((has_credentials() || port.has_value()) &&
11488
54
          parsed_type == ada::scheme::type::FILE) {
11489
1
        return true;
11490
1
      }
11491
11492
      // If url’s scheme is "file" and its host is an empty host, then return.
11493
      // An empty host is the empty string.
11494
53
      if (type == ada::scheme::type::FILE && host.has_value() &&
11495
53
          host.value().empty()) {
11496
1
        return true;
11497
1
      }
11498
53
    }
11499
11500
52
    type = parsed_type;
11501
11502
52
    if (has_state_override) {
11503
      // This is uncommon.
11504
52
      uint16_t urls_scheme_port = get_special_port();
11505
11506
52
      if (urls_scheme_port) {
11507
        // If url’s port is url’s scheme’s default port, then set url’s port to
11508
        // null.
11509
24
        if (port.has_value() && *port == urls_scheme_port) {
11510
1
          port = std::nullopt;
11511
1
        }
11512
24
      }
11513
52
    }
11514
305
  } else {  // slow path
11515
305
    std::string _buffer = std::string(input);
11516
    // Next function is only valid if the input is ASCII and returns false
11517
    // otherwise, but it seems that we always have ascii content so we do not
11518
    // need to check the return value.
11519
    // bool is_ascii =
11520
305
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
11521
11522
305
    if (has_state_override) {
11523
      // If url’s scheme is a special scheme and buffer is not a special scheme,
11524
      // then return. If url’s scheme is not a special scheme and buffer is a
11525
      // special scheme, then return.
11526
305
      if (is_special() != ada::scheme::is_special(_buffer)) {
11527
162
        return true;
11528
162
      }
11529
11530
      // If url includes credentials or has a non-null port, and buffer is
11531
      // "file", then return.
11532
143
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
11533
1
        return true;
11534
1
      }
11535
11536
      // If url’s scheme is "file" and its host is an empty host, then return.
11537
      // An empty host is the empty string.
11538
142
      if (type == ada::scheme::type::FILE && host.has_value() &&
11539
142
          host.value().empty()) {
11540
1
        return true;
11541
1
      }
11542
142
    }
11543
11544
141
    set_scheme(std::move(_buffer));
11545
11546
141
    if (has_state_override) {
11547
      // This is uncommon.
11548
141
      uint16_t urls_scheme_port = get_special_port();
11549
11550
141
      if (urls_scheme_port) {
11551
        // If url’s port is url’s scheme’s default port, then set url’s port to
11552
        // null.
11553
26
        if (port.has_value() && *port == urls_scheme_port) {
11554
1
          port = std::nullopt;
11555
1
        }
11556
26
      }
11557
141
    }
11558
141
  }
11559
11560
193
  return true;
11561
360
}
bool ada::url::parse_scheme<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
11470
10.2k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
11471
10.2k
  auto parsed_type = ada::scheme::get_scheme_type(input);
11472
10.2k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
11473
  /**
11474
   * In the common case, we will immediately recognize a special scheme (e.g.,
11475
   *http, https), in which case, we can go really fast.
11476
   **/
11477
10.2k
  if (is_input_special) {  // fast path!!!
11478
4.51k
    if (has_state_override) {
11479
      // If url’s scheme is not a special scheme and buffer is a special scheme,
11480
      // then return.
11481
0
      if (is_special() != is_input_special) {
11482
0
        return true;
11483
0
      }
11484
11485
      // If url includes credentials or has a non-null port, and buffer is
11486
      // "file", then return.
11487
0
      if ((has_credentials() || port.has_value()) &&
11488
0
          parsed_type == ada::scheme::type::FILE) {
11489
0
        return true;
11490
0
      }
11491
11492
      // If url’s scheme is "file" and its host is an empty host, then return.
11493
      // An empty host is the empty string.
11494
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
11495
0
          host.value().empty()) {
11496
0
        return true;
11497
0
      }
11498
0
    }
11499
11500
4.51k
    type = parsed_type;
11501
11502
4.51k
    if (has_state_override) {
11503
      // This is uncommon.
11504
0
      uint16_t urls_scheme_port = get_special_port();
11505
11506
0
      if (urls_scheme_port) {
11507
        // If url’s port is url’s scheme’s default port, then set url’s port to
11508
        // null.
11509
0
        if (port.has_value() && *port == urls_scheme_port) {
11510
0
          port = std::nullopt;
11511
0
        }
11512
0
      }
11513
0
    }
11514
5.71k
  } else {  // slow path
11515
5.71k
    std::string _buffer = std::string(input);
11516
    // Next function is only valid if the input is ASCII and returns false
11517
    // otherwise, but it seems that we always have ascii content so we do not
11518
    // need to check the return value.
11519
    // bool is_ascii =
11520
5.71k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
11521
11522
5.71k
    if (has_state_override) {
11523
      // If url’s scheme is a special scheme and buffer is not a special scheme,
11524
      // then return. If url’s scheme is not a special scheme and buffer is a
11525
      // special scheme, then return.
11526
0
      if (is_special() != ada::scheme::is_special(_buffer)) {
11527
0
        return true;
11528
0
      }
11529
11530
      // If url includes credentials or has a non-null port, and buffer is
11531
      // "file", then return.
11532
0
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
11533
0
        return true;
11534
0
      }
11535
11536
      // If url’s scheme is "file" and its host is an empty host, then return.
11537
      // An empty host is the empty string.
11538
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
11539
0
          host.value().empty()) {
11540
0
        return true;
11541
0
      }
11542
0
    }
11543
11544
5.71k
    set_scheme(std::move(_buffer));
11545
11546
5.71k
    if (has_state_override) {
11547
      // This is uncommon.
11548
0
      uint16_t urls_scheme_port = get_special_port();
11549
11550
0
      if (urls_scheme_port) {
11551
        // If url’s port is url’s scheme’s default port, then set url’s port to
11552
        // null.
11553
0
        if (port.has_value() && *port == urls_scheme_port) {
11554
0
          port = std::nullopt;
11555
0
        }
11556
0
      }
11557
0
    }
11558
5.71k
  }
11559
11560
10.2k
  return true;
11561
10.2k
}
11562
11563
10.1k
ada_really_inline bool url::parse_host(std::string_view input) {
11564
10.1k
  ada_log("parse_host ", input, "[", input.size(), " bytes]");
11565
10.1k
  if (input.empty()) {
11566
13
    return is_valid = false;
11567
13
  }  // technically unnecessary.
11568
  // If input starts with U+005B ([), then:
11569
10.1k
  if (input[0] == '[') {
11570
    // If input does not end with U+005D (]), validation error, return failure.
11571
786
    if (input.back() != ']') {
11572
254
      return is_valid = false;
11573
254
    }
11574
532
    ada_log("parse_host ipv6");
11575
11576
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
11577
    // trailing U+005D (]) removed.
11578
532
    input.remove_prefix(1);
11579
532
    input.remove_suffix(1);
11580
532
    return parse_ipv6(input);
11581
786
  }
11582
11583
  // If isNotSpecial is true, then return the result of opaque-host parsing
11584
  // input.
11585
9.36k
  if (!is_special()) {
11586
1.00k
    return parse_opaque_host(input);
11587
1.00k
  }
11588
  // Let domain be the result of running UTF-8 decode without BOM on the
11589
  // percent-decoding of input. Let asciiDomain be the result of running domain
11590
  // to ASCII with domain and false. The most common case is an ASCII input, in
11591
  // which case we do not need to call the expensive 'to_ascii' if a few
11592
  // conditions are met: no '%' and no 'xn-' subsequence.
11593
8.35k
  std::string buffer = std::string(input);
11594
  // This next function checks that the result is ascii, but we are going to
11595
  // to check anyhow with is_forbidden.
11596
  // bool is_ascii =
11597
8.35k
  unicode::to_lower_ascii(buffer.data(), buffer.size());
11598
8.35k
  bool is_forbidden = unicode::contains_forbidden_domain_code_point(
11599
8.35k
      buffer.data(), buffer.size());
11600
8.35k
  if (is_forbidden == 0 && buffer.find("xn-") == std::string_view::npos) {
11601
    // fast path
11602
5.18k
    host = std::move(buffer);
11603
5.18k
    if (checkers::is_ipv4(host.value())) {
11604
1.93k
      ada_log("parse_host fast path ipv4");
11605
1.93k
      return parse_ipv4(host.value());
11606
1.93k
    }
11607
3.25k
    ada_log("parse_host fast path ", *host);
11608
3.25k
    return true;
11609
5.18k
  }
11610
3.17k
  ada_log("parse_host calling to_ascii");
11611
3.17k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
11612
3.17k
  if (!is_valid) {
11613
1.56k
    ada_log("parse_host to_ascii returns false");
11614
1.56k
    return is_valid = false;
11615
1.56k
  }
11616
11617
1.61k
  if (std::any_of(host.value().begin(), host.value().end(),
11618
1.61k
                  ada::unicode::is_forbidden_domain_code_point)) {
11619
0
    host = std::nullopt;
11620
0
    return is_valid = false;
11621
0
  }
11622
11623
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
11624
  // asciiDomain.
11625
1.61k
  if (checkers::is_ipv4(host.value())) {
11626
226
    ada_log("parse_host got ipv4", *host);
11627
226
    return parse_ipv4(host.value());
11628
226
  }
11629
11630
1.38k
  return true;
11631
1.61k
}
11632
11633
7.20k
ada_really_inline void url::parse_path(std::string_view input) {
11634
7.20k
  ada_log("parse_path ", input);
11635
7.20k
  std::string tmp_buffer;
11636
7.20k
  std::string_view internal_input;
11637
7.20k
  if (unicode::has_tabs_or_newline(input)) {
11638
103
    tmp_buffer = input;
11639
    // Optimization opportunity: Instead of copying and then pruning, we could
11640
    // just directly build the string from user_input.
11641
103
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
11642
103
    internal_input = tmp_buffer;
11643
7.10k
  } else {
11644
7.10k
    internal_input = input;
11645
7.10k
  }
11646
11647
  // If url is special, then:
11648
7.20k
  if (is_special()) {
11649
5.52k
    if (internal_input.empty()) {
11650
3.45k
      path = "/";
11651
3.45k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
11652
530
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
11653
530
      return;
11654
1.53k
    } else {
11655
1.53k
      helpers::parse_prepared_path(internal_input, type, path);
11656
1.53k
      return;
11657
1.53k
    }
11658
5.52k
  } else if (!internal_input.empty()) {
11659
767
    if (internal_input[0] == '/') {
11660
252
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
11661
252
      return;
11662
515
    } else {
11663
515
      helpers::parse_prepared_path(internal_input, type, path);
11664
515
      return;
11665
515
    }
11666
913
  } else {
11667
913
    if (!host.has_value()) {
11668
0
      path = "/";
11669
0
    }
11670
913
  }
11671
4.37k
  return;
11672
7.20k
}
11673
11674
0
std::string url::to_string() const {
11675
0
  if (!is_valid) {
11676
0
    return "null";
11677
0
  }
11678
0
  std::string answer;
11679
0
  auto back = std::back_insert_iterator(answer);
11680
0
  answer.append("{\n");
11681
0
  answer.append("\t\"protocol\":\"");
11682
0
  helpers::encode_json(get_protocol(), back);
11683
0
  answer.append("\",\n");
11684
0
  if (has_credentials()) {
11685
0
    answer.append("\t\"username\":\"");
11686
0
    helpers::encode_json(username, back);
11687
0
    answer.append("\",\n");
11688
0
    answer.append("\t\"password\":\"");
11689
0
    helpers::encode_json(password, back);
11690
0
    answer.append("\",\n");
11691
0
  }
11692
0
  if (host.has_value()) {
11693
0
    answer.append("\t\"host\":\"");
11694
0
    helpers::encode_json(host.value(), back);
11695
0
    answer.append("\",\n");
11696
0
  }
11697
0
  if (port.has_value()) {
11698
0
    answer.append("\t\"port\":\"");
11699
0
    answer.append(std::to_string(port.value()));
11700
0
    answer.append("\",\n");
11701
0
  }
11702
0
  answer.append("\t\"path\":\"");
11703
0
  helpers::encode_json(path, back);
11704
0
  answer.append("\",\n");
11705
0
  answer.append("\t\"opaque path\":");
11706
0
  answer.append((has_opaque_path ? "true" : "false"));
11707
0
  if (has_search()) {
11708
0
    answer.append(",\n");
11709
0
    answer.append("\t\"query\":\"");
11710
0
    helpers::encode_json(query.value(), back);
11711
0
    answer.append("\"");
11712
0
  }
11713
0
  if (hash.has_value()) {
11714
0
    answer.append(",\n");
11715
0
    answer.append("\t\"hash\":\"");
11716
0
    helpers::encode_json(hash.value(), back);
11717
0
    answer.append("\"");
11718
0
  }
11719
0
  answer.append("\n}");
11720
0
  return answer;
11721
0
}
11722
11723
0
[[nodiscard]] bool url::has_valid_domain() const noexcept {
11724
0
  if (!host.has_value()) {
11725
0
    return false;
11726
0
  }
11727
0
  return checkers::verify_dns_length(host.value());
11728
0
}
11729
11730
}  // namespace ada
11731
/* end file src/url.cpp */
11732
/* begin file src/url-getters.cpp */
11733
/**
11734
 * @file url-getters.cpp
11735
 * Includes all the getters of `ada::url`
11736
 */
11737
11738
#include <algorithm>
11739
#include <string>
11740
11741
namespace ada {
11742
8.27k
[[nodiscard]] std::string url::get_origin() const noexcept {
11743
8.27k
  if (is_special()) {
11744
    // Return a new opaque origin.
11745
5.52k
    if (type == scheme::FILE) {
11746
1.48k
      return "null";
11747
1.48k
    }
11748
4.03k
    return ada::helpers::concat(get_protocol(), "//", get_host());
11749
5.52k
  }
11750
11751
2.74k
  if (non_special_scheme == "blob") {
11752
398
    if (!path.empty()) {
11753
385
      auto result = ada::parse<ada::url>(path);
11754
385
      if (result &&
11755
385
          (result->type == scheme::HTTP || result->type == scheme::HTTPS)) {
11756
        // If pathURL’s scheme is not "http" and not "https", then return a
11757
        // new opaque origin.
11758
10
        return ada::helpers::concat(result->get_protocol(), "//",
11759
10
                                    result->get_host());
11760
10
      }
11761
385
    }
11762
398
  }
11763
11764
  // Return a new opaque origin.
11765
2.73k
  return "null";
11766
2.74k
}
11767
11768
12.3k
[[nodiscard]] std::string url::get_protocol() const noexcept {
11769
12.3k
  if (is_special()) {
11770
9.57k
    return helpers::concat(ada::scheme::details::is_special_list[type], ":");
11771
9.57k
  }
11772
  // We only move the 'scheme' if it is non-special.
11773
2.74k
  return helpers::concat(non_special_scheme, ":");
11774
12.3k
}
11775
11776
12.3k
[[nodiscard]] std::string url::get_host() const noexcept {
11777
  // If url’s host is null, then return the empty string.
11778
  // If url’s port is null, return url’s host, serialized.
11779
  // Return url’s host, serialized, followed by U+003A (:) and url’s port,
11780
  // serialized.
11781
12.3k
  if (!host.has_value()) {
11782
1.21k
    return "";
11783
1.21k
  }
11784
11.1k
  if (port.has_value()) {
11785
467
    return host.value() + ":" + get_port();
11786
467
  }
11787
10.6k
  return host.value();
11788
11.1k
}
11789
11790
8.27k
[[nodiscard]] std::string url::get_hostname() const noexcept {
11791
8.27k
  return host.value_or("");
11792
8.27k
}
11793
11794
10.0k
[[nodiscard]] const std::string_view url::get_pathname() const noexcept {
11795
10.0k
  return path;
11796
10.0k
}
11797
11798
8.27k
[[nodiscard]] std::string url::get_search() const noexcept {
11799
  // If this’s URL’s query is either null or the empty string, then return the
11800
  // empty string. Return U+003F (?), followed by this’s URL’s query.
11801
8.27k
  return (!query.has_value() || (query.value().empty())) ? ""
11802
8.27k
                                                         : "?" + query.value();
11803
8.27k
}
11804
11805
8.27k
[[nodiscard]] const std::string& url::get_username() const noexcept {
11806
8.27k
  return username;
11807
8.27k
}
11808
11809
8.27k
[[nodiscard]] const std::string& url::get_password() const noexcept {
11810
8.27k
  return password;
11811
8.27k
}
11812
11813
8.73k
[[nodiscard]] std::string url::get_port() const noexcept {
11814
8.73k
  return port.has_value() ? std::to_string(port.value()) : "";
11815
8.73k
}
11816
11817
8.27k
[[nodiscard]] std::string url::get_hash() const noexcept {
11818
  // If this’s URL’s fragment is either null or the empty string, then return
11819
  // the empty string. Return U+0023 (#), followed by this’s URL’s fragment.
11820
8.27k
  return (!hash.has_value() || (hash.value().empty())) ? ""
11821
8.27k
                                                       : "#" + hash.value();
11822
8.27k
}
11823
11824
}  // namespace ada
11825
/* end file src/url-getters.cpp */
11826
/* begin file src/url-setters.cpp */
11827
/**
11828
 * @file url-setters.cpp
11829
 * Includes all the setters of `ada::url`
11830
 */
11831
11832
#include <optional>
11833
#include <string>
11834
11835
namespace ada {
11836
11837
template <bool override_hostname>
11838
16.5k
bool url::set_host_or_hostname(const std::string_view input) {
11839
16.5k
  if (has_opaque_path) {
11840
2.13k
    return false;
11841
2.13k
  }
11842
11843
14.4k
  std::optional<std::string> previous_host = host;
11844
14.4k
  std::optional<uint16_t> previous_port = port;
11845
11846
14.4k
  size_t host_end_pos = input.find('#');
11847
14.4k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
11848
14.4k
                                      ? host_end_pos
11849
14.4k
                                      : input.size());
11850
14.4k
  helpers::remove_ascii_tab_or_newline(_host);
11851
14.4k
  std::string_view new_host(_host);
11852
11853
  // If url's scheme is "file", then set state to file host state, instead of
11854
  // host state.
11855
14.4k
  if (type != ada::scheme::type::FILE) {
11856
11.4k
    std::string_view host_view(_host.data(), _host.length());
11857
11.4k
    auto [location, found_colon] =
11858
11.4k
        helpers::get_host_delimiter_location(is_special(), host_view);
11859
11860
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
11861
    // Note: the 'found_colon' value is true if and only if a colon was
11862
    // encountered while not inside brackets.
11863
11.4k
    if (found_colon) {
11864
222
      if (override_hostname) {
11865
111
        return false;
11866
111
      }
11867
111
      std::string_view buffer = new_host.substr(location + 1);
11868
111
      if (!buffer.empty()) {
11869
99
        set_port(buffer);
11870
99
      }
11871
111
    }
11872
    // If url is special and host_view is the empty string, validation error,
11873
    // return failure. Otherwise, if state override is given, host_view is the
11874
    // empty string, and either url includes credentials or url’s port is
11875
    // non-null, return.
11876
11.2k
    else if (host_view.empty() &&
11877
11.2k
             (is_special() || has_credentials() || port.has_value())) {
11878
6.09k
      return false;
11879
6.09k
    }
11880
11881
    // Let host be the result of host parsing host_view with url is not special.
11882
5.22k
    if (host_view.empty()) {
11883
2.23k
      host = "";
11884
2.23k
      return true;
11885
2.23k
    }
11886
11887
2.99k
    bool succeeded = parse_host(host_view);
11888
2.99k
    if (!succeeded) {
11889
1.05k
      host = previous_host;
11890
1.05k
      update_base_port(previous_port);
11891
1.05k
    }
11892
2.99k
    return succeeded;
11893
5.22k
  }
11894
11895
2.97k
  size_t location = new_host.find_first_of("/\\?");
11896
2.97k
  if (location != std::string_view::npos) {
11897
592
    new_host.remove_suffix(new_host.length() - location);
11898
592
  }
11899
11900
2.97k
  if (new_host.empty()) {
11901
    // Set url’s host to the empty string.
11902
2.03k
    host = "";
11903
2.03k
  } else {
11904
    // Let host be the result of host parsing buffer with url is not special.
11905
944
    if (!parse_host(new_host)) {
11906
386
      host = previous_host;
11907
386
      update_base_port(previous_port);
11908
386
      return false;
11909
386
    }
11910
11911
    // If host is "localhost", then set host to the empty string.
11912
558
    if (host.has_value() && host.value() == "localhost") {
11913
2
      host = "";
11914
2
    }
11915
558
  }
11916
2.58k
  return true;
11917
2.97k
}
bool ada::url::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
11838
8.27k
bool url::set_host_or_hostname(const std::string_view input) {
11839
8.27k
  if (has_opaque_path) {
11840
1.06k
    return false;
11841
1.06k
  }
11842
11843
7.20k
  std::optional<std::string> previous_host = host;
11844
7.20k
  std::optional<uint16_t> previous_port = port;
11845
11846
7.20k
  size_t host_end_pos = input.find('#');
11847
7.20k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
11848
7.20k
                                      ? host_end_pos
11849
7.20k
                                      : input.size());
11850
7.20k
  helpers::remove_ascii_tab_or_newline(_host);
11851
7.20k
  std::string_view new_host(_host);
11852
11853
  // If url's scheme is "file", then set state to file host state, instead of
11854
  // host state.
11855
7.20k
  if (type != ada::scheme::type::FILE) {
11856
5.71k
    std::string_view host_view(_host.data(), _host.length());
11857
5.71k
    auto [location, found_colon] =
11858
5.71k
        helpers::get_host_delimiter_location(is_special(), host_view);
11859
11860
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
11861
    // Note: the 'found_colon' value is true if and only if a colon was
11862
    // encountered while not inside brackets.
11863
5.71k
    if (found_colon) {
11864
111
      if (override_hostname) {
11865
0
        return false;
11866
0
      }
11867
111
      std::string_view buffer = new_host.substr(location + 1);
11868
111
      if (!buffer.empty()) {
11869
99
        set_port(buffer);
11870
99
      }
11871
111
    }
11872
    // If url is special and host_view is the empty string, validation error,
11873
    // return failure. Otherwise, if state override is given, host_view is the
11874
    // empty string, and either url includes credentials or url’s port is
11875
    // non-null, return.
11876
5.60k
    else if (host_view.empty() &&
11877
5.60k
             (is_special() || has_credentials() || port.has_value())) {
11878
3.04k
      return false;
11879
3.04k
    }
11880
11881
    // Let host be the result of host parsing host_view with url is not special.
11882
2.67k
    if (host_view.empty()) {
11883
1.13k
      host = "";
11884
1.13k
      return true;
11885
1.13k
    }
11886
11887
1.53k
    bool succeeded = parse_host(host_view);
11888
1.53k
    if (!succeeded) {
11889
538
      host = previous_host;
11890
538
      update_base_port(previous_port);
11891
538
    }
11892
1.53k
    return succeeded;
11893
2.67k
  }
11894
11895
1.48k
  size_t location = new_host.find_first_of("/\\?");
11896
1.48k
  if (location != std::string_view::npos) {
11897
296
    new_host.remove_suffix(new_host.length() - location);
11898
296
  }
11899
11900
1.48k
  if (new_host.empty()) {
11901
    // Set url’s host to the empty string.
11902
1.01k
    host = "";
11903
1.01k
  } else {
11904
    // Let host be the result of host parsing buffer with url is not special.
11905
472
    if (!parse_host(new_host)) {
11906
193
      host = previous_host;
11907
193
      update_base_port(previous_port);
11908
193
      return false;
11909
193
    }
11910
11911
    // If host is "localhost", then set host to the empty string.
11912
279
    if (host.has_value() && host.value() == "localhost") {
11913
1
      host = "";
11914
1
    }
11915
279
  }
11916
1.29k
  return true;
11917
1.48k
}
bool ada::url::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
11838
8.27k
bool url::set_host_or_hostname(const std::string_view input) {
11839
8.27k
  if (has_opaque_path) {
11840
1.06k
    return false;
11841
1.06k
  }
11842
11843
7.20k
  std::optional<std::string> previous_host = host;
11844
7.20k
  std::optional<uint16_t> previous_port = port;
11845
11846
7.20k
  size_t host_end_pos = input.find('#');
11847
7.20k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
11848
7.20k
                                      ? host_end_pos
11849
7.20k
                                      : input.size());
11850
7.20k
  helpers::remove_ascii_tab_or_newline(_host);
11851
7.20k
  std::string_view new_host(_host);
11852
11853
  // If url's scheme is "file", then set state to file host state, instead of
11854
  // host state.
11855
7.20k
  if (type != ada::scheme::type::FILE) {
11856
5.71k
    std::string_view host_view(_host.data(), _host.length());
11857
5.71k
    auto [location, found_colon] =
11858
5.71k
        helpers::get_host_delimiter_location(is_special(), host_view);
11859
11860
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
11861
    // Note: the 'found_colon' value is true if and only if a colon was
11862
    // encountered while not inside brackets.
11863
5.71k
    if (found_colon) {
11864
111
      if (override_hostname) {
11865
111
        return false;
11866
111
      }
11867
0
      std::string_view buffer = new_host.substr(location + 1);
11868
0
      if (!buffer.empty()) {
11869
0
        set_port(buffer);
11870
0
      }
11871
0
    }
11872
    // If url is special and host_view is the empty string, validation error,
11873
    // return failure. Otherwise, if state override is given, host_view is the
11874
    // empty string, and either url includes credentials or url’s port is
11875
    // non-null, return.
11876
5.60k
    else if (host_view.empty() &&
11877
5.60k
             (is_special() || has_credentials() || port.has_value())) {
11878
3.04k
      return false;
11879
3.04k
    }
11880
11881
    // Let host be the result of host parsing host_view with url is not special.
11882
2.55k
    if (host_view.empty()) {
11883
1.09k
      host = "";
11884
1.09k
      return true;
11885
1.09k
    }
11886
11887
1.46k
    bool succeeded = parse_host(host_view);
11888
1.46k
    if (!succeeded) {
11889
519
      host = previous_host;
11890
519
      update_base_port(previous_port);
11891
519
    }
11892
1.46k
    return succeeded;
11893
2.55k
  }
11894
11895
1.48k
  size_t location = new_host.find_first_of("/\\?");
11896
1.48k
  if (location != std::string_view::npos) {
11897
296
    new_host.remove_suffix(new_host.length() - location);
11898
296
  }
11899
11900
1.48k
  if (new_host.empty()) {
11901
    // Set url’s host to the empty string.
11902
1.01k
    host = "";
11903
1.01k
  } else {
11904
    // Let host be the result of host parsing buffer with url is not special.
11905
472
    if (!parse_host(new_host)) {
11906
193
      host = previous_host;
11907
193
      update_base_port(previous_port);
11908
193
      return false;
11909
193
    }
11910
11911
    // If host is "localhost", then set host to the empty string.
11912
279
    if (host.has_value() && host.value() == "localhost") {
11913
1
      host = "";
11914
1
    }
11915
279
  }
11916
1.29k
  return true;
11917
1.48k
}
11918
11919
8.27k
bool url::set_host(const std::string_view input) {
11920
8.27k
  return set_host_or_hostname<false>(input);
11921
8.27k
}
11922
11923
8.27k
bool url::set_hostname(const std::string_view input) {
11924
8.27k
  return set_host_or_hostname<true>(input);
11925
8.27k
}
11926
11927
8.27k
bool url::set_username(const std::string_view input) {
11928
8.27k
  if (cannot_have_credentials_or_port()) {
11929
4.03k
    return false;
11930
4.03k
  }
11931
4.23k
  username = ada::unicode::percent_encode(
11932
4.23k
      input, character_sets::USERINFO_PERCENT_ENCODE);
11933
4.23k
  return true;
11934
8.27k
}
11935
11936
8.27k
bool url::set_password(const std::string_view input) {
11937
8.27k
  if (cannot_have_credentials_or_port()) {
11938
4.03k
    return false;
11939
4.03k
  }
11940
4.23k
  password = ada::unicode::percent_encode(
11941
4.23k
      input, character_sets::USERINFO_PERCENT_ENCODE);
11942
4.23k
  return true;
11943
8.27k
}
11944
11945
8.37k
bool url::set_port(const std::string_view input) {
11946
8.37k
  if (cannot_have_credentials_or_port()) {
11947
3.87k
    return false;
11948
3.87k
  }
11949
4.49k
  std::string trimmed(input);
11950
4.49k
  helpers::remove_ascii_tab_or_newline(trimmed);
11951
4.49k
  if (trimmed.empty()) {
11952
2.65k
    port = std::nullopt;
11953
2.65k
    return true;
11954
2.65k
  }
11955
  // Input should not start with control characters.
11956
1.84k
  if (ada::unicode::is_c0_control_or_space(trimmed.front())) {
11957
79
    return false;
11958
79
  }
11959
  // Input should contain at least one ascii digit.
11960
1.76k
  if (input.find_first_of("0123456789") == std::string_view::npos) {
11961
1.05k
    return false;
11962
1.05k
  }
11963
11964
  // Revert changes if parse_port fails.
11965
712
  std::optional<uint16_t> previous_port = port;
11966
712
  parse_port(trimmed);
11967
712
  if (is_valid) {
11968
522
    return true;
11969
522
  }
11970
190
  port = previous_port;
11971
190
  is_valid = true;
11972
190
  return false;
11973
712
}
11974
11975
8.27k
void url::set_hash(const std::string_view input) {
11976
8.27k
  if (input.empty()) {
11977
5.24k
    hash = std::nullopt;
11978
5.24k
    helpers::strip_trailing_spaces_from_opaque_path(*this);
11979
5.24k
    return;
11980
5.24k
  }
11981
11982
3.02k
  std::string new_value;
11983
3.02k
  new_value = input[0] == '#' ? input.substr(1) : input;
11984
3.02k
  helpers::remove_ascii_tab_or_newline(new_value);
11985
3.02k
  hash = unicode::percent_encode(new_value,
11986
3.02k
                                 ada::character_sets::FRAGMENT_PERCENT_ENCODE);
11987
3.02k
  return;
11988
8.27k
}
11989
11990
8.27k
void url::set_search(const std::string_view input) {
11991
8.27k
  if (input.empty()) {
11992
5.24k
    query = std::nullopt;
11993
5.24k
    helpers::strip_trailing_spaces_from_opaque_path(*this);
11994
5.24k
    return;
11995
5.24k
  }
11996
11997
3.02k
  std::string new_value;
11998
3.02k
  new_value = input[0] == '?' ? input.substr(1) : input;
11999
3.02k
  helpers::remove_ascii_tab_or_newline(new_value);
12000
12001
3.02k
  auto query_percent_encode_set =
12002
3.02k
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12003
3.02k
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
12004
12005
3.02k
  query = ada::unicode::percent_encode(std::string_view(new_value),
12006
3.02k
                                       query_percent_encode_set);
12007
3.02k
}
12008
12009
8.27k
bool url::set_pathname(const std::string_view input) {
12010
8.27k
  if (has_opaque_path) {
12011
1.06k
    return false;
12012
1.06k
  }
12013
7.20k
  path = "";
12014
7.20k
  parse_path(input);
12015
7.20k
  return true;
12016
8.27k
}
12017
12018
8.27k
bool url::set_protocol(const std::string_view input) {
12019
8.27k
  std::string view(input);
12020
8.27k
  helpers::remove_ascii_tab_or_newline(view);
12021
8.27k
  if (view.empty()) {
12022
5.29k
    return true;
12023
5.29k
  }
12024
12025
  // Schemes should start with alpha values.
12026
2.97k
  if (!checkers::is_alpha(view[0])) {
12027
2.41k
    return false;
12028
2.41k
  }
12029
12030
564
  view.append(":");
12031
12032
564
  std::string::iterator pointer =
12033
564
      std::find_if_not(view.begin(), view.end(), unicode::is_alnum_plus);
12034
12035
564
  if (pointer != view.end() && *pointer == ':') {
12036
360
    return parse_scheme<true>(
12037
360
        std::string_view(view.data(), pointer - view.begin()));
12038
360
  }
12039
204
  return false;
12040
564
}
12041
12042
0
bool url::set_href(const std::string_view input) {
12043
0
  ada::result<ada::url> out = ada::parse<ada::url>(input);
12044
12045
0
  if (out) {
12046
0
    username = out->username;
12047
0
    password = out->password;
12048
0
    host = out->host;
12049
0
    port = out->port;
12050
0
    path = out->path;
12051
0
    query = out->query;
12052
0
    hash = out->hash;
12053
0
    type = out->type;
12054
0
    non_special_scheme = out->non_special_scheme;
12055
0
    has_opaque_path = out->has_opaque_path;
12056
0
  }
12057
12058
0
  return out.has_value();
12059
0
}
12060
12061
}  // namespace ada
12062
/* end file src/url-setters.cpp */
12063
/* begin file src/parser.cpp */
12064
12065
#include <numeric>
12066
#include <limits>
12067
12068
namespace ada::parser {
12069
12070
template <class result_type>
12071
result_type parse_url(std::string_view user_input,
12072
59.9k
                      const result_type* base_url) {
12073
  // We can specialize the implementation per type.
12074
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
12075
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
12076
  // something else } is free (at runtime). This means that ada::url_aggregator
12077
  // and ada::url **do not have to support the exact same API**.
12078
59.9k
  constexpr bool result_type_is_ada_url =
12079
59.9k
      std::is_same<ada::url, result_type>::value;
12080
59.9k
  constexpr bool result_type_is_ada_url_aggregator =
12081
59.9k
      std::is_same<ada::url_aggregator, result_type>::value;
12082
59.9k
  static_assert(result_type_is_ada_url ||
12083
59.9k
                result_type_is_ada_url_aggregator);  // We don't support
12084
                                                     // anything else for now.
12085
12086
59.9k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
12087
59.9k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
12088
59.9k
          ")");
12089
12090
59.9k
  ada::state state = ada::state::SCHEME_START;
12091
59.9k
  result_type url{};
12092
12093
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
12094
  // surely the result of a bug or are otherwise a security concern.
12095
59.9k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) {
12096
2
    url.is_valid = false;
12097
2
  }
12098
  // Going forward, user_input.size() is in [0,
12099
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
12100
  // base, or the optional_url was invalid, we must return.
12101
59.9k
  if (base_url != nullptr) {
12102
2.66k
    url.is_valid &= base_url->is_valid;
12103
2.66k
  }
12104
59.9k
  if (!url.is_valid) {
12105
2
    return url;
12106
2
  }
12107
59.9k
  if constexpr (result_type_is_ada_url_aggregator) {
12108
    // Most of the time, we just need user_input.size().
12109
    // In some instances, we may need a bit more.
12110
    ///////////////////////////
12111
    // This is *very* important. This line should be removed
12112
    // hastily. There are principled reasons why reserve is important
12113
    // for performance. If you have a benchmark with small inputs,
12114
    // it may not matter, but in other instances, it could.
12115
    ////
12116
    // This rounds up to the next power of two.
12117
    // We know that user_input.size() is in [0,
12118
    // std::numeric_limits<uint32_t>::max).
12119
45.4k
    uint32_t reserve_capacity =
12120
45.4k
        (0xFFFFFFFF >>
12121
45.4k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
12122
45.4k
        1;
12123
45.4k
    url.reserve(reserve_capacity);
12124
    //
12125
    //
12126
    //
12127
45.4k
  }
12128
59.9k
  std::string tmp_buffer;
12129
59.9k
  std::string_view internal_input;
12130
59.9k
  if (unicode::has_tabs_or_newline(user_input)) {
12131
670
    tmp_buffer = user_input;
12132
    // Optimization opportunity: Instead of copying and then pruning, we could
12133
    // just directly build the string from user_input.
12134
670
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12135
670
    internal_input = tmp_buffer;
12136
59.2k
  } else {
12137
59.2k
    internal_input = user_input;
12138
59.2k
  }
12139
12140
  // Leading and trailing control characters are uncommon and easy to deal with
12141
  // (no performance concern).
12142
59.9k
  std::string_view url_data = internal_input;
12143
59.9k
  helpers::trim_c0_whitespace(url_data);
12144
12145
  // Optimization opportunity. Most websites do not have fragment.
12146
59.9k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
12147
  // We add it last so that an implementation like ada::url_aggregator
12148
  // can append it last to its internal buffer, thus improving performance.
12149
12150
  // Here url_data no longer has its fragment.
12151
  // We are going to access the data from url_data (it is immutable).
12152
  // At any given time, we are pointing at byte 'input_position' in url_data.
12153
  // The input_position variable should range from 0 to input_size.
12154
  // It is illegal to access url_data at input_size.
12155
59.9k
  size_t input_position = 0;
12156
59.9k
  const size_t input_size = url_data.size();
12157
  // Keep running the following state machine by switching on state.
12158
  // If after a run pointer points to the EOF code point, go to the next step.
12159
  // Otherwise, increase pointer by 1 and continue with the state machine.
12160
  // We never decrement input_position.
12161
244k
  while (input_position <= input_size) {
12162
229k
    ada_log("In parsing at ", input_position, " out of ", input_size,
12163
229k
            " in state ", ada::to_string(state));
12164
229k
    switch (state) {
12165
59.9k
      case ada::state::SCHEME_START: {
12166
59.9k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
12167
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
12168
        // state to scheme state.
12169
59.9k
        if ((input_position != input_size) &&
12170
59.9k
            checkers::is_alpha(url_data[input_position])) {
12171
37.6k
          state = ada::state::SCHEME;
12172
37.6k
          input_position++;
12173
37.6k
        } else {
12174
          // Otherwise, if state override is not given, set state to no scheme
12175
          // state and decrease pointer by 1.
12176
22.2k
          state = ada::state::NO_SCHEME;
12177
22.2k
        }
12178
59.9k
        break;
12179
0
      }
12180
37.6k
      case ada::state::SCHEME: {
12181
37.6k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
12182
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
12183
        // append c, lowercased, to buffer.
12184
125k
        while ((input_position != input_size) &&
12185
125k
               (ada::unicode::is_alnum_plus(url_data[input_position]))) {
12186
88.0k
          input_position++;
12187
88.0k
        }
12188
        // Otherwise, if c is U+003A (:), then:
12189
37.6k
        if ((input_position != input_size) &&
12190
37.6k
            (url_data[input_position] == ':')) {
12191
34.4k
          ada_log("SCHEME the scheme should be ",
12192
34.4k
                  url_data.substr(0, input_position));
12193
34.4k
          if constexpr (result_type_is_ada_url) {
12194
24.2k
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
12195
0
              return url;
12196
0
            }
12197
24.2k
          } else {
12198
            // we pass the colon along instead of painfully adding it back.
12199
24.2k
            if (!url.parse_scheme_with_colon(
12200
24.2k
                    url_data.substr(0, input_position + 1))) {
12201
0
              return url;
12202
0
            }
12203
24.2k
          }
12204
34.4k
          ada_log("SCHEME the scheme is ", url.get_protocol());
12205
12206
          // If url’s scheme is "file", then:
12207
34.4k
          if (url.type == ada::scheme::type::FILE) {
12208
            // Set state to file state.
12209
5.74k
            state = ada::state::FILE;
12210
5.74k
          }
12211
          // Otherwise, if url is special, base is non-null, and base’s scheme
12212
          // is url’s scheme: Note: Doing base_url->scheme is unsafe if base_url
12213
          // != nullptr is false.
12214
28.7k
          else if (url.is_special() && base_url != nullptr &&
12215
28.7k
                   base_url->type == url.type) {
12216
            // Set state to special relative or authority state.
12217
120
            state = ada::state::SPECIAL_RELATIVE_OR_AUTHORITY;
12218
120
          }
12219
          // Otherwise, if url is special, set state to special authority
12220
          // slashes state.
12221
28.6k
          else if (url.is_special()) {
12222
18.4k
            state = ada::state::SPECIAL_AUTHORITY_SLASHES;
12223
18.4k
          }
12224
          // Otherwise, if remaining starts with an U+002F (/), set state to
12225
          // path or authority state and increase pointer by 1.
12226
10.2k
          else if (input_position + 1 < input_size &&
12227
10.2k
                   url_data[input_position + 1] == '/') {
12228
5.76k
            state = ada::state::PATH_OR_AUTHORITY;
12229
5.76k
            input_position++;
12230
5.76k
          }
12231
          // Otherwise, set url’s path to the empty string and set state to
12232
          // opaque path state.
12233
4.43k
          else {
12234
4.43k
            state = ada::state::OPAQUE_PATH;
12235
4.43k
          }
12236
34.4k
        }
12237
        // Otherwise, if state override is not given, set buffer to the empty
12238
        // string, state to no scheme state, and start over (from the first code
12239
        // point in input).
12240
3.15k
        else {
12241
3.15k
          state = ada::state::NO_SCHEME;
12242
3.15k
          input_position = 0;
12243
3.15k
          break;
12244
3.15k
        }
12245
34.4k
        input_position++;
12246
34.4k
        break;
12247
37.6k
      }
12248
25.4k
      case ada::state::NO_SCHEME: {
12249
25.4k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
12250
        // If base is null, or base has an opaque path and c is not U+0023 (#),
12251
        // validation error, return failure.
12252
25.4k
        if (base_url == nullptr ||
12253
25.4k
            (base_url->has_opaque_path && !fragment.has_value())) {
12254
24.1k
          ada_log("NO_SCHEME validation error");
12255
24.1k
          url.is_valid = false;
12256
24.1k
          return url;
12257
24.1k
        }
12258
        // Otherwise, if base has an opaque path and c is U+0023 (#),
12259
        // set url’s scheme to base’s scheme, url’s path to base’s path, url’s
12260
        // query to base’s query, and set state to fragment state.
12261
1.24k
        else if (base_url->has_opaque_path && fragment.has_value() &&
12262
1.24k
                 input_position == input_size) {
12263
28
          ada_log("NO_SCHEME opaque base with fragment");
12264
28
          url.copy_scheme(*base_url);
12265
28
          url.has_opaque_path = base_url->has_opaque_path;
12266
12267
28
          if constexpr (result_type_is_ada_url) {
12268
28
            url.path = base_url->path;
12269
28
            url.query = base_url->query;
12270
28
          } else {
12271
28
            url.update_base_pathname(base_url->get_pathname());
12272
28
            url.update_base_search(base_url->get_search());
12273
28
          }
12274
28
          url.update_unencoded_base_hash(*fragment);
12275
28
          return url;
12276
28
        }
12277
        // Otherwise, if base’s scheme is not "file", set state to relative
12278
        // state and decrease pointer by 1.
12279
1.21k
        else if (base_url->type != ada::scheme::type::FILE) {
12280
657
          ada_log("NO_SCHEME non-file relative path");
12281
657
          state = ada::state::RELATIVE_SCHEME;
12282
657
        }
12283
        // Otherwise, set state to file state and decrease pointer by 1.
12284
562
        else {
12285
562
          ada_log("NO_SCHEME file base type");
12286
562
          state = ada::state::FILE;
12287
562
        }
12288
1.21k
        break;
12289
25.4k
      }
12290
19.6k
      case ada::state::AUTHORITY: {
12291
19.6k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
12292
        // most URLs have no @. Having no @ tells us that we don't have to worry
12293
        // about AUTHORITY. Of course, we could have @ and still not have to
12294
        // worry about AUTHORITY.
12295
        // TODO: Instead of just collecting a bool, collect the location of the
12296
        // '@' and do something useful with it.
12297
        // TODO: We could do various processing early on, using a single pass
12298
        // over the string to collect information about it, e.g., telling us
12299
        // whether there is a @ and if so, where (or how many).
12300
19.6k
        const bool contains_ampersand =
12301
19.6k
            (url_data.find('@', input_position) != std::string_view::npos);
12302
12303
19.6k
        if (!contains_ampersand) {
12304
18.2k
          state = ada::state::HOST;
12305
18.2k
          break;
12306
18.2k
        }
12307
1.40k
        bool at_sign_seen{false};
12308
1.40k
        bool password_token_seen{false};
12309
        /**
12310
         * We expect something of the sort...
12311
         * https://user:pass@example.com:1234/foo/bar?baz#quux
12312
         * --------^
12313
         */
12314
10.7k
        do {
12315
10.7k
          std::string_view view = helpers::substring(url_data, input_position);
12316
          // The delimiters are @, /, ? \\.
12317
10.7k
          size_t location =
12318
10.7k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
12319
10.7k
                               : helpers::find_authority_delimiter(view);
12320
10.7k
          std::string_view authority_view(view.data(), location);
12321
10.7k
          size_t end_of_authority = input_position + authority_view.size();
12322
          // If c is U+0040 (@), then:
12323
10.7k
          if ((end_of_authority != input_size) &&
12324
10.7k
              (url_data[end_of_authority] == '@')) {
12325
            // If atSignSeen is true, then prepend "%40" to buffer.
12326
9.36k
            if (at_sign_seen) {
12327
8.01k
              if (password_token_seen) {
12328
1.95k
                if constexpr (result_type_is_ada_url) {
12329
1.37k
                  url.password += "%40";
12330
1.37k
                } else {
12331
1.37k
                  url.append_base_password("%40");
12332
1.37k
                }
12333
6.06k
              } else {
12334
6.06k
                if constexpr (result_type_is_ada_url) {
12335
4.25k
                  url.username += "%40";
12336
4.25k
                } else {
12337
4.25k
                  url.append_base_username("%40");
12338
4.25k
                }
12339
6.06k
              }
12340
8.01k
            }
12341
12342
9.36k
            at_sign_seen = true;
12343
12344
9.36k
            if (!password_token_seen) {
12345
7.40k
              size_t password_token_location = authority_view.find(':');
12346
7.40k
              password_token_seen =
12347
7.40k
                  password_token_location != std::string_view::npos;
12348
12349
7.40k
              if (!password_token_seen) {
12350
6.94k
                if constexpr (result_type_is_ada_url) {
12351
4.85k
                  url.username += unicode::percent_encode(
12352
4.85k
                      authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12353
4.85k
                } else {
12354
4.85k
                  url.append_base_username(unicode::percent_encode(
12355
4.85k
                      authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12356
4.85k
                }
12357
6.94k
              } else {
12358
465
                if constexpr (result_type_is_ada_url) {
12359
325
                  url.username += unicode::percent_encode(
12360
325
                      authority_view.substr(0, password_token_location),
12361
325
                      character_sets::USERINFO_PERCENT_ENCODE);
12362
325
                  url.password += unicode::percent_encode(
12363
325
                      authority_view.substr(password_token_location + 1),
12364
325
                      character_sets::USERINFO_PERCENT_ENCODE);
12365
325
                } else {
12366
325
                  url.append_base_username(unicode::percent_encode(
12367
325
                      authority_view.substr(0, password_token_location),
12368
325
                      character_sets::USERINFO_PERCENT_ENCODE));
12369
325
                  url.append_base_password(unicode::percent_encode(
12370
325
                      authority_view.substr(password_token_location + 1),
12371
325
                      character_sets::USERINFO_PERCENT_ENCODE));
12372
325
                }
12373
465
              }
12374
7.40k
            } else {
12375
1.95k
              if constexpr (result_type_is_ada_url) {
12376
1.37k
                url.password += unicode::percent_encode(
12377
1.37k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12378
1.37k
              } else {
12379
1.37k
                url.append_base_password(unicode::percent_encode(
12380
1.37k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12381
1.37k
              }
12382
1.95k
            }
12383
9.36k
          }
12384
          // Otherwise, if one of the following is true:
12385
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12386
          // - url is special and c is U+005C (\)
12387
1.40k
          else if (end_of_authority == input_size ||
12388
1.40k
                   url_data[end_of_authority] == '/' ||
12389
1.40k
                   url_data[end_of_authority] == '?' ||
12390
1.40k
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
12391
            // If atSignSeen is true and authority_view is the empty string,
12392
            // validation error, return failure.
12393
1.40k
            if (at_sign_seen && authority_view.empty()) {
12394
745
              url.is_valid = false;
12395
745
              return url;
12396
745
            }
12397
656
            state = ada::state::HOST;
12398
656
            break;
12399
1.40k
          }
12400
9.36k
          if (end_of_authority == input_size) {
12401
0
            if (fragment.has_value()) {
12402
0
              url.update_unencoded_base_hash(*fragment);
12403
0
            }
12404
0
            return url;
12405
0
          }
12406
9.36k
          input_position = end_of_authority + 1;
12407
9.36k
        } while (true);
12408
12409
656
        break;
12410
1.40k
      }
12411
656
      case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY: {
12412
120
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
12413
120
                helpers::substring(url_data, input_position));
12414
12415
        // If c is U+002F (/) and remaining starts with U+002F (/),
12416
        // then set state to special authority ignore slashes state and increase
12417
        // pointer by 1.
12418
120
        std::string_view view = helpers::substring(url_data, input_position);
12419
120
        if (ada::checkers::begins_with(view, "//")) {
12420
2
          state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12421
2
          input_position += 2;
12422
118
        } else {
12423
          // Otherwise, validation error, set state to relative state and
12424
          // decrease pointer by 1.
12425
118
          state = ada::state::RELATIVE_SCHEME;
12426
118
        }
12427
12428
120
        break;
12429
1.40k
      }
12430
5.76k
      case ada::state::PATH_OR_AUTHORITY: {
12431
5.76k
        ada_log("PATH_OR_AUTHORITY ",
12432
5.76k
                helpers::substring(url_data, input_position));
12433
12434
        // If c is U+002F (/), then set state to authority state.
12435
5.76k
        if ((input_position != input_size) &&
12436
5.76k
            (url_data[input_position] == '/')) {
12437
1.17k
          state = ada::state::AUTHORITY;
12438
1.17k
          input_position++;
12439
4.59k
        } else {
12440
          // Otherwise, set state to path state, and decrease pointer by 1.
12441
4.59k
          state = ada::state::PATH;
12442
4.59k
        }
12443
12444
5.76k
        break;
12445
1.40k
      }
12446
775
      case ada::state::RELATIVE_SCHEME: {
12447
775
        ada_log("RELATIVE_SCHEME ",
12448
775
                helpers::substring(url_data, input_position));
12449
12450
        // Set url’s scheme to base’s scheme.
12451
775
        url.copy_scheme(*base_url);
12452
12453
        // If c is U+002F (/), then set state to relative slash state.
12454
775
        if ((input_position != input_size) &&
12455
775
            (url_data[input_position] == '/')) {
12456
43
          ada_log(
12457
43
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
12458
43
              "slash state");
12459
43
          state = ada::state::RELATIVE_SLASH;
12460
732
        } else if (url.is_special() && (input_position != input_size) &&
12461
732
                   (url_data[input_position] == '\\')) {
12462
          // Otherwise, if url is special and c is U+005C (\), validation error,
12463
          // set state to relative slash state.
12464
1
          ada_log(
12465
1
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
12466
1
              "error, set state to relative slash state");
12467
1
          state = ada::state::RELATIVE_SLASH;
12468
731
        } else {
12469
731
          ada_log("RELATIVE_SCHEME otherwise");
12470
          // Set url’s username to base’s username, url’s password to base’s
12471
          // password, url’s host to base’s host, url’s port to base’s port,
12472
          // url’s path to a clone of base’s path, and url’s query to base’s
12473
          // query.
12474
731
          if constexpr (result_type_is_ada_url) {
12475
731
            url.username = base_url->username;
12476
731
            url.password = base_url->password;
12477
731
            url.host = base_url->host;
12478
731
            url.port = base_url->port;
12479
            // cloning the base path includes cloning the has_opaque_path flag
12480
0
            url.has_opaque_path = base_url->has_opaque_path;
12481
0
            url.path = base_url->path;
12482
0
            url.query = base_url->query;
12483
731
          } else {
12484
731
            url.update_base_authority(base_url->get_href(),
12485
731
                                      base_url->get_components());
12486
            // TODO: Get rid of set_hostname and replace it with
12487
            // update_base_hostname
12488
731
            url.set_hostname(base_url->get_hostname());
12489
731
            url.update_base_port(base_url->retrieve_base_port());
12490
            // cloning the base path includes cloning the has_opaque_path flag
12491
731
            url.has_opaque_path = base_url->has_opaque_path;
12492
731
            url.update_base_pathname(base_url->get_pathname());
12493
731
            url.update_base_search(base_url->get_search());
12494
731
          }
12495
12496
731
          url.has_opaque_path = base_url->has_opaque_path;
12497
12498
          // If c is U+003F (?), then set url’s query to the empty string, and
12499
          // state to query state.
12500
731
          if ((input_position != input_size) &&
12501
731
              (url_data[input_position] == '?')) {
12502
5
            state = ada::state::QUERY;
12503
5
          }
12504
          // Otherwise, if c is not the EOF code point:
12505
726
          else if (input_position != input_size) {
12506
            // Set url’s query to null.
12507
233
            url.clear_search();
12508
233
            if constexpr (result_type_is_ada_url) {
12509
              // Shorten url’s path.
12510
0
              helpers::shorten_path(url.path, url.type);
12511
233
            } else {
12512
233
              std::string_view path = url.get_pathname();
12513
233
              if (helpers::shorten_path(path, url.type)) {
12514
197
                url.update_base_pathname(std::string(path));
12515
197
              }
12516
233
            }
12517
            // Set state to path state and decrease pointer by 1.
12518
233
            state = ada::state::PATH;
12519
233
            break;
12520
233
          }
12521
731
        }
12522
542
        input_position++;
12523
542
        break;
12524
775
      }
12525
44
      case ada::state::RELATIVE_SLASH: {
12526
44
        ada_log("RELATIVE_SLASH ",
12527
44
                helpers::substring(url_data, input_position));
12528
12529
        // If url is special and c is U+002F (/) or U+005C (\), then:
12530
44
        if (url.is_special() && (input_position != input_size) &&
12531
44
            (url_data[input_position] == '/' ||
12532
18
             url_data[input_position] == '\\')) {
12533
          // Set state to special authority ignore slashes state.
12534
3
          state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12535
3
        }
12536
        // Otherwise, if c is U+002F (/), then set state to authority state.
12537
41
        else if ((input_position != input_size) &&
12538
41
                 (url_data[input_position] == '/')) {
12539
5
          state = ada::state::AUTHORITY;
12540
5
        }
12541
        // Otherwise, set
12542
        // - url’s username to base’s username,
12543
        // - url’s password to base’s password,
12544
        // - url’s host to base’s host,
12545
        // - url’s port to base’s port,
12546
        // - state to path state, and then, decrease pointer by 1.
12547
36
        else {
12548
36
          if constexpr (result_type_is_ada_url) {
12549
36
            url.username = base_url->username;
12550
36
            url.password = base_url->password;
12551
36
            url.host = base_url->host;
12552
36
            url.port = base_url->port;
12553
36
          } else {
12554
36
            url.update_base_authority(base_url->get_href(),
12555
36
                                      base_url->get_components());
12556
            // TODO: Get rid of set_hostname and replace it with
12557
            // update_base_hostname
12558
36
            url.set_hostname(base_url->get_hostname());
12559
36
            url.update_base_port(base_url->retrieve_base_port());
12560
36
          }
12561
36
          state = ada::state::PATH;
12562
36
          break;
12563
36
        }
12564
12565
8
        input_position++;
12566
8
        break;
12567
44
      }
12568
18.4k
      case ada::state::SPECIAL_AUTHORITY_SLASHES: {
12569
18.4k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
12570
18.4k
                helpers::substring(url_data, input_position));
12571
12572
        // If c is U+002F (/) and remaining starts with U+002F (/),
12573
        // then set state to special authority ignore slashes state and increase
12574
        // pointer by 1.
12575
18.4k
        state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12576
18.4k
        std::string_view view = helpers::substring(url_data, input_position);
12577
18.4k
        if (ada::checkers::begins_with(view, "//")) {
12578
48
          input_position += 2;
12579
48
        }
12580
12581
18.4k
        [[fallthrough]];
12582
18.4k
      }
12583
18.4k
      case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
12584
18.4k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
12585
18.4k
                helpers::substring(url_data, input_position));
12586
12587
        // If c is neither U+002F (/) nor U+005C (\), then set state to
12588
        // authority state and decrease pointer by 1.
12589
20.1k
        while ((input_position != input_size) &&
12590
20.1k
               ((url_data[input_position] == '/') ||
12591
19.9k
                (url_data[input_position] == '\\'))) {
12592
1.68k
          input_position++;
12593
1.68k
        }
12594
18.4k
        state = ada::state::AUTHORITY;
12595
12596
18.4k
        break;
12597
18.4k
      }
12598
955
      case ada::state::QUERY: {
12599
955
        ada_log("QUERY ", helpers::substring(url_data, input_position));
12600
        // Let queryPercentEncodeSet be the special-query percent-encode set if
12601
        // url is special; otherwise the query percent-encode set.
12602
955
        const uint8_t* query_percent_encode_set =
12603
955
            url.is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12604
955
                             : ada::character_sets::QUERY_PERCENT_ENCODE;
12605
12606
        // Percent-encode after encoding, with encoding, buffer, and
12607
        // queryPercentEncodeSet, and append the result to url’s query.
12608
955
        url.update_base_search(helpers::substring(url_data, input_position),
12609
955
                               query_percent_encode_set);
12610
955
        ada_log("QUERY update_base_search completed ");
12611
955
        if (fragment.has_value()) {
12612
106
          url.update_unencoded_base_hash(*fragment);
12613
106
        }
12614
955
        return url;
12615
18.4k
      }
12616
18.8k
      case ada::state::HOST: {
12617
18.8k
        ada_log("HOST ", helpers::substring(url_data, input_position));
12618
12619
18.8k
        std::string_view host_view =
12620
18.8k
            helpers::substring(url_data, input_position);
12621
18.8k
        auto [location, found_colon] =
12622
18.8k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
12623
18.8k
        input_position = (location != std::string_view::npos)
12624
18.8k
                             ? input_position + location
12625
18.8k
                             : input_size;
12626
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12627
        // Note: the 'found_colon' value is true if and only if a colon was
12628
        // encountered while not inside brackets.
12629
18.8k
        if (found_colon) {
12630
          // If buffer is the empty string, validation error, return failure.
12631
          // Let host be the result of host parsing buffer with url is not
12632
          // special.
12633
2.81k
          ada_log("HOST parsing ", host_view);
12634
2.81k
          if (!url.parse_host(host_view)) {
12635
434
            return url;
12636
434
          }
12637
2.37k
          ada_log("HOST parsing results in ", url.get_hostname());
12638
          // Set url’s host to host, buffer to the empty string, and state to
12639
          // port state.
12640
2.37k
          state = ada::state::PORT;
12641
2.37k
          input_position++;
12642
2.37k
        }
12643
        // Otherwise, if one of the following is true:
12644
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12645
        // - url is special and c is U+005C (\)
12646
        // The get_host_delimiter_location function either brings us to
12647
        // the colon outside of the bracket, or to one of those characters.
12648
16.0k
        else {
12649
          // If url is special and host_view is the empty string, validation
12650
          // error, return failure.
12651
16.0k
          if (url.is_special() && host_view.empty()) {
12652
143
            url.is_valid = false;
12653
143
            return url;
12654
143
          }
12655
15.9k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
12656
          // Let host be the result of host parsing host_view with url is not
12657
          // special.
12658
15.9k
          if (host_view.empty()) {
12659
103
            url.update_base_hostname("");
12660
15.8k
          } else if (!url.parse_host(host_view)) {
12661
3.79k
            return url;
12662
3.79k
          }
12663
12.1k
          ada_log("HOST parsing results in ", url.get_hostname(),
12664
12.1k
                  " href=", url.get_href());
12665
12666
          // Set url’s host to host, and state to path start state.
12667
12.1k
          state = ada::state::PATH_START;
12668
12.1k
        }
12669
12670
14.4k
        break;
12671
18.8k
      }
12672
14.4k
      case ada::state::OPAQUE_PATH: {
12673
4.43k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
12674
4.43k
        std::string_view view = helpers::substring(url_data, input_position);
12675
        // If c is U+003F (?), then set url’s query to the empty string and
12676
        // state to query state.
12677
4.43k
        size_t location = view.find('?');
12678
4.43k
        if (location != std::string_view::npos) {
12679
310
          view.remove_suffix(view.size() - location);
12680
310
          state = ada::state::QUERY;
12681
310
          input_position += location + 1;
12682
4.12k
        } else {
12683
4.12k
          input_position = input_size + 1;
12684
4.12k
        }
12685
4.43k
        url.has_opaque_path = true;
12686
        // This is a really unlikely scenario in real world. We should not seek
12687
        // to optimize it.
12688
4.43k
        url.update_base_pathname(unicode::percent_encode(
12689
4.43k
            view, character_sets::C0_CONTROL_PERCENT_ENCODE));
12690
4.43k
        break;
12691
18.8k
      }
12692
2.37k
      case ada::state::PORT: {
12693
2.37k
        ada_log("PORT ", helpers::substring(url_data, input_position));
12694
2.37k
        std::string_view port_view =
12695
2.37k
            helpers::substring(url_data, input_position);
12696
2.37k
        size_t consumed_bytes = url.parse_port(port_view, true);
12697
2.37k
        input_position += consumed_bytes;
12698
2.37k
        if (!url.is_valid) {
12699
271
          return url;
12700
271
        }
12701
2.10k
        state = state::PATH_START;
12702
2.10k
        [[fallthrough]];
12703
2.10k
      }
12704
15.8k
      case ada::state::PATH_START: {
12705
15.8k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
12706
12707
        // If url is special, then:
12708
15.8k
        if (url.is_special()) {
12709
          // Set state to path state.
12710
15.0k
          state = ada::state::PATH;
12711
12712
          // Optimization: Avoiding going into PATH state improves the
12713
          // performance of urls ending with /.
12714
15.0k
          if (input_position == input_size) {
12715
13.7k
            url.update_base_pathname("/");
12716
13.7k
            if (fragment.has_value()) {
12717
256
              url.update_unencoded_base_hash(*fragment);
12718
256
            }
12719
13.7k
            return url;
12720
13.7k
          }
12721
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
12722
          // by 1. We know that (input_position == input_size) is impossible
12723
          // here, because of the previous if-check.
12724
1.36k
          if ((url_data[input_position] != '/') &&
12725
1.36k
              (url_data[input_position] != '\\')) {
12726
289
            break;
12727
289
          }
12728
1.36k
        }
12729
        // Otherwise, if state override is not given and c is U+003F (?),
12730
        // set url’s query to the empty string and state to query state.
12731
829
        else if ((input_position != input_size) &&
12732
829
                 (url_data[input_position] == '?')) {
12733
86
          state = ada::state::QUERY;
12734
86
        }
12735
        // Otherwise, if c is not the EOF code point:
12736
743
        else if (input_position != input_size) {
12737
          // Set state to path state.
12738
93
          state = ada::state::PATH;
12739
12740
          // If c is not U+002F (/), then decrease pointer by 1.
12741
93
          if (url_data[input_position] != '/') {
12742
0
            break;
12743
0
          }
12744
93
        }
12745
12746
1.90k
        input_position++;
12747
1.90k
        break;
12748
15.8k
      }
12749
10.2k
      case ada::state::PATH: {
12750
10.2k
        std::string_view view = helpers::substring(url_data, input_position);
12751
10.2k
        ada_log("PATH ", helpers::substring(url_data, input_position));
12752
12753
        // Most time, we do not need percent encoding.
12754
        // Furthermore, we can immediately locate the '?'.
12755
10.2k
        size_t locofquestionmark = view.find('?');
12756
10.2k
        if (locofquestionmark != std::string_view::npos) {
12757
552
          state = ada::state::QUERY;
12758
552
          view.remove_suffix(view.size() - locofquestionmark);
12759
552
          input_position += locofquestionmark + 1;
12760
9.72k
        } else {
12761
9.72k
          input_position = input_size + 1;
12762
9.72k
        }
12763
10.2k
        if constexpr (result_type_is_ada_url) {
12764
7.26k
          helpers::parse_prepared_path(view, url.type, url.path);
12765
7.26k
        } else {
12766
7.26k
          url.consume_prepared_path(view);
12767
7.26k
          ADA_ASSERT_TRUE(url.validate());
12768
7.26k
        }
12769
10.2k
        break;
12770
15.8k
      }
12771
2.53k
      case ada::state::FILE_SLASH: {
12772
2.53k
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
12773
12774
        // If c is U+002F (/) or U+005C (\), then:
12775
2.53k
        if ((input_position != input_size) &&
12776
2.53k
            (url_data[input_position] == '/' ||
12777
2.20k
             url_data[input_position] == '\\')) {
12778
2.10k
          ada_log("FILE_SLASH c is U+002F or U+005C");
12779
          // Set state to file host state.
12780
2.10k
          state = ada::state::FILE_HOST;
12781
2.10k
          input_position++;
12782
2.10k
        } else {
12783
429
          ada_log("FILE_SLASH otherwise");
12784
          // If base is non-null and base’s scheme is "file", then:
12785
          // Note: it is unsafe to do base_url->scheme unless you know that
12786
          // base_url_has_value() is true.
12787
429
          if (base_url != nullptr &&
12788
429
              base_url->type == ada::scheme::type::FILE) {
12789
            // Set url’s host to base’s host.
12790
261
            if constexpr (result_type_is_ada_url) {
12791
261
              url.host = base_url->host;
12792
261
            } else {
12793
              // TODO: Optimization opportunity.
12794
261
              url.set_host(base_url->get_host());
12795
261
            }
12796
            // If the code point substring from pointer to the end of input does
12797
            // not start with a Windows drive letter and base’s path[0] is a
12798
            // normalized Windows drive letter, then append base’s path[0] to
12799
            // url’s path.
12800
261
            if (!base_url->get_pathname().empty()) {
12801
261
              if (!checkers::is_windows_drive_letter(
12802
261
                      helpers::substring(url_data, input_position))) {
12803
256
                std::string_view first_base_url_path =
12804
256
                    base_url->get_pathname().substr(1);
12805
256
                size_t loc = first_base_url_path.find('/');
12806
256
                if (loc != std::string_view::npos) {
12807
12
                  helpers::resize(first_base_url_path, loc);
12808
12
                }
12809
256
                if (checkers::is_normalized_windows_drive_letter(
12810
256
                        first_base_url_path)) {
12811
3
                  if constexpr (result_type_is_ada_url) {
12812
3
                    url.path += '/';
12813
3
                    url.path += first_base_url_path;
12814
3
                  } else {
12815
3
                    url.append_base_pathname(
12816
3
                        helpers::concat("/", first_base_url_path));
12817
3
                  }
12818
3
                }
12819
256
              }
12820
261
            }
12821
261
          }
12822
12823
          // Set state to path state, and decrease pointer by 1.
12824
429
          state = ada::state::PATH;
12825
429
        }
12826
12827
2.53k
        break;
12828
15.8k
      }
12829
2.10k
      case ada::state::FILE_HOST: {
12830
2.10k
        std::string_view view = helpers::substring(url_data, input_position);
12831
2.10k
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
12832
12833
2.10k
        size_t location = view.find_first_of("/\\?");
12834
2.10k
        std::string_view file_host_buffer(
12835
2.10k
            view.data(),
12836
2.10k
            (location != std::string_view::npos) ? location : view.size());
12837
12838
2.10k
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
12839
29
          state = ada::state::PATH;
12840
2.07k
        } else if (file_host_buffer.empty()) {
12841
          // Set url’s host to the empty string.
12842
57
          if constexpr (result_type_is_ada_url) {
12843
43
            url.host = "";
12844
43
          } else {
12845
43
            url.update_base_hostname("");
12846
43
          }
12847
          // Set state to path start state.
12848
57
          state = ada::state::PATH_START;
12849
2.02k
        } else {
12850
2.02k
          size_t consumed_bytes = file_host_buffer.size();
12851
2.02k
          input_position += consumed_bytes;
12852
          // Let host be the result of host parsing buffer with url is not
12853
          // special.
12854
2.02k
          if (!url.parse_host(file_host_buffer)) {
12855
392
            return url;
12856
392
          }
12857
12858
1.62k
          if constexpr (result_type_is_ada_url) {
12859
            // If host is "localhost", then set host to the empty string.
12860
1.26k
            if (url.host.has_value() && url.host.value() == "localhost") {
12861
3
              url.host = "";
12862
3
            }
12863
1.26k
          } else {
12864
1.26k
            if (url.get_hostname() == "localhost") {
12865
10
              url.update_base_hostname("");
12866
10
            }
12867
1.26k
          }
12868
12869
          // Set buffer to the empty string and state to path start state.
12870
1.62k
          state = ada::state::PATH_START;
12871
1.62k
        }
12872
12873
1.71k
        break;
12874
2.10k
      }
12875
6.31k
      case ada::state::FILE: {
12876
6.31k
        ada_log("FILE ", helpers::substring(url_data, input_position));
12877
6.31k
        std::string_view file_view =
12878
6.31k
            helpers::substring(url_data, input_position);
12879
12880
6.31k
        url.set_protocol_as_file();
12881
6.31k
        if constexpr (result_type_is_ada_url) {
12882
          // Set url’s host to the empty string.
12883
1.61k
          url.host = "";
12884
4.69k
        } else {
12885
4.69k
          url.update_base_hostname("");
12886
4.69k
        }
12887
        // If c is U+002F (/) or U+005C (\), then:
12888
6.31k
        if (input_position != input_size &&
12889
6.31k
            (url_data[input_position] == '/' ||
12890
3.83k
             url_data[input_position] == '\\')) {
12891
2.53k
          ada_log("FILE c is U+002F or U+005C");
12892
          // Set state to file slash state.
12893
2.53k
          state = ada::state::FILE_SLASH;
12894
2.53k
        }
12895
        // Otherwise, if base is non-null and base’s scheme is "file":
12896
3.77k
        else if (base_url != nullptr &&
12897
3.77k
                 base_url->type == ada::scheme::type::FILE) {
12898
          // Set url’s host to base’s host, url’s path to a clone of base’s
12899
          // path, and url’s query to base’s query.
12900
380
          ada_log("FILE base non-null");
12901
380
          if constexpr (result_type_is_ada_url) {
12902
380
            url.host = base_url->host;
12903
380
            url.path = base_url->path;
12904
380
            url.query = base_url->query;
12905
380
          } else {
12906
            // TODO: Get rid of set_hostname and replace it with
12907
            // update_base_hostname
12908
380
            url.set_hostname(base_url->get_hostname());
12909
380
            url.update_base_pathname(base_url->get_pathname());
12910
380
            url.update_base_search(base_url->get_search());
12911
380
          }
12912
380
          url.has_opaque_path = base_url->has_opaque_path;
12913
12914
          // If c is U+003F (?), then set url’s query to the empty string and
12915
          // state to query state.
12916
380
          if (input_position != input_size && url_data[input_position] == '?') {
12917
2
            state = ada::state::QUERY;
12918
2
          }
12919
          // Otherwise, if c is not the EOF code point:
12920
378
          else if (input_position != input_size) {
12921
            // Set url’s query to null.
12922
105
            url.clear_search();
12923
            // If the code point substring from pointer to the end of input does
12924
            // not start with a Windows drive letter, then shorten url’s path.
12925
105
            if (!checkers::is_windows_drive_letter(file_view)) {
12926
93
              if constexpr (result_type_is_ada_url) {
12927
93
                helpers::shorten_path(url.path, url.type);
12928
93
              } else {
12929
93
                std::string_view path = url.get_pathname();
12930
93
                if (helpers::shorten_path(path, url.type)) {
12931
85
                  url.update_base_pathname(std::string(path));
12932
85
                }
12933
93
              }
12934
93
            }
12935
            // Otherwise:
12936
12
            else {
12937
              // Set url’s path to an empty list.
12938
12
              url.clear_pathname();
12939
12
              url.has_opaque_path = true;
12940
12
            }
12941
12942
            // Set state to path state and decrease pointer by 1.
12943
105
            state = ada::state::PATH;
12944
105
            break;
12945
105
          }
12946
380
        }
12947
        // Otherwise, set state to path state, and decrease pointer by 1.
12948
3.39k
        else {
12949
3.39k
          ada_log("FILE go to path");
12950
3.39k
          state = ada::state::PATH;
12951
3.39k
          break;
12952
3.39k
        }
12953
12954
2.81k
        input_position++;
12955
2.81k
        break;
12956
6.31k
      }
12957
0
      default:
12958
0
        ada::unreachable();
12959
229k
    }
12960
229k
  }
12961
15.2k
  if (fragment.has_value()) {
12962
565
    url.update_unencoded_base_hash(*fragment);
12963
565
  }
12964
15.2k
  return url;
12965
59.9k
}
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
12072
14.5k
                      const result_type* base_url) {
12073
  // We can specialize the implementation per type.
12074
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
12075
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
12076
  // something else } is free (at runtime). This means that ada::url_aggregator
12077
  // and ada::url **do not have to support the exact same API**.
12078
14.5k
  constexpr bool result_type_is_ada_url =
12079
14.5k
      std::is_same<ada::url, result_type>::value;
12080
14.5k
  constexpr bool result_type_is_ada_url_aggregator =
12081
14.5k
      std::is_same<ada::url_aggregator, result_type>::value;
12082
14.5k
  static_assert(result_type_is_ada_url ||
12083
14.5k
                result_type_is_ada_url_aggregator);  // We don't support
12084
                                                     // anything else for now.
12085
12086
14.5k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
12087
14.5k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
12088
14.5k
          ")");
12089
12090
14.5k
  ada::state state = ada::state::SCHEME_START;
12091
14.5k
  result_type url{};
12092
12093
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
12094
  // surely the result of a bug or are otherwise a security concern.
12095
14.5k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) {
12096
0
    url.is_valid = false;
12097
0
  }
12098
  // Going forward, user_input.size() is in [0,
12099
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
12100
  // base, or the optional_url was invalid, we must return.
12101
14.5k
  if (base_url != nullptr) {
12102
0
    url.is_valid &= base_url->is_valid;
12103
0
  }
12104
14.5k
  if (!url.is_valid) {
12105
0
    return url;
12106
0
  }
12107
14.5k
  if constexpr (result_type_is_ada_url_aggregator) {
12108
    // Most of the time, we just need user_input.size().
12109
    // In some instances, we may need a bit more.
12110
    ///////////////////////////
12111
    // This is *very* important. This line should be removed
12112
    // hastily. There are principled reasons why reserve is important
12113
    // for performance. If you have a benchmark with small inputs,
12114
    // it may not matter, but in other instances, it could.
12115
    ////
12116
    // This rounds up to the next power of two.
12117
    // We know that user_input.size() is in [0,
12118
    // std::numeric_limits<uint32_t>::max).
12119
14.5k
    uint32_t reserve_capacity =
12120
14.5k
        (0xFFFFFFFF >>
12121
14.5k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
12122
14.5k
        1;
12123
14.5k
    url.reserve(reserve_capacity);
12124
    //
12125
    //
12126
    //
12127
14.5k
  }
12128
14.5k
  std::string tmp_buffer;
12129
14.5k
  std::string_view internal_input;
12130
14.5k
  if (unicode::has_tabs_or_newline(user_input)) {
12131
202
    tmp_buffer = user_input;
12132
    // Optimization opportunity: Instead of copying and then pruning, we could
12133
    // just directly build the string from user_input.
12134
202
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12135
202
    internal_input = tmp_buffer;
12136
14.3k
  } else {
12137
14.3k
    internal_input = user_input;
12138
14.3k
  }
12139
12140
  // Leading and trailing control characters are uncommon and easy to deal with
12141
  // (no performance concern).
12142
14.5k
  std::string_view url_data = internal_input;
12143
14.5k
  helpers::trim_c0_whitespace(url_data);
12144
12145
  // Optimization opportunity. Most websites do not have fragment.
12146
14.5k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
12147
  // We add it last so that an implementation like ada::url_aggregator
12148
  // can append it last to its internal buffer, thus improving performance.
12149
12150
  // Here url_data no longer has its fragment.
12151
  // We are going to access the data from url_data (it is immutable).
12152
  // At any given time, we are pointing at byte 'input_position' in url_data.
12153
  // The input_position variable should range from 0 to input_size.
12154
  // It is illegal to access url_data at input_size.
12155
14.5k
  size_t input_position = 0;
12156
14.5k
  const size_t input_size = url_data.size();
12157
  // Keep running the following state machine by switching on state.
12158
  // If after a run pointer points to the EOF code point, go to the next step.
12159
  // Otherwise, increase pointer by 1 and continue with the state machine.
12160
  // We never decrement input_position.
12161
65.3k
  while (input_position <= input_size) {
12162
61.2k
    ada_log("In parsing at ", input_position, " out of ", input_size,
12163
61.2k
            " in state ", ada::to_string(state));
12164
61.2k
    switch (state) {
12165
14.5k
      case ada::state::SCHEME_START: {
12166
14.5k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
12167
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
12168
        // state to scheme state.
12169
14.5k
        if ((input_position != input_size) &&
12170
14.5k
            checkers::is_alpha(url_data[input_position])) {
12171
11.2k
          state = ada::state::SCHEME;
12172
11.2k
          input_position++;
12173
11.2k
        } else {
12174
          // Otherwise, if state override is not given, set state to no scheme
12175
          // state and decrease pointer by 1.
12176
3.27k
          state = ada::state::NO_SCHEME;
12177
3.27k
        }
12178
14.5k
        break;
12179
0
      }
12180
11.2k
      case ada::state::SCHEME: {
12181
11.2k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
12182
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
12183
        // append c, lowercased, to buffer.
12184
38.6k
        while ((input_position != input_size) &&
12185
38.6k
               (ada::unicode::is_alnum_plus(url_data[input_position]))) {
12186
27.3k
          input_position++;
12187
27.3k
        }
12188
        // Otherwise, if c is U+003A (:), then:
12189
11.2k
        if ((input_position != input_size) &&
12190
11.2k
            (url_data[input_position] == ':')) {
12191
10.2k
          ada_log("SCHEME the scheme should be ",
12192
10.2k
                  url_data.substr(0, input_position));
12193
10.2k
          if constexpr (result_type_is_ada_url) {
12194
10.2k
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
12195
0
              return url;
12196
0
            }
12197
10.2k
          } else {
12198
            // we pass the colon along instead of painfully adding it back.
12199
10.2k
            if (!url.parse_scheme_with_colon(
12200
10.2k
                    url_data.substr(0, input_position + 1))) {
12201
10.2k
              return url;
12202
10.2k
            }
12203
10.2k
          }
12204
10.2k
          ada_log("SCHEME the scheme is ", url.get_protocol());
12205
12206
          // If url’s scheme is "file", then:
12207
10.2k
          if (url.type == ada::scheme::type::FILE) {
12208
            // Set state to file state.
12209
1.61k
            state = ada::state::FILE;
12210
1.61k
          }
12211
          // Otherwise, if url is special, base is non-null, and base’s scheme
12212
          // is url’s scheme: Note: Doing base_url->scheme is unsafe if base_url
12213
          // != nullptr is false.
12214
8.60k
          else if (url.is_special() && base_url != nullptr &&
12215
8.60k
                   base_url->type == url.type) {
12216
            // Set state to special relative or authority state.
12217
0
            state = ada::state::SPECIAL_RELATIVE_OR_AUTHORITY;
12218
0
          }
12219
          // Otherwise, if url is special, set state to special authority
12220
          // slashes state.
12221
8.60k
          else if (url.is_special()) {
12222
5.66k
            state = ada::state::SPECIAL_AUTHORITY_SLASHES;
12223
5.66k
          }
12224
          // Otherwise, if remaining starts with an U+002F (/), set state to
12225
          // path or authority state and increase pointer by 1.
12226
2.94k
          else if (input_position + 1 < input_size &&
12227
2.94k
                   url_data[input_position + 1] == '/') {
12228
1.85k
            state = ada::state::PATH_OR_AUTHORITY;
12229
1.85k
            input_position++;
12230
1.85k
          }
12231
          // Otherwise, set url’s path to the empty string and set state to
12232
          // opaque path state.
12233
1.09k
          else {
12234
1.09k
            state = ada::state::OPAQUE_PATH;
12235
1.09k
          }
12236
10.2k
        }
12237
        // Otherwise, if state override is not given, set buffer to the empty
12238
        // string, state to no scheme state, and start over (from the first code
12239
        // point in input).
12240
1.00k
        else {
12241
1.00k
          state = ada::state::NO_SCHEME;
12242
1.00k
          input_position = 0;
12243
1.00k
          break;
12244
1.00k
        }
12245
10.2k
        input_position++;
12246
10.2k
        break;
12247
11.2k
      }
12248
4.28k
      case ada::state::NO_SCHEME: {
12249
4.28k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
12250
        // If base is null, or base has an opaque path and c is not U+0023 (#),
12251
        // validation error, return failure.
12252
4.28k
        if (base_url == nullptr ||
12253
4.28k
            (base_url->has_opaque_path && !fragment.has_value())) {
12254
4.28k
          ada_log("NO_SCHEME validation error");
12255
4.28k
          url.is_valid = false;
12256
4.28k
          return url;
12257
4.28k
        }
12258
        // Otherwise, if base has an opaque path and c is U+0023 (#),
12259
        // set url’s scheme to base’s scheme, url’s path to base’s path, url’s
12260
        // query to base’s query, and set state to fragment state.
12261
0
        else if (base_url->has_opaque_path && fragment.has_value() &&
12262
0
                 input_position == input_size) {
12263
0
          ada_log("NO_SCHEME opaque base with fragment");
12264
0
          url.copy_scheme(*base_url);
12265
0
          url.has_opaque_path = base_url->has_opaque_path;
12266
12267
0
          if constexpr (result_type_is_ada_url) {
12268
0
            url.path = base_url->path;
12269
0
            url.query = base_url->query;
12270
0
          } else {
12271
0
            url.update_base_pathname(base_url->get_pathname());
12272
0
            url.update_base_search(base_url->get_search());
12273
0
          }
12274
0
          url.update_unencoded_base_hash(*fragment);
12275
0
          return url;
12276
0
        }
12277
        // Otherwise, if base’s scheme is not "file", set state to relative
12278
        // state and decrease pointer by 1.
12279
0
        else if (base_url->type != ada::scheme::type::FILE) {
12280
0
          ada_log("NO_SCHEME non-file relative path");
12281
0
          state = ada::state::RELATIVE_SCHEME;
12282
0
        }
12283
        // Otherwise, set state to file state and decrease pointer by 1.
12284
0
        else {
12285
0
          ada_log("NO_SCHEME file base type");
12286
0
          state = ada::state::FILE;
12287
0
        }
12288
0
        break;
12289
4.28k
      }
12290
6.03k
      case ada::state::AUTHORITY: {
12291
6.03k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
12292
        // most URLs have no @. Having no @ tells us that we don't have to worry
12293
        // about AUTHORITY. Of course, we could have @ and still not have to
12294
        // worry about AUTHORITY.
12295
        // TODO: Instead of just collecting a bool, collect the location of the
12296
        // '@' and do something useful with it.
12297
        // TODO: We could do various processing early on, using a single pass
12298
        // over the string to collect information about it, e.g., telling us
12299
        // whether there is a @ and if so, where (or how many).
12300
6.03k
        const bool contains_ampersand =
12301
6.03k
            (url_data.find('@', input_position) != std::string_view::npos);
12302
12303
6.03k
        if (!contains_ampersand) {
12304
5.60k
          state = ada::state::HOST;
12305
5.60k
          break;
12306
5.60k
        }
12307
431
        bool at_sign_seen{false};
12308
431
        bool password_token_seen{false};
12309
        /**
12310
         * We expect something of the sort...
12311
         * https://user:pass@example.com:1234/foo/bar?baz#quux
12312
         * --------^
12313
         */
12314
3.23k
        do {
12315
3.23k
          std::string_view view = helpers::substring(url_data, input_position);
12316
          // The delimiters are @, /, ? \\.
12317
3.23k
          size_t location =
12318
3.23k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
12319
3.23k
                               : helpers::find_authority_delimiter(view);
12320
3.23k
          std::string_view authority_view(view.data(), location);
12321
3.23k
          size_t end_of_authority = input_position + authority_view.size();
12322
          // If c is U+0040 (@), then:
12323
3.23k
          if ((end_of_authority != input_size) &&
12324
3.23k
              (url_data[end_of_authority] == '@')) {
12325
            // If atSignSeen is true, then prepend "%40" to buffer.
12326
2.80k
            if (at_sign_seen) {
12327
2.39k
              if (password_token_seen) {
12328
580
                if constexpr (result_type_is_ada_url) {
12329
580
                  url.password += "%40";
12330
580
                } else {
12331
580
                  url.append_base_password("%40");
12332
580
                }
12333
1.81k
              } else {
12334
1.81k
                if constexpr (result_type_is_ada_url) {
12335
1.81k
                  url.username += "%40";
12336
1.81k
                } else {
12337
1.81k
                  url.append_base_username("%40");
12338
1.81k
                }
12339
1.81k
              }
12340
2.39k
            }
12341
12342
2.80k
            at_sign_seen = true;
12343
12344
2.80k
            if (!password_token_seen) {
12345
2.22k
              size_t password_token_location = authority_view.find(':');
12346
2.22k
              password_token_seen =
12347
2.22k
                  password_token_location != std::string_view::npos;
12348
12349
2.22k
              if (!password_token_seen) {
12350
2.08k
                if constexpr (result_type_is_ada_url) {
12351
2.08k
                  url.username += unicode::percent_encode(
12352
2.08k
                      authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12353
2.08k
                } else {
12354
2.08k
                  url.append_base_username(unicode::percent_encode(
12355
2.08k
                      authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12356
2.08k
                }
12357
2.08k
              } else {
12358
140
                if constexpr (result_type_is_ada_url) {
12359
140
                  url.username += unicode::percent_encode(
12360
140
                      authority_view.substr(0, password_token_location),
12361
140
                      character_sets::USERINFO_PERCENT_ENCODE);
12362
140
                  url.password += unicode::percent_encode(
12363
140
                      authority_view.substr(password_token_location + 1),
12364
140
                      character_sets::USERINFO_PERCENT_ENCODE);
12365
140
                } else {
12366
140
                  url.append_base_username(unicode::percent_encode(
12367
140
                      authority_view.substr(0, password_token_location),
12368
140
                      character_sets::USERINFO_PERCENT_ENCODE));
12369
140
                  url.append_base_password(unicode::percent_encode(
12370
140
                      authority_view.substr(password_token_location + 1),
12371
140
                      character_sets::USERINFO_PERCENT_ENCODE));
12372
140
                }
12373
140
              }
12374
2.22k
            } else {
12375
580
              if constexpr (result_type_is_ada_url) {
12376
580
                url.password += unicode::percent_encode(
12377
580
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12378
580
              } else {
12379
580
                url.append_base_password(unicode::percent_encode(
12380
580
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12381
580
              }
12382
580
            }
12383
2.80k
          }
12384
          // Otherwise, if one of the following is true:
12385
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12386
          // - url is special and c is U+005C (\)
12387
431
          else if (end_of_authority == input_size ||
12388
431
                   url_data[end_of_authority] == '/' ||
12389
431
                   url_data[end_of_authority] == '?' ||
12390
431
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
12391
            // If atSignSeen is true and authority_view is the empty string,
12392
            // validation error, return failure.
12393
431
            if (at_sign_seen && authority_view.empty()) {
12394
232
              url.is_valid = false;
12395
232
              return url;
12396
232
            }
12397
199
            state = ada::state::HOST;
12398
199
            break;
12399
431
          }
12400
2.80k
          if (end_of_authority == input_size) {
12401
0
            if (fragment.has_value()) {
12402
0
              url.update_unencoded_base_hash(*fragment);
12403
0
            }
12404
0
            return url;
12405
0
          }
12406
2.80k
          input_position = end_of_authority + 1;
12407
2.80k
        } while (true);
12408
12409
199
        break;
12410
431
      }
12411
199
      case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY: {
12412
0
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
12413
0
                helpers::substring(url_data, input_position));
12414
12415
        // If c is U+002F (/) and remaining starts with U+002F (/),
12416
        // then set state to special authority ignore slashes state and increase
12417
        // pointer by 1.
12418
0
        std::string_view view = helpers::substring(url_data, input_position);
12419
0
        if (ada::checkers::begins_with(view, "//")) {
12420
0
          state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12421
0
          input_position += 2;
12422
0
        } else {
12423
          // Otherwise, validation error, set state to relative state and
12424
          // decrease pointer by 1.
12425
0
          state = ada::state::RELATIVE_SCHEME;
12426
0
        }
12427
12428
0
        break;
12429
431
      }
12430
1.85k
      case ada::state::PATH_OR_AUTHORITY: {
12431
1.85k
        ada_log("PATH_OR_AUTHORITY ",
12432
1.85k
                helpers::substring(url_data, input_position));
12433
12434
        // If c is U+002F (/), then set state to authority state.
12435
1.85k
        if ((input_position != input_size) &&
12436
1.85k
            (url_data[input_position] == '/')) {
12437
372
          state = ada::state::AUTHORITY;
12438
372
          input_position++;
12439
1.47k
        } else {
12440
          // Otherwise, set state to path state, and decrease pointer by 1.
12441
1.47k
          state = ada::state::PATH;
12442
1.47k
        }
12443
12444
1.85k
        break;
12445
431
      }
12446
0
      case ada::state::RELATIVE_SCHEME: {
12447
0
        ada_log("RELATIVE_SCHEME ",
12448
0
                helpers::substring(url_data, input_position));
12449
12450
        // Set url’s scheme to base’s scheme.
12451
0
        url.copy_scheme(*base_url);
12452
12453
        // If c is U+002F (/), then set state to relative slash state.
12454
0
        if ((input_position != input_size) &&
12455
0
            (url_data[input_position] == '/')) {
12456
0
          ada_log(
12457
0
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
12458
0
              "slash state");
12459
0
          state = ada::state::RELATIVE_SLASH;
12460
0
        } else if (url.is_special() && (input_position != input_size) &&
12461
0
                   (url_data[input_position] == '\\')) {
12462
          // Otherwise, if url is special and c is U+005C (\), validation error,
12463
          // set state to relative slash state.
12464
0
          ada_log(
12465
0
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
12466
0
              "error, set state to relative slash state");
12467
0
          state = ada::state::RELATIVE_SLASH;
12468
0
        } else {
12469
0
          ada_log("RELATIVE_SCHEME otherwise");
12470
          // Set url’s username to base’s username, url’s password to base’s
12471
          // password, url’s host to base’s host, url’s port to base’s port,
12472
          // url’s path to a clone of base’s path, and url’s query to base’s
12473
          // query.
12474
0
          if constexpr (result_type_is_ada_url) {
12475
0
            url.username = base_url->username;
12476
0
            url.password = base_url->password;
12477
0
            url.host = base_url->host;
12478
0
            url.port = base_url->port;
12479
            // cloning the base path includes cloning the has_opaque_path flag
12480
0
            url.has_opaque_path = base_url->has_opaque_path;
12481
0
            url.path = base_url->path;
12482
0
            url.query = base_url->query;
12483
0
          } else {
12484
0
            url.update_base_authority(base_url->get_href(),
12485
0
                                      base_url->get_components());
12486
            // TODO: Get rid of set_hostname and replace it with
12487
            // update_base_hostname
12488
0
            url.set_hostname(base_url->get_hostname());
12489
0
            url.update_base_port(base_url->retrieve_base_port());
12490
            // cloning the base path includes cloning the has_opaque_path flag
12491
0
            url.has_opaque_path = base_url->has_opaque_path;
12492
0
            url.update_base_pathname(base_url->get_pathname());
12493
0
            url.update_base_search(base_url->get_search());
12494
0
          }
12495
12496
0
          url.has_opaque_path = base_url->has_opaque_path;
12497
12498
          // If c is U+003F (?), then set url’s query to the empty string, and
12499
          // state to query state.
12500
0
          if ((input_position != input_size) &&
12501
0
              (url_data[input_position] == '?')) {
12502
0
            state = ada::state::QUERY;
12503
0
          }
12504
          // Otherwise, if c is not the EOF code point:
12505
0
          else if (input_position != input_size) {
12506
            // Set url’s query to null.
12507
0
            url.clear_search();
12508
0
            if constexpr (result_type_is_ada_url) {
12509
              // Shorten url’s path.
12510
0
              helpers::shorten_path(url.path, url.type);
12511
0
            } else {
12512
0
              std::string_view path = url.get_pathname();
12513
0
              if (helpers::shorten_path(path, url.type)) {
12514
0
                url.update_base_pathname(std::string(path));
12515
0
              }
12516
0
            }
12517
            // Set state to path state and decrease pointer by 1.
12518
0
            state = ada::state::PATH;
12519
0
            break;
12520
0
          }
12521
0
        }
12522
0
        input_position++;
12523
0
        break;
12524
0
      }
12525
0
      case ada::state::RELATIVE_SLASH: {
12526
0
        ada_log("RELATIVE_SLASH ",
12527
0
                helpers::substring(url_data, input_position));
12528
12529
        // If url is special and c is U+002F (/) or U+005C (\), then:
12530
0
        if (url.is_special() && (input_position != input_size) &&
12531
0
            (url_data[input_position] == '/' ||
12532
0
             url_data[input_position] == '\\')) {
12533
          // Set state to special authority ignore slashes state.
12534
0
          state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12535
0
        }
12536
        // Otherwise, if c is U+002F (/), then set state to authority state.
12537
0
        else if ((input_position != input_size) &&
12538
0
                 (url_data[input_position] == '/')) {
12539
0
          state = ada::state::AUTHORITY;
12540
0
        }
12541
        // Otherwise, set
12542
        // - url’s username to base’s username,
12543
        // - url’s password to base’s password,
12544
        // - url’s host to base’s host,
12545
        // - url’s port to base’s port,
12546
        // - state to path state, and then, decrease pointer by 1.
12547
0
        else {
12548
0
          if constexpr (result_type_is_ada_url) {
12549
0
            url.username = base_url->username;
12550
0
            url.password = base_url->password;
12551
0
            url.host = base_url->host;
12552
0
            url.port = base_url->port;
12553
0
          } else {
12554
0
            url.update_base_authority(base_url->get_href(),
12555
0
                                      base_url->get_components());
12556
            // TODO: Get rid of set_hostname and replace it with
12557
            // update_base_hostname
12558
0
            url.set_hostname(base_url->get_hostname());
12559
0
            url.update_base_port(base_url->retrieve_base_port());
12560
0
          }
12561
0
          state = ada::state::PATH;
12562
0
          break;
12563
0
        }
12564
12565
0
        input_position++;
12566
0
        break;
12567
0
      }
12568
5.66k
      case ada::state::SPECIAL_AUTHORITY_SLASHES: {
12569
5.66k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
12570
5.66k
                helpers::substring(url_data, input_position));
12571
12572
        // If c is U+002F (/) and remaining starts with U+002F (/),
12573
        // then set state to special authority ignore slashes state and increase
12574
        // pointer by 1.
12575
5.66k
        state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12576
5.66k
        std::string_view view = helpers::substring(url_data, input_position);
12577
5.66k
        if (ada::checkers::begins_with(view, "//")) {
12578
14
          input_position += 2;
12579
14
        }
12580
12581
5.66k
        [[fallthrough]];
12582
5.66k
      }
12583
5.66k
      case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
12584
5.66k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
12585
5.66k
                helpers::substring(url_data, input_position));
12586
12587
        // If c is neither U+002F (/) nor U+005C (\), then set state to
12588
        // authority state and decrease pointer by 1.
12589
6.18k
        while ((input_position != input_size) &&
12590
6.18k
               ((url_data[input_position] == '/') ||
12591
6.15k
                (url_data[input_position] == '\\'))) {
12592
526
          input_position++;
12593
526
        }
12594
5.66k
        state = ada::state::AUTHORITY;
12595
12596
5.66k
        break;
12597
5.66k
      }
12598
268
      case ada::state::QUERY: {
12599
268
        ada_log("QUERY ", helpers::substring(url_data, input_position));
12600
        // Let queryPercentEncodeSet be the special-query percent-encode set if
12601
        // url is special; otherwise the query percent-encode set.
12602
268
        const uint8_t* query_percent_encode_set =
12603
268
            url.is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12604
268
                             : ada::character_sets::QUERY_PERCENT_ENCODE;
12605
12606
        // Percent-encode after encoding, with encoding, buffer, and
12607
        // queryPercentEncodeSet, and append the result to url’s query.
12608
268
        url.update_base_search(helpers::substring(url_data, input_position),
12609
268
                               query_percent_encode_set);
12610
268
        ada_log("QUERY update_base_search completed ");
12611
268
        if (fragment.has_value()) {
12612
26
          url.update_unencoded_base_hash(*fragment);
12613
26
        }
12614
268
        return url;
12615
5.66k
      }
12616
5.80k
      case ada::state::HOST: {
12617
5.80k
        ada_log("HOST ", helpers::substring(url_data, input_position));
12618
12619
5.80k
        std::string_view host_view =
12620
5.80k
            helpers::substring(url_data, input_position);
12621
5.80k
        auto [location, found_colon] =
12622
5.80k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
12623
5.80k
        input_position = (location != std::string_view::npos)
12624
5.80k
                             ? input_position + location
12625
5.80k
                             : input_size;
12626
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12627
        // Note: the 'found_colon' value is true if and only if a colon was
12628
        // encountered while not inside brackets.
12629
5.80k
        if (found_colon) {
12630
          // If buffer is the empty string, validation error, return failure.
12631
          // Let host be the result of host parsing buffer with url is not
12632
          // special.
12633
867
          ada_log("HOST parsing ", host_view);
12634
867
          if (!url.parse_host(host_view)) {
12635
139
            return url;
12636
139
          }
12637
728
          ada_log("HOST parsing results in ", url.get_hostname());
12638
          // Set url’s host to host, buffer to the empty string, and state to
12639
          // port state.
12640
728
          state = ada::state::PORT;
12641
728
          input_position++;
12642
728
        }
12643
        // Otherwise, if one of the following is true:
12644
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12645
        // - url is special and c is U+005C (\)
12646
        // The get_host_delimiter_location function either brings us to
12647
        // the colon outside of the bracket, or to one of those characters.
12648
4.93k
        else {
12649
          // If url is special and host_view is the empty string, validation
12650
          // error, return failure.
12651
4.93k
          if (url.is_special() && host_view.empty()) {
12652
40
            url.is_valid = false;
12653
40
            return url;
12654
40
          }
12655
4.89k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
12656
          // Let host be the result of host parsing host_view with url is not
12657
          // special.
12658
4.89k
          if (host_view.empty()) {
12659
28
            url.update_base_hostname("");
12660
4.86k
          } else if (!url.parse_host(host_view)) {
12661
1.19k
            return url;
12662
1.19k
          }
12663
3.70k
          ada_log("HOST parsing results in ", url.get_hostname(),
12664
3.70k
                  " href=", url.get_href());
12665
12666
          // Set url’s host to host, and state to path start state.
12667
3.70k
          state = ada::state::PATH_START;
12668
3.70k
        }
12669
12670
4.42k
        break;
12671
5.80k
      }
12672
4.42k
      case ada::state::OPAQUE_PATH: {
12673
1.09k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
12674
1.09k
        std::string_view view = helpers::substring(url_data, input_position);
12675
        // If c is U+003F (?), then set url’s query to the empty string and
12676
        // state to query state.
12677
1.09k
        size_t location = view.find('?');
12678
1.09k
        if (location != std::string_view::npos) {
12679
86
          view.remove_suffix(view.size() - location);
12680
86
          state = ada::state::QUERY;
12681
86
          input_position += location + 1;
12682
1.00k
        } else {
12683
1.00k
          input_position = input_size + 1;
12684
1.00k
        }
12685
1.09k
        url.has_opaque_path = true;
12686
        // This is a really unlikely scenario in real world. We should not seek
12687
        // to optimize it.
12688
1.09k
        url.update_base_pathname(unicode::percent_encode(
12689
1.09k
            view, character_sets::C0_CONTROL_PERCENT_ENCODE));
12690
1.09k
        break;
12691
5.80k
      }
12692
728
      case ada::state::PORT: {
12693
728
        ada_log("PORT ", helpers::substring(url_data, input_position));
12694
728
        std::string_view port_view =
12695
728
            helpers::substring(url_data, input_position);
12696
728
        size_t consumed_bytes = url.parse_port(port_view, true);
12697
728
        input_position += consumed_bytes;
12698
728
        if (!url.is_valid) {
12699
84
          return url;
12700
84
        }
12701
644
        state = state::PATH_START;
12702
644
        [[fallthrough]];
12703
644
      }
12704
4.72k
      case ada::state::PATH_START: {
12705
4.72k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
12706
12707
        // If url is special, then:
12708
4.72k
        if (url.is_special()) {
12709
          // Set state to path state.
12710
4.46k
          state = ada::state::PATH;
12711
12712
          // Optimization: Avoiding going into PATH state improves the
12713
          // performance of urls ending with /.
12714
4.46k
          if (input_position == input_size) {
12715
4.05k
            url.update_base_pathname("/");
12716
4.05k
            if (fragment.has_value()) {
12717
80
              url.update_unencoded_base_hash(*fragment);
12718
80
            }
12719
4.05k
            return url;
12720
4.05k
          }
12721
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
12722
          // by 1. We know that (input_position == input_size) is impossible
12723
          // here, because of the previous if-check.
12724
404
          if ((url_data[input_position] != '/') &&
12725
404
              (url_data[input_position] != '\\')) {
12726
87
            break;
12727
87
          }
12728
404
        }
12729
        // Otherwise, if state override is not given and c is U+003F (?),
12730
        // set url’s query to the empty string and state to query state.
12731
259
        else if ((input_position != input_size) &&
12732
259
                 (url_data[input_position] == '?')) {
12733
27
          state = ada::state::QUERY;
12734
27
        }
12735
        // Otherwise, if c is not the EOF code point:
12736
232
        else if (input_position != input_size) {
12737
          // Set state to path state.
12738
29
          state = ada::state::PATH;
12739
12740
          // If c is not U+002F (/), then decrease pointer by 1.
12741
29
          if (url_data[input_position] != '/') {
12742
0
            break;
12743
0
          }
12744
29
        }
12745
12746
576
        input_position++;
12747
576
        break;
12748
4.72k
      }
12749
3.01k
      case ada::state::PATH: {
12750
3.01k
        std::string_view view = helpers::substring(url_data, input_position);
12751
3.01k
        ada_log("PATH ", helpers::substring(url_data, input_position));
12752
12753
        // Most time, we do not need percent encoding.
12754
        // Furthermore, we can immediately locate the '?'.
12755
3.01k
        size_t locofquestionmark = view.find('?');
12756
3.01k
        if (locofquestionmark != std::string_view::npos) {
12757
155
          state = ada::state::QUERY;
12758
155
          view.remove_suffix(view.size() - locofquestionmark);
12759
155
          input_position += locofquestionmark + 1;
12760
2.86k
        } else {
12761
2.86k
          input_position = input_size + 1;
12762
2.86k
        }
12763
3.01k
        if constexpr (result_type_is_ada_url) {
12764
3.01k
          helpers::parse_prepared_path(view, url.type, url.path);
12765
3.01k
        } else {
12766
3.01k
          url.consume_prepared_path(view);
12767
3.01k
          ADA_ASSERT_TRUE(url.validate());
12768
3.01k
        }
12769
3.01k
        break;
12770
4.72k
      }
12771
570
      case ada::state::FILE_SLASH: {
12772
570
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
12773
12774
        // If c is U+002F (/) or U+005C (\), then:
12775
570
        if ((input_position != input_size) &&
12776
570
            (url_data[input_position] == '/' ||
12777
533
             url_data[input_position] == '\\')) {
12778
517
          ada_log("FILE_SLASH c is U+002F or U+005C");
12779
          // Set state to file host state.
12780
517
          state = ada::state::FILE_HOST;
12781
517
          input_position++;
12782
517
        } else {
12783
53
          ada_log("FILE_SLASH otherwise");
12784
          // If base is non-null and base’s scheme is "file", then:
12785
          // Note: it is unsafe to do base_url->scheme unless you know that
12786
          // base_url_has_value() is true.
12787
53
          if (base_url != nullptr &&
12788
53
              base_url->type == ada::scheme::type::FILE) {
12789
            // Set url’s host to base’s host.
12790
0
            if constexpr (result_type_is_ada_url) {
12791
0
              url.host = base_url->host;
12792
0
            } else {
12793
              // TODO: Optimization opportunity.
12794
0
              url.set_host(base_url->get_host());
12795
0
            }
12796
            // If the code point substring from pointer to the end of input does
12797
            // not start with a Windows drive letter and base’s path[0] is a
12798
            // normalized Windows drive letter, then append base’s path[0] to
12799
            // url’s path.
12800
0
            if (!base_url->get_pathname().empty()) {
12801
0
              if (!checkers::is_windows_drive_letter(
12802
0
                      helpers::substring(url_data, input_position))) {
12803
0
                std::string_view first_base_url_path =
12804
0
                    base_url->get_pathname().substr(1);
12805
0
                size_t loc = first_base_url_path.find('/');
12806
0
                if (loc != std::string_view::npos) {
12807
0
                  helpers::resize(first_base_url_path, loc);
12808
0
                }
12809
0
                if (checkers::is_normalized_windows_drive_letter(
12810
0
                        first_base_url_path)) {
12811
0
                  if constexpr (result_type_is_ada_url) {
12812
0
                    url.path += '/';
12813
0
                    url.path += first_base_url_path;
12814
0
                  } else {
12815
0
                    url.append_base_pathname(
12816
0
                        helpers::concat("/", first_base_url_path));
12817
0
                  }
12818
0
                }
12819
0
              }
12820
0
            }
12821
0
          }
12822
12823
          // Set state to path state, and decrease pointer by 1.
12824
53
          state = ada::state::PATH;
12825
53
        }
12826
12827
570
        break;
12828
4.72k
      }
12829
517
      case ada::state::FILE_HOST: {
12830
517
        std::string_view view = helpers::substring(url_data, input_position);
12831
517
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
12832
12833
517
        size_t location = view.find_first_of("/\\?");
12834
517
        std::string_view file_host_buffer(
12835
517
            view.data(),
12836
517
            (location != std::string_view::npos) ? location : view.size());
12837
12838
517
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
12839
7
          state = ada::state::PATH;
12840
510
        } else if (file_host_buffer.empty()) {
12841
          // Set url’s host to the empty string.
12842
14
          if constexpr (result_type_is_ada_url) {
12843
14
            url.host = "";
12844
14
          } else {
12845
14
            url.update_base_hostname("");
12846
14
          }
12847
          // Set state to path start state.
12848
14
          state = ada::state::PATH_START;
12849
496
        } else {
12850
496
          size_t consumed_bytes = file_host_buffer.size();
12851
496
          input_position += consumed_bytes;
12852
          // Let host be the result of host parsing buffer with url is not
12853
          // special.
12854
496
          if (!url.parse_host(file_host_buffer)) {
12855
133
            return url;
12856
133
          }
12857
12858
363
          if constexpr (result_type_is_ada_url) {
12859
            // If host is "localhost", then set host to the empty string.
12860
363
            if (url.host.has_value() && url.host.value() == "localhost") {
12861
3
              url.host = "";
12862
3
            }
12863
363
          } else {
12864
363
            if (url.get_hostname() == "localhost") {
12865
363
              url.update_base_hostname("");
12866
363
            }
12867
363
          }
12868
12869
          // Set buffer to the empty string and state to path start state.
12870
363
          state = ada::state::PATH_START;
12871
363
        }
12872
12873
384
        break;
12874
517
      }
12875
1.61k
      case ada::state::FILE: {
12876
1.61k
        ada_log("FILE ", helpers::substring(url_data, input_position));
12877
1.61k
        std::string_view file_view =
12878
1.61k
            helpers::substring(url_data, input_position);
12879
12880
1.61k
        url.set_protocol_as_file();
12881
1.61k
        if constexpr (result_type_is_ada_url) {
12882
          // Set url’s host to the empty string.
12883
1.61k
          url.host = "";
12884
1.61k
        } else {
12885
1.61k
          url.update_base_hostname("");
12886
1.61k
        }
12887
        // If c is U+002F (/) or U+005C (\), then:
12888
1.61k
        if (input_position != input_size &&
12889
1.61k
            (url_data[input_position] == '/' ||
12890
909
             url_data[input_position] == '\\')) {
12891
570
          ada_log("FILE c is U+002F or U+005C");
12892
          // Set state to file slash state.
12893
570
          state = ada::state::FILE_SLASH;
12894
570
        }
12895
        // Otherwise, if base is non-null and base’s scheme is "file":
12896
1.04k
        else if (base_url != nullptr &&
12897
1.04k
                 base_url->type == ada::scheme::type::FILE) {
12898
          // Set url’s host to base’s host, url’s path to a clone of base’s
12899
          // path, and url’s query to base’s query.
12900
0
          ada_log("FILE base non-null");
12901
0
          if constexpr (result_type_is_ada_url) {
12902
0
            url.host = base_url->host;
12903
0
            url.path = base_url->path;
12904
0
            url.query = base_url->query;
12905
0
          } else {
12906
            // TODO: Get rid of set_hostname and replace it with
12907
            // update_base_hostname
12908
0
            url.set_hostname(base_url->get_hostname());
12909
0
            url.update_base_pathname(base_url->get_pathname());
12910
0
            url.update_base_search(base_url->get_search());
12911
0
          }
12912
0
          url.has_opaque_path = base_url->has_opaque_path;
12913
12914
          // If c is U+003F (?), then set url’s query to the empty string and
12915
          // state to query state.
12916
0
          if (input_position != input_size && url_data[input_position] == '?') {
12917
0
            state = ada::state::QUERY;
12918
0
          }
12919
          // Otherwise, if c is not the EOF code point:
12920
0
          else if (input_position != input_size) {
12921
            // Set url’s query to null.
12922
0
            url.clear_search();
12923
            // If the code point substring from pointer to the end of input does
12924
            // not start with a Windows drive letter, then shorten url’s path.
12925
0
            if (!checkers::is_windows_drive_letter(file_view)) {
12926
0
              if constexpr (result_type_is_ada_url) {
12927
0
                helpers::shorten_path(url.path, url.type);
12928
0
              } else {
12929
0
                std::string_view path = url.get_pathname();
12930
0
                if (helpers::shorten_path(path, url.type)) {
12931
0
                  url.update_base_pathname(std::string(path));
12932
0
                }
12933
0
              }
12934
0
            }
12935
            // Otherwise:
12936
0
            else {
12937
              // Set url’s path to an empty list.
12938
0
              url.clear_pathname();
12939
0
              url.has_opaque_path = true;
12940
0
            }
12941
12942
            // Set state to path state and decrease pointer by 1.
12943
0
            state = ada::state::PATH;
12944
0
            break;
12945
0
          }
12946
0
        }
12947
        // Otherwise, set state to path state, and decrease pointer by 1.
12948
1.04k
        else {
12949
1.04k
          ada_log("FILE go to path");
12950
1.04k
          state = ada::state::PATH;
12951
1.04k
          break;
12952
1.04k
        }
12953
12954
570
        input_position++;
12955
570
        break;
12956
1.61k
      }
12957
0
      default:
12958
0
        ada::unreachable();
12959
61.2k
    }
12960
61.2k
  }
12961
4.07k
  if (fragment.has_value()) {
12962
157
    url.update_unencoded_base_hash(*fragment);
12963
157
  }
12964
4.07k
  return url;
12965
14.5k
}
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
12072
45.4k
                      const result_type* base_url) {
12073
  // We can specialize the implementation per type.
12074
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
12075
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
12076
  // something else } is free (at runtime). This means that ada::url_aggregator
12077
  // and ada::url **do not have to support the exact same API**.
12078
45.4k
  constexpr bool result_type_is_ada_url =
12079
45.4k
      std::is_same<ada::url, result_type>::value;
12080
45.4k
  constexpr bool result_type_is_ada_url_aggregator =
12081
45.4k
      std::is_same<ada::url_aggregator, result_type>::value;
12082
45.4k
  static_assert(result_type_is_ada_url ||
12083
45.4k
                result_type_is_ada_url_aggregator);  // We don't support
12084
                                                     // anything else for now.
12085
12086
45.4k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
12087
45.4k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
12088
45.4k
          ")");
12089
12090
45.4k
  ada::state state = ada::state::SCHEME_START;
12091
45.4k
  result_type url{};
12092
12093
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
12094
  // surely the result of a bug or are otherwise a security concern.
12095
45.4k
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) {
12096
2
    url.is_valid = false;
12097
2
  }
12098
  // Going forward, user_input.size() is in [0,
12099
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
12100
  // base, or the optional_url was invalid, we must return.
12101
45.4k
  if (base_url != nullptr) {
12102
2.66k
    url.is_valid &= base_url->is_valid;
12103
2.66k
  }
12104
45.4k
  if (!url.is_valid) {
12105
2
    return url;
12106
2
  }
12107
45.4k
  if constexpr (result_type_is_ada_url_aggregator) {
12108
    // Most of the time, we just need user_input.size().
12109
    // In some instances, we may need a bit more.
12110
    ///////////////////////////
12111
    // This is *very* important. This line should be removed
12112
    // hastily. There are principled reasons why reserve is important
12113
    // for performance. If you have a benchmark with small inputs,
12114
    // it may not matter, but in other instances, it could.
12115
    ////
12116
    // This rounds up to the next power of two.
12117
    // We know that user_input.size() is in [0,
12118
    // std::numeric_limits<uint32_t>::max).
12119
45.4k
    uint32_t reserve_capacity =
12120
45.4k
        (0xFFFFFFFF >>
12121
45.4k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
12122
45.4k
        1;
12123
45.4k
    url.reserve(reserve_capacity);
12124
    //
12125
    //
12126
    //
12127
45.4k
  }
12128
45.4k
  std::string tmp_buffer;
12129
45.4k
  std::string_view internal_input;
12130
45.4k
  if (unicode::has_tabs_or_newline(user_input)) {
12131
468
    tmp_buffer = user_input;
12132
    // Optimization opportunity: Instead of copying and then pruning, we could
12133
    // just directly build the string from user_input.
12134
468
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12135
468
    internal_input = tmp_buffer;
12136
44.9k
  } else {
12137
44.9k
    internal_input = user_input;
12138
44.9k
  }
12139
12140
  // Leading and trailing control characters are uncommon and easy to deal with
12141
  // (no performance concern).
12142
45.4k
  std::string_view url_data = internal_input;
12143
45.4k
  helpers::trim_c0_whitespace(url_data);
12144
12145
  // Optimization opportunity. Most websites do not have fragment.
12146
45.4k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
12147
  // We add it last so that an implementation like ada::url_aggregator
12148
  // can append it last to its internal buffer, thus improving performance.
12149
12150
  // Here url_data no longer has its fragment.
12151
  // We are going to access the data from url_data (it is immutable).
12152
  // At any given time, we are pointing at byte 'input_position' in url_data.
12153
  // The input_position variable should range from 0 to input_size.
12154
  // It is illegal to access url_data at input_size.
12155
45.4k
  size_t input_position = 0;
12156
45.4k
  const size_t input_size = url_data.size();
12157
  // Keep running the following state machine by switching on state.
12158
  // If after a run pointer points to the EOF code point, go to the next step.
12159
  // Otherwise, increase pointer by 1 and continue with the state machine.
12160
  // We never decrement input_position.
12161
179k
  while (input_position <= input_size) {
12162
168k
    ada_log("In parsing at ", input_position, " out of ", input_size,
12163
168k
            " in state ", ada::to_string(state));
12164
168k
    switch (state) {
12165
45.4k
      case ada::state::SCHEME_START: {
12166
45.4k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
12167
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
12168
        // state to scheme state.
12169
45.4k
        if ((input_position != input_size) &&
12170
45.4k
            checkers::is_alpha(url_data[input_position])) {
12171
26.4k
          state = ada::state::SCHEME;
12172
26.4k
          input_position++;
12173
26.4k
        } else {
12174
          // Otherwise, if state override is not given, set state to no scheme
12175
          // state and decrease pointer by 1.
12176
18.9k
          state = ada::state::NO_SCHEME;
12177
18.9k
        }
12178
45.4k
        break;
12179
0
      }
12180
26.4k
      case ada::state::SCHEME: {
12181
26.4k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
12182
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
12183
        // append c, lowercased, to buffer.
12184
87.0k
        while ((input_position != input_size) &&
12185
87.0k
               (ada::unicode::is_alnum_plus(url_data[input_position]))) {
12186
60.6k
          input_position++;
12187
60.6k
        }
12188
        // Otherwise, if c is U+003A (:), then:
12189
26.4k
        if ((input_position != input_size) &&
12190
26.4k
            (url_data[input_position] == ':')) {
12191
24.2k
          ada_log("SCHEME the scheme should be ",
12192
24.2k
                  url_data.substr(0, input_position));
12193
24.2k
          if constexpr (result_type_is_ada_url) {
12194
24.2k
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
12195
24.2k
              return url;
12196
24.2k
            }
12197
24.2k
          } else {
12198
            // we pass the colon along instead of painfully adding it back.
12199
24.2k
            if (!url.parse_scheme_with_colon(
12200
24.2k
                    url_data.substr(0, input_position + 1))) {
12201
0
              return url;
12202
0
            }
12203
24.2k
          }
12204
24.2k
          ada_log("SCHEME the scheme is ", url.get_protocol());
12205
12206
          // If url’s scheme is "file", then:
12207
24.2k
          if (url.type == ada::scheme::type::FILE) {
12208
            // Set state to file state.
12209
4.13k
            state = ada::state::FILE;
12210
4.13k
          }
12211
          // Otherwise, if url is special, base is non-null, and base’s scheme
12212
          // is url’s scheme: Note: Doing base_url->scheme is unsafe if base_url
12213
          // != nullptr is false.
12214
20.1k
          else if (url.is_special() && base_url != nullptr &&
12215
20.1k
                   base_url->type == url.type) {
12216
            // Set state to special relative or authority state.
12217
120
            state = ada::state::SPECIAL_RELATIVE_OR_AUTHORITY;
12218
120
          }
12219
          // Otherwise, if url is special, set state to special authority
12220
          // slashes state.
12221
20.0k
          else if (url.is_special()) {
12222
12.7k
            state = ada::state::SPECIAL_AUTHORITY_SLASHES;
12223
12.7k
          }
12224
          // Otherwise, if remaining starts with an U+002F (/), set state to
12225
          // path or authority state and increase pointer by 1.
12226
7.25k
          else if (input_position + 1 < input_size &&
12227
7.25k
                   url_data[input_position + 1] == '/') {
12228
3.91k
            state = ada::state::PATH_OR_AUTHORITY;
12229
3.91k
            input_position++;
12230
3.91k
          }
12231
          // Otherwise, set url’s path to the empty string and set state to
12232
          // opaque path state.
12233
3.34k
          else {
12234
3.34k
            state = ada::state::OPAQUE_PATH;
12235
3.34k
          }
12236
24.2k
        }
12237
        // Otherwise, if state override is not given, set buffer to the empty
12238
        // string, state to no scheme state, and start over (from the first code
12239
        // point in input).
12240
2.15k
        else {
12241
2.15k
          state = ada::state::NO_SCHEME;
12242
2.15k
          input_position = 0;
12243
2.15k
          break;
12244
2.15k
        }
12245
24.2k
        input_position++;
12246
24.2k
        break;
12247
26.4k
      }
12248
21.1k
      case ada::state::NO_SCHEME: {
12249
21.1k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
12250
        // If base is null, or base has an opaque path and c is not U+0023 (#),
12251
        // validation error, return failure.
12252
21.1k
        if (base_url == nullptr ||
12253
21.1k
            (base_url->has_opaque_path && !fragment.has_value())) {
12254
19.8k
          ada_log("NO_SCHEME validation error");
12255
19.8k
          url.is_valid = false;
12256
19.8k
          return url;
12257
19.8k
        }
12258
        // Otherwise, if base has an opaque path and c is U+0023 (#),
12259
        // set url’s scheme to base’s scheme, url’s path to base’s path, url’s
12260
        // query to base’s query, and set state to fragment state.
12261
1.24k
        else if (base_url->has_opaque_path && fragment.has_value() &&
12262
1.24k
                 input_position == input_size) {
12263
28
          ada_log("NO_SCHEME opaque base with fragment");
12264
28
          url.copy_scheme(*base_url);
12265
28
          url.has_opaque_path = base_url->has_opaque_path;
12266
12267
28
          if constexpr (result_type_is_ada_url) {
12268
28
            url.path = base_url->path;
12269
28
            url.query = base_url->query;
12270
28
          } else {
12271
28
            url.update_base_pathname(base_url->get_pathname());
12272
28
            url.update_base_search(base_url->get_search());
12273
28
          }
12274
28
          url.update_unencoded_base_hash(*fragment);
12275
28
          return url;
12276
28
        }
12277
        // Otherwise, if base’s scheme is not "file", set state to relative
12278
        // state and decrease pointer by 1.
12279
1.21k
        else if (base_url->type != ada::scheme::type::FILE) {
12280
657
          ada_log("NO_SCHEME non-file relative path");
12281
657
          state = ada::state::RELATIVE_SCHEME;
12282
657
        }
12283
        // Otherwise, set state to file state and decrease pointer by 1.
12284
562
        else {
12285
562
          ada_log("NO_SCHEME file base type");
12286
562
          state = ada::state::FILE;
12287
562
        }
12288
1.21k
        break;
12289
21.1k
      }
12290
13.5k
      case ada::state::AUTHORITY: {
12291
13.5k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
12292
        // most URLs have no @. Having no @ tells us that we don't have to worry
12293
        // about AUTHORITY. Of course, we could have @ and still not have to
12294
        // worry about AUTHORITY.
12295
        // TODO: Instead of just collecting a bool, collect the location of the
12296
        // '@' and do something useful with it.
12297
        // TODO: We could do various processing early on, using a single pass
12298
        // over the string to collect information about it, e.g., telling us
12299
        // whether there is a @ and if so, where (or how many).
12300
13.5k
        const bool contains_ampersand =
12301
13.5k
            (url_data.find('@', input_position) != std::string_view::npos);
12302
12303
13.5k
        if (!contains_ampersand) {
12304
12.6k
          state = ada::state::HOST;
12305
12.6k
          break;
12306
12.6k
        }
12307
970
        bool at_sign_seen{false};
12308
970
        bool password_token_seen{false};
12309
        /**
12310
         * We expect something of the sort...
12311
         * https://user:pass@example.com:1234/foo/bar?baz#quux
12312
         * --------^
12313
         */
12314
7.52k
        do {
12315
7.52k
          std::string_view view = helpers::substring(url_data, input_position);
12316
          // The delimiters are @, /, ? \\.
12317
7.52k
          size_t location =
12318
7.52k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
12319
7.52k
                               : helpers::find_authority_delimiter(view);
12320
7.52k
          std::string_view authority_view(view.data(), location);
12321
7.52k
          size_t end_of_authority = input_position + authority_view.size();
12322
          // If c is U+0040 (@), then:
12323
7.52k
          if ((end_of_authority != input_size) &&
12324
7.52k
              (url_data[end_of_authority] == '@')) {
12325
            // If atSignSeen is true, then prepend "%40" to buffer.
12326
6.55k
            if (at_sign_seen) {
12327
5.62k
              if (password_token_seen) {
12328
1.37k
                if constexpr (result_type_is_ada_url) {
12329
1.37k
                  url.password += "%40";
12330
1.37k
                } else {
12331
1.37k
                  url.append_base_password("%40");
12332
1.37k
                }
12333
4.25k
              } else {
12334
4.25k
                if constexpr (result_type_is_ada_url) {
12335
4.25k
                  url.username += "%40";
12336
4.25k
                } else {
12337
4.25k
                  url.append_base_username("%40");
12338
4.25k
                }
12339
4.25k
              }
12340
5.62k
            }
12341
12342
6.55k
            at_sign_seen = true;
12343
12344
6.55k
            if (!password_token_seen) {
12345
5.18k
              size_t password_token_location = authority_view.find(':');
12346
5.18k
              password_token_seen =
12347
5.18k
                  password_token_location != std::string_view::npos;
12348
12349
5.18k
              if (!password_token_seen) {
12350
4.85k
                if constexpr (result_type_is_ada_url) {
12351
4.85k
                  url.username += unicode::percent_encode(
12352
4.85k
                      authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12353
4.85k
                } else {
12354
4.85k
                  url.append_base_username(unicode::percent_encode(
12355
4.85k
                      authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12356
4.85k
                }
12357
4.85k
              } else {
12358
325
                if constexpr (result_type_is_ada_url) {
12359
325
                  url.username += unicode::percent_encode(
12360
325
                      authority_view.substr(0, password_token_location),
12361
325
                      character_sets::USERINFO_PERCENT_ENCODE);
12362
325
                  url.password += unicode::percent_encode(
12363
325
                      authority_view.substr(password_token_location + 1),
12364
325
                      character_sets::USERINFO_PERCENT_ENCODE);
12365
325
                } else {
12366
325
                  url.append_base_username(unicode::percent_encode(
12367
325
                      authority_view.substr(0, password_token_location),
12368
325
                      character_sets::USERINFO_PERCENT_ENCODE));
12369
325
                  url.append_base_password(unicode::percent_encode(
12370
325
                      authority_view.substr(password_token_location + 1),
12371
325
                      character_sets::USERINFO_PERCENT_ENCODE));
12372
325
                }
12373
325
              }
12374
5.18k
            } else {
12375
1.37k
              if constexpr (result_type_is_ada_url) {
12376
1.37k
                url.password += unicode::percent_encode(
12377
1.37k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12378
1.37k
              } else {
12379
1.37k
                url.append_base_password(unicode::percent_encode(
12380
1.37k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12381
1.37k
              }
12382
1.37k
            }
12383
6.55k
          }
12384
          // Otherwise, if one of the following is true:
12385
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12386
          // - url is special and c is U+005C (\)
12387
970
          else if (end_of_authority == input_size ||
12388
970
                   url_data[end_of_authority] == '/' ||
12389
970
                   url_data[end_of_authority] == '?' ||
12390
970
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
12391
            // If atSignSeen is true and authority_view is the empty string,
12392
            // validation error, return failure.
12393
970
            if (at_sign_seen && authority_view.empty()) {
12394
513
              url.is_valid = false;
12395
513
              return url;
12396
513
            }
12397
457
            state = ada::state::HOST;
12398
457
            break;
12399
970
          }
12400
6.55k
          if (end_of_authority == input_size) {
12401
0
            if (fragment.has_value()) {
12402
0
              url.update_unencoded_base_hash(*fragment);
12403
0
            }
12404
0
            return url;
12405
0
          }
12406
6.55k
          input_position = end_of_authority + 1;
12407
6.55k
        } while (true);
12408
12409
457
        break;
12410
970
      }
12411
457
      case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY: {
12412
120
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
12413
120
                helpers::substring(url_data, input_position));
12414
12415
        // If c is U+002F (/) and remaining starts with U+002F (/),
12416
        // then set state to special authority ignore slashes state and increase
12417
        // pointer by 1.
12418
120
        std::string_view view = helpers::substring(url_data, input_position);
12419
120
        if (ada::checkers::begins_with(view, "//")) {
12420
2
          state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12421
2
          input_position += 2;
12422
118
        } else {
12423
          // Otherwise, validation error, set state to relative state and
12424
          // decrease pointer by 1.
12425
118
          state = ada::state::RELATIVE_SCHEME;
12426
118
        }
12427
12428
120
        break;
12429
970
      }
12430
3.91k
      case ada::state::PATH_OR_AUTHORITY: {
12431
3.91k
        ada_log("PATH_OR_AUTHORITY ",
12432
3.91k
                helpers::substring(url_data, input_position));
12433
12434
        // If c is U+002F (/), then set state to authority state.
12435
3.91k
        if ((input_position != input_size) &&
12436
3.91k
            (url_data[input_position] == '/')) {
12437
800
          state = ada::state::AUTHORITY;
12438
800
          input_position++;
12439
3.11k
        } else {
12440
          // Otherwise, set state to path state, and decrease pointer by 1.
12441
3.11k
          state = ada::state::PATH;
12442
3.11k
        }
12443
12444
3.91k
        break;
12445
970
      }
12446
775
      case ada::state::RELATIVE_SCHEME: {
12447
775
        ada_log("RELATIVE_SCHEME ",
12448
775
                helpers::substring(url_data, input_position));
12449
12450
        // Set url’s scheme to base’s scheme.
12451
775
        url.copy_scheme(*base_url);
12452
12453
        // If c is U+002F (/), then set state to relative slash state.
12454
775
        if ((input_position != input_size) &&
12455
775
            (url_data[input_position] == '/')) {
12456
43
          ada_log(
12457
43
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
12458
43
              "slash state");
12459
43
          state = ada::state::RELATIVE_SLASH;
12460
732
        } else if (url.is_special() && (input_position != input_size) &&
12461
732
                   (url_data[input_position] == '\\')) {
12462
          // Otherwise, if url is special and c is U+005C (\), validation error,
12463
          // set state to relative slash state.
12464
1
          ada_log(
12465
1
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
12466
1
              "error, set state to relative slash state");
12467
1
          state = ada::state::RELATIVE_SLASH;
12468
731
        } else {
12469
731
          ada_log("RELATIVE_SCHEME otherwise");
12470
          // Set url’s username to base’s username, url’s password to base’s
12471
          // password, url’s host to base’s host, url’s port to base’s port,
12472
          // url’s path to a clone of base’s path, and url’s query to base’s
12473
          // query.
12474
731
          if constexpr (result_type_is_ada_url) {
12475
731
            url.username = base_url->username;
12476
731
            url.password = base_url->password;
12477
731
            url.host = base_url->host;
12478
731
            url.port = base_url->port;
12479
            // cloning the base path includes cloning the has_opaque_path flag
12480
731
            url.has_opaque_path = base_url->has_opaque_path;
12481
731
            url.path = base_url->path;
12482
731
            url.query = base_url->query;
12483
731
          } else {
12484
731
            url.update_base_authority(base_url->get_href(),
12485
731
                                      base_url->get_components());
12486
            // TODO: Get rid of set_hostname and replace it with
12487
            // update_base_hostname
12488
731
            url.set_hostname(base_url->get_hostname());
12489
731
            url.update_base_port(base_url->retrieve_base_port());
12490
            // cloning the base path includes cloning the has_opaque_path flag
12491
731
            url.has_opaque_path = base_url->has_opaque_path;
12492
731
            url.update_base_pathname(base_url->get_pathname());
12493
731
            url.update_base_search(base_url->get_search());
12494
731
          }
12495
12496
731
          url.has_opaque_path = base_url->has_opaque_path;
12497
12498
          // If c is U+003F (?), then set url’s query to the empty string, and
12499
          // state to query state.
12500
731
          if ((input_position != input_size) &&
12501
731
              (url_data[input_position] == '?')) {
12502
5
            state = ada::state::QUERY;
12503
5
          }
12504
          // Otherwise, if c is not the EOF code point:
12505
726
          else if (input_position != input_size) {
12506
            // Set url’s query to null.
12507
233
            url.clear_search();
12508
233
            if constexpr (result_type_is_ada_url) {
12509
              // Shorten url’s path.
12510
233
              helpers::shorten_path(url.path, url.type);
12511
233
            } else {
12512
233
              std::string_view path = url.get_pathname();
12513
233
              if (helpers::shorten_path(path, url.type)) {
12514
197
                url.update_base_pathname(std::string(path));
12515
197
              }
12516
233
            }
12517
            // Set state to path state and decrease pointer by 1.
12518
233
            state = ada::state::PATH;
12519
233
            break;
12520
233
          }
12521
731
        }
12522
542
        input_position++;
12523
542
        break;
12524
775
      }
12525
44
      case ada::state::RELATIVE_SLASH: {
12526
44
        ada_log("RELATIVE_SLASH ",
12527
44
                helpers::substring(url_data, input_position));
12528
12529
        // If url is special and c is U+002F (/) or U+005C (\), then:
12530
44
        if (url.is_special() && (input_position != input_size) &&
12531
44
            (url_data[input_position] == '/' ||
12532
18
             url_data[input_position] == '\\')) {
12533
          // Set state to special authority ignore slashes state.
12534
3
          state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12535
3
        }
12536
        // Otherwise, if c is U+002F (/), then set state to authority state.
12537
41
        else if ((input_position != input_size) &&
12538
41
                 (url_data[input_position] == '/')) {
12539
5
          state = ada::state::AUTHORITY;
12540
5
        }
12541
        // Otherwise, set
12542
        // - url’s username to base’s username,
12543
        // - url’s password to base’s password,
12544
        // - url’s host to base’s host,
12545
        // - url’s port to base’s port,
12546
        // - state to path state, and then, decrease pointer by 1.
12547
36
        else {
12548
36
          if constexpr (result_type_is_ada_url) {
12549
36
            url.username = base_url->username;
12550
36
            url.password = base_url->password;
12551
36
            url.host = base_url->host;
12552
36
            url.port = base_url->port;
12553
36
          } else {
12554
36
            url.update_base_authority(base_url->get_href(),
12555
36
                                      base_url->get_components());
12556
            // TODO: Get rid of set_hostname and replace it with
12557
            // update_base_hostname
12558
36
            url.set_hostname(base_url->get_hostname());
12559
36
            url.update_base_port(base_url->retrieve_base_port());
12560
36
          }
12561
36
          state = ada::state::PATH;
12562
36
          break;
12563
36
        }
12564
12565
8
        input_position++;
12566
8
        break;
12567
44
      }
12568
12.7k
      case ada::state::SPECIAL_AUTHORITY_SLASHES: {
12569
12.7k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
12570
12.7k
                helpers::substring(url_data, input_position));
12571
12572
        // If c is U+002F (/) and remaining starts with U+002F (/),
12573
        // then set state to special authority ignore slashes state and increase
12574
        // pointer by 1.
12575
12.7k
        state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12576
12.7k
        std::string_view view = helpers::substring(url_data, input_position);
12577
12.7k
        if (ada::checkers::begins_with(view, "//")) {
12578
34
          input_position += 2;
12579
34
        }
12580
12581
12.7k
        [[fallthrough]];
12582
12.7k
      }
12583
12.7k
      case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
12584
12.7k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
12585
12.7k
                helpers::substring(url_data, input_position));
12586
12587
        // If c is neither U+002F (/) nor U+005C (\), then set state to
12588
        // authority state and decrease pointer by 1.
12589
13.9k
        while ((input_position != input_size) &&
12590
13.9k
               ((url_data[input_position] == '/') ||
12591
13.8k
                (url_data[input_position] == '\\'))) {
12592
1.16k
          input_position++;
12593
1.16k
        }
12594
12.7k
        state = ada::state::AUTHORITY;
12595
12596
12.7k
        break;
12597
12.7k
      }
12598
687
      case ada::state::QUERY: {
12599
687
        ada_log("QUERY ", helpers::substring(url_data, input_position));
12600
        // Let queryPercentEncodeSet be the special-query percent-encode set if
12601
        // url is special; otherwise the query percent-encode set.
12602
687
        const uint8_t* query_percent_encode_set =
12603
687
            url.is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12604
687
                             : ada::character_sets::QUERY_PERCENT_ENCODE;
12605
12606
        // Percent-encode after encoding, with encoding, buffer, and
12607
        // queryPercentEncodeSet, and append the result to url’s query.
12608
687
        url.update_base_search(helpers::substring(url_data, input_position),
12609
687
                               query_percent_encode_set);
12610
687
        ada_log("QUERY update_base_search completed ");
12611
687
        if (fragment.has_value()) {
12612
80
          url.update_unencoded_base_hash(*fragment);
12613
80
        }
12614
687
        return url;
12615
12.7k
      }
12616
13.0k
      case ada::state::HOST: {
12617
13.0k
        ada_log("HOST ", helpers::substring(url_data, input_position));
12618
12619
13.0k
        std::string_view host_view =
12620
13.0k
            helpers::substring(url_data, input_position);
12621
13.0k
        auto [location, found_colon] =
12622
13.0k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
12623
13.0k
        input_position = (location != std::string_view::npos)
12624
13.0k
                             ? input_position + location
12625
13.0k
                             : input_size;
12626
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12627
        // Note: the 'found_colon' value is true if and only if a colon was
12628
        // encountered while not inside brackets.
12629
13.0k
        if (found_colon) {
12630
          // If buffer is the empty string, validation error, return failure.
12631
          // Let host be the result of host parsing buffer with url is not
12632
          // special.
12633
1.94k
          ada_log("HOST parsing ", host_view);
12634
1.94k
          if (!url.parse_host(host_view)) {
12635
295
            return url;
12636
295
          }
12637
1.64k
          ada_log("HOST parsing results in ", url.get_hostname());
12638
          // Set url’s host to host, buffer to the empty string, and state to
12639
          // port state.
12640
1.64k
          state = ada::state::PORT;
12641
1.64k
          input_position++;
12642
1.64k
        }
12643
        // Otherwise, if one of the following is true:
12644
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12645
        // - url is special and c is U+005C (\)
12646
        // The get_host_delimiter_location function either brings us to
12647
        // the colon outside of the bracket, or to one of those characters.
12648
11.1k
        else {
12649
          // If url is special and host_view is the empty string, validation
12650
          // error, return failure.
12651
11.1k
          if (url.is_special() && host_view.empty()) {
12652
103
            url.is_valid = false;
12653
103
            return url;
12654
103
          }
12655
11.0k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
12656
          // Let host be the result of host parsing host_view with url is not
12657
          // special.
12658
11.0k
          if (host_view.empty()) {
12659
75
            url.update_base_hostname("");
12660
10.9k
          } else if (!url.parse_host(host_view)) {
12661
2.60k
            return url;
12662
2.60k
          }
12663
8.40k
          ada_log("HOST parsing results in ", url.get_hostname(),
12664
8.40k
                  " href=", url.get_href());
12665
12666
          // Set url’s host to host, and state to path start state.
12667
8.40k
          state = ada::state::PATH_START;
12668
8.40k
        }
12669
12670
10.0k
        break;
12671
13.0k
      }
12672
10.0k
      case ada::state::OPAQUE_PATH: {
12673
3.34k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
12674
3.34k
        std::string_view view = helpers::substring(url_data, input_position);
12675
        // If c is U+003F (?), then set url’s query to the empty string and
12676
        // state to query state.
12677
3.34k
        size_t location = view.find('?');
12678
3.34k
        if (location != std::string_view::npos) {
12679
224
          view.remove_suffix(view.size() - location);
12680
224
          state = ada::state::QUERY;
12681
224
          input_position += location + 1;
12682
3.11k
        } else {
12683
3.11k
          input_position = input_size + 1;
12684
3.11k
        }
12685
3.34k
        url.has_opaque_path = true;
12686
        // This is a really unlikely scenario in real world. We should not seek
12687
        // to optimize it.
12688
3.34k
        url.update_base_pathname(unicode::percent_encode(
12689
3.34k
            view, character_sets::C0_CONTROL_PERCENT_ENCODE));
12690
3.34k
        break;
12691
13.0k
      }
12692
1.64k
      case ada::state::PORT: {
12693
1.64k
        ada_log("PORT ", helpers::substring(url_data, input_position));
12694
1.64k
        std::string_view port_view =
12695
1.64k
            helpers::substring(url_data, input_position);
12696
1.64k
        size_t consumed_bytes = url.parse_port(port_view, true);
12697
1.64k
        input_position += consumed_bytes;
12698
1.64k
        if (!url.is_valid) {
12699
187
          return url;
12700
187
        }
12701
1.46k
        state = state::PATH_START;
12702
1.46k
        [[fallthrough]];
12703
1.46k
      }
12704
11.1k
      case ada::state::PATH_START: {
12705
11.1k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
12706
12707
        // If url is special, then:
12708
11.1k
        if (url.is_special()) {
12709
          // Set state to path state.
12710
10.6k
          state = ada::state::PATH;
12711
12712
          // Optimization: Avoiding going into PATH state improves the
12713
          // performance of urls ending with /.
12714
10.6k
          if (input_position == input_size) {
12715
9.64k
            url.update_base_pathname("/");
12716
9.64k
            if (fragment.has_value()) {
12717
176
              url.update_unencoded_base_hash(*fragment);
12718
176
            }
12719
9.64k
            return url;
12720
9.64k
          }
12721
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
12722
          // by 1. We know that (input_position == input_size) is impossible
12723
          // here, because of the previous if-check.
12724
961
          if ((url_data[input_position] != '/') &&
12725
961
              (url_data[input_position] != '\\')) {
12726
202
            break;
12727
202
          }
12728
961
        }
12729
        // Otherwise, if state override is not given and c is U+003F (?),
12730
        // set url’s query to the empty string and state to query state.
12731
570
        else if ((input_position != input_size) &&
12732
570
                 (url_data[input_position] == '?')) {
12733
59
          state = ada::state::QUERY;
12734
59
        }
12735
        // Otherwise, if c is not the EOF code point:
12736
511
        else if (input_position != input_size) {
12737
          // Set state to path state.
12738
64
          state = ada::state::PATH;
12739
12740
          // If c is not U+002F (/), then decrease pointer by 1.
12741
64
          if (url_data[input_position] != '/') {
12742
0
            break;
12743
0
          }
12744
64
        }
12745
12746
1.32k
        input_position++;
12747
1.32k
        break;
12748
11.1k
      }
12749
7.26k
      case ada::state::PATH: {
12750
7.26k
        std::string_view view = helpers::substring(url_data, input_position);
12751
7.26k
        ada_log("PATH ", helpers::substring(url_data, input_position));
12752
12753
        // Most time, we do not need percent encoding.
12754
        // Furthermore, we can immediately locate the '?'.
12755
7.26k
        size_t locofquestionmark = view.find('?');
12756
7.26k
        if (locofquestionmark != std::string_view::npos) {
12757
397
          state = ada::state::QUERY;
12758
397
          view.remove_suffix(view.size() - locofquestionmark);
12759
397
          input_position += locofquestionmark + 1;
12760
6.86k
        } else {
12761
6.86k
          input_position = input_size + 1;
12762
6.86k
        }
12763
7.26k
        if constexpr (result_type_is_ada_url) {
12764
7.26k
          helpers::parse_prepared_path(view, url.type, url.path);
12765
7.26k
        } else {
12766
7.26k
          url.consume_prepared_path(view);
12767
7.26k
          ADA_ASSERT_TRUE(url.validate());
12768
7.26k
        }
12769
7.26k
        break;
12770
11.1k
      }
12771
1.96k
      case ada::state::FILE_SLASH: {
12772
1.96k
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
12773
12774
        // If c is U+002F (/) or U+005C (\), then:
12775
1.96k
        if ((input_position != input_size) &&
12776
1.96k
            (url_data[input_position] == '/' ||
12777
1.67k
             url_data[input_position] == '\\')) {
12778
1.58k
          ada_log("FILE_SLASH c is U+002F or U+005C");
12779
          // Set state to file host state.
12780
1.58k
          state = ada::state::FILE_HOST;
12781
1.58k
          input_position++;
12782
1.58k
        } else {
12783
376
          ada_log("FILE_SLASH otherwise");
12784
          // If base is non-null and base’s scheme is "file", then:
12785
          // Note: it is unsafe to do base_url->scheme unless you know that
12786
          // base_url_has_value() is true.
12787
376
          if (base_url != nullptr &&
12788
376
              base_url->type == ada::scheme::type::FILE) {
12789
            // Set url’s host to base’s host.
12790
261
            if constexpr (result_type_is_ada_url) {
12791
261
              url.host = base_url->host;
12792
261
            } else {
12793
              // TODO: Optimization opportunity.
12794
261
              url.set_host(base_url->get_host());
12795
261
            }
12796
            // If the code point substring from pointer to the end of input does
12797
            // not start with a Windows drive letter and base’s path[0] is a
12798
            // normalized Windows drive letter, then append base’s path[0] to
12799
            // url’s path.
12800
261
            if (!base_url->get_pathname().empty()) {
12801
261
              if (!checkers::is_windows_drive_letter(
12802
261
                      helpers::substring(url_data, input_position))) {
12803
256
                std::string_view first_base_url_path =
12804
256
                    base_url->get_pathname().substr(1);
12805
256
                size_t loc = first_base_url_path.find('/');
12806
256
                if (loc != std::string_view::npos) {
12807
12
                  helpers::resize(first_base_url_path, loc);
12808
12
                }
12809
256
                if (checkers::is_normalized_windows_drive_letter(
12810
256
                        first_base_url_path)) {
12811
3
                  if constexpr (result_type_is_ada_url) {
12812
3
                    url.path += '/';
12813
3
                    url.path += first_base_url_path;
12814
3
                  } else {
12815
3
                    url.append_base_pathname(
12816
3
                        helpers::concat("/", first_base_url_path));
12817
3
                  }
12818
3
                }
12819
256
              }
12820
261
            }
12821
261
          }
12822
12823
          // Set state to path state, and decrease pointer by 1.
12824
376
          state = ada::state::PATH;
12825
376
        }
12826
12827
1.96k
        break;
12828
11.1k
      }
12829
1.58k
      case ada::state::FILE_HOST: {
12830
1.58k
        std::string_view view = helpers::substring(url_data, input_position);
12831
1.58k
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
12832
12833
1.58k
        size_t location = view.find_first_of("/\\?");
12834
1.58k
        std::string_view file_host_buffer(
12835
1.58k
            view.data(),
12836
1.58k
            (location != std::string_view::npos) ? location : view.size());
12837
12838
1.58k
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
12839
22
          state = ada::state::PATH;
12840
1.56k
        } else if (file_host_buffer.empty()) {
12841
          // Set url’s host to the empty string.
12842
43
          if constexpr (result_type_is_ada_url) {
12843
43
            url.host = "";
12844
43
          } else {
12845
43
            url.update_base_hostname("");
12846
43
          }
12847
          // Set state to path start state.
12848
43
          state = ada::state::PATH_START;
12849
1.52k
        } else {
12850
1.52k
          size_t consumed_bytes = file_host_buffer.size();
12851
1.52k
          input_position += consumed_bytes;
12852
          // Let host be the result of host parsing buffer with url is not
12853
          // special.
12854
1.52k
          if (!url.parse_host(file_host_buffer)) {
12855
259
            return url;
12856
259
          }
12857
12858
1.26k
          if constexpr (result_type_is_ada_url) {
12859
            // If host is "localhost", then set host to the empty string.
12860
1.26k
            if (url.host.has_value() && url.host.value() == "localhost") {
12861
1.26k
              url.host = "";
12862
1.26k
            }
12863
1.26k
          } else {
12864
1.26k
            if (url.get_hostname() == "localhost") {
12865
10
              url.update_base_hostname("");
12866
10
            }
12867
1.26k
          }
12868
12869
          // Set buffer to the empty string and state to path start state.
12870
1.26k
          state = ada::state::PATH_START;
12871
1.26k
        }
12872
12873
1.33k
        break;
12874
1.58k
      }
12875
4.69k
      case ada::state::FILE: {
12876
4.69k
        ada_log("FILE ", helpers::substring(url_data, input_position));
12877
4.69k
        std::string_view file_view =
12878
4.69k
            helpers::substring(url_data, input_position);
12879
12880
4.69k
        url.set_protocol_as_file();
12881
4.69k
        if constexpr (result_type_is_ada_url) {
12882
          // Set url’s host to the empty string.
12883
4.69k
          url.host = "";
12884
4.69k
        } else {
12885
4.69k
          url.update_base_hostname("");
12886
4.69k
        }
12887
        // If c is U+002F (/) or U+005C (\), then:
12888
4.69k
        if (input_position != input_size &&
12889
4.69k
            (url_data[input_position] == '/' ||
12890
2.92k
             url_data[input_position] == '\\')) {
12891
1.96k
          ada_log("FILE c is U+002F or U+005C");
12892
          // Set state to file slash state.
12893
1.96k
          state = ada::state::FILE_SLASH;
12894
1.96k
        }
12895
        // Otherwise, if base is non-null and base’s scheme is "file":
12896
2.72k
        else if (base_url != nullptr &&
12897
2.72k
                 base_url->type == ada::scheme::type::FILE) {
12898
          // Set url’s host to base’s host, url’s path to a clone of base’s
12899
          // path, and url’s query to base’s query.
12900
380
          ada_log("FILE base non-null");
12901
380
          if constexpr (result_type_is_ada_url) {
12902
380
            url.host = base_url->host;
12903
380
            url.path = base_url->path;
12904
380
            url.query = base_url->query;
12905
380
          } else {
12906
            // TODO: Get rid of set_hostname and replace it with
12907
            // update_base_hostname
12908
380
            url.set_hostname(base_url->get_hostname());
12909
380
            url.update_base_pathname(base_url->get_pathname());
12910
380
            url.update_base_search(base_url->get_search());
12911
380
          }
12912
380
          url.has_opaque_path = base_url->has_opaque_path;
12913
12914
          // If c is U+003F (?), then set url’s query to the empty string and
12915
          // state to query state.
12916
380
          if (input_position != input_size && url_data[input_position] == '?') {
12917
2
            state = ada::state::QUERY;
12918
2
          }
12919
          // Otherwise, if c is not the EOF code point:
12920
378
          else if (input_position != input_size) {
12921
            // Set url’s query to null.
12922
105
            url.clear_search();
12923
            // If the code point substring from pointer to the end of input does
12924
            // not start with a Windows drive letter, then shorten url’s path.
12925
105
            if (!checkers::is_windows_drive_letter(file_view)) {
12926
93
              if constexpr (result_type_is_ada_url) {
12927
93
                helpers::shorten_path(url.path, url.type);
12928
93
              } else {
12929
93
                std::string_view path = url.get_pathname();
12930
93
                if (helpers::shorten_path(path, url.type)) {
12931
85
                  url.update_base_pathname(std::string(path));
12932
85
                }
12933
93
              }
12934
93
            }
12935
            // Otherwise:
12936
12
            else {
12937
              // Set url’s path to an empty list.
12938
12
              url.clear_pathname();
12939
12
              url.has_opaque_path = true;
12940
12
            }
12941
12942
            // Set state to path state and decrease pointer by 1.
12943
105
            state = ada::state::PATH;
12944
105
            break;
12945
105
          }
12946
380
        }
12947
        // Otherwise, set state to path state, and decrease pointer by 1.
12948
2.34k
        else {
12949
2.34k
          ada_log("FILE go to path");
12950
2.34k
          state = ada::state::PATH;
12951
2.34k
          break;
12952
2.34k
        }
12953
12954
2.24k
        input_position++;
12955
2.24k
        break;
12956
4.69k
      }
12957
0
      default:
12958
0
        ada::unreachable();
12959
168k
    }
12960
168k
  }
12961
11.1k
  if (fragment.has_value()) {
12962
408
    url.update_unencoded_base_hash(*fragment);
12963
408
  }
12964
11.1k
  return url;
12965
45.4k
}
12966
12967
template url parse_url<url>(std::string_view user_input,
12968
                            const url* base_url = nullptr);
12969
template url_aggregator parse_url<url_aggregator>(
12970
    std::string_view user_input, const url_aggregator* base_url = nullptr);
12971
12972
}  // namespace ada::parser
12973
/* end file src/parser.cpp */
12974
/* begin file src/url_components.cpp */
12975
12976
#include <numeric>
12977
#include <string>
12978
12979
namespace ada {
12980
12981
0
bool url_components::check_offset_consistency() const noexcept {
12982
  /**
12983
   * https://user:pass@example.com:1234/foo/bar?baz#quux
12984
   *       |     |    |          | ^^^^|       |   |
12985
   *       |     |    |          | |   |       |   `----- hash_start
12986
   *       |     |    |          | |   |       `--------- search_start
12987
   *       |     |    |          | |   `----------------- pathname_start
12988
   *       |     |    |          | `--------------------- port
12989
   *       |     |    |          `----------------------- host_end
12990
   *       |     |    `---------------------------------- host_start
12991
   *       |     `--------------------------------------- username_end
12992
   *       `--------------------------------------------- protocol_end
12993
   */
12994
  // These conditions can be made more strict.
12995
0
  uint32_t index = 0;
12996
12997
0
  if (protocol_end == url_components::omitted) {
12998
0
    return false;
12999
0
  }
13000
0
  if (protocol_end < index) {
13001
0
    return false;
13002
0
  }
13003
0
  index = protocol_end;
13004
13005
0
  if (username_end == url_components::omitted) {
13006
0
    return false;
13007
0
  }
13008
0
  if (username_end < index) {
13009
0
    return false;
13010
0
  }
13011
0
  index = username_end;
13012
13013
0
  if (host_start == url_components::omitted) {
13014
0
    return false;
13015
0
  }
13016
0
  if (host_start < index) {
13017
0
    return false;
13018
0
  }
13019
0
  index = host_start;
13020
13021
0
  if (port != url_components::omitted) {
13022
0
    if (port > 0xffff) {
13023
0
      return false;
13024
0
    }
13025
0
    uint32_t port_length = helpers::fast_digit_count(port) + 1;
13026
0
    if (index + port_length < index) {
13027
0
      return false;
13028
0
    }
13029
0
    index += port_length;
13030
0
  }
13031
13032
0
  if (pathname_start == url_components::omitted) {
13033
0
    return false;
13034
0
  }
13035
0
  if (pathname_start < index) {
13036
0
    return false;
13037
0
  }
13038
0
  index = pathname_start;
13039
13040
0
  if (search_start != url_components::omitted) {
13041
0
    if (search_start < index) {
13042
0
      return false;
13043
0
    }
13044
0
    index = search_start;
13045
0
  }
13046
13047
0
  if (hash_start != url_components::omitted) {
13048
0
    if (hash_start < index) {
13049
0
      return false;
13050
0
    }
13051
0
    index = hash_start;
13052
0
  }
13053
13054
0
  return true;
13055
0
}
13056
13057
0
std::string url_components::to_string() const {
13058
0
  std::string answer;
13059
0
  auto back = std::back_insert_iterator(answer);
13060
0
  answer.append("{\n");
13061
13062
0
  answer.append("\t\"protocol_end\":\"");
13063
0
  helpers::encode_json(std::to_string(protocol_end), back);
13064
0
  answer.append("\",\n");
13065
13066
0
  answer.append("\t\"username_end\":\"");
13067
0
  helpers::encode_json(std::to_string(username_end), back);
13068
0
  answer.append("\",\n");
13069
13070
0
  answer.append("\t\"host_start\":\"");
13071
0
  helpers::encode_json(std::to_string(host_start), back);
13072
0
  answer.append("\",\n");
13073
13074
0
  answer.append("\t\"host_end\":\"");
13075
0
  helpers::encode_json(std::to_string(host_end), back);
13076
0
  answer.append("\",\n");
13077
13078
0
  answer.append("\t\"port\":\"");
13079
0
  helpers::encode_json(std::to_string(port), back);
13080
0
  answer.append("\",\n");
13081
13082
0
  answer.append("\t\"pathname_start\":\"");
13083
0
  helpers::encode_json(std::to_string(pathname_start), back);
13084
0
  answer.append("\",\n");
13085
13086
0
  answer.append("\t\"search_start\":\"");
13087
0
  helpers::encode_json(std::to_string(search_start), back);
13088
0
  answer.append("\",\n");
13089
13090
0
  answer.append("\t\"hash_start\":\"");
13091
0
  helpers::encode_json(std::to_string(hash_start), back);
13092
0
  answer.append("\",\n");
13093
13094
0
  answer.append("\n}");
13095
0
  return answer;
13096
0
}
13097
13098
}  // namespace ada
13099
/* end file src/url_components.cpp */
13100
/* begin file src/url_aggregator.cpp */
13101
13102
#include <string>
13103
#include <string_view>
13104
13105
namespace ada {
13106
template <bool has_state_override>
13107
[[nodiscard]] ada_really_inline bool url_aggregator::parse_scheme_with_colon(
13108
24.6k
    const std::string_view input_with_colon) {
13109
24.6k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
13110
24.6k
  ADA_ASSERT_TRUE(validate());
13111
24.6k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
13112
24.6k
  std::string_view input{input_with_colon};
13113
24.6k
  input.remove_suffix(1);
13114
24.6k
  auto parsed_type = ada::scheme::get_scheme_type(input);
13115
24.6k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
13116
  /**
13117
   * In the common case, we will immediately recognize a special scheme (e.g.,
13118
   *http, https), in which case, we can go really fast.
13119
   **/
13120
24.6k
  if (is_input_special) {  // fast path!!!
13121
10.6k
    if (has_state_override) {
13122
      // If url’s scheme is not a special scheme and buffer is a special scheme,
13123
      // then return.
13124
71
      if (is_special() != is_input_special) {
13125
2
        return true;
13126
2
      }
13127
13128
      // If url includes credentials or has a non-null port, and buffer is
13129
      // "file", then return.
13130
69
      if ((has_credentials() || components.port != url_components::omitted) &&
13131
69
          parsed_type == ada::scheme::type::FILE) {
13132
1
        return true;
13133
1
      }
13134
13135
      // If url’s scheme is "file" and its host is an empty host, then return.
13136
      // An empty host is the empty string.
13137
68
      if (type == ada::scheme::type::FILE &&
13138
68
          components.host_start == components.host_end) {
13139
2
        return true;
13140
2
      }
13141
68
    }
13142
13143
10.6k
    type = parsed_type;
13144
10.6k
    set_scheme_from_view_with_colon(input_with_colon);
13145
13146
10.6k
    if (has_state_override) {
13147
      // This is uncommon.
13148
66
      uint16_t urls_scheme_port = get_special_port();
13149
13150
      // If url’s port is url’s scheme’s default port, then set url’s port to
13151
      // null.
13152
66
      if (components.port == urls_scheme_port) {
13153
13
        clear_port();
13154
13
      }
13155
66
    }
13156
13.9k
  } else {  // slow path
13157
13.9k
    std::string _buffer = std::string(input);
13158
    // Next function is only valid if the input is ASCII and returns false
13159
    // otherwise, but it seems that we always have ascii content so we do not
13160
    // need to check the return value.
13161
13.9k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
13162
13163
13.9k
    if (has_state_override) {
13164
      // If url’s scheme is a special scheme and buffer is not a special scheme,
13165
      // then return. If url’s scheme is not a special scheme and buffer is a
13166
      // special scheme, then return.
13167
282
      if (is_special() != ada::scheme::is_special(_buffer)) {
13168
117
        return true;
13169
117
      }
13170
13171
      // If url includes credentials or has a non-null port, and buffer is
13172
      // "file", then return.
13173
165
      if ((has_credentials() || components.port != url_components::omitted) &&
13174
165
          _buffer == "file") {
13175
1
        return true;
13176
1
      }
13177
13178
      // If url’s scheme is "file" and its host is an empty host, then return.
13179
      // An empty host is the empty string.
13180
164
      if (type == ada::scheme::type::FILE &&
13181
164
          components.host_start == components.host_end) {
13182
3
        return true;
13183
3
      }
13184
164
    }
13185
13186
13.8k
    set_scheme(_buffer);
13187
13188
13.8k
    if (has_state_override) {
13189
      // This is uncommon.
13190
161
      uint16_t urls_scheme_port = get_special_port();
13191
13192
      // If url’s port is url’s scheme’s default port, then set url’s port to
13193
      // null.
13194
161
      if (components.port == urls_scheme_port) {
13195
14
        clear_port();
13196
14
      }
13197
161
    }
13198
13.8k
  }
13199
24.4k
  ADA_ASSERT_TRUE(validate());
13200
24.4k
  return true;
13201
24.6k
}
bool ada::url_aggregator::parse_scheme_with_colon<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
13108
24.2k
    const std::string_view input_with_colon) {
13109
24.2k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
13110
24.2k
  ADA_ASSERT_TRUE(validate());
13111
24.2k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
13112
24.2k
  std::string_view input{input_with_colon};
13113
24.2k
  input.remove_suffix(1);
13114
24.2k
  auto parsed_type = ada::scheme::get_scheme_type(input);
13115
24.2k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
13116
  /**
13117
   * In the common case, we will immediately recognize a special scheme (e.g.,
13118
   *http, https), in which case, we can go really fast.
13119
   **/
13120
24.2k
  if (is_input_special) {  // fast path!!!
13121
10.5k
    if (has_state_override) {
13122
      // If url’s scheme is not a special scheme and buffer is a special scheme,
13123
      // then return.
13124
0
      if (is_special() != is_input_special) {
13125
0
        return true;
13126
0
      }
13127
13128
      // If url includes credentials or has a non-null port, and buffer is
13129
      // "file", then return.
13130
0
      if ((has_credentials() || components.port != url_components::omitted) &&
13131
0
          parsed_type == ada::scheme::type::FILE) {
13132
0
        return true;
13133
0
      }
13134
13135
      // If url’s scheme is "file" and its host is an empty host, then return.
13136
      // An empty host is the empty string.
13137
0
      if (type == ada::scheme::type::FILE &&
13138
0
          components.host_start == components.host_end) {
13139
0
        return true;
13140
0
      }
13141
0
    }
13142
13143
10.5k
    type = parsed_type;
13144
10.5k
    set_scheme_from_view_with_colon(input_with_colon);
13145
13146
10.5k
    if (has_state_override) {
13147
      // This is uncommon.
13148
0
      uint16_t urls_scheme_port = get_special_port();
13149
13150
      // If url’s port is url’s scheme’s default port, then set url’s port to
13151
      // null.
13152
0
      if (components.port == urls_scheme_port) {
13153
0
        clear_port();
13154
0
      }
13155
0
    }
13156
13.6k
  } else {  // slow path
13157
13.6k
    std::string _buffer = std::string(input);
13158
    // Next function is only valid if the input is ASCII and returns false
13159
    // otherwise, but it seems that we always have ascii content so we do not
13160
    // need to check the return value.
13161
13.6k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
13162
13163
13.6k
    if (has_state_override) {
13164
      // If url’s scheme is a special scheme and buffer is not a special scheme,
13165
      // then return. If url’s scheme is not a special scheme and buffer is a
13166
      // special scheme, then return.
13167
0
      if (is_special() != ada::scheme::is_special(_buffer)) {
13168
0
        return true;
13169
0
      }
13170
13171
      // If url includes credentials or has a non-null port, and buffer is
13172
      // "file", then return.
13173
0
      if ((has_credentials() || components.port != url_components::omitted) &&
13174
0
          _buffer == "file") {
13175
0
        return true;
13176
0
      }
13177
13178
      // If url’s scheme is "file" and its host is an empty host, then return.
13179
      // An empty host is the empty string.
13180
0
      if (type == ada::scheme::type::FILE &&
13181
0
          components.host_start == components.host_end) {
13182
0
        return true;
13183
0
      }
13184
0
    }
13185
13186
13.6k
    set_scheme(_buffer);
13187
13188
13.6k
    if (has_state_override) {
13189
      // This is uncommon.
13190
0
      uint16_t urls_scheme_port = get_special_port();
13191
13192
      // If url’s port is url’s scheme’s default port, then set url’s port to
13193
      // null.
13194
0
      if (components.port == urls_scheme_port) {
13195
0
        clear_port();
13196
0
      }
13197
0
    }
13198
13.6k
  }
13199
24.2k
  ADA_ASSERT_TRUE(validate());
13200
24.2k
  return true;
13201
24.2k
}
bool ada::url_aggregator::parse_scheme_with_colon<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
13108
353
    const std::string_view input_with_colon) {
13109
353
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
13110
353
  ADA_ASSERT_TRUE(validate());
13111
353
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
13112
353
  std::string_view input{input_with_colon};
13113
353
  input.remove_suffix(1);
13114
353
  auto parsed_type = ada::scheme::get_scheme_type(input);
13115
353
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
13116
  /**
13117
   * In the common case, we will immediately recognize a special scheme (e.g.,
13118
   *http, https), in which case, we can go really fast.
13119
   **/
13120
353
  if (is_input_special) {  // fast path!!!
13121
71
    if (has_state_override) {
13122
      // If url’s scheme is not a special scheme and buffer is a special scheme,
13123
      // then return.
13124
71
      if (is_special() != is_input_special) {
13125
2
        return true;
13126
2
      }
13127
13128
      // If url includes credentials or has a non-null port, and buffer is
13129
      // "file", then return.
13130
69
      if ((has_credentials() || components.port != url_components::omitted) &&
13131
69
          parsed_type == ada::scheme::type::FILE) {
13132
1
        return true;
13133
1
      }
13134
13135
      // If url’s scheme is "file" and its host is an empty host, then return.
13136
      // An empty host is the empty string.
13137
68
      if (type == ada::scheme::type::FILE &&
13138
68
          components.host_start == components.host_end) {
13139
2
        return true;
13140
2
      }
13141
68
    }
13142
13143
66
    type = parsed_type;
13144
66
    set_scheme_from_view_with_colon(input_with_colon);
13145
13146
66
    if (has_state_override) {
13147
      // This is uncommon.
13148
66
      uint16_t urls_scheme_port = get_special_port();
13149
13150
      // If url’s port is url’s scheme’s default port, then set url’s port to
13151
      // null.
13152
66
      if (components.port == urls_scheme_port) {
13153
13
        clear_port();
13154
13
      }
13155
66
    }
13156
282
  } else {  // slow path
13157
282
    std::string _buffer = std::string(input);
13158
    // Next function is only valid if the input is ASCII and returns false
13159
    // otherwise, but it seems that we always have ascii content so we do not
13160
    // need to check the return value.
13161
282
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
13162
13163
282
    if (has_state_override) {
13164
      // If url’s scheme is a special scheme and buffer is not a special scheme,
13165
      // then return. If url’s scheme is not a special scheme and buffer is a
13166
      // special scheme, then return.
13167
282
      if (is_special() != ada::scheme::is_special(_buffer)) {
13168
117
        return true;
13169
117
      }
13170
13171
      // If url includes credentials or has a non-null port, and buffer is
13172
      // "file", then return.
13173
165
      if ((has_credentials() || components.port != url_components::omitted) &&
13174
165
          _buffer == "file") {
13175
1
        return true;
13176
1
      }
13177
13178
      // If url’s scheme is "file" and its host is an empty host, then return.
13179
      // An empty host is the empty string.
13180
164
      if (type == ada::scheme::type::FILE &&
13181
164
          components.host_start == components.host_end) {
13182
3
        return true;
13183
3
      }
13184
164
    }
13185
13186
161
    set_scheme(_buffer);
13187
13188
161
    if (has_state_override) {
13189
      // This is uncommon.
13190
161
      uint16_t urls_scheme_port = get_special_port();
13191
13192
      // If url’s port is url’s scheme’s default port, then set url’s port to
13193
      // null.
13194
161
      if (components.port == urls_scheme_port) {
13195
14
        clear_port();
13196
14
      }
13197
161
    }
13198
161
  }
13199
227
  ADA_ASSERT_TRUE(validate());
13200
227
  return true;
13201
353
}
13202
13203
803
inline void url_aggregator::copy_scheme(const url_aggregator& u) noexcept {
13204
803
  ada_log("url_aggregator::copy_scheme ", u.buffer);
13205
803
  ADA_ASSERT_TRUE(validate());
13206
  // next line could overflow but unsigned arithmetic has well-defined
13207
  // overflows.
13208
803
  uint32_t new_difference = u.components.protocol_end - components.protocol_end;
13209
803
  type = u.type;
13210
803
  buffer.erase(0, components.protocol_end);
13211
803
  buffer.insert(0, u.get_protocol());
13212
803
  components.protocol_end = u.components.protocol_end;
13213
13214
  // No need to update the components
13215
803
  if (new_difference == 0) {
13216
118
    return;
13217
118
  }
13218
13219
  // Update the rest of the components.
13220
685
  components.username_end += new_difference;
13221
685
  components.host_start += new_difference;
13222
685
  components.host_end += new_difference;
13223
685
  components.pathname_start += new_difference;
13224
685
  if (components.search_start != url_components::omitted) {
13225
0
    components.search_start += new_difference;
13226
0
  }
13227
685
  if (components.hash_start != url_components::omitted) {
13228
0
    components.hash_start += new_difference;
13229
0
  }
13230
685
  ADA_ASSERT_TRUE(validate());
13231
685
}
13232
13233
inline void url_aggregator::set_scheme_from_view_with_colon(
13234
10.6k
    std::string_view new_scheme_with_colon) noexcept {
13235
10.6k
  ada_log("url_aggregator::set_scheme_from_view_with_colon ",
13236
10.6k
          new_scheme_with_colon);
13237
10.6k
  ADA_ASSERT_TRUE(validate());
13238
10.6k
  ADA_ASSERT_TRUE(!new_scheme_with_colon.empty() &&
13239
10.6k
                  new_scheme_with_colon.back() == ':');
13240
  // next line could overflow but unsigned arithmetic has well-defined
13241
  // overflows.
13242
10.6k
  uint32_t new_difference =
13243
10.6k
      uint32_t(new_scheme_with_colon.size()) - components.protocol_end;
13244
13245
10.6k
  if (buffer.empty()) {
13246
10.5k
    buffer.append(new_scheme_with_colon);
13247
10.5k
  } else {
13248
66
    buffer.erase(0, components.protocol_end);
13249
66
    buffer.insert(0, new_scheme_with_colon);
13250
66
  }
13251
10.6k
  components.protocol_end += new_difference;
13252
13253
  // Update the rest of the components.
13254
10.6k
  components.username_end += new_difference;
13255
10.6k
  components.host_start += new_difference;
13256
10.6k
  components.host_end += new_difference;
13257
10.6k
  components.pathname_start += new_difference;
13258
10.6k
  if (components.search_start != url_components::omitted) {
13259
18
    components.search_start += new_difference;
13260
18
  }
13261
10.6k
  if (components.hash_start != url_components::omitted) {
13262
10
    components.hash_start += new_difference;
13263
10
  }
13264
10.6k
  ADA_ASSERT_TRUE(validate());
13265
10.6k
}
13266
13267
13.8k
inline void url_aggregator::set_scheme(std::string_view new_scheme) noexcept {
13268
13.8k
  ada_log("url_aggregator::set_scheme ", new_scheme);
13269
13.8k
  ADA_ASSERT_TRUE(validate());
13270
13.8k
  ADA_ASSERT_TRUE(new_scheme.empty() || new_scheme.back() != ':');
13271
  // next line could overflow but unsigned arithmetic has well-defined
13272
  // overflows.
13273
13.8k
  uint32_t new_difference =
13274
13.8k
      uint32_t(new_scheme.size()) - components.protocol_end + 1;
13275
13276
13.8k
  type = ada::scheme::get_scheme_type(new_scheme);
13277
13.8k
  if (buffer.empty()) {
13278
13.6k
    buffer.append(helpers::concat(new_scheme, ":"));
13279
13.6k
  } else {
13280
161
    buffer.erase(0, components.protocol_end);
13281
161
    buffer.insert(0, helpers::concat(new_scheme, ":"));
13282
161
  }
13283
13.8k
  components.protocol_end = uint32_t(new_scheme.size() + 1);
13284
13285
  // Update the rest of the components.
13286
13.8k
  components.username_end += new_difference;
13287
13.8k
  components.host_start += new_difference;
13288
13.8k
  components.host_end += new_difference;
13289
13.8k
  components.pathname_start += new_difference;
13290
13.8k
  if (components.search_start != url_components::omitted) {
13291
16
    components.search_start += new_difference;
13292
16
  }
13293
13.8k
  if (components.hash_start != url_components::omitted) {
13294
18
    components.hash_start += new_difference;
13295
18
  }
13296
13.8k
  ADA_ASSERT_TRUE(validate());
13297
13.8k
}
13298
13299
8.27k
bool url_aggregator::set_protocol(const std::string_view input) {
13300
8.27k
  ada_log("url_aggregator::set_protocol ", input);
13301
8.27k
  ADA_ASSERT_TRUE(validate());
13302
8.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13303
8.27k
  std::string view(input);
13304
8.27k
  helpers::remove_ascii_tab_or_newline(view);
13305
8.27k
  if (view.empty()) {
13306
6.74k
    return true;
13307
6.74k
  }
13308
13309
  // Schemes should start with alpha values.
13310
1.52k
  if (!checkers::is_alpha(view[0])) {
13311
1.08k
    return false;
13312
1.08k
  }
13313
13314
437
  view.append(":");
13315
13316
437
  std::string::iterator pointer =
13317
437
      std::find_if_not(view.begin(), view.end(), unicode::is_alnum_plus);
13318
13319
437
  if (pointer != view.end() && *pointer == ':') {
13320
353
    return parse_scheme_with_colon<true>(
13321
353
        std::string_view(view.data(), pointer - view.begin() + 1));
13322
353
  }
13323
84
  return false;
13324
437
}
13325
13326
8.27k
bool url_aggregator::set_username(const std::string_view input) {
13327
8.27k
  ada_log("url_aggregator::set_username '", input, "' ");
13328
8.27k
  ADA_ASSERT_TRUE(validate());
13329
8.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13330
8.27k
  if (cannot_have_credentials_or_port()) {
13331
4.04k
    return false;
13332
4.04k
  }
13333
4.22k
  size_t idx = ada::unicode::percent_encode_index(
13334
4.22k
      input, character_sets::USERINFO_PERCENT_ENCODE);
13335
4.22k
  if (idx == input.size()) {
13336
3.66k
    update_base_username(input);
13337
3.66k
  } else {
13338
    // We only create a temporary string if we have to!
13339
558
    update_base_username(ada::unicode::percent_encode(
13340
558
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
13341
558
  }
13342
4.22k
  ADA_ASSERT_TRUE(validate());
13343
4.22k
  return true;
13344
8.27k
}
13345
13346
8.27k
bool url_aggregator::set_password(const std::string_view input) {
13347
8.27k
  ada_log("url_aggregator::set_password '", input, "'");
13348
8.27k
  ADA_ASSERT_TRUE(validate());
13349
8.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13350
8.27k
  if (cannot_have_credentials_or_port()) {
13351
4.04k
    return false;
13352
4.04k
  }
13353
4.22k
  size_t idx = ada::unicode::percent_encode_index(
13354
4.22k
      input, character_sets::USERINFO_PERCENT_ENCODE);
13355
4.22k
  if (idx == input.size()) {
13356
3.66k
    update_base_password(input);
13357
3.66k
  } else {
13358
    // We only create a temporary string if we have to!
13359
558
    update_base_password(ada::unicode::percent_encode(
13360
558
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
13361
558
  }
13362
4.22k
  ADA_ASSERT_TRUE(validate());
13363
4.22k
  return true;
13364
8.27k
}
13365
13366
8.44k
bool url_aggregator::set_port(const std::string_view input) {
13367
8.44k
  ada_log("url_aggregator::set_port ", input);
13368
8.44k
  ADA_ASSERT_TRUE(validate());
13369
8.44k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13370
8.44k
  if (cannot_have_credentials_or_port()) {
13371
4.00k
    return false;
13372
4.00k
  }
13373
4.44k
  std::string trimmed(input);
13374
4.44k
  helpers::remove_ascii_tab_or_newline(trimmed);
13375
4.44k
  if (trimmed.empty()) {
13376
3.28k
    clear_port();
13377
3.28k
    return true;
13378
3.28k
  }
13379
  // Input should not start with control characters.
13380
1.16k
  if (ada::unicode::is_c0_control_or_space(trimmed.front())) {
13381
63
    return false;
13382
63
  }
13383
  // Input should contain at least one ascii digit.
13384
1.09k
  if (input.find_first_of("0123456789") == std::string_view::npos) {
13385
523
    return false;
13386
523
  }
13387
13388
  // Revert changes if parse_port fails.
13389
575
  uint32_t previous_port = components.port;
13390
575
  parse_port(trimmed);
13391
575
  if (is_valid) {
13392
425
    return true;
13393
425
  }
13394
150
  update_base_port(previous_port);
13395
150
  is_valid = true;
13396
150
  ADA_ASSERT_TRUE(validate());
13397
150
  return false;
13398
575
}
13399
13400
8.27k
bool url_aggregator::set_pathname(const std::string_view input) {
13401
8.27k
  ada_log("url_aggregator::set_pathname ", input);
13402
8.27k
  ADA_ASSERT_TRUE(validate());
13403
8.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13404
8.27k
  if (has_opaque_path) {
13405
1.06k
    return false;
13406
1.06k
  }
13407
7.20k
  clear_pathname();
13408
7.20k
  parse_path(input);
13409
7.20k
  if (checkers::begins_with(input, "//") && !has_authority() &&
13410
7.20k
      !has_dash_dot()) {
13411
3
    buffer.insert(components.pathname_start, "/.");
13412
3
    components.pathname_start += 2;
13413
3
  }
13414
7.20k
  ADA_ASSERT_TRUE(validate());
13415
7.20k
  return true;
13416
8.27k
}
13417
13418
7.20k
ada_really_inline void url_aggregator::parse_path(std::string_view input) {
13419
7.20k
  ada_log("url_aggregator::parse_path ", input);
13420
7.20k
  ADA_ASSERT_TRUE(validate());
13421
7.20k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13422
7.20k
  std::string tmp_buffer;
13423
7.20k
  std::string_view internal_input;
13424
7.20k
  if (unicode::has_tabs_or_newline(input)) {
13425
140
    tmp_buffer = input;
13426
    // Optimization opportunity: Instead of copying and then pruning, we could
13427
    // just directly build the string from user_input.
13428
140
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13429
140
    internal_input = tmp_buffer;
13430
7.06k
  } else {
13431
7.06k
    internal_input = input;
13432
7.06k
  }
13433
13434
  // If url is special, then:
13435
7.20k
  if (is_special()) {
13436
5.52k
    if (internal_input.empty()) {
13437
4.49k
      update_base_pathname("/");
13438
4.49k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
13439
24
      consume_prepared_path(internal_input.substr(1));
13440
1.00k
    } else {
13441
1.00k
      consume_prepared_path(internal_input);
13442
1.00k
    }
13443
5.52k
  } else if (!internal_input.empty()) {
13444
345
    if (internal_input[0] == '/') {
13445
32
      consume_prepared_path(internal_input.substr(1));
13446
313
    } else {
13447
313
      consume_prepared_path(internal_input);
13448
313
    }
13449
1.33k
  } else {
13450
    // Non-special URLs with an empty host can have their paths erased
13451
    // Path-only URLs cannot have their paths erased
13452
1.33k
    if (components.host_start == components.host_end && !has_authority()) {
13453
1.17k
      update_base_pathname("/");
13454
1.17k
    }
13455
1.33k
  }
13456
7.20k
  ADA_ASSERT_TRUE(validate());
13457
7.20k
}
13458
13459
8.27k
void url_aggregator::set_search(const std::string_view input) {
13460
8.27k
  ada_log("url_aggregator::set_search ", input);
13461
8.27k
  ADA_ASSERT_TRUE(validate());
13462
8.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13463
8.27k
  if (input.empty()) {
13464
6.67k
    clear_search();
13465
6.67k
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13466
6.67k
    return;
13467
6.67k
  }
13468
13469
1.60k
  std::string new_value;
13470
1.60k
  new_value = input[0] == '?' ? input.substr(1) : input;
13471
1.60k
  helpers::remove_ascii_tab_or_newline(new_value);
13472
13473
1.60k
  auto query_percent_encode_set =
13474
1.60k
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13475
1.60k
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
13476
13477
1.60k
  update_base_search(new_value, query_percent_encode_set);
13478
1.60k
  ADA_ASSERT_TRUE(validate());
13479
1.60k
}
13480
13481
8.27k
void url_aggregator::set_hash(const std::string_view input) {
13482
8.27k
  ada_log("url_aggregator::set_hash ", input);
13483
8.27k
  ADA_ASSERT_TRUE(validate());
13484
8.27k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13485
8.27k
  if (input.empty()) {
13486
6.67k
    if (components.hash_start != url_components::omitted) {
13487
126
      buffer.resize(components.hash_start);
13488
126
      components.hash_start = url_components::omitted;
13489
126
    }
13490
6.67k
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13491
6.67k
    return;
13492
6.67k
  }
13493
13494
1.60k
  std::string new_value;
13495
1.60k
  new_value = input[0] == '#' ? input.substr(1) : input;
13496
1.60k
  helpers::remove_ascii_tab_or_newline(new_value);
13497
1.60k
  update_unencoded_base_hash(new_value);
13498
1.60k
  ADA_ASSERT_TRUE(validate());
13499
1.60k
}
13500
13501
0
bool url_aggregator::set_href(const std::string_view input) {
13502
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13503
0
  ada_log("url_aggregator::set_href ", input, "[", input.size(), " bytes]");
13504
0
  ada::result<url_aggregator> out = ada::parse<url_aggregator>(input);
13505
0
  ada_log("url_aggregator::set_href, success :", out.has_value());
13506
13507
0
  if (out) {
13508
0
    ada_log("url_aggregator::set_href, parsed ", out->to_string());
13509
    // TODO: Figure out why the following line puts test to never finish.
13510
0
    *this = *out;
13511
0
  }
13512
13513
0
  return out.has_value();
13514
0
}
13515
13516
17.8k
ada_really_inline bool url_aggregator::parse_host(std::string_view input) {
13517
17.8k
  ada_log("url_aggregator:parse_host ", input, "[", input.size(), " bytes]");
13518
17.8k
  ADA_ASSERT_TRUE(validate());
13519
17.8k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13520
17.8k
  if (input.empty()) {
13521
31
    return is_valid = false;
13522
31
  }  // technically unnecessary.
13523
  // If input starts with U+005B ([), then:
13524
17.7k
  if (input[0] == '[') {
13525
    // If input does not end with U+005D (]), validation error, return failure.
13526
1.30k
    if (input.back() != ']') {
13527
385
      return is_valid = false;
13528
385
    }
13529
922
    ada_log("parse_host ipv6");
13530
13531
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
13532
    // trailing U+005D (]) removed.
13533
922
    input.remove_prefix(1);
13534
922
    input.remove_suffix(1);
13535
922
    return parse_ipv6(input);
13536
1.30k
  }
13537
13538
  // If isNotSpecial is true, then return the result of opaque-host parsing
13539
  // input.
13540
16.4k
  if (!is_special()) {
13541
1.00k
    return parse_opaque_host(input);
13542
1.00k
  }
13543
  // Let domain be the result of running UTF-8 decode without BOM on the
13544
  // percent-decoding of input. Let asciiDomain be the result of running domain
13545
  // to ASCII with domain and false. The most common case is an ASCII input, in
13546
  // which case we do not need to call the expensive 'to_ascii' if a few
13547
  // conditions are met: no '%' and no 'xn-' subsequence.
13548
13549
  // Often, the input does not contain any forbidden code points, and no upper
13550
  // case ASCII letter, then we can just copy it to the buffer. We want to
13551
  // optimize for such a common case.
13552
15.4k
  uint8_t is_forbidden_or_upper =
13553
15.4k
      unicode::contains_forbidden_domain_code_point_or_upper(input.data(),
13554
15.4k
                                                             input.size());
13555
  // Minor optimization opportunity:
13556
  // contains_forbidden_domain_code_point_or_upper could be extend to check for
13557
  // the presence of characters that cannot appear in the ipv4 address and we
13558
  // could also check whether x and n and - are present, and so we could skip
13559
  // some of the checks below. However, the gains are likely to be small, and
13560
  // the code would be more complex.
13561
15.4k
  if (is_forbidden_or_upper == 0 &&
13562
15.4k
      input.find("xn-") == std::string_view::npos) {
13563
    // fast path
13564
7.91k
    update_base_hostname(input);
13565
7.91k
    if (checkers::is_ipv4(get_hostname())) {
13566
3.21k
      ada_log("parse_host fast path ipv4");
13567
3.21k
      return parse_ipv4(get_hostname());
13568
3.21k
    }
13569
4.69k
    ada_log("parse_host fast path ", get_hostname());
13570
4.69k
    return true;
13571
7.91k
  }
13572
  // We have encountered at least one forbidden code point or the input contains
13573
  // 'xn-' (case insensitive), so we need to call 'to_ascii' to perform the full
13574
  // conversion.
13575
13576
7.54k
  ada_log("parse_host calling to_ascii");
13577
7.54k
  std::optional<std::string> host = std::string(get_hostname());
13578
7.54k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
13579
7.54k
  if (!is_valid) {
13580
1.99k
    ada_log("parse_host to_ascii returns false");
13581
1.99k
    return is_valid = false;
13582
1.99k
  }
13583
13584
5.55k
  if (std::any_of(host.value().begin(), host.value().end(),
13585
5.55k
                  ada::unicode::is_forbidden_domain_code_point)) {
13586
0
    return is_valid = false;
13587
0
  }
13588
13589
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
13590
  // asciiDomain.
13591
5.55k
  if (checkers::is_ipv4(host.value())) {
13592
808
    ada_log("parse_host got ipv4", *host);
13593
808
    return parse_ipv4(host.value());
13594
808
  }
13595
13596
4.74k
  update_base_hostname(host.value());
13597
4.74k
  ADA_ASSERT_TRUE(validate());
13598
4.74k
  return true;
13599
5.55k
}
13600
13601
template <bool override_hostname>
13602
17.9k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
13603
17.9k
  ada_log("url_aggregator::set_host_or_hostname ", input);
13604
17.9k
  ADA_ASSERT_TRUE(validate());
13605
17.9k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13606
17.9k
  if (has_opaque_path) {
13607
2.13k
    return false;
13608
2.13k
  }
13609
13610
15.8k
  std::string previous_host = std::string(get_hostname());
13611
15.8k
  uint32_t previous_port = components.port;
13612
13613
15.8k
  size_t host_end_pos = input.find('#');
13614
15.8k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
13615
15.8k
                                      ? host_end_pos
13616
15.8k
                                      : input.size());
13617
15.8k
  helpers::remove_ascii_tab_or_newline(_host);
13618
15.8k
  std::string_view new_host(_host);
13619
13620
  // If url's scheme is "file", then set state to file host state, instead of
13621
  // host state.
13622
15.8k
  if (type != ada::scheme::type::FILE) {
13623
12.2k
    std::string_view host_view(_host.data(), _host.length());
13624
12.2k
    auto [location, found_colon] =
13625
12.2k
        helpers::get_host_delimiter_location(is_special(), host_view);
13626
13627
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13628
    // Note: the 'found_colon' value is true if and only if a colon was
13629
    // encountered while not inside brackets.
13630
12.2k
    if (found_colon) {
13631
400
      if (override_hostname) {
13632
200
        return false;
13633
200
      }
13634
200
      std::string_view sub_buffer = new_host.substr(location + 1);
13635
200
      if (!sub_buffer.empty()) {
13636
177
        set_port(sub_buffer);
13637
177
      }
13638
200
    }
13639
    // If url is special and host_view is the empty string, validation error,
13640
    // return failure. Otherwise, if state override is given, host_view is the
13641
    // empty string, and either url includes credentials or url’s port is
13642
    // non-null, return.
13643
11.8k
    else if (host_view.empty() &&
13644
11.8k
             (is_special() || has_credentials() ||
13645
9.43k
              components.port != url_components::omitted)) {
13646
6.64k
      return false;
13647
6.64k
    }
13648
13649
    // Let host be the result of host parsing host_view with url is not special.
13650
5.36k
    if (host_view.empty()) {
13651
2.86k
      if (has_hostname()) {
13652
307
        clear_hostname();  // easy!
13653
2.56k
      } else if (has_dash_dot()) {
13654
34
        add_authority_slashes_if_needed();
13655
34
        delete_dash_dot();
13656
34
      }
13657
2.86k
      return true;
13658
2.86k
    }
13659
13660
2.49k
    bool succeeded = parse_host(host_view);
13661
2.49k
    if (!succeeded) {
13662
669
      update_base_hostname(previous_host);
13663
669
      update_base_port(previous_port);
13664
1.82k
    } else if (has_dash_dot()) {
13665
      // Should remove dash_dot from pathname
13666
9
      delete_dash_dot();
13667
9
    }
13668
2.49k
    return succeeded;
13669
5.36k
  }
13670
13671
3.60k
  size_t location = new_host.find_first_of("/\\?");
13672
3.60k
  if (location != std::string_view::npos) {
13673
44
    new_host.remove_suffix(new_host.length() - location);
13674
44
  }
13675
13676
3.60k
  if (new_host.empty()) {
13677
    // Set url’s host to the empty string.
13678
2.69k
    clear_hostname();
13679
2.69k
  } else {
13680
    // Let host be the result of host parsing buffer with url is not special.
13681
906
    if (!parse_host(new_host)) {
13682
138
      update_base_hostname(previous_host);
13683
138
      update_base_port(previous_port);
13684
138
      return false;
13685
138
    }
13686
13687
    // If host is "localhost", then set host to the empty string.
13688
768
    if (helpers::substring(buffer, components.host_start,
13689
768
                           components.host_end) == "localhost") {
13690
40
      clear_hostname();
13691
40
    }
13692
768
  }
13693
3.46k
  ADA_ASSERT_TRUE(validate());
13694
3.46k
  return true;
13695
3.60k
}
bool ada::url_aggregator::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
13602
8.53k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
13603
8.53k
  ada_log("url_aggregator::set_host_or_hostname ", input);
13604
8.53k
  ADA_ASSERT_TRUE(validate());
13605
8.53k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13606
8.53k
  if (has_opaque_path) {
13607
1.06k
    return false;
13608
1.06k
  }
13609
13610
7.46k
  std::string previous_host = std::string(get_hostname());
13611
7.46k
  uint32_t previous_port = components.port;
13612
13613
7.46k
  size_t host_end_pos = input.find('#');
13614
7.46k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
13615
7.46k
                                      ? host_end_pos
13616
7.46k
                                      : input.size());
13617
7.46k
  helpers::remove_ascii_tab_or_newline(_host);
13618
7.46k
  std::string_view new_host(_host);
13619
13620
  // If url's scheme is "file", then set state to file host state, instead of
13621
  // host state.
13622
7.46k
  if (type != ada::scheme::type::FILE) {
13623
5.72k
    std::string_view host_view(_host.data(), _host.length());
13624
5.72k
    auto [location, found_colon] =
13625
5.72k
        helpers::get_host_delimiter_location(is_special(), host_view);
13626
13627
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13628
    // Note: the 'found_colon' value is true if and only if a colon was
13629
    // encountered while not inside brackets.
13630
5.72k
    if (found_colon) {
13631
200
      if (override_hostname) {
13632
0
        return false;
13633
0
      }
13634
200
      std::string_view sub_buffer = new_host.substr(location + 1);
13635
200
      if (!sub_buffer.empty()) {
13636
177
        set_port(sub_buffer);
13637
177
      }
13638
200
    }
13639
    // If url is special and host_view is the empty string, validation error,
13640
    // return failure. Otherwise, if state override is given, host_view is the
13641
    // empty string, and either url includes credentials or url’s port is
13642
    // non-null, return.
13643
5.52k
    else if (host_view.empty() &&
13644
5.52k
             (is_special() || has_credentials() ||
13645
4.65k
              components.port != url_components::omitted)) {
13646
3.32k
      return false;
13647
3.32k
    }
13648
13649
    // Let host be the result of host parsing host_view with url is not special.
13650
2.40k
    if (host_view.empty()) {
13651
1.41k
      if (has_hostname()) {
13652
204
        clear_hostname();  // easy!
13653
1.20k
      } else if (has_dash_dot()) {
13654
2
        add_authority_slashes_if_needed();
13655
2
        delete_dash_dot();
13656
2
      }
13657
1.41k
      return true;
13658
1.41k
    }
13659
13660
990
    bool succeeded = parse_host(host_view);
13661
990
    if (!succeeded) {
13662
363
      update_base_hostname(previous_host);
13663
363
      update_base_port(previous_port);
13664
627
    } else if (has_dash_dot()) {
13665
      // Should remove dash_dot from pathname
13666
7
      delete_dash_dot();
13667
7
    }
13668
990
    return succeeded;
13669
2.40k
  }
13670
13671
1.74k
  size_t location = new_host.find_first_of("/\\?");
13672
1.74k
  if (location != std::string_view::npos) {
13673
22
    new_host.remove_suffix(new_host.length() - location);
13674
22
  }
13675
13676
1.74k
  if (new_host.empty()) {
13677
    // Set url’s host to the empty string.
13678
1.31k
    clear_hostname();
13679
1.31k
  } else {
13680
    // Let host be the result of host parsing buffer with url is not special.
13681
429
    if (!parse_host(new_host)) {
13682
69
      update_base_hostname(previous_host);
13683
69
      update_base_port(previous_port);
13684
69
      return false;
13685
69
    }
13686
13687
    // If host is "localhost", then set host to the empty string.
13688
360
    if (helpers::substring(buffer, components.host_start,
13689
360
                           components.host_end) == "localhost") {
13690
20
      clear_hostname();
13691
20
    }
13692
360
  }
13693
1.67k
  ADA_ASSERT_TRUE(validate());
13694
1.67k
  return true;
13695
1.74k
}
bool ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
13602
9.41k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
13603
9.41k
  ada_log("url_aggregator::set_host_or_hostname ", input);
13604
9.41k
  ADA_ASSERT_TRUE(validate());
13605
9.41k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13606
9.41k
  if (has_opaque_path) {
13607
1.06k
    return false;
13608
1.06k
  }
13609
13610
8.35k
  std::string previous_host = std::string(get_hostname());
13611
8.35k
  uint32_t previous_port = components.port;
13612
13613
8.35k
  size_t host_end_pos = input.find('#');
13614
8.35k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
13615
8.35k
                                      ? host_end_pos
13616
8.35k
                                      : input.size());
13617
8.35k
  helpers::remove_ascii_tab_or_newline(_host);
13618
8.35k
  std::string_view new_host(_host);
13619
13620
  // If url's scheme is "file", then set state to file host state, instead of
13621
  // host state.
13622
8.35k
  if (type != ada::scheme::type::FILE) {
13623
6.48k
    std::string_view host_view(_host.data(), _host.length());
13624
6.48k
    auto [location, found_colon] =
13625
6.48k
        helpers::get_host_delimiter_location(is_special(), host_view);
13626
13627
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13628
    // Note: the 'found_colon' value is true if and only if a colon was
13629
    // encountered while not inside brackets.
13630
6.48k
    if (found_colon) {
13631
200
      if (override_hostname) {
13632
200
        return false;
13633
200
      }
13634
0
      std::string_view sub_buffer = new_host.substr(location + 1);
13635
0
      if (!sub_buffer.empty()) {
13636
0
        set_port(sub_buffer);
13637
0
      }
13638
0
    }
13639
    // If url is special and host_view is the empty string, validation error,
13640
    // return failure. Otherwise, if state override is given, host_view is the
13641
    // empty string, and either url includes credentials or url’s port is
13642
    // non-null, return.
13643
6.28k
    else if (host_view.empty() &&
13644
6.28k
             (is_special() || has_credentials() ||
13645
4.78k
              components.port != url_components::omitted)) {
13646
3.32k
      return false;
13647
3.32k
    }
13648
13649
    // Let host be the result of host parsing host_view with url is not special.
13650
2.96k
    if (host_view.empty()) {
13651
1.45k
      if (has_hostname()) {
13652
103
        clear_hostname();  // easy!
13653
1.35k
      } else if (has_dash_dot()) {
13654
32
        add_authority_slashes_if_needed();
13655
32
        delete_dash_dot();
13656
32
      }
13657
1.45k
      return true;
13658
1.45k
    }
13659
13660
1.50k
    bool succeeded = parse_host(host_view);
13661
1.50k
    if (!succeeded) {
13662
306
      update_base_hostname(previous_host);
13663
306
      update_base_port(previous_port);
13664
1.19k
    } else if (has_dash_dot()) {
13665
      // Should remove dash_dot from pathname
13666
2
      delete_dash_dot();
13667
2
    }
13668
1.50k
    return succeeded;
13669
2.96k
  }
13670
13671
1.86k
  size_t location = new_host.find_first_of("/\\?");
13672
1.86k
  if (location != std::string_view::npos) {
13673
22
    new_host.remove_suffix(new_host.length() - location);
13674
22
  }
13675
13676
1.86k
  if (new_host.empty()) {
13677
    // Set url’s host to the empty string.
13678
1.38k
    clear_hostname();
13679
1.38k
  } else {
13680
    // Let host be the result of host parsing buffer with url is not special.
13681
477
    if (!parse_host(new_host)) {
13682
69
      update_base_hostname(previous_host);
13683
69
      update_base_port(previous_port);
13684
69
      return false;
13685
69
    }
13686
13687
    // If host is "localhost", then set host to the empty string.
13688
408
    if (helpers::substring(buffer, components.host_start,
13689
408
                           components.host_end) == "localhost") {
13690
20
      clear_hostname();
13691
20
    }
13692
408
  }
13693
1.79k
  ADA_ASSERT_TRUE(validate());
13694
1.79k
  return true;
13695
1.86k
}
13696
13697
8.53k
bool url_aggregator::set_host(const std::string_view input) {
13698
8.53k
  ada_log("url_aggregator::set_host '", input, "'");
13699
8.53k
  ADA_ASSERT_TRUE(validate());
13700
8.53k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13701
8.53k
  return set_host_or_hostname<false>(input);
13702
8.53k
}
13703
13704
9.41k
bool url_aggregator::set_hostname(const std::string_view input) {
13705
9.41k
  ada_log("url_aggregator::set_hostname '", input, "'");
13706
9.41k
  ADA_ASSERT_TRUE(validate());
13707
9.41k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13708
9.41k
  return set_host_or_hostname<true>(input);
13709
9.41k
}
13710
13711
8.27k
[[nodiscard]] std::string url_aggregator::get_origin() const noexcept {
13712
8.27k
  ada_log("url_aggregator::get_origin");
13713
8.27k
  if (is_special()) {
13714
    // Return a new opaque origin.
13715
5.52k
    if (type == scheme::FILE) {
13716
1.48k
      return "null";
13717
1.48k
    }
13718
13719
4.04k
    return helpers::concat(get_protocol(), "//", get_host());
13720
5.52k
  }
13721
13722
2.74k
  if (get_protocol() == "blob:") {
13723
395
    std::string_view path = get_pathname();
13724
395
    if (!path.empty()) {
13725
393
      auto out = ada::parse<ada::url_aggregator>(path);
13726
393
      if (out && (out->type == scheme::HTTP || out->type == scheme::HTTPS)) {
13727
        // If pathURL’s scheme is not "http" and not "https", then return a
13728
        // new opaque origin.
13729
10
        return helpers::concat(out->get_protocol(), "//", out->get_host());
13730
10
      }
13731
393
    }
13732
395
  }
13733
13734
  // Return a new opaque origin.
13735
2.73k
  return "null";
13736
2.74k
}
13737
13738
8.27k
[[nodiscard]] std::string_view url_aggregator::get_username() const noexcept {
13739
8.27k
  ada_log("url_aggregator::get_username");
13740
8.27k
  if (has_non_empty_username()) {
13741
902
    return helpers::substring(buffer, components.protocol_end + 2,
13742
902
                              components.username_end);
13743
902
  }
13744
7.37k
  return "";
13745
8.27k
}
13746
13747
8.27k
[[nodiscard]] std::string_view url_aggregator::get_password() const noexcept {
13748
8.27k
  ada_log("url_aggregator::get_password");
13749
8.27k
  if (has_non_empty_password()) {
13750
902
    return helpers::substring(buffer, components.username_end + 1,
13751
902
                              components.host_start);
13752
902
  }
13753
7.37k
  return "";
13754
8.27k
}
13755
13756
8.27k
[[nodiscard]] std::string_view url_aggregator::get_port() const noexcept {
13757
8.27k
  ada_log("url_aggregator::get_port");
13758
8.27k
  if (components.port == url_components::omitted) {
13759
8.03k
    return "";
13760
8.03k
  }
13761
241
  return helpers::substring(buffer, components.host_end + 1,
13762
241
                            components.pathname_start);
13763
8.27k
}
13764
13765
8.27k
[[nodiscard]] std::string_view url_aggregator::get_hash() const noexcept {
13766
8.27k
  ada_log("url_aggregator::get_hash");
13767
  // If this’s URL’s fragment is either null or the empty string, then return
13768
  // the empty string. Return U+0023 (#), followed by this’s URL’s fragment.
13769
8.27k
  if (components.hash_start == url_components::omitted) {
13770
6.67k
    return "";
13771
6.67k
  }
13772
1.60k
  if (buffer.size() - components.hash_start <= 1) {
13773
78
    return "";
13774
78
  }
13775
1.52k
  return helpers::substring(buffer, components.hash_start);
13776
1.60k
}
13777
13778
12.5k
[[nodiscard]] std::string_view url_aggregator::get_host() const noexcept {
13779
12.5k
  ada_log("url_aggregator::get_host");
13780
  // Technically, we should check if there is a hostname, but
13781
  // the code below works even if there isn't.
13782
  // if(!has_hostname()) { return ""; }
13783
12.5k
  size_t start = components.host_start;
13784
12.5k
  if (components.host_end > components.host_start &&
13785
12.5k
      buffer[components.host_start] == '@') {
13786
1.70k
    start++;
13787
1.70k
  }
13788
  // if we have an empty host, then the space between components.host_end and
13789
  // components.pathname_start may be occupied by /.
13790
12.5k
  if (start == components.host_end) {
13791
4.04k
    return std::string_view();
13792
4.04k
  }
13793
8.53k
  return helpers::substring(buffer, start, components.pathname_start);
13794
12.5k
}
13795
13796
45.1k
[[nodiscard]] std::string_view url_aggregator::get_hostname() const noexcept {
13797
45.1k
  ada_log("url_aggregator::get_hostname");
13798
  // Technically, we should check if there is a hostname, but
13799
  // the code below works even if there isn't.
13800
  // if(!has_hostname()) { return ""; }
13801
45.1k
  size_t start = components.host_start;
13802
  // So host_start is not where the host begins.
13803
45.1k
  if (components.host_end > components.host_start &&
13804
45.1k
      buffer[components.host_start] == '@') {
13805
4.54k
    start++;
13806
4.54k
  }
13807
45.1k
  return helpers::substring(buffer, start, components.host_end);
13808
45.1k
}
13809
13810
15.8k
[[nodiscard]] std::string_view url_aggregator::get_pathname() const noexcept {
13811
15.8k
  ada_log("url_aggregator::get_pathname pathname_start = ",
13812
15.8k
          components.pathname_start, " buffer.size() = ", buffer.size(),
13813
15.8k
          " components.search_start = ", components.search_start,
13814
15.8k
          " components.hash_start = ", components.hash_start);
13815
15.8k
  uint32_t ending_index = uint32_t(buffer.size());
13816
15.8k
  if (components.search_start != url_components::omitted) {
13817
1.80k
    ending_index = components.search_start;
13818
14.0k
  } else if (components.hash_start != url_components::omitted) {
13819
152
    ending_index = components.hash_start;
13820
152
  }
13821
15.8k
  return helpers::substring(buffer, components.pathname_start, ending_index);
13822
15.8k
}
13823
13824
9.41k
[[nodiscard]] std::string_view url_aggregator::get_search() const noexcept {
13825
9.41k
  ada_log("url_aggregator::get_search");
13826
  // If this’s URL’s query is either null or the empty string, then return the
13827
  // empty string. Return U+003F (?), followed by this’s URL’s query.
13828
9.41k
  if (components.search_start == url_components::omitted) {
13829
7.73k
    return "";
13830
7.73k
  }
13831
1.67k
  uint32_t ending_index = uint32_t(buffer.size());
13832
1.67k
  if (components.hash_start != url_components::omitted) {
13833
1.62k
    ending_index = components.hash_start;
13834
1.62k
  }
13835
1.67k
  if (ending_index - components.search_start <= 1) {
13836
111
    return "";
13837
111
  }
13838
1.56k
  return helpers::substring(buffer, components.search_start, ending_index);
13839
1.67k
}
13840
13841
15.8k
[[nodiscard]] std::string_view url_aggregator::get_protocol() const noexcept {
13842
15.8k
  ada_log("url_aggregator::get_protocol");
13843
15.8k
  return helpers::substring(buffer, 0, components.protocol_end);
13844
15.8k
}
13845
13846
0
std::string ada::url_aggregator::to_string() const {
13847
0
  ada_log("url_aggregator::to_string buffer:", buffer, "[", buffer.size(),
13848
0
          " bytes]");
13849
0
  if (!is_valid) {
13850
0
    return "null";
13851
0
  }
13852
13853
0
  std::string answer;
13854
0
  auto back = std::back_insert_iterator(answer);
13855
0
  answer.append("{\n");
13856
13857
0
  answer.append("\t\"buffer\":\"");
13858
0
  helpers::encode_json(buffer, back);
13859
0
  answer.append("\",\n");
13860
13861
0
  answer.append("\t\"protocol\":\"");
13862
0
  helpers::encode_json(get_protocol(), back);
13863
0
  answer.append("\",\n");
13864
13865
0
  if (has_credentials()) {
13866
0
    answer.append("\t\"username\":\"");
13867
0
    helpers::encode_json(get_username(), back);
13868
0
    answer.append("\",\n");
13869
0
    answer.append("\t\"password\":\"");
13870
0
    helpers::encode_json(get_password(), back);
13871
0
    answer.append("\",\n");
13872
0
  }
13873
13874
0
  answer.append("\t\"host\":\"");
13875
0
  helpers::encode_json(get_host(), back);
13876
0
  answer.append("\",\n");
13877
13878
0
  answer.append("\t\"path\":\"");
13879
0
  helpers::encode_json(get_pathname(), back);
13880
0
  answer.append("\",\n");
13881
0
  answer.append("\t\"opaque path\":");
13882
0
  answer.append((has_opaque_path ? "true" : "false"));
13883
0
  answer.append(",\n");
13884
13885
0
  if (components.search_start != url_components::omitted) {
13886
0
    answer.append("\t\"query\":\"");
13887
0
    helpers::encode_json(get_search(), back);
13888
0
    answer.append("\",\n");
13889
0
  }
13890
0
  if (components.hash_start != url_components::omitted) {
13891
0
    answer.append("\t\"fragment\":\"");
13892
0
    helpers::encode_json(get_hash(), back);
13893
0
    answer.append("\",\n");
13894
0
  }
13895
13896
0
  auto convert_offset_to_string = [](uint32_t offset) -> std::string {
13897
0
    if (offset == url_components::omitted) {
13898
0
      return "null";
13899
0
    } else {
13900
0
      return std::to_string(offset);
13901
0
    }
13902
0
  };
13903
13904
0
  answer.append("\t\"protocol_end\":");
13905
0
  answer.append(convert_offset_to_string(components.protocol_end));
13906
0
  answer.append(",\n");
13907
13908
0
  answer.append("\t\"username_end\":");
13909
0
  answer.append(convert_offset_to_string(components.username_end));
13910
0
  answer.append(",\n");
13911
13912
0
  answer.append("\t\"host_start\":");
13913
0
  answer.append(convert_offset_to_string(components.host_start));
13914
0
  answer.append(",\n");
13915
13916
0
  answer.append("\t\"host_end\":");
13917
0
  answer.append(convert_offset_to_string(components.host_end));
13918
0
  answer.append(",\n");
13919
13920
0
  answer.append("\t\"port\":");
13921
0
  answer.append(convert_offset_to_string(components.port));
13922
0
  answer.append(",\n");
13923
13924
0
  answer.append("\t\"pathname_start\":");
13925
0
  answer.append(convert_offset_to_string(components.pathname_start));
13926
0
  answer.append(",\n");
13927
13928
0
  answer.append("\t\"search_start\":");
13929
0
  answer.append(convert_offset_to_string(components.search_start));
13930
0
  answer.append(",\n");
13931
13932
0
  answer.append("\t\"hash_start\":");
13933
0
  answer.append(convert_offset_to_string(components.hash_start));
13934
0
  answer.append("\n}");
13935
13936
0
  return answer;
13937
0
}
13938
13939
0
[[nodiscard]] bool url_aggregator::has_valid_domain() const noexcept {
13940
0
  if (components.host_start == components.host_end) {
13941
0
    return false;
13942
0
  }
13943
0
  return checkers::verify_dns_length(get_hostname());
13944
0
}
13945
13946
4.02k
bool url_aggregator::parse_ipv4(std::string_view input) {
13947
4.02k
  ada_log("parse_ipv4 ", input, "[", input.size(),
13948
4.02k
          " bytes], overlaps with buffer: ",
13949
4.02k
          helpers::overlaps(input, buffer) ? "yes" : "no");
13950
4.02k
  ADA_ASSERT_TRUE(validate());
13951
4.02k
  const bool trailing_dot = (input.back() == '.');
13952
4.02k
  if (trailing_dot) {
13953
65
    input.remove_suffix(1);
13954
65
  }
13955
4.02k
  size_t digit_count{0};
13956
4.02k
  int pure_decimal_count = 0;  // entries that are decimal
13957
4.02k
  uint64_t ipv4{0};
13958
  // we could unroll for better performance?
13959
5.29k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
13960
5.26k
    uint32_t
13961
5.26k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
13962
5.26k
    bool is_hex = checkers::has_hex_prefix(input);
13963
5.26k
    if (is_hex && ((input.length() == 2) ||
13964
1.20k
                   ((input.length() > 2) && (input[2] == '.')))) {
13965
      // special case
13966
124
      segment_result = 0;
13967
124
      input.remove_prefix(2);
13968
5.13k
    } else {
13969
5.13k
      std::from_chars_result r;
13970
5.13k
      if (is_hex) {
13971
1.07k
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
13972
1.07k
                            segment_result, 16);
13973
4.05k
      } else if ((input.length() >= 2) && input[0] == '0' &&
13974
4.05k
                 checkers::is_digit(input[1])) {
13975
504
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
13976
504
                            segment_result, 8);
13977
3.55k
      } else {
13978
3.55k
        pure_decimal_count++;
13979
3.55k
        r = std::from_chars(input.data(), input.data() + input.size(),
13980
3.55k
                            segment_result, 10);
13981
3.55k
      }
13982
5.13k
      if (r.ec != std::errc()) {
13983
677
        return is_valid = false;
13984
677
      }
13985
4.45k
      input.remove_prefix(r.ptr - input.data());
13986
4.45k
    }
13987
4.58k
    if (input.empty()) {
13988
      // We have the last value.
13989
      // At this stage, ipv4 contains digit_count*8 bits.
13990
      // So we have 32-digit_count*8 bits left.
13991
3.10k
      if (segment_result > (uint64_t(1) << (32 - digit_count * 8))) {
13992
18
        return is_valid = false;
13993
18
      }
13994
3.08k
      ipv4 <<= (32 - digit_count * 8);
13995
3.08k
      ipv4 |= segment_result;
13996
3.08k
      goto final;
13997
3.10k
    } else {
13998
      // There is more, so that the value must no be larger than 255
13999
      // and we must have a '.'.
14000
1.48k
      if ((segment_result > 255) || (input[0] != '.')) {
14001
216
        return is_valid = false;
14002
216
      }
14003
1.26k
      ipv4 <<= 8;
14004
1.26k
      ipv4 |= segment_result;
14005
1.26k
      input.remove_prefix(1);  // remove '.'
14006
1.26k
    }
14007
4.58k
  }
14008
32
  if ((digit_count != 4) || (!input.empty())) {
14009
32
    return is_valid = false;
14010
32
  }
14011
3.08k
final:
14012
3.08k
  ada_log("url_aggregator::parse_ipv4 completed ", get_href(),
14013
3.08k
          " host: ", get_host());
14014
14015
  // We could also check r.ptr to see where the parsing ended.
14016
3.08k
  if (pure_decimal_count == 4 && !trailing_dot) {
14017
    // The original input was already all decimal and we validated it. So we
14018
    // don't need to do anything.
14019
2.85k
  } else {
14020
    // Optimization opportunity: Get rid of unnecessary string return in ipv4
14021
    // serializer.
14022
    // TODO: This is likely a bug because it goes back update_base_hostname, not
14023
    // what we want to do.
14024
2.85k
    update_base_hostname(
14025
2.85k
        ada::serializers::ipv4(ipv4));  // We have to reserialize the address.
14026
2.85k
  }
14027
3.08k
  ADA_ASSERT_TRUE(validate());
14028
3.08k
  return true;
14029
32
}
14030
14031
922
bool url_aggregator::parse_ipv6(std::string_view input) {
14032
  // TODO: Find a way to merge parse_ipv6 with url.cpp implementation.
14033
922
  ada_log("parse_ipv6 ", input, "[", input.size(), " bytes]");
14034
922
  ADA_ASSERT_TRUE(validate());
14035
922
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14036
922
  if (input.empty()) {
14037
61
    return is_valid = false;
14038
61
  }
14039
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
14040
861
  std::array<uint16_t, 8> address{};
14041
14042
  // Let pieceIndex be 0.
14043
861
  int piece_index = 0;
14044
14045
  // Let compress be null.
14046
861
  std::optional<int> compress{};
14047
14048
  // Let pointer be a pointer for input.
14049
861
  std::string_view::iterator pointer = input.begin();
14050
14051
  // If c is U+003A (:), then:
14052
861
  if (input[0] == ':') {
14053
    // If remaining does not start with U+003A (:), validation error, return
14054
    // failure.
14055
241
    if (input.size() == 1 || input[1] != ':') {
14056
16
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
14057
16
      return is_valid = false;
14058
16
    }
14059
14060
    // Increase pointer by 2.
14061
225
    pointer += 2;
14062
14063
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
14064
225
    compress = ++piece_index;
14065
225
  }
14066
14067
  // While c is not the EOF code point:
14068
2.53k
  while (pointer != input.end()) {
14069
    // If pieceIndex is 8, validation error, return failure.
14070
2.06k
    if (piece_index == 8) {
14071
10
      ada_log("parse_ipv6 piece_index == 8");
14072
10
      return is_valid = false;
14073
10
    }
14074
14075
    // If c is U+003A (:), then:
14076
2.05k
    if (*pointer == ':') {
14077
      // If compress is non-null, validation error, return failure.
14078
167
      if (compress.has_value()) {
14079
7
        ada_log("parse_ipv6 compress is non-null");
14080
7
        return is_valid = false;
14081
7
      }
14082
14083
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
14084
      // then continue.
14085
160
      pointer++;
14086
160
      compress = ++piece_index;
14087
160
      continue;
14088
167
    }
14089
14090
    // Let value and length be 0.
14091
1.88k
    uint16_t value = 0, length = 0;
14092
14093
    // While length is less than 4 and c is an ASCII hex digit,
14094
    // set value to value × 0x10 + c interpreted as hexadecimal number, and
14095
    // increase pointer and length by 1.
14096
5.00k
    while (length < 4 && pointer != input.end() &&
14097
5.00k
           unicode::is_ascii_hex_digit(*pointer)) {
14098
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
14099
3.12k
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
14100
3.12k
      pointer++;
14101
3.12k
      length++;
14102
3.12k
    }
14103
14104
    // If c is U+002E (.), then:
14105
1.88k
    if (pointer != input.end() && *pointer == '.') {
14106
      // If length is 0, validation error, return failure.
14107
184
      if (length == 0) {
14108
6
        ada_log("parse_ipv6 length is 0");
14109
6
        return is_valid = false;
14110
6
      }
14111
14112
      // Decrease pointer by length.
14113
178
      pointer -= length;
14114
14115
      // If pieceIndex is greater than 6, validation error, return failure.
14116
178
      if (piece_index > 6) {
14117
6
        ada_log("parse_ipv6 piece_index > 6");
14118
6
        return is_valid = false;
14119
6
      }
14120
14121
      // Let numbersSeen be 0.
14122
172
      int numbers_seen = 0;
14123
14124
      // While c is not the EOF code point:
14125
525
      while (pointer != input.end()) {
14126
        // Let ipv4Piece be null.
14127
463
        std::optional<uint16_t> ipv4_piece{};
14128
14129
        // If numbersSeen is greater than 0, then:
14130
463
        if (numbers_seen > 0) {
14131
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
14132
          // pointer by 1.
14133
291
          if (*pointer == '.' && numbers_seen < 4) {
14134
255
            pointer++;
14135
255
          } else {
14136
            // Otherwise, validation error, return failure.
14137
36
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
14138
36
            return is_valid = false;
14139
36
          }
14140
291
        }
14141
14142
        // If c is not an ASCII digit, validation error, return failure.
14143
427
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
14144
47
          ada_log(
14145
47
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
14146
47
              "failure");
14147
47
          return is_valid = false;
14148
47
        }
14149
14150
        // While c is an ASCII digit:
14151
884
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
14152
          // Let number be c interpreted as decimal number.
14153
531
          int number = *pointer - '0';
14154
14155
          // If ipv4Piece is null, then set ipv4Piece to number.
14156
531
          if (!ipv4_piece.has_value()) {
14157
380
            ipv4_piece = number;
14158
380
          }
14159
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
14160
151
          else if (ipv4_piece == 0) {
14161
6
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
14162
6
            return is_valid = false;
14163
6
          }
14164
          // Otherwise, set ipv4Piece to ipv4Piece × 10 + number.
14165
145
          else {
14166
145
            ipv4_piece = *ipv4_piece * 10 + number;
14167
145
          }
14168
14169
          // If ipv4Piece is greater than 255, validation error, return failure.
14170
525
          if (ipv4_piece > 255) {
14171
21
            ada_log("parse_ipv6 ipv4_piece > 255");
14172
21
            return is_valid = false;
14173
21
          }
14174
14175
          // Increase pointer by 1.
14176
504
          pointer++;
14177
504
        }
14178
14179
        // Set address[pieceIndex] to address[pieceIndex] × 0x100 + ipv4Piece.
14180
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
14181
353
        address[piece_index] =
14182
353
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
14183
14184
        // Increase numbersSeen by 1.
14185
353
        numbers_seen++;
14186
14187
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
14188
353
        if (numbers_seen == 2 || numbers_seen == 4) {
14189
150
          piece_index++;
14190
150
        }
14191
353
      }
14192
14193
      // If numbersSeen is not 4, validation error, return failure.
14194
62
      if (numbers_seen != 4) {
14195
16
        return is_valid = false;
14196
16
      }
14197
14198
      // Break.
14199
46
      break;
14200
62
    }
14201
    // Otherwise, if c is U+003A (:):
14202
1.70k
    else if ((pointer != input.end()) && (*pointer == ':')) {
14203
      // Increase pointer by 1.
14204
1.20k
      pointer++;
14205
14206
      // If c is the EOF code point, validation error, return failure.
14207
1.20k
      if (pointer == input.end()) {
14208
6
        ada_log(
14209
6
            "parse_ipv6 If c is the EOF code point, validation error, return "
14210
6
            "failure");
14211
6
        return is_valid = false;
14212
6
      }
14213
1.20k
    }
14214
    // Otherwise, if c is not the EOF code point, validation error, return
14215
    // failure.
14216
501
    else if (pointer != input.end()) {
14217
162
      ada_log(
14218
162
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
14219
162
          "error, return failure");
14220
162
      return is_valid = false;
14221
162
    }
14222
14223
    // Set address[pieceIndex] to value.
14224
1.53k
    address[piece_index] = value;
14225
14226
    // Increase pieceIndex by 1.
14227
1.53k
    piece_index++;
14228
1.53k
  }
14229
14230
  // If compress is non-null, then:
14231
522
  if (compress.has_value()) {
14232
    // Let swaps be pieceIndex − compress.
14233
366
    int swaps = piece_index - *compress;
14234
14235
    // Set pieceIndex to 7.
14236
366
    piece_index = 7;
14237
14238
    // While pieceIndex is not 0 and swaps is greater than 0,
14239
    // swap address[pieceIndex] with address[compress + swaps − 1], and then
14240
    // decrease both pieceIndex and swaps by 1.
14241
921
    while (piece_index != 0 && swaps > 0) {
14242
555
      std::swap(address[piece_index], address[*compress + swaps - 1]);
14243
555
      piece_index--;
14244
555
      swaps--;
14245
555
    }
14246
366
  }
14247
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
14248
  // return failure.
14249
156
  else if (piece_index != 8) {
14250
110
    ada_log(
14251
110
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
14252
110
        "error, return failure");
14253
110
    return is_valid = false;
14254
110
  }
14255
  // TODO: Optimization opportunity: Get rid of unnecessary string creation.
14256
  // TODO: This is likely a bug because it goes back update_base_hostname, not
14257
  // what we want to do.
14258
412
  update_base_hostname(ada::serializers::ipv6(address));
14259
412
  ada_log("parse_ipv6 ", get_hostname());
14260
412
  ADA_ASSERT_TRUE(validate());
14261
412
  return true;
14262
522
}
14263
14264
1.00k
bool url_aggregator::parse_opaque_host(std::string_view input) {
14265
1.00k
  ada_log("parse_opaque_host ", input, "[", input.size(), " bytes]");
14266
1.00k
  ADA_ASSERT_TRUE(validate());
14267
1.00k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14268
1.00k
  if (std::any_of(input.begin(), input.end(),
14269
1.00k
                  ada::unicode::is_forbidden_host_code_point)) {
14270
103
    return is_valid = false;
14271
103
  }
14272
14273
  // Return the result of running UTF-8 percent-encode on input using the C0
14274
  // control percent-encode set.
14275
902
  size_t idx = ada::unicode::percent_encode_index(
14276
902
      input, character_sets::C0_CONTROL_PERCENT_ENCODE);
14277
902
  if (idx == input.size()) {
14278
458
    update_base_hostname(input);
14279
458
  } else {
14280
    // We only create a temporary string if we need to.
14281
444
    update_base_hostname(ada::unicode::percent_encode(
14282
444
        input, character_sets::C0_CONTROL_PERCENT_ENCODE, idx));
14283
444
  }
14284
902
  ADA_ASSERT_TRUE(validate());
14285
902
  return true;
14286
1.00k
}
14287
14288
0
std::string url_aggregator::to_diagram() const {
14289
0
  if (!is_valid) {
14290
0
    return "invalid";
14291
0
  }
14292
0
  std::string answer;
14293
0
  answer.append(buffer);
14294
0
  answer.append(" [");
14295
0
  answer.append(std::to_string(buffer.size()));
14296
0
  answer.append(" bytes]");
14297
0
  answer.append("\n");
14298
  // first line
14299
0
  std::string line1;
14300
0
  line1.resize(buffer.size(), ' ');
14301
0
  if (components.hash_start != url_components::omitted) {
14302
0
    line1[components.hash_start] = '|';
14303
0
  }
14304
0
  if (components.search_start != url_components::omitted) {
14305
0
    line1[components.search_start] = '|';
14306
0
  }
14307
0
  if (components.pathname_start != buffer.size()) {
14308
0
    line1[components.pathname_start] = '|';
14309
0
  }
14310
0
  if (components.host_end != buffer.size()) {
14311
0
    line1[components.host_end] = '|';
14312
0
  }
14313
0
  if (components.host_start != buffer.size()) {
14314
0
    line1[components.host_start] = '|';
14315
0
  }
14316
0
  if (components.username_end != buffer.size()) {
14317
0
    line1[components.username_end] = '|';
14318
0
  }
14319
0
  if (components.protocol_end != buffer.size()) {
14320
0
    line1[components.protocol_end] = '|';
14321
0
  }
14322
0
  answer.append(line1);
14323
0
  answer.append("\n");
14324
14325
0
  std::string line2 = line1;
14326
0
  if (components.hash_start != url_components::omitted) {
14327
0
    line2[components.hash_start] = '`';
14328
0
    line1[components.hash_start] = ' ';
14329
14330
0
    for (size_t i = components.hash_start + 1; i < line2.size(); i++) {
14331
0
      line2[i] = '-';
14332
0
    }
14333
0
    line2.append(" hash_start");
14334
0
    answer.append(line2);
14335
0
    answer.append("\n");
14336
0
  }
14337
14338
0
  std::string line3 = line1;
14339
0
  if (components.search_start != url_components::omitted) {
14340
0
    line3[components.search_start] = '`';
14341
0
    line1[components.search_start] = ' ';
14342
14343
0
    for (size_t i = components.search_start + 1; i < line3.size(); i++) {
14344
0
      line3[i] = '-';
14345
0
    }
14346
0
    line3.append(" search_start ");
14347
0
    line3.append(std::to_string(components.search_start));
14348
0
    answer.append(line3);
14349
0
    answer.append("\n");
14350
0
  }
14351
14352
0
  std::string line4 = line1;
14353
0
  if (components.pathname_start != buffer.size()) {
14354
0
    line4[components.pathname_start] = '`';
14355
0
    line1[components.pathname_start] = ' ';
14356
0
    for (size_t i = components.pathname_start + 1; i < line4.size(); i++) {
14357
0
      line4[i] = '-';
14358
0
    }
14359
0
    line4.append(" pathname_start ");
14360
0
    line4.append(std::to_string(components.pathname_start));
14361
0
    answer.append(line4);
14362
0
    answer.append("\n");
14363
0
  }
14364
14365
0
  std::string line5 = line1;
14366
0
  if (components.host_end != buffer.size()) {
14367
0
    line5[components.host_end] = '`';
14368
0
    line1[components.host_end] = ' ';
14369
14370
0
    for (size_t i = components.host_end + 1; i < line5.size(); i++) {
14371
0
      line5[i] = '-';
14372
0
    }
14373
0
    line5.append(" host_end ");
14374
0
    line5.append(std::to_string(components.host_end));
14375
0
    answer.append(line5);
14376
0
    answer.append("\n");
14377
0
  }
14378
14379
0
  std::string line6 = line1;
14380
0
  if (components.host_start != buffer.size()) {
14381
0
    line6[components.host_start] = '`';
14382
0
    line1[components.host_start] = ' ';
14383
14384
0
    for (size_t i = components.host_start + 1; i < line6.size(); i++) {
14385
0
      line6[i] = '-';
14386
0
    }
14387
0
    line6.append(" host_start ");
14388
0
    line6.append(std::to_string(components.host_start));
14389
0
    answer.append(line6);
14390
0
    answer.append("\n");
14391
0
  }
14392
14393
0
  std::string line7 = line1;
14394
0
  if (components.username_end != buffer.size()) {
14395
0
    line7[components.username_end] = '`';
14396
0
    line1[components.username_end] = ' ';
14397
14398
0
    for (size_t i = components.username_end + 1; i < line7.size(); i++) {
14399
0
      line7[i] = '-';
14400
0
    }
14401
0
    line7.append(" username_end ");
14402
0
    line7.append(std::to_string(components.username_end));
14403
0
    answer.append(line7);
14404
0
    answer.append("\n");
14405
0
  }
14406
14407
0
  std::string line8 = line1;
14408
0
  if (components.protocol_end != buffer.size()) {
14409
0
    line8[components.protocol_end] = '`';
14410
0
    line1[components.protocol_end] = ' ';
14411
14412
0
    for (size_t i = components.protocol_end + 1; i < line8.size(); i++) {
14413
0
      line8[i] = '-';
14414
0
    }
14415
0
    line8.append(" protocol_end ");
14416
0
    line8.append(std::to_string(components.protocol_end));
14417
0
    answer.append(line8);
14418
0
    answer.append("\n");
14419
0
  }
14420
14421
0
  if (components.hash_start == url_components::omitted) {
14422
0
    answer.append("note: hash omitted\n");
14423
0
  }
14424
0
  if (components.search_start == url_components::omitted) {
14425
0
    answer.append("note: search omitted\n");
14426
0
  }
14427
0
  if (components.protocol_end > buffer.size()) {
14428
0
    answer.append("warning: protocol_end overflows\n");
14429
0
  }
14430
0
  if (components.username_end > buffer.size()) {
14431
0
    answer.append("warning: username_end overflows\n");
14432
0
  }
14433
0
  if (components.host_start > buffer.size()) {
14434
0
    answer.append("warning: host_start overflows\n");
14435
0
  }
14436
0
  if (components.host_end > buffer.size()) {
14437
0
    answer.append("warning: host_end overflows\n");
14438
0
  }
14439
0
  if (components.pathname_start > buffer.size()) {
14440
0
    answer.append("warning: pathname_start overflows\n");
14441
0
  }
14442
0
  return answer;
14443
0
}
14444
14445
0
bool url_aggregator::validate() const noexcept {
14446
0
  if (!is_valid) {
14447
0
    return true;
14448
0
  }
14449
0
  if (!components.check_offset_consistency()) {
14450
0
    ada_log("url_aggregator::validate inconsistent components \n",
14451
0
            to_diagram());
14452
0
    return false;
14453
0
  }
14454
  // We have a credible components struct, but let us investivate more
14455
  // carefully:
14456
  /**
14457
   * https://user:pass@example.com:1234/foo/bar?baz#quux
14458
   *       |     |    |          | ^^^^|       |   |
14459
   *       |     |    |          | |   |       |   `----- hash_start
14460
   *       |     |    |          | |   |       `--------- search_start
14461
   *       |     |    |          | |   `----------------- pathname_start
14462
   *       |     |    |          | `--------------------- port
14463
   *       |     |    |          `----------------------- host_end
14464
   *       |     |    `---------------------------------- host_start
14465
   *       |     `--------------------------------------- username_end
14466
   *       `--------------------------------------------- protocol_end
14467
   */
14468
0
  if (components.protocol_end == url_components::omitted) {
14469
0
    ada_log("url_aggregator::validate omitted protocol_end \n", to_diagram());
14470
0
    return false;
14471
0
  }
14472
0
  if (components.username_end == url_components::omitted) {
14473
0
    ada_log("url_aggregator::validate omitted username_end \n", to_diagram());
14474
0
    return false;
14475
0
  }
14476
0
  if (components.host_start == url_components::omitted) {
14477
0
    ada_log("url_aggregator::validate omitted host_start \n", to_diagram());
14478
0
    return false;
14479
0
  }
14480
0
  if (components.host_end == url_components::omitted) {
14481
0
    ada_log("url_aggregator::validate omitted host_end \n", to_diagram());
14482
0
    return false;
14483
0
  }
14484
0
  if (components.pathname_start == url_components::omitted) {
14485
0
    ada_log("url_aggregator::validate omitted pathname_start \n", to_diagram());
14486
0
    return false;
14487
0
  }
14488
14489
0
  if (components.protocol_end > buffer.size()) {
14490
0
    ada_log("url_aggregator::validate protocol_end overflow \n", to_diagram());
14491
0
    return false;
14492
0
  }
14493
0
  if (components.username_end > buffer.size()) {
14494
0
    ada_log("url_aggregator::validate username_end overflow \n", to_diagram());
14495
0
    return false;
14496
0
  }
14497
0
  if (components.host_start > buffer.size()) {
14498
0
    ada_log("url_aggregator::validate host_start overflow \n", to_diagram());
14499
0
    return false;
14500
0
  }
14501
0
  if (components.host_end > buffer.size()) {
14502
0
    ada_log("url_aggregator::validate host_end overflow \n", to_diagram());
14503
0
    return false;
14504
0
  }
14505
0
  if (components.pathname_start > buffer.size()) {
14506
0
    ada_log("url_aggregator::validate pathname_start overflow \n",
14507
0
            to_diagram());
14508
0
    return false;
14509
0
  }
14510
14511
0
  if (components.protocol_end > 0) {
14512
0
    if (buffer[components.protocol_end - 1] != ':') {
14513
0
      ada_log(
14514
0
          "url_aggregator::validate missing : at the end of the protocol \n",
14515
0
          to_diagram());
14516
0
      return false;
14517
0
    }
14518
0
  }
14519
14520
0
  if (components.username_end != buffer.size() &&
14521
0
      components.username_end > components.protocol_end + 2) {
14522
0
    if (buffer[components.username_end] != ':' &&
14523
0
        buffer[components.username_end] != '@') {
14524
0
      ada_log(
14525
0
          "url_aggregator::validate missing : or @ at the end of the username "
14526
0
          "\n",
14527
0
          to_diagram());
14528
0
      return false;
14529
0
    }
14530
0
  }
14531
14532
0
  if (components.host_start != buffer.size()) {
14533
0
    if (components.host_start > components.username_end) {
14534
0
      if (buffer[components.host_start] != '@') {
14535
0
        ada_log(
14536
0
            "url_aggregator::validate missing @ at the end of the password \n",
14537
0
            to_diagram());
14538
0
        return false;
14539
0
      }
14540
0
    } else if (components.host_start == components.username_end &&
14541
0
               components.host_end > components.host_start) {
14542
0
      if (components.host_start == components.protocol_end + 2) {
14543
0
        if (buffer[components.protocol_end] != '/' ||
14544
0
            buffer[components.protocol_end + 1] != '/') {
14545
0
          ada_log(
14546
0
              "url_aggregator::validate missing // between protocol and host "
14547
0
              "\n",
14548
0
              to_diagram());
14549
0
          return false;
14550
0
        }
14551
0
      } else {
14552
0
        if (components.host_start > components.protocol_end &&
14553
0
            buffer[components.host_start] != '@') {
14554
0
          ada_log(
14555
0
              "url_aggregator::validate missing @ at the end of the username "
14556
0
              "\n",
14557
0
              to_diagram());
14558
0
          return false;
14559
0
        }
14560
0
      }
14561
0
    } else {
14562
0
      if (components.host_end != components.host_start) {
14563
0
        ada_log("url_aggregator::validate expected omitted host \n",
14564
0
                to_diagram());
14565
0
        return false;
14566
0
      }
14567
0
    }
14568
0
  }
14569
0
  if (components.host_end != buffer.size() &&
14570
0
      components.pathname_start > components.host_end) {
14571
0
    if (components.pathname_start == components.host_end + 2 &&
14572
0
        buffer[components.host_end] == '/' &&
14573
0
        buffer[components.host_end + 1] == '.') {
14574
0
      if (components.pathname_start + 1 >= buffer.size() ||
14575
0
          buffer[components.pathname_start] != '/' ||
14576
0
          buffer[components.pathname_start + 1] != '/') {
14577
0
        ada_log(
14578
0
            "url_aggregator::validate expected the path to begin with // \n",
14579
0
            to_diagram());
14580
0
        return false;
14581
0
      }
14582
0
    } else if (buffer[components.host_end] != ':') {
14583
0
      ada_log("url_aggregator::validate missing : at the port \n",
14584
0
              to_diagram());
14585
0
      return false;
14586
0
    }
14587
0
  }
14588
0
  if (components.pathname_start != buffer.size() &&
14589
0
      components.pathname_start < components.search_start &&
14590
0
      components.pathname_start < components.hash_start && !has_opaque_path) {
14591
0
    if (buffer[components.pathname_start] != '/') {
14592
0
      ada_log("url_aggregator::validate missing / at the path \n",
14593
0
              to_diagram());
14594
0
      return false;
14595
0
    }
14596
0
  }
14597
0
  if (components.search_start != url_components::omitted) {
14598
0
    if (buffer[components.search_start] != '?') {
14599
0
      ada_log("url_aggregator::validate missing ? at the search \n",
14600
0
              to_diagram());
14601
0
      return false;
14602
0
    }
14603
0
  }
14604
0
  if (components.hash_start != url_components::omitted) {
14605
0
    if (buffer[components.hash_start] != '#') {
14606
0
      ada_log("url_aggregator::validate missing # at the hash \n",
14607
0
              to_diagram());
14608
0
      return false;
14609
0
    }
14610
0
  }
14611
14612
0
  return true;
14613
0
}
14614
14615
79
void url_aggregator::delete_dash_dot() {
14616
79
  ada_log("url_aggregator::delete_dash_dot");
14617
79
  ADA_ASSERT_TRUE(validate());
14618
79
  ADA_ASSERT_TRUE(has_dash_dot());
14619
79
  buffer.erase(components.host_end, 2);
14620
79
  components.pathname_start -= 2;
14621
79
  if (components.search_start != url_components::omitted) {
14622
30
    components.search_start -= 2;
14623
30
  }
14624
79
  if (components.hash_start != url_components::omitted) {
14625
37
    components.hash_start -= 2;
14626
37
  }
14627
79
  ADA_ASSERT_TRUE(validate());
14628
79
  ADA_ASSERT_TRUE(!has_dash_dot());
14629
79
}
14630
14631
8.63k
inline void url_aggregator::consume_prepared_path(std::string_view input) {
14632
8.63k
  ada_log("url_aggregator::consume_prepared_path ", input);
14633
  /***
14634
   * This is largely duplicated code from helpers::parse_prepared_path, which is
14635
   * unfortunate. This particular function is nearly identical, except that it
14636
   * is a method on url_aggregator. The idea is that the trivial path (which is
14637
   * very common) merely appends to the buffer. This is the same trivial path as
14638
   * with helpers::parse_prepared_path, except that we have the additional check
14639
   * for is_at_path(). Otherwise, we grab a copy of the current path and we
14640
   * modify it, and then insert it back into the buffer.
14641
   */
14642
8.63k
  uint8_t accumulator = checkers::path_signature(input);
14643
  // Let us first detect a trivial case.
14644
  // If it is special, we check that we have no dot, no %,  no \ and no
14645
  // character needing percent encoding. Otherwise, we check that we have no %,
14646
  // no dot, and no character needing percent encoding.
14647
8.63k
  constexpr uint8_t need_encoding = 1;
14648
8.63k
  constexpr uint8_t backslash_char = 2;
14649
8.63k
  constexpr uint8_t dot_char = 4;
14650
8.63k
  constexpr uint8_t percent_char = 8;
14651
8.63k
  bool special = type != ada::scheme::NOT_SPECIAL;
14652
8.63k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
14653
8.63k
                                      checkers::is_windows_drive_letter(input));
14654
8.63k
  bool trivial_path =
14655
8.63k
      (special ? (accumulator == 0)
14656
8.63k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
14657
3.61k
                  0)) &&
14658
8.63k
      (!may_need_slow_file_handling);
14659
8.63k
  if (accumulator == dot_char && !may_need_slow_file_handling) {
14660
    // '4' means that we have at least one dot, but nothing that requires
14661
    // percent encoding or decoding. The only part that is not trivial is
14662
    // that we may have single dots and double dots path segments.
14663
    // If we have such segments, then we either have a path that begins
14664
    // with '.' (easy to check), or we have the sequence './'.
14665
    // Note: input cannot be empty, it must at least contain one character ('.')
14666
    // Note: we know that '\' is not present.
14667
1.08k
    if (input[0] != '.') {
14668
563
      size_t slashdot = input.find("/.");
14669
563
      if (slashdot == std::string_view::npos) {  // common case
14670
150
        trivial_path = true;
14671
413
      } else {  // uncommon
14672
        // only three cases matter: /./, /.. or a final /
14673
413
        trivial_path =
14674
413
            !(slashdot + 2 == input.size() || input[slashdot + 2] == '.' ||
14675
413
              input[slashdot + 2] == '/');
14676
413
      }
14677
563
    }
14678
1.08k
  }
14679
8.63k
  if (trivial_path && is_at_path()) {
14680
5.12k
    ada_log("parse_path trivial");
14681
5.12k
    buffer += '/';
14682
5.12k
    buffer += input;
14683
5.12k
    return;
14684
5.12k
  }
14685
3.50k
  std::string path = std::string(get_pathname());
14686
  // We are going to need to look a bit at the path, but let us see if we can
14687
  // ignore percent encoding *and* backslashes *and* percent characters.
14688
  // Except for the trivial case, this is likely to capture 99% of paths out
14689
  // there.
14690
3.50k
  bool fast_path =
14691
3.50k
      (special &&
14692
3.50k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
14693
3.50k
      (type != ada::scheme::type::FILE);
14694
3.50k
  if (fast_path) {
14695
550
    ada_log("parse_prepared_path fast");
14696
    // Here we don't need to worry about \ or percent encoding.
14697
    // We also do not have a file protocol. We might have dots, however,
14698
    // but dots must as appear as '.', and they cannot be encoded because
14699
    // the symbol '%' is not present.
14700
550
    size_t previous_location = 0;  // We start at 0.
14701
4.39k
    do {
14702
4.39k
      size_t new_location = input.find('/', previous_location);
14703
      // std::string_view path_view = input;
14704
      //  We process the last segment separately:
14705
4.39k
      if (new_location == std::string_view::npos) {
14706
550
        std::string_view path_view = input.substr(previous_location);
14707
550
        if (path_view == "..") {  // The path ends with ..
14708
          // e.g., if you receive ".." with an empty path, you go to "/".
14709
73
          if (path.empty()) {
14710
27
            path = '/';
14711
27
            update_base_pathname(path);
14712
27
            return;
14713
27
          }
14714
          // Fast case where we have nothing to do:
14715
46
          if (path.back() == '/') {
14716
21
            update_base_pathname(path);
14717
21
            return;
14718
21
          }
14719
          // If you have the path "/joe/myfriend",
14720
          // then you delete 'myfriend'.
14721
25
          path.resize(path.rfind('/') + 1);
14722
25
          update_base_pathname(path);
14723
25
          return;
14724
46
        }
14725
477
        path += '/';
14726
477
        if (path_view != ".") {
14727
334
          path.append(path_view);
14728
334
        }
14729
477
        update_base_pathname(path);
14730
477
        return;
14731
3.84k
      } else {
14732
        // This is a non-final segment.
14733
3.84k
        std::string_view path_view =
14734
3.84k
            input.substr(previous_location, new_location - previous_location);
14735
3.84k
        previous_location = new_location + 1;
14736
3.84k
        if (path_view == "..") {
14737
672
          size_t last_delimiter = path.rfind('/');
14738
672
          if (last_delimiter != std::string::npos) {
14739
353
            path.erase(last_delimiter);
14740
353
          }
14741
3.17k
        } else if (path_view != ".") {
14742
2.76k
          path += '/';
14743
2.76k
          path.append(path_view);
14744
2.76k
        }
14745
3.84k
      }
14746
4.39k
    } while (true);
14747
2.95k
  } else {
14748
2.95k
    ada_log("parse_path slow");
14749
    // we have reached the general case
14750
2.95k
    bool needs_percent_encoding = (accumulator & 1);
14751
2.95k
    std::string path_buffer_tmp;
14752
20.4k
    do {
14753
20.4k
      size_t location = (special && (accumulator & 2))
14754
20.4k
                            ? input.find_first_of("/\\")
14755
20.4k
                            : input.find('/');
14756
20.4k
      std::string_view path_view = input;
14757
20.4k
      if (location != std::string_view::npos) {
14758
17.4k
        path_view.remove_suffix(path_view.size() - location);
14759
17.4k
        input.remove_prefix(location + 1);
14760
17.4k
      }
14761
      // path_buffer is either path_view or it might point at a percent encoded
14762
      // temporary string.
14763
20.4k
      std::string_view path_buffer =
14764
20.4k
          (needs_percent_encoding &&
14765
20.4k
           ada::unicode::percent_encode<false>(
14766
11.8k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
14767
20.4k
              ? path_buffer_tmp
14768
20.4k
              : path_view;
14769
20.4k
      if (unicode::is_double_dot_path_segment(path_buffer)) {
14770
4.53k
        if ((helpers::shorten_path(path, type) || special) &&
14771
4.53k
            location == std::string_view::npos) {
14772
277
          path += '/';
14773
277
        }
14774
15.8k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
14775
15.8k
                 (location == std::string_view::npos)) {
14776
124
        path += '/';
14777
124
      }
14778
      // Otherwise, if path_buffer is not a single-dot path segment, then:
14779
15.7k
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
14780
        // If url’s scheme is "file", url’s path is empty, and path_buffer is a
14781
        // Windows drive letter, then replace the second code point in
14782
        // path_buffer with U+003A (:).
14783
14.3k
        if (type == ada::scheme::type::FILE && path.empty() &&
14784
14.3k
            checkers::is_windows_drive_letter(path_buffer)) {
14785
138
          path += '/';
14786
138
          path += path_buffer[0];
14787
138
          path += ':';
14788
138
          path_buffer.remove_prefix(2);
14789
138
          path.append(path_buffer);
14790
14.2k
        } else {
14791
          // Append path_buffer to url’s path.
14792
14.2k
          path += '/';
14793
14.2k
          path.append(path_buffer);
14794
14.2k
        }
14795
14.3k
      }
14796
20.4k
      if (location == std::string_view::npos) {
14797
2.95k
        update_base_pathname(path);
14798
2.95k
        return;
14799
2.95k
      }
14800
20.4k
    } while (true);
14801
2.95k
  }
14802
3.50k
}
14803
}  // namespace ada
14804
/* end file src/url_aggregator.cpp */
14805
/* begin file src/ada_c.cpp */
14806
14807
0
ada::result<ada::url_aggregator>& get_instance(void* result) noexcept {
14808
0
  return *(ada::result<ada::url_aggregator>*)result;
14809
0
}
14810
14811
extern "C" {
14812
typedef void* ada_url;
14813
14814
struct ada_string {
14815
  const char* data;
14816
  size_t length;
14817
};
14818
14819
struct ada_owned_string {
14820
  const char* data;
14821
  size_t length;
14822
};
14823
14824
0
ada_string ada_string_create(const char* data, size_t length) {
14825
0
  ada_string out{};
14826
0
  out.data = data;
14827
0
  out.length = length;
14828
0
  return out;
14829
0
}
14830
14831
struct ada_url_components {
14832
  /*
14833
   * By using 32-bit integers, we implicitly assume that the URL string
14834
   * cannot exceed 4 GB.
14835
   *
14836
   * https://user:pass@example.com:1234/foo/bar?baz#quux
14837
   *       |     |    |          | ^^^^|       |   |
14838
   *       |     |    |          | |   |       |   `----- hash_start
14839
   *       |     |    |          | |   |       `--------- search_start
14840
   *       |     |    |          | |   `----------------- pathname_start
14841
   *       |     |    |          | `--------------------- port
14842
   *       |     |    |          `----------------------- host_end
14843
   *       |     |    `---------------------------------- host_start
14844
   *       |     `--------------------------------------- username_end
14845
   *       `--------------------------------------------- protocol_end
14846
   */
14847
  uint32_t protocol_end;
14848
  /**
14849
   * Username end is not `omitted` by default (-1) to make username and password
14850
   * getters less costly to implement.
14851
   */
14852
  uint32_t username_end;
14853
  uint32_t host_start;
14854
  uint32_t host_end;
14855
  uint32_t port;
14856
  uint32_t pathname_start;
14857
  uint32_t search_start;
14858
  uint32_t hash_start;
14859
};
14860
14861
0
ada_url ada_parse(const char* input, size_t length) noexcept {
14862
0
  return new ada::result<ada::url_aggregator>(
14863
0
      ada::parse<ada::url_aggregator>(std::string_view(input, length)));
14864
0
}
14865
14866
ada_url ada_parse_with_base(const char* input, size_t input_length,
14867
0
                            const char* base, size_t base_length) noexcept {
14868
0
  auto base_out =
14869
0
      ada::parse<ada::url_aggregator>(std::string_view(base, base_length));
14870
14871
0
  if (!base_out) {
14872
0
    return new ada::result<ada::url_aggregator>(base_out);
14873
0
  }
14874
14875
0
  return new ada::result<ada::url_aggregator>(ada::parse<ada::url_aggregator>(
14876
0
      std::string_view(input, input_length), &base_out.value()));
14877
0
}
14878
14879
0
bool ada_can_parse(const char* input, size_t length) noexcept {
14880
0
  return ada::can_parse(std::string_view(input, length));
14881
0
}
14882
14883
bool ada_can_parse_with_base(const char* input, size_t input_length,
14884
0
                             const char* base, size_t base_length) noexcept {
14885
0
  auto base_view = std::string_view(base, base_length);
14886
0
  return ada::can_parse(std::string_view(input, input_length), &base_view);
14887
0
}
14888
14889
0
void ada_free(ada_url result) noexcept {
14890
0
  ada::result<ada::url_aggregator>* r =
14891
0
      (ada::result<ada::url_aggregator>*)result;
14892
0
  delete r;
14893
0
}
14894
14895
0
bool ada_is_valid(ada_url result) noexcept {
14896
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
14897
0
  return r.has_value();
14898
0
}
14899
14900
// caller must free the result with ada_free_owned_string
14901
0
ada_owned_string ada_get_origin(ada_url result) noexcept {
14902
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
14903
0
  ada_owned_string owned;
14904
0
  if (!r) {
14905
0
    owned.data = nullptr;
14906
0
    owned.length = 0;
14907
0
    return owned;
14908
0
  }
14909
0
  std::string out = r->get_origin();
14910
0
  owned.length = out.size();
14911
0
  owned.data = new char[owned.length];
14912
0
  memcpy((void*)owned.data, out.data(), owned.length);
14913
0
  return owned;
14914
0
}
14915
14916
0
void ada_free_owned_string(ada_owned_string owned) noexcept {
14917
0
  delete[] owned.data;
14918
0
  owned.data = nullptr;
14919
0
  owned.length = 0;
14920
0
}
14921
14922
0
ada_string ada_get_href(ada_url result) noexcept {
14923
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
14924
0
  if (!r) {
14925
0
    return ada_string_create(NULL, 0);
14926
0
  }
14927
0
  std::string_view out = r->get_href();
14928
0
  return ada_string_create(out.data(), out.length());
14929
0
}
14930
14931
0
ada_string ada_get_username(ada_url result) noexcept {
14932
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
14933
0
  if (!r) {
14934
0
    return ada_string_create(NULL, 0);
14935
0
  }
14936
0
  std::string_view out = r->get_username();
14937
0
  return ada_string_create(out.data(), out.length());
14938
0
}
14939
14940
0
ada_string ada_get_password(ada_url result) noexcept {
14941
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
14942
0
  if (!r) {
14943
0
    return ada_string_create(NULL, 0);
14944
0
  }
14945
0
  std::string_view out = r->get_password();
14946
0
  return ada_string_create(out.data(), out.length());
14947
0
}
14948
14949
0
ada_string ada_get_port(ada_url result) noexcept {
14950
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
14951
0
  if (!r) {
14952
0
    return ada_string_create(NULL, 0);
14953
0
  }
14954
0
  std::string_view out = r->get_port();
14955
0
  return ada_string_create(out.data(), out.length());
14956
0
}
14957
14958
0
ada_string ada_get_hash(ada_url result) noexcept {
14959
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
14960
0
  if (!r) {
14961
0
    return ada_string_create(NULL, 0);
14962
0
  }
14963
0
  std::string_view out = r->get_hash();
14964
0
  return ada_string_create(out.data(), out.length());
14965
0
}
14966
14967
0
ada_string ada_get_host(ada_url result) noexcept {
14968
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
14969
0
  if (!r) {
14970
0
    return ada_string_create(NULL, 0);
14971
0
  }
14972
0
  std::string_view out = r->get_host();
14973
0
  return ada_string_create(out.data(), out.length());
14974
0
}
14975
14976
0
ada_string ada_get_hostname(ada_url result) noexcept {
14977
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
14978
0
  if (!r) {
14979
0
    return ada_string_create(NULL, 0);
14980
0
  }
14981
0
  std::string_view out = r->get_hostname();
14982
0
  return ada_string_create(out.data(), out.length());
14983
0
}
14984
14985
0
ada_string ada_get_pathname(ada_url result) noexcept {
14986
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
14987
0
  if (!r) {
14988
0
    return ada_string_create(NULL, 0);
14989
0
  }
14990
0
  std::string_view out = r->get_pathname();
14991
0
  return ada_string_create(out.data(), out.length());
14992
0
}
14993
14994
0
ada_string ada_get_search(ada_url result) noexcept {
14995
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
14996
0
  if (!r) {
14997
0
    return ada_string_create(NULL, 0);
14998
0
  }
14999
0
  std::string_view out = r->get_search();
15000
0
  return ada_string_create(out.data(), out.length());
15001
0
}
15002
15003
0
ada_string ada_get_protocol(ada_url result) noexcept {
15004
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15005
0
  if (!r) {
15006
0
    return ada_string_create(NULL, 0);
15007
0
  }
15008
0
  std::string_view out = r->get_protocol();
15009
0
  return ada_string_create(out.data(), out.length());
15010
0
}
15011
15012
0
bool ada_set_href(ada_url result, const char* input, size_t length) noexcept {
15013
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15014
0
  if (!r) {
15015
0
    return false;
15016
0
  }
15017
0
  return r->set_href(std::string_view(input, length));
15018
0
}
15019
15020
0
bool ada_set_host(ada_url result, const char* input, size_t length) noexcept {
15021
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15022
0
  if (!r) {
15023
0
    return false;
15024
0
  }
15025
0
  return r->set_host(std::string_view(input, length));
15026
0
}
15027
15028
bool ada_set_hostname(ada_url result, const char* input,
15029
0
                      size_t length) noexcept {
15030
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15031
0
  if (!r) {
15032
0
    return false;
15033
0
  }
15034
0
  return r->set_hostname(std::string_view(input, length));
15035
0
}
15036
15037
bool ada_set_protocol(ada_url result, const char* input,
15038
0
                      size_t length) noexcept {
15039
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15040
0
  if (!r) {
15041
0
    return false;
15042
0
  }
15043
0
  return r->set_protocol(std::string_view(input, length));
15044
0
}
15045
15046
bool ada_set_username(ada_url result, const char* input,
15047
0
                      size_t length) noexcept {
15048
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15049
0
  if (!r) {
15050
0
    return false;
15051
0
  }
15052
0
  return r->set_username(std::string_view(input, length));
15053
0
}
15054
15055
bool ada_set_password(ada_url result, const char* input,
15056
0
                      size_t length) noexcept {
15057
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15058
0
  if (!r) {
15059
0
    return false;
15060
0
  }
15061
0
  return r->set_password(std::string_view(input, length));
15062
0
}
15063
15064
0
bool ada_set_port(ada_url result, const char* input, size_t length) noexcept {
15065
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15066
0
  if (!r) {
15067
0
    return false;
15068
0
  }
15069
0
  return r->set_port(std::string_view(input, length));
15070
0
}
15071
15072
bool ada_set_pathname(ada_url result, const char* input,
15073
0
                      size_t length) noexcept {
15074
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15075
0
  if (!r) {
15076
0
    return false;
15077
0
  }
15078
0
  return r->set_pathname(std::string_view(input, length));
15079
0
}
15080
15081
0
void ada_set_search(ada_url result, const char* input, size_t length) noexcept {
15082
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15083
0
  if (r) {
15084
0
    r->set_search(std::string_view(input, length));
15085
0
  }
15086
0
}
15087
15088
0
void ada_set_hash(ada_url result, const char* input, size_t length) noexcept {
15089
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15090
0
  if (r) {
15091
0
    r->set_hash(std::string_view(input, length));
15092
0
  }
15093
0
}
15094
15095
0
bool ada_has_credentials(ada_url result) noexcept {
15096
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15097
0
  if (!r) {
15098
0
    return false;
15099
0
  }
15100
0
  return r->has_credentials();
15101
0
}
15102
15103
0
bool ada_has_empty_hostname(ada_url result) noexcept {
15104
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15105
0
  if (!r) {
15106
0
    return false;
15107
0
  }
15108
0
  return r->has_empty_hostname();
15109
0
}
15110
15111
0
bool ada_has_hostname(ada_url result) noexcept {
15112
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15113
0
  if (!r) {
15114
0
    return false;
15115
0
  }
15116
0
  return r->has_hostname();
15117
0
}
15118
15119
0
bool ada_has_non_empty_username(ada_url result) noexcept {
15120
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15121
0
  if (!r) {
15122
0
    return false;
15123
0
  }
15124
0
  return r->has_non_empty_username();
15125
0
}
15126
15127
0
bool ada_has_non_empty_password(ada_url result) noexcept {
15128
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15129
0
  if (!r) {
15130
0
    return false;
15131
0
  }
15132
0
  return r->has_non_empty_password();
15133
0
}
15134
15135
0
bool ada_has_port(ada_url result) noexcept {
15136
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15137
0
  if (!r) {
15138
0
    return false;
15139
0
  }
15140
0
  return r->has_port();
15141
0
}
15142
15143
0
bool ada_has_password(ada_url result) noexcept {
15144
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15145
0
  if (!r) {
15146
0
    return false;
15147
0
  }
15148
0
  return r->has_password();
15149
0
}
15150
15151
0
bool ada_has_hash(ada_url result) noexcept {
15152
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15153
0
  if (!r) {
15154
0
    return false;
15155
0
  }
15156
0
  return r->has_hash();
15157
0
}
15158
15159
0
bool ada_has_search(ada_url result) noexcept {
15160
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15161
0
  if (!r) {
15162
0
    return false;
15163
0
  }
15164
0
  return r->has_search();
15165
0
}
15166
15167
// returns a pointer to the internal url_aggregator::url_components
15168
0
const ada_url_components* ada_get_components(ada_url result) noexcept {
15169
0
  static_assert(sizeof(ada_url_components) == sizeof(ada::url_components));
15170
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
15171
0
  if (!r) {
15172
0
    return nullptr;
15173
0
  }
15174
0
  return reinterpret_cast<const ada_url_components*>(&r->get_components());
15175
0
}
15176
}  // extern "C"
15177
/* end file src/ada_c.cpp */
15178
/* end file src/ada.cpp */